Music Widget Modifications + Request Music Verb (#74170)

## About The Pull Request

This PR alters the Play Internet Sound, First off it modifies the Widget
To clean up some info on the widget to hide information when that
information is not available to be shown. Secondly it makes the URL
input prompt for Play Internet Sound to be a TGUI text input box, as
well as adds in a warning if a song being played is >10 minutes long,
and adds in a proc to play music with a supplied variable.

Secondly This PR adds in a new player facing VERB in the OOC tab called
`Request Internet Sound` functionally the verb is similar to Pray but it
grants admins the ability to play URL's directly from the chat or
Request Manager, where it will prompt the admin if they wish to play the
song.

<details>
<summary>Screenshots/Videos</summary>


![dreamseeker_PJ1PCCWxT3](https://user-images.githubusercontent.com/2568378/226795466-541def6e-d1cc-4481-b14a-21d2690c80b3.png)

<details>
<summary>Widget</summary>


![image](https://user-images.githubusercontent.com/2568378/226794671-ab1f6f3f-08e4-44f7-9569-634ff70e8462.png)

![image](https://user-images.githubusercontent.com/2568378/226794685-4f2e71bd-c3f9-4409-86f1-8b5be28bed41.png)

![image](https://user-images.githubusercontent.com/2568378/226794696-2725fadf-0066-4cd4-b975-e9e69f1ef4c9.png)
</details>

<details>
<summary>New Prompts</summary>


![tO6QsZdHfe](https://user-images.githubusercontent.com/2568378/226794891-ce2e6737-409d-479c-90f2-57d55fc89561.png)

![RZVwU417nX](https://user-images.githubusercontent.com/2568378/226794912-0261e374-a7fa-4864-b5b8-99821cff32a8.png)
</details>

<details>
<summary>Videos</summary>


https://user-images.githubusercontent.com/2568378/226794939-4ca018b3-bba5-4893-9301-6858b0d433b9.mp4


https://user-images.githubusercontent.com/2568378/226794783-ca750840-3149-489c-9239-00014ac4ca5c.mp4
</details>
</details>

## Why It's Good For The Game

This cleans up the UI for the Play Internet Sound so that things to hide
info when admins choose to hide it, or to not show it if that
information exists at all. As well as grants players a ability to
request music to be played via Admin Midi and sorts them with prayers
and allows admins to directly play URL's simultaneously cleaning up any
music requests made through prays as well as a more obvious way for
people to request music rather than them Ahelping for music

## Changelog

🆑
add: New VERB, Request Internet Sound, It is in the OOC tab and allows
you to request music from admins to play, by default only allows
bandcamp, youtube, and soundcloud links
fix: Fixes the Admin Midi Widget UI to only present info that is
available to players to be seen
admin: Play Internet Sound URL input is now TGUI
admin: Play Internet Sound warns you if a song length is >10 Minutes
admin: Added new mute type to mute internet sound requests from a player
config: Added thee new config options, LOG_INTERNET_REQUEST,
REQUEST_INTERNET_SOUND, REQUEST_INTERNET_ALLOWED
/🆑

---------

Co-authored-by: Aleksej Komarov <stylemistake@gmail.com>
This commit is contained in:
SomeRandomOwl
2023-03-29 19:04:41 -06:00
committed by GitHub
co-authored by Aleksej Komarov
parent 401372c088
commit b2f6058c92
14 changed files with 247 additions and 99 deletions
+10
View File
@@ -1748,3 +1748,13 @@
if(!paper_to_show)
return
paper_to_show.ui_interact(usr)
else if(href_list["play_internet"])
if(!check_rights(R_SOUND))
return
var/link_url = href_list["play_internet"]
if(!link_url)
return
web_sound(usr, link_url)
+3
View File
@@ -208,6 +208,9 @@
if(MUTE_DEADCHAT)
mute_string = "deadchat and DSAY"
feedback_string = "Deadchat"
if(MUTE_INTERNET_REQUEST)
mute_string = "internet sound requests"
feedback_string = "Internet Sound Requests"
if(MUTE_ALL)
mute_string = "everything"
feedback_string = "Everything"
+1
View File
@@ -84,6 +84,7 @@
body += "<A href='?_src_=holder;[HrefToken()];mute=[M.ckey];mute_type=[MUTE_OOC]'><font color='[(muted & MUTE_OOC)?"red":"blue"]'>OOC</font></a> | "
body += "<A href='?_src_=holder;[HrefToken()];mute=[M.ckey];mute_type=[MUTE_PRAY]'><font color='[(muted & MUTE_PRAY)?"red":"blue"]'>PRAY</font></a> | "
body += "<A href='?_src_=holder;[HrefToken()];mute=[M.ckey];mute_type=[MUTE_ADMINHELP]'><font color='[(muted & MUTE_ADMINHELP)?"red":"blue"]'>ADMINHELP</font></a> | "
body += "<A href='?_src_=holder;[HrefToken()];mute=[M.ckey];mute_type=[MUTE_INTERNET_REQUEST]'><font color='[(muted & MUTE_INTERNET_REQUEST)?"red":"blue"]'>WEBREQ</font></a> | "
body += "<A href='?_src_=holder;[HrefToken()];mute=[M.ckey];mute_type=[MUTE_DEADCHAT]'><font color='[(muted & MUTE_DEADCHAT)?"red":"blue"]'>DEADCHAT</font></a>\]"
body += "(<A href='?_src_=holder;[HrefToken()];mute=[M.ckey];mute_type=[MUTE_ALL]'><font color='[(muted & MUTE_ALL)?"red":"blue"]'>toggle all</font></a>)"
+104 -90
View File
@@ -70,6 +70,100 @@
SEND_SOUND(M, S)
SSblackbox.record_feedback("tally", "admin_verb", 1, "Play Direct Mob Sound") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
///Takes an input from either proc/play_web_sound or the request manager and runs it through youtube-dl and prompts the user before playing it to the server.
/proc/web_sound(mob/user, input)
if(!check_rights(R_SOUND))
return
var/ytdl = CONFIG_GET(string/invoke_youtubedl)
if(!ytdl)
to_chat(user, span_boldwarning("Youtube-dl was not configured, action unavailable"), confidential = TRUE) //Check config.txt for the INVOKE_YOUTUBEDL value
return
var/web_sound_url = ""
var/stop_web_sounds = FALSE
var/list/music_extra_data = list()
if(istext(input))
var/list/output = world.shelleo("[ytdl] --geo-bypass --format \"bestaudio\[ext=mp3]/best\[ext=mp4]\[height <= 360]/bestaudio\[ext=m4a]/bestaudio\[ext=aac]\" --dump-single-json --no-playlist -- \"[input]\"")
var/errorlevel = output[SHELLEO_ERRORLEVEL]
var/stdout = output[SHELLEO_STDOUT]
var/stderr = output[SHELLEO_STDERR]
if(errorlevel)
to_chat(user, span_boldwarning("Youtube-dl URL retrieval FAILED:"), confidential = TRUE)
to_chat(user, span_warning("[stderr]"), confidential = TRUE)
return
var/list/data
try
data = json_decode(stdout)
catch(var/exception/e)
to_chat(user, span_boldwarning("Youtube-dl JSON parsing FAILED:"), confidential = TRUE)
to_chat(user, span_warning("[e]: [stdout]"), confidential = TRUE)
return
if (data["url"])
web_sound_url = data["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["duration"] = DisplayTimeText(data["duration"] * 1 SECONDS)
music_extra_data["link"] = data["webpage_url"]
music_extra_data["artist"] = data["artist"]
music_extra_data["upload_date"] = data["upload_date"]
music_extra_data["album"] = data["album"]
var/duration = data["duration"] * 1 SECONDS
if (duration > 10 MINUTES)
if((tgui_alert(user, "This song is over 10 minutes long. Are you sure you want to play it?", "Length Warning!", list("No", "Yes", "Cancel")) != "Yes"))
return
var/res = tgui_alert(user, "Show the title of and link to this song to the players?\n[title]", "Show Info?", list("Yes", "No", "Cancel"))
switch(res)
if("Yes")
music_extra_data["title"] = data["title"]
if("No")
music_extra_data["link"] = "Song Link Hidden"
music_extra_data["title"] = "Song Title Hidden"
music_extra_data["artist"] = "Song Artist Hidden"
music_extra_data["upload_date"] = "Song Upload Date Hidden"
music_extra_data["album"] = "Song Album Hidden"
if("Cancel", null)
return
var/anon = tgui_alert(user, "Display who played the song?", "Credit Yourself?", list("Yes", "No", "Cancel"))
switch(anon)
if("Yes")
if(res == "Yes")
to_chat(world, span_boldannounce("[user] played: [webpage_url]"), confidential = TRUE)
else
to_chat(world, span_boldannounce("[user] played some music"), confidential = TRUE)
if("No")
if(res == "Yes")
to_chat(world, span_boldannounce("An admin played: [webpage_url]"), confidential = TRUE)
if("Cancel", null)
return
SSblackbox.record_feedback("nested tally", "played_url", 1, list("[user.ckey]", "[input]"))
log_admin("[key_name(user)] played web sound: [input]")
message_admins("[key_name(user)] played web sound: [input]")
else
//pressed ok with blank
log_admin("[key_name(user)] stopped web sounds.")
message_admins("[key_name(user)] stopped web sounds.")
web_sound_url = null
stop_web_sounds = TRUE
if(web_sound_url && !findtext(web_sound_url, GLOB.is_http_protocol))
tgui_alert(user, "The media provider returned a content URL that isn't using the HTTP or HTTPS protocol. This is a security risk and the sound will not be played.", "Security Risk", list("OK"))
to_chat(user, span_boldwarning("BLOCKED: Content URL not using HTTP(S) Protocol!"), confidential = TRUE)
return
if(web_sound_url || stop_web_sounds)
for(var/m in GLOB.player_list)
var/mob/M = m
var/client/C = M.client
if(C.prefs.read_preference(/datum/preference/toggle/sound_midi))
if(!stop_web_sounds)
C.tgui_panel?.play_music(web_sound_url, music_extra_data)
else
C.tgui_panel?.stop_music()
SSblackbox.record_feedback("tally", "admin_verb", 1, "Play Internet Sound")
/client/proc/play_web_sound()
set category = "Admin.Fun"
set name = "Play Internet Sound"
@@ -81,98 +175,18 @@
to_chat(src, span_boldwarning("Youtube-dl was not configured, action unavailable"), confidential = TRUE) //Check config.txt for the INVOKE_YOUTUBEDL value
return
var/web_sound_input = input("Enter content URL (supported sites only, leave blank to stop playing)", "Play Internet Sound via youtube-dl") as text|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))
var/web_sound_input = tgui_input_text(usr, "Enter content URL (supported sites only, leave blank to stop playing)", "Play Internet Sound", null)
web_sound_input = trim(web_sound_input)
if(findtext(web_sound_input, ":") && !findtext(web_sound_input, GLOB.is_http_protocol))
to_chat(src, span_boldwarning("Non-http(s) URIs are not allowed."), confidential = TRUE)
to_chat(src, span_warning("For youtube-dl shortcuts like ytsearch: please use the appropriate full url from the website."), confidential = TRUE)
return
var/shell_scrubbed_input = shell_url_scrub(web_sound_input)
var/list/output = world.shelleo("[ytdl] --geo-bypass --format \"bestaudio\[ext=mp3]/best\[ext=mp4]\[height <= 360]/bestaudio\[ext=m4a]/bestaudio\[ext=aac]\" --dump-single-json --no-playlist -- \"[shell_scrubbed_input]\"")
var/errorlevel = output[SHELLEO_ERRORLEVEL]
var/stdout = output[SHELLEO_STDOUT]
var/stderr = output[SHELLEO_STDERR]
if(!errorlevel)
var/list/data
try
data = json_decode(stdout)
catch(var/exception/e)
to_chat(src, span_boldwarning("Youtube-dl JSON parsing FAILED:"), confidential = TRUE)
to_chat(src, span_warning("[e]: [stdout]"), confidential = TRUE)
return
if (data["url"])
web_sound_url = data["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["duration"] = DisplayTimeText(data["duration"] * 1 SECONDS)
music_extra_data["link"] = data["webpage_url"]
music_extra_data["artist"] = data["artist"]
music_extra_data["upload_date"] = data["upload_date"]
music_extra_data["album"] = data["album"]
var/res = tgui_alert(usr, "Show the title of and link to this song to the players?\n[title]",, list("No", "Yes", "Cancel"))
switch(res)
if("Yes")
music_extra_data["title"] = data["title"]
if("No")
music_extra_data["link"] = "Song Link Hidden"
music_extra_data["title"] = "Song Title Hidden"
music_extra_data["artist"] = "Song Artist Hidden"
music_extra_data["upload_date"] = "Song Upload Date Hidden"
music_extra_data["album"] = "Song Album Hidden"
if("Cancel")
return
var/anon = tgui_alert(usr, "Display who played the song?", "Credit Yourself?", list("No", "Yes", "Cancel"))
switch(anon)
if("Yes")
if(res == "Yes")
to_chat(world, span_boldannounce("[src] played: [webpage_url]"), confidential = TRUE)
else
to_chat(world, span_boldannounce("[src] played some music"), confidential = TRUE)
if("No")
if(res == "Yes")
to_chat(world, span_boldannounce("An admin played: [webpage_url]"), confidential = TRUE)
if("Cancel")
return
SSblackbox.record_feedback("nested tally", "played_url", 1, list("[ckey]", "[web_sound_input]"))
log_admin("[key_name(src)] played web sound: [web_sound_input]")
message_admins("[key_name(src)] played web sound: [web_sound_input]")
else
to_chat(src, span_boldwarning("Youtube-dl URL retrieval FAILED:"), confidential = TRUE)
to_chat(src, span_warning("[stderr]"), confidential = TRUE)
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_boldwarning("BLOCKED: Content URL not using http(s) protocol"), confidential = TRUE)
to_chat(src, span_warning("The media provider returned a content URL that isn't using the HTTP or HTTPS protocol"), confidential = TRUE)
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_boldwarning("Non-http(s) URIs are not allowed."), confidential = TRUE)
to_chat(src, span_warning("For youtube-dl shortcuts like ytsearch: please use the appropriate full URL from the website."), confidential = TRUE)
return
if(web_sound_url || stop_web_sounds)
for(var/m in GLOB.player_list)
var/mob/M = m
var/client/C = M.client
if(C.prefs.read_preference(/datum/preference/toggle/sound_midi))
if(!stop_web_sounds)
C.tgui_panel?.play_music(web_sound_url, music_extra_data)
else
C.tgui_panel?.stop_music()
SSblackbox.record_feedback("tally", "admin_verb", 1, "Play Internet Sound")
var/shell_scrubbed_input = shell_url_scrub(web_sound_input)
web_sound(usr, shell_scrubbed_input)
else
web_sound(usr, null)
/client/proc/set_round_end_sound(S as sound)
set category = "Admin.Fun"
@@ -0,0 +1,39 @@
/mob/verb/request_internet_sound()
set category = "OOC"
set name = "Request Internet Sound"
if(GLOB.say_disabled) //This is here to try to identify lag problems
to_chat(usr, span_danger("Speech is currently admin-disabled."), confidential = TRUE)
return
if (!CONFIG_GET(flag/request_internet_sound))
to_chat(usr, span_danger("This server has disabled internet sound requests."), confidential = TRUE)
return
var/request_url = tgui_input_text(usr, "Please Input a URL", "Only certain sites are allowed, such as YouTube, SoundCloud, and Bandcamp.", "")
if(!request_url)
return
//regex filter
var/regex/allowed_regex = regex(replacetext(CONFIG_GET(string/request_internet_allowed), ",", "|"), "i")
if(!allowed_regex.Find(request_url))
to_chat(usr, span_danger("Invalid URL. Please use a URL from one of the following sites: [replacetext(CONFIG_GET(string/request_internet_allowed), "\\", "")]"), confidential = TRUE)
return
request_url = shell_url_scrub(request_url)
log_internet_request("[src.key]/([src.name]): [request_url]")
if(usr.client)
if(usr.client.prefs.muted & MUTE_INTERNET_REQUEST)
to_chat(usr, span_danger("You cannot request music at this time. (muted)."), confidential = TRUE)
return
if(src.client.handle_spam_prevention(request_url,MUTE_INTERNET_REQUEST))
return
GLOB.requests.music_request(usr.client, request_url)
to_chat(usr, span_info("You requested: \"[request_url]\" to be played."), confidential = TRUE)
request_url = span_adminnotice("<b><font color='cyan'>MUSIC REQUEST: </font>[ADMIN_FULLMONTY(src)] [ADMIN_SC(src)]:</b> [span_linkify(request_url)] [ADMIN_PLAY_INTERNET(request_url)]")
for(var/client/admin_client in GLOB.admins)
if(admin_client.prefs.chat_toggles & CHAT_PRAYER)
to_chat(admin_client, request_url, type = MESSAGE_TYPE_PRAYER, confidential = TRUE)
SSblackbox.record_feedback("tally", "music_request", 1, "Music Request") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!