mirror of
https://github.com/Aurorastation/Aurora.3.git
synced 2026-07-16 02:17:06 +01:00
Updates the TGS DM API to 7.0.1 (#9465)
* Updates the TGS DM API to 7.0.1 * Update code/__defines/tgs.dm Co-authored-by: Erki <skull132@users.noreply.github.com> * Add rust_g.so * Update rust_g detection with method from tg Co-authored-by: Werner <Arrow768@users.noreply.github.com> Co-authored-by: Erki <skull132@users.noreply.github.com>
This commit is contained in:
+275
-105
@@ -1,179 +1,349 @@
|
||||
//tgstation-server DMAPI
|
||||
// tgstation-server DMAPI
|
||||
|
||||
//All functions and datums outside this document are subject to change with any version and should not be relied on
|
||||
#define TGS_DMAPI_VERSION "5.2.2"
|
||||
|
||||
//CONFIGURATION
|
||||
// All functions and datums outside this document are subject to change with any version and should not be relied on.
|
||||
|
||||
//create this define if you want to do configuration outside of this file
|
||||
// CONFIGURATION
|
||||
|
||||
/// Create this define if you want to do TGS configuration outside of this file.
|
||||
#ifndef TGS_EXTERNAL_CONFIGURATION
|
||||
|
||||
//Comment this out once you've filled in the below
|
||||
// Comment this out once you've filled in the below.
|
||||
//#error TGS API unconfigured
|
||||
|
||||
//Required interfaces (fill in with your codebase equivalent):
|
||||
// Uncomment this if you wish to allow the game to interact with TGS 3.
|
||||
// This will raise the minimum required security level of your game to TGS_SECURITY_TRUSTED due to it utilizing call()()
|
||||
//#define TGS_V3_API
|
||||
|
||||
//create a global variable named `Name` and set it to `Value`
|
||||
//These globals must not be modifiable from anywhere outside of the server tools
|
||||
// Required interfaces (fill in with your codebase equivalent):
|
||||
|
||||
/// Create a global variable named `Name` and set it to `Value`.
|
||||
#define TGS_DEFINE_AND_SET_GLOBAL(Name, Value) var/global/_tgs_##Name = ##Value
|
||||
|
||||
//Read the value in the global variable `Name`
|
||||
/// Read the value in the global variable `Name`.
|
||||
#define TGS_READ_GLOBAL(Name) global._tgs_##Name
|
||||
|
||||
//Set the value in the global variable `Name` to `Value`
|
||||
/// Set the value in the global variable `Name` to `Value`.
|
||||
#define TGS_WRITE_GLOBAL(Name, Value) global._tgs_##Name = ##Value
|
||||
|
||||
//Disallow ANYONE from reflecting a given `path`, security measure to prevent in-game priveledge escalation
|
||||
/// Disallow ANYONE from reflecting a given `path`, security measure to prevent in-game use of DD -> TGS capabilities.
|
||||
#define TGS_PROTECT_DATUM(Path)
|
||||
|
||||
//display an announcement `message` from the server to all players
|
||||
#define TGS_WORLD_ANNOUNCE(message) world << "[html_encode(##message)]"
|
||||
/// Display an announcement `message` from the server to all players.
|
||||
#define TGS_WORLD_ANNOUNCE(message) world << "<b>TGS Notification</b>: [html_encode(##message)]"
|
||||
|
||||
//Notify current in-game administrators of a string `event`
|
||||
/// Notify current in-game administrators of a string `event`.
|
||||
#define TGS_NOTIFY_ADMINS(event) message_admins(##event)
|
||||
|
||||
//Write an info `message` to a server log
|
||||
/// Write an info `message` to a server log.
|
||||
#define TGS_INFO_LOG(message) log_tgs("[##message]")
|
||||
|
||||
//Write an error `message` to a server log
|
||||
/// Write an warning `message` to a server log.
|
||||
#define TGS_WARNING_LOG(message) log_tgs("[##message]", SEVERITY_WARNING)
|
||||
|
||||
/// Write an error `message` to a server log.
|
||||
#define TGS_ERROR_LOG(message) log_tgs("[##message]", SEVERITY_ERROR)
|
||||
|
||||
//Get the number of connected /clients
|
||||
/// Get the number of connected /clients.
|
||||
#define TGS_CLIENT_COUNT clients.len
|
||||
|
||||
#endif
|
||||
|
||||
//EVENT CODES
|
||||
// EVENT CODES
|
||||
|
||||
//TODO
|
||||
/// Before a reboot mode change, extras parameters are the current and new reboot mode enums
|
||||
#define TGS_EVENT_REBOOT_MODE_CHANGE -1
|
||||
/// Before a port change is about to happen, extra parameters is new port
|
||||
#define TGS_EVENT_PORT_SWAP -2
|
||||
/// Before the instance is renamed, extra parameter is the new name
|
||||
#define TGS_EVENT_INSTANCE_RENAMED -3
|
||||
/// After the watchdog reattaches to DD, extra parameter is the new [/datum/tgs_version] of the server
|
||||
#define TGS_EVENT_WATCHDOG_REATTACH -4
|
||||
|
||||
/// When the repository is reset to its origin reference. Parameters: Reference name, Commit SHA
|
||||
#define TGS_EVENT_REPO_RESET_ORIGIN 0
|
||||
/// When the repository performs a checkout. Parameters: Checkout git object
|
||||
#define TGS_EVENT_REPO_CHECKOUT 1
|
||||
/// When the repository performs a fetch operation. No parameters
|
||||
#define TGS_EVENT_REPO_FETCH 2
|
||||
/// When the repository merges a pull request. Parameters: PR Number, PR Sha, (Nullable) Comment made by TGS user
|
||||
#define TGS_EVENT_REPO_MERGE_PULL_REQUEST 3
|
||||
/// Before the repository makes a sychronize operation. Parameters: Absolute repostiory path
|
||||
#define TGS_EVENT_REPO_PRE_SYNCHRONIZE 4
|
||||
/// Before a BYOND install operation begins. Parameters: [/datum/tgs_version] of the installing BYOND
|
||||
#define TGS_EVENT_BYOND_INSTALL_START 5
|
||||
/// When a BYOND install operation fails. Parameters: Error message
|
||||
#define TGS_EVENT_BYOND_INSTALL_FAIL 6
|
||||
/// When the active BYOND version changes. Parameters: (Nullable) [/datum/tgs_version] of the current BYOND, [/datum/tgs_version] of the new BYOND
|
||||
#define TGS_EVENT_BYOND_ACTIVE_VERSION_CHANGE 7
|
||||
/// When the compiler starts running. Parameters: Game directory path, origin commit SHA
|
||||
#define TGS_EVENT_COMPILE_START 8
|
||||
/// When a compile is cancelled. No parameters
|
||||
#define TGS_EVENT_COMPILE_CANCELLED 9
|
||||
/// When a compile fails. Parameters: Game directory path, [TRUE]/[FALSE] based on if the cause for failure was DMAPI validation
|
||||
#define TGS_EVENT_COMPILE_FAILURE 10
|
||||
/// When a compile operation completes. Note, this event fires before the new .dmb is loaded into the watchdog. Consider using the [TGS_EVENT_DEPLOYMENT_COMPLETE] instead. Parameters: Game directory path
|
||||
#define TGS_EVENT_COMPILE_COMPLETE 11
|
||||
/// When an automatic update for the current instance begins. No parameters
|
||||
#define TGS_EVENT_INSTANCE_AUTO_UPDATE_START 12
|
||||
/// When the repository encounters a merge conflict: Parameters: Base SHA, target SHA, base reference, target reference
|
||||
#define TGS_EVENT_REPO_MERGE_CONFLICT 13
|
||||
/// When a deployment completes. No Parameters
|
||||
#define TGS_EVENT_DEPLOYMENT_COMPLETE 14
|
||||
/// Before the watchdog shuts down. Not sent for graceful shutdowns. No parameters.
|
||||
#define TGS_EVENT_WATCHDOG_SHUTDOWN 15
|
||||
/// Before the watchdog detaches for a TGS update/restart. No parameters.
|
||||
#define TGS_EVENT_WATCHDOG_DETACH 16
|
||||
// We don't actually implement this value as the DMAPI can never receive it
|
||||
// #define TGS_EVENT_WATCHDOG_LAUNCH 17
|
||||
|
||||
// OTHER ENUMS
|
||||
|
||||
/// The server will reboot normally.
|
||||
#define TGS_REBOOT_MODE_NORMAL 0
|
||||
/// The server will stop running on reboot.
|
||||
#define TGS_REBOOT_MODE_SHUTDOWN 1
|
||||
/// The watchdog will restart on reboot.
|
||||
#define TGS_REBOOT_MODE_RESTART 2
|
||||
|
||||
/// DreamDaemon Trusted security level.
|
||||
#define TGS_SECURITY_TRUSTED 0
|
||||
/// DreamDaemon Safe security level.
|
||||
#define TGS_SECURITY_SAFE 1
|
||||
/// DreamDaemon Ultrasafe security level.
|
||||
#define TGS_SECURITY_ULTRASAFE 2
|
||||
|
||||
//REQUIRED HOOKS
|
||||
|
||||
//Call this somewhere in /world/New() that is always run
|
||||
//event_handler: optional user defined event handler. The default behaviour is to broadcast the event in english to all connected admin channels
|
||||
/world/proc/TgsNew(datum/tgs_event_handler/event_handler)
|
||||
/**
|
||||
* Call this somewhere in [/world/proc/New] that is always run. This function may sleep!
|
||||
*
|
||||
* * event_handler - Optional user defined [/datum/tgs_event_handler].
|
||||
* * minimum_required_security_level: The minimum required security level to run the game in which the DMAPI is integrated. Can be one of [TGS_SECURITY_ULTRASAFE], [TGS_SECURITY_SAFE], or [TGS_SECURITY_TRUSTED].
|
||||
*/
|
||||
/world/proc/TgsNew(datum/tgs_event_handler/event_handler, minimum_required_security_level = TGS_SECURITY_ULTRASAFE)
|
||||
return
|
||||
|
||||
//Call this when your initializations are complete and your game is ready to play before any player interactions happen
|
||||
//This may use world.sleep_offline to make this happen so ensure no changes are made to it while this call is running
|
||||
/**
|
||||
* Call this when your initializations are complete and your game is ready to play before any player interactions happen.
|
||||
*
|
||||
* This may use [/world/var/sleep_offline] to make this happen so ensure no changes are made to it while this call is running.
|
||||
* Afterwards, consider explicitly setting it to what you want to avoid this BYOND bug: http://www.byond.com/forum/post/2575184
|
||||
* Before this point, note that any static files or directories may be in use by another server. Your code should account for this.
|
||||
* This function should not be called before ..() in [/world/proc/New].
|
||||
*/
|
||||
/world/proc/TgsInitializationComplete()
|
||||
return
|
||||
|
||||
//Put this somewhere in /world/Topic(T, Addr, Master, Keys) that is always run before T is modified
|
||||
#define TGS_TOPIC var/tgs_topic_return = TgsTopic(T); if(tgs_topic_return) return tgs_topic_return
|
||||
/// Put this at the start of [/world/proc/Topic].
|
||||
#define TGS_TOPIC var/tgs_topic_return = TgsTopic(args[1]); if(tgs_topic_return) return tgs_topic_return
|
||||
|
||||
//Call this at the beginning of world/Reboot(reason)
|
||||
/**
|
||||
* Call this at the beginning of [world/proc/Reboot].
|
||||
*/
|
||||
/world/proc/TgsReboot()
|
||||
return
|
||||
|
||||
//DATUM DEFINITIONS
|
||||
//unless otherwise specified all datums defined here should be considered read-only, warranty void if written
|
||||
// DATUM DEFINITIONS
|
||||
// All datums defined here should be considered read-only
|
||||
|
||||
//represents git revision information about the current world build
|
||||
/// Represents git revision information.
|
||||
/datum/tgs_revision_information
|
||||
var/commit //full sha of compiled commit
|
||||
var/origin_commit //full sha of last known remote commit. This may be null if the TGS repository is not currently tracking a remote branch
|
||||
/// Full SHA of the commit.
|
||||
var/commit
|
||||
/// Full sha of last known remote commit. This may be null if the TGS repository is not currently tracking a remote branch.
|
||||
var/origin_commit
|
||||
|
||||
//represents a merge of a GitHub pull request
|
||||
/datum/tgs_revision_information/test_merge
|
||||
var/number //pull request number
|
||||
var/title //pull request title
|
||||
var/body //pull request body
|
||||
var/author //pull request github author
|
||||
var/url //link to pull request html
|
||||
var/pull_request_commit //commit of the pull request when it was merged
|
||||
var/time_merged //timestamp of when the merge commit for the pull request was created
|
||||
var/comment //optional comment left by the one who initiated the test merge
|
||||
/// Represents a version.
|
||||
/datum/tgs_version
|
||||
/// The suite/major version number
|
||||
var/suite
|
||||
|
||||
//represents a connected chat channel
|
||||
/datum/tgs_chat_channel
|
||||
var/id //internal channel representation
|
||||
var/friendly_name //user friendly channel name
|
||||
var/server_name //server name the channel resides on
|
||||
var/provider_name //chat provider for the channel
|
||||
var/is_admin_channel //if the server operator has marked this channel for game admins only
|
||||
var/is_private_channel //if this is a private chat channel
|
||||
// This group of variables can be null to represent a wild card
|
||||
/// The minor version number. null for wildcards
|
||||
var/minor
|
||||
/// The patch version number. null for wildcards
|
||||
var/patch
|
||||
|
||||
//represents a chat user
|
||||
/datum/tgs_chat_user
|
||||
var/id //Internal user representation
|
||||
var/friendly_name //The user's public name
|
||||
var/mention //The text to use to ping this user in a message
|
||||
var/datum/tgs_chat_channel/channel //The /datum/tgs_chat_channel this user was from
|
||||
/// Legacy version number. Generally null
|
||||
var/deprecated_patch
|
||||
|
||||
//user definable callback for handling events
|
||||
/datum/tgs_event_handler/proc/HandleEvent(event_code)
|
||||
/// Unparsed string value
|
||||
var/raw_parameter
|
||||
/// String value minus prefix
|
||||
var/deprefixed_parameter
|
||||
|
||||
/**
|
||||
* Returns [TRUE]/[FALSE] based on if the [/datum/tgs_version] contains wildcards.
|
||||
*/
|
||||
/datum/tgs_version/proc/Wildcard()
|
||||
return
|
||||
|
||||
//user definable chat command
|
||||
/datum/tgs_chat_command
|
||||
var/name = "" //the string to trigger this command on a chat bot. e.g. TGS3_BOT: do_this_command
|
||||
var/help_text = "" //help text for this command
|
||||
var/admin_only = FALSE //set to TRUE if this command should only be usable by registered chat admins
|
||||
/**
|
||||
* Returns [TRUE]/[FALSE] based on if the [/datum/tgs_version] equals some other version.
|
||||
*
|
||||
* other_version - The [/datum/tgs_version] to compare against.
|
||||
*/
|
||||
/datum/tgs_version/proc/Equals(datum/tgs_version/other_version)
|
||||
return
|
||||
|
||||
//override to implement command
|
||||
//sender: The tgs_chat_user who send to command
|
||||
//params: The trimmed string following the command name
|
||||
//The return value will be stringified and sent to the appropriate chat
|
||||
/// Represents a merge of a GitHub pull request.
|
||||
/datum/tgs_revision_information/test_merge
|
||||
/// The pull request number.
|
||||
var/number
|
||||
/// The pull request title when it was merged.
|
||||
var/title
|
||||
/// The pull request body when it was merged.
|
||||
var/body
|
||||
/// The GitHub username of the pull request's author.
|
||||
var/author
|
||||
/// An http URL to the pull request.
|
||||
var/url
|
||||
/// The SHA of the pull request when that was merged.
|
||||
var/pull_request_commit
|
||||
/// ISO 8601 timestamp of when the pull request was merged.
|
||||
var/time_merged
|
||||
/// (Nullable) Comment left by the TGS user who initiated the merge..
|
||||
var/comment
|
||||
|
||||
/// Represents a connected chat channel.
|
||||
/datum/tgs_chat_channel
|
||||
/// TGS internal channel ID.
|
||||
var/id
|
||||
/// User friendly name of the channel.
|
||||
var/friendly_name
|
||||
/// Name of the chat connection. This is the IRC server address or the Discord guild.
|
||||
var/connection_name
|
||||
/// [TRUE]/[FALSE] based on if the server operator has marked this channel for game admins only.
|
||||
var/is_admin_channel
|
||||
/// [TRUE]/[FALSE] if the channel is a private message channel for a [/datum/tgs_chat_user].
|
||||
var/is_private_channel
|
||||
/// Tag string associated with the channel in TGS
|
||||
var/custom_tag
|
||||
|
||||
// Represents a chat user
|
||||
/datum/tgs_chat_user
|
||||
/// TGS internal user ID.
|
||||
var/id
|
||||
// The user's display name.
|
||||
var/friendly_name
|
||||
// The string to use to ping this user in a message.
|
||||
var/mention
|
||||
/// The [/datum/tgs_chat_channel] the user was from
|
||||
var/datum/tgs_chat_channel/channel
|
||||
|
||||
/**
|
||||
* User definable callback for handling TGS events.
|
||||
*
|
||||
* event_code - One of the TGS_EVENT_ defines. Extra parameters will be documented in each
|
||||
*/
|
||||
/datum/tgs_event_handler/proc/HandleEvent(event_code, ...)
|
||||
set waitfor = FALSE
|
||||
return
|
||||
|
||||
/// User definable chat command
|
||||
/datum/tgs_chat_command
|
||||
/// The string to trigger this command on a chat bot. e.g `@bot name ...` or `!tgs name ...`
|
||||
var/name = ""
|
||||
/// The help text displayed for this command
|
||||
var/help_text = ""
|
||||
/// If this command should be available to game administrators only
|
||||
var/admin_only = FALSE
|
||||
|
||||
/**
|
||||
* Process command activation. Should return a string to respond to the issuer with.
|
||||
*
|
||||
* sender - The [/datum/tgs_chat_user] who issued the command.
|
||||
* params - The trimmed string following the command `/datum/tgs_chat_command/var/name].
|
||||
*/
|
||||
/datum/tgs_chat_command/proc/Run(datum/tgs_chat_user/sender, params)
|
||||
CRASH("[type] has no implementation for Run()")
|
||||
|
||||
//FUNCTIONS
|
||||
// API FUNCTIONS
|
||||
|
||||
//Returns the respective string version of the API
|
||||
/// Returns the maximum supported [/datum/tgs_version] of the DMAPI.
|
||||
/world/proc/TgsMaximumAPIVersion()
|
||||
return
|
||||
|
||||
/// Returns the minimum supported [/datum/tgs_version] of the DMAPI.
|
||||
/world/proc/TgsMinimumAPIVersion()
|
||||
return
|
||||
|
||||
//Gets the current version of the server tools running the server
|
||||
/world/proc/TgsVersion()
|
||||
return
|
||||
|
||||
//Returns TRUE if the world was launched under the server tools and the API matches, FALSE otherwise
|
||||
//No function below this succeeds if it returns FALSE
|
||||
/**
|
||||
* Returns [TRUE] if DreamDaemon was launched under TGS, the API matches, and was properly initialized. [FALSE] will be returned otherwise.
|
||||
*/
|
||||
/world/proc/TgsAvailable()
|
||||
return
|
||||
|
||||
/world/proc/TgsInstanceName()
|
||||
return
|
||||
// No function below this succeeds if it TgsAvailable() returns FALSE or if TgsNew() has yet to be called.
|
||||
|
||||
//Get the current `/datum/tgs_revision_information`
|
||||
/world/proc/TgsRevision()
|
||||
return
|
||||
|
||||
//Gets a list of active `/datum/tgs_revision_information/test_merge`s
|
||||
/world/proc/TgsTestMerges()
|
||||
return
|
||||
|
||||
//Forces a hard reboot of BYOND by ending the process
|
||||
//unlike del(world) clients will try to reconnect
|
||||
//If the service has not requested a shutdown, the next server will take over
|
||||
/**
|
||||
* Forces a hard reboot of DreamDaemon by ending the process.
|
||||
*
|
||||
* Unlike del(world) clients will try to reconnect.
|
||||
* If TGS has not requested a [TGS_REBOOT_MODE_SHUTDOWN] DreamDaemon will be launched again
|
||||
*/
|
||||
/world/proc/TgsEndProcess()
|
||||
return
|
||||
|
||||
//Gets a list of connected tgs_chat_channel
|
||||
/world/proc/TgsChatChannelInfo()
|
||||
/**
|
||||
* Send a message to connected chats.
|
||||
*
|
||||
* message - The string to send.
|
||||
* admin_only: If [TRUE], message will be sent to admin connected chats. Vice-versa applies.
|
||||
*/
|
||||
/world/proc/TgsTargetedChatBroadcast(message, admin_only = FALSE)
|
||||
return
|
||||
|
||||
//Sends a message to connected game chats
|
||||
//message: The message to send
|
||||
//channels: optional channels to limit the broadcast to
|
||||
/world/proc/TgsChatBroadcast(message, list/channels)
|
||||
return
|
||||
|
||||
//Send a message to non-admin connected chats
|
||||
//message: The message to send
|
||||
//admin_only: If TRUE, message will instead be sent to only admin connected chats
|
||||
/world/proc/TgsTargetedChatBroadcast(message, admin_only)
|
||||
return
|
||||
|
||||
//Send a private message to a specific user
|
||||
//message: The message to send
|
||||
//user: The /datum/tgs_chat_user to send to
|
||||
/**
|
||||
* Send a private message to a specific user.
|
||||
*
|
||||
* message - The string to send.
|
||||
* user: The [/datum/tgs_chat_user] to PM.
|
||||
*/
|
||||
/world/proc/TgsChatPrivateMessage(message, datum/tgs_chat_user/user)
|
||||
return
|
||||
|
||||
// The following functions will sleep if a call to TgsNew() is sleeping
|
||||
|
||||
/**
|
||||
* Send a message to connected chats that are flagged as game-related in TGS.
|
||||
*
|
||||
* message - The string to send.
|
||||
* channels - Optional list of [/datum/tgs_chat_channel]s to restrict the message to.
|
||||
*/
|
||||
/world/proc/TgsChatBroadcast(message, list/channels = null)
|
||||
return
|
||||
|
||||
/// Returns the current [/datum/tgs_version] of TGS if it is running the server, null otherwise.
|
||||
/world/proc/TgsVersion()
|
||||
return
|
||||
|
||||
/// Returns the current [/datum/tgs_version] of the DMAPI being used if it was activated, null otherwise.
|
||||
/world/proc/TgsApiVersion()
|
||||
return
|
||||
|
||||
/// Returns the name of the TGS instance running the game if TGS is present, null otherwise.
|
||||
/world/proc/TgsInstanceName()
|
||||
return
|
||||
|
||||
/// Return the current [/datum/tgs_revision_information] of the running server if TGS is present, null otherwise.
|
||||
/world/proc/TgsRevision()
|
||||
return
|
||||
|
||||
/// Returns the current BYOND security level as a TGS_SECURITY_ define if TGS is present, null otherwise.
|
||||
/world/proc/TgsSecurityLevel()
|
||||
return
|
||||
|
||||
/// Returns a list of active [/datum/tgs_revision_information/test_merge]s if TGS is present, null otherwise.
|
||||
/world/proc/TgsTestMerges()
|
||||
return
|
||||
|
||||
/// Returns a list of connected [/datum/tgs_chat_channel]s if TGS is present, null otherwise.
|
||||
/world/proc/TgsChatChannelInfo()
|
||||
return
|
||||
|
||||
/*
|
||||
The MIT License
|
||||
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
The MIT License
|
||||
|
||||
Copyright (c) 2017 Jordan Brown
|
||||
|
||||
Permission is hereby granted, free of charge,
|
||||
to any person obtaining a copy of this software and
|
||||
associated documentation files (the "Software"), to
|
||||
deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify,
|
||||
merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom
|
||||
the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice
|
||||
shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
@@ -0,0 +1,13 @@
|
||||
# DMAPI Internals
|
||||
|
||||
This folder should be placed on it's own inside a codebase that wishes to use the TGS DMAPI. Warranty void if modified.
|
||||
|
||||
- [includes.dm](./includes.dm) is the file that should be included by DM code, it handles including the rest.
|
||||
- The [core](./core) folder includes all code not directly part of any API version.
|
||||
- The other versioned folders contain code for the different DMAPI versions.
|
||||
- [v3210](./v3210) contains the final TGS3 API.
|
||||
- [v4](./v4) is the legacy DMAPI 4 (Used in TGS 4.0.X versions).
|
||||
- [v5](./v5) is the current DMAPI version used by TGS4 >=4.1.
|
||||
- [LICENSE](./LICENSE) is the MIT license for the DMAPI.
|
||||
|
||||
APIs communicate with TGS in two ways. All versions implement TGS -> DM communication using /world/Topic. DM -> TGS communication, called the bridge method, is different for each version.
|
||||
@@ -0,0 +1,8 @@
|
||||
# Core DMAPI functions
|
||||
|
||||
This folder contains all DMAPI code not directly involved in an API.
|
||||
|
||||
- [_definitions.dm](./definitions.dm) contains defines needed across DMAPI internals.
|
||||
- [core.dm](./core.dm) contains the implementations of the `/world/proc/TgsXXX()` procs. Many map directly to the `/datum/tgs_api` functions. It also contains the /datum selection and setup code.
|
||||
- [datum.dm](./datum.dm) contains the `/datum/tgs_api` declarations that all APIs must implement.
|
||||
- [tgs_version.dm](./tgs_version.dm) contains the `/datum/tgs_version` definition
|
||||
@@ -1,48 +1,74 @@
|
||||
/world/TgsNew(datum/tgs_event_handler/event_handler)
|
||||
var/tgs_version = world.params[TGS_VERSION_PARAMETER]
|
||||
if(!tgs_version)
|
||||
/world/TgsNew(datum/tgs_event_handler/event_handler, minimum_required_security_level = TGS_SECURITY_ULTRASAFE)
|
||||
var/current_api = TGS_READ_GLOBAL(tgs)
|
||||
if(current_api)
|
||||
TGS_ERROR_LOG("API datum already set (\ref[current_api] ([current_api]))! Was TgsNew() called more than once?")
|
||||
return
|
||||
|
||||
var/path = SelectTgsApi(tgs_version)
|
||||
if(!path)
|
||||
TGS_ERROR_LOG("Found unsupported API version: [tgs_version]. If this is a valid version please report this, backporting is done on demand.")
|
||||
if(!(minimum_required_security_level in list(TGS_SECURITY_ULTRASAFE, TGS_SECURITY_SAFE, TGS_SECURITY_TRUSTED)))
|
||||
TGS_ERROR_LOG("Invalid minimum_required_security_level: [minimum_required_security_level]!")
|
||||
return
|
||||
|
||||
TGS_INFO_LOG("Activating API for version [tgs_version]")
|
||||
var/datum/tgs_api/new_api = new path
|
||||
#ifdef TGS_V3_API
|
||||
if(minimum_required_security_level != TGS_SECURITY_TRUSTED)
|
||||
TGS_WARNING_LOG("V3 DMAPI requires trusted security!")
|
||||
minimum_required_security_level = TGS_SECURITY_TRUSTED
|
||||
#endif
|
||||
var/raw_parameter = world.params[TGS_VERSION_PARAMETER]
|
||||
if(!raw_parameter)
|
||||
return
|
||||
|
||||
var/result = new_api.OnWorldNew(event_handler ? event_handler : new /datum/tgs_event_handler/tgs_default)
|
||||
if(result && result != TGS_UNIMPLEMENTED)
|
||||
TGS_WRITE_GLOBAL(tgs, new_api)
|
||||
else
|
||||
var/datum/tgs_version/version = new(raw_parameter)
|
||||
if(!version.Valid(FALSE))
|
||||
TGS_ERROR_LOG("Failed to validate DMAPI version parameter: [raw_parameter]!")
|
||||
return
|
||||
|
||||
var/api_datum
|
||||
switch(version.suite)
|
||||
if(3)
|
||||
#ifndef TGS_V3_API
|
||||
TGS_ERROR_LOG("Detected V3 API but TGS_V3_API isn't defined!")
|
||||
return
|
||||
#else
|
||||
switch(version.minor)
|
||||
if(2)
|
||||
api_datum = /datum/tgs_api/v3210
|
||||
#endif
|
||||
if(4)
|
||||
switch(version.minor)
|
||||
if(0)
|
||||
api_datum = /datum/tgs_api/v4
|
||||
if(5)
|
||||
api_datum = /datum/tgs_api/v5
|
||||
|
||||
var/datum/tgs_version/max_api_version = TgsMaximumAPIVersion();
|
||||
if(version.suite != null && version.minor != null && version.patch != null && version.deprecated_patch != null && version.deprefixed_parameter > max_api_version.deprefixed_parameter)
|
||||
TGS_ERROR_LOG("Detected unknown API version! Defaulting to latest. Update the DMAPI to fix this problem.")
|
||||
api_datum = /datum/tgs_api/latest
|
||||
|
||||
if(!api_datum)
|
||||
TGS_ERROR_LOG("Found unsupported API version: [raw_parameter]. If this is a valid version please report this, backporting is done on demand.")
|
||||
return
|
||||
|
||||
TGS_INFO_LOG("Activating API for version [version.deprefixed_parameter]")
|
||||
|
||||
if(event_handler && !istype(event_handler))
|
||||
TGS_ERROR_LOG("Invalid parameter for event_handler: [event_handler]")
|
||||
event_handler = null
|
||||
|
||||
var/datum/tgs_api/new_api = new api_datum(event_handler, version)
|
||||
|
||||
TGS_WRITE_GLOBAL(tgs, new_api)
|
||||
|
||||
var/result = new_api.OnWorldNew(minimum_required_security_level)
|
||||
if(!result || result == TGS_UNIMPLEMENTED)
|
||||
TGS_WRITE_GLOBAL(tgs, null)
|
||||
TGS_ERROR_LOG("Failed to activate API!")
|
||||
|
||||
/world/proc/SelectTgsApi(tgs_version)
|
||||
//remove the old 3.0 header
|
||||
tgs_version = replacetext(tgs_version, "/tg/station 13 Server v", "")
|
||||
|
||||
var/list/version_bits = splittext(tgs_version, ".")
|
||||
|
||||
var/super = text2num(version_bits[1])
|
||||
var/major = text2num(version_bits[2])
|
||||
var/minor = text2num(version_bits[3])
|
||||
var/patch = text2num(version_bits[4])
|
||||
|
||||
switch(super)
|
||||
if(3)
|
||||
switch(major)
|
||||
if(2)
|
||||
return /datum/tgs_api/v3210
|
||||
|
||||
if(super != null && major != null && minor != null && patch != null && tgs_version > TgsMaximumAPIVersion())
|
||||
TGS_ERROR_LOG("Detected unknown API version! Defaulting to latest. Update the DMAPI to fix this problem.")
|
||||
return /datum/tgs_api/latest
|
||||
|
||||
/world/TgsMaximumAPIVersion()
|
||||
return "4.0.0.0"
|
||||
return new /datum/tgs_version("5.x.x")
|
||||
|
||||
/world/TgsMinimumAPIVersion()
|
||||
return "3.2.0.0"
|
||||
return new /datum/tgs_version("3.2.x")
|
||||
|
||||
/world/TgsInitializationComplete()
|
||||
var/datum/tgs_api/api = TGS_READ_GLOBAL(tgs)
|
||||
@@ -72,7 +98,14 @@
|
||||
return TGS_READ_GLOBAL(tgs) != null
|
||||
|
||||
/world/TgsVersion()
|
||||
return world.params[TGS_VERSION_PARAMETER]
|
||||
var/datum/tgs_api/api = TGS_READ_GLOBAL(tgs)
|
||||
if(api)
|
||||
return api.version
|
||||
|
||||
/world/TgsApiVersion()
|
||||
var/datum/tgs_api/api = TGS_READ_GLOBAL(tgs)
|
||||
if(api)
|
||||
return api.ApiVersion()
|
||||
|
||||
/world/TgsInstanceName()
|
||||
var/datum/tgs_api/api = TGS_READ_GLOBAL(tgs)
|
||||
@@ -117,29 +150,7 @@
|
||||
if(api)
|
||||
api.ChatPrivateMessage(message, user)
|
||||
|
||||
/*
|
||||
The MIT License
|
||||
|
||||
Copyright (c) 2017 Jordan Brown
|
||||
|
||||
Permission is hereby granted, free of charge,
|
||||
to any person obtaining a copy of this software and
|
||||
associated documentation files (the "Software"), to
|
||||
deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify,
|
||||
merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom
|
||||
the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice
|
||||
shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
/world/TgsSecurityLevel()
|
||||
var/datum/tgs_api/api = TGS_READ_GLOBAL(tgs)
|
||||
if(api)
|
||||
api.SecurityLevel()
|
||||
|
||||
@@ -1,9 +1,16 @@
|
||||
TGS_DEFINE_AND_SET_GLOBAL(tgs, null)
|
||||
|
||||
/datum/tgs_api
|
||||
var/datum/tgs_version/version
|
||||
var/datum/tgs_event_handler/event_handler
|
||||
|
||||
/datum/tgs_api/New(datum/tgs_event_handler/event_handler, datum/tgs_version/version)
|
||||
. = ..()
|
||||
src.event_handler = event_handler
|
||||
src.version = version
|
||||
|
||||
/datum/tgs_api/latest
|
||||
parent_type = /datum/tgs_api/v3210
|
||||
parent_type = /datum/tgs_api/v5
|
||||
|
||||
TGS_PROTECT_DATUM(/datum/tgs_api)
|
||||
|
||||
@@ -43,32 +50,8 @@ TGS_PROTECT_DATUM(/datum/tgs_api)
|
||||
/datum/tgs_api/proc/ChatTargetedBroadcast(message, admin_only)
|
||||
return TGS_UNIMPLEMENTED
|
||||
|
||||
/datum/tgs_api/proc/ChatPrivateMessage(message, admin_only)
|
||||
/datum/tgs_api/proc/ChatPrivateMessage(message, datum/tgs_chat_user/user)
|
||||
return TGS_UNIMPLEMENTED
|
||||
|
||||
/*
|
||||
The MIT License
|
||||
|
||||
Copyright (c) 2017 Jordan Brown
|
||||
|
||||
Permission is hereby granted, free of charge,
|
||||
to any person obtaining a copy of this software and
|
||||
associated documentation files (the "Software"), to
|
||||
deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify,
|
||||
merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom
|
||||
the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice
|
||||
shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
/datum/tgs_api/proc/SecurityLevel()
|
||||
return TGS_UNIMPLEMENTED
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
/datum/tgs_version/New(raw_parameter)
|
||||
src.raw_parameter = raw_parameter
|
||||
deprefixed_parameter = replacetext(raw_parameter, "/tg/station 13 Server v", "")
|
||||
var/list/version_bits = splittext(deprefixed_parameter, ".")
|
||||
|
||||
suite = text2num(version_bits[1])
|
||||
if(version_bits.len > 1)
|
||||
minor = text2num(version_bits[2])
|
||||
if(version_bits.len > 2)
|
||||
patch = text2num(version_bits[3])
|
||||
if(version_bits.len == 4)
|
||||
deprecated_patch = text2num(version_bits[4])
|
||||
|
||||
/datum/tgs_version/proc/Valid(allow_wildcards = FALSE)
|
||||
if(suite == null)
|
||||
return FALSE
|
||||
if(allow_wildcards)
|
||||
return TRUE
|
||||
return !Wildcard()
|
||||
|
||||
/datum/tgs_version/Wildcard()
|
||||
return minor == null || patch == null
|
||||
|
||||
/datum/tgs_version/Equals(datum/tgs_version/other_version)
|
||||
if(!istype(other_version))
|
||||
return FALSE
|
||||
|
||||
return suite == other_version.suite && minor == other_version.minor && patch == other_version.patch && deprecated_patch == other_version.deprecated_patch
|
||||
@@ -1,6 +1,17 @@
|
||||
#include "core\_definitions.dm"
|
||||
#include "core\core.dm"
|
||||
#include "core\datum.dm"
|
||||
#include "core\default_event_handler.dm"
|
||||
#include "core\tgs_version.dm"
|
||||
|
||||
#ifdef TGS_V3_API
|
||||
#include "v3210\api.dm"
|
||||
#include "v3210\commands.dm"
|
||||
#endif
|
||||
|
||||
#include "v4\api.dm"
|
||||
#include "v4\commands.dm"
|
||||
|
||||
#include "v5\_defines.dm"
|
||||
#include "v5\api.dm"
|
||||
#include "v5\commands.dm"
|
||||
#include "v5\undef.dm"
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
# DMAPI V3
|
||||
|
||||
This DMAPI implements bridge using file output which TGS monitors for.
|
||||
|
||||
- [api.dm](./api.dm) contains the bulk of the API code.
|
||||
- [commands.dm](./commands.dm) contains functions relating to `/datum/tgs_chat_command`s.
|
||||
@@ -39,7 +39,7 @@
|
||||
var/warned_custom_commands = FALSE
|
||||
|
||||
/datum/tgs_api/v3210/ApiVersion()
|
||||
return "3.2.1.0"
|
||||
return new /datum/tgs_version("3.2.1.0")
|
||||
|
||||
/datum/tgs_api/v3210/proc/trim_left(text)
|
||||
for (var/i = 1 to length(text))
|
||||
@@ -56,7 +56,7 @@
|
||||
/datum/tgs_api/v3210/proc/file2list(filename)
|
||||
return splittext(trim_left(trim_right(file2text(filename))), "\n")
|
||||
|
||||
/datum/tgs_api/v3210/OnWorldNew(datum/tgs_event_handler/event_handler) //don't use event handling in this version
|
||||
/datum/tgs_api/v3210/OnWorldNew(minimum_required_security_level)
|
||||
. = FALSE
|
||||
|
||||
comms_key = world.params[SERVICE_WORLD_PARAM]
|
||||
@@ -76,7 +76,8 @@
|
||||
TGS_ERROR_LOG("This API version is only supported on Windows. Not running on Windows. Aborting initialization!")
|
||||
return
|
||||
ListServiceCustomCommands(TRUE)
|
||||
ExportService("[SERVICE_REQUEST_API_VERSION] [ApiVersion()]", TRUE)
|
||||
var/datum/tgs_version/api_version = ApiVersion()
|
||||
ExportService("[SERVICE_REQUEST_API_VERSION] [api_version.deprefixed_parameter]", TRUE)
|
||||
return TRUE
|
||||
|
||||
//nothing to do for v3
|
||||
@@ -166,11 +167,13 @@
|
||||
|
||||
/datum/tgs_api/v3210/Revision()
|
||||
if(!warned_revison)
|
||||
TGS_ERROR_LOG("Use of TgsRevision on [ApiVersion()] origin_commit only points to master!")
|
||||
var/datum/tgs_version/api_version = ApiVersion()
|
||||
TGS_ERROR_LOG("Use of TgsRevision on [api_version.deprefixed_parameter] origin_commit only points to master!")
|
||||
warned_revison = TRUE
|
||||
var/datum/tgs_revision_information/ri = new
|
||||
ri.commit = commit
|
||||
ri.origin_commit = originmastercommit
|
||||
return ri
|
||||
|
||||
/datum/tgs_api/v3210/EndProcess()
|
||||
sleep(world.tick_lag) //flush the buffers
|
||||
@@ -188,9 +191,12 @@
|
||||
/datum/tgs_api/v3210/ChatTargetedBroadcast(message, admin_only)
|
||||
ExportService("[admin_only ? SERVICE_REQUEST_IRC_ADMIN_CHANNEL_MESSAGE : SERVICE_REQUEST_IRC_BROADCAST] [message]")
|
||||
|
||||
/datum/tgs_api/v3210/ChatPrivateMessage(message, admin_only)
|
||||
/datum/tgs_api/v3210/ChatPrivateMessage(message, datum/tgs_chat_user/user)
|
||||
return TGS_UNIMPLEMENTED
|
||||
|
||||
/datum/tgs_api/v3210/SecurityLevel()
|
||||
return TGS_SECURITY_TRUSTED
|
||||
|
||||
#undef REBOOT_MODE_NORMAL
|
||||
#undef REBOOT_MODE_HARD
|
||||
#undef REBOOT_MODE_SHUTDOWN
|
||||
@@ -220,30 +226,3 @@
|
||||
#undef SERVICE_REQUEST_API_VERSION
|
||||
|
||||
#undef SERVICE_RETURN_SUCCESS
|
||||
|
||||
/*
|
||||
The MIT License
|
||||
|
||||
Copyright (c) 2017 Jordan Brown
|
||||
|
||||
Permission is hereby granted, free of charge,
|
||||
to any person obtaining a copy of this software and
|
||||
associated documentation files (the "Software"), to
|
||||
deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify,
|
||||
merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom
|
||||
the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice
|
||||
shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
TGS_ERROR_LOG("Custom command [command_name] can't be used as it is empty or contains illegal characters!")
|
||||
warned_command_names[command_name] = TRUE
|
||||
continue
|
||||
|
||||
|
||||
if(command_name_types[command_name])
|
||||
if(warnings_only)
|
||||
TGS_ERROR_LOG("Custom commands [command_name_types[command_name]] and [stc] have the same name, only [command_name_types[command_name]] will be available!")
|
||||
@@ -44,35 +44,3 @@
|
||||
user.friendly_name = sender
|
||||
user.mention = sender
|
||||
return stc.Run(user, params) || TRUE
|
||||
|
||||
/*
|
||||
|
||||
#undef SERVICE_JSON_PARAM_HELPTEXT
|
||||
#undef SERVICE_JSON_PARAM_ADMINONLY
|
||||
#undef SERVICE_JSON_PARAM_REQUIREDPARAMETERS
|
||||
|
||||
The MIT License
|
||||
|
||||
Copyright (c) 2017 Jordan Brown
|
||||
|
||||
Permission is hereby granted, free of charge,
|
||||
to any person obtaining a copy of this software and
|
||||
associated documentation files (the "Software"), to
|
||||
deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify,
|
||||
merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom
|
||||
the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice
|
||||
shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
# DMAPI V4
|
||||
|
||||
This DMAPI implements bridge requests using file output which TGS monitors for. It has a safe mode restriction.
|
||||
|
||||
- [api.dm](./api.dm) contains the bulk of the API code.
|
||||
- [commands.dm](./commands.dm) contains functions relating to `/datum/tgs_chat_command`s.
|
||||
@@ -0,0 +1,318 @@
|
||||
#define TGS4_PARAM_INFO_JSON "tgs_json"
|
||||
|
||||
#define TGS4_INTEROP_ACCESS_IDENTIFIER "tgs_tok"
|
||||
|
||||
#define TGS4_RESPONSE_SUCCESS "tgs_succ"
|
||||
|
||||
#define TGS4_TOPIC_CHANGE_PORT "tgs_port"
|
||||
#define TGS4_TOPIC_CHANGE_REBOOT_MODE "tgs_rmode"
|
||||
#define TGS4_TOPIC_CHAT_COMMAND "tgs_chat_comm"
|
||||
#define TGS4_TOPIC_EVENT "tgs_event"
|
||||
#define TGS4_TOPIC_INTEROP_RESPONSE "tgs_interop"
|
||||
|
||||
#define TGS4_COMM_NEW_PORT "tgs_new_port"
|
||||
#define TGS4_COMM_VALIDATE "tgs_validate"
|
||||
#define TGS4_COMM_SERVER_PRIMED "tgs_prime"
|
||||
#define TGS4_COMM_WORLD_REBOOT "tgs_reboot"
|
||||
#define TGS4_COMM_END_PROCESS "tgs_kill"
|
||||
#define TGS4_COMM_CHAT "tgs_chat_send"
|
||||
|
||||
#define TGS4_PARAMETER_COMMAND "tgs_com"
|
||||
#define TGS4_PARAMETER_DATA "tgs_data"
|
||||
|
||||
#define TGS4_PORT_CRITFAIL_MESSAGE " Must exit to let watchdog reboot..."
|
||||
|
||||
#define EXPORT_TIMEOUT_DS 200
|
||||
|
||||
/datum/tgs_api/v4
|
||||
var/access_identifier
|
||||
var/instance_name
|
||||
var/json_path
|
||||
var/chat_channels_json_path
|
||||
var/chat_commands_json_path
|
||||
var/server_commands_json_path
|
||||
var/reboot_mode = TGS_REBOOT_MODE_NORMAL
|
||||
var/security_level
|
||||
|
||||
var/requesting_new_port = FALSE
|
||||
|
||||
var/list/intercepted_message_queue
|
||||
|
||||
var/list/custom_commands
|
||||
|
||||
var/list/cached_test_merges
|
||||
var/datum/tgs_revision_information/cached_revision
|
||||
|
||||
var/export_lock = FALSE
|
||||
var/list/last_interop_response
|
||||
|
||||
/datum/tgs_api/v4/ApiVersion()
|
||||
return new /datum/tgs_version("4.0.0.0")
|
||||
|
||||
/datum/tgs_api/v4/OnWorldNew(minimum_required_security_level)
|
||||
if(minimum_required_security_level == TGS_SECURITY_ULTRASAFE)
|
||||
TGS_WARNING_LOG("V4 DMAPI requires safe security!")
|
||||
minimum_required_security_level = TGS_SECURITY_SAFE
|
||||
|
||||
json_path = world.params[TGS4_PARAM_INFO_JSON]
|
||||
if(!json_path)
|
||||
TGS_ERROR_LOG("Missing [TGS4_PARAM_INFO_JSON] world parameter!")
|
||||
return
|
||||
var/json_file = file2text(json_path)
|
||||
if(!json_file)
|
||||
TGS_ERROR_LOG("Missing specified json file: [json_path]")
|
||||
return
|
||||
var/cached_json = json_decode(json_file)
|
||||
if(!cached_json)
|
||||
TGS_ERROR_LOG("Failed to decode info json: [json_file]")
|
||||
return
|
||||
|
||||
access_identifier = cached_json["accessIdentifier"]
|
||||
server_commands_json_path = cached_json["serverCommandsJson"]
|
||||
|
||||
if(cached_json["apiValidateOnly"])
|
||||
TGS_INFO_LOG("Validating API and exiting...")
|
||||
Export(TGS4_COMM_VALIDATE, list(TGS4_PARAMETER_DATA = "[minimum_required_security_level]"))
|
||||
del(world)
|
||||
|
||||
security_level = cached_json["securityLevel"]
|
||||
chat_channels_json_path = cached_json["chatChannelsJson"]
|
||||
chat_commands_json_path = cached_json["chatCommandsJson"]
|
||||
instance_name = cached_json["instanceName"]
|
||||
|
||||
ListCustomCommands()
|
||||
|
||||
var/list/revisionData = cached_json["revision"]
|
||||
if(revisionData)
|
||||
cached_revision = new
|
||||
cached_revision.commit = revisionData["commitSha"]
|
||||
cached_revision.origin_commit = revisionData["originCommitSha"]
|
||||
|
||||
cached_test_merges = list()
|
||||
var/list/json = cached_json["testMerges"]
|
||||
for(var/entry in json)
|
||||
var/datum/tgs_revision_information/test_merge/tm = new
|
||||
tm.time_merged = text2num(entry["timeMerged"])
|
||||
|
||||
var/list/revInfo = entry["revision"]
|
||||
if(revInfo)
|
||||
tm.commit = revInfo["commitSha"]
|
||||
tm.origin_commit = revInfo["originCommitSha"]
|
||||
|
||||
tm.title = entry["titleAtMerge"]
|
||||
tm.body = entry["bodyAtMerge"]
|
||||
tm.url = entry["url"]
|
||||
tm.author = entry["author"]
|
||||
tm.number = entry["number"]
|
||||
tm.pull_request_commit = entry["pullRequestRevision"]
|
||||
tm.comment = entry["comment"]
|
||||
|
||||
cached_test_merges += tm
|
||||
|
||||
return TRUE
|
||||
|
||||
/datum/tgs_api/v4/OnInitializationComplete()
|
||||
Export(TGS4_COMM_SERVER_PRIMED)
|
||||
|
||||
var/tgs4_secret_sleep_offline_sauce = 29051994
|
||||
var/old_sleep_offline = world.sleep_offline
|
||||
world.sleep_offline = tgs4_secret_sleep_offline_sauce
|
||||
sleep(1)
|
||||
if(world.sleep_offline == tgs4_secret_sleep_offline_sauce) //if not someone changed it
|
||||
world.sleep_offline = old_sleep_offline
|
||||
else
|
||||
TGS_WARNING_LOG("world.sleep_offline unexpectedly changed!")
|
||||
|
||||
/datum/tgs_api/v4/OnTopic(T)
|
||||
var/list/params = params2list(T)
|
||||
var/their_sCK = params[TGS4_INTEROP_ACCESS_IDENTIFIER]
|
||||
if(!their_sCK)
|
||||
return FALSE //continue world/Topic
|
||||
|
||||
if(their_sCK != access_identifier)
|
||||
return "Invalid comms key!";
|
||||
|
||||
var/command = params[TGS4_PARAMETER_COMMAND]
|
||||
if(!command)
|
||||
return "No command!"
|
||||
|
||||
. = TGS4_RESPONSE_SUCCESS
|
||||
|
||||
switch(command)
|
||||
if(TGS4_TOPIC_CHAT_COMMAND)
|
||||
var/result = HandleCustomCommand(params[TGS4_PARAMETER_DATA])
|
||||
if(result == null)
|
||||
result = "Error running chat command!"
|
||||
return result
|
||||
if(TGS4_TOPIC_EVENT)
|
||||
intercepted_message_queue = list()
|
||||
var/list/event_notification = json_decode(params[TGS4_PARAMETER_DATA])
|
||||
var/list/event_parameters = event_notification["Parameters"]
|
||||
|
||||
var/list/event_call = list(event_notification["Type"])
|
||||
if(event_parameters)
|
||||
event_call += event_parameters
|
||||
|
||||
if(event_handler != null)
|
||||
event_handler.HandleEvent(arglist(event_call))
|
||||
|
||||
. = json_encode(intercepted_message_queue)
|
||||
intercepted_message_queue = null
|
||||
return
|
||||
if(TGS4_TOPIC_INTEROP_RESPONSE)
|
||||
last_interop_response = json_decode(params[TGS4_PARAMETER_DATA])
|
||||
return
|
||||
if(TGS4_TOPIC_CHANGE_PORT)
|
||||
var/new_port = text2num(params[TGS4_PARAMETER_DATA])
|
||||
if (!(new_port > 0))
|
||||
return "Invalid port: [new_port]"
|
||||
|
||||
//the topic still completes, miraculously
|
||||
//I honestly didn't believe byond could do it
|
||||
if(event_handler != null)
|
||||
event_handler.HandleEvent(TGS_EVENT_PORT_SWAP, new_port)
|
||||
if(!world.OpenPort(new_port))
|
||||
return "Port change failed!"
|
||||
return
|
||||
if(TGS4_TOPIC_CHANGE_REBOOT_MODE)
|
||||
var/new_reboot_mode = text2num(params[TGS4_PARAMETER_DATA])
|
||||
if(event_handler != null)
|
||||
event_handler.HandleEvent(TGS_EVENT_REBOOT_MODE_CHANGE, reboot_mode, new_reboot_mode)
|
||||
reboot_mode = new_reboot_mode
|
||||
return
|
||||
|
||||
return "Unknown command: [command]"
|
||||
|
||||
/datum/tgs_api/v4/proc/Export(command, list/data, override_requesting_new_port = FALSE)
|
||||
if(!data)
|
||||
data = list()
|
||||
data[TGS4_PARAMETER_COMMAND] = command
|
||||
var/json = json_encode(data)
|
||||
|
||||
while(requesting_new_port && !override_requesting_new_port)
|
||||
sleep(1)
|
||||
|
||||
//we need some port open at this point to facilitate return communication
|
||||
if(!world.port)
|
||||
requesting_new_port = TRUE
|
||||
if(!world.OpenPort(0)) //open any port
|
||||
TGS_ERROR_LOG("Unable to open random port to retrieve new port![TGS4_PORT_CRITFAIL_MESSAGE]")
|
||||
del(world)
|
||||
|
||||
//request a new port
|
||||
export_lock = FALSE
|
||||
var/list/new_port_json = Export(TGS4_COMM_NEW_PORT, list(TGS4_PARAMETER_DATA = "[world.port]"), TRUE) //stringify this on purpose
|
||||
|
||||
if(!new_port_json)
|
||||
TGS_ERROR_LOG("No new port response from server![TGS4_PORT_CRITFAIL_MESSAGE]")
|
||||
del(world)
|
||||
|
||||
var/new_port = new_port_json[TGS4_PARAMETER_DATA]
|
||||
if(!isnum(new_port) || new_port <= 0)
|
||||
TGS_ERROR_LOG("Malformed new port json ([json_encode(new_port_json)])![TGS4_PORT_CRITFAIL_MESSAGE]")
|
||||
del(world)
|
||||
|
||||
if(new_port != world.port && !world.OpenPort(new_port))
|
||||
TGS_ERROR_LOG("Unable to open port [new_port]![TGS4_PORT_CRITFAIL_MESSAGE]")
|
||||
del(world)
|
||||
requesting_new_port = FALSE
|
||||
|
||||
while(export_lock)
|
||||
sleep(1)
|
||||
export_lock = TRUE
|
||||
|
||||
last_interop_response = null
|
||||
fdel(server_commands_json_path)
|
||||
text2file(json, server_commands_json_path)
|
||||
|
||||
for(var/I = 0; I < EXPORT_TIMEOUT_DS && !last_interop_response; ++I)
|
||||
sleep(1)
|
||||
|
||||
if(!last_interop_response)
|
||||
TGS_ERROR_LOG("Failed to get export result for: [json]")
|
||||
else
|
||||
. = last_interop_response
|
||||
|
||||
export_lock = FALSE
|
||||
|
||||
/datum/tgs_api/v4/OnReboot()
|
||||
var/list/result = Export(TGS4_COMM_WORLD_REBOOT)
|
||||
if(!result)
|
||||
return
|
||||
|
||||
//okay so the standard TGS4 proceedure is: right before rebooting change the port to whatever was sent to us in the above json's data parameter
|
||||
|
||||
var/port = result[TGS4_PARAMETER_DATA]
|
||||
if(!isnum(port))
|
||||
return //this is valid, server may just want use to reboot
|
||||
|
||||
if(port == 0)
|
||||
//to byond 0 means any port and "none" means close vOv
|
||||
port = "none"
|
||||
|
||||
if(!world.OpenPort(port))
|
||||
TGS_ERROR_LOG("Unable to set port to [port]!")
|
||||
|
||||
/datum/tgs_api/v4/InstanceName()
|
||||
return instance_name
|
||||
|
||||
/datum/tgs_api/v4/TestMerges()
|
||||
return cached_test_merges
|
||||
|
||||
/datum/tgs_api/v4/EndProcess()
|
||||
Export(TGS4_COMM_END_PROCESS)
|
||||
|
||||
/datum/tgs_api/v4/Revision()
|
||||
return cached_revision
|
||||
|
||||
/datum/tgs_api/v4/ChatBroadcast(message, list/channels)
|
||||
var/list/ids
|
||||
if(length(channels))
|
||||
ids = list()
|
||||
for(var/I in channels)
|
||||
var/datum/tgs_chat_channel/channel = I
|
||||
ids += channel.id
|
||||
message = list("message" = message, "channelIds" = ids)
|
||||
if(intercepted_message_queue)
|
||||
intercepted_message_queue += list(message)
|
||||
else
|
||||
Export(TGS4_COMM_CHAT, message)
|
||||
|
||||
/datum/tgs_api/v4/ChatTargetedBroadcast(message, 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 = list("message" = message, "channelIds" = channels)
|
||||
if(intercepted_message_queue)
|
||||
intercepted_message_queue += list(message)
|
||||
else
|
||||
Export(TGS4_COMM_CHAT, message)
|
||||
|
||||
/datum/tgs_api/v4/ChatPrivateMessage(message, datum/tgs_chat_user/user)
|
||||
message = list("message" = message, "channelIds" = list(user.channel.id))
|
||||
if(intercepted_message_queue)
|
||||
intercepted_message_queue += list(message)
|
||||
else
|
||||
Export(TGS4_COMM_CHAT, message)
|
||||
|
||||
/datum/tgs_api/v4/ChatChannelInfo()
|
||||
. = list()
|
||||
//no caching cause tgs may change this
|
||||
var/list/json = json_decode(file2text(chat_channels_json_path))
|
||||
for(var/I in json)
|
||||
. += DecodeChannel(I)
|
||||
|
||||
/datum/tgs_api/v4/proc/DecodeChannel(channel_json)
|
||||
var/datum/tgs_chat_channel/channel = new
|
||||
channel.id = channel_json["id"]
|
||||
channel.friendly_name = channel_json["friendlyName"]
|
||||
channel.connection_name = channel_json["connectionName"]
|
||||
channel.is_admin_channel = channel_json["isAdminChannel"]
|
||||
channel.is_private_channel = channel_json["isPrivateChannel"]
|
||||
channel.custom_tag = channel_json["tag"]
|
||||
return channel
|
||||
|
||||
/datum/tgs_api/v4/SecurityLevel()
|
||||
return security_level
|
||||
@@ -0,0 +1,41 @@
|
||||
/datum/tgs_api/v4/proc/ListCustomCommands()
|
||||
var/results = list()
|
||||
custom_commands = list()
|
||||
for(var/I in typesof(/datum/tgs_chat_command) - /datum/tgs_chat_command)
|
||||
var/datum/tgs_chat_command/stc = new I
|
||||
var/command_name = stc.name
|
||||
if(!command_name || findtext(command_name, " ") || findtext(command_name, "'") || findtext(command_name, "\""))
|
||||
TGS_ERROR_LOG("Custom command [command_name] ([I]) can't be used as it is empty or contains illegal characters!")
|
||||
continue
|
||||
|
||||
if(results[command_name])
|
||||
var/datum/other = custom_commands[command_name]
|
||||
TGS_ERROR_LOG("Custom commands [other.type] and [I] have the same name (\"[command_name]\"), only [other.type] will be available!")
|
||||
continue
|
||||
results += list(list("name" = command_name, "help_text" = stc.help_text, "admin_only" = stc.admin_only))
|
||||
custom_commands[command_name] = stc
|
||||
|
||||
var/commands_file = chat_commands_json_path
|
||||
if(!commands_file)
|
||||
return
|
||||
text2file(json_encode(results), commands_file)
|
||||
|
||||
/datum/tgs_api/v4/proc/HandleCustomCommand(command_json)
|
||||
var/list/data = json_decode(command_json)
|
||||
var/command = data["command"]
|
||||
var/user = data["user"]
|
||||
var/params = data["params"]
|
||||
|
||||
var/datum/tgs_chat_user/u = new
|
||||
u.id = user["id"]
|
||||
u.friendly_name = user["friendlyName"]
|
||||
u.mention = user["mention"]
|
||||
u.channel = DecodeChannel(user["channel"])
|
||||
|
||||
var/datum/tgs_chat_command/sc = custom_commands[command]
|
||||
if(sc)
|
||||
var/result = sc.Run(u, params)
|
||||
if(result == null)
|
||||
result = ""
|
||||
return result
|
||||
return "Unknown command: [command]!"
|
||||
@@ -0,0 +1,98 @@
|
||||
#define DMAPI5_PARAM_SERVER_PORT "tgs_port"
|
||||
#define DMAPI5_PARAM_ACCESS_IDENTIFIER "tgs_key"
|
||||
|
||||
#define DMAPI5_BRIDGE_DATA "data"
|
||||
#define DMAPI5_TOPIC_DATA "tgs_data"
|
||||
|
||||
#define DMAPI5_BRIDGE_COMMAND_PORT_UPDATE 0
|
||||
#define DMAPI5_BRIDGE_COMMAND_STARTUP 1
|
||||
#define DMAPI5_BRIDGE_COMMAND_PRIME 2
|
||||
#define DMAPI5_BRIDGE_COMMAND_REBOOT 3
|
||||
#define DMAPI5_BRIDGE_COMMAND_KILL 4
|
||||
#define DMAPI5_BRIDGE_COMMAND_CHAT_SEND 5
|
||||
|
||||
#define DMAPI5_PARAMETER_ACCESS_IDENTIFIER "accessIdentifier"
|
||||
#define DMAPI5_PARAMETER_CUSTOM_COMMANDS "customCommands"
|
||||
|
||||
#define DMAPI5_RESPONSE_ERROR_MESSAGE "errorMessage"
|
||||
|
||||
#define DMAPI5_BRIDGE_PARAMETER_COMMAND_TYPE "commandType"
|
||||
#define DMAPI5_BRIDGE_PARAMETER_CURRENT_PORT "currentPort"
|
||||
#define DMAPI5_BRIDGE_PARAMETER_VERSION "version"
|
||||
#define DMAPI5_BRIDGE_PARAMETER_CHAT_MESSAGE "chatMessage"
|
||||
#define DMAPI5_BRIDGE_PARAMETER_MINIMUM_SECURITY_LEVEL "minimumSecurityLevel"
|
||||
|
||||
#define DMAPI5_BRIDGE_RESPONSE_NEW_PORT "newPort"
|
||||
#define DMAPI5_BRIDGE_RESPONSE_RUNTIME_INFORMATION "runtimeInformation"
|
||||
|
||||
#define DMAPI5_CHAT_MESSAGE_TEXT "text"
|
||||
#define DMAPI5_CHAT_MESSAGE_CHANNEL_IDS "channelIds"
|
||||
|
||||
#define DMAPI5_RUNTIME_INFORMATION_ACCESS_IDENTIFIER "accessIdentifier"
|
||||
#define DMAPI5_RUNTIME_INFORMATION_SERVER_VERSION "serverVersion"
|
||||
#define DMAPI5_RUNTIME_INFORMATION_SERVER_PORT "serverPort"
|
||||
#define DMAPI5_RUNTIME_INFORMATION_API_VALIDATE_ONLY "apiValidateOnly"
|
||||
#define DMAPI5_RUNTIME_INFORMATION_INSTANCE_NAME "instanceName"
|
||||
#define DMAPI5_RUNTIME_INFORMATION_REVISION "revision"
|
||||
#define DMAPI5_RUNTIME_INFORMATION_TEST_MERGES "testMerges"
|
||||
#define DMAPI5_RUNTIME_INFORMATION_SECURITY_LEVEL "securityLevel"
|
||||
|
||||
#define DMAPI5_CHAT_UPDATE_CHANNELS "channels"
|
||||
|
||||
#define DMAPI5_TEST_MERGE_TIME_MERGED "timeMerged"
|
||||
#define DMAPI5_TEST_MERGE_REVISION "revision"
|
||||
#define DMAPI5_TEST_MERGE_TITLE_AT_MERGE "titleAtMerge"
|
||||
#define DMAPI5_TEST_MERGE_BODY_AT_MERGE "bodyAtMerge"
|
||||
#define DMAPI5_TEST_MERGE_URL "url"
|
||||
#define DMAPI5_TEST_MERGE_AUTHOR "author"
|
||||
#define DMAPI5_TEST_MERGE_NUMBER "number"
|
||||
#define DMAPI5_TEST_MERGE_PULL_REQUEST_REVISION "pullRequestRevision"
|
||||
#define DMAPI5_TEST_MERGE_COMMENT "comment"
|
||||
|
||||
#define DMAPI5_CHAT_COMMAND_NAME "name"
|
||||
#define DMAPI5_CHAT_COMMAND_PARAMS "params"
|
||||
#define DMAPI5_CHAT_COMMAND_USER "user"
|
||||
|
||||
#define DMAPI5_EVENT_NOTIFICATION_TYPE "type"
|
||||
#define DMAPI5_EVENT_NOTIFICATION_PARAMETERS "parameters"
|
||||
|
||||
#define DMAPI5_TOPIC_COMMAND_CHAT_COMMAND 0
|
||||
#define DMAPI5_TOPIC_COMMAND_EVENT_NOTIFICATION 1
|
||||
#define DMAPI5_TOPIC_COMMAND_CHANGE_PORT 2
|
||||
#define DMAPI5_TOPIC_COMMAND_CHANGE_REBOOT_STATE 3
|
||||
#define DMAPI5_TOPIC_COMMAND_INSTANCE_RENAMED 4
|
||||
#define DMAPI5_TOPIC_COMMAND_CHAT_CHANNELS_UPDATE 5
|
||||
#define DMAPI5_TOPIC_COMMAND_SERVER_PORT_UPDATE 6
|
||||
#define DMAPI5_TOPIC_COMMAND_HEARTBEAT 7
|
||||
#define DMAPI5_TOPIC_COMMAND_WATCHDOG_REATTACH 8
|
||||
|
||||
#define DMAPI5_TOPIC_PARAMETER_COMMAND_TYPE "commandType"
|
||||
#define DMAPI5_TOPIC_PARAMETER_CHAT_COMMAND "chatCommand"
|
||||
#define DMAPI5_TOPIC_PARAMETER_EVENT_NOTIFICATION "eventNotification"
|
||||
#define DMAPI5_TOPIC_PARAMETER_NEW_PORT "newPort"
|
||||
#define DMAPI5_TOPIC_PARAMETER_NEW_REBOOT_STATE "newRebootState"
|
||||
#define DMAPI5_TOPIC_PARAMETER_NEW_INSTANCE_NAME "newInstanceName"
|
||||
#define DMAPI5_TOPIC_PARAMETER_CHAT_UPDATE "chatUpdate"
|
||||
#define DMAPI5_TOPIC_PARAMETER_NEW_SERVER_VERSION "newServerVersion"
|
||||
|
||||
#define DMAPI5_TOPIC_RESPONSE_COMMAND_RESPONSE_MESSAGE "commandResponseMessage"
|
||||
#define DMAPI5_TOPIC_RESPONSE_CHAT_RESPONSES "chatResponses"
|
||||
|
||||
#define DMAPI5_REVISION_INFORMATION_COMMIT_SHA "commitSha"
|
||||
#define DMAPI5_REVISION_INFORMATION_ORIGIN_COMMIT_SHA "originCommitSha"
|
||||
|
||||
#define DMAPI5_CHAT_USER_ID "id"
|
||||
#define DMAPI5_CHAT_USER_FRIENDLY_NAME "friendlyName"
|
||||
#define DMAPI5_CHAT_USER_MENTION "mention"
|
||||
#define DMAPI5_CHAT_USER_CHANNEL "channel"
|
||||
|
||||
#define DMAPI5_CHAT_CHANNEL_ID "id"
|
||||
#define DMAPI5_CHAT_CHANNEL_FRIENDLY_NAME "friendlyName"
|
||||
#define DMAPI5_CHAT_CHANNEL_CONNECTION_NAME "connectionName"
|
||||
#define DMAPI5_CHAT_CHANNEL_IS_ADMIN_CHANNEL "isAdminChannel"
|
||||
#define DMAPI5_CHAT_CHANNEL_IS_PRIVATE_CHANNEL "isPrivateChannel"
|
||||
#define DMAPI5_CHAT_CHANNEL_TAG "tag"
|
||||
|
||||
#define DMAPI5_CUSTOM_CHAT_COMMAND_NAME "name"
|
||||
#define DMAPI5_CUSTOM_CHAT_COMMAND_HELP_TEXT "helpText"
|
||||
#define DMAPI5_CUSTOM_CHAT_COMMAND_ADMIN_ONLY "adminOnly"
|
||||
@@ -0,0 +1,357 @@
|
||||
/datum/tgs_api/v5
|
||||
var/server_port
|
||||
var/access_identifier
|
||||
|
||||
var/instance_name
|
||||
var/security_level
|
||||
|
||||
var/reboot_mode = TGS_REBOOT_MODE_NORMAL
|
||||
|
||||
var/list/intercepted_message_queue
|
||||
|
||||
var/list/custom_commands
|
||||
|
||||
var/list/test_merges
|
||||
var/datum/tgs_revision_information/revision
|
||||
var/list/chat_channels
|
||||
|
||||
/datum/tgs_api/v5/ApiVersion()
|
||||
return new /datum/tgs_version("5.2.2")
|
||||
|
||||
/datum/tgs_api/v5/OnWorldNew(minimum_required_security_level)
|
||||
server_port = world.params[DMAPI5_PARAM_SERVER_PORT]
|
||||
access_identifier = world.params[DMAPI5_PARAM_ACCESS_IDENTIFIER]
|
||||
|
||||
var/datum/tgs_version/api_version = ApiVersion()
|
||||
version = null
|
||||
var/list/bridge_response = Bridge(DMAPI5_BRIDGE_COMMAND_STARTUP, list(DMAPI5_BRIDGE_PARAMETER_MINIMUM_SECURITY_LEVEL = minimum_required_security_level, DMAPI5_BRIDGE_PARAMETER_VERSION = api_version.raw_parameter, DMAPI5_PARAMETER_CUSTOM_COMMANDS = ListCustomCommands()))
|
||||
if(!istype(bridge_response))
|
||||
TGS_ERROR_LOG("Failed initial bridge request!")
|
||||
return FALSE
|
||||
|
||||
var/list/runtime_information = bridge_response[DMAPI5_BRIDGE_RESPONSE_RUNTIME_INFORMATION]
|
||||
if(!istype(runtime_information))
|
||||
TGS_ERROR_LOG("Failed to decode runtime information from bridge response: [json_encode(bridge_response)]!")
|
||||
return FALSE
|
||||
|
||||
if(runtime_information[DMAPI5_RUNTIME_INFORMATION_API_VALIDATE_ONLY])
|
||||
TGS_INFO_LOG("DMAPI validation, exiting...")
|
||||
del(world)
|
||||
|
||||
version = new /datum/tgs_version(runtime_information[DMAPI5_RUNTIME_INFORMATION_SERVER_VERSION])
|
||||
security_level = runtime_information[DMAPI5_RUNTIME_INFORMATION_SECURITY_LEVEL]
|
||||
instance_name = runtime_information[DMAPI5_RUNTIME_INFORMATION_INSTANCE_NAME]
|
||||
|
||||
var/list/revisionData = runtime_information[DMAPI5_RUNTIME_INFORMATION_REVISION]
|
||||
if(istype(revisionData))
|
||||
revision = new
|
||||
revision.commit = revisionData[DMAPI5_REVISION_INFORMATION_COMMIT_SHA]
|
||||
revision.origin_commit = revisionData[DMAPI5_REVISION_INFORMATION_ORIGIN_COMMIT_SHA]
|
||||
else
|
||||
TGS_ERROR_LOG("Failed to decode [DMAPI5_RUNTIME_INFORMATION_REVISION] from runtime information!")
|
||||
|
||||
test_merges = list()
|
||||
var/list/test_merge_json = runtime_information[DMAPI5_RUNTIME_INFORMATION_TEST_MERGES]
|
||||
if(istype(test_merge_json))
|
||||
for(var/entry in test_merge_json)
|
||||
var/datum/tgs_revision_information/test_merge/tm = new
|
||||
tm.number = entry[DMAPI5_TEST_MERGE_NUMBER]
|
||||
|
||||
var/list/revInfo = entry[DMAPI5_TEST_MERGE_REVISION]
|
||||
if(revInfo)
|
||||
tm.commit = revisionData[DMAPI5_REVISION_INFORMATION_COMMIT_SHA]
|
||||
tm.origin_commit = revisionData[DMAPI5_REVISION_INFORMATION_ORIGIN_COMMIT_SHA]
|
||||
else
|
||||
TGS_WARNING_LOG("Failed to decode [DMAPI5_TEST_MERGE_REVISION] from test merge #[tm.number]!")
|
||||
|
||||
tm.time_merged = text2num(entry[DMAPI5_TEST_MERGE_TIME_MERGED])
|
||||
tm.title = entry[DMAPI5_TEST_MERGE_TITLE_AT_MERGE]
|
||||
tm.body = entry[DMAPI5_TEST_MERGE_BODY_AT_MERGE]
|
||||
tm.url = entry[DMAPI5_TEST_MERGE_URL]
|
||||
tm.author = entry[DMAPI5_TEST_MERGE_AUTHOR]
|
||||
tm.pull_request_commit = entry[DMAPI5_TEST_MERGE_PULL_REQUEST_REVISION]
|
||||
tm.comment = entry[DMAPI5_TEST_MERGE_COMMENT]
|
||||
|
||||
test_merges += tm
|
||||
else
|
||||
TGS_WARNING_LOG("Failed to decode [DMAPI5_RUNTIME_INFORMATION_TEST_MERGES] from runtime information!")
|
||||
|
||||
chat_channels = list()
|
||||
DecodeChannels(runtime_information)
|
||||
|
||||
return TRUE
|
||||
|
||||
/datum/tgs_api/v5/proc/RequireInitialBridgeResponse()
|
||||
while(!version)
|
||||
sleep(1)
|
||||
|
||||
/datum/tgs_api/v5/OnInitializationComplete()
|
||||
Bridge(DMAPI5_BRIDGE_COMMAND_PRIME)
|
||||
|
||||
var/tgs4_secret_sleep_offline_sauce = 29051994
|
||||
var/old_sleep_offline = world.sleep_offline
|
||||
world.sleep_offline = tgs4_secret_sleep_offline_sauce
|
||||
sleep(1)
|
||||
if(world.sleep_offline == tgs4_secret_sleep_offline_sauce) //if not someone changed it
|
||||
world.sleep_offline = old_sleep_offline
|
||||
else
|
||||
TGS_WARNING_LOG("world.sleep_offline unexpectedly changed!")
|
||||
|
||||
/datum/tgs_api/v5/proc/TopicResponse(error_message = null)
|
||||
var/list/response = list()
|
||||
response[DMAPI5_RESPONSE_ERROR_MESSAGE] = error_message
|
||||
|
||||
return json_encode(response)
|
||||
|
||||
/datum/tgs_api/v5/OnTopic(T)
|
||||
var/list/params = params2list(T)
|
||||
var/json = params[DMAPI5_TOPIC_DATA]
|
||||
if(!json)
|
||||
return FALSE //continue world/Topic
|
||||
|
||||
var/list/topic_parameters = json_decode(json)
|
||||
if(!topic_parameters)
|
||||
return TopicResponse("Invalid topic parameters json!");
|
||||
|
||||
var/their_sCK = topic_parameters[DMAPI5_PARAMETER_ACCESS_IDENTIFIER]
|
||||
if(their_sCK != access_identifier)
|
||||
return TopicResponse("Failed to decode [DMAPI5_PARAMETER_ACCESS_IDENTIFIER] from: [json]!");
|
||||
|
||||
var/command = topic_parameters[DMAPI5_TOPIC_PARAMETER_COMMAND_TYPE]
|
||||
if(!isnum(command))
|
||||
return TopicResponse("Failed to decode [DMAPI5_TOPIC_PARAMETER_COMMAND_TYPE] from: [json]!")
|
||||
|
||||
switch(command)
|
||||
if(DMAPI5_TOPIC_COMMAND_CHAT_COMMAND)
|
||||
var/result = HandleCustomCommand(topic_parameters[DMAPI5_TOPIC_PARAMETER_CHAT_COMMAND])
|
||||
if(!result)
|
||||
result = TopicResponse("Error running chat command!")
|
||||
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]!")
|
||||
|
||||
var/event_type = event_notification[DMAPI5_EVENT_NOTIFICATION_TYPE]
|
||||
if(!isnum(event_type))
|
||||
return TopicResponse("Invalid or missing [DMAPI5_EVENT_NOTIFICATION_TYPE]!")
|
||||
|
||||
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]!")
|
||||
|
||||
var/list/event_call = list(event_type)
|
||||
if(event_parameters)
|
||||
event_call += event_parameters
|
||||
|
||||
if(event_handler != null)
|
||||
event_handler.HandleEvent(arglist(event_call))
|
||||
|
||||
var/list/response = list()
|
||||
response[DMAPI5_TOPIC_RESPONSE_CHAT_RESPONSES] = intercepted_message_queue
|
||||
intercepted_message_queue = null
|
||||
return json_encode(response)
|
||||
if(DMAPI5_TOPIC_COMMAND_CHANGE_PORT)
|
||||
var/new_port = topic_parameters[DMAPI5_TOPIC_PARAMETER_NEW_PORT]
|
||||
if (!isnum(new_port) || !(new_port > 0))
|
||||
return TopicResponse("Invalid or missing [DMAPI5_TOPIC_PARAMETER_NEW_PORT]]")
|
||||
|
||||
if(event_handler != null)
|
||||
event_handler.HandleEvent(TGS_EVENT_PORT_SWAP, new_port)
|
||||
|
||||
//the topic still completes, miraculously
|
||||
//I honestly didn't believe byond could do it without exploding
|
||||
if(!world.OpenPort(new_port))
|
||||
return TopicResponse("Port change failed!")
|
||||
|
||||
return TopicResponse()
|
||||
if(DMAPI5_TOPIC_COMMAND_CHANGE_REBOOT_STATE)
|
||||
var/new_reboot_mode = topic_parameters[DMAPI5_TOPIC_PARAMETER_NEW_REBOOT_STATE]
|
||||
if(!isnum(new_reboot_mode))
|
||||
return TopicResponse("Invalid or missing [DMAPI5_TOPIC_PARAMETER_NEW_REBOOT_STATE]!")
|
||||
|
||||
if(event_handler != null)
|
||||
event_handler.HandleEvent(TGS_EVENT_REBOOT_MODE_CHANGE, reboot_mode, new_reboot_mode)
|
||||
|
||||
reboot_mode = new_reboot_mode
|
||||
return TopicResponse()
|
||||
if(DMAPI5_TOPIC_COMMAND_INSTANCE_RENAMED)
|
||||
var/new_instance_name = topic_parameters[DMAPI5_TOPIC_PARAMETER_NEW_INSTANCE_NAME]
|
||||
if(!istext(new_instance_name))
|
||||
return TopicResponse("Invalid or missing [DMAPI5_TOPIC_PARAMETER_NEW_INSTANCE_NAME]!")
|
||||
|
||||
if(event_handler != null)
|
||||
event_handler.HandleEvent(TGS_EVENT_INSTANCE_RENAMED, new_instance_name)
|
||||
|
||||
instance_name = new_instance_name
|
||||
return TopicResponse()
|
||||
if(DMAPI5_TOPIC_COMMAND_CHAT_CHANNELS_UPDATE)
|
||||
var/list/chat_update_json = topic_parameters[DMAPI5_TOPIC_PARAMETER_CHAT_UPDATE]
|
||||
if(!istype(chat_update_json))
|
||||
return TopicResponse("Invalid or missing [DMAPI5_TOPIC_PARAMETER_CHAT_UPDATE]!")
|
||||
|
||||
DecodeChannels(chat_update_json)
|
||||
return TopicResponse()
|
||||
if(DMAPI5_TOPIC_COMMAND_SERVER_PORT_UPDATE)
|
||||
var/new_port = topic_parameters[DMAPI5_TOPIC_PARAMETER_NEW_PORT]
|
||||
if (!isnum(new_port) || !(new_port > 0))
|
||||
return TopicResponse("Invalid or missing [DMAPI5_TOPIC_PARAMETER_NEW_PORT]]")
|
||||
|
||||
server_port = new_port
|
||||
return TopicResponse()
|
||||
if(DMAPI5_TOPIC_COMMAND_HEARTBEAT)
|
||||
return TopicResponse()
|
||||
if(DMAPI5_TOPIC_COMMAND_WATCHDOG_REATTACH)
|
||||
var/new_port = topic_parameters[DMAPI5_TOPIC_PARAMETER_NEW_PORT]
|
||||
var/error_message = null
|
||||
if (new_port != null)
|
||||
if (!isnum(new_port) || !(new_port > 0))
|
||||
error_message = "Invalid [DMAPI5_TOPIC_PARAMETER_NEW_PORT]]"
|
||||
else
|
||||
server_port = new_port
|
||||
|
||||
var/new_version_string = topic_parameters[DMAPI5_TOPIC_PARAMETER_NEW_SERVER_VERSION]
|
||||
if (!istext(new_version_string))
|
||||
if(error_message != null)
|
||||
error_message += ", "
|
||||
error_message += "Invalid or missing [DMAPI5_TOPIC_PARAMETER_NEW_SERVER_VERSION]]"
|
||||
else
|
||||
var/datum/tgs_version/new_version = new(new_version_string)
|
||||
if (event_handler)
|
||||
event_handler.HandleEvent(TGS_EVENT_WATCHDOG_REATTACH, new_version)
|
||||
|
||||
version = new_version
|
||||
|
||||
return json_encode(list(DMAPI5_RESPONSE_ERROR_MESSAGE = error_message, DMAPI5_PARAMETER_CUSTOM_COMMANDS = ListCustomCommands()))
|
||||
|
||||
return TopicResponse("Unknown command: [command]")
|
||||
|
||||
/datum/tgs_api/v5/proc/Bridge(command, list/data)
|
||||
if(!data)
|
||||
data = list()
|
||||
|
||||
data[DMAPI5_BRIDGE_PARAMETER_COMMAND_TYPE] = command
|
||||
data[DMAPI5_PARAMETER_ACCESS_IDENTIFIER] = access_identifier
|
||||
|
||||
var/json = json_encode(data)
|
||||
var/encoded_json = url_encode(json)
|
||||
|
||||
// This is an infinite sleep until we get a response
|
||||
var/export_response = world.Export("http://127.0.0.1:[server_port]/Bridge?[DMAPI5_BRIDGE_DATA]=[encoded_json]")
|
||||
if(!export_response)
|
||||
TGS_ERROR_LOG("Failed export request: [json]")
|
||||
return
|
||||
|
||||
var/response_json = file2text(export_response["CONTENT"])
|
||||
if(!response_json)
|
||||
TGS_ERROR_LOG("Failed export request, missing content!")
|
||||
return
|
||||
|
||||
var/list/bridge_response = json_decode(response_json)
|
||||
if(!bridge_response)
|
||||
TGS_ERROR_LOG("Failed export request, bad json: [response_json]")
|
||||
return
|
||||
|
||||
var/error = bridge_response[DMAPI5_RESPONSE_ERROR_MESSAGE]
|
||||
if(error)
|
||||
TGS_ERROR_LOG("Failed export request, bad request: [error]")
|
||||
return
|
||||
|
||||
return bridge_response
|
||||
|
||||
/datum/tgs_api/v5/OnReboot()
|
||||
var/list/result = Bridge(DMAPI5_BRIDGE_COMMAND_REBOOT)
|
||||
if(!result)
|
||||
return
|
||||
|
||||
//okay so the standard TGS4 proceedure is: right before rebooting change the port to whatever was sent to us in the above json's data parameter
|
||||
|
||||
var/port = result[DMAPI5_BRIDGE_RESPONSE_NEW_PORT]
|
||||
if(!isnum(port))
|
||||
return //this is valid, server may just want use to reboot
|
||||
|
||||
if(port == 0)
|
||||
//to byond 0 means any port and "none" means close vOv
|
||||
port = "none"
|
||||
|
||||
if(!world.OpenPort(port))
|
||||
TGS_ERROR_LOG("Unable to set port to [port]!")
|
||||
|
||||
/datum/tgs_api/v5/InstanceName()
|
||||
RequireInitialBridgeResponse()
|
||||
return instance_name
|
||||
|
||||
/datum/tgs_api/v5/TestMerges()
|
||||
RequireInitialBridgeResponse()
|
||||
return test_merges
|
||||
|
||||
/datum/tgs_api/v5/EndProcess()
|
||||
Bridge(DMAPI5_BRIDGE_COMMAND_KILL)
|
||||
|
||||
/datum/tgs_api/v5/Revision()
|
||||
RequireInitialBridgeResponse()
|
||||
return revision
|
||||
|
||||
/datum/tgs_api/v5/ChatBroadcast(message, list/channels)
|
||||
if(!length(channels))
|
||||
channels = ChatChannelInfo()
|
||||
|
||||
var/list/ids = list()
|
||||
for(var/I in channels)
|
||||
var/datum/tgs_chat_channel/channel = I
|
||||
ids += channel.id
|
||||
|
||||
message = list(DMAPI5_CHAT_MESSAGE_TEXT = message, DMAPI5_CHAT_MESSAGE_CHANNEL_IDS = ids)
|
||||
if(intercepted_message_queue)
|
||||
intercepted_message_queue += list(message)
|
||||
else
|
||||
Bridge(DMAPI5_BRIDGE_COMMAND_CHAT_SEND, list(DMAPI5_BRIDGE_PARAMETER_CHAT_MESSAGE = message))
|
||||
|
||||
/datum/tgs_api/v5/ChatTargetedBroadcast(message, 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 = list(DMAPI5_CHAT_MESSAGE_TEXT = message, DMAPI5_CHAT_MESSAGE_CHANNEL_IDS = channels)
|
||||
if(intercepted_message_queue)
|
||||
intercepted_message_queue += list(message)
|
||||
else
|
||||
Bridge(DMAPI5_BRIDGE_COMMAND_CHAT_SEND, list(DMAPI5_BRIDGE_PARAMETER_CHAT_MESSAGE = message))
|
||||
|
||||
/datum/tgs_api/v5/ChatPrivateMessage(message, datum/tgs_chat_user/user)
|
||||
message = list(DMAPI5_CHAT_MESSAGE_TEXT = message, DMAPI5_CHAT_MESSAGE_CHANNEL_IDS = list(user.channel.id))
|
||||
if(intercepted_message_queue)
|
||||
intercepted_message_queue += list(message)
|
||||
else
|
||||
Bridge(DMAPI5_BRIDGE_COMMAND_CHAT_SEND, list(DMAPI5_BRIDGE_PARAMETER_CHAT_MESSAGE = message))
|
||||
|
||||
/datum/tgs_api/v5/ChatChannelInfo()
|
||||
RequireInitialBridgeResponse()
|
||||
return chat_channels
|
||||
|
||||
/datum/tgs_api/v5/proc/DecodeChannels(chat_update_json)
|
||||
var/list/chat_channels_json = chat_update_json[DMAPI5_CHAT_UPDATE_CHANNELS]
|
||||
if(istype(chat_channels_json))
|
||||
chat_channels.Cut()
|
||||
for(var/channel_json in chat_channels_json)
|
||||
var/datum/tgs_chat_channel/channel = DecodeChannel(channel_json)
|
||||
if(channel)
|
||||
chat_channels += channel
|
||||
else
|
||||
TGS_WARNING_LOG("Failed to decode [DMAPI5_CHAT_UPDATE_CHANNELS] from channel update!")
|
||||
|
||||
/datum/tgs_api/v5/proc/DecodeChannel(channel_json)
|
||||
var/datum/tgs_chat_channel/channel = new
|
||||
channel.id = channel_json[DMAPI5_CHAT_CHANNEL_ID]
|
||||
channel.friendly_name = channel_json[DMAPI5_CHAT_CHANNEL_FRIENDLY_NAME]
|
||||
channel.connection_name = channel_json[DMAPI5_CHAT_CHANNEL_CONNECTION_NAME]
|
||||
channel.is_admin_channel = channel_json[DMAPI5_CHAT_CHANNEL_IS_ADMIN_CHANNEL]
|
||||
channel.is_private_channel = channel_json[DMAPI5_CHAT_CHANNEL_IS_PRIVATE_CHANNEL]
|
||||
channel.custom_tag = channel_json[DMAPI5_CHAT_CHANNEL_TAG]
|
||||
return channel
|
||||
|
||||
/datum/tgs_api/v5/SecurityLevel()
|
||||
RequireInitialBridgeResponse()
|
||||
return security_level
|
||||
@@ -0,0 +1,40 @@
|
||||
/datum/tgs_api/v5/proc/ListCustomCommands()
|
||||
var/results = list()
|
||||
custom_commands = list()
|
||||
for(var/I in typesof(/datum/tgs_chat_command) - /datum/tgs_chat_command)
|
||||
var/datum/tgs_chat_command/stc = new I
|
||||
var/command_name = stc.name
|
||||
if(!command_name || findtext(command_name, " ") || findtext(command_name, "'") || findtext(command_name, "\""))
|
||||
TGS_WARNING_LOG("Custom command [command_name] ([I]) can't be used as it is empty or contains illegal characters!")
|
||||
continue
|
||||
|
||||
if(results[command_name])
|
||||
var/datum/other = custom_commands[command_name]
|
||||
TGS_WARNING_LOG("Custom commands [other.type] and [I] have the same name (\"[command_name]\"), only [other.type] will be available!")
|
||||
continue
|
||||
results += list(list(DMAPI5_CUSTOM_CHAT_COMMAND_NAME = command_name, DMAPI5_CUSTOM_CHAT_COMMAND_HELP_TEXT = stc.help_text, DMAPI5_CUSTOM_CHAT_COMMAND_ADMIN_ONLY = stc.admin_only))
|
||||
custom_commands[command_name] = stc
|
||||
|
||||
return results
|
||||
|
||||
/datum/tgs_api/v5/proc/HandleCustomCommand(list/command_json)
|
||||
var/command = command_json[DMAPI5_CHAT_COMMAND_NAME]
|
||||
var/user = command_json[DMAPI5_CHAT_COMMAND_USER]
|
||||
var/params = command_json[DMAPI5_CHAT_COMMAND_PARAMS]
|
||||
|
||||
var/datum/tgs_chat_user/u = new
|
||||
u.id = user[DMAPI5_CHAT_USER_ID]
|
||||
u.friendly_name = user[DMAPI5_CHAT_USER_FRIENDLY_NAME]
|
||||
u.mention = user[DMAPI5_CHAT_USER_MENTION]
|
||||
u.channel = DecodeChannel(user[DMAPI5_CHAT_USER_CHANNEL])
|
||||
|
||||
var/datum/tgs_chat_command/sc = custom_commands[command]
|
||||
if(sc)
|
||||
var/text_response = sc.Run(u, params)
|
||||
var/list/topic_response = list()
|
||||
if(!istext(text_response))
|
||||
TGS_ERROR_LOG("Custom command [command] should return a string! Got: \"[text_response]\"")
|
||||
text_response = null
|
||||
topic_response[DMAPI5_TOPIC_RESPONSE_COMMAND_RESPONSE_MESSAGE] = text_response
|
||||
return json_encode(topic_response)
|
||||
return TopicResponse("Unknown custom chat command: [command]!")
|
||||
@@ -0,0 +1,98 @@
|
||||
#undef DMAPI5_PARAM_SERVER_PORT
|
||||
#undef DMAPI5_PARAM_ACCESS_IDENTIFIER
|
||||
|
||||
#undef DMAPI5_BRIDGE_DATA
|
||||
#undef DMAPI5_TOPIC_DATA
|
||||
|
||||
#undef DMAPI5_BRIDGE_COMMAND_PORT_UPDATE
|
||||
#undef DMAPI5_BRIDGE_COMMAND_STARTUP
|
||||
#undef DMAPI5_BRIDGE_COMMAND_PRIME
|
||||
#undef DMAPI5_BRIDGE_COMMAND_REBOOT
|
||||
#undef DMAPI5_BRIDGE_COMMAND_KILL
|
||||
#undef DMAPI5_BRIDGE_COMMAND_CHAT_SEND
|
||||
|
||||
#undef DMAPI5_PARAMETER_ACCESS_IDENTIFIER
|
||||
#undef DMAPI5_PARAMETER_CUSTOM_COMMANDS
|
||||
|
||||
#undef DMAPI5_RESPONSE_ERROR_MESSAGE
|
||||
|
||||
#undef DMAPI5_BRIDGE_PARAMETER_COMMAND_TYPE
|
||||
#undef DMAPI5_BRIDGE_PARAMETER_CURRENT_PORT
|
||||
#undef DMAPI5_BRIDGE_PARAMETER_VERSION
|
||||
#undef DMAPI5_BRIDGE_PARAMETER_CHAT_MESSAGE
|
||||
#undef DMAPI5_BRIDGE_PARAMETER_MINIMUM_SECURITY_LEVEL
|
||||
|
||||
#undef DMAPI5_BRIDGE_RESPONSE_NEW_PORT
|
||||
#undef DMAPI5_BRIDGE_RESPONSE_RUNTIME_INFORMATION
|
||||
|
||||
#undef DMAPI5_CHAT_MESSAGE_TEXT
|
||||
#undef DMAPI5_CHAT_MESSAGE_CHANNEL_IDS
|
||||
|
||||
#undef DMAPI5_RUNTIME_INFORMATION_ACCESS_IDENTIFIER
|
||||
#undef DMAPI5_RUNTIME_INFORMATION_SERVER_VERSION
|
||||
#undef DMAPI5_RUNTIME_INFORMATION_SERVER_PORT
|
||||
#undef DMAPI5_RUNTIME_INFORMATION_API_VALIDATE_ONLY
|
||||
#undef DMAPI5_RUNTIME_INFORMATION_INSTANCE_NAME
|
||||
#undef DMAPI5_RUNTIME_INFORMATION_REVISION
|
||||
#undef DMAPI5_RUNTIME_INFORMATION_TEST_MERGES
|
||||
#undef DMAPI5_RUNTIME_INFORMATION_SECURITY_LEVEL
|
||||
|
||||
#undef DMAPI5_CHAT_UPDATE_CHANNELS
|
||||
|
||||
#undef DMAPI5_TEST_MERGE_TIME_MERGED
|
||||
#undef DMAPI5_TEST_MERGE_REVISION
|
||||
#undef DMAPI5_TEST_MERGE_TITLE_AT_MERGE
|
||||
#undef DMAPI5_TEST_MERGE_BODY_AT_MERGE
|
||||
#undef DMAPI5_TEST_MERGE_URL
|
||||
#undef DMAPI5_TEST_MERGE_AUTHOR
|
||||
#undef DMAPI5_TEST_MERGE_NUMBER
|
||||
#undef DMAPI5_TEST_MERGE_PULL_REQUEST_REVISION
|
||||
#undef DMAPI5_TEST_MERGE_COMMENT
|
||||
|
||||
#undef DMAPI5_CHAT_COMMAND_NAME
|
||||
#undef DMAPI5_CHAT_COMMAND_PARAMS
|
||||
#undef DMAPI5_CHAT_COMMAND_USER
|
||||
|
||||
#undef DMAPI5_EVENT_NOTIFICATION_TYPE
|
||||
#undef DMAPI5_EVENT_NOTIFICATION_PARAMETERS
|
||||
|
||||
#undef DMAPI5_TOPIC_COMMAND_CHAT_COMMAND
|
||||
#undef DMAPI5_TOPIC_COMMAND_EVENT_NOTIFICATION
|
||||
#undef DMAPI5_TOPIC_COMMAND_CHANGE_PORT
|
||||
#undef DMAPI5_TOPIC_COMMAND_CHANGE_REBOOT_STATE
|
||||
#undef DMAPI5_TOPIC_COMMAND_INSTANCE_RENAMED
|
||||
#undef DMAPI5_TOPIC_COMMAND_CHAT_CHANNELS_UPDATE
|
||||
#undef DMAPI5_TOPIC_COMMAND_SERVER_PORT_UPDATE
|
||||
#undef DMAPI5_TOPIC_COMMAND_HEARTBEAT
|
||||
#undef DMAPI5_TOPIC_COMMAND_WATCHDOG_REATTACH
|
||||
|
||||
#undef DMAPI5_TOPIC_PARAMETER_COMMAND_TYPE
|
||||
#undef DMAPI5_TOPIC_PARAMETER_CHAT_COMMAND
|
||||
#undef DMAPI5_TOPIC_PARAMETER_EVENT_NOTIFICATION
|
||||
#undef DMAPI5_TOPIC_PARAMETER_NEW_PORT
|
||||
#undef DMAPI5_TOPIC_PARAMETER_NEW_REBOOT_STATE
|
||||
#undef DMAPI5_TOPIC_PARAMETER_NEW_INSTANCE_NAME
|
||||
#undef DMAPI5_TOPIC_PARAMETER_CHAT_UPDATE
|
||||
#undef DMAPI5_TOPIC_PARAMETER_NEW_SERVER_VERSION
|
||||
|
||||
#undef DMAPI5_TOPIC_RESPONSE_COMMAND_RESPONSE_MESSAGE
|
||||
#undef DMAPI5_TOPIC_RESPONSE_CHAT_RESPONSES
|
||||
|
||||
#undef DMAPI5_REVISION_INFORMATION_COMMIT_SHA
|
||||
#undef DMAPI5_REVISION_INFORMATION_ORIGIN_COMMIT_SHA
|
||||
|
||||
#undef DMAPI5_CHAT_USER_ID
|
||||
#undef DMAPI5_CHAT_USER_FRIENDLY_NAME
|
||||
#undef DMAPI5_CHAT_USER_MENTION
|
||||
#undef DMAPI5_CHAT_USER_CHANNEL
|
||||
|
||||
#undef DMAPI5_CHAT_CHANNEL_ID
|
||||
#undef DMAPI5_CHAT_CHANNEL_FRIENDLY_NAME
|
||||
#undef DMAPI5_CHAT_CHANNEL_CONNECTION_NAME
|
||||
#undef DMAPI5_CHAT_CHANNEL_IS_ADMIN_CHANNEL
|
||||
#undef DMAPI5_CHAT_CHANNEL_IS_PRIVATE_CHANNEL
|
||||
#undef DMAPI5_CHAT_CHANNEL_TAG
|
||||
|
||||
#undef DMAPI5_CUSTOM_CHAT_COMMAND_NAME
|
||||
#undef DMAPI5_CUSTOM_CHAT_COMMAND_HELP_TEXT
|
||||
#undef DMAPI5_CUSTOM_CHAT_COMMAND_ADMIN_ONLY
|
||||
Binary file not shown.
Reference in New Issue
Block a user