updates from korner #7

Merged
axdzitte merged 2 commits from axdzitte/cammiechat:master into master 2024-10-10 13:11:41 +02:00
8 changed files with 104 additions and 107 deletions

8
cammiewatcher.py Normal file
View file

@ -0,0 +1,8 @@
import requests
import time
while True:
data = requests.get("https://kelder.zeus.ugent.be/camera/api/info").json()
cammie_watchers = data['connections']['/']
r = requests.put('http://10.0.0.10/api/mailbox.json', json={'message':str(cammie_watchers), 'topic': 'cammie'})
time.sleep(1)

198
chat.py
View file

@ -1,131 +1,45 @@
#!/bin/false #!/bin/false
# Don't run directly, use gunicorn # Don't run directly, use gunicorn
from flask import Flask, request, escape, render_template from flask import Flask, request, render_template
from flask_socketio import SocketIO, emit, send from flask_socketio import SocketIO, emit, send
import subprocess import subprocess
import json import json
from datetime import datetime from datetime import datetime
from collections import defaultdict from collections import defaultdict
import mpd
from urllib.parse import urlencode from urllib.parse import urlencode
import urllib.request import urllib.request
import base64 import base64
import requests import requests
import socket
mpc = mpd.MPDClient()
mpc.timeout = 0.2
app = Flask(__name__) app = Flask(__name__)
# This is fine # This is fine
socketio = SocketIO(app, cors_allowed_origins='*') socketio = SocketIO(app, cors_allowed_origins='*')
messages = [] messages = []
last_sent = defaultdict(lambda: datetime(1970,1,1))
timeout = 1 timeout = 1
class Message: class Message:
def __init__(self, time, sender, sendertype, msg): def __init__(self, time, sender, sendertype, msg, sid = None):
self.time = time self.time = time
self.sid = sid
self.sender = sender self.sender = sender
self.sendertype = sendertype self.sendertype = sendertype
self.msg = msg self.msg = msg
def send_message(message) -> tuple:
@app.route("/messages/") if not message.msg:
def messages_get(): return (False,"No message found")
try:
mpc.connect("localhost", 6600)
song = mpc.currentsong()
status = mpc.status()
except:
status = {"state": "not connected"}
song = {}
try:
mpc.disconnect()
except:
pass
return render_template("chat.html", messages=messages[::-1], mpd_song=song, mpd_status=status) if len(message.msg) > 200:
return (False,"Message too long, maximum 200")
@app.route("/reply/", methods = ["POST"]) messages.append(message)
def reply_post():
if request.data:
if "X-Username" in request.headers:
sender = request.headers["X-Username"]
sendertype = "name"
elif "X-Real-IP" in request.headers:
sender = request.headers["X-Real-IP"]
sendertype = "ip"
else:
sender = "somebody"
sendertype = "unknown"
if sender[:6] == "abefor":
sender = "abeforkelder"
time = datetime.now()
last_sent_from_ip = last_sent[sendertype + sender]
last_sent[sendertype + sender] = time
if (time-last_sent_from_ip).total_seconds() < timeout:
return "OK Felix"
message = request.data.decode()
if len(message) > 200:
return "Message too long, maximum 200"
if not message:
return "No message found"
socketio.emit('replymessage', {'message': message}, broadcast=True)
return "Message sent\n"
return "Failed\n"
@app.route("/messages/", methods = ["POST"])
def messages_post():
if request.data:
if "X-Username" in request.headers:
sender = request.headers["X-Username"]
sendertype = "name"
elif "X-Real-IP" in request.headers:
sender = request.headers["X-Real-IP"]
sendertype = "ip"
else:
sender = "somebody"
sendertype = "unknown"
if sender[:6] == "abefor":
sender = "abeforkelder"
time = datetime.now()
last_sent_from_ip = last_sent[sendertype + sender]
last_sent[sendertype + sender] = time
if (time-last_sent_from_ip).total_seconds() < timeout:
return "OK Felix"
message = request.data.decode()
if len(message) > 200:
return "Message too long, maximum 200"
if not message:
return "No message found"
if "spam" in message.lower():
messages.append(Message(time, "1.3.3.7", "ip", "Nee"))
return "OK"
# Save message to serve it in this application
messages.append(Message(time, sender, sendertype, message))
# Send message to MessageOS # Send message to MessageOS
msg_with_sendr: str = "<{}> {}".format(sender, message) if sender != "somebody" else message msg_with_sendr: str = "<{}> {}".format(message.sender, message.msg) if message.sender != "somebody" else message.msg
msg_b64 = base64.b64encode(msg_with_sendr.encode()) msg_b64 = base64.b64encode(msg_with_sendr.encode())
url = "http://10.0.5.42:8000/" # Set destination URL here url = "http://10.0.5.42:8000/" # Set destination URL here
@ -138,8 +52,94 @@ def messages_post():
except: except:
pass pass
return "OK" 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 # make sure only messages from the last hour are sent
# this command also only sends messages the user doesn't have yet. # this command also only sends messages the user doesn't have yet.
@ -153,4 +153,4 @@ def api(last_index):
if __name__ == "__main__": if __name__ == "__main__":
socketio.run(app) socketio.run(app,port=3000,host='0.0.0.0')

10
pyserial.py Normal file
View file

@ -0,0 +1,10 @@
import serial
import requests
ser = serial.Serial('/dev/ttyUSB0')
while True:
line = ser.readline()
out = requests.post("http://localhost:3000/reply",data=line.decode()[:-1])
ser.close()

3
requirements.txt Normal file
View file

@ -0,0 +1,3 @@
flask
requests
flask_socketio

View file

@ -2,13 +2,4 @@
killall gunicorn killall gunicorn
./run.sh & disown ./run.sh & disown
sleep 1
DISPLAY=:0 xdotool key ctrl+F5
sleep 5
DISPLAY=:0 xdotool key ctrl+F5
sleep 10
DISPLAY=:0 xdotool key ctrl+F5
sleep 10
DISPLAY=:0 xdotool key ctrl+F5
sleep 10
DISPLAY=:0 xdotool key ctrl+F5

6
run.py Executable file
View file

@ -0,0 +1,6 @@
#!/usr/bin/env python3
from chat import app
from chat import socketio
socketio.run(app,port=3000,host='0.0.0.0',allow_unsafe_werkzeug=True)

7
run.sh
View file

@ -1,7 +0,0 @@
#!/bin/bash
cd "$(dirname "$0")"
poetry install
export FLASK_APP=chat.py
exec poetry run gunicorn --worker-class eventlet -w 1 -b0.0.0.0:5000 chat:app

View file

@ -37,31 +37,17 @@
.msg .sender.name:before { content: "<"; } .msg .sender.name:after { content: ">"; } .msg .sender.name:before { content: "<"; } .msg .sender.name:after { content: ">"; }
.msg .sender.ip:before { content: "["; } .msg .sender.ip:after { content: "]"; } .msg .sender.ip:before { content: "["; } .msg .sender.ip:after { content: "]"; }
.mpd-status { margin-bottom: 0.2em; }
.mpd-status:before { content: " ▶ "; }
</style> </style>
<title>Messages from the world to kelder</title> <title>Messages from the world to kelder</title>
<meta http-equiv="refresh" content="5" /> <meta http-equiv="refresh" content="5" />
</head> </head>
<body> <body>
{% if mpd_status["state"] == "play" %}
{% if mpd_song["artist"] and mpd_song["title"] %}
<div class="mpd-status"><span class="artist">{{ mpd_song["artist"] }}</span><span class="between artist-title"> </span><span class="title">{{ mpd_song["title"] }}</span></div>
{% elif mpd_song["title"] %}
<div class="mpd-status"><span class="title">{{ mpd_song["title"] }}</span></div>
{% elif mpd_song["artist"] %}
<div class="mpd-status"><span class="artist">{{ mpd_song["artist"] }}</span></div>
{% else %}
<div class="mpd-status">Unknown music, fix your metadata!</div>
{% endif %}
{% endif %}
<h1>Messages</h1> <h1>Messages</h1>
{% for m in messages %} {% for m in messages %}
<div class="msg_wrapper"> <div class="msg_wrapper">
<div class="msg"><!-- <div class="msg"><!--
--><span class="meta"><!-- --><span class="meta"><!--
--><time datetime="{{ m.time }}">{{ "{:%d/%m %H:%M:%S}".format(m.time) }}</time><span class="between time-sender"> - </span><!-- --><time datetime="{{ m.time }}">{{ "{:%d/%m %H:%M:%S}".format(m.time) }}</time><!--
--><span class="sender {{ m.sendertype }}">{{ m.sender }}</span><span class="between sender-msg">: </span><!--
--></span><!-- --></span><!--
--><span class="msg">{{ m.msg }}</span><!-- --><span class="msg">{{ m.msg }}</span><!--
--></div> --></div>