Skip to content

Commit dc7835d

Browse files
committed
ЭТО ТОЖЕ ОКЕЙ?
1 parent 75765e1 commit dc7835d

2 files changed

Lines changed: 162 additions & 56 deletions

File tree

  • code
    • controllers/subsystem
    • modules/client/preferences/middleware

code/controllers/subsystem/tts.dm

Lines changed: 159 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ SUBSYSTEM_DEF(tts)
3232
var/tts_enabled = FALSE
3333
/// Whether the TTS engine supports pitch adjustment or not.
3434
var/pitch_enabled = FALSE
35+
// MM EDIT MNE POHUY
36+
/// HELLO VALTOS, IT'S TTSensky WE NEED 5 BILLION REQUESTS
37+
var/legacy_api = FALSE
38+
// MM EDIT
3539

3640
/// TTS messages won't play if requests took longer than this duration of time.
3741
var/message_timeout = 7 SECONDS
@@ -61,30 +65,90 @@ SUBSYSTEM_DEF(tts)
6165
/proc/cmp_word_length_asc(datum/tts_request/a, datum/tts_request/b)
6266
return length(b.message) - length(a.message)
6367

68+
/datum/controller/subsystem/tts/proc/parse_speakers(response_body, source_endpoint = "unknown")
69+
var/list/speakers = list()
70+
var/decoded = safe_json_decode(response_body)
71+
if(!islist(decoded))
72+
var/body_preview = istext(response_body) ? copytext(response_body, 1, 161) : "<non-text body>"
73+
log_tts("TTS voices response was not valid JSON", list(
74+
"endpoint" = source_endpoint,
75+
"body_preview" = body_preview
76+
))
77+
return speakers
78+
79+
var/list/legacy_voices = decoded["voices"]
80+
if(islist(legacy_voices))
81+
for(var/list/voice_data in legacy_voices)
82+
if(!islist(voice_data))
83+
continue
84+
var/list/voice_speakers = voice_data["speakers"]
85+
if(!islist(voice_speakers) || !length(voice_speakers))
86+
continue
87+
var/speaker_name = voice_speakers[1]
88+
if(istext(speaker_name))
89+
speakers += speaker_name
90+
return speakers
91+
92+
for(var/speaker_index in 1 to length(decoded))
93+
var/speaker_name = decoded[speaker_index]
94+
if(istext(speaker_name))
95+
speakers += speaker_name
96+
97+
return speakers
98+
6499
/// Establishes (or re-establishes) a connection to the TTS server and updates the list of available speakers.
65100
/// This is blocking, so be careful when calling.
66101
/datum/controller/subsystem/tts/proc/establish_connection_to_tts()
67-
var/datum/http_request/request = new()
68102
var/list/headers = list()
69103
headers["Authorization"] = CONFIG_GET(string/tts_http_token)
70-
//MASSMETA EDIT BEGIN (/n/tts)
71-
//request.prepare(RUSTG_HTTP_METHOD_GET, "[CONFIG_GET(string/tts_http_url)]/tts-voices", "", headers, timeout_seconds = CONFIG_GET(number/tts_http_timeout_seconds))
72-
73-
request.prepare(RUSTG_HTTP_METHOD_GET, "[CONFIG_GET(string/tts_http_url)]/speakers", "", headers, timeout_seconds = CONFIG_GET(number/tts_http_timeout_seconds))
74-
//MASSMETA EDIT END
75-
request.begin_async()
76-
UNTIL(request.is_complete())
77-
var/datum/http_response/response = request.into_response()
78-
if(response.errored || response.status_code != 200)
79-
stack_trace(response.error)
104+
available_speakers = list()
105+
legacy_api = FALSE
106+
var/list/speaker_endpoints = list("tts-voices", "speakers")
107+
var/datum/http_response/last_response
108+
for(var/endpoint in speaker_endpoints)
109+
var/datum/http_request/request = new()
110+
request.prepare(RUSTG_HTTP_METHOD_GET, "[CONFIG_GET(string/tts_http_url)]/[endpoint]", "", headers, timeout_seconds = CONFIG_GET(number/tts_http_timeout_seconds))
111+
request.begin_async()
112+
UNTIL(request.is_complete())
113+
var/datum/http_response/response = request.into_response()
114+
var/content_type = "<missing>"
115+
if(islist(response.headers))
116+
content_type = response.headers["content-type"] || response.headers["Content-Type"] || "<missing>"
117+
var/body_preview = istext(response.body) ? copytext(response.body, 1, 161) : "<non-text body>"
118+
log_tts("TTS voice endpoint response", list(
119+
"endpoint" = endpoint,
120+
"status_code" = response.status_code,
121+
"errored" = response.errored,
122+
"content_type" = content_type,
123+
"body_preview" = body_preview
124+
))
125+
last_response = response
126+
if(response.errored || response.status_code != 200)
127+
continue
128+
129+
available_speakers = parse_speakers(response.body, endpoint)
130+
if(length(available_speakers))
131+
legacy_api = (endpoint == "speakers")
132+
break
133+
134+
if(!length(available_speakers))
135+
if(last_response && last_response.errored)
136+
log_tts("Could not fetch TTS voices from configured endpoints", list(
137+
"url" = CONFIG_GET(string/tts_http_url),
138+
"error" = last_response.error
139+
))
140+
else
141+
var/last_status_code
142+
if(last_response)
143+
last_status_code = last_response.status_code
144+
var/fallback_preview = (last_response && istext(last_response.body)) ? copytext(last_response.body, 1, 161) : "<non-text body>"
145+
log_tts("Could not fetch TTS voices from configured endpoints", list(
146+
"url" = CONFIG_GET(string/tts_http_url),
147+
"status_code" = last_status_code,
148+
"body_preview" = fallback_preview
149+
))
80150
return FALSE
81-
//MASSMETA EDIT BEGIN (/n/tts)
82-
//available_speakers = json_decode(response.body)
83151

84-
var/list/temp_speakers = json_decode(response.body)?["voices"]
85-
for(var/speaker in temp_speakers)
86-
available_speakers.Add(speaker["speakers"][1])
87-
//MASSMETA EDIT END
88152
tts_enabled = TRUE
89153
if(CONFIG_GET(str_list/tts_voice_blacklist))
90154
var/list/blacklisted_voices = CONFIG_GET(str_list/tts_voice_blacklist)
@@ -111,7 +175,7 @@ SUBSYSTEM_DEF(tts)
111175
var/datum/http_response/response_pitch = request_pitch.into_response()
112176
if(response_pitch.errored || response_pitch.status_code != 200)
113177
if(response_pitch.errored)
114-
stack_trace(response.error)
178+
stack_trace(response_pitch.error)
115179
pitch_enabled = FALSE
116180
rustg_file_write(json_encode(available_speakers), "data/cached_tts_voices.json")
117181
rustg_file_write("rustg HTTP requests can't write to folders that don't exist, so we need to make it exist.", "tmp/tts/init.txt")
@@ -228,10 +292,13 @@ SUBSYSTEM_DEF(tts)
228292
tts_enabled = FALSE
229293
for(var/datum/tts_request/data in in_process_http_messages)
230294
var/datum/http_request/request = data.request
231-
var/datum/http_request/request_blips = data.request_blips
232-
var/datum/http_request/request_radio = data.request_radio
233-
var/datum/http_request/request_blips_radio = data.request_blips_radio
234-
UNTIL(request.is_complete() && request_blips.is_complete() && request_radio.is_complete() && request_blips_radio.is_complete())
295+
if(data.legacy_api)
296+
UNTIL(request.is_complete())
297+
else
298+
var/datum/http_request/request_blips = data.request_blips
299+
var/datum/http_request/request_radio = data.request_radio
300+
var/datum/http_request/request_blips_radio = data.request_blips_radio
301+
UNTIL(request.is_complete() && request_blips.is_complete() && request_radio.is_complete() && request_blips_radio.is_complete())
235302

236303
#define SHIFT_DATA_ARRAY(tts_message_queue, target, data) \
237304
popleft(##data); \
@@ -270,14 +337,18 @@ SUBSYSTEM_DEF(tts)
270337
average_tts_messages_time = MC_AVERAGE(average_tts_messages_time, world.time - current_request.start_time)
271338
var/identifier = current_request.identifier
272339
var/datum/http_response/normal_response = current_request.request.into_response()
273-
var/datum/http_response/blips_response = current_request.request_blips.into_response()
274-
var/datum/http_response/radio_response = current_request.request_radio.into_response()
275-
var/datum/http_response/radio_blips_response = current_request.request_blips_radio.into_response()
340+
var/datum/http_response/blips_response = normal_response
341+
var/datum/http_response/radio_response = normal_response
342+
var/datum/http_response/radio_blips_response = normal_response
343+
if(!current_request.legacy_api)
344+
blips_response = current_request.request_blips.into_response()
345+
radio_response = current_request.request_radio.into_response()
346+
radio_blips_response = current_request.request_blips_radio.into_response()
276347
if(current_request.requests_errored())
277348
if(queued_radio_messages[identifier])
278349
queued_radio_messages.Remove(identifier)
279350
current_request.timed_out = TRUE
280-
log_tts("TTS HTTP request errored | Normal: [normal_response.error] | Blips: [blips_response.error] | Radio: [radio_response.error] | Radio Blips: [radio_blips_response.error]", list(
351+
log_tts("TTS HTTP request errored | Normal: [normal_response.status_code] [normal_response.error] | Blips: [blips_response.status_code] [blips_response.error] | Radio: [radio_response.status_code] [radio_response.error] | Radio Blips: [radio_blips_response.status_code] [radio_blips_response.error]", list(
281352
"normal" = normal_response,
282353
"blips" = blips_response,
283354
"radio" = radio_response,
@@ -288,25 +359,39 @@ SUBSYSTEM_DEF(tts)
288359
current_request.audio_length = text2num(normal_response.headers["audio-length"]) * 10
289360
if(!current_request.audio_length)
290361
current_request.audio_length = 0
291-
if(length(blips_response.headers) && blips_response.headers.Find("audio-length"))
292-
current_request.audio_length_blips = text2num(blips_response.headers["audio-length"]) * 10
293-
if(!current_request.audio_length_blips)
294-
current_request.audio_length_blips = 0
295-
if(length(radio_response.headers) && radio_response.headers.Find("audio-length"))
296-
current_request.audio_length_radio = text2num(radio_response.headers["audio-length"]) * 10
297-
if(!current_request.audio_length_radio)
298-
current_request.audio_length_radio = 0
299-
if(length(radio_blips_response.headers) && radio_blips_response.headers.Find("audio-length"))
300-
current_request.audio_length_blips_radio = text2num(radio_blips_response.headers["audio-length"]) * 10
301-
if(!current_request.audio_length_blips_radio)
302-
current_request.audio_length_blips_radio = 0
362+
if(current_request.legacy_api)
363+
current_request.audio_length_blips = current_request.audio_length
364+
current_request.audio_length_radio = current_request.audio_length
365+
current_request.audio_length_blips_radio = current_request.audio_length
366+
else
367+
if(length(blips_response.headers) && blips_response.headers.Find("audio-length"))
368+
current_request.audio_length_blips = text2num(blips_response.headers["audio-length"]) * 10
369+
if(!current_request.audio_length_blips)
370+
current_request.audio_length_blips = 0
371+
if(length(radio_response.headers) && radio_response.headers.Find("audio-length"))
372+
current_request.audio_length_radio = text2num(radio_response.headers["audio-length"]) * 10
373+
if(!current_request.audio_length_radio)
374+
current_request.audio_length_radio = 0
375+
if(length(radio_blips_response.headers) && radio_blips_response.headers.Find("audio-length"))
376+
current_request.audio_length_blips_radio = text2num(radio_blips_response.headers["audio-length"]) * 10
377+
if(!current_request.audio_length_blips_radio)
378+
current_request.audio_length_blips_radio = 0
303379
current_request.audio_file = "tmp/tts/[identifier].ogg"
304-
current_request.audio_file_blips = "tmp/tts/[identifier]_blips.ogg" // We aren't as concerned about the audio length for blips as we are with actual speech
305-
current_request.audio_file_radio = "tmp/tts/[identifier]_radio.ogg"
306-
current_request.audio_file_blips_radio = "tmp/tts/[identifier]_blips_radio.ogg"
380+
if(current_request.legacy_api)
381+
current_request.audio_file_blips = current_request.audio_file
382+
current_request.audio_file_radio = current_request.audio_file
383+
current_request.audio_file_blips_radio = current_request.audio_file
384+
if(queued_radio_messages[identifier])
385+
queued_radio_messages.Remove(identifier)
386+
else
387+
current_request.audio_file_blips = "tmp/tts/[identifier]_blips.ogg" // We aren't as concerned about the audio length for blips as we are with actual speech
388+
current_request.audio_file_radio = "tmp/tts/[identifier]_radio.ogg"
389+
current_request.audio_file_blips_radio = "tmp/tts/[identifier]_blips_radio.ogg"
307390
// Don't need the request anymore so we can deallocate it
308391
current_request.request = null
309392
current_request.request_blips = null
393+
current_request.request_radio = null
394+
current_request.request_blips_radio = null
310395
if(MC_TICK_CHECK)
311396
return
312397

@@ -415,7 +500,7 @@ SUBSYSTEM_DEF(tts)
415500
if(!fexists("tmp/tts/init.txt"))
416501
rustg_file_write("rustg HTTP requests can't write to folders that don't exist, so we need to make it exist.", "tmp/tts/init.txt")
417502

418-
var/static/regex/contains_alphanumeric = regex("\[a-zA-Z0-9]")
503+
var/static/regex/contains_alphanumeric = regex("\[а-яА-ЯёЁa-zA-Z0-9]")
419504
// If there is no alphanumeric char, the output will usually be static, so
420505
// don't bother sending
421506
if(contains_alphanumeric.Find(message) == 0)
@@ -429,18 +514,24 @@ SUBSYSTEM_DEF(tts)
429514
headers["Content-Type"] = "application/json"
430515
headers["Authorization"] = CONFIG_GET(string/tts_http_token)
431516
var/datum/http_request/request = new()
432-
var/datum/http_request/request_blips = new()
433-
var/datum/http_request/request_radio = new()
434-
var/datum/http_request/request_blips_radio = new()
517+
var/datum/http_request/request_blips
518+
var/datum/http_request/request_radio
519+
var/datum/http_request/request_blips_radio
435520
var/file_name = "tmp/tts/[identifier].ogg"
436521
var/file_name_blips = "tmp/tts/[identifier]_blips.ogg"
437522
var/file_name_radio = "tmp/tts/[identifier]_radio.ogg"
438523
var/file_name_blips_radio = "tmp/tts/[identifier]_blips_radio.ogg"
439-
request.prepare(RUSTG_HTTP_METHOD_GET, "[CONFIG_GET(string/tts_http_url)]/tts?voice=[speaker]&identifier=[identifier]&filter=[tts_filter_encode(filter, speaker, pitch)]&pitch=[pitch]&special_filters=[url_encode(special_filters)]", json_encode(list("text" = shell_scrubbed_input)), headers, file_name, timeout_seconds = CONFIG_GET(number/tts_http_timeout_seconds))
440-
request_blips.prepare(RUSTG_HTTP_METHOD_GET, "[CONFIG_GET(string/tts_http_url)]/tts-blips?voice=[speaker]&identifier=[identifier]&filter=[tts_filter_encode(filter, speaker, pitch, blips = TRUE)]&pitch=[pitch]&special_filters=[url_encode(special_filters)]&blip_base=[blip_base]&blip_number=[blip_number]", json_encode(list("text" = shell_scrubbed_input)), headers, file_name_blips, timeout_seconds = CONFIG_GET(number/tts_http_timeout_seconds))
441-
request_radio.prepare(RUSTG_HTTP_METHOD_GET, "[CONFIG_GET(string/tts_http_url)]/tts-radio?voice=[speaker]&identifier=[identifier]&filter=[tts_filter_encode(filter, speaker, pitch)]&pitch=[pitch]&special_filters=[url_encode(special_filters)]", json_encode(list("text" = shell_scrubbed_input)), headers, file_name_radio, timeout_seconds = CONFIG_GET(number/tts_http_timeout_seconds))
442-
request_blips_radio.prepare(RUSTG_HTTP_METHOD_GET, "[CONFIG_GET(string/tts_http_url)]/tts-blips-radio?voice=[speaker]&identifier=[identifier]&filter=[tts_filter_encode(filter, speaker, pitch, blips = TRUE)]&pitch=[pitch]&special_filters=[url_encode(special_filters)]&blip_base=[blip_base]&blip_number=[blip_number]", json_encode(list("text" = shell_scrubbed_input)), headers, file_name_blips_radio, timeout_seconds = CONFIG_GET(number/tts_http_timeout_seconds))
443-
var/datum/tts_request/current_request = new /datum/tts_request(identifier, request, request_blips, request_radio, request_blips_radio, shell_scrubbed_input, target, local, language, message_range, volume_offset, listeners, pitch, force_blips)
524+
if(legacy_api)
525+
request.prepare(RUSTG_HTTP_METHOD_GET, "[CONFIG_GET(string/tts_http_url)]?text=[url_encode(shell_scrubbed_input)]&speaker=[speaker]&ext=ogg", "", headers, file_name, timeout_seconds = CONFIG_GET(number/tts_http_timeout_seconds))
526+
else
527+
request_blips = new()
528+
request_radio = new()
529+
request_blips_radio = new()
530+
request.prepare(RUSTG_HTTP_METHOD_GET, "[CONFIG_GET(string/tts_http_url)]/tts?voice=[speaker]&identifier=[identifier]&filter=[tts_filter_encode(filter, speaker, pitch)]&pitch=[pitch]&special_filters=[url_encode(special_filters)]", json_encode(list("text" = shell_scrubbed_input)), headers, file_name, timeout_seconds = CONFIG_GET(number/tts_http_timeout_seconds))
531+
request_blips.prepare(RUSTG_HTTP_METHOD_GET, "[CONFIG_GET(string/tts_http_url)]/tts-blips?voice=[speaker]&identifier=[identifier]&filter=[tts_filter_encode(filter, speaker, pitch, blips = TRUE)]&pitch=[pitch]&special_filters=[url_encode(special_filters)]&blip_base=[blip_base]&blip_number=[blip_number]", json_encode(list("text" = shell_scrubbed_input)), headers, file_name_blips, timeout_seconds = CONFIG_GET(number/tts_http_timeout_seconds))
532+
request_radio.prepare(RUSTG_HTTP_METHOD_GET, "[CONFIG_GET(string/tts_http_url)]/tts-radio?voice=[speaker]&identifier=[identifier]&filter=[tts_filter_encode(filter, speaker, pitch)]&pitch=[pitch]&special_filters=[url_encode(special_filters)]", json_encode(list("text" = shell_scrubbed_input)), headers, file_name_radio, timeout_seconds = CONFIG_GET(number/tts_http_timeout_seconds))
533+
request_blips_radio.prepare(RUSTG_HTTP_METHOD_GET, "[CONFIG_GET(string/tts_http_url)]/tts-blips-radio?voice=[speaker]&identifier=[identifier]&filter=[tts_filter_encode(filter, speaker, pitch, blips = TRUE)]&pitch=[pitch]&special_filters=[url_encode(special_filters)]&blip_base=[blip_base]&blip_number=[blip_number]", json_encode(list("text" = shell_scrubbed_input)), headers, file_name_blips_radio, timeout_seconds = CONFIG_GET(number/tts_http_timeout_seconds))
534+
var/datum/tts_request/current_request = new /datum/tts_request(identifier, request, request_blips, request_radio, request_blips_radio, shell_scrubbed_input, target, local, language, message_range, volume_offset, listeners, pitch, force_blips, legacy_api)
444535
var/list/player_queued_tts_messages = queued_tts_messages[target]
445536
if(!player_queued_tts_messages)
446537
player_queued_tts_messages = list()
@@ -523,9 +614,11 @@ SUBSYSTEM_DEF(tts)
523614
var/pitch = 0
524615
/// Should we force play blips? Used for the blips preview.
525616
var/force_blips = FALSE
617+
/// Whether this request uses the legacy ntts endpoint.
618+
var/legacy_api = FALSE
526619

527620

528-
/datum/tts_request/New(identifier, datum/http_request/request, datum/http_request/request_blips, datum/http_request/request_radio, datum/http_request/request_blips_radio, message, target, local, datum/language/language, message_range, volume_offset, list/listeners, pitch, force_blips = FALSE)
621+
/datum/tts_request/New(identifier, datum/http_request/request, datum/http_request/request_blips, datum/http_request/request_radio, datum/http_request/request_blips_radio, message, target, local, datum/language/language, message_range, volume_offset, list/listeners, pitch, force_blips = FALSE, legacy_api = FALSE)
529622
. = ..()
530623
src.identifier = identifier
531624
src.request = request
@@ -541,6 +634,7 @@ SUBSYSTEM_DEF(tts)
541634
src.listeners = listeners
542635
src.pitch = pitch
543636
src.force_blips = force_blips
637+
src.legacy_api = legacy_api
544638
start_time = world.time
545639

546640
/datum/tts_request/proc/start_requests()
@@ -549,6 +643,9 @@ SUBSYSTEM_DEF(tts)
549643
use_blips = (current_client?.prefs.read_preference(/datum/preference/choiced/sound_tts) == TTS_SOUND_BLIPS)
550644
else if(istype(target, /mob))
551645
use_blips = (target.client?.prefs.read_preference(/datum/preference/choiced/sound_tts) == TTS_SOUND_BLIPS)
646+
if(legacy_api)
647+
request.begin_async()
648+
return
552649
if(local)
553650
if(use_blips || force_blips)
554651
request_blips.begin_async()
@@ -561,6 +658,8 @@ SUBSYSTEM_DEF(tts)
561658
request_blips_radio.begin_async()
562659

563660
/datum/tts_request/proc/get_primary_request()
661+
if(legacy_api)
662+
return request
564663
if(local)
565664
if(use_blips || force_blips)
566665
return request_blips
@@ -570,6 +669,8 @@ SUBSYSTEM_DEF(tts)
570669
return request
571670

572671
/datum/tts_request/proc/get_primary_response()
672+
if(legacy_api)
673+
return request.into_response()
573674
if(local)
574675
if(use_blips || force_blips)
575676
return request_blips.into_response()
@@ -579,21 +680,26 @@ SUBSYSTEM_DEF(tts)
579680
return request.into_response()
580681

581682
/datum/tts_request/proc/requests_errored()
683+
if(legacy_api)
684+
var/datum/http_response/response = request.into_response()
685+
return response.errored || response.status_code != 200
582686
if(local)
583687
var/datum/http_response/response
584688
if(use_blips || force_blips)
585689
response = request_blips.into_response()
586690
else
587691
response = request.into_response()
588-
return response.errored
692+
return response.errored || response.status_code != 200
589693
else
590694
var/datum/http_response/response = request.into_response()
591695
var/datum/http_response/response_blips = request_blips.into_response()
592696
var/datum/http_response/response_radio = request_radio.into_response()
593697
var/datum/http_response/response_blips_radio = request_blips_radio.into_response()
594-
return response.errored || response_blips.errored || response_radio.errored || response_blips_radio.errored
698+
return response.errored || response.status_code != 200 || response_blips.errored || response_blips.status_code != 200 || response_radio.errored || response_radio.status_code != 200 || response_blips_radio.errored || response_blips_radio.status_code != 200
595699

596700
/datum/tts_request/proc/requests_completed()
701+
if(legacy_api)
702+
return request.is_complete()
597703
if(local)
598704
if(use_blips || force_blips)
599705
return request_blips.is_complete()

0 commit comments

Comments
 (0)