forked from Kelder/cammiechat
158 lines
4.6 KiB
Python
158 lines
4.6 KiB
Python
#!/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"
|
|
if len(sender) > 50:
|
|
return "Username too long"
|
|
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('/<last_index>/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')
|