Merge pull request 'updates from korner' (#7) from axdzitte/cammiechat:master into master

Reviewed-on: Kelder/cammiechat#7
This commit is contained in:
axdzitte 2024-10-10 13:11:41 +02:00
commit 19c4cb71f6
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)

150
chat.py
View file

@ -1,77 +1,73 @@
#!/bin/false
# 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
import subprocess
import json
from datetime import datetime
from collections import defaultdict
import mpd
from urllib.parse import urlencode
import urllib.request
import base64
import requests
mpc = mpd.MPDClient()
mpc.timeout = 0.2
import socket
app = Flask(__name__)
# This is fine
socketio = SocketIO(app, cors_allowed_origins='*')
messages = []
last_sent = defaultdict(lambda: datetime(1970,1,1))
timeout = 1
class Message:
def __init__(self, time, sender, sendertype, msg):
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:
@app.route("/messages/")
def messages_get():
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:
mpc.connect("localhost", 6600)
song = mpc.currentsong()
status = mpc.status()
except:
status = {"state": "not connected"}
song = {}
try:
mpc.disconnect()
requests.put("http://10.0.0.10/api/mailbox.json", json={"topic": "morsemessage", "message": msg_with_sendr})
except:
pass
return render_template("chat.html", messages=messages[::-1], mpd_song=song, mpd_status=status)
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:
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()
@ -80,66 +76,70 @@ def reply_post():
if not message:
return "No message found"
socketio.emit('replymessage', {'message': message}, broadcast=True)
return "Message sent\n"
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:
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 = request.headers["X-Real-IP"]
sender = reverse_lookup(request.headers["X-Real-IP"])
sendertype = "ip"
else:
sender = "somebody"
sender = "-"
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"
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
# Save message to serve it in this application
messages.append(Message(time, sender, sendertype, message))
# Send message to MessageOS
msg_with_sendr: str = "<{}> {}".format(sender, message) if sender != "somebody" else message
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 "OK"
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.
@ -153,4 +153,4 @@ def api(last_index):
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
./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.ip:before { content: "["; } .msg .sender.ip:after { content: "]"; }
.mpd-status { margin-bottom: 0.2em; }
.mpd-status:before { content: " ▶ "; }
</style>
<title>Messages from the world to kelder</title>
<meta http-equiv="refresh" content="5" />
</head>
<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>
{% for m in messages %}
<div class="msg_wrapper">
<div class="msg"><!--
--><span class="meta"><!--
--><time datetime="{{ m.time }}">{{ "{:%d/%m %H:%M:%S}".format(m.time) }}</time><span class="between time-sender"> - </span><!--
--><span class="sender {{ m.sendertype }}">{{ m.sender }}</span><span class="between sender-msg">: </span><!--
--><time datetime="{{ m.time }}">{{ "{:%d/%m %H:%M:%S}".format(m.time) }}</time><!--
--></span><!--
--><span class="msg">{{ m.msg }}</span><!--
--></div>