mirror of
https://github.com/Aurorastation/Aurora.3.git
synced 2025-12-21 07:32:02 +00:00
API refactor + update (#6127)
This commit is contained in:
116
code/modules/world_api/commands/admin.dm
Normal file
116
code/modules/world_api/commands/admin.dm
Normal file
@@ -0,0 +1,116 @@
|
||||
//Grant Respawn
|
||||
/datum/topic_command/grant_respawn
|
||||
name = "grant_respawn"
|
||||
description = "Grants a respawn to a specific target"
|
||||
params = list(
|
||||
"senderkey" = list("name"="senderkey","desc"="Unique id of the person that authorized the respawn","req"=1,"type"="senderkey"),
|
||||
"target" = list("name"="target","desc"="Ckey of the target that should be granted a respawn","req"=1,"type"="str")
|
||||
)
|
||||
|
||||
/datum/topic_command/grant_respawn/run_command(queryparams)
|
||||
var/list/ghosts = get_ghosts(1,1)
|
||||
var/target = queryparams["target"]
|
||||
var/allow_antaghud = queryparams["allow_antaghud"]
|
||||
var/senderkey = queryparams["senderkey"] //Identifier of the sender (Ckey / Userid / ...)
|
||||
|
||||
var/mob/abstract/observer/G = ghosts[target]
|
||||
|
||||
if(!G in ghosts)
|
||||
statuscode = 404
|
||||
response = "Target not in ghosts list"
|
||||
data = null
|
||||
return TRUE
|
||||
|
||||
if(G.has_enabled_antagHUD && config.antag_hud_restricted && allow_antaghud == 0)
|
||||
statuscode = 409
|
||||
response = "Ghost has used Antag Hud - Respawn Aborted"
|
||||
data = null
|
||||
return TRUE
|
||||
G.timeofdeath=-19999 /* time of death is checked in /mob/verb/abandon_mob() which is the Respawn verb.
|
||||
timeofdeath is used for bodies on autopsy but since we're messing with a ghost I'm pretty sure
|
||||
there won't be an autopsy.
|
||||
*/
|
||||
var/datum/preferences/P
|
||||
|
||||
if (G.client)
|
||||
P = G.client.prefs
|
||||
else if (G.ckey)
|
||||
P = preferences_datums[G.ckey]
|
||||
else
|
||||
statuscode = 500
|
||||
response = "Something went wrong, couldn't find the target's preferences datum"
|
||||
data = null
|
||||
return TRUE
|
||||
|
||||
for (var/entry in P.time_of_death)//Set all the prefs' times of death to a huge negative value so any respawn timers will be fine
|
||||
P.time_of_death[entry] = -99999
|
||||
|
||||
G.has_enabled_antagHUD = 2
|
||||
G.can_reenter_corpse = 1
|
||||
|
||||
G:show_message(text("<span class='notice'><B>You may now respawn. You should roleplay as if you learned nothing about the round during your time with the dead.</B></span>"), 1)
|
||||
log_admin("[senderkey] allowed [key_name(G)] to bypass the 30 minute respawn limit via the API",ckey=key_name(G),admin_key=senderkey)
|
||||
message_admins("Admin [senderkey] allowed [key_name_admin(G)] to bypass the 30 minute respawn limit via the API", 1)
|
||||
|
||||
|
||||
statuscode = 200
|
||||
response = "Respawn Granted"
|
||||
data = null
|
||||
return TRUE
|
||||
|
||||
//Get available Fax Machines
|
||||
/datum/topic_command/send_adminmsg
|
||||
name = "send_adminmsg"
|
||||
description = "Sends a adminmessage to a player"
|
||||
params = list(
|
||||
"ckey" = list("name"="ckey","desc"="The target of the adminmessage","req"=1,"type"="str"),
|
||||
"msg" = list("name"="msg","desc"="The message that should be sent","req"=1,"type"="str"),
|
||||
"senderkey" = list("name"="senderkey","desc"="Unique id of the person that sent the adminmessage","req"=1,"type"="senderkey"),
|
||||
"rank" = list("name"="rank","desc"="The rank that should be displayed - Defaults to admin if none specified","req"=0,"type"="str")
|
||||
)
|
||||
|
||||
/datum/topic_command/send_adminmsg/run_command(queryparams)
|
||||
/*
|
||||
We got an adminmsg from IRC bot lets split the API
|
||||
expected output:
|
||||
1. ckey = ckey of person the message is to
|
||||
2. msg = contents of message, parems2list requires
|
||||
3. rank = Rank that should be displayed
|
||||
4. senderkey = the ircnick that send the message.
|
||||
*/
|
||||
|
||||
var/client/C
|
||||
var/req_ckey = ckey(queryparams["ckey"])
|
||||
|
||||
for(var/client/K in clients)
|
||||
if(K.ckey == req_ckey)
|
||||
C = K
|
||||
break
|
||||
if(!C)
|
||||
statuscode = 404
|
||||
response = "No client with that name on server"
|
||||
data = null
|
||||
return TRUE
|
||||
|
||||
var/rank = queryparams["rank"]
|
||||
if(!rank)
|
||||
rank = "Admin"
|
||||
|
||||
var/message = "<font color='red'>[rank] PM from <b><a href='?discord_msg=[queryparams["senderkey"]]'>[queryparams["senderkey"]]</a></b>: [queryparams["msg"]]</font>"
|
||||
var/amessage = "<font color='blue'>[rank] PM from <a href='?discord_msg=[queryparams["senderkey"]]'>[queryparams["senderkey"]]</a> to <b>[key_name(C, highlight_special = 1)]</b> : [queryparams["msg"]]</font>"
|
||||
|
||||
C.received_discord_pm = world.time
|
||||
C.discord_admin = queryparams["senderkey"]
|
||||
|
||||
sound_to(C, 'sound/effects/adminhelp.ogg')
|
||||
to_chat(C, message)
|
||||
|
||||
for(var/client/A in admins)
|
||||
if(A != C)
|
||||
to_chat(A, amessage)
|
||||
|
||||
|
||||
statuscode = 200
|
||||
response = "Admin Message sent"
|
||||
data = null
|
||||
return TRUE
|
||||
148
code/modules/world_api/commands/api_helpers.dm
Normal file
148
code/modules/world_api/commands/api_helpers.dm
Normal file
@@ -0,0 +1,148 @@
|
||||
//
|
||||
// API for the API
|
||||
//
|
||||
/datum/topic_command/api_get_version
|
||||
name = "api_get_version"
|
||||
description = "Gets the version of the API"
|
||||
no_auth = TRUE
|
||||
no_throttle = TRUE
|
||||
|
||||
/datum/topic_command/api_get_version/run_command(queryparams)
|
||||
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"] = 5 //Minor Version Number --> Increment when adding features
|
||||
version["patch"] = 0 //Patchlevel --> Increment when fixing bugs
|
||||
|
||||
versionstring = "[version["major"]].[version["minor"]].[version["patch"]]"
|
||||
|
||||
statuscode = 200
|
||||
response = versionstring
|
||||
data = version
|
||||
return TRUE
|
||||
|
||||
|
||||
//Get all the commands a specific token / ip combo is authorized to use
|
||||
/datum/topic_command/api_get_authed_commands
|
||||
name = "api_get_authed_commands"
|
||||
description = "Returns the commands that can be accessed by the requesting ip and token"
|
||||
|
||||
/datum/topic_command/api_get_authed_commands/run_command(queryparams)
|
||||
var/list/commands = list()
|
||||
//Check if DB Connection is established
|
||||
if (!establish_db_connection(dbcon))
|
||||
statuscode = 500
|
||||
response = "DB Connection Unavailable"
|
||||
return TRUE
|
||||
|
||||
var/DBQuery/commandsquery = dbcon.NewQuery({"SELECT api_f.command
|
||||
FROM ss13_api_token_command as api_t_f, ss13_api_tokens as api_t, ss13_api_commands as api_f
|
||||
WHERE api_t.id = api_t_f.token_id AND api_f.id = api_t_f.command_id
|
||||
AND (
|
||||
(token = :token: AND ip = :ip:)
|
||||
OR
|
||||
(token = :token: AND ip IS NULL)
|
||||
OR
|
||||
(token IS NULL AND ip = :ip:)
|
||||
)
|
||||
ORDER BY command DESC"})
|
||||
|
||||
|
||||
commandsquery.Execute(list("token" = queryparams["auth"], "ip" = queryparams["addr"]))
|
||||
while (commandsquery.NextRow())
|
||||
commands[commandsquery.item[1]] = commandsquery.item[1]
|
||||
if(commandsquery.item[1] == "_ANY")
|
||||
statuscode = 200
|
||||
response = "Authorized commands retrieved - ALL"
|
||||
data = topic_commands_names
|
||||
return TRUE
|
||||
|
||||
|
||||
statuscode = 200
|
||||
response = "Authorized commands retrieved"
|
||||
data = commands
|
||||
return TRUE
|
||||
|
||||
//Get details for a specific api command
|
||||
/datum/topic_command/api_explain_command
|
||||
name = "api_explain_command"
|
||||
description = "Explains a specific API command"
|
||||
no_throttle = TRUE
|
||||
params = list(
|
||||
"command" = list("name"="command","desc"="The name of the API command that should be explained","req"=1,"type"="str")
|
||||
)
|
||||
|
||||
/datum/topic_command/api_explain_command/run_command(queryparams)
|
||||
var/datum/topic_command/apicommand = topic_commands[queryparams["command"]]
|
||||
var/list/commanddata = list()
|
||||
|
||||
if (isnull(apicommand))
|
||||
statuscode = 501
|
||||
response = "Not Implemented - The requested command does not exist"
|
||||
return TRUE
|
||||
|
||||
//Then query for auth
|
||||
if (!establish_db_connection(dbcon))
|
||||
statuscode = 500
|
||||
response = "DB Connection Unavailable"
|
||||
return TRUE
|
||||
|
||||
if (apicommand.check_auth(queryparams["addr"], queryparams["auth"], TRUE))
|
||||
statuscode = 401
|
||||
response = "Not Authorized - You are not authorized to use the requested command."
|
||||
return TRUE
|
||||
|
||||
commanddata["name"] = apicommand.name
|
||||
commanddata["description"] = apicommand.description
|
||||
commanddata["params"] = apicommand.params
|
||||
|
||||
statuscode = 200
|
||||
response = "Command data retrieved"
|
||||
data = commanddata
|
||||
return TRUE
|
||||
|
||||
|
||||
/datum/topic_command/update_command_database
|
||||
name = "update_command_database"
|
||||
description = "Updates the available topic commands in the database"
|
||||
|
||||
/datum/topic_command/update_command_database/run_command(queryparams)
|
||||
if (!api_update_command_database())
|
||||
statuscode = 500
|
||||
return FALSE
|
||||
else
|
||||
statuscode = 200
|
||||
return TRUE
|
||||
|
||||
/datum/topic_command/update_command_database/proc/api_update_command_database()
|
||||
log_debug("API: DB Command Update Called")
|
||||
//Check if DB Connection is established
|
||||
if (!establish_db_connection(dbcon))
|
||||
response = "Database connection lost, cannot update commands."
|
||||
return FALSE //Error
|
||||
|
||||
var/DBQuery/commandinsertquery = dbcon.NewQuery({"INSERT INTO ss13_api_commands (command,description)
|
||||
VALUES (:command_name:,:command_description:)
|
||||
ON DUPLICATE KEY UPDATE description = :command_description:;"})
|
||||
|
||||
for(var/com in topic_commands)
|
||||
var/datum/topic_command/command = topic_commands[com]
|
||||
commandinsertquery.Execute(list("command_name" = command.name, "command_description" = command.description))
|
||||
|
||||
log_debug("API: DB Command Update Executed")
|
||||
|
||||
response = "Commands successfully updated."
|
||||
return TRUE //OK
|
||||
|
||||
//Ping Test
|
||||
/datum/topic_command/ping
|
||||
name = "ping"
|
||||
description = "API test command"
|
||||
no_auth = TRUE
|
||||
|
||||
/datum/topic_command/ping/run_command(queryparams)
|
||||
statuscode = 200
|
||||
response = "Pong"
|
||||
data = "Pong"
|
||||
return TRUE
|
||||
258
code/modules/world_api/commands/cciaa.dm
Normal file
258
code/modules/world_api/commands/cciaa.dm
Normal file
@@ -0,0 +1,258 @@
|
||||
//Get available Fax Machines
|
||||
/datum/topic_command/get_faxmachines
|
||||
name = "get_faxmachines"
|
||||
description = "Gets all available fax machines"
|
||||
|
||||
/datum/topic_command/get_faxmachines/run_command(queryparams)
|
||||
var/list/faxlocations = list()
|
||||
|
||||
for (var/obj/machinery/photocopier/faxmachine/F in allfaxes)
|
||||
faxlocations.Add(F.department)
|
||||
|
||||
statuscode = 200
|
||||
response = "Fax machines fetched"
|
||||
data = faxlocations
|
||||
return TRUE
|
||||
|
||||
//Get Fax List
|
||||
/datum/topic_command/get_faxlist
|
||||
name = "get_faxlist"
|
||||
description = "Gets the list of faxes sent / received"
|
||||
params = list(
|
||||
"faxtype" = list("name"="faxtype","desc"="Type of the faxes that should be retrieved","req"=1,"type"="slct","options"=list("sent","received"))
|
||||
)
|
||||
|
||||
/datum/topic_command/get_faxlist/run_command(queryparams)
|
||||
var/list/faxes = list()
|
||||
switch (queryparams["faxtype"])
|
||||
if ("received")
|
||||
faxes = arrived_faxes
|
||||
if ("sent")
|
||||
faxes = sent_faxes
|
||||
|
||||
if (!faxes || !faxes.len)
|
||||
statuscode = 404
|
||||
response = "No faxes found"
|
||||
data = null
|
||||
return TRUE
|
||||
|
||||
var/list/output = list()
|
||||
for (var/i = 1, i <= faxes.len, i++)
|
||||
var/obj/item/a = faxes[i]
|
||||
output += "[i]"
|
||||
output[i] = a.name ? a.name : "Untitled Fax"
|
||||
|
||||
statuscode = 200
|
||||
response = "Fetched Fax List"
|
||||
data = output
|
||||
return TRUE
|
||||
|
||||
//Get Specific Fax
|
||||
/datum/topic_command/get_fax
|
||||
name = "get_fax"
|
||||
description = "Gets a specific fax that has been sent or received"
|
||||
params = list(
|
||||
"faxtype" = list("name"="faxtype","desc"="Type of the faxes that should be retrieved","req"=1,"type"="slct","options"=list("sent","received")),
|
||||
"faxid" = list("name"="faxid","desc"="ID of the fax that should be retrieved","req"=1,"type"="int")
|
||||
)
|
||||
|
||||
/datum/topic_command/get_fax/run_command(queryparams)
|
||||
var/list/faxes = list()
|
||||
switch (queryparams["faxtype"])
|
||||
if ("received")
|
||||
faxes = arrived_faxes
|
||||
if ("sent")
|
||||
faxes = sent_faxes
|
||||
|
||||
if (!faxes || !faxes.len)
|
||||
statuscode = 500
|
||||
response = "No faxes found!"
|
||||
data = null
|
||||
return TRUE
|
||||
|
||||
var/fax_id = text2num(queryparams["faxid"])
|
||||
if (fax_id > faxes.len || fax_id < 1)
|
||||
statuscode = 404
|
||||
response = "Invalid Fax ID"
|
||||
data = null
|
||||
return TRUE
|
||||
|
||||
var/output = list()
|
||||
if (istype(faxes[fax_id], /obj/item/weapon/paper))
|
||||
var/obj/item/weapon/paper/a = faxes[fax_id]
|
||||
output["title"] = a.name ? a.name : "Untitled Fax"
|
||||
|
||||
var/content = replacetext(a.info, "<br>", "\n")
|
||||
content = strip_html_properly(content, 0)
|
||||
output["content"] = content
|
||||
|
||||
statuscode = 200
|
||||
response = "Fax (Paper) with id [fax_id] retrieved"
|
||||
data = output
|
||||
return TRUE
|
||||
else if (istype(faxes[fax_id], /obj/item/weapon/photo))
|
||||
statuscode = 501
|
||||
response = "Fax is a Photo - Unable to send"
|
||||
data = null
|
||||
return TRUE
|
||||
else if (istype(faxes[fax_id], /obj/item/weapon/paper_bundle))
|
||||
var/obj/item/weapon/paper_bundle/b = faxes[fax_id]
|
||||
output["title"] = b.name ? b.name : "Untitled Paper Bundle"
|
||||
|
||||
if (!b.pages || !b.pages.len)
|
||||
statuscode = 500
|
||||
response = "Fax Paper Bundle is empty - This should not happen"
|
||||
data = null
|
||||
return TRUE
|
||||
|
||||
var/i = 0
|
||||
for (var/obj/item/weapon/paper/c in b.pages)
|
||||
i++
|
||||
var/content = replacetext(c.info, "<br>", "\n")
|
||||
content = strip_html_properly(content, 0)
|
||||
output["content"] += "Page [i]:\n[content]\n\n"
|
||||
|
||||
statuscode = 200
|
||||
response = "Fax (PaperBundle) retrieved"
|
||||
data = output
|
||||
return TRUE
|
||||
|
||||
statuscode = 500
|
||||
response = "Unable to recognize the fax type. Cannot send contents!"
|
||||
data = null
|
||||
return TRUE
|
||||
|
||||
//Send a Command Report
|
||||
/datum/topic_command/send_commandreport
|
||||
name = "send_commandreport"
|
||||
description = "Sends a command report"
|
||||
params = list(
|
||||
"senderkey" = list("name"="senderkey","desc"="Unique id of the person that sent the commandreport","req"=1,"type"="senderkey"),
|
||||
"title" = list("name"="title","desc"="The message title that should be sent, Defaults to NanoTrasen Update if not specified","req"=0,"type"="str"),
|
||||
"body" = list("name"="body","desc"="The message body that should be sent","req"=1,"type"="str"),
|
||||
"type" = list("name"="type","desc"="The type of the message that should be sent, Defaults to freeform","req"=0,"type"="slct","options"=list("freeform","ccia")),
|
||||
"sendername" = list("name"="sendername","desc"="IC Name of the sender for the CCIA Report, Defaults to CCIAAMS, \[Command-StationName\]","req"=0,"type"="str"),
|
||||
"announce" = list("name"="announce","desc"="If the report should be announce 1 -> Yes, 0 -> No, Defaults to 1","req"=0,"type"="int")
|
||||
)
|
||||
|
||||
/datum/topic_command/send_commandreport/run_command(queryparams)
|
||||
var/senderkey = sanitize(queryparams["senderkey"]) //Identifier of the sender (Ckey / Userid / ...)
|
||||
var/reporttitle = sanitizeSafe(queryparams["title"]) //Title of the report
|
||||
var/reportbody = nl2br(sanitize(queryparams["body"],encode=0,extra=0,max_length=0)) //Body of the report
|
||||
var/reporttype = queryparams["type"] //Type of the report: freeform / ccia / admin
|
||||
var/reportsender = sanitizeSafe(queryparams["sendername"]) //Name of the sender
|
||||
var/reportannounce = text2num(queryparams["announce"]) //Announce the contents report to the public: 1 / 0
|
||||
|
||||
if(!reporttitle)
|
||||
reporttitle = "NanoTrasen Update"
|
||||
if(!reporttype)
|
||||
reporttype = "freeform"
|
||||
if(!reportannounce)
|
||||
reportannounce = 1
|
||||
|
||||
//Set the report footer for CCIA Announcements
|
||||
if (reporttype == "ccia")
|
||||
if (reportsender)
|
||||
reportbody += "<br><br>- [reportsender], Central Command Internal Affairs Agent, [commstation_name()]"
|
||||
else
|
||||
reportbody += "<br><br>- CCIAAMS, [commstation_name()]"
|
||||
|
||||
//Send the message to the communications consoles
|
||||
post_comm_message(reporttitle, reportbody)
|
||||
|
||||
if(reportannounce == 1)
|
||||
command_announcement.Announce(reportbody, reporttitle, new_sound = 'sound/AI/commandreport.ogg', do_newscast = 1, msg_sanitized = 1);
|
||||
if(reportannounce == 0)
|
||||
to_world("<span class='alert'>New NanoTrasen Update available at all communication consoles.</span>")
|
||||
to_world(sound('sound/AI/commandreport.ogg'))
|
||||
|
||||
|
||||
log_admin("[senderkey] has created a command report via the api: [reportbody]",admin_key=senderkey)
|
||||
message_admins("[senderkey] has created a command report via the api", 1)
|
||||
|
||||
statuscode = 200
|
||||
response = "Command Report sent"
|
||||
data = null
|
||||
return TRUE
|
||||
|
||||
//Send Fax
|
||||
/datum/topic_command/send_fax
|
||||
name = "send_fax"
|
||||
description = "Sends a fax"
|
||||
params = list(
|
||||
"senderkey" = list("name"="senderkey","desc"="Unique id of the person that sent the fax","req"=1,"type"="senderkey"),
|
||||
"title" = list("name"="title","desc"="The message title that should be sent","req"=1,"type"="str"),
|
||||
"body" = list("name"="body","desc"="The message body that should be sent","req"=1,"type"="str"),
|
||||
"target" = list("name"="target","desc"="The target faxmachines the fax should be sent to","req"=1,"type"="lst")
|
||||
)
|
||||
|
||||
/datum/topic_command/send_fax/run_command(queryparams)
|
||||
var/list/responselist = list()
|
||||
var/list/sendsuccess = list()
|
||||
var/list/targetlist = queryparams["target"] //Target locations where the fax should be sent to
|
||||
var/senderkey = sanitize(queryparams["senderkey"]) //Identifier of the sender (Ckey / Userid / ...)
|
||||
var/faxtitle = sanitizeSafe(queryparams["title"]) //Title of the report
|
||||
var/faxbody = sanitize(queryparams["body"],max_length=0) //Body of the report
|
||||
var/faxannounce = text2num(queryparams["announce"]) //Announce the contents report to the public: 0 - Dont announce, 1 - Announce, 2 - Only if pda not linked
|
||||
|
||||
if(!targetlist || targetlist.len < 1)
|
||||
statuscode = 400
|
||||
response = "Parameter target not set"
|
||||
data = null
|
||||
return TRUE
|
||||
|
||||
var/sendresult = 0
|
||||
var/notifyresult = 1
|
||||
|
||||
//Send the fax
|
||||
for (var/obj/machinery/photocopier/faxmachine/F in allfaxes)
|
||||
if (F.department in targetlist)
|
||||
sendresult = send_fax(F, faxtitle, faxbody, senderkey)
|
||||
if (sendresult == 1)
|
||||
sendsuccess.Add(F.department)
|
||||
if(!LAZYLEN(F.alert_pdas))
|
||||
notifyresult = 0
|
||||
responselist[F.department] = "notlinked"
|
||||
else
|
||||
responselist[F.department] = "success"
|
||||
else
|
||||
responselist[F.department] = "failed"
|
||||
|
||||
//Announce that the fax has been sent
|
||||
if(faxannounce == 1 || (faxannounce==2 && notifyresult==0))
|
||||
if(sendsuccess.len < 1)
|
||||
command_announcement.Announce("A fax message from Central Command could not be delivered because all of the following fax machines are inoperational: <br>"+jointext(targetlist, ", "), "Fax Delivery Failure", new_sound = 'sound/AI/commandreport.ogg', msg_sanitized = 1);
|
||||
else
|
||||
command_announcement.Announce("A fax message from Central Command has been sent to the following fax machines: <br>"+jointext(sendsuccess, ", "), "Fax Received", new_sound = 'sound/AI/commandreport.ogg', msg_sanitized = 1);
|
||||
|
||||
log_admin("[senderkey] sent a fax via the API: : [faxbody]",admin_key=senderkey)
|
||||
message_admins("[senderkey] sent a fax via the API", 1)
|
||||
|
||||
statuscode = 200
|
||||
response = "Fax sent"
|
||||
data = responselist
|
||||
return TRUE
|
||||
|
||||
/datum/topic_command/send_fax/proc/send_fax(var/obj/machinery/photocopier/faxmachine/F, title, body, senderkey)
|
||||
// Create the reply message
|
||||
var/obj/item/weapon/paper/P = new /obj/item/weapon/paper( null ) //hopefully the null loc won't cause trouble for us
|
||||
P.name = "[current_map.boss_name] - [title]"
|
||||
P.info = body
|
||||
P.update_icon()
|
||||
|
||||
// Stamps
|
||||
var/image/stampoverlay = image('icons/obj/bureaucracy.dmi')
|
||||
stampoverlay.icon_state = "paper_stamp-cent"
|
||||
if(!P.stamped)
|
||||
P.stamped = new
|
||||
P.stamped += /obj/item/weapon/stamp
|
||||
P.add_overlay(stampoverlay)
|
||||
P.stamps += "<HR><i>This paper has been stamped by the Central Command Quantum Relay.</i>"
|
||||
|
||||
if(F.receivefax(P))
|
||||
log_and_message_admins("[senderkey] sent a fax message to the [F.department] fax machine via the api. (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[F.x];Y=[F.y];Z=[F.z]'>JMP</a>)")
|
||||
sent_faxes += P
|
||||
return TRUE
|
||||
else
|
||||
qdel(P)
|
||||
return FALSE
|
||||
172
code/modules/world_api/commands/misc.dm
Normal file
172
code/modules/world_api/commands/misc.dm
Normal file
@@ -0,0 +1,172 @@
|
||||
// Gets the currently configured access levels
|
||||
/datum/topic_command/get_access_levels
|
||||
name = "get_access_levels"
|
||||
description = "Gets the currently configured access levels."
|
||||
|
||||
/datum/topic_command/get_access_levels/run_command()
|
||||
var/list/access_levels = list()
|
||||
for(var/datum/access/acc in get_all_access_datums())
|
||||
access_levels.Add(list(acc.get_info_list()))
|
||||
|
||||
data = access_levels
|
||||
statuscode = 200
|
||||
response = "Levels Sent"
|
||||
return TRUE
|
||||
|
||||
//Gets a overview of all polls (title, id, type)
|
||||
/datum/topic_command/get_polls
|
||||
name = "get_polls"
|
||||
description = "Gets a overview of all polls."
|
||||
params = list(
|
||||
"current_only" = list("name"="current_only","desc"="Only get information about the current polls","type"="int","req"=0),
|
||||
"admin_only" = list("name"="admin_only","desc"="Only get information about the admin_only polls","type"="int","req"=0)
|
||||
)
|
||||
|
||||
/datum/topic_command/get_polls/run_command(queryparams)
|
||||
var/current_only = text2num(queryparams["current_only"])
|
||||
var/admin_only = text2num(queryparams["admin_only"])
|
||||
|
||||
if(!establish_db_connection(dbcon))
|
||||
statuscode = 500
|
||||
response = "DB-Connection unavailable"
|
||||
return TRUE
|
||||
|
||||
var/list/polldata = list()
|
||||
|
||||
var/DBQuery/select_query = dbcon.NewQuery("SELECT id, polltype, starttime, endtime, question, multiplechoiceoptions, adminonly FROM ss13_poll_question [(current_only || admin_only) ? "WHERE" : ""] [(admin_only ? "adminonly = true " : "")][(current_only && admin_only ? "AND " : "")][(current_only ? "Now() BETWEEN starttime AND endtime" : "")]")
|
||||
select_query.Execute()
|
||||
while(select_query.NextRow())
|
||||
polldata["[select_query.item[1]]"] = list(
|
||||
"id"=select_query.item[1],
|
||||
"polltype"=select_query.item[2],
|
||||
"starttime"=select_query.item[3],
|
||||
"endtime"=select_query.item[4],
|
||||
"question"=select_query.item[5],
|
||||
"multiplechoiceoptions"=select_query.item[6],
|
||||
"adminonly"=select_query.item[7]
|
||||
)
|
||||
|
||||
statuscode = 200
|
||||
response = "Polldata sent"
|
||||
data = polldata
|
||||
return TRUE
|
||||
|
||||
|
||||
// Gets infos about a poll
|
||||
/datum/topic_command/get_poll_info
|
||||
name = "get_poll_info"
|
||||
description = "Gets Information about a poll."
|
||||
params = list(
|
||||
"poll_id" = list("name"="poll_id","desc"="The poll id that should be queried","type"="int","req"=1)
|
||||
)
|
||||
|
||||
/datum/topic_command/get_poll_info/run_command(queryparams)
|
||||
var/poll_id = text2num(queryparams["poll_id"])
|
||||
|
||||
if(!establish_db_connection(dbcon))
|
||||
statuscode = 500
|
||||
response = "DB-Connection unavailable"
|
||||
return TRUE
|
||||
|
||||
//Get general data about the poll
|
||||
var/DBQuery/select_query = dbcon.NewQuery("SELECT id, polltype, starttime, endtime, question, multiplechoiceoptions, adminonly, publicresult, viewtoken FROM ss13_poll_question WHERE id = :poll_id:")
|
||||
select_query.Execute(list("poll_id"=poll_id))
|
||||
|
||||
//Check if the poll exists
|
||||
if(!select_query.NextRow())
|
||||
statuscode = 404
|
||||
response = "The requested poll does not exist"
|
||||
data = null
|
||||
return TRUE
|
||||
var/list/poll_data = list(
|
||||
"id"=select_query.item[1],
|
||||
"polltype"=select_query.item[2],
|
||||
"starttime"=select_query.item[3],
|
||||
"endtime"=select_query.item[4],
|
||||
"question"=select_query.item[5],
|
||||
"multiplechoiceoptions"=select_query.item[6],
|
||||
"adminonly"=select_query.item[7],
|
||||
"publicresult"=select_query.item[8]
|
||||
)
|
||||
|
||||
//Lets add a WI link to the poll, if we have the WI configured
|
||||
if(config.webint_url)
|
||||
poll_data["link"]="[config.webint_url]server/poll/[select_query.item[1]]/[select_query.item[9]]"
|
||||
|
||||
var/list/result_data = list()
|
||||
|
||||
/** Return different data based on the poll type: */
|
||||
//If we have a option or a multiple choice poll, return the number of options
|
||||
if(poll_data["polltype"] == "OPTION" || poll_data["polltype"] == "MULTICHOICE")
|
||||
var/DBQuery/result_query = dbcon.NewQuery({"SELECT ss13_poll_vote.optionid, ss13_poll_option.text, COUNT(*) as option_count
|
||||
FROM ss13_poll_vote
|
||||
LEFT JOIN ss13_poll_option ON ss13_poll_vote.optionid = ss13_poll_option.id
|
||||
WHERE ss13_poll_vote.pollid = :poll_id:
|
||||
GROUP BY ss13_poll_vote.optionid"})
|
||||
result_query.Execute(list("poll_id"=poll_id))
|
||||
|
||||
while(result_query.NextRow())
|
||||
result_data["[result_query.item[1]]"] = list(
|
||||
"option_id"=result_query.item[1],
|
||||
"option_question"=result_query.item[2],
|
||||
"option_count"=result_query.item[3]
|
||||
)
|
||||
if(!length(result_data))
|
||||
statuscode = 500
|
||||
response = "No data returned by result query."
|
||||
data = null
|
||||
return TRUE
|
||||
|
||||
//If we have a numval poll, return the options with the min, max, and average
|
||||
else if(poll_data["polltype"] == "NUMVAL")
|
||||
var/DBQuery/result_query = dbcon.NewQuery({"SELECT ss13_poll_vote.optionid, ss13_poll_option.text, ss13_poll_option.minval, ss13_poll_option.maxval, ss13_poll_option.descmin, ss13_poll_option.descmid, ss13_poll_option.descmax, AVG(rating) as option_rating_avg, MIN(rating) as option_rating_min, MAX(rating) as option_rating_max
|
||||
FROM ss13_poll_vote
|
||||
LEFT JOIN ss13_poll_option ON ss13_poll_vote.optionid = ss13_poll_option.id
|
||||
WHERE ss13_poll_vote.pollid = :poll_id:
|
||||
GROUP BY ss13_poll_vote.optionid"})
|
||||
result_query.Execute(list("poll_id"=poll_id))
|
||||
while(result_query.NextRow())
|
||||
result_data["[result_query.item[1]]"] = list(
|
||||
"option_id"=result_query.item[1],
|
||||
"option_question"=result_query.item[2],
|
||||
"option_minval"=result_query.item[3],
|
||||
"option_maxval"=result_query.item[4],
|
||||
"option_descmin"=result_query.item[5],
|
||||
"option_descmid"=result_query.item[6],
|
||||
"option_descmax"=result_query.item[7],
|
||||
"option_rating_min"=result_query.item[8],
|
||||
"option_rating_max"=result_query.item[9],
|
||||
"option_rating_avg"=result_query.item[10] //TODO: Expand that with MEDIAN once we upgrade mariadb
|
||||
)
|
||||
if(!length(result_data))
|
||||
statuscode = 500
|
||||
response = "No data returned by result query."
|
||||
data = null
|
||||
return TRUE
|
||||
|
||||
//If we have a textpoll, return the number of answers
|
||||
else if(poll_data["polltype"] == "TEXT")
|
||||
var/DBQuery/result_query = dbcon.NewQuery({"SELECT COUNT(*) as count FROM ss13_poll_textreply WHERE pollid = :poll_id:"})
|
||||
result_query.Execute(list("poll_id"=poll_id))
|
||||
if(result_query.NextRow())
|
||||
result_data = list(
|
||||
"response_count"=result_query.item[1]
|
||||
)
|
||||
else
|
||||
statuscode = 500
|
||||
response = "No data returned by result query."
|
||||
data = null
|
||||
return TRUE
|
||||
else
|
||||
statuscode = 500
|
||||
response = "Unknown Poll Type"
|
||||
data = poll_data
|
||||
return TRUE
|
||||
|
||||
|
||||
poll_data["results"] = result_data
|
||||
|
||||
statuscode = 200
|
||||
response = "Poll data fetched"
|
||||
data = poll_data
|
||||
return TRUE
|
||||
90
code/modules/world_api/commands/server_management.dm
Normal file
90
code/modules/world_api/commands/server_management.dm
Normal file
@@ -0,0 +1,90 @@
|
||||
// Reloads the current cargo configuration
|
||||
/datum/topic_command/cargo_reload
|
||||
name = "cargo_reload"
|
||||
description = "Reloads the current cargo configuration."
|
||||
params = list(
|
||||
"force" = list("name"="force","desc"="Force the reload even if orders have already been placed","type"="int","req"=0)
|
||||
)
|
||||
|
||||
/datum/topic_command/cargo_reload/run_command(queryparams)
|
||||
var/force = text2num(queryparams["force"])
|
||||
if(!SScargo.get_order_count())
|
||||
SScargo.load_from_sql()
|
||||
message_admins("Cargo has been reloaded via the API.")
|
||||
statuscode = 200
|
||||
response = "Cargo Reloaded from SQL."
|
||||
else
|
||||
if(force)
|
||||
SScargo.load_from_sql()
|
||||
message_admins("Cargo has been force-reloaded via the API. All current orders have been purged.")
|
||||
statuscode = 200
|
||||
response = "Cargo Force-Reloaded from SQL."
|
||||
else
|
||||
statuscode = 500
|
||||
response = "Orders have been placed. Use force parameter to overwrite."
|
||||
return TRUE
|
||||
|
||||
// Update discord_bot's channels.
|
||||
/datum/topic_command/update_bot_channels
|
||||
name = "update_bot_channels"
|
||||
description = "Tells the ingame instance of the Discord bot to update its cached channels list."
|
||||
|
||||
/datum/topic_command/update_bot_channels/run_command()
|
||||
data = null
|
||||
|
||||
if (!discord_bot)
|
||||
statuscode = 404
|
||||
response = "Ingame Discord bot not initialized."
|
||||
return 1
|
||||
|
||||
switch (discord_bot.update_channels())
|
||||
if (1)
|
||||
statuscode = 404
|
||||
response = "Ingame Discord bot is not active."
|
||||
if (2)
|
||||
statuscode = 500
|
||||
response = "Ingame Discord bot encountered error attempting to access database."
|
||||
else
|
||||
statuscode = 200
|
||||
response = "Ingame Discord bot's channels were successfully updated."
|
||||
|
||||
return TRUE
|
||||
|
||||
//Restart Round
|
||||
/datum/topic_command/restart_round
|
||||
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")
|
||||
)
|
||||
|
||||
/datum/topic_command/restart_round/run_command(queryparams)
|
||||
var/senderkey = sanitize(queryparams["senderkey"]) //Identifier of the sender (Ckey / Userid / ...)
|
||||
|
||||
to_world("<font size=4 color='#ff2222'>Server restarting by remote command.</font>")
|
||||
log_and_message_admins("World restart initiated remotely by [senderkey].")
|
||||
feedback_set_details("end_error","remote restart")
|
||||
|
||||
spawn(50)
|
||||
log_game("Rebooting due to remote command.")
|
||||
world.Reboot("Rebooting due to remote command.")
|
||||
|
||||
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(
|
||||
"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"])
|
||||
|
||||
statuscode = 200
|
||||
response = "Text sent"
|
||||
return TRUE
|
||||
295
code/modules/world_api/commands/server_query.dm
Normal file
295
code/modules/world_api/commands/server_query.dm
Normal file
@@ -0,0 +1,295 @@
|
||||
//Get Server Status
|
||||
/datum/topic_command/get_serverstatus
|
||||
name = "get_serverstatus"
|
||||
description = "Gets the server status."
|
||||
no_auth = TRUE
|
||||
|
||||
/datum/topic_command/get_serverstatus/run_command(queryparams)
|
||||
var/list/s[] = list()
|
||||
s["version"] = game_version
|
||||
s["mode"] = master_mode
|
||||
s["respawn"] = config.abandon_allowed
|
||||
s["enter"] = config.enter_allowed
|
||||
s["vote"] = config.allow_vote_mode
|
||||
s["ai"] = config.allow_ai
|
||||
s["host"] = host ? host : null
|
||||
s["stationtime"] = worldtime2text()
|
||||
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["players"] = clients.len
|
||||
s["admins"] = 0
|
||||
|
||||
for(var/client/C in clients)
|
||||
if(C.holder)
|
||||
if(C.holder.fakekey)
|
||||
continue
|
||||
|
||||
s["admins"]++
|
||||
|
||||
statuscode = 200
|
||||
response = "Server status fetched."
|
||||
data = s
|
||||
return TRUE
|
||||
|
||||
|
||||
//Get a Staff List
|
||||
/datum/topic_command/get_stafflist
|
||||
name = "get_stafflist"
|
||||
description = "Gets a list of connected staffmembers"
|
||||
|
||||
/datum/topic_command/get_stafflist/run_command(queryparams)
|
||||
var/list/staff = list()
|
||||
for (var/client/C in admins)
|
||||
staff[C] = C.holder.rank
|
||||
|
||||
statuscode = 200
|
||||
response = "Staff list fetched"
|
||||
data = staff
|
||||
return TRUE
|
||||
|
||||
//Char Names
|
||||
/datum/topic_command/get_char_list
|
||||
name = "get_char_list"
|
||||
description = "Provides a list of all characters ingame"
|
||||
|
||||
/datum/topic_command/get_char_list/run_command(queryparams)
|
||||
var/list/chars = list()
|
||||
|
||||
var/list/mobs = sortmobs()
|
||||
for(var/mob/M in mobs)
|
||||
if(!M.ckey) continue
|
||||
chars[M.name] += M.key ? (M.client ? M.key : "[M.key] (DC)") : "No key"
|
||||
|
||||
statuscode = 200
|
||||
response = "Char list fetched"
|
||||
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_count_admin/run_command(queryparams)
|
||||
var/n = 0
|
||||
for (var/client/client in clients)
|
||||
if (client.holder && client.holder.rights & (R_ADMIN))
|
||||
n++
|
||||
|
||||
statuscode = 200
|
||||
response = "Admin count fetched"
|
||||
data = n
|
||||
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_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++
|
||||
|
||||
statuscode = 200
|
||||
response = "CCIA count fetched"
|
||||
data = n
|
||||
return TRUE
|
||||
|
||||
//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
|
||||
/datum/topic_command/get_count_player
|
||||
name = "get_count_player"
|
||||
description = "Gets the number of players connected"
|
||||
no_auth = TRUE
|
||||
|
||||
/datum/topic_command/get_count_player/run_command(queryparams)
|
||||
var/n = 0
|
||||
for(var/mob/M in player_list)
|
||||
if(M.client)
|
||||
n++
|
||||
|
||||
statuscode = 200
|
||||
response = "Player count fetched"
|
||||
data = n
|
||||
return TRUE
|
||||
|
||||
//Get Ghosts
|
||||
/datum/topic_command/get_ghosts
|
||||
name = "get_ghosts"
|
||||
description = "Gets the ghosts"
|
||||
|
||||
/datum/topic_command/get_ghosts/run_command(queryparams)
|
||||
var/list/ghosts[] = list()
|
||||
ghosts = get_ghosts(1,1)
|
||||
|
||||
statuscode = 200
|
||||
response = "Fetched Ghost list"
|
||||
data = ghosts
|
||||
return TRUE
|
||||
|
||||
// Crew Manifest
|
||||
/datum/topic_command/get_manifest
|
||||
name = "get_manifest"
|
||||
description = "Gets the crew manifest"
|
||||
|
||||
/datum/topic_command/get_manifest/run_command(queryparams)
|
||||
var/list/positions = list()
|
||||
var/list/set_names = list(
|
||||
"heads" = command_positions,
|
||||
"sec" = security_positions,
|
||||
"eng" = engineering_positions,
|
||||
"med" = medical_positions,
|
||||
"sci" = science_positions,
|
||||
"civ" = civilian_positions,
|
||||
"bot" = nonhuman_positions
|
||||
)
|
||||
|
||||
for(var/datum/data/record/t in data_core.general)
|
||||
var/name = t.fields["name"]
|
||||
var/rank = t.fields["rank"]
|
||||
var/real_rank = make_list_rank(t.fields["real_rank"])
|
||||
|
||||
var/department = 0
|
||||
for(var/k in set_names)
|
||||
if(real_rank in set_names[k])
|
||||
if(!positions[k])
|
||||
positions[k] = list()
|
||||
positions[k][name] = rank
|
||||
department = 1
|
||||
if(!department)
|
||||
if(!positions["misc"])
|
||||
positions["misc"] = list()
|
||||
positions["misc"][name] = rank
|
||||
|
||||
statuscode = 200
|
||||
response = "Manifest fetched"
|
||||
data = positions
|
||||
return TRUE
|
||||
|
||||
//Player Ckeys
|
||||
/datum/topic_command/get_player_list
|
||||
name = "get_player_list"
|
||||
description = "Gets a list of connected players"
|
||||
params = list(
|
||||
"showadmins" = list("name"="show admins","desc"="A boolean to toggle whether or not hidden admins should be shown with proper or improper ckeys.","req"=0,"type"="int")
|
||||
)
|
||||
|
||||
/datum/topic_command/get_player_list/run_command(queryparams)
|
||||
var/show_hidden_admins = 0
|
||||
|
||||
if (!isnull(queryparams["showadmins"]))
|
||||
show_hidden_admins = text2num(queryparams["showadmins"])
|
||||
|
||||
var/list/players = list()
|
||||
for (var/client/C in clients)
|
||||
if (show_hidden_admins && C.holder && C.holder.fakekey)
|
||||
players += ckey(C.holder.fakekey)
|
||||
else
|
||||
players += C.ckey
|
||||
|
||||
statuscode = 200
|
||||
response = "Player list fetched"
|
||||
data = players
|
||||
return TRUE
|
||||
|
||||
//Get info about a specific player
|
||||
/datum/topic_command/get_player_info
|
||||
name = "get_player_info"
|
||||
description = "Gets information about a specific player"
|
||||
params = list(
|
||||
"search" = list("name"="search","desc"="List with strings that should be searched for","req"=1,"type"="lst")
|
||||
)
|
||||
|
||||
/datum/topic_command/get_player_info/run_command(queryparams)
|
||||
var/list/search = queryparams["search"]
|
||||
|
||||
var/list/ckeysearch = list()
|
||||
for(var/text in search)
|
||||
ckeysearch += ckey(text)
|
||||
|
||||
var/list/match = list()
|
||||
|
||||
for(var/mob/M in mob_list)
|
||||
var/strings = list(M.name, M.ckey)
|
||||
if(M.mind)
|
||||
strings += M.mind.assigned_role
|
||||
strings += M.mind.special_role
|
||||
for(var/text in strings)
|
||||
if(ckey(text) in ckeysearch)
|
||||
match[M] += 10 // an exact match is far better than a partial one
|
||||
else
|
||||
for(var/searchstr in search)
|
||||
if(findtext(text, searchstr))
|
||||
match[M] += 1
|
||||
|
||||
var/maxstrength = 0
|
||||
for(var/mob/M in match)
|
||||
maxstrength = max(match[M], maxstrength)
|
||||
for(var/mob/M in match)
|
||||
if(match[M] < maxstrength)
|
||||
match -= M
|
||||
|
||||
if(!match.len)
|
||||
statuscode = 449
|
||||
response = "No match found"
|
||||
data = null
|
||||
return TRUE
|
||||
else if(match.len == 1)
|
||||
var/mob/M = match[1]
|
||||
var/info = list()
|
||||
info["key"] = M.key
|
||||
if (M.client)
|
||||
var/client/C = M.client
|
||||
info["discordmuted"] = C.mute_discord ? "Yes" : "No"
|
||||
info["name"] = M.name == M.real_name ? M.name : "[M.name] ([M.real_name])"
|
||||
info["role"] = M.mind ? (M.mind.assigned_role ? M.mind.assigned_role : "No role") : "No mind"
|
||||
var/turf/MT = get_turf(M)
|
||||
info["loc"] = M.loc ? "[M.loc]" : "null"
|
||||
info["turf"] = MT ? "[MT] @ [MT.x], [MT.y], [MT.z]" : "null"
|
||||
info["area"] = MT ? "[MT.loc]" : "null"
|
||||
info["antag"] = M.mind ? (M.mind.special_role ? M.mind.special_role : "Not antag") : "No mind"
|
||||
info["hasbeenrev"] = M.mind ? M.mind.has_been_rev : "No mind"
|
||||
info["stat"] = M.stat
|
||||
info["type"] = M.type
|
||||
if(isliving(M))
|
||||
var/mob/living/L = M
|
||||
info["damage"] = list2params(list(
|
||||
oxy = L.getOxyLoss(),
|
||||
tox = L.getToxLoss(),
|
||||
fire = L.getFireLoss(),
|
||||
brute = L.getBruteLoss(),
|
||||
clone = L.getCloneLoss(),
|
||||
brain = L.getBrainLoss()
|
||||
))
|
||||
else
|
||||
info["damage"] = "non-living"
|
||||
info["gender"] = M.gender
|
||||
statuscode = 200
|
||||
response = "Client data fetched"
|
||||
data = info
|
||||
return TRUE
|
||||
else
|
||||
statuscode = 449
|
||||
response = "Multiple Matches found"
|
||||
data = null
|
||||
return TRUE
|
||||
105
code/modules/world_api/commands/tickets.dm
Normal file
105
code/modules/world_api/commands/tickets.dm
Normal file
@@ -0,0 +1,105 @@
|
||||
/datum/topic_command/tickets_info
|
||||
name = "get_ticketsinfo"
|
||||
description = "Lists a general overview of tickets in the current round."
|
||||
|
||||
/datum/topic_command/tickets_info/run_command(queryparams)
|
||||
statuscode = 200
|
||||
response = "General tickets overview."
|
||||
|
||||
var/list/ticket_data = list(
|
||||
"total" = tickets.len,
|
||||
"assigned" = 0,
|
||||
"unassigned" = 0,
|
||||
"closed" = 0
|
||||
)
|
||||
|
||||
for (var/id in tickets)
|
||||
var/datum/ticket/ticket = tickets[id]
|
||||
switch (ticket.status)
|
||||
if (TICKET_OPEN)
|
||||
ticket_data["unassigned"]++
|
||||
if (TICKET_ASSIGNED)
|
||||
ticket_data["assigned"]++
|
||||
if (TICKET_CLOSED)
|
||||
ticket_data["closed"]++
|
||||
|
||||
data = ticket_data
|
||||
return TRUE
|
||||
|
||||
|
||||
/datum/topic_command/tickets_list
|
||||
name = "get_ticketslist"
|
||||
description = "Lists tickets in the current round."
|
||||
params = list(
|
||||
"only_open" = list("name"="only_open","desc"="If present, only opened tickets are listed.","req"=0,"type"="int")
|
||||
)
|
||||
|
||||
/datum/topic_command/tickets_list/run_command(queryparams)
|
||||
statuscode = 200
|
||||
response = "Tickets list."
|
||||
|
||||
var/only_open = !!queryparams["only_open"]
|
||||
|
||||
var/list/ticket_data = list()
|
||||
|
||||
for (var/datum/ticket/ticket in tickets)
|
||||
if (!only_open || ticket.status == TICKET_CLOSED)
|
||||
continue
|
||||
|
||||
ticket_data["[ticket.id]"] = serialize_ticket(ticket)
|
||||
|
||||
data = ticket_data
|
||||
return TRUE
|
||||
|
||||
/datum/topic_command/tickets_list/proc/serialize_ticket(datum/ticket/ticket)
|
||||
return list(
|
||||
"id" = ticket.id,
|
||||
"owner" = ticket.owner,
|
||||
"status" = ticket.status,
|
||||
"closed_by" = ticket.closed_by,
|
||||
"opened_time" = ticket.opened_time,
|
||||
"assigned_admins" = ticket.assigned_admins,
|
||||
"message_count" = ticket.msgs.len
|
||||
)
|
||||
|
||||
/datum/topic_command/tickets_close
|
||||
name = "tickets_close"
|
||||
description = "Closes the listed ticket."
|
||||
params = list(
|
||||
"id" = list("name"="id","desc"="The ID of the ticket to be closed.","req"=1,"type"="int"),
|
||||
"admin" = list("name"="admin","desc"="Ckey of the admin who is closing the ticket.","req"=1,"type"="str")
|
||||
)
|
||||
|
||||
/datum/topic_command/tickets_close/run_command(queryparams)
|
||||
if (!queryparams["id"] || !isnum(queryparams["id"]))
|
||||
response = "No or invalid ID provided."
|
||||
statuscode = 400
|
||||
data = null
|
||||
return TRUE
|
||||
|
||||
var/id = text2num(queryparams["id"])
|
||||
|
||||
if (!queryparams["admin"] || !ckey(queryparams["admin"]))
|
||||
response = "No administrator ckey provided."
|
||||
statuscode = 400
|
||||
data = null
|
||||
return TRUE
|
||||
|
||||
var/ckey = ckey(queryparams["admin"])
|
||||
|
||||
var/datum/ticket/ticket = get_ticket_by_id(id)
|
||||
|
||||
if (!ticket)
|
||||
response = "Ticket not found with the given ID."
|
||||
statuscode = 404
|
||||
data = null
|
||||
return TRUE
|
||||
|
||||
if (ticket.close_remotely(ckey))
|
||||
response = "Ticket successfully closed."
|
||||
statuscode = 200
|
||||
return TRUE
|
||||
else
|
||||
response = "Unable to close the ticket."
|
||||
statuscode = 500
|
||||
return TRUE
|
||||
Reference in New Issue
Block a user