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."