#!/bin/false # Don't run directly, use gunicorn from flask import Flask, request, render_template from flask_socketio import SocketIO, emit, send import subprocess import json from datetime import datetime from collections import defaultdict from urllib.parse import urlencode import urllib.request import base64 import requests import socket app = Flask(__name__) # This is fine socketio = SocketIO(app, cors_allowed_origins='*') messages = [] timeout = 1 class Message: def __init__(self, time, sender, sendertype, msg, sid = None): self.time = time self.sid = sid self.sender = sender self.sendertype = sendertype self.msg = msg def send_message(message) -> tuple: if not message.msg: return (False,"No message found") if len(message.msg) > 200: return (False,"Message too long, maximum 200") messages.append(message) # Send message to MessageOS msg_with_sendr: str = "<{}> {}".format(message.sender, message.msg) if message.sender != "somebody" else message.msg msg_b64 = base64.b64encode(msg_with_sendr.encode()) url = "http://10.0.5.42:8000/" # Set destination URL here post_fields = {"X-Messages": msg_b64} assembly_request = urllib.request.Request(url, urlencode(post_fields).encode()) assembly_request.add_header("X-Messages", msg_b64) urllib.request.urlopen(assembly_request).read().decode() try: requests.put("http://10.0.0.10/api/mailbox.json", json={"topic": "morsemessage", "message": msg_with_sendr}) except: pass return (True,"OK") def reverse_lookup(ip): rdns = socket.getnameinfo((ip, 0), 0) if rdns: ip = rdns[0] return ip @app.route("/messages/") def messages_get(): return render_template("chat.html", messages=messages[::-1]) @app.route("/reply/", methods = ["POST"]) def reply_post(): if request.data: message = request.data.decode() if len(message) > 200: return "Message too long, maximum 200" if not message: return "No message found" if len(messages) > 0 and messages[-1].sid: socketio.emit('replymessage', {'message': message},to=messages[-1].sid) return "Message sent\n" else: return "Could not reply" return "Failed\n" @socketio.on('message') def message_socket(data): if data.get("username"): sender = data.get("username") sendertype = "name" elif "X-Real-IP" in request.headers: sender = reverse_lookup(request.headers["X-Real-IP"]) sendertype = "ip" else: sender = "somebody" sendertype = "unknown" ok, return_message = send_message(Message(datetime.now(), sender, sendertype, data.get("message"), sid = request.sid)) return return_message @app.route("/messages/", methods = ["POST"]) def messages_post(): if request.data: if "X-Username" in request.headers and len(request.headers["X-Username"]) > 0: sender = request.headers["X-Username"] sendertype = "name" elif "X-Real-IP" in request.headers: sender = reverse_lookup(request.headers["X-Real-IP"]) sendertype = "ip" else: sender = "-" sendertype = "unknown" message = request.data.decode() if not message: return "No message found" headers = { 'X-Username': sender, } data = { 'message': message } try: response = requests.post("http://10.0.0.171:8080/message", headers=headers, json=data) response.raise_for_status() except: pass msg_with_sendr: str = "<{}> {}".format(sender, message) if sender != "somebody" else message try: requests.put("http://10.0.0.10/api/mailbox.json", json={"topic": "morsemessage", "message": msg_with_sendr}) except: pass messages.append(Message(datetime.now(), sender, sendertype, message)) return "" else: return "" # make sure only messages from the last hour are sent # this command also only sends messages the user doesn't have yet. @app.route('//api.json') def api(last_index): curr_time = datetime.now() ci = len(messages)-1 while curr_time - messages[ci].time < datetime.timedelta(hours = 1) and ci > last_index: ci -= 1 return jsonify({"newest_msg_index": len(messages) , "messages": messages[ci:]}) if __name__ == "__main__": socketio.run(app,port=3000,host='0.0.0.0')