From 111cdf100e0e17662cea0a4d19e39cf46f9ad730 Mon Sep 17 00:00:00 2001
From: Ryll Ryll <3589655+Ryll-Ryll@users.noreply.github.com>
Date: Thu, 31 Mar 2022 21:54:43 -0400
Subject: [PATCH] Adds linking tickets in asay, referencing mob datums in asay,
improves asay ref code (#65634)
About The Pull Request
Continuing on the work started in #65154 and 61712, this PR expands what asay linking can be used for and improves the code for it. You can now link tickets in asay by saying #[ticket ID] like #1. This shows the ticket's status and who filed the ahelp. Might remove the ticket filer if it's not really useful.
This also fixes an oversight of mine with datum linking, with how mobs and certain other datums (armor datums, landmarks) don't follow the memory address format for their tag values. Datum linking now uses a @[tag] format, so you can link to a mob by saying @mob_702 and such.
dreamseeker_2022-03-22_21-51-41.png
Why It's Good For The Game
More robust admin tools
Changelog
cl Ryll/Shaps
admin: You can now link tickets in asay with #[ticket ID], like #1 and #5.
admin: asay datum linking now functions by saying '@[datum's tag value]`, whether it's a normal datum (@0x2001169) or a mob (@mob_702) or whatever else.
Discord_2022-03-16_23-38-09.png
(old pic)
---
code/__DEFINES/admin.dm | 8 +-
code/_globalvars/_regexes.dm | 1 -
code/modules/admin/verbs/adminhelp.dm | 101 ++++++++++--------
code/modules/admin/verbs/adminsay.dm | 29 +++--
.../admin/view_variables/view_variables.dm | 2 +-
5 files changed, 72 insertions(+), 69 deletions(-)
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\]" : "