diff --git a/httpstatic/tts_hack.js b/httpstatic/tts_hack.js new file mode 100644 index 00000000..f4723ebe --- /dev/null +++ b/httpstatic/tts_hack.js @@ -0,0 +1,18 @@ +import {choc, set_content, DOM, on} from "https://rosuav.github.io/choc/factory.js"; +const {OPTGROUP, OPTION} = choc; //autoimport + +export function render(data) { + set_content("#tts_voice", data.voices.map(([label, voices]) => + OPTGROUP({label}, voices.map(v => OPTION({value: v.selector}, v.desc))) + )); +} + +export function sockmsg_speak(msg) { + DOM("#player").src = msg.tts; + DOM("#player").play(); +} + +on("submit", "#send", e => { + e.preventDefault(); + ws_sync.send({cmd: "speak", text: DOM("#stuff").value, voice: DOM("#tts_voice").value}); +}); diff --git a/modules/http/tts_hack.pike b/modules/http/tts_hack.pike new file mode 100644 index 00000000..d6dcbb5e --- /dev/null +++ b/modules/http/tts_hack.pike @@ -0,0 +1,34 @@ +inherit http_websocket; +inherit annotated; + +constant markdown = #"# TTS hack + + + + +
+"; + +mapping(string:mixed) http_request(Protocols.HTTP.Server.Request req) { + return render(req, (["vars": (["ws_group": req->variables->key || ""])])); +} + +@retain: multiset tts_hack_valid_keys = (<>); +string websocket_validate(mapping(string:mixed) conn, mapping(string:mixed) msg) { + if (!tts_hack_valid_keys[msg->group]) return "Nope"; +} + +mapping get_state(string group) { + return (["voices": G->G->tts_config->avail_voices || ({ })]); +} + +__async__ mapping|zero websocket_cmd_speak(mapping(string:mixed) conn, mapping(string:mixed) msg) { + string text = msg->text; + if (!text || text == "") return 0; + object alertbox = G->G->websocket_types->chan_alertbox; + text = await(alertbox->filter_bad_words(text, "replace")); + string tts = await(alertbox->text_to_speech(text, msg->voice || "en-GB/en-GB-Standard-A/FEMALE", "tts_hack")); + return (["cmd": "speak", "text": text, "tts": tts]); +} + +protected void create(string name) {::create(name);}