Compare commits

...

21 commits

Author SHA1 Message Date
739295e865 Limit sender username 2024-10-23 14:10:35 +02:00
19c4cb71f6 Merge pull request 'updates from korner' (#7) from axdzitte/cammiechat:master into master
Reviewed-on: Kelder/cammiechat#7
2024-10-10 13:11:41 +02:00
c17fa92ec1 Added cammiewatcher 2024-09-29 17:31:19 +02:00
unknown
12c261b0b1 updates 2024-09-26 20:52:45 +02:00
j
0e8ec152f0 Merge branch 'swamp' into 'master'
Add API to get recent chat messages

See merge request kelder/cammiechat!5
2022-02-28 18:58:51 +00:00
swamp
95dcdea1c1 Add API to get recent chat messages 2022-02-28 18:58:51 +00:00
redfast00
e08ac5ed7b
Add led strip API 2022-02-28 19:55:51 +01:00
redfast00
2efcdb0624
Add failed if failed 2021-09-27 15:17:40 +02:00
749069c66a
Switch to poetry because pipenv let us down 2020-01-10 17:23:10 +01:00
redfast00
93bc22f067
Add eventlet in run script 2019-10-08 04:06:23 +02:00
redfast00
919f89fb56
Add eventlet 2019-10-08 04:04:24 +02:00
redfast00
0607536b91
Allow all origins 2019-10-08 03:46:04 +02:00
redfast00
5013020bdf
Websockets 2019-10-08 02:21:36 +02:00
redfast00
77a87d4aeb
Add changes 2019-10-08 01:36:24 +02:00
cf9b0e03cc Refactor and fix 2019-09-03 01:05:40 +02:00
c3524a6536 Dedupe message decoding to string 2019-09-03 00:50:28 +02:00
hannes
378b668f7a Merge branch 'name_on_message' into 'master'
fixed errer

See merge request kelder/cammiechat!4
2019-09-03 00:44:23 +02:00
f54f83bb0d Check truthness instead of length 2019-09-03 00:36:39 +02:00
hannes
3c4f11dcb7 Merge branch 'name_on_message' into 'master'
change decode again

See merge request kelder/cammiechat!3
2019-09-03 00:34:47 +02:00
j
14cffd4d46 Merge branch 'name_on_message' into 'master'
decoded sender to concat in string

See merge request kelder/cammiechat!2
2019-09-03 00:30:58 +02:00
j
f929cc745a Merge branch 'name_on_message' into 'master'
add name when sending message from mattermost

See merge request kelder/cammiechat!1
2019-09-03 00:09:21 +02:00
12 changed files with 468 additions and 210 deletions

14
Pipfile
View file

@ -1,14 +0,0 @@
[[source]]
url = "https://pypi.org/simple"
verify_ssl = true
name = "pypi"
[packages]
gunicorn = "*"
flask = "*"
"python-mpd2" = "*"
[dev-packages]
[requires]
python_version = "3.6"

106
Pipfile.lock generated
View file

@ -1,106 +0,0 @@
{
"_meta": {
"hash": {
"sha256": "804aaad19da42dd0078edca3a25a05492b4832c1a3b2f75601730dc4c7a43a3e"
},
"pipfile-spec": 6,
"requires": {
"python_version": "3.7"
},
"sources": [
{
"name": "pypi",
"url": "https://pypi.org/simple",
"verify_ssl": true
}
]
},
"default": {
"click": {
"hashes": [
"sha256:2335065e6395b9e67ca716de5f7526736bfa6ceead690adf616d925bdc622b13",
"sha256:5b94b49521f6456670fdb30cd82a4eca9412788a93fa6dd6df72c94d5a8ff2d7"
],
"version": "==7.0"
},
"flask": {
"hashes": [
"sha256:2271c0070dbcb5275fad4a82e29f23ab92682dc45f9dfbc22c02ba9b9322ce48",
"sha256:a080b744b7e345ccfcbc77954861cb05b3c63786e93f2b3875e0913d44b43f05"
],
"index": "pypi",
"version": "==1.0.2"
},
"gunicorn": {
"hashes": [
"sha256:aa8e0b40b4157b36a5df5e599f45c9c76d6af43845ba3b3b0efe2c70473c2471",
"sha256:fa2662097c66f920f53f70621c6c58ca4a3c4d3434205e608e121b5b3b71f4f3"
],
"index": "pypi",
"version": "==19.9.0"
},
"itsdangerous": {
"hashes": [
"sha256:321b033d07f2a4136d3ec762eac9f16a10ccd60f53c0c91af90217ace7ba1f19",
"sha256:b12271b2047cb23eeb98c8b5622e2e5c5e9abd9784a153e9d8ef9cb4dd09d749"
],
"version": "==1.1.0"
},
"jinja2": {
"hashes": [
"sha256:74c935a1b8bb9a3947c50a54766a969d4846290e1e788ea44c1392163723c3bd",
"sha256:f84be1bb0040caca4cea721fcbbbbd61f9be9464ca236387158b0feea01914a4"
],
"version": "==2.10"
},
"markupsafe": {
"hashes": [
"sha256:048ef924c1623740e70204aa7143ec592504045ae4429b59c30054cb31e3c432",
"sha256:130f844e7f5bdd8e9f3f42e7102ef1d49b2e6fdf0d7526df3f87281a532d8c8b",
"sha256:19f637c2ac5ae9da8bfd98cef74d64b7e1bb8a63038a3505cd182c3fac5eb4d9",
"sha256:1b8a7a87ad1b92bd887568ce54b23565f3fd7018c4180136e1cf412b405a47af",
"sha256:1c25694ca680b6919de53a4bb3bdd0602beafc63ff001fea2f2fc16ec3a11834",
"sha256:1f19ef5d3908110e1e891deefb5586aae1b49a7440db952454b4e281b41620cd",
"sha256:1fa6058938190ebe8290e5cae6c351e14e7bb44505c4a7624555ce57fbbeba0d",
"sha256:31cbb1359e8c25f9f48e156e59e2eaad51cd5242c05ed18a8de6dbe85184e4b7",
"sha256:3e835d8841ae7863f64e40e19477f7eb398674da6a47f09871673742531e6f4b",
"sha256:4e97332c9ce444b0c2c38dd22ddc61c743eb208d916e4265a2a3b575bdccb1d3",
"sha256:525396ee324ee2da82919f2ee9c9e73b012f23e7640131dd1b53a90206a0f09c",
"sha256:52b07fbc32032c21ad4ab060fec137b76eb804c4b9a1c7c7dc562549306afad2",
"sha256:52ccb45e77a1085ec5461cde794e1aa037df79f473cbc69b974e73940655c8d7",
"sha256:5c3fbebd7de20ce93103cb3183b47671f2885307df4a17a0ad56a1dd51273d36",
"sha256:5e5851969aea17660e55f6a3be00037a25b96a9b44d2083651812c99d53b14d1",
"sha256:5edfa27b2d3eefa2210fb2f5d539fbed81722b49f083b2c6566455eb7422fd7e",
"sha256:7d263e5770efddf465a9e31b78362d84d015cc894ca2c131901a4445eaa61ee1",
"sha256:83381342bfc22b3c8c06f2dd93a505413888694302de25add756254beee8449c",
"sha256:857eebb2c1dc60e4219ec8e98dfa19553dae33608237e107db9c6078b1167856",
"sha256:98e439297f78fca3a6169fd330fbe88d78b3bb72f967ad9961bcac0d7fdd1550",
"sha256:bf54103892a83c64db58125b3f2a43df6d2cb2d28889f14c78519394feb41492",
"sha256:d9ac82be533394d341b41d78aca7ed0e0f4ba5a2231602e2f05aa87f25c51672",
"sha256:e982fe07ede9fada6ff6705af70514a52beb1b2c3d25d4e873e82114cf3c5401",
"sha256:edce2ea7f3dfc981c4ddc97add8a61381d9642dc3273737e756517cc03e84dd6",
"sha256:efdc45ef1afc238db84cb4963aa689c0408912a0239b0721cb172b4016eb31d6",
"sha256:f137c02498f8b935892d5c0172560d7ab54bc45039de8805075e19079c639a9c",
"sha256:f82e347a72f955b7017a39708a3667f106e6ad4d10b25f237396a7115d8ed5fd",
"sha256:fb7c206e01ad85ce57feeaaa0bf784b97fa3cad0d4a5737bc5295785f5c613a1"
],
"version": "==1.1.0"
},
"python-mpd2": {
"hashes": [
"sha256:29119e3a88ef4a6f15acb1b83bab9344fba8eefc370e0144ffb77f5138e65dd7",
"sha256:772fa6861273bb9f363a97987c2c45ca3965eb770570f1f02566efec9c89fc5f"
],
"index": "pypi",
"version": "==1.0.0"
},
"werkzeug": {
"hashes": [
"sha256:c3fd7a7d41976d9f44db327260e263132466836cef6f91512889ed60ad26557c",
"sha256:d5da73735293558eb1651ee2fddc4d0dedcfa06538b8813a2e20011583c9e49b"
],
"version": "==0.14.1"
}
},
"develop": {}
}

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)

168
chat.py
View file

@ -1,108 +1,158 @@
#!/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
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
mpc = mpd.MPDClient() import socket
mpc.timeout = 0.2
app = Flask(__name__) app = Flask(__name__)
# This is fine
socketio = SocketIO(app, cors_allowed_origins='*')
messages = [] messages = []
last_sent = defaultdict(lambda: datetime(1970,1,1))
timeout = 1 timeout = 1
def speak(text):
espk_proc = subprocess.Popen(("espeak", "-vnl"), stdin=subprocess.PIPE, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
espk_proc.stdin.write(text)
espk_proc.stdin.close()
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")
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: try:
mpc.connect("localhost", 6600) requests.put("http://10.0.0.10/api/mailbox.json", json={"topic": "morsemessage", "message": msg_with_sendr})
song = mpc.currentsong()
status = mpc.status()
except:
status = {"state": "not connected"}
song = {}
try:
mpc.disconnect()
except: except:
pass 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/", methods = ["POST"]) @app.route("/messages/")
def messages_post(): def messages_get():
return render_template("chat.html", messages=messages[::-1])
@app.route("/reply/", methods = ["POST"])
def reply_post():
if request.data: if request.data:
if "X-Username" in request.headers:
sender = request.headers["X-Username"] 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" sendertype = "name"
elif "X-Real-IP" in request.headers: elif "X-Real-IP" in request.headers:
sender = request.headers["X-Real-IP"] sender = reverse_lookup(request.headers["X-Real-IP"])
sendertype = "ip" sendertype = "ip"
else: else:
sender = "somebody" sender = "somebody"
sendertype = "unknown" sendertype = "unknown"
if sender[:6] == "abefor": ok, return_message = send_message(Message(datetime.now(), sender, sendertype, data.get("message"), sid = request.sid))
sender = "abeforkelder"
time = datetime.now() return return_message
last_sent_from_ip = last_sent[sendertype + sender]
last_sent[sendertype + sender] = time @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"
if (time-last_sent_from_ip).total_seconds() < timeout: message = request.data.decode()
return "OK Felix" if not message:
message = request.data
if len(message) > 200:
return "Message too long, maximum 200"
if len(message) == 0:
return "No message found" return "No message found"
if "spam" in str(message, "UTF-8").lower(): headers = {
messages.append(Message(time, "1.3.3.7", "ip", "Nee")) 'X-Username': sender,
return "OK" }
data = {
'message': message
}
if sender != "somebody": try:
message = "<" + sender + "> " + message.decode() response = requests.post("http://10.0.0.171:8080/message", headers=headers, json=data)
response.raise_for_status()
except:
pass
messages.append(Message(time, sender, sendertype, message)) msg_with_sendr: str = "<{}> {}".format(sender, message) if sender != "somebody" else message
url = 'http://10.0.5.42:8000/' # Set destination URL here try:
post_fields = {'X-Messages': base64.b64encode(message)} requests.put("http://10.0.0.10/api/mailbox.json", json={"topic": "morsemessage", "message": msg_with_sendr})
except:
pass
assembly_request = urllib.request.Request(url, urlencode(post_fields).encode()) messages.append(Message(datetime.now(), sender, sendertype, message))
assembly_request.add_header('X-Messages', base64.b64encode(message))
urllib.request.urlopen(assembly_request).read().decode()
speak(message)
return "OK" 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__": if __name__ == "__main__":
app.run() socketio.run(app,port=3000,host='0.0.0.0')

303
poetry.lock generated Normal file
View file

@ -0,0 +1,303 @@
[[package]]
category = "main"
description = "Composable command line interface toolkit"
name = "click"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
version = "7.0"
[[package]]
category = "main"
description = "DNS toolkit"
name = "dnspython"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
version = "1.16.0"
[package.extras]
DNSSEC = ["pycryptodome", "ecdsa (>=0.13)"]
IDNA = ["idna (>=2.1)"]
[[package]]
category = "main"
description = "Highly concurrent networking library"
name = "eventlet"
optional = false
python-versions = "*"
version = "0.25.1"
[package.dependencies]
dnspython = ">=1.15.0"
greenlet = ">=0.3"
monotonic = ">=1.4"
six = ">=1.10.0"
[[package]]
category = "main"
description = "A simple framework for building complex web applications."
name = "flask"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
version = "1.1.1"
[package.dependencies]
Jinja2 = ">=2.10.1"
Werkzeug = ">=0.15"
click = ">=5.1"
itsdangerous = ">=0.24"
[package.extras]
dev = ["pytest", "coverage", "tox", "sphinx", "pallets-sphinx-themes", "sphinxcontrib-log-cabinet", "sphinx-issues"]
docs = ["sphinx", "pallets-sphinx-themes", "sphinxcontrib-log-cabinet", "sphinx-issues"]
dotenv = ["python-dotenv"]
[[package]]
category = "main"
description = "Socket.IO integration for Flask applications"
name = "flask-socketio"
optional = false
python-versions = "*"
version = "4.2.1"
[package.dependencies]
Flask = ">=0.9"
python-socketio = ">=4.3.0"
[[package]]
category = "main"
description = "Lightweight in-process concurrent programming"
name = "greenlet"
optional = false
python-versions = "*"
version = "0.4.15"
[[package]]
category = "main"
description = "WSGI HTTP Server for UNIX"
name = "gunicorn"
optional = false
python-versions = ">=3.4"
version = "20.0.4"
[package.dependencies]
setuptools = ">=3.0"
[package.extras]
eventlet = ["eventlet (>=0.9.7)"]
gevent = ["gevent (>=0.13)"]
setproctitle = ["setproctitle"]
tornado = ["tornado (>=0.2)"]
[[package]]
category = "main"
description = "Various helpers to pass data to untrusted environments and back."
name = "itsdangerous"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
version = "1.1.0"
[[package]]
category = "main"
description = "A very fast and expressive template engine."
name = "jinja2"
optional = false
python-versions = "*"
version = "2.10.3"
[package.dependencies]
MarkupSafe = ">=0.23"
[package.extras]
i18n = ["Babel (>=0.8)"]
[[package]]
category = "main"
description = "Safely add untrusted strings to HTML/XML markup."
name = "markupsafe"
optional = false
python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*"
version = "1.1.1"
[[package]]
category = "main"
description = "An implementation of time.monotonic() for Python 2 & < 3.3"
name = "monotonic"
optional = false
python-versions = "*"
version = "1.5"
[[package]]
category = "main"
description = "Engine.IO server"
name = "python-engineio"
optional = false
python-versions = "*"
version = "3.11.2"
[package.dependencies]
six = ">=1.9.0"
[package.extras]
asyncio_client = ["aiohttp (>=3.4)"]
client = ["requests (>=2.21.0)", "websocket-client (>=0.54.0)"]
[[package]]
category = "main"
description = "A Python MPD client library"
name = "python-mpd2"
optional = false
python-versions = "*"
version = "1.0.0"
[package.extras]
twisted = ["twisted"]
[[package]]
category = "main"
description = "Socket.IO server"
name = "python-socketio"
optional = false
python-versions = "*"
version = "4.4.0"
[package.dependencies]
python-engineio = ">=3.9.0"
six = ">=1.9.0"
[package.extras]
asyncio_client = ["aiohttp (>=3.4)", "websockets (>=7.0)"]
client = ["requests (>=2.21.0)", "websocket-client (>=0.54.0)"]
[[package]]
category = "main"
description = "Python 2 and 3 compatibility utilities"
name = "six"
optional = false
python-versions = ">=2.6, !=3.0.*, !=3.1.*"
version = "1.13.0"
[[package]]
category = "main"
description = "The comprehensive WSGI web application library."
name = "werkzeug"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
version = "0.16.0"
[package.extras]
dev = ["pytest", "coverage", "tox", "sphinx", "pallets-sphinx-themes", "sphinx-issues"]
termcolor = ["termcolor"]
watchdog = ["watchdog"]
[metadata]
content-hash = "37516445f8e0fb70eead3e64133d40d41ba04634c586c2020232d5eaebe6f075"
python-versions = "^3.6"
[metadata.files]
click = [
{file = "Click-7.0-py2.py3-none-any.whl", hash = "sha256:2335065e6395b9e67ca716de5f7526736bfa6ceead690adf616d925bdc622b13"},
{file = "Click-7.0.tar.gz", hash = "sha256:5b94b49521f6456670fdb30cd82a4eca9412788a93fa6dd6df72c94d5a8ff2d7"},
]
dnspython = [
{file = "dnspython-1.16.0-py2.py3-none-any.whl", hash = "sha256:f69c21288a962f4da86e56c4905b49d11aba7938d3d740e80d9e366ee4f1632d"},
{file = "dnspython-1.16.0.zip", hash = "sha256:36c5e8e38d4369a08b6780b7f27d790a292b2b08eea01607865bf0936c558e01"},
]
eventlet = [
{file = "eventlet-0.25.1-py2.py3-none-any.whl", hash = "sha256:658b1cd80937adc1a4860de2841e0528f64e2ca672885c4e00fc0e2217bde6b1"},
{file = "eventlet-0.25.1.tar.gz", hash = "sha256:6c9c625af48424c4680d89314dbe45a76cc990cf002489f9469ff214b044ffc1"},
]
flask = [
{file = "Flask-1.1.1-py2.py3-none-any.whl", hash = "sha256:45eb5a6fd193d6cf7e0cf5d8a5b31f83d5faae0293695626f539a823e93b13f6"},
{file = "Flask-1.1.1.tar.gz", hash = "sha256:13f9f196f330c7c2c5d7a5cf91af894110ca0215ac051b5844701f2bfd934d52"},
]
flask-socketio = [
{file = "Flask-SocketIO-4.2.1.tar.gz", hash = "sha256:2172dff1e42415ba480cee02c30c2fc833671ff326f1598ee3d69aa02cf768ec"},
{file = "Flask_SocketIO-4.2.1-py2.py3-none-any.whl", hash = "sha256:7ff5b2f5edde23e875a8b0abf868584e5706e11741557449bc5147df2cd78268"},
]
greenlet = [
{file = "greenlet-0.4.15-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:99a26afdb82ea83a265137a398f570402aa1f2b5dfb4ac3300c026931817b163"},
{file = "greenlet-0.4.15-cp27-cp27m-win32.whl", hash = "sha256:beeabe25c3b704f7d56b573f7d2ff88fc99f0138e43480cecdfcaa3b87fe4f87"},
{file = "greenlet-0.4.15-cp27-cp27m-win_amd64.whl", hash = "sha256:9854f612e1b59ec66804931df5add3b2d5ef0067748ea29dc60f0efdcda9a638"},
{file = "greenlet-0.4.15-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:ac57fcdcfb0b73bb3203b58a14501abb7e5ff9ea5e2edfa06bb03035f0cff248"},
{file = "greenlet-0.4.15-cp33-cp33m-win32.whl", hash = "sha256:d634a7ea1fc3380ff96f9e44d8d22f38418c1c381d5fac680b272d7d90883720"},
{file = "greenlet-0.4.15-cp33-cp33m-win_amd64.whl", hash = "sha256:0d48200bc50cbf498716712129eef819b1729339e34c3ae71656964dac907c28"},
{file = "greenlet-0.4.15-cp34-cp34m-manylinux1_x86_64.whl", hash = "sha256:bcb530089ff24f6458a81ac3fa699e8c00194208a724b644ecc68422e1111939"},
{file = "greenlet-0.4.15-cp34-cp34m-win32.whl", hash = "sha256:8b4572c334593d449113f9dc8d19b93b7b271bdbe90ba7509eb178923327b625"},
{file = "greenlet-0.4.15-cp34-cp34m-win_amd64.whl", hash = "sha256:a9f145660588187ff835c55a7d2ddf6abfc570c2651c276d3d4be8a2766db490"},
{file = "greenlet-0.4.15-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:51503524dd6f152ab4ad1fbd168fc6c30b5795e8c70be4410a64940b3abb55c0"},
{file = "greenlet-0.4.15-cp35-cp35m-win32.whl", hash = "sha256:a19bf883b3384957e4a4a13e6bd1ae3d85ae87f4beb5957e35b0be287f12f4e4"},
{file = "greenlet-0.4.15-cp35-cp35m-win_amd64.whl", hash = "sha256:853da4f9563d982e4121fed8c92eea1a4594a2299037b3034c3c898cb8e933d6"},
{file = "greenlet-0.4.15-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:23d12eacffa9d0f290c0fe0c4e81ba6d5f3a5b7ac3c30a5eaf0126bf4deda5c8"},
{file = "greenlet-0.4.15-cp36-cp36m-win32.whl", hash = "sha256:000546ad01e6389e98626c1367be58efa613fa82a1be98b0c6fc24b563acc6d0"},
{file = "greenlet-0.4.15-cp36-cp36m-win_amd64.whl", hash = "sha256:d97b0661e1aead761f0ded3b769044bb00ed5d33e1ec865e891a8b128bf7c656"},
{file = "greenlet-0.4.15-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:8041e2de00e745c0e05a502d6e6db310db7faa7c979b3a5877123548a4c0b214"},
{file = "greenlet-0.4.15-cp37-cp37m-win32.whl", hash = "sha256:81fcd96a275209ef117e9ec91f75c731fa18dcfd9ffaa1c0adbdaa3616a86043"},
{file = "greenlet-0.4.15-cp37-cp37m-win_amd64.whl", hash = "sha256:37c9ba82bd82eb6a23c2e5acc03055c0e45697253b2393c9a50cef76a3985304"},
{file = "greenlet-0.4.15.tar.gz", hash = "sha256:9416443e219356e3c31f1f918a91badf2e37acf297e2fa13d24d1cc2380f8fbc"},
]
gunicorn = [
{file = "gunicorn-20.0.4-py2.py3-none-any.whl", hash = "sha256:cd4a810dd51bf497552cf3f863b575dabd73d6ad6a91075b65936b151cbf4f9c"},
{file = "gunicorn-20.0.4.tar.gz", hash = "sha256:1904bb2b8a43658807108d59c3f3d56c2b6121a701161de0ddf9ad140073c626"},
]
itsdangerous = [
{file = "itsdangerous-1.1.0-py2.py3-none-any.whl", hash = "sha256:b12271b2047cb23eeb98c8b5622e2e5c5e9abd9784a153e9d8ef9cb4dd09d749"},
{file = "itsdangerous-1.1.0.tar.gz", hash = "sha256:321b033d07f2a4136d3ec762eac9f16a10ccd60f53c0c91af90217ace7ba1f19"},
]
jinja2 = [
{file = "Jinja2-2.10.3-py2.py3-none-any.whl", hash = "sha256:74320bb91f31270f9551d46522e33af46a80c3d619f4a4bf42b3164d30b5911f"},
{file = "Jinja2-2.10.3.tar.gz", hash = "sha256:9fe95f19286cfefaa917656583d020be14e7859c6b0252588391e47db34527de"},
]
markupsafe = [
{file = "MarkupSafe-1.1.1-cp27-cp27m-macosx_10_6_intel.whl", hash = "sha256:09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161"},
{file = "MarkupSafe-1.1.1-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7"},
{file = "MarkupSafe-1.1.1-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183"},
{file = "MarkupSafe-1.1.1-cp27-cp27m-win32.whl", hash = "sha256:b2051432115498d3562c084a49bba65d97cf251f5a331c64a12ee7e04dacc51b"},
{file = "MarkupSafe-1.1.1-cp27-cp27m-win_amd64.whl", hash = "sha256:98c7086708b163d425c67c7a91bad6e466bb99d797aa64f965e9d25c12111a5e"},
{file = "MarkupSafe-1.1.1-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f"},
{file = "MarkupSafe-1.1.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1"},
{file = "MarkupSafe-1.1.1-cp34-cp34m-macosx_10_6_intel.whl", hash = "sha256:1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5"},
{file = "MarkupSafe-1.1.1-cp34-cp34m-manylinux1_i686.whl", hash = "sha256:62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1"},
{file = "MarkupSafe-1.1.1-cp34-cp34m-manylinux1_x86_64.whl", hash = "sha256:88e5fcfb52ee7b911e8bb6d6aa2fd21fbecc674eadd44118a9cc3863f938e735"},
{file = "MarkupSafe-1.1.1-cp34-cp34m-win32.whl", hash = "sha256:ade5e387d2ad0d7ebf59146cc00c8044acbd863725f887353a10df825fc8ae21"},
{file = "MarkupSafe-1.1.1-cp34-cp34m-win_amd64.whl", hash = "sha256:09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235"},
{file = "MarkupSafe-1.1.1-cp35-cp35m-macosx_10_6_intel.whl", hash = "sha256:79855e1c5b8da654cf486b830bd42c06e8780cea587384cf6545b7d9ac013a0b"},
{file = "MarkupSafe-1.1.1-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:c8716a48d94b06bb3b2524c2b77e055fb313aeb4ea620c8dd03a105574ba704f"},
{file = "MarkupSafe-1.1.1-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:7c1699dfe0cf8ff607dbdcc1e9b9af1755371f92a68f706051cc8c37d447c905"},
{file = "MarkupSafe-1.1.1-cp35-cp35m-win32.whl", hash = "sha256:6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1"},
{file = "MarkupSafe-1.1.1-cp35-cp35m-win_amd64.whl", hash = "sha256:9add70b36c5666a2ed02b43b335fe19002ee5235efd4b8a89bfcf9005bebac0d"},
{file = "MarkupSafe-1.1.1-cp36-cp36m-macosx_10_6_intel.whl", hash = "sha256:24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff"},
{file = "MarkupSafe-1.1.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:00bc623926325b26bb9605ae9eae8a215691f33cae5df11ca5424f06f2d1f473"},
{file = "MarkupSafe-1.1.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e"},
{file = "MarkupSafe-1.1.1-cp36-cp36m-win32.whl", hash = "sha256:535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66"},
{file = "MarkupSafe-1.1.1-cp36-cp36m-win_amd64.whl", hash = "sha256:b1282f8c00509d99fef04d8ba936b156d419be841854fe901d8ae224c59f0be5"},
{file = "MarkupSafe-1.1.1-cp37-cp37m-macosx_10_6_intel.whl", hash = "sha256:8defac2f2ccd6805ebf65f5eeb132adcf2ab57aa11fdf4c0dd5169a004710e7d"},
{file = "MarkupSafe-1.1.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e"},
{file = "MarkupSafe-1.1.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6"},
{file = "MarkupSafe-1.1.1-cp37-cp37m-win32.whl", hash = "sha256:b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2"},
{file = "MarkupSafe-1.1.1-cp37-cp37m-win_amd64.whl", hash = "sha256:9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c"},
{file = "MarkupSafe-1.1.1.tar.gz", hash = "sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b"},
]
monotonic = [
{file = "monotonic-1.5-py2.py3-none-any.whl", hash = "sha256:552a91f381532e33cbd07c6a2655a21908088962bb8fa7239ecbcc6ad1140cc7"},
{file = "monotonic-1.5.tar.gz", hash = "sha256:23953d55076df038541e648a53676fb24980f7a1be290cdda21300b3bc21dfb0"},
]
python-engineio = [
{file = "python-engineio-3.11.2.tar.gz", hash = "sha256:47ae4a9b3b4f2e8a68929f37a518338838e119f24c9a9121af92c49f8bea55c3"},
{file = "python_engineio-3.11.2-py2.py3-none-any.whl", hash = "sha256:c3a3822deb51fdf9c7fe4d78abf807c73b83ea538036a50862d3024450746253"},
]
python-mpd2 = [
{file = "python-mpd2-1.0.0.tar.bz2", hash = "sha256:772fa6861273bb9f363a97987c2c45ca3965eb770570f1f02566efec9c89fc5f"},
{file = "python_mpd2-1.0.0-py2.py3-none-any.whl", hash = "sha256:29119e3a88ef4a6f15acb1b83bab9344fba8eefc370e0144ffb77f5138e65dd7"},
]
python-socketio = [
{file = "python-socketio-4.4.0.tar.gz", hash = "sha256:48cba5b827ac665dbf923a4f5ec590812aed5299a831fc43576a9af346272534"},
{file = "python_socketio-4.4.0-py2.py3-none-any.whl", hash = "sha256:af6c23c35497960f82106e36688123ecb52ad5a77d0ca27954ff3811c4d9d562"},
]
six = [
{file = "six-1.13.0-py2.py3-none-any.whl", hash = "sha256:1f1b7d42e254082a9db6279deae68afb421ceba6158efa6131de7b3003ee93fd"},
{file = "six-1.13.0.tar.gz", hash = "sha256:30f610279e8b2578cab6db20741130331735c781b56053c59c4076da27f06b66"},
]
werkzeug = [
{file = "Werkzeug-0.16.0-py2.py3-none-any.whl", hash = "sha256:e5f4a1f98b52b18a93da705a7458e55afb26f32bff83ff5d19189f92462d65c4"},
{file = "Werkzeug-0.16.0.tar.gz", hash = "sha256:7280924747b5733b246fe23972186c6b348f9ae29724135a6dfc1e53cea433e7"},
]

19
pyproject.toml Normal file
View file

@ -0,0 +1,19 @@
[tool.poetry]
name = "cammiechat"
version = "0.1.0"
description = ""
authors = ["Midgard <midgard@zeus.ugent.be>", "Robbe <robbevanherck@zeus.ugent.be>"]
[tool.poetry.dependencies]
python = "^3.6"
gunicorn = "^20.0.4"
flask = "^1.1.1"
python-mpd2 = "^1.0.0"
flask-socketio = "^4.2.1"
eventlet = "^0.25.1"
[tool.poetry.dev-dependencies]
[build-system]
requires = ["poetry>=0.12"]
build-backend = "poetry.masonry.api"

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,5 +2,4 @@
killall gunicorn killall gunicorn
./run.sh & disown ./run.sh & disown
sleep 1
DISPLAY=:0 xdotool key 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)

6
run.sh
View file

@ -1,6 +0,0 @@
#!/bin/bash
cd "$(dirname "$0")"
pipenv install
export FLASK_APP=chat.py
exec pipenv run gunicorn -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>