From ab9daa1cba210a7dc287cd8602a6ebba4f786ebd Mon Sep 17 00:00:00 2001
From: SkyratBot <59378654+SkyratBot@users.noreply.github.com>
Date: Fri, 1 Oct 2021 22:08:59 +0200
Subject: [PATCH] [MIRROR] Add the ability to cancel incoming and outgoing
cross comms console messages for admins [MDB IGNORE] (#8538)
* Add the ability to cancel incoming and outgoing cross comms console messages for admins (#61799)
You can now cancel incoming and outgoing cross comms console messages.
* Add the ability to cancel incoming and outgoing cross comms console messages for admins
Co-authored-by: Mothblocks <35135081+Mothblocks@users.noreply.github.com>
---
code/__DEFINES/communications.dm | 2 +
code/datums/world_topic.dm | 54 +++++++++++++++-
.../game/machinery/computer/communications.dm | 63 ++++++++++++++++---
tgstation.dme | 1 +
4 files changed, 108 insertions(+), 12 deletions(-)
create mode 100644 code/__DEFINES/communications.dm
diff --git a/code/__DEFINES/communications.dm b/code/__DEFINES/communications.dm
new file mode 100644
index 00000000000..c8403bade30
--- /dev/null
+++ b/code/__DEFINES/communications.dm
@@ -0,0 +1,2 @@
+/// The time an admin has to cancel a cross-sector message
+#define CROSS_SECTOR_CANCEL_TIME (10 SECONDS)
diff --git a/code/datums/world_topic.dm b/code/datums/world_topic.dm
index 63dcd56a542..662dc1a1472 100644
--- a/code/datums/world_topic.dm
+++ b/code/datums/world_topic.dm
@@ -90,6 +90,8 @@
keyword = "Comms_Console"
require_comms_key = TRUE
+ var/list/timers
+
/datum/world_topic/comms_console/Run(list/input)
// Reject comms messages from other servers that are not on our configured network,
// if this has been configured. (See CROSS_COMMS_NETWORK in comms.txt)
@@ -97,10 +99,58 @@
if (configured_network && configured_network != input["network"])
return
+ // We can't add the timer without the timer ID, but we can't get the timer ID without the timer!
+ // To solve this, we just use a list that we mutate later.
+ var/list/data = list("input" = input)
+ var/timer_id = addtimer(CALLBACK(src, .proc/receive_cross_comms_message, data), CROSS_SECTOR_CANCEL_TIME, TIMER_STOPPABLE)
+ data["timer_id"] = timer_id
+
+ LAZYADD(timers, timer_id)
+
+ to_chat(
+ GLOB.admins,
+ span_adminnotice( \
+ "CROSS-SECTOR MESSAGE (INCOMING): [input["sender_ckey"]] (from [input["source"]]) is about to send \
+ the following message (will autoapprove in [DisplayTimeText(CROSS_SECTOR_CANCEL_TIME)]): \
+ REJECT
\
+ [html_encode(input["message"])]" \
+ )
+ )
+
+/datum/world_topic/comms_console/Topic(href, list/href_list)
+ . = ..()
+ if (.)
+ return
+
+ if (href_list["reject_cross_comms_message"])
+ if (!usr.client?.holder)
+ log_game("[key_name(usr)] tried to reject an incoming cross-comms message without being an admin.")
+ message_admins("[key_name(usr)] tried to reject an incoming cross-comms message without being an admin.")
+ return
+
+ var/timer_id = href_list["reject_cross_comms_message"]
+ if (!(timer_id in timers))
+ to_chat(usr, span_warning("It's too late!"))
+ return
+
+ deltimer(timer_id)
+ LAZYREMOVE(timers, timer_id)
+
+ log_admin("[key_name(usr)] has cancelled the incoming cross-comms message.")
+ message_admins("[key_name(usr)] has cancelled the incoming cross-comms message.")
+
+ return TRUE
+
+/datum/world_topic/comms_console/proc/receive_cross_comms_message(list/data)
+ var/list/input = data["input"]
+ var/timer_id = data["timer_id"]
+
+ LAZYREMOVE(timers, timer_id)
+
minor_announce(input["message"], "Incoming message from [input["message_sender"]]")
message_admins("Receiving a message from [input["sender_ckey"]] at [input["source"]]")
- for(var/obj/machinery/computer/communications/CM in GLOB.machines)
- CM.override_cooldown()
+ for(var/obj/machinery/computer/communications/communications_console in GLOB.machines)
+ communications_console.override_cooldown()
/datum/world_topic/news_report
keyword = "News_Report"
diff --git a/code/game/machinery/computer/communications.dm b/code/game/machinery/computer/communications.dm
index 9dc4a4c83a2..6dda8fcfb38 100755
--- a/code/game/machinery/computer/communications.dm
+++ b/code/game/machinery/computer/communications.dm
@@ -40,6 +40,9 @@
/// Used to clear the modal to change alert level
var/alert_level_tick = 0
+ /// The timer ID for sending the next cross-comms message
+ var/send_cross_comms_message_timer
+
/// The last lines used for changing the status display
var/static/last_status_display
@@ -272,18 +275,19 @@
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE)
var/destination = params["destination"]
- var/list/payload = list()
- var/network_name = CONFIG_GET(string/cross_comms_network)
- if (network_name)
- payload["network"] = network_name
- payload["sender_ckey"] = usr.ckey
+ log_game("[key_name(usr)] is about to send the following message to [destination]: [message]")
+ to_chat(
+ GLOB.admins,
+ span_adminnotice( \
+ "CROSS-SECTOR MESSAGE (OUTGOING): [ADMIN_LOOKUPFLW(usr)] is about to send \
+ the following message to [destination] (will autoapprove in [DisplayTimeText(CROSS_SECTOR_CANCEL_TIME)]): \
+ REJECT
\
+ [html_encode(message)]" \
+ )
+ )
- send2otherserver(html_decode(station_name()), message, "Comms_Console", destination == "all" ? null : list(destination), additional_data = payload)
- minor_announce(message, title = "Outgoing message to allied station")
- usr.log_talk(message, LOG_SAY, tag = "message to the other server")
- message_admins("[ADMIN_LOOKUPFLW(usr)] has sent a message to the other server\[s].")
- deadchat_broadcast(" has sent an outgoing message to the other station(s).", "[usr.real_name]", usr, message_type = DEADCHAT_ANNOUNCEMENT)
+ send_cross_comms_message_timer = addtimer(CALLBACK(src, .proc/send_cross_comms_message, usr, destination, message), CROSS_SECTOR_CANCEL_TIME, TIMER_STOPPABLE)
COOLDOWN_START(src, important_action_cooldown, IMPORTANT_ACTION_COOLDOWN)
if ("setState")
@@ -395,6 +399,22 @@
last_toggled = world.time
return FALSE //if we are not in cooldown, allow using the button
+/obj/machinery/computer/communications/proc/send_cross_comms_message(mob/user, destination, message)
+ send_cross_comms_message_timer = null
+
+ var/list/payload = list()
+
+ var/network_name = CONFIG_GET(string/cross_comms_network)
+ if (network_name)
+ payload["network"] = network_name
+ payload["sender_ckey"] = usr.ckey
+
+ send2otherserver(html_decode(station_name()), message, "Comms_Console", destination == "all" ? null : list(destination), additional_data = payload)
+ minor_announce(message, title = "Outgoing message to allied station")
+ usr.log_talk(message, LOG_SAY, tag = "message to the other server")
+ message_admins("[ADMIN_LOOKUPFLW(usr)] has sent a message to the other server\[s].")
+ deadchat_broadcast(" has sent an outgoing message to the other station(s).", "[usr.real_name]", usr, message_type = DEADCHAT_ANNOUNCEMENT)
+
/obj/machinery/computer/communications/ui_data(mob/user)
var/list/data = list(
"authenticated" = FALSE,
@@ -545,6 +565,29 @@
"maxMessageLength" = MAX_MESSAGE_LEN,
)
+/obj/machinery/computer/communications/Topic(href, href_list)
+ . = ..()
+ if (.)
+ return
+
+ if (href_list["reject_cross_comms_message"])
+ if (!usr.client?.holder)
+ log_game("[key_name(usr)] tried to reject a cross-comms message without being an admin.")
+ message_admins("[key_name(usr)] tried to reject a cross-comms message without being an admin.")
+ return
+
+ if (isnull(send_cross_comms_message_timer))
+ to_chat(usr, span_warning("It's too late!"))
+ return
+
+ deltimer(send_cross_comms_message_timer)
+ send_cross_comms_message_timer = null
+
+ log_admin("[key_name(usr)] has cancelled the outgoing cross-comms message.")
+ message_admins("[key_name(usr)] has cancelled the outgoing cross-comms message.")
+
+ return TRUE
+
/// Returns whether or not the communications console can communicate with the station
/obj/machinery/computer/communications/proc/has_communication()
var/turf/current_turf = get_turf(src)
diff --git a/tgstation.dme b/tgstation.dme
index 3f104c7e2a2..896d00cbd5a 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -48,6 +48,7 @@
#include "code\__DEFINES\cleaning.dm"
#include "code\__DEFINES\colors.dm"
#include "code\__DEFINES\combat.dm"
+#include "code\__DEFINES\communications.dm"
#include "code\__DEFINES\configuration.dm"
#include "code\__DEFINES\construction.dm"
#include "code\__DEFINES\cooldowns.dm"