@@ -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