Import stateserver into tree, MyPy-ify, CI-ify
This commit is contained in:
parent
de49a1d6be
commit
45f26d7c75
8 changed files with 469 additions and 42 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -27,7 +27,8 @@ yarn-error.log*
|
|||
|
||||
.mypy_cache/
|
||||
env/
|
||||
env.ci/
|
||||
|
||||
shittyserver.ini
|
||||
serverconfig.ini
|
||||
|
||||
.idea/
|
12
Jenkinsfile
vendored
12
Jenkinsfile
vendored
|
@ -29,9 +29,14 @@ pipeline {
|
|||
sh 'node_modules/.bin/tsc -p tsconfig.json --noEmit --extendedDiagnostics'
|
||||
}
|
||||
}
|
||||
stage('MyPy') {
|
||||
stage('MyPy (stateserver)') {
|
||||
steps {
|
||||
sh 'env/bin/mypy server.py'
|
||||
sh 'env/bin/mypy stateserver.py'
|
||||
}
|
||||
}
|
||||
stage('MyPy (shittyserver)') {
|
||||
steps {
|
||||
sh 'env/bin/mypy shittyserver.py'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -69,7 +74,8 @@ pipeline {
|
|||
stage('Deploy server') {
|
||||
steps {
|
||||
sshagent(credentials: ['ury']) {
|
||||
sh 'scp -v -o StrictHostKeyChecking=no server.py liquidsoap@dolby.ury:/opt/webstudioserver/server.py'
|
||||
sh 'scp -v -o StrictHostKeyChecking=no stateserver.py liquidsoap@dolby.ury:/opt/webstudioserver/stateserver.py'
|
||||
sh 'scp -v -o StrictHostKeyChecking=no shittyserver.py liquidsoap@dolby.ury:/opt/webstudioserver/shittyserver.py'
|
||||
sh 'scp -v -o StrictHostKeyChecking=no requirements.txt liquidsoap@dolby.ury:/opt/webstudioserver/requirements.txt'
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +1,59 @@
|
|||
aiohttp==3.6.2
|
||||
async-timeout==3.0.1
|
||||
appdirs==1.4.3
|
||||
astroid==2.3.3
|
||||
attrs==19.3.0
|
||||
autopep8==1.5
|
||||
black==19.10b0
|
||||
certifi==2019.11.28
|
||||
chardet==3.0.4
|
||||
idna==2.9
|
||||
multidict==4.7.5
|
||||
mypy==0.770
|
||||
click==7.1.1
|
||||
colorama==0.4.1
|
||||
decorator==4.4.0
|
||||
distlib==0.3.0
|
||||
docopt==0.6.2
|
||||
dokuwiki==1.2.1
|
||||
entrypoints==0.3
|
||||
filelock==3.0.12
|
||||
flake8==3.7.9
|
||||
frida==12.8.7
|
||||
frida-tools==6.0.0
|
||||
greenlet==0.4.15
|
||||
idna==2.8
|
||||
isort==4.3.21
|
||||
jedi==0.15.2
|
||||
lazy-object-proxy==1.4.3
|
||||
mccabe==0.6.1
|
||||
msgpack==1.0.0
|
||||
mypy-extensions==0.4.3
|
||||
parso==0.6.2
|
||||
pathspec==0.7.0
|
||||
pipenv==2018.11.26
|
||||
pluggy==0.13.1
|
||||
prompt-toolkit==2.0.10
|
||||
protonvpn-cli==2.2.1
|
||||
psutil==5.6.3
|
||||
pycodestyle==2.5.0
|
||||
pydocstyle==5.0.2
|
||||
pyflakes==2.1.1
|
||||
Pygments==2.5.2
|
||||
pylint==2.4.4
|
||||
pynvim==0.4.1
|
||||
pyte==0.8.0
|
||||
python-jsonrpc-server==0.3.4
|
||||
python-language-server==0.31.8
|
||||
pythondialog==3.5.1
|
||||
regex==2020.2.20
|
||||
requests==2.22.0
|
||||
rope==0.16.0
|
||||
six==1.12.0
|
||||
snowballstemmer==2.0.0
|
||||
thefuck==3.29
|
||||
toml==0.10.0
|
||||
typed-ast==1.4.1
|
||||
typing-extensions==3.7.4.2
|
||||
websockets==8.1
|
||||
yarl==1.4.2
|
||||
ujson==1.35
|
||||
urllib3==1.25.8
|
||||
virtualenv==20.0.16
|
||||
virtualenv-clone==0.5.4
|
||||
wcwidth==0.1.7
|
||||
wrapt==1.11.2
|
||||
yapf==0.29.0
|
||||
|
|
|
@ -8,12 +8,18 @@ blinker==1.4
|
|||
certifi==2020.4.5.1
|
||||
cffi==1.14.0
|
||||
chardet==3.0.4
|
||||
click==7.1.1
|
||||
crc32c==2.0
|
||||
cryptography==2.8
|
||||
Flask==1.1.2
|
||||
Flask-Cors==3.0.8
|
||||
idna==2.9
|
||||
itsdangerous==1.1.0
|
||||
JACK-Client==0.5.2
|
||||
jedi==0.15.2
|
||||
Jinja2==2.11.2
|
||||
jsonpickle==1.3
|
||||
MarkupSafe==1.1.1
|
||||
multidict==4.7.5
|
||||
mypy==0.770
|
||||
mypy-extensions==0.4.3
|
||||
|
@ -35,4 +41,5 @@ typing-extensions==3.7.4.2
|
|||
ujson==1.35
|
||||
urllib3==1.25.8
|
||||
websockets==8.1
|
||||
Werkzeug==1.0.1
|
||||
yarl==1.4.2
|
||||
|
|
12
serverconfig.ini.example
Normal file
12
serverconfig.ini.example
Normal file
|
@ -0,0 +1,12 @@
|
|||
[raygun]
|
||||
key = CHANGEME
|
||||
enable = False
|
||||
|
||||
[shittyserver]
|
||||
notify_url = https://example.com
|
||||
websocket_port = 8079
|
||||
telnet_port = 8078
|
||||
|
||||
[stateserver]
|
||||
myradio_key = CHANGEME
|
||||
sustainer_autonews = True
|
|
@ -1,10 +0,0 @@
|
|||
[raygun]
|
||||
key = CHANGEME
|
||||
enable = False
|
||||
|
||||
[mattserver]
|
||||
notify_url = https://ent9s2r5u77vj.x.pipedream.net
|
||||
|
||||
[ports]
|
||||
websocket = 8079
|
||||
telnet = 8078
|
|
@ -1,27 +1,24 @@
|
|||
import asyncio
|
||||
import websockets
|
||||
import configparser
|
||||
import json
|
||||
import uuid
|
||||
import av # type: ignore
|
||||
import struct
|
||||
from aiortc import MediaStreamTrack, RTCPeerConnection, RTCSessionDescription # type: ignore
|
||||
from aiortc.mediastreams import MediaStreamError # type: ignore
|
||||
from aiortc.contrib.media import MediaBlackhole, MediaPlayer # type: ignore
|
||||
import jack as Jack # type: ignore
|
||||
import os
|
||||
import re
|
||||
from datetime import datetime
|
||||
from typing import Optional, Any, Type, Dict
|
||||
from types import TracebackType
|
||||
import sys
|
||||
import aiohttp
|
||||
from raygun4py import raygunprovider # type: ignore
|
||||
import struct
|
||||
import uuid
|
||||
from datetime import datetime
|
||||
from types import TracebackType
|
||||
from typing import Optional, Any, Type, Dict
|
||||
|
||||
import configparser
|
||||
import aiohttp
|
||||
import av # type: ignore
|
||||
import jack as Jack # type: ignore
|
||||
import websockets
|
||||
from aiortc import MediaStreamTrack, RTCPeerConnection, RTCSessionDescription # type: ignore
|
||||
from aiortc.mediastreams import MediaStreamError # type: ignore
|
||||
from raygun4py import raygunprovider # type: ignore
|
||||
|
||||
config = configparser.ConfigParser()
|
||||
config.read("shittyserver.ini")
|
||||
config.read("serverconfig.ini")
|
||||
|
||||
ENABLE_EXCEPTION_LOGGING = False
|
||||
|
||||
|
@ -112,7 +109,7 @@ async def notify_mattserver_about_sessions() -> None:
|
|||
data: Dict[str, Dict[str, str]] = {}
|
||||
for sid, sess in active_sessions.items():
|
||||
data[sid] = sess.to_dict()
|
||||
async with session.post(config.get("mattserver", "notify_url"), json=data) as response:
|
||||
async with session.post(config.get("shittyserver", "notify_url"), json=data) as response:
|
||||
print("Mattserver response", response)
|
||||
|
||||
|
||||
|
@ -339,10 +336,10 @@ async def serve(websocket: websockets.WebSocketServerProtocol, path: str) -> Non
|
|||
|
||||
|
||||
start_server = websockets.serve(
|
||||
serve, "localhost", int(config.get("ports", "websocket"))
|
||||
serve, "localhost", int(config.get("shittyserver", "websocket_port"))
|
||||
)
|
||||
|
||||
print("Shittyserver WS starting on port {}.".format(config.get("ports", "websocket")))
|
||||
print("Shittyserver WS starting on port {}.".format(config.get("shittyserver", "websocket_port")))
|
||||
|
||||
|
||||
async def telnet_server(
|
||||
|
@ -417,14 +414,14 @@ async def telnet_server(
|
|||
|
||||
async def run_telnet_server() -> None:
|
||||
server = await asyncio.start_server(
|
||||
telnet_server, "localhost", int(config.get("ports", "telnet"))
|
||||
telnet_server, "localhost", int(config.get("shittyserver", "telnet_port"))
|
||||
)
|
||||
await server.serve_forever()
|
||||
|
||||
|
||||
jack.activate()
|
||||
|
||||
print("Shittyserver TELNET starting on port {}".format(config.get("ports", "telnet")))
|
||||
print("Shittyserver TELNET starting on port {}".format(config.get("shittyserver", "telnet_port")))
|
||||
asyncio.get_event_loop().run_until_complete(notify_mattserver_about_sessions())
|
||||
|
||||
asyncio.get_event_loop().run_until_complete(
|
367
stateserver.py
Executable file
367
stateserver.py
Executable file
|
@ -0,0 +1,367 @@
|
|||
#!flask/bin/python
|
||||
## IMPORTANT ASSUMPTIONS MADE:
|
||||
# show timestamps start on the hour.
|
||||
# normal shows in real studios aren't currently a thing!!!
|
||||
import subprocess
|
||||
from typing import List, Any, Dict, Optional
|
||||
|
||||
from flask import Flask, jsonify, request
|
||||
from flask_cors import CORS # type: ignore
|
||||
import requests
|
||||
import datetime
|
||||
import random
|
||||
from telnetlib import Telnet
|
||||
import configparser
|
||||
|
||||
config = configparser.ConfigParser()
|
||||
config.read("serverconfig.ini")
|
||||
|
||||
api_key = config.get("stateserver", "myradio_key")
|
||||
app = Flask(__name__)
|
||||
CORS(app) # Enable Cors access-all
|
||||
|
||||
SUSTAINER_AUTONEWS = config.get("stateserver", "sustainer_autonews") == "True"
|
||||
|
||||
|
||||
def do_ws_srv_telnet(source: str) -> None:
|
||||
HOST = "localhost"
|
||||
print("telnet {} {} SEL {}".format(HOST, config.get("shittyserver", "telnet_port"), source))
|
||||
tn = Telnet(HOST, int(config.get("shittyserver", "telnet_port")))
|
||||
tn.write(b"SEL " + str.encode(source) + b"\n")
|
||||
try:
|
||||
print(tn.read_until(b"\n").decode("utf-8"))
|
||||
except EOFError:
|
||||
pass
|
||||
else:
|
||||
tn.close()
|
||||
|
||||
|
||||
def genFail(reason: str, code: int = 400) -> Any:
|
||||
return jsonify({"status": "FAIL", "reason": reason})
|
||||
|
||||
|
||||
def genPayload(payload: Any) -> Any:
|
||||
return jsonify({"status": "OK", "payload": payload})
|
||||
|
||||
|
||||
def myradioApiRequest(url: str) -> Any:
|
||||
res = requests.get('https://ury.org.uk/api/v2/' + url + '?api_key=' + api_key)
|
||||
if res.ok:
|
||||
return res.json()["payload"]
|
||||
else:
|
||||
raise Exception("err {} {}".format(res.status_code, res.text))
|
||||
|
||||
|
||||
def getNextHourTimestamp() -> int:
|
||||
current = datetime.datetime.now()
|
||||
currentPlusHour = current + datetime.timedelta(hours=1)
|
||||
nextHourStart = currentPlusHour.replace(minute=0, second=0)
|
||||
nextTimestamp = int(nextHourStart.timestamp())
|
||||
return nextTimestamp
|
||||
|
||||
|
||||
# sadly we're on python 3.7 so we can't use TypedDict
|
||||
Connection = Dict[str, Any]
|
||||
|
||||
|
||||
def getConnByID(connID: str) -> Optional[Connection]:
|
||||
for conn in connections:
|
||||
if conn["connid"] == connID:
|
||||
return conn
|
||||
return None
|
||||
|
||||
|
||||
SOURCE_JUKEBOX = 3 # Set to 8 for testing.
|
||||
SOURCE_OB = 4
|
||||
SOURCE_WS = 5
|
||||
SOURCE_OFFAIR = 8
|
||||
SOURCES = [SOURCE_JUKEBOX, SOURCE_OB, SOURCE_WS, SOURCE_OFFAIR]
|
||||
|
||||
# This array will only hold connections we've validated to be authorised to broadcast.
|
||||
connections: List[Connection] = []
|
||||
wsSessions: Dict[str, Dict[str, str]] = {}
|
||||
lastConnectionIDToRegister = -1
|
||||
|
||||
|
||||
def getCurrentShowConnection() -> Optional[Connection]:
|
||||
for connection in connections:
|
||||
if (connection["startTimestamp"] <= datetime.datetime.now().timestamp()) and (
|
||||
connection["endTimestamp"] >= getNextHourTimestamp()):
|
||||
return connection
|
||||
return None
|
||||
|
||||
|
||||
def getNextHourConnection() -> Optional[Connection]:
|
||||
nextHourTimestamp = getNextHourTimestamp()
|
||||
isConnectionEnding = False
|
||||
for connection in connections:
|
||||
if connection["startTimestamp"] == nextHourTimestamp:
|
||||
return connection
|
||||
if connection["endTimestamp"] == nextHourTimestamp:
|
||||
isConnectionEnding = True
|
||||
|
||||
if not isConnectionEnding:
|
||||
# There isn't a show that starts at the next hour, so we're returning the current connection.
|
||||
return getCurrentShowConnection()
|
||||
else:
|
||||
# The show is ending, return no next show.
|
||||
return None
|
||||
|
||||
|
||||
def cleanOldConnections() -> None:
|
||||
global connections
|
||||
for i in range(len(connections)):
|
||||
if connections[i]["endTimestamp"] < datetime.datetime.now().timestamp():
|
||||
connections.pop(i)
|
||||
|
||||
|
||||
def stateDecider() -> Dict[str, Any]:
|
||||
currentConnection = getCurrentShowConnection()
|
||||
nextConnection = getNextHourConnection()
|
||||
print("currentConnection:", currentConnection)
|
||||
print("nextConnection:", nextConnection)
|
||||
willRunAutoNews = True
|
||||
switchAudioAtMin = 2
|
||||
newSelSource = None
|
||||
newWSSource = None
|
||||
if currentConnection != nextConnection:
|
||||
print("Will be transitioning")
|
||||
# The show is transitioning this hour.
|
||||
if currentConnection:
|
||||
print("There's a current connection.")
|
||||
# Current show wants to end their show at 2 mins past
|
||||
if currentConnection["autoNewsEnd"] == False:
|
||||
print("This show doesn't want to end with news.")
|
||||
willRunAutoNews = False
|
||||
switchAudioAtMin = 2 # no real change here
|
||||
if nextConnection:
|
||||
print("There's a next connection.")
|
||||
# next show wants to begin at 0 mins past hour.
|
||||
if nextConnection["autoNewsBeginning"] == False:
|
||||
print("The next connection doesn't want news at start.")
|
||||
willRunAutoNews = False
|
||||
switchAudioAtMin = 0
|
||||
|
||||
newSelSource = nextConnection["sourceid"]
|
||||
newWSSource = nextConnection["wsid"] # None if show is not a WS.
|
||||
else:
|
||||
print("No next show, going back to jukebox.")
|
||||
# There isn't a next show, go back to sustainer
|
||||
newSelSource = SOURCE_JUKEBOX
|
||||
|
||||
else:
|
||||
# Show/sustainer is continuing for another hour.
|
||||
print("Show / Sustainer is continuing this hour.")
|
||||
if currentConnection:
|
||||
print("We're currently doing a show, so check if they want middle news.")
|
||||
willRunAutoNews = currentConnection["autoNewsMiddle"]
|
||||
newSelSource = currentConnection["sourceid"]
|
||||
newWSSource = currentConnection["wsid"]
|
||||
elif SUSTAINER_AUTONEWS:
|
||||
print("There's no show on currently, so we're going to AutoNEWS on sustainer")
|
||||
# Jukebox -> NEWS -> Jukebox
|
||||
newSelSource = SOURCE_JUKEBOX
|
||||
else:
|
||||
print("There's no show on currently, but AutoNews on sustainer is disabled, so don't do news")
|
||||
# Jukebox -> Jukebox
|
||||
newSelSource = SOURCE_JUKEBOX
|
||||
switchAudioAtMin = 0
|
||||
willRunAutoNews = False
|
||||
|
||||
nextState = {
|
||||
"autoNews": willRunAutoNews,
|
||||
"switchAudioAtMin": switchAudioAtMin,
|
||||
"selSource": newSelSource,
|
||||
"wsSource": newWSSource
|
||||
}
|
||||
|
||||
return nextState
|
||||
|
||||
|
||||
@app.route('/api/v1/status', methods=['GET'])
|
||||
def get_status() -> Any:
|
||||
print(getNextHourTimestamp())
|
||||
global connections
|
||||
cleanOldConnections()
|
||||
return genPayload(
|
||||
{
|
||||
"connections": connections,
|
||||
"wsSessions": wsSessions
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@app.route('/api/v1/nextTransition', methods=['GET'])
|
||||
def get_next_transition() -> Any:
|
||||
cleanOldConnections()
|
||||
return genPayload(stateDecider())
|
||||
|
||||
|
||||
@app.route('/api/v1/cancelTimeslot', methods=['POST'])
|
||||
def post_cancelCheck() -> Any:
|
||||
global connections
|
||||
content = request.json
|
||||
if not content:
|
||||
return genFail("No parameters provided.")
|
||||
if not isinstance(content["connid"], int):
|
||||
return genFail("Request missing valid connid.")
|
||||
|
||||
# We're gonna cancel their show.
|
||||
currentShow = getCurrentShowConnection()
|
||||
if currentShow and currentShow["connid"] == content["connid"]:
|
||||
# this show is (at least supposed to be) live now.
|
||||
# kill their show
|
||||
do_ws_srv_telnet("NUL")
|
||||
switch_proc = subprocess.Popen(["sel", str(SOURCE_JUKEBOX)])
|
||||
pass
|
||||
for i in range(len(connections)):
|
||||
if connections[i]["connid"] == content["connid"]:
|
||||
connections.pop(i)
|
||||
return genPayload("Connection cancelled.")
|
||||
return genFail("Connection not found.")
|
||||
|
||||
|
||||
@app.route('/api/v1/registerTimeslot', methods=['POST'])
|
||||
def post_registerCheck() -> Any:
|
||||
global connections
|
||||
global lastConnectionIDToRegister
|
||||
|
||||
content = request.json
|
||||
if not content:
|
||||
return genFail("No parameters provided.")
|
||||
if not isinstance(content["timeslotid"], int):
|
||||
return genFail("Request missing valid timeslotid.")
|
||||
if not isinstance(content["memberid"], int):
|
||||
return genFail("Request missing valid memberid.")
|
||||
if not isinstance(content["sourceid"], int):
|
||||
return genFail("Request missing valid source.")
|
||||
if not content["sourceid"] in SOURCES:
|
||||
return genFail("Request missing valid source.")
|
||||
|
||||
member = myradioApiRequest("user/" + str(content["memberid"]))
|
||||
if not member:
|
||||
return genFail("Could not get member.")
|
||||
|
||||
timeslot = myradioApiRequest("timeslot/" + str(content["timeslotid"]))
|
||||
if not timeslot:
|
||||
return genFail("Could not get tiemslot.")
|
||||
|
||||
found_credit = False
|
||||
for credit in timeslot["credits"]:
|
||||
if content["memberid"] == credit["memberid"]:
|
||||
found_credit = True
|
||||
break
|
||||
if not found_credit:
|
||||
return genFail("You are not authorised to broadcast for this timeslot.")
|
||||
|
||||
for conn in connections:
|
||||
if content["timeslotid"] == conn["timeslotid"]:
|
||||
# they've already registered, return the existing session
|
||||
return genPayload(conn)
|
||||
|
||||
start_time = datetime.datetime.strptime(timeslot["start_time"], "%d/%m/%Y %H:%M")
|
||||
|
||||
duration = timeslot["duration"].split(":")
|
||||
duration_time = datetime.timedelta(hours=int(duration[0]), minutes=int(duration[1]))
|
||||
|
||||
end_time = start_time + duration_time
|
||||
|
||||
now_time = datetime.datetime.now()
|
||||
if start_time - now_time > datetime.timedelta(hours=1):
|
||||
return genFail("This show too far away, please try again within an hour of starting your show.")
|
||||
|
||||
if start_time + duration_time < now_time:
|
||||
return genFail("This show has already ended.")
|
||||
|
||||
random.seed(a=timeslot["timeslot_id"], version=2)
|
||||
connection = {
|
||||
"connid": random.randint(0, 100000000), # TODO: this is horrible. I'll sort this later.
|
||||
"timeslotid": timeslot["timeslot_id"],
|
||||
"startTimestamp": int(start_time.timestamp()),
|
||||
"endTimestamp": int(end_time.timestamp()),
|
||||
"sourceid": content["sourceid"],
|
||||
'autoNewsBeginning': True,
|
||||
'autoNewsMiddle': True,
|
||||
'autoNewsEnd': True,
|
||||
'wsid': None
|
||||
}
|
||||
connections.append(connection)
|
||||
print(connections)
|
||||
|
||||
lastConnectionIDToRegister = connection["connid"]
|
||||
|
||||
return genPayload(connection)
|
||||
|
||||
|
||||
@app.route('/api/v1/changeTimeslot', methods=['POST'])
|
||||
def post_settingsCheck() -> Any:
|
||||
global connections
|
||||
content = request.json
|
||||
if not content:
|
||||
return genFail("No parameters provided.")
|
||||
if not isinstance(content["connid"], int):
|
||||
return genFail("Request missing valid connID.")
|
||||
if not isinstance(content["beginning"], bool):
|
||||
return genFail("Request missing valid beginning bool.")
|
||||
if not isinstance(content["middle"], bool):
|
||||
return genFail("Request missing valid middle bool.")
|
||||
if not isinstance(content["end"], bool):
|
||||
return genFail("Request missing valid end bool.")
|
||||
if not isinstance(content["sourceid"], int):
|
||||
return genFail("Request missing valid sourcid.")
|
||||
|
||||
for conn in connections:
|
||||
if conn["connid"] == content["connid"]:
|
||||
conn["autoNewsBeginning"] = content["beginning"]
|
||||
conn["autoNewsMiddle"] = content["middle"]
|
||||
conn["autoNewsEnd"] = content["end"]
|
||||
conn["sourceid"] = content["sourceid"]
|
||||
return genPayload(conn)
|
||||
return genFail("No connection found.")
|
||||
|
||||
|
||||
@app.route('/api/v1/updateWSSessions', methods=['POST'])
|
||||
def post_wsSessions() -> Any:
|
||||
global connections
|
||||
global wsSessions
|
||||
content = request.json
|
||||
# if not content:
|
||||
# return genFail("No parameters provided.")
|
||||
oldSessions = wsSessions
|
||||
|
||||
wsSessions = content
|
||||
print("New wsSessions:", wsSessions)
|
||||
wsids_to_remove = []
|
||||
wsids_to_add = []
|
||||
for session in oldSessions:
|
||||
if not oldSessions[session]["connection_id"] in wsSessions:
|
||||
wsids_to_remove.append(oldSessions[session]["connection_id"])
|
||||
|
||||
print("wsSessions which have disappeared:", wsids_to_remove)
|
||||
|
||||
for session in wsSessions:
|
||||
if not wsSessions[session]["connection_id"] in oldSessions:
|
||||
wsids_to_add.append(wsSessions[session]["connection_id"])
|
||||
|
||||
print("wsSessions which have appeared:", wsids_to_add)
|
||||
|
||||
for conn in connections:
|
||||
if conn["connid"] == lastConnectionIDToRegister:
|
||||
if conn["wsid"] == None and len(wsids_to_add) == 1:
|
||||
conn["wsid"] = wsids_to_add[0]
|
||||
# time.sleep(5)
|
||||
# TODO this doesn't exactly work right
|
||||
do_ws_srv_telnet(conn["wsid"])
|
||||
subprocess.Popen(['sel', '5'])
|
||||
|
||||
if conn["wsid"] in wsids_to_remove:
|
||||
conn["wsid"] = None
|
||||
# TODO Make this actually do a disconnect sequence if this is the current show.
|
||||
# time.sleep(5)
|
||||
subprocess.Popen(['sel', str(SOURCE_JUKEBOX)])
|
||||
do_ws_srv_telnet("NUL")
|
||||
return genPayload("Thx, K, bye.")
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
app.run(debug=True, host="0.0.0.0")
|
Loading…
Reference in a new issue