From a2fb309ce832625850e577460247f2fb7e9e1566 Mon Sep 17 00:00:00 2001 From: monster860 Date: Sat, 5 Jun 2021 06:12:20 -0400 Subject: [PATCH 1/6] Voice Announcement System --- .gitignore | 4 +- Dockerfile | 3 + config.yml | 10 +- run_with_env_vars.bat | 2 + yogsite/__init__.py | 4 +- yogsite/config.py | 2 +- yogsite/modules/voice_announce/__init__.py | 1 + yogsite/modules/voice_announce/routes.py | 114 ++++++++ yogsite/static/js/voice_announce.js | 245 ++++++++++++++++++ .../voice_announce/voice_announce.html | 49 ++++ 10 files changed, 430 insertions(+), 4 deletions(-) create mode 100644 yogsite/modules/voice_announce/__init__.py create mode 100644 yogsite/modules/voice_announce/routes.py create mode 100644 yogsite/static/js/voice_announce.js create mode 100644 yogsite/templates/voice_announce/voice_announce.html diff --git a/.gitignore b/.gitignore index 6bb7afc..4d03b77 100644 --- a/.gitignore +++ b/.gitignore @@ -6,4 +6,6 @@ venv key_env.bat -.vscode \ No newline at end of file +.vscode + +voice_announce_tmp \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index d2c81b0..8975916 100644 --- a/Dockerfile +++ b/Dockerfile @@ -5,6 +5,9 @@ ENV UWSGI_INI /srv/www/yogsite/uwsgi.ini COPY . /srv/www/yogsite COPY nginx.conf /etc/nginx/sites-available/ +RUN apt-get install -y ffmpeg +ENV FFMPEG_COMMAND ffmpeg + RUN pip install -r /srv/www/yogsite/requirements.txt WORKDIR /srv/www/yogsite \ No newline at end of file diff --git a/config.yml b/config.yml index 24dff08..7a775d7 100644 --- a/config.yml +++ b/config.yml @@ -15,6 +15,7 @@ items_per_page: 20 servers: main: id: "main" + sqlname: "yogstation" host: "game.yogstation.net" port: 4133 name: "YogStation Main" @@ -103,7 +104,11 @@ roles: [ "gangster", "darkspawn", "Holoparasite", - "Zombie" + "Zombie", + "Appearance", + "Emote", + "OOC", + "Voice Announcements" ] library: @@ -133,6 +138,9 @@ paypal: return_url: "/donate?confirm=1" notify_url: "/api/paypal_donate" +voice_announce: + directory: $GAME_VOICE_ANNOUNCE_DIR + donation: tiers: - amount: 7.00 diff --git a/run_with_env_vars.bat b/run_with_env_vars.bat index 4124f97..acbbf82 100644 --- a/run_with_env_vars.bat +++ b/run_with_env_vars.bat @@ -6,4 +6,6 @@ set DB_GAME_NAME="yogstation" set FLASK_SECRET_KEY="geiogjiovheiofhweiofh" +set GAME_VOICE_ANNOUNCE_DIR=".\\voice_announce_tmp" + python wsgi.py \ No newline at end of file diff --git a/yogsite/__init__.py b/yogsite/__init__.py index 440d960..da46afa 100644 --- a/yogsite/__init__.py +++ b/yogsite/__init__.py @@ -85,6 +85,7 @@ def modify_query(**new_values): from yogsite.modules.login import blueprint as bp_login from yogsite.modules.home import blueprint as bp_home from yogsite.modules.rounds import blueprint as bp_rounds +from yogsite.modules.voice_announce import blueprint as bp_voice_announce app.register_blueprint(bp_admin) app.register_blueprint(bp_api) @@ -94,4 +95,5 @@ def modify_query(**new_values): app.register_blueprint(bp_home) app.register_blueprint(bp_library) app.register_blueprint(bp_login) -app.register_blueprint(bp_rounds) \ No newline at end of file +app.register_blueprint(bp_rounds) +app.register_blueprint(bp_voice_announce) \ No newline at end of file diff --git a/yogsite/config.py b/yogsite/config.py index 8329a00..142c417 100644 --- a/yogsite/config.py +++ b/yogsite/config.py @@ -2,4 +2,4 @@ cfg = EnvYAML("config.yml") -XENFORO_HEADERS = {"XF-Api-Key": cfg.get("xenforo_key")} \ No newline at end of file +XENFORO_HEADERS = {"XF-Api-Key": cfg.get("xenforo_key")} diff --git a/yogsite/modules/voice_announce/__init__.py b/yogsite/modules/voice_announce/__init__.py new file mode 100644 index 0000000..05c7d51 --- /dev/null +++ b/yogsite/modules/voice_announce/__init__.py @@ -0,0 +1 @@ +from .routes import blueprint \ No newline at end of file diff --git a/yogsite/modules/voice_announce/routes.py b/yogsite/modules/voice_announce/routes.py new file mode 100644 index 0000000..1c45db9 --- /dev/null +++ b/yogsite/modules/voice_announce/routes.py @@ -0,0 +1,114 @@ +from flask import Blueprint, Response, request, render_template +from werkzeug.utils import secure_filename +from io import open +from os import path, stat, remove +from yogsite.extensions import flask_csrf_ext +from yogsite.config import cfg +from yogsite.util import topic_query +from subprocess import run,DEVNULL +from datetime import datetime, timedelta, timezone +import json + +blueprint = Blueprint("voice_announce", __name__) + +type_extensions = { + "audio/aac": ".aac", + "audio/mpeg": ".mp3", + "audio/ogg": ".ogg", + "audio/opus": ".opus", + "audio/wav": ".wav", + "audio/webm": ".weba" +} + +@blueprint.route("/voice_announce/") +def page_voice_announce(id): + id = secure_filename(id) + dir = cfg.get('voice_announce.directory') + if not path.exists(path.join(dir, id + ".json")): + return Response("Invalid voice announcement URL", status=404) + with open(path.join(dir, id + ".json")) as f: + data = json.load(f) + created_date = datetime.fromisoformat(data["created"]) + print(created_date) + time_since_created = datetime.utcnow().replace(tzinfo=timezone.utc) - created_date + if time_since_created > timedelta(seconds = 15): + return Response("Voice announcement URL expired", status=404) + + return render_template("voice_announce/voice_announce.html", enable_robot_voice = data["is_ai"]) + +@blueprint.route("/voice_announce//upload", methods=["POST"]) +@flask_csrf_ext.exempt +def voice_announce_upload(id): + id = secure_filename(id) + dir = cfg.get('voice_announce.directory') + if not path.exists(path.join(dir, id + ".json")): + return Response("Invalid voice announcement upload URL", status=404) + with open(path.join(dir, id + ".json")) as f: + data = json.load(f) + created_date = datetime.fromisoformat(data["created"]) + print(created_date) + time_since_created = datetime.utcnow().replace(tzinfo=timezone.utc) - created_date + if time_since_created > timedelta(minutes = 5): + remove(path.join(dir, id + ".json")) + return Response("Voice announcement URL expired", status=404) + if request.content_length > 120000: + return Response("File too large", status=400) + ct = request.content_type + semicolon_loc = ct.find(";") + if semicolon_loc != -1: + ct = ct[:semicolon_loc] + if type_extensions[ct] == None: + return Response("Invalid file type", status=400) + filename_base = id + filename = filename_base + "_base" + type_extensions[ct] + ogg_filename = filename_base + "_converted.ogg" + + #if path.exists(path.join(dir, ogg_filename)): + # return Response("URL already used", status=400) + + with open(path.join(dir,filename), "wb") as file: + file.write(request.get_data()) + + result = run(["ffmpeg", "-i", path.join(dir,filename), "-c:a", "libvorbis", "-y", path.join(dir,ogg_filename)], stdin=DEVNULL,stdout=DEVNULL,stderr=DEVNULL) + if result.returncode != 0: + remove(path.join(dir, filename)) + return Response("Conversion failed", status=500) + probe_result = run(["ffprobe", "-i", path.join(dir, ogg_filename), "-show_entries", "format=duration", "-v", "quiet", "-of", "csv=p=0"], capture_output=True) + if probe_result.returncode != 0: + remove(path.join(dir, filename)) + remove(path.join(dir, ogg_filename)) + return Response("ffprobe failed: " + probe_result.stderr.decode("utf-8"), status=500) + duration = float(probe_result.stdout) + if duration > 35: + remove(path.join(dir, filename)) + remove(path.join(dir, ogg_filename)) + return Response("Duration too long!", status=400) + + for s in cfg.get("servers").values(): + if s["sqlname"]: + server = s + + topic_query(server, "", args = { + "voice_announce": id, + "voice_announce_token": data["topic_token"], + "ogg_file": ogg_filename, + "uploaded_file": filename, + "ip": request.remote_addr, + "duration": duration + }) + + remove(path.join(dir, id + ".json")) + + return Response(None, status=204) + +@blueprint.route("/voice_announce//cancel", methods=["GET","POST"]) +@flask_csrf_ext.exempt +def voice_announce_cancel(id): + id = secure_filename(id) + dir = cfg.get('voice_announce.directory') + if not path.exists(path.join(dir, id + ".json")): + return Response("Invalid voice announcement upload URL", status=404) + + remove(path.join(dir, id + ".json")) + + return Response(None, status=204) diff --git a/yogsite/static/js/voice_announce.js b/yogsite/static/js/voice_announce.js new file mode 100644 index 0000000..11649c8 --- /dev/null +++ b/yogsite/static/js/voice_announce.js @@ -0,0 +1,245 @@ +const RECORDING_STATE_IDLE = 0; +const RECORDING_STATE_WAITING = 1; +const RECORDING_STATE_RECORDING = 2; +const RECORDING_STATE_UPLOADING = 3; +const RECORDING_STATE_DONE = 4; + +let recording_state = RECORDING_STATE_IDLE; +/** @type {MediaStream} */ +let mic_media_stream; +/** @type {MediaStream} */ +let dest_media_stream; +/** @type {AnalyserNode} */ +let analyser; +/** @type {Float32Array} */ +let analyser_data; +let recorder; +let recording_start_time; + +/** @type {Blob} */ +let recorded_blob; +/** @type {string} */ +let recorded_blob_url; + +const audio_ctx = new AudioContext(); + +const robot_freq = 59.94; // Our nanotrasen-brand AIs operate on NTSC, okay? +const robot_cycles = 300; + +function set_recording_state(state) { + let prev = recording_state; + if(recording_state == state) return; + recording_state = state; + let elem = document.getElementById("va-button-record"); + elem.classList.remove("is-warning", "is-success"); + if(state == RECORDING_STATE_IDLE) { + if(prev == RECORDING_STATE_RECORDING || prev == RECORDING_STATE_UPLOADING) elem.textContent = "Re-record"; + else elem.textContent = "Record"; + } else if(state == RECORDING_STATE_WAITING) { + elem.textContent = "Waiting for permission..."; + elem.classList.add("is-warning"); + } else if(state == RECORDING_STATE_RECORDING) { + elem.textContent = "Stop Recording"; + elem.classList.add("is-success"); + } + for(let item of document.getElementsByClassName("va-record-show")) { + if(state == RECORDING_STATE_RECORDING) { + item.classList.remove("is-hidden"); + } else { + item.classList.add("is-hidden"); + } + } + let upload_button = document.getElementById("va-button-announce"); + upload_button.classList.remove("is-warning"); + upload_button.classList.remove("is-success"); + if(state == RECORDING_STATE_UPLOADING) { + elem.classList.add("is-hidden"); + upload_button.classList.add("is-warning"); + upload_button.textContent = "Uploading..."; + } else if(state == RECORDING_STATE_DONE) { + elem.classList.add("is-hidden"); + upload_button.classList.add("is-success"); + upload_button.textContent = "Upload successful!"; + } else { + elem.classList.remove("is-hidden"); + upload_button.textContent = "Confirm Announcement" + } +} + +let speaker_setups = [ + [0, 0, 0.7], // delay, pan, gain + [0.1, -0.6, 0.25], + [0.2, 0.9, 0.18], + [0.4, 0.3, 0.03] +]; + +/** + * + * @param {AudioParam} param + */ +function apply_robot_wave(param, time = audio_ctx.currentTime) { + console.log("Applying " + time + ", now: " + audio_ctx.currentTime); + let values = new Float32Array(robot_cycles * 2); + for(let i = 0; i < robot_cycles; i++) { + values[i*2] = 0; + values[i*2+1] = 1; + } + let duration = robot_cycles / robot_freq; + param.setValueCurveAtTime(values, time, duration); + setTimeout(() => {apply_robot_wave(param, time + duration + 0.001);}, ((time + duration - (duration/3)) - audio_ctx.currentTime) * 1000); +} + +/** + * + * @param {AudioNode} output + * @param {AudioNode} input + */ +function apply_effects(output, input) { + if(enable_robot_voice) { + // Apply a really primitive "robot voice" filter + let final_gain = audio_ctx.createGain(); + input.connect(final_gain); + input = final_gain; + apply_robot_wave(final_gain.gain); + } + analyser = audio_ctx.createAnalyser(); + analyser.connect(output); + analyser_data = new Float32Array(analyser.frequencyBinCount); + output = analyser; + //input.connect(analyser); + + for(let [delay, pan, gain] of speaker_setups) { + let curr = input; + + if(delay) { + let delay_node = audio_ctx.createDelay(delay); + delay_node.delayTime.value = delay; + curr.connect(delay_node); + curr = delay_node; + } + + if(pan) { + let pan_node = audio_ctx.createStereoPanner(); + pan_node.pan.value = pan; + curr.connect(pan_node); + curr = pan_node; + } + + if(gain) { + let gain_node = audio_ctx.createGain(); + gain_node.gain.value = gain; + curr.connect(gain_node); + curr = gain_node; + } + curr.connect(output); + } +} + +function update_level() { + analyser.getFloatTimeDomainData(analyser_data); + /** @type {HTMLProgressElement} */ + let bar = document.getElementById("va-level"); + let max_abs = 0; + for(let i = 0; i < analyser_data.length; i++) { + max_abs = Math.max(max_abs, Math.abs(analyser_data[i])); + } + bar.value = 100 * max_abs; + if(recording_state == RECORDING_STATE_RECORDING) { + document.getElementById("va-time").textContent = (Math.floor(audio_ctx.currentTime - recording_start_time)) + " / 30"; + if((audio_ctx.currentTime - recording_start_time) >= 30) { + stop_recording(); + } + } + requestAnimationFrame(update_level); +} + +async function setup_media_stream() { + if(dest_media_stream) return; + + await audio_ctx.resume(); + mic_media_stream = await navigator.mediaDevices.getUserMedia({audio: true}); + let stream_node = audio_ctx.createMediaStreamSource(mic_media_stream); + let dest_node = audio_ctx.createMediaStreamDestination(); + dest_media_stream = dest_node.stream; + apply_effects(dest_node, stream_node); + update_level(); +} + +async function stop_recording() { + set_recording_state(RECORDING_STATE_IDLE); + recorded_blob = await new Promise((resolve, reject) => { + recorder.ondataavailable = (e) => {resolve(e.data);}; + recorder.onerror = reject; + recorder.stop(); + }); + for(let track of mic_media_stream.getAudioTracks()) track.enabled = false; + recorded_blob_url = URL.createObjectURL(recorded_blob); + document.getElementById("va-button-announce").classList.remove("is-hidden"); + document.getElementById("va-preview").classList.remove("is-hidden"); + document.getElementById("va-preview").src = recorded_blob_url; +} + +async function record_button() { + if(recording_state == RECORDING_STATE_IDLE) { + if(recorded_blob) { + recorded_blob = null; + URL.revokeObjectURL(recorded_blob_url); + recorded_blob_url = null; + document.getElementById("va-button-announce").classList.add("is-hidden"); + document.getElementById("va-preview").classList.add("is-hidden"); + document.getElementById("va-preview").pause(); + } + set_recording_state(RECORDING_STATE_WAITING); + try { + await setup_media_stream(); + for(let track of mic_media_stream.getAudioTracks()) track.enabled = true; + set_recording_state(RECORDING_STATE_RECORDING); + recorder = new MediaRecorder(dest_media_stream, {audioBitsPerSecond: 20000}); + recorder.start(); + recording_start_time = audio_ctx.currentTime; + } catch(e) { + console.error(e); + set_recording_state(RECORDING_STATE_IDLE); + } + } else if(recording_state == RECORDING_STATE_RECORDING) { + await stop_recording(); + } +} + +async function upload_button() { + if(recording_state == RECORDING_STATE_IDLE && recorded_blob) { + set_recording_state(RECORDING_STATE_UPLOADING); + let url = location.origin + location.pathname + "/upload"; + try { + let res = await fetch(url, { + method: 'POST', + cache: 'no-cache', + body: recorded_blob, + headers: { + 'Content-Type': recorded_blob.type + }, + mode: 'same-origin' + }); + if(res.status == 204) { + set_recording_state(RECORDING_STATE_DONE); + for(let track of mic_media_stream.getAudioTracks()) track.stop(); + } else { + set_recording_state(RECORDING_STATE_IDLE); + } + } catch(e) { + set_recording_state(RECORDING_STATE_IDLE); + } + } +} + +window.addEventListener("DOMContentLoaded", () => { + document.getElementById("va-button-record").addEventListener("click", record_button); + document.getElementById("va-button-announce").addEventListener("click", upload_button); +}); + +document.addEventListener("visibilitychange", () => { + let url = location.origin + location.pathname + "/cancel"; + if(recording_state != RECORDING_STATE_DONE && document.visibilityState == 'hidden') { + navigator.sendBeacon(url) + } +}) diff --git a/yogsite/templates/voice_announce/voice_announce.html b/yogsite/templates/voice_announce/voice_announce.html new file mode 100644 index 0000000..6793f59 --- /dev/null +++ b/yogsite/templates/voice_announce/voice_announce.html @@ -0,0 +1,49 @@ +{% extends "layout.html" %} + +{% block title %}Voice Announcements{% endblock %} + +{% block head %} + + +{% endblock %} + +{% block content %} +

Voice Announcement System

+ +
+
+
+

WARNING: Misuse of this system will lead to a ban. You may only use this system to upload your own voice.

+
+
+
+
+ +
+ +
+ +
+
+
+
+
+
+
+
+ +
+
+ +
+
+
+
+
+
+
+{% endblock %} \ No newline at end of file From 52b7fb281b2ab3e5e0b79cd87af8d5b3e552f6fb Mon Sep 17 00:00:00 2001 From: monster860 Date: Sat, 5 Jun 2021 08:59:14 -0400 Subject: [PATCH 2/6] Experimental branch for ffmpeg --- Dockerfile | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 8975916..0b28a99 100644 --- a/Dockerfile +++ b/Dockerfile @@ -5,8 +5,9 @@ ENV UWSGI_INI /srv/www/yogsite/uwsgi.ini COPY . /srv/www/yogsite COPY nginx.conf /etc/nginx/sites-available/ -RUN apt-get install -y ffmpeg -ENV FFMPEG_COMMAND ffmpeg +RUN echo "deb http://deb.debian.org/debian experimental main" >> /etc/apt/sources.list +RUN apt-get update +RUN apt-get install -y -t experimental ffmpeg RUN pip install -r /srv/www/yogsite/requirements.txt From 458eac22bf00b3b187329a55150afff7654afd4a Mon Sep 17 00:00:00 2001 From: monster860 Date: Sat, 5 Jun 2021 09:52:00 -0400 Subject: [PATCH 3/6] makes the thing work --- Dockerfile | 1 + 1 file changed, 1 insertion(+) diff --git a/Dockerfile b/Dockerfile index 0b28a99..7c2a949 100644 --- a/Dockerfile +++ b/Dockerfile @@ -6,6 +6,7 @@ COPY . /srv/www/yogsite COPY nginx.conf /etc/nginx/sites-available/ RUN echo "deb http://deb.debian.org/debian experimental main" >> /etc/apt/sources.list +RUN echo "deb http://deb.debian.org/debian sid main" >> /etc/apt/sources.list RUN apt-get update RUN apt-get install -y -t experimental ffmpeg From 29d2ac9f112a23b7db84de095af72f1e89272b37 Mon Sep 17 00:00:00 2001 From: monster860 Date: Sat, 5 Jun 2021 12:11:46 -0400 Subject: [PATCH 4/6] Uses topic instead of json files --- config.yml | 5 +- run_with_env_vars.bat | 1 + yogsite/modules/voice_announce/routes.py | 82 +++++++++++------------- 3 files changed, 42 insertions(+), 46 deletions(-) diff --git a/config.yml b/config.yml index 7a775d7..ed93158 100644 --- a/config.yml +++ b/config.yml @@ -16,10 +16,11 @@ servers: main: id: "main" sqlname: "yogstation" - host: "game.yogstation.net" - port: 4133 + host: "localhost" + port: 6060 name: "YogStation Main" primary: true + comms_key: $COMMS_KEY logs: directory: $GAME_LOGS_DIR diff --git a/run_with_env_vars.bat b/run_with_env_vars.bat index acbbf82..acfe90e 100644 --- a/run_with_env_vars.bat +++ b/run_with_env_vars.bat @@ -5,6 +5,7 @@ set DB_GAME_PORT=3306 set DB_GAME_NAME="yogstation" set FLASK_SECRET_KEY="geiogjiovheiofhweiofh" +set COMMS_KEY="" set GAME_VOICE_ANNOUNCE_DIR=".\\voice_announce_tmp" diff --git a/yogsite/modules/voice_announce/routes.py b/yogsite/modules/voice_announce/routes.py index 1c45db9..b3fe445 100644 --- a/yogsite/modules/voice_announce/routes.py +++ b/yogsite/modules/voice_announce/routes.py @@ -1,13 +1,11 @@ from flask import Blueprint, Response, request, render_template from werkzeug.utils import secure_filename from io import open -from os import path, stat, remove +from os import path, remove from yogsite.extensions import flask_csrf_ext from yogsite.config import cfg from yogsite.util import topic_query from subprocess import run,DEVNULL -from datetime import datetime, timedelta, timezone -import json blueprint = Blueprint("voice_announce", __name__) @@ -20,37 +18,37 @@ "audio/webm": ".weba" } -@blueprint.route("/voice_announce/") -def page_voice_announce(id): - id = secure_filename(id) - dir = cfg.get('voice_announce.directory') - if not path.exists(path.join(dir, id + ".json")): +@blueprint.route("/voice_announce//") +def page_voice_announce(serversqlname, id): + for s in cfg.get("servers").values(): + if s["sqlname"] == serversqlname: + server = s + res = topic_query(server, "", args = { + "voice_announce_query": id, + "key": server["comms_key"] + }) + print(res["exists"]) + print(int(res["exists"])) + if (not res) or (not int(res["exists"])): return Response("Invalid voice announcement URL", status=404) - with open(path.join(dir, id + ".json")) as f: - data = json.load(f) - created_date = datetime.fromisoformat(data["created"]) - print(created_date) - time_since_created = datetime.utcnow().replace(tzinfo=timezone.utc) - created_date - if time_since_created > timedelta(seconds = 15): - return Response("Voice announcement URL expired", status=404) - - return render_template("voice_announce/voice_announce.html", enable_robot_voice = data["is_ai"]) + + return render_template("voice_announce/voice_announce.html", enable_robot_voice = int(res["is_ai"])) -@blueprint.route("/voice_announce//upload", methods=["POST"]) +@blueprint.route("/voice_announce///upload", methods=["POST"]) @flask_csrf_ext.exempt -def voice_announce_upload(id): +def voice_announce_upload(serversqlname, id): + for s in cfg.get("servers").values(): + if s["sqlname"] == serversqlname: + server = s id = secure_filename(id) dir = cfg.get('voice_announce.directory') - if not path.exists(path.join(dir, id + ".json")): - return Response("Invalid voice announcement upload URL", status=404) - with open(path.join(dir, id + ".json")) as f: - data = json.load(f) - created_date = datetime.fromisoformat(data["created"]) - print(created_date) - time_since_created = datetime.utcnow().replace(tzinfo=timezone.utc) - created_date - if time_since_created > timedelta(minutes = 5): - remove(path.join(dir, id + ".json")) - return Response("Voice announcement URL expired", status=404) + res = topic_query(server, "", args = { + "voice_announce_query": id, + "key": server["comms_key"] + }) + if (not res) or (not int(res["exists"])): + return Response("Invalid voice announcement URL", status=404) + if request.content_length > 120000: return Response("File too large", status=400) ct = request.content_type @@ -84,31 +82,27 @@ def voice_announce_upload(id): remove(path.join(dir, ogg_filename)) return Response("Duration too long!", status=400) - for s in cfg.get("servers").values(): - if s["sqlname"]: - server = s - topic_query(server, "", args = { "voice_announce": id, - "voice_announce_token": data["topic_token"], "ogg_file": ogg_filename, "uploaded_file": filename, "ip": request.remote_addr, - "duration": duration + "duration": duration, + "key": server["comms_key"] }) - remove(path.join(dir, id + ".json")) - return Response(None, status=204) -@blueprint.route("/voice_announce//cancel", methods=["GET","POST"]) +@blueprint.route("/voice_announce///cancel", methods=["GET","POST"]) @flask_csrf_ext.exempt -def voice_announce_cancel(id): - id = secure_filename(id) - dir = cfg.get('voice_announce.directory') - if not path.exists(path.join(dir, id + ".json")): - return Response("Invalid voice announcement upload URL", status=404) +def voice_announce_cancel(serversqlname, id): + for s in cfg.get("servers").values(): + if s["sqlname"] == serversqlname: + server = s - remove(path.join(dir, id + ".json")) + topic_query(server, "", args = { + "voice_announce_cancel": id, + "key": server["comms_key"] + }) return Response(None, status=204) From 8300d130604db3e8f1dec12e3e202d50e6ebcfd1 Mon Sep 17 00:00:00 2001 From: monster860 Date: Sat, 5 Jun 2021 12:15:01 -0400 Subject: [PATCH 5/6] oops forgot to change it back --- config.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config.yml b/config.yml index ed93158..1c02bdc 100644 --- a/config.yml +++ b/config.yml @@ -16,8 +16,8 @@ servers: main: id: "main" sqlname: "yogstation" - host: "localhost" - port: 6060 + host: "game.yogstation.net" + port: 4133 name: "YogStation Main" primary: true comms_key: $COMMS_KEY From 39da94ee20738183192c1b2a0212c88c63050339 Mon Sep 17 00:00:00 2001 From: Maxim Nikitin Date: Wed, 9 Jun 2021 04:20:09 -0400 Subject: [PATCH 6/6] remove printf debugging --- yogsite/modules/voice_announce/routes.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/yogsite/modules/voice_announce/routes.py b/yogsite/modules/voice_announce/routes.py index b3fe445..eb2dcd8 100644 --- a/yogsite/modules/voice_announce/routes.py +++ b/yogsite/modules/voice_announce/routes.py @@ -27,8 +27,6 @@ def page_voice_announce(serversqlname, id): "voice_announce_query": id, "key": server["comms_key"] }) - print(res["exists"]) - print(int(res["exists"])) if (not res) or (not int(res["exists"])): return Response("Invalid voice announcement URL", status=404) @@ -60,10 +58,6 @@ def voice_announce_upload(serversqlname, id): filename_base = id filename = filename_base + "_base" + type_extensions[ct] ogg_filename = filename_base + "_converted.ogg" - - #if path.exists(path.join(dir, ogg_filename)): - # return Response("URL already used", status=400) - with open(path.join(dir,filename), "wb") as file: file.write(request.get_data())