Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allows MP3 files to be uploaded to the TGchat player - renames play internet sound #28575

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion code/modules/admin/admin_verbs.dm
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ GLOBAL_LIST_INIT(admin_verbs_sounds, list(
/client/proc/play_intercomm_sound,
/client/proc/stop_global_admin_sounds,
/client/proc/stop_sounds_global,
/client/proc/play_web_sound
/client/proc/play_sound_tgchat
))
GLOBAL_LIST_INIT(admin_verbs_event, list(
/client/proc/object_talk,
Expand Down
206 changes: 117 additions & 89 deletions code/modules/admin/verbs/playsound.dm
Original file line number Diff line number Diff line change
Expand Up @@ -130,107 +130,135 @@ GLOBAL_LIST_EMPTY(sounds_cache)
var/client/C = M.client
C?.tgui_panel?.stop_music()

/client/proc/play_web_sound()
/client/proc/play_sound_tgchat()
set category = "Event"
set name = "Play Internet Sound"
set name = "Play Global Sound TGchat"
if(!check_rights(R_SOUNDS))
return

if(!GLOB.configuration.system.ytdlp_url)
to_chat(src, "<span class='boldwarning'>yt-dlp was not configured, action unavailable</span>") //Check config
var/sound_mode = tgui_alert(src, "Play a sound from which source?", "Select Source", list("Web", "Upload MP3"))
if(!sound_mode)
return

var/web_sound_input
var/asset_name
var/must_send_assets = FALSE
var/web_sound_url = ""
var/list/music_extra_data = list()
var/list/data = list()

var/web_sound_input = tgui_input_text(src, "Enter content URL (supported sites only, leave blank to stop playing)", "Play Internet Sound", null)
if(istext(web_sound_input))
var/web_sound_url = ""
var/stop_web_sounds = FALSE
var/list/music_extra_data = list()
if(length(web_sound_input))
web_sound_input = trim(web_sound_input)
if(findtext(web_sound_input, ":") && !findtext(web_sound_input, GLOB.is_http_protocol))
to_chat(src, "<span class='boldwarning'>Non-http(s) URIs are not allowed.</span>")
to_chat(src, "<span class='warning'>For yt-dlp shortcuts like ytsearch: please use the appropriate full url from the website.</span>")
if(sound_mode == "Web")
if(!GLOB.configuration.system.ytdlp_url)
to_chat(src, "<span class='boldwarning'>yt-dlp was not configured, action unavailable</span>") //Check config
return

web_sound_input = tgui_input_text(src, "Enter content URL", "Play Internet Sound", null)
if(!length(web_sound_input))
return

web_sound_input = trim(web_sound_input)

if(findtext(web_sound_input, ":") && !findtext(web_sound_input, GLOB.is_http_protocol))
to_chat(src, "<span class='boldwarning'>Non-http(s) URIs are not allowed.</span>")
to_chat(src, "<span class='warning'>For yt-dlp shortcuts like ytsearch: please use the appropriate full url from the website.</span>")
return

// Prepare the body
var/list/request_body = list("url" = web_sound_input)
// Send the request off
var/datum/http_request/media_poll_request = new()
// The fact we are using GET with a body offends me
media_poll_request.prepare(RUSTG_HTTP_METHOD_GET, GLOB.configuration.system.ytdlp_url, json_encode(request_body))
// Start it off and wait
media_poll_request.begin_async()
UNTIL(media_poll_request.is_complete())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As a complete noob, what will happen if we newer get an answer from server? Will we wait forever or will we fall into catch?

Copy link
Contributor Author

@Bm0n Bm0n Mar 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The web side of the code is mostly done by Affected and is unchanged from play internet sound

It'll runtime on into_response and give you back a yt-dlp URL retrieval FAILED error.
I think the only situation where this would happen is if the config is set and the ytdlp server is down... which shouldn't happen because the ytdlp server is hosted on the main server

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good to know. Than i feel like the rest of the logic will work fine.

var/datum/http_response/media_poll_response = media_poll_request.into_response()

if(media_poll_response.status_code == 200)
try
data = json_decode(media_poll_response.body)
catch(var/exception/e)
to_chat(src, "<span class='boldwarning'>yt-dlp JSON parsing FAILED:</span>")
to_chat(src, "<span class='warning'>[e]: [media_poll_response.body]</span>")
return
else
to_chat(src, "<span class='boldwarning'>yt-dlp URL retrieval FAILED:</span>")
to_chat(src, "<span class='warning'>[media_poll_response.body]</span>")
return

else if(sound_mode == "Upload MP3")
if(GLOB.configuration.asset_cache.asset_transport == "simple")
if(tgui_alert(src, "WARNING: Your server is using simple asset transport. Sounds will have to be sent directly to players, which may freeze the game for long durations. Are you SURE?", "Really play direct sound?", list("Yes", "No")) != "Yes")
return
must_send_assets = TRUE

// Prepare the body
var/list/request_body = list("url" = web_sound_input)
// Send the request off
var/datum/http_request/media_poll_request = new()
// The fact we are using GET with a body offends me
media_poll_request.prepare(RUSTG_HTTP_METHOD_GET, GLOB.configuration.system.ytdlp_url, json_encode(request_body))
// Start it off and wait
media_poll_request.begin_async()
UNTIL(media_poll_request.is_complete())
var/datum/http_response/media_poll_response = media_poll_request.into_response()

if(media_poll_response.status_code == 200)
var/list/data
try
data = json_decode(media_poll_response.body)
catch(var/exception/e)
to_chat(src, "<span class='boldwarning'>yt-dlp JSON parsing FAILED:</span>")
to_chat(src, "<span class='warning'>[e]: [media_poll_response.body]</span>")
return

if(data["sound_url"])
web_sound_url = data["sound_url"]
var/title = "[data["title"]]"
var/webpage_url = title
if(data["webpage_url"])
webpage_url = "<a href=\"[data["webpage_url"]]\">[title]</a>"
music_extra_data["start"] = data["start"]
music_extra_data["end"] = data["end"]
music_extra_data["link"] = data["webpage_url"]
music_extra_data["title"] = data["title"]

var/res = tgui_alert(src, "Show the title of and link to this song to the players?\n[title]", "Show Info?", list("Yes", "No", "Cancel"))
switch(res)
if("Yes")
log_admin("[key_name(src)] played web sound: [web_sound_input]")
message_admins("[key_name(src)] played web sound: [web_sound_input]")
to_chat(world, "<span class='boldannounceooc'>[src.ckey] played: [webpage_url]</span>")
if("No")
music_extra_data["link"] = "Song Link Hidden"
music_extra_data["title"] = "Song Title Hidden"
music_extra_data["artist"] = "Song Artist Hidden"
log_admin("[key_name(src)] played web sound: [web_sound_input]")
message_admins("[key_name(src)] played web sound: [web_sound_input]")
to_chat(world, "<span class='boldannounceooc'>[src.ckey] played an internet sound</span>")
if("Cancel")
return

SSblackbox.record_feedback("tally", "admin_verb", 1, "Play Internet Sound")
var/soundfile = input(src, "Choose an MP3 file to play", "Upload Sound") as null|file
if(!soundfile)
return

else
to_chat(src, "<span class='boldwarning'>yt-dlp URL retrieval FAILED:</span>")
to_chat(src, "<span class='warning'>[media_poll_response.body]</span>")

else //pressed ok with blank
log_admin("[key_name(src)] stopped web sound")
message_admins("[key_name(src)] stopped web sound")
web_sound_url = null
stop_web_sounds = TRUE

if(web_sound_url && !findtext(web_sound_url, GLOB.is_http_protocol))
to_chat(src, "<span class='boldwarning'>BLOCKED: Content URL not using http(s) protocol</span>", confidential = TRUE)
to_chat(src, "<span class='warning'>The media provider returned a content URL that isn't using the HTTP or HTTPS protocol</span>", confidential = TRUE)
var/static/regex/only_extension = regex(@{"^.*\.([a-z0-9]{1,5})$"}, "gi")
var/extension = only_extension.Replace("[soundfile]", "$1")
if(!length(extension) || extension != "mp3")
to_chat(src, "<span class='boldwarning'>Invalid filename extension.</span>")
return

if(web_sound_url || stop_web_sounds)
for(var/mob/M in GLOB.player_list)
var/client/C = M.client
var/this_uid = M.client.UID()
if(stop_web_sounds)
C.tgui_panel?.stop_music()
var/static/playsound_notch = 1
asset_name = "admin_sound_[playsound_notch++].[extension]"
SSassets.transport.register_asset(asset_name, soundfile)
log_admin("[key_name_admin(src)] uploaded admin sound '[soundfile]' to asset transport.")
message_admins("[key_name_admin(src)] uploaded admin sound '[soundfile]' to asset transport.")

var/static/regex/remove_extension = regex(@{"\.[a-z0-9]+$"}, "gi")
data["title"] = remove_extension.Replace("[soundfile]", "")
data["sound_url"] = SSassets.transport.get_asset_url(asset_name)
web_sound_input = "[soundfile]"

if(data["sound_url"])
web_sound_url = data["sound_url"]
var/title = "[data["title"]]"
var/webpage_url = title
if(data["webpage_url"])
webpage_url = "<a href=\"[data["webpage_url"]]\">[title]</a>"
music_extra_data["start"] = data["start"]
music_extra_data["end"] = data["end"]
music_extra_data["link"] = data["webpage_url"]
music_extra_data["title"] = data["title"]

var/res = tgui_alert(src, "Show the title of and link to this song to the players?\n[title]", "Show Info?", list("Yes", "No"))
if(!res)
return
if(res == "Yes")
log_admin("[key_name(src)] played sound: [web_sound_input]")
message_admins("[key_name(src)] played sound: [web_sound_input]")
to_chat(world, "<span class='boldannounceooc'>[src.ckey] played: [webpage_url]</span>")
else if(res == "No")
music_extra_data["link"] = "Song Link Hidden"
music_extra_data["title"] = "Song Title Hidden"
music_extra_data["artist"] = "Song Artist Hidden"
log_admin("[key_name(src)] played sound: [web_sound_input]")
message_admins("[key_name(src)] played sound: [web_sound_input]")
to_chat(world, "<span class='boldannounceooc'>[src.ckey] played a sound</span>")

SSblackbox.record_feedback("tally", "admin_verb", 1, "Play Global Sound TGchat")

if(!must_send_assets && web_sound_url && !findtext(web_sound_url, GLOB.is_http_protocol))
to_chat(src, "<span class='boldwarning'>BLOCKED: Content URL not using http(s) protocol</span>", confidential = TRUE)
to_chat(src, "<span class='warning'>The media provider returned a content URL that isn't using the HTTP or HTTPS protocol</span>", confidential = TRUE)
return

if(web_sound_url)
for(var/mob/M in GLOB.player_list)
var/client/C = M.client
var/player_uid = M.client.UID()
if(C.prefs.sound & SOUND_MIDI)
if(ckey in M.client.prefs.admin_sound_ckey_ignore)
to_chat(C, "<span class='warning'>But [src.ckey] is muted locally in preferences!</span>")
continue
if(C.prefs.sound & SOUND_MIDI)
if(ckey in M.client.prefs.admin_sound_ckey_ignore)
to_chat(C, "<span class='warning'>But [src.ckey] is muted locally in preferences!</span>")
continue
else
C.tgui_panel?.play_music(web_sound_url, music_extra_data)
to_chat(C, "<span class='warning'>(<a href='byond://?src=[this_uid];action=silenceSound'>SILENCE</a>) (<a href='byond://?src=[this_uid];action=muteAdmin&a=[ckey]'>ALWAYS SILENCE THIS ADMIN</a>)</span>")
else
to_chat(C, "<span class='warning'>But Admin MIDIs are disabled in preferences!</span>")
if(must_send_assets)
SSassets.transport.send_assets(C, asset_name)
C.tgui_panel?.play_music(web_sound_url, music_extra_data)
to_chat(C, "<span class='warning'>(<a href='byond://?src=[player_uid];action=silenceSound'>SILENCE</a>) (<a href='byond://?src=[player_uid];action=muteAdmin&a=[ckey]'>ALWAYS SILENCE THIS ADMIN</a>)</span>")
else
to_chat(C, "<span class='warning'>But Admin MIDIs are disabled in preferences!</span>")
return
2 changes: 0 additions & 2 deletions code/modules/tgui/tgui_panel/audio.dm
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,6 @@
/datum/tgui_panel/proc/play_music(url, extra_data)
if(!is_ready())
return
if(!findtext(url, GLOB.is_http_protocol))
return
var/list/payload = list()
if(length(extra_data) > 0)
for(var/key in extra_data)
Expand Down