diff --git a/code/__DEFINES/admin.dm b/code/__DEFINES/admin.dm index 7b6626411a1..cb97b5cdda5 100644 --- a/code/__DEFINES/admin.dm +++ b/code/__DEFINES/admin.dm @@ -142,10 +142,10 @@ GLOBAL_VAR_INIT(ghost_role_flags, (~0)) #define LIGHTNING_BOLT_DAMAGE 75 #define LIGHTNING_BOLT_ELECTROCUTION_ANIMATION_LENGTH 40 -/// for asay pings, this is the index in the return list for [/proc/check_admin_pings] that contains the message modified with underlines for the spotted names -#define ADMINSAY_PING_UNDERLINE_NAME_INDEX "!underlined_names" -/// for asay datum refs, this is the index in the return list for [/proc/check_memory_refs] that contains the message modified with underlines for the linked datums -#define ADMINSAY_LINK_DATUM_REF "!datum_ref" +/// for [/proc/check_asay_links], if there are any actionable refs in the asay message, this index in the return list contains the new message text to be printed +#define ASAY_LINK_NEW_MESSAGE_INDEX "!asay_new_message" +/// for [/proc/check_asay_links], if there are any admin pings in the asay message, this index in the return list contains a list of admins to ping +#define ASAY_LINK_PINGED_ADMINS_INDEX "!pinged_admins" /// When passed in as the duration for ban_panel, will make the ban default to permanent #define BAN_PANEL_PERMANENT "permanent" diff --git a/code/_globalvars/_regexes.dm b/code/_globalvars/_regexes.dm index 1902fed0d20..7e571576213 100644 --- a/code/_globalvars/_regexes.dm +++ b/code/_globalvars/_regexes.dm @@ -6,7 +6,6 @@ GLOBAL_DATUM_INIT(is_email, /regex, regex("\[a-z0-9_-]+@\[a-z0-9_-]+.\[a-z0-9_-] GLOBAL_DATUM_INIT(is_alphanumeric, /regex, regex("\[a-z0-9]+", "i")) GLOBAL_DATUM_INIT(is_punctuation, /regex, regex("\[.!?]+", "i")) GLOBAL_DATUM_INIT(is_color, /regex, regex("^#\[0-9a-fA-F]{6}$")) -GLOBAL_DATUM_INIT(is_memref, /regex, regex("0x\[0-9a-fA-F\]{7,8}")) //finds text strings recognized as links on discord. Mainly used to stop embedding. GLOBAL_DATUM_INIT(has_discord_embeddable_links, /regex, regex("(https?://\[^\\s|<\]{2,})")) diff --git a/code/modules/admin/verbs/adminhelp.dm b/code/modules/admin/verbs/adminhelp.dm index 11be561b9d8..30b8de8dcaa 100644 --- a/code/modules/admin/verbs/adminhelp.dm +++ b/code/modules/admin/verbs/adminhelp.dm @@ -977,68 +977,77 @@ GLOBAL_DATUM_INIT(admin_help_ui_handler, /datum/admin_help_ui_handler, new) return potential_hits /** - * Checks a given message to see if any of the words contain an active admin's ckey with an @ before it + * Checks a given message to see if any of the words are something we want to treat specially, as detailed below. * - * Returns nothing if no pings are found, otherwise returns an associative list with ckey -> client - * Also modifies msg to underline the pings, then stores them in the key [ADMINSAY_PING_UNDERLINE_NAME_INDEX] for returning + * There are 3 cases where a word is something we want to act on + * 1. Admin pings, like @adminckey. Pings the admin in question, text is not clickable + * 2. Datum refs, like @0x2001169 or @mob_23. Clicking on the link opens up the VV for that datum + * 3. Ticket refs, like #3. Displays the status and ahelper in the link, clicking on it brings up the ticket panel for it. + * Returns a list being used as a tuple. Index ASAY_LINK_NEW_MESSAGE_INDEX contains the new message text (with clickable links and such) + * while index ASAY_LINK_PINGED_ADMINS_INDEX contains a list of pinged admin clients, if there are any. * * Arguments: * * msg - the message being scanned */ -/proc/check_admin_pings(msg) - //explode the input msg into a list - var/list/msglist = splittext(msg, " ") - var/list/admins_to_ping = list() +/proc/check_asay_links(msg) + var/list/msglist = splittext(msg, " ") //explode the input msg into a list + var/list/pinged_admins = list() // if we ping any admins, store them here so we can ping them after + var/modified = FALSE // did we find anything? var/i = 0 for(var/word in msglist) i++ if(!length(word)) continue - if(word[1] != "@") - continue - var/ckey_check = lowertext(copytext(word, 2)) - var/client/client_check = GLOB.directory[ckey_check] - if(client_check?.holder) - msglist[i] = "[word]" - admins_to_ping[ckey_check] = client_check - if(length(admins_to_ping)) - admins_to_ping[ADMINSAY_PING_UNDERLINE_NAME_INDEX] = jointext(msglist, " ") // without tuples, we must make do! - return admins_to_ping + switch(word[1]) + if("@") + var/stripped_word = ckey(copytext(word, 2)) -/** - * Checks a given message to see if any of the words contain a memory ref for a datum. Said ref should not have brackets around it - * - * Returns nothing if no refs are found, otherwise returns an associative list with ckey -> client - * Also modifies msg to underline and linkify the [ref] so other admins can click on the address to open the VV entry for said datum - * - * Arguments: - * * msg - the message being scanned - */ -/proc/check_memory_refs(msg) - if(!findtext(msg, GLOB.is_memref)) - return + // first we check if it's a ckey of an admin + var/client/client_check = GLOB.directory[stripped_word] + if(client_check?.holder) + msglist[i] = "[word]" + pinged_admins[stripped_word] = client_check + modified = TRUE + continue - //explode the input msg into a list - var/list/msglist = splittext(msg, " ") - var/list/datums_to_ref = list() + // then if not, we check if it's a datum ref - var/i = 0 - for(var/word in msglist) - i++ - if(!length(word)) - continue - var/word_with_brackets = "\[[word]\]" // the actual memory address lookups need the bracket wraps - var/datum/check_datum = locate(word_with_brackets) - if(!istype(check_datum)) - continue - msglist[i] = "[word_with_brackets]" - datums_to_ref[word] = word + var/word_with_brackets = "\[[stripped_word]\]" // the actual memory address lookups need the bracket wraps + var/datum/datum_check = locate(word_with_brackets) + if(!istype(datum_check)) + continue + msglist[i] = "[word]" + modified = TRUE + + if("#") // check if we're linking a ticket + var/possible_ticket_id = text2num(copytext(word, 2)) + if(!possible_ticket_id) + continue + + var/datum/admin_help/ahelp_check = GLOB.ahelp_tickets?.TicketByID(possible_ticket_id) + if(!ahelp_check) + continue + + var/state_word + switch(ahelp_check.state) + if(AHELP_ACTIVE) + state_word = "Active" + if(AHELP_CLOSED) + state_word = "Closed" + if(AHELP_RESOLVED) + state_word = "Resolved" + + msglist[i]= "[word] ([state_word] | [ahelp_check.initiator_key_name])" + modified = TRUE + + if(modified) + var/list/return_list = list() + return_list[ASAY_LINK_NEW_MESSAGE_INDEX] = jointext(msglist, " ") // without tuples, we must make do! + return_list[ASAY_LINK_PINGED_ADMINS_INDEX] = pinged_admins + return return_list - if(length(datums_to_ref)) - datums_to_ref[ADMINSAY_LINK_DATUM_REF] = jointext(msglist, " ") // without tuples, we must make do! - return datums_to_ref #undef WEBHOOK_URGENT #undef WEBHOOK_NONE diff --git a/code/modules/admin/verbs/adminsay.dm b/code/modules/admin/verbs/adminsay.dm index f39358b2f34..3ff5c6802e6 100644 --- a/code/modules/admin/verbs/adminsay.dm +++ b/code/modules/admin/verbs/adminsay.dm @@ -9,23 +9,18 @@ if(!msg) return - var/list/pinged_admin_clients = check_admin_pings(msg) - if(length(pinged_admin_clients) && pinged_admin_clients[ADMINSAY_PING_UNDERLINE_NAME_INDEX]) - msg = pinged_admin_clients[ADMINSAY_PING_UNDERLINE_NAME_INDEX] - pinged_admin_clients -= ADMINSAY_PING_UNDERLINE_NAME_INDEX - - for(var/iter_ckey in pinged_admin_clients) - var/client/iter_admin_client = pinged_admin_clients[iter_ckey] - if(!iter_admin_client?.holder) - continue - window_flash(iter_admin_client) - SEND_SOUND(iter_admin_client.mob, sound('sound/misc/asay_ping.ogg')) - - - var/list/linked_datums = check_memory_refs(msg) - if(length(linked_datums) && linked_datums[ADMINSAY_LINK_DATUM_REF]) - msg = linked_datums[ADMINSAY_LINK_DATUM_REF] - linked_datums -= ADMINSAY_LINK_DATUM_REF + if(findtext(msg, "@") || findtext(msg, "#")) + var/list/link_results = check_asay_links(msg) + if(length(link_results)) + msg = link_results[ASAY_LINK_NEW_MESSAGE_INDEX] + link_results[ASAY_LINK_NEW_MESSAGE_INDEX] = null + var/list/pinged_admin_clients = link_results[ASAY_LINK_PINGED_ADMINS_INDEX] + for(var/iter_ckey in pinged_admin_clients) + var/client/iter_admin_client = pinged_admin_clients[iter_ckey] + if(!iter_admin_client?.holder) + continue + window_flash(iter_admin_client) + SEND_SOUND(iter_admin_client.mob, sound('sound/misc/asay_ping.ogg')) mob.log_talk(msg, LOG_ASAY) msg = keywords_lookup(msg) diff --git a/code/modules/admin/view_variables/view_variables.dm b/code/modules/admin/view_variables/view_variables.dm index 459316f18aa..830979e2f54 100644 --- a/code/modules/admin/view_variables/view_variables.dm +++ b/code/modules/admin/view_variables/view_variables.dm @@ -42,7 +42,7 @@ sprite_text = no_icon? "\[NO ICON\]" : "" var/list/header = islist(D)? list("/list") : D.vv_get_header() - var/ref_line = copytext(refid, 2, -1) // get rid of the brackets + var/ref_line = "@[copytext(refid, 2, -1)]" // get rid of the brackets, add a @ prefix for copy pasting in asay var/marked_line if(holder && holder.marked_datum && holder.marked_datum == D)