From 261ac3d9ffc292e4760032c61591bdb6230ac212 Mon Sep 17 00:00:00 2001 From: tgstation-server Date: Sun, 16 Jul 2023 00:54:44 +0000 Subject: [PATCH] Update TGS DMAPI --- code/__DEFINES/tgs.dm | 2 +- code/modules/tgs/core/_definitions.dm | 8 ++++ code/modules/tgs/v3210/commands.dm | 4 +- code/modules/tgs/v4/commands.dm | 2 +- code/modules/tgs/v5/_defines.dm | 4 +- code/modules/tgs/v5/api.dm | 53 ++++++++++++++++++--------- code/modules/tgs/v5/commands.dm | 6 +-- code/modules/tgs/v5/serializers.dm | 18 ++++----- code/modules/tgs/v5/topic.dm | 39 ++++++++++++-------- 9 files changed, 85 insertions(+), 51 deletions(-) diff --git a/code/__DEFINES/tgs.dm b/code/__DEFINES/tgs.dm index 89976c49842..22c3827022f 100644 --- a/code/__DEFINES/tgs.dm +++ b/code/__DEFINES/tgs.dm @@ -1,6 +1,6 @@ // tgstation-server DMAPI -#define TGS_DMAPI_VERSION "6.5.0" +#define TGS_DMAPI_VERSION "6.5.2" // All functions and datums outside this document are subject to change with any version and should not be relied on. diff --git a/code/modules/tgs/core/_definitions.dm b/code/modules/tgs/core/_definitions.dm index ebf6d17c2a0..fd98034eb71 100644 --- a/code/modules/tgs/core/_definitions.dm +++ b/code/modules/tgs/core/_definitions.dm @@ -1,2 +1,10 @@ +#if DM_VERSION < 510 +#error The TGS DMAPI does not support BYOND versions < 510! +#endif + #define TGS_UNIMPLEMENTED "___unimplemented" #define TGS_VERSION_PARAMETER "server_service_version" + +#ifndef TGS_DEBUG_LOG +#define TGS_DEBUG_LOG(message) +#endif diff --git a/code/modules/tgs/v3210/commands.dm b/code/modules/tgs/v3210/commands.dm index d9bd287465b..e65c816320d 100644 --- a/code/modules/tgs/v3210/commands.dm +++ b/code/modules/tgs/v3210/commands.dm @@ -47,7 +47,7 @@ user.friendly_name = sender // Discord hack, fix the mention if it's only numbers (fuck you IRC trolls) - var/regex/discord_id_regex = regex(@"^[0-9]+$") + var/regex/discord_id_regex = regex("^\[0-9\]+$") if(findtext(sender, discord_id_regex)) sender = "<@[sender]>" @@ -55,4 +55,4 @@ var/datum/tgs_message_content/result = stc.Run(user, params) result = UpgradeDeprecatedCommandResponse(result, command) - return result?.text || TRUE + return result ? result.text : TRUE diff --git a/code/modules/tgs/v4/commands.dm b/code/modules/tgs/v4/commands.dm index d6d3d718d47..25dd6740e3a 100644 --- a/code/modules/tgs/v4/commands.dm +++ b/code/modules/tgs/v4/commands.dm @@ -40,5 +40,5 @@ var/datum/tgs_message_content/result = sc.Run(u, params) result = UpgradeDeprecatedCommandResponse(result, command) - return result?.text + return result ? result.text : TRUE return "Unknown command: [command]!" diff --git a/code/modules/tgs/v5/_defines.dm b/code/modules/tgs/v5/_defines.dm index c7213cc2469..f973338daa0 100644 --- a/code/modules/tgs/v5/_defines.dm +++ b/code/modules/tgs/v5/_defines.dm @@ -5,8 +5,8 @@ #define DMAPI5_TOPIC_DATA "tgs_data" #define DMAPI5_BRIDGE_REQUEST_LIMIT 8198 -#define DMAPI5_TOPIC_REQUEST_LIMIT 65529 -#define DMAPI5_TOPIC_RESPONSE_LIMIT 65528 +#define DMAPI5_TOPIC_REQUEST_LIMIT 65528 +#define DMAPI5_TOPIC_RESPONSE_LIMIT 65529 #define DMAPI5_BRIDGE_COMMAND_PORT_UPDATE 0 #define DMAPI5_BRIDGE_COMMAND_STARTUP 1 diff --git a/code/modules/tgs/v5/api.dm b/code/modules/tgs/v5/api.dm index 926ea10a8f2..34cc43f8762 100644 --- a/code/modules/tgs/v5/api.dm +++ b/code/modules/tgs/v5/api.dm @@ -22,12 +22,17 @@ var/detached = FALSE +/datum/tgs_api/v5/New() + . = ..() + TGS_DEBUG_LOG("V5 API created") + /datum/tgs_api/v5/ApiVersion() return new /datum/tgs_version( #include "__interop_version.dm" ) /datum/tgs_api/v5/OnWorldNew(minimum_required_security_level) + TGS_DEBUG_LOG("OnWorldNew()") server_port = world.params[DMAPI5_PARAM_SERVER_PORT] access_identifier = world.params[DMAPI5_PARAM_ACCESS_IDENTIFIER] @@ -96,17 +101,28 @@ return TRUE /datum/tgs_api/v5/proc/RequireInitialBridgeResponse() + TGS_DEBUG_LOG("RequireInitialBridgeResponse()") + var/logged = FALSE while(!version) + if(!logged) + TGS_DEBUG_LOG("RequireInitialBridgeResponse: Starting sleep") + logged = TRUE + sleep(1) + TGS_DEBUG_LOG("RequireInitialBridgeResponse: Passed") + /datum/tgs_api/v5/OnInitializationComplete() Bridge(DMAPI5_BRIDGE_COMMAND_PRIME) /datum/tgs_api/v5/OnTopic(T) + TGS_DEBUG_LOG("OnTopic()") RequireInitialBridgeResponse() + TGS_DEBUG_LOG("OnTopic passed bridge request gate") var/list/params = params2list(T) var/json = params[DMAPI5_TOPIC_DATA] if(!json) + TGS_DEBUG_LOG("No \"[DMAPI5_TOPIC_DATA]\" entry found, ignoring...") return FALSE // continue to /world/Topic if(!initialized) @@ -156,7 +172,7 @@ TGS_WARNING_LOG("Received legacy string when a [/datum/tgs_message_content] was expected. Please audit all calls to TgsChatBroadcast, TgsChatTargetedBroadcast, and TgsChatPrivateMessage to ensure they use the new /datum.") return new /datum/tgs_message_content(message) -/datum/tgs_api/v5/ChatBroadcast(datum/tgs_message_content/message, list/channels) +/datum/tgs_api/v5/ChatBroadcast(datum/tgs_message_content/message2, list/channels) if(!length(channels)) channels = ChatChannelInfo() @@ -165,45 +181,45 @@ var/datum/tgs_chat_channel/channel = I ids += channel.id - message = UpgradeDeprecatedChatMessage(message) + message2 = UpgradeDeprecatedChatMessage(message2) if (!length(channels)) return - message = message._interop_serialize() - message[DMAPI5_CHAT_MESSAGE_CHANNEL_IDS] = ids + var/list/data = message2._interop_serialize() + data[DMAPI5_CHAT_MESSAGE_CHANNEL_IDS] = ids if(intercepted_message_queue) - intercepted_message_queue += list(message) + intercepted_message_queue += list(data) else - Bridge(DMAPI5_BRIDGE_COMMAND_CHAT_SEND, list(DMAPI5_BRIDGE_PARAMETER_CHAT_MESSAGE = message)) + Bridge(DMAPI5_BRIDGE_COMMAND_CHAT_SEND, list(DMAPI5_BRIDGE_PARAMETER_CHAT_MESSAGE = data)) -/datum/tgs_api/v5/ChatTargetedBroadcast(datum/tgs_message_content/message, admin_only) +/datum/tgs_api/v5/ChatTargetedBroadcast(datum/tgs_message_content/message2, admin_only) var/list/channels = list() for(var/I in ChatChannelInfo()) var/datum/tgs_chat_channel/channel = I if (!channel.is_private_channel && ((channel.is_admin_channel && admin_only) || (!channel.is_admin_channel && !admin_only))) channels += channel.id - message = UpgradeDeprecatedChatMessage(message) + message2 = UpgradeDeprecatedChatMessage(message2) if (!length(channels)) return - message = message._interop_serialize() - message[DMAPI5_CHAT_MESSAGE_CHANNEL_IDS] = channels + var/list/data = message2._interop_serialize() + data[DMAPI5_CHAT_MESSAGE_CHANNEL_IDS] = channels if(intercepted_message_queue) - intercepted_message_queue += list(message) + intercepted_message_queue += list(data) else - Bridge(DMAPI5_BRIDGE_COMMAND_CHAT_SEND, list(DMAPI5_BRIDGE_PARAMETER_CHAT_MESSAGE = message)) + Bridge(DMAPI5_BRIDGE_COMMAND_CHAT_SEND, list(DMAPI5_BRIDGE_PARAMETER_CHAT_MESSAGE = data)) -/datum/tgs_api/v5/ChatPrivateMessage(datum/tgs_message_content/message, datum/tgs_chat_user/user) - message = UpgradeDeprecatedChatMessage(message) - message = message._interop_serialize() - message[DMAPI5_CHAT_MESSAGE_CHANNEL_IDS] = list(user.channel.id) +/datum/tgs_api/v5/ChatPrivateMessage(datum/tgs_message_content/message2, datum/tgs_chat_user/user) + message2 = UpgradeDeprecatedChatMessage(message2) + var/list/data = message2._interop_serialize() + data[DMAPI5_CHAT_MESSAGE_CHANNEL_IDS] = list(user.channel.id) if(intercepted_message_queue) - intercepted_message_queue += list(message) + intercepted_message_queue += list(data) else - Bridge(DMAPI5_BRIDGE_COMMAND_CHAT_SEND, list(DMAPI5_BRIDGE_PARAMETER_CHAT_MESSAGE = message)) + Bridge(DMAPI5_BRIDGE_COMMAND_CHAT_SEND, list(DMAPI5_BRIDGE_PARAMETER_CHAT_MESSAGE = data)) /datum/tgs_api/v5/ChatChannelInfo() RequireInitialBridgeResponse() @@ -211,6 +227,7 @@ return chat_channels.Copy() /datum/tgs_api/v5/proc/DecodeChannels(chat_update_json) + TGS_DEBUG_LOG("DecodeChannels()") var/list/chat_channels_json = chat_update_json[DMAPI5_CHAT_UPDATE_CHANNELS] if(istype(chat_channels_json)) chat_channels.Cut() diff --git a/code/modules/tgs/v5/commands.dm b/code/modules/tgs/v5/commands.dm index a832c81f172..9557f8a08ed 100644 --- a/code/modules/tgs/v5/commands.dm +++ b/code/modules/tgs/v5/commands.dm @@ -35,10 +35,10 @@ if(sc) var/datum/tgs_message_content/response = sc.Run(u, params) response = UpgradeDeprecatedCommandResponse(response, command) - + var/list/topic_response = TopicResponse() - topic_response[DMAPI5_TOPIC_RESPONSE_COMMAND_RESPONSE_MESSAGE] = response?.text - topic_response[DMAPI5_TOPIC_RESPONSE_COMMAND_RESPONSE] = response?._interop_serialize() + topic_response[DMAPI5_TOPIC_RESPONSE_COMMAND_RESPONSE_MESSAGE] = response ? response.text : null + topic_response[DMAPI5_TOPIC_RESPONSE_COMMAND_RESPONSE] = response ? response._interop_serialize() : null return topic_response return TopicResponse("Unknown custom chat command: [command]!") diff --git a/code/modules/tgs/v5/serializers.dm b/code/modules/tgs/v5/serializers.dm index 7f9bc731b79..3a32848ad51 100644 --- a/code/modules/tgs/v5/serializers.dm +++ b/code/modules/tgs/v5/serializers.dm @@ -1,12 +1,12 @@ /datum/tgs_message_content/proc/_interop_serialize() - return list("text" = text, "embed" = embed?._interop_serialize()) + return list("text" = text, "embed" = embed ? embed._interop_serialize() : null) /datum/tgs_chat_embed/proc/_interop_serialize() CRASH("Base /proc/interop_serialize called on [type]!") /datum/tgs_chat_embed/structure/_interop_serialize() var/list/serialized_fields - if(islist(fields)) + if(istype(fields, /list)) serialized_fields = list() for(var/datum/tgs_chat_embed/field/field as anything in fields) serialized_fields += list(field._interop_serialize()) @@ -16,12 +16,12 @@ "url" = url, "timestamp" = timestamp, "colour" = colour, - "image" = image?._interop_serialize(), - "thumbnail" = thumbnail?._interop_serialize(), - "video" = video?._interop_serialize(), - "footer" = footer?._interop_serialize(), - "provider" = provider?._interop_serialize(), - "author" = author?._interop_serialize(), + "image" = src.image ? src.image._interop_serialize() : null, + "thumbnail" = thumbnail ? thumbnail._interop_serialize() : null, + "video" = video ? video._interop_serialize() : null, + "footer" = footer ? footer._interop_serialize() : null, + "provider" = provider ? provider._interop_serialize() : null, + "author" = author ? author._interop_serialize() : null, "fields" = serialized_fields ) @@ -43,7 +43,7 @@ . = ..() .["iconUrl"] = icon_url .["proxyIconUrl"] = proxy_icon_url - + /datum/tgs_chat_embed/footer/_interop_serialize() return list( "text" = text, diff --git a/code/modules/tgs/v5/topic.dm b/code/modules/tgs/v5/topic.dm index 56c1824fd97..d7d47121381 100644 --- a/code/modules/tgs/v5/topic.dm +++ b/code/modules/tgs/v5/topic.dm @@ -5,6 +5,7 @@ return response /datum/tgs_api/v5/proc/ProcessTopicJson(json, check_access_identifier) + TGS_DEBUG_LOG("ProcessTopicJson(..., [check_access_identifier])") var/list/result = ProcessRawTopic(json, check_access_identifier) if(!result) result = TopicResponse("Runtime error!") @@ -25,16 +26,20 @@ return response_json /datum/tgs_api/v5/proc/ProcessRawTopic(json, check_access_identifier) + TGS_DEBUG_LOG("ProcessRawTopic(..., [check_access_identifier])") var/list/topic_parameters = json_decode(json) if(!topic_parameters) + TGS_DEBUG_LOG("ProcessRawTopic: json_decode failed") return TopicResponse("Invalid topic parameters json: [json]!"); var/their_sCK = topic_parameters[DMAPI5_PARAMETER_ACCESS_IDENTIFIER] if(check_access_identifier && their_sCK != access_identifier) - return TopicResponse("Failed to decode [DMAPI5_PARAMETER_ACCESS_IDENTIFIER]!") + TGS_DEBUG_LOG("ProcessRawTopic: access identifier check failed") + return TopicResponse("Failed to decode [DMAPI5_PARAMETER_ACCESS_IDENTIFIER] or it does not match!") var/command = topic_parameters[DMAPI5_TOPIC_PARAMETER_COMMAND_TYPE] if(!isnum(command)) + TGS_DEBUG_LOG("ProcessRawTopic: command type check failed") return TopicResponse("Failed to decode [DMAPI5_TOPIC_PARAMETER_COMMAND_TYPE]!") return ProcessTopicCommand(command, topic_parameters) @@ -43,6 +48,7 @@ return "response[payload_id]" /datum/tgs_api/v5/proc/ProcessTopicCommand(command, list/topic_parameters) + TGS_DEBUG_LOG("ProcessTopicCommand([command], ...)") switch(command) if(DMAPI5_TOPIC_COMMAND_CHAT_COMMAND) @@ -55,7 +61,6 @@ return result if(DMAPI5_TOPIC_COMMAND_EVENT_NOTIFICATION) - intercepted_message_queue = list() var/list/event_notification = topic_parameters[DMAPI5_TOPIC_PARAMETER_EVENT_NOTIFICATION] if(!istype(event_notification)) return TopicResponse("Invalid [DMAPI5_TOPIC_PARAMETER_EVENT_NOTIFICATION]!") @@ -66,23 +71,25 @@ var/list/event_parameters = event_notification[DMAPI5_EVENT_NOTIFICATION_PARAMETERS] if(event_parameters && !istype(event_parameters)) - return TopicResponse("Invalid or missing [DMAPI5_EVENT_NOTIFICATION_PARAMETERS]!") + . = TopicResponse("Invalid or missing [DMAPI5_EVENT_NOTIFICATION_PARAMETERS]!") + else + var/list/response = TopicResponse() + . = response + if(event_handler != null) + var/list/event_call = list(event_type) + if(event_parameters) + event_call += event_parameters + + intercepted_message_queue = list() + event_handler.HandleEvent(arglist(event_call)) + response[DMAPI5_TOPIC_RESPONSE_CHAT_RESPONSES] = intercepted_message_queue + intercepted_message_queue = null - var/list/event_call = list(event_type) if (event_type == TGS_EVENT_WATCHDOG_DETACH) detached = TRUE chat_channels.Cut() // https://github.com/tgstation/tgstation-server/issues/1490 - if(event_parameters) - event_call += event_parameters - - if(event_handler != null) - event_handler.HandleEvent(arglist(event_call)) - - var/list/response = TopicResponse() - response[DMAPI5_TOPIC_RESPONSE_CHAT_RESPONSES] = intercepted_message_queue - intercepted_message_queue = null - return response + return if(DMAPI5_TOPIC_COMMAND_CHANGE_PORT) var/new_port = topic_parameters[DMAPI5_TOPIC_PARAMETER_NEW_PORT] @@ -122,8 +129,10 @@ return TopicResponse() if(DMAPI5_TOPIC_COMMAND_CHAT_CHANNELS_UPDATE) + TGS_DEBUG_LOG("ProcessTopicCommand: It's a chat update") var/list/chat_update_json = topic_parameters[DMAPI5_TOPIC_PARAMETER_CHAT_UPDATE] if(!istype(chat_update_json)) + TGS_DEBUG_LOG("ProcessTopicCommand: failed \"[DMAPI5_TOPIC_PARAMETER_CHAT_UPDATE]\" check") return TopicResponse("Invalid or missing [DMAPI5_TOPIC_PARAMETER_CHAT_UPDATE]!") DecodeChannels(chat_update_json) @@ -138,7 +147,7 @@ return TopicResponse() if(DMAPI5_TOPIC_COMMAND_HEALTHCHECK) - if(event_handler?.receive_health_checks) + if(event_handler && event_handler.receive_health_checks) event_handler.HandleEvent(TGS_EVENT_HEALTH_CHECK) return TopicResponse()