diff --git a/code/__defines/admin.dm b/code/__defines/admin.dm
index 944e123a9ce..ed1934fedac 100644
--- a/code/__defines/admin.dm
+++ b/code/__defines/admin.dm
@@ -41,6 +41,7 @@
#define R_CCIAA 0x8000 //higher than this will overflow
#define R_MAXPERMISSION 0x8000 // This holds the maximum value for a permission. It is used in iteration, so keep it updated.
+#define R_ALL 0x7FFF // All perms forever.
// ticket statuses
#define TICKET_CLOSED 0
diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm
index cdad7156e93..249261ef592 100644
--- a/code/modules/admin/admin.dm
+++ b/code/modules/admin/admin.dm
@@ -666,11 +666,13 @@ proc/admin_notice(var/message, var/rights)
set category = "Special Verbs"
set name = "Announce"
set desc="Announce your desires to the world"
- if(!check_rights(0)) return
- var/message = input("Global message to send:", "Admin Announce", null, null) as message//todo: sanitize for all?
+ if (!check_rights(R_ADMIN))
+ return
+
+ var/message = input("Global message to send:", "Admin Announce", null, null) as message
if(message)
- if(!check_rights(R_SERVER,0))
+ if(!check_rights(R_SERVER, 0))
message = sanitize(message, 500, extra = 0)
message = replacetext(message, "\n", "
") // required since we're putting it in a
tag
to_world("[usr.client.holder.fakekey ? "Administrator" : usr.key] Announces:[message]
")
diff --git a/code/modules/world_api/commands/admin.dm b/code/modules/world_api/commands/admin.dm
index 371ef797f26..2a016aaaf61 100644
--- a/code/modules/world_api/commands/admin.dm
+++ b/code/modules/world_api/commands/admin.dm
@@ -106,10 +106,9 @@
to_chat(C, message)
for(var/client/A in staff)
- if(A != C)
+ if(A != C && check_rights(R_MOD|R_ADMIN, show_msg = FALSE, user = A.mob))
to_chat(A, amessage)
-
statuscode = 200
response = "Admin Message sent"
data = null
diff --git a/code/modules/world_api/commands/api_helpers.dm b/code/modules/world_api/commands/api_helpers.dm
index f19996e5a82..82a9f01e5e9 100644
--- a/code/modules/world_api/commands/api_helpers.dm
+++ b/code/modules/world_api/commands/api_helpers.dm
@@ -11,8 +11,8 @@
var/list/version = list()
var/versionstring = null
//The Version Number follows SemVer http://semver.org/
- version["major"] = 2 //Major Version Number --> Increment when implementing breaking changes
- version["minor"] = 7 //Minor Version Number --> Increment when adding features
+ version["major"] = 3 //Major Version Number --> Increment when implementing breaking changes
+ version["minor"] = 0 //Minor Version Number --> Increment when adding features
version["patch"] = 0 //Patchlevel --> Increment when fixing bugs
versionstring = "[version["major"]].[version["minor"]].[version["patch"]]"
diff --git a/code/modules/world_api/commands/server_management.dm b/code/modules/world_api/commands/server_management.dm
index cc12d4d6b8e..402c511ba0c 100644
--- a/code/modules/world_api/commands/server_management.dm
+++ b/code/modules/world_api/commands/server_management.dm
@@ -55,8 +55,8 @@
name = "restart_round"
description = "Restarts the round"
params = list(
- "senderkey" = list("name"="senderkey","desc"="Unique id of the person that authorized the restart","req"=1,"type"="str")
- )
+ "senderkey" = list("name"="senderkey","desc"="A display friendly name for the sender.","req"=1,"type"="str")
+ )
/datum/topic_command/restart_round/run_command(queryparams)
var/senderkey = sanitize(queryparams["senderkey"]) //Identifier of the sender (Ckey / Userid / ...)
@@ -66,7 +66,7 @@
feedback_set_details("end_error","remote restart")
spawn(50)
- log_game("Rebooting due to remote command.")
+ log_game("Rebooting due to remote command. Initiator: [senderkey]")
world.Reboot("Rebooting due to remote command.")
statuscode = 200
@@ -74,16 +74,48 @@
data = null
return TRUE
+/datum/topic_command/tgs_reboot
+ name = "restart_tgs"
+ description = "Orders an immediate reboot via TGS, including the shutting down of DreamDaemon."
+ params = list(
+ "senderkey" = list("name"="senderkey","desc"="Unique id of the person that authorized the restart","req"=1,"type"="str")
+ )
+
+/datum/topic_command/tgs_reboot/run_command(queryparams)
+ var/senderkey = sanitize(queryparams["senderkey"]) //Identifier of the sender (Ckey / Userid / ...)
+
+ if (!world.TgsAvailable())
+ statuscode = 503
+ response = "TGS not available."
+ data = null
+ return TRUE
+
+ to_world("Server restarting by remote command.")
+ log_and_message_admins("World restart initiated remotely by [senderkey].")
+ feedback_set_details("end_error","remote restart")
+
+ world.Reboot("Rebooting due to remote command.", hard_reset = TRUE)
+
+ statuscode = 200
+ response = "Restart Command accepted"
+ data = null
+ return TRUE
+
//Sends a text to everyone on the server
/datum/topic_command/broadcast_text
name = "broadcast_text"
description = "Sends a text to everyone on the server."
params = list(
+ "senderkey" = list("name"="senderkey","desc"="A display friendly name for the sender.","req"=1,"type"="str"),
"text" = list("name"="text","desc"="The text that should be sent","req"=1,"type"="str")
)
/datum/topic_command/broadcast_text/run_command(queryparams)
- to_world(queryparams["text"])
+ var/sender = sanitize(queryparams["senderkey"])
+ var/text = sanitize(queryparams["text"])
+
+ to_world("[sender] Announces via Remote:[text]
")
+ log_admin("Remote announce: [sender] : [queryparams["text"]]")
statuscode = 200
response = "Text sent"
diff --git a/code/modules/world_api/commands/server_query.dm b/code/modules/world_api/commands/server_query.dm
index a92f21e9e68..c3d1bda8ad0 100644
--- a/code/modules/world_api/commands/server_query.dm
+++ b/code/modules/world_api/commands/server_query.dm
@@ -17,7 +17,7 @@
s["roundduration"] = get_round_duration_formatted()
s["gameid"] = game_id
s["game_state"] = SSticker ? 0 : SSticker.current_state
- s["transferring"] = emergency_shuttle ? !emergency_shuttle.online() : FALSE
+ s["transferring"] = !!(emergency_shuttle?.online())
s["players"] = clients.len
s["admins"] = 0
@@ -27,7 +27,7 @@
var/client/C = S
if(C.holder.fakekey)
continue
- if(C.holder.rights & R_BAN) // we are doing R_BAN to not count retired admins, since they get R_MOD and R_ADMIN but not R_BAN.
+ if(C.holder.rights & (R_MOD|R_ADMIN))
s["admins"]++
statuscode = 200
@@ -70,52 +70,78 @@
data = chars
return TRUE
-//Admin Count
-/datum/topic_command/get_count_admin
- name = "get_count_admin"
- description = "Gets the number of admins connected"
+/datum/topic_command/get_staff_by_flag
+ name = "get_staff_by_flag"
+ description = "Gets the list of staff, selected by flag values."
+ params = list(
+ "flags" = list("name"="flags","desc"="The flags to query based on.","req"=1,"type"="int"),
+ "strict" = list("name"="strict","desc"="Set to 1 if you want all flags to be present on the holder.","req"=0,"type"="int"),
+ "show_fakekeys" = list("name"="strict","desc"="Set to 1 if you want to show fake key holders as well.","req"=0,"type"="int")
+ )
+
+/datum/topic_command/get_staff_by_flag/run_command(queryparams)
+ var/flags = text2num(queryparams["flags"])
+
+ flags &= R_ALL
+
+ var/strict = !!(queryparams["strict"] && (text2num(queryparams["strict"]) == 1))
+ var/show_fakes = !!(queryparams["show_fakekeys"] && (text2num(queryparams["show_fakekeys"]) == 1))
+
+ var/list/ckeys_found = list()
-/datum/topic_command/get_count_admin/run_command(queryparams)
- var/n = 0
for (var/client/client in clients)
- if (client.holder && client.holder.rights & (R_ADMIN))
- n++
+ if (!client.holder)
+ continue
+
+ if (!show_fakes && client.holder.fakekey)
+ continue
+
+ if (strict)
+ if (client.holder.rights == flags)
+ ckeys_found += client.ckey
+ else
+ if (client.holder.rights & flags)
+ ckeys_found += client.ckey
statuscode = 200
- response = "Admin count fetched"
- data = n
+ response = "Staff count and list fetched."
+ data = list(
+ "ckeys" = ckeys_found
+ )
+
return TRUE
-//CCIA Count
-/datum/topic_command/get_count_cciaa
- name = "get_count_cciaa"
- description = "Gets the number of ccia connected"
+/datum/topic_command/get_staff_by_rank
+ name = "get_staff_by_rank"
+ description = "Gets the list of staff, selected by their rank."
+ params = list(
+ "rank" = list("name"="flags","desc"="The rank name to query based on.","req"=1,"type"="str"),
+ "show_fakekeys" = list("name"="strict","desc"="Set to 1 if you want to show fake key holders as well.","req"=0,"type"="int")
+ )
+
+/datum/topic_command/get_staff_by_flag/run_command(queryparams)
+ var/rank = queryparams["rank"]
+
+ var/show_fakes = !!(queryparams["show_fakekeys"] && (text2num(queryparams["show_fakekeys"]) == 1))
+
+ var/list/ckeys_found = list()
-/datum/topic_command/get_count_ccia/run_command(queryparams)
- var/n = 0
for (var/client/client in clients)
- if (client.holder && (client.holder.rights & R_CCIAA) && !(client.holder.rights & R_ADMIN))
- n++
+ if (!client.holder)
+ continue
+
+ if (!show_fakes && client.holder.fakekey)
+ continue
+
+ if (client.holder.rank == rank)
+ ckeys_found += client.ckey
statuscode = 200
- response = "CCIA count fetched"
- data = n
- return TRUE
+ response = "Staff count and list fetched."
+ data = list(
+ "ckeys" = ckeys_found
+ )
-//Mod Count
-/datum/topic_command/get_count_mod
- name = "get_count_mod"
- description = "Gets the number of mods connected"
-
-/datum/topic_command/get_count_mod/run_command(queryparams)
- var/n = 0
- for (var/client/client in clients)
- if (client.holder && (client.holder.rights & R_MOD) && !(client.holder.rights & R_ADMIN))
- n++
-
- statuscode = 200
- response = "Mod count fetched"
- data = n
return TRUE
//Player Count
@@ -204,7 +230,7 @@
var/list/players = list()
for (var/client/C in clients)
- if (show_hidden_admins && C.holder && C.holder.fakekey)
+ if (!show_hidden_admins && C.holder?.fakekey)
players += ckey(C.holder.fakekey)
else
players += C.ckey
diff --git a/code/world.dm b/code/world.dm
index 87305e636fd..67fb2963314 100644
--- a/code/world.dm
+++ b/code/world.dm
@@ -188,10 +188,8 @@ var/list/world_api_rate_limit = list()
return json_encode(response)
-/world/Reboot(var/reason)
- var/hard_reset = FALSE
-
- if (world.TgsAvailable())
+/world/Reboot(reason, hard_reset = FALSE)
+ if (!hard_reset && world.TgsAvailable())
switch (config.rounds_until_hard_restart)
if (-1)
hard_reset = FALSE
@@ -204,6 +202,8 @@ var/list/world_api_rate_limit = list()
else
hard_reset = FALSE
SSpersist_config.rounds_since_hard_restart++
+ else if (!world.TgsAvailable() && hard_reset)
+ hard_reset = FALSE
SSpersist_config.save_to_file("data/persistent_config.json")
Master.Shutdown()
diff --git a/html/changelogs/skull132_api.yml b/html/changelogs/skull132_api.yml
new file mode 100644
index 00000000000..266abf2466f
--- /dev/null
+++ b/html/changelogs/skull132_api.yml
@@ -0,0 +1,7 @@
+author: Skull132
+delete-after: True
+
+changes:
+ - bugfix: "Random staff will no longer see Discord-PMs. Only R_MOD and R_ADMIN staff will."
+ - backend: "Remote TGS restart command implemented."
+ - tweak: "Remote announce formatting changed to match the real announce."