mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-07-21 12:04:48 +01:00
Logs tickets to the DB (#19679)
* Logs tickets to the DB * Awho tracking * This aint needed
This commit is contained in:
@@ -18,6 +18,7 @@ GLOBAL_REAL(SSmentor_tickets, /datum/controller/subsystem/tickets/mentor_tickets
|
||||
other_ticket_permission = R_ADMIN
|
||||
close_rights = R_MENTOR | R_ADMIN
|
||||
rights_needed = R_MENTOR | R_ADMIN | R_MOD
|
||||
db_save_id = "MENTOR"
|
||||
|
||||
/datum/controller/subsystem/tickets/mentor_tickets/Initialize()
|
||||
close_messages = list("<font color='red' size='3'><b>- [ticket_name] Closed -</b></font>",
|
||||
@@ -29,7 +30,7 @@ GLOBAL_REAL(SSmentor_tickets, /datum/controller/subsystem/tickets/mentor_tickets
|
||||
message_mentorTicket(msg, important)
|
||||
|
||||
/datum/controller/subsystem/tickets/mentor_tickets/create_other_system_ticket(datum/ticket/T)
|
||||
SStickets.newTicket(get_client_by_ckey(T.client_ckey), T.content, T.raw_title)
|
||||
SStickets.newTicket(get_client_by_ckey(T.client_ckey), T.first_raw_response, T.raw_title)
|
||||
|
||||
/datum/controller/subsystem/tickets/mentor_tickets/autoRespond(N)
|
||||
return
|
||||
|
||||
@@ -41,6 +41,9 @@ SUBSYSTEM_DEF(tickets)
|
||||
|
||||
var/ticketCounter = 1
|
||||
|
||||
/// DB ID for these tickets to be logged with
|
||||
var/db_save_id = "ADMIN"
|
||||
|
||||
/datum/controller/subsystem/tickets/get_metrics()
|
||||
. = ..()
|
||||
var/list/cust = list()
|
||||
@@ -140,9 +143,8 @@ SUBSYSTEM_DEF(tickets)
|
||||
var/new_ticket_num = getTicketCounterAndInc()
|
||||
var/url_title = makeUrlMessage(C, title, new_ticket_num)
|
||||
|
||||
var/datum/ticket/T = new(url_title, title, passedContent, new_ticket_num)
|
||||
var/datum/ticket/T = new(url_title, title, passedContent, new_ticket_num, C.ckey)
|
||||
allTickets += T
|
||||
T.client_ckey = C.ckey
|
||||
T.locationSent = C.mob.loc.name
|
||||
T.mobControlled = C.mob
|
||||
|
||||
@@ -202,7 +204,7 @@ SUBSYSTEM_DEF(tickets)
|
||||
|
||||
/datum/controller/subsystem/tickets/proc/create_other_system_ticket(datum/ticket/T)
|
||||
var/client/C = get_client_by_ckey(T.client_ckey)
|
||||
SSmentor_tickets.newTicket(C, T.content, T.raw_title)
|
||||
SSmentor_tickets.newTicket(C, T.first_raw_response, T.raw_title)
|
||||
|
||||
/datum/controller/subsystem/tickets/proc/autoRespond(N)
|
||||
if(!check_rights(rights_needed))
|
||||
@@ -224,7 +226,7 @@ SUBSYSTEM_DEF(tickets)
|
||||
"IC Issue" = "This is an In Character (IC) issue and will not be handled by admins. You could speak to Security, Internal Affairs, a Departmental Head, Nanotrasen Representetive, or any other relevant authority currently on station.",
|
||||
"Reject" = "Reject",
|
||||
"Man Up" = "Man Up",
|
||||
)
|
||||
)
|
||||
|
||||
if(GLOB.configuration.url.banappeals_url)
|
||||
response_phrases["Appeal on the Forums"] = "Appealing a ban must occur on the forums. Privately messaging, or adminhelping about your ban will not resolve it. To appeal your ban, please head to <a href='[GLOB.configuration.url.banappeals_url]'>[GLOB.configuration.url.banappeals_url]</a>"
|
||||
@@ -240,7 +242,7 @@ SUBSYSTEM_DEF(tickets)
|
||||
var/client/ticket_owner = get_client_by_ckey(T.client_ckey)
|
||||
switch(message_key)
|
||||
if(null) //they cancelled
|
||||
T.staffAssigned = initial(T.staffAssigned) //if they cancel we dont need to hold this ticket anymore
|
||||
T.staffAssigned = null //if they cancel we dont need to hold this ticket anymore
|
||||
return
|
||||
if("Reject")
|
||||
if(!closeTicket(N))
|
||||
@@ -306,14 +308,16 @@ SUBSYSTEM_DEF(tickets)
|
||||
var/ticketNum
|
||||
/// ckey of the client who opened the ticket.
|
||||
var/client_ckey
|
||||
/// Time the ticket was opened.
|
||||
var/timeOpened
|
||||
/// Real time the ticket was opened.
|
||||
var/real_time_opened
|
||||
/// Ingame time the ticket was opened
|
||||
var/ingame_time_opened
|
||||
/// The initial message with links.
|
||||
var/title
|
||||
/// The title without URLs added.
|
||||
var/raw_title
|
||||
/// Content of the staff help.
|
||||
var/list/content
|
||||
var/list/datum/ticket_response/ticket_responses
|
||||
/// Last staff member who responded.
|
||||
var/lastStaffResponse
|
||||
/// When the staff last responded.
|
||||
@@ -332,18 +336,38 @@ SUBSYSTEM_DEF(tickets)
|
||||
var/ticketCooldown
|
||||
/// Staff member who has assigned themselves to this ticket.
|
||||
var/client/staffAssigned
|
||||
/// The first raw response. Used for ticket conversions
|
||||
var/first_raw_response
|
||||
/// Staff member ckey who took it
|
||||
var/staff_ckey
|
||||
/// The time the staff member took the ticket
|
||||
var/staff_take_time
|
||||
/// List of adminwho data
|
||||
var/list/adminwho_data = list()
|
||||
|
||||
/datum/ticket/New(tit, raw_tit, cont, num)
|
||||
|
||||
/datum/ticket/New(tit, raw_tit, cont, num, the_ckey)
|
||||
title = tit
|
||||
raw_title = raw_tit
|
||||
content = list()
|
||||
content += cont
|
||||
timeOpened = worldtime2text()
|
||||
client_ckey = the_ckey
|
||||
first_raw_response = cont
|
||||
ticket_responses = list()
|
||||
ticket_responses += new /datum/ticket_response(cont, the_ckey)
|
||||
real_time_opened = SQLtime()
|
||||
ingame_time_opened = (ROUND_TIME ? time2text(ROUND_TIME, "hh:mm:ss") : 0)
|
||||
timeUntilStale = world.time + TICKET_TIMEOUT
|
||||
setCooldownPeriod()
|
||||
ticketNum = num
|
||||
ticketState = TICKET_OPEN
|
||||
|
||||
var/list/this_data = list()
|
||||
for(var/client/C in GLOB.admins)
|
||||
this_data["ckey"] = C.ckey
|
||||
this_data["rank"] = C.holder.rank
|
||||
this_data["afk"] = C.inactivity
|
||||
|
||||
adminwho_data += list(this_data)
|
||||
|
||||
//Set the cooldown period for the ticket. The time when it's created plus the defined cooldown time.
|
||||
/datum/ticket/proc/setCooldownPeriod()
|
||||
ticketCooldown = world.time + TICKET_DUPLICATE_COOLDOWN
|
||||
@@ -372,18 +396,36 @@ SUBSYSTEM_DEF(tickets)
|
||||
if(!C)
|
||||
return
|
||||
staffAssigned = C
|
||||
staff_ckey = C.ckey
|
||||
staff_take_time = SQLtime()
|
||||
return TRUE
|
||||
|
||||
/datum/ticket/proc/addResponse(client/C, msg)
|
||||
if(C.holder)
|
||||
setLastStaffResponse(C)
|
||||
msg = "[C]: [msg]"
|
||||
content += msg
|
||||
ticket_responses += new /datum/ticket_response(msg, C.ckey)
|
||||
|
||||
/datum/ticket/proc/makeStale()
|
||||
ticketState = TICKET_STALE
|
||||
return ticketNum
|
||||
|
||||
// Staff ticket response
|
||||
/datum/ticket_response
|
||||
/// Text of this response
|
||||
var/response_text
|
||||
/// Who made the response
|
||||
var/response_user
|
||||
/// The time of the response
|
||||
var/response_time
|
||||
|
||||
/datum/ticket_response/New(the_text, the_ckey)
|
||||
response_text = the_text
|
||||
response_user = the_ckey
|
||||
response_time = SQLtime()
|
||||
|
||||
/datum/ticket_response/proc/to_string()
|
||||
return "[response_user]: [response_text]"
|
||||
|
||||
/*
|
||||
|
||||
UI STUFF
|
||||
@@ -412,7 +454,7 @@ UI STUFF
|
||||
for(var/T in allTickets)
|
||||
ticket = T
|
||||
if(ticket.ticketState == TICKET_OPEN || ticket.ticketState == TICKET_STALE)
|
||||
dat += "<tr style='[trStyle]'><td style ='[tdStyleleft]'><a href='?src=[UID()];resolve=[ticket.ticketNum]'>Resolve</a><a href='?src=[UID()];details=[ticket.ticketNum]'>Details</a> <br /> #[ticket.ticketNum] ([ticket.timeOpened]) [ticket.ticketState == TICKET_STALE ? "<font color='red'><b>STALE</font>" : ""] </td><td style='[tdStyle]'><b>[ticket.title]</td></tr>"
|
||||
dat += "<tr style='[trStyle]'><td style ='[tdStyleleft]'><a href='?src=[UID()];resolve=[ticket.ticketNum]'>Resolve</a><a href='?src=[UID()];details=[ticket.ticketNum]'>Details</a> <br /> #[ticket.ticketNum] ([ticket.ingame_time_opened]) [ticket.ticketState == TICKET_STALE ? "<font color='red'><b>STALE</font>" : ""] </td><td style='[tdStyle]'><b>[ticket.title]</td></tr>"
|
||||
else
|
||||
continue
|
||||
else if(tab == TICKET_RESOLVED)
|
||||
@@ -420,7 +462,7 @@ UI STUFF
|
||||
for(var/T in allTickets)
|
||||
ticket = T
|
||||
if(ticket.ticketState == TICKET_RESOLVED)
|
||||
dat += "<tr style='[trStyle]'><td style ='[tdStyleleft]'><a href='?src=[UID()];resolve=[ticket.ticketNum]'>Resolve</a><a href='?src=[UID()];details=[ticket.ticketNum]'>Details</a> <br /> #[ticket.ticketNum] ([ticket.timeOpened]) </td><td style='[tdStyle]'><b>[ticket.title]</td></tr>"
|
||||
dat += "<tr style='[trStyle]'><td style ='[tdStyleleft]'><a href='?src=[UID()];resolve=[ticket.ticketNum]'>Resolve</a><a href='?src=[UID()];details=[ticket.ticketNum]'>Details</a> <br /> #[ticket.ticketNum] ([ticket.ingame_time_opened]) </td><td style='[tdStyle]'><b>[ticket.title]</td></tr>"
|
||||
else
|
||||
continue
|
||||
else if(tab == TICKET_CLOSED)
|
||||
@@ -428,7 +470,7 @@ UI STUFF
|
||||
for(var/T in allTickets)
|
||||
ticket = T
|
||||
if(ticket.ticketState == TICKET_CLOSED)
|
||||
dat += "<tr style='[trStyle]'><td style ='[tdStyleleft]'><a href='?src=[UID()];resolve=[ticket.ticketNum]'>Resolve</a><a href='?src=[UID()];details=[ticket.ticketNum]'>Details</a> <br /> #[ticket.ticketNum] ([ticket.timeOpened]) </td><td style='[tdStyle]'><b>[ticket.title]</td></tr>"
|
||||
dat += "<tr style='[trStyle]'><td style ='[tdStyleleft]'><a href='?src=[UID()];resolve=[ticket.ticketNum]'>Resolve</a><a href='?src=[UID()];details=[ticket.ticketNum]'>Details</a> <br /> #[ticket.ticketNum] ([ticket.ingame_time_opened]) </td><td style='[tdStyle]'><b>[ticket.title]</td></tr>"
|
||||
else
|
||||
continue
|
||||
|
||||
@@ -458,14 +500,15 @@ UI STUFF
|
||||
|
||||
dat += "<h2>Ticket #[T.ticketNum]</h2>"
|
||||
|
||||
dat += "<h3>[T.client_ckey] / [T.mobControlled] opened this [ticket_name] at [T.timeOpened] at location [T.locationSent]</h3>"
|
||||
dat += "<h3>[T.client_ckey] / [T.mobControlled] opened this [ticket_name] at [T.ingame_time_opened] at location [T.locationSent]</h3>"
|
||||
dat += "<h4>Ticket Status: [status]"
|
||||
dat += "<table style='width:950px; border: 3px solid;'>"
|
||||
dat += "<tr><td>[T.title]</td></tr>"
|
||||
|
||||
if(T.content.len > 1)
|
||||
for(var/i = 2, i <= T.content.len, i++)
|
||||
dat += "<tr><td>[T.content[i]]</td></tr>"
|
||||
if(length(T.ticket_responses) > 1)
|
||||
for(var/i in 2 to length(T.ticket_responses))
|
||||
var/datum/ticket_response/TR = T.ticket_responses[i]
|
||||
dat += "<tr><td>[TR.to_string()]</td></tr>"
|
||||
|
||||
dat += "</table><br /><br />"
|
||||
dat += "<a href='?src=[UID()];detailreopen=[T.ticketNum]'>Re-Open</a>[check_rights(rights_needed, 0) ? "<a href='?src=[UID()];autorespond=[T.ticketNum]'>Auto</a>": ""]<a href='?src=[UID()];detailresolve=[T.ticketNum]'>Resolve</a><br /><br />"
|
||||
@@ -497,8 +540,9 @@ UI STUFF
|
||||
dat += "<table>"
|
||||
for(var/datum/ticket/T in tickets)
|
||||
dat += "<tr><td><h2>Ticket #[T.ticketNum]</h2></td></tr>"
|
||||
for(var/i = 1, i <= T.content.len, i++)
|
||||
dat += "<tr><td>[T.content[i]]</td></tr>"
|
||||
for(var/i in 1 to length(T.ticket_responses))
|
||||
var/datum/ticket_response/TR = T.ticket_responses[i]
|
||||
dat += "<tr><td>[TR.to_string()]</td></tr>"
|
||||
dat += "</table>"
|
||||
|
||||
var/datum/browser/popup = new(user, "[ticket_system_name]userticketsdetail", ticket_system_name, 1000, 600)
|
||||
@@ -625,5 +669,58 @@ UI STUFF
|
||||
else
|
||||
message_staff("<span class='admin_channel'>[usr.client] / ([usr]) has unassigned [ticket_name] number [index]</span>", TICKET_STAFF_MESSAGE_ADMIN_CHANNEL)
|
||||
|
||||
|
||||
/datum/controller/subsystem/tickets/Shutdown()
|
||||
// Lets get saving these tickets
|
||||
var/list/datum/db_query/all_queries = list()
|
||||
|
||||
for(var/datum/ticket/T in allTickets)
|
||||
var/end_state_txt = "UNKNOWN"
|
||||
|
||||
switch(T.ticketState)
|
||||
if(TICKET_OPEN)
|
||||
end_state_txt = "OPEN"
|
||||
if(TICKET_CLOSED)
|
||||
end_state_txt = "CLOSED"
|
||||
if(TICKET_RESOLVED)
|
||||
end_state_txt = "RESOLVED"
|
||||
if(TICKET_STALE)
|
||||
end_state_txt = "STALE"
|
||||
|
||||
// Lets sort our responses out
|
||||
var/list/raw_responses = list()
|
||||
for(var/datum/ticket_response/TR in T.ticket_responses)
|
||||
var/list/this_response = list()
|
||||
this_response["ckey"] = TR.response_user
|
||||
this_response["text"] = strip_html_tags(TR.response_text) // Dont want to save HTML tags in the thing
|
||||
this_response["time"] = TR.response_time
|
||||
|
||||
raw_responses += list(this_response)
|
||||
|
||||
var/all_responses_txt = json_encode(raw_responses)
|
||||
|
||||
var/datum/db_query/Q = SSdbcore.NewQuery({"INSERT INTO tickets
|
||||
(ticket_num, ticket_type, real_filetime, relative_filetime, ticket_creator, ticket_topic, ticket_taker, ticket_take_time, all_responses, end_round_state, awho)
|
||||
VALUES
|
||||
(:tnum, :ttype, :realt, :relativet, :tcreator, :ttopic, :ttaker, :ttaketime, :allresponses, :endstate, :awho)"},
|
||||
list(
|
||||
"tnum" = T.ticketNum,
|
||||
"ttype" = db_save_id,
|
||||
"realt" = T.real_time_opened,
|
||||
"relativet" = T.ingame_time_opened,
|
||||
"tcreator" = T.client_ckey,
|
||||
"ttopic" = T.raw_title,
|
||||
"ttaker" = T.staff_ckey,
|
||||
"ttaketime" = T.staff_take_time,
|
||||
"allresponses" = all_responses_txt,
|
||||
"endstate" = end_state_txt,
|
||||
"awho" = json_encode(T.adminwho_data),
|
||||
))
|
||||
|
||||
all_queries += Q
|
||||
|
||||
SSdbcore.MassExecute(all_queries, TRUE, TRUE, FALSE, TRUE)
|
||||
|
||||
|
||||
#undef TICKET_STAFF_MESSAGE_ADMIN_CHANNEL
|
||||
#undef TICKET_STAFF_MESSAGE_PREFIX
|
||||
|
||||
Reference in New Issue
Block a user