var/global/list/tickets = list() var/global/list/ticket_panels = list() /datum/ticket var/owner var/list/assigned_admins = list() var/status = TICKET_OPEN var/list/msgs = list() var/closed_by var/id var/opened_time // Real time references for SQL based logging. var/opened_rt var/closed_rt var/response_time var/reminder_timer /datum/ticket/New(var/owner) src.owner = owner tickets |= src id = tickets.len opened_time = world.time opened_rt = world.realtime if (config.ticket_reminder_period) reminder_timer = addtimer(CALLBACK(src, .proc/remind), config.ticket_reminder_period SECONDS, TIMER_UNIQUE|TIMER_STOPPABLE) /datum/ticket/proc/broadcast_closure(closing_user) var/client/owner_client = client_by_ckey(owner) if(owner_client && owner_client.adminhelped == ADMINHELPED_DISCORD) discord_bot.send_to_admins("[key_name(owner_client)]'s request for help has been closed/deemed unnecessary by [closing_user].") owner_client.adminhelped = ADMINHELPED /datum/ticket/proc/set_to_closed(closing_key) src.status = TICKET_CLOSED src.closed_by = closing_key src.closed_rt = world.realtime update_ticket_panels() if (reminder_timer) deltimer(reminder_timer) log_to_db() /datum/ticket/proc/close(var/client/closed_by) if(!closed_by) return FALSE if(status == TICKET_CLOSED) return FALSE if(status == TICKET_ASSIGNED && !((closed_by.ckey in assigned_admins) || owner == closed_by.ckey) && alert(closed_by, "You are not assigned to this ticket. Are you sure you want to close it?", "Close ticket?" , "Yes" , "No") != "Yes") return FALSE if(status == TICKET_ASSIGNED && !closed_by.holder) // non-admins can only close a ticket if no admin has taken it return FALSE broadcast_closure(key_name(closed_by)) to_chat(client_by_ckey(src.owner), "Your ticket has been closed by [closed_by].") message_admins("[src.owner]'s ticket has been closed by [key_name(closed_by)].") set_to_closed(closed_by.ckey) return TRUE /datum/ticket/proc/close_remotely(closing_user) if (!closing_user) return FALSE if (status != TICKET_OPEN) return FALSE broadcast_closure("[closing_user] (Remotely)") to_chat(client_by_ckey(src.owner), "Your ticket has been closed by [closing_user] (remotely).") message_admins("[src.owner]'s ticket has been closed by [closing_user] (remotely).") set_to_closed(closing_user) return TRUE /datum/ticket/proc/take(var/client/assigned_admin) if(!assigned_admin) return if(status == TICKET_CLOSED) return if(assigned_admin.ckey == owner) return if(status == TICKET_ASSIGNED && ((assigned_admin.ckey in assigned_admins) || alert(assigned_admin, "This ticket is already assigned. Do you want to add yourself to the ticket?", "Join ticket?" , "Yes" , "No") != "Yes")) return assigned_admins |= assigned_admin.ckey src.status = TICKET_ASSIGNED var/client/owner_client = client_by_ckey(src.owner) if(owner_client && owner_client.adminhelped == ADMINHELPED_DISCORD) discord_bot.send_to_admins("[key_name(owner_client)]'s request for help has been taken by [key_name(assigned_admin)].") owner_client.adminhelped = ADMINHELPED message_admins("[key_name(assigned_admin)] has assigned themself to [src.owner]'s ticket.") to_chat(owner_client, "[assigned_admin] has added themself to your ticket and should respond shortly. Thanks for your patience!") to_chat(assigned_admin, get_options_bar(owner_client, 2, 1, 1)) update_ticket_panels() return 1 /datum/ticket/proc/remind() if (status == TICKET_CLOSED) reminder_timer = null return var/admin_found = FALSE for (var/ckey in assigned_admins) var/client/C = client_by_ckey(ckey) if (C) admin_found = TRUE to_chat(C, "You have yet to close [owner]'s ticket!") sound_to(C, 'sound/effects/adminhelp.ogg') if (!admin_found) message_admins("[owner]'s ticket has yet to be closed!") for(var/s in staff) var/client/C = s if((C.holder.rights & (R_ADMIN|R_MOD)) && (C.prefs.toggles & SOUND_ADMINHELP)) sound_to(C, 'sound/effects/adminhelp.ogg') reminder_timer = addtimer(CALLBACK(src, .proc/remind), config.ticket_reminder_period SECONDS, TIMER_UNIQUE|TIMER_STOPPABLE) /proc/get_open_ticket_by_ckey(var/owner) for(var/datum/ticket/ticket in tickets) if(ticket.owner == owner && (ticket.status == TICKET_OPEN || ticket.status == TICKET_ASSIGNED)) return ticket // there should only be one open ticket by a client at a time, so no need to keep looking /proc/get_ticket_by_id(id) for (var/datum/ticket/ticket in tickets) if (ticket.id == id) return ticket return null /datum/ticket/proc/is_active() if(status != TICKET_ASSIGNED) return 0 for(var/admin in assigned_admins) var/client/admin_client = client_by_ckey(admin) if(admin_client && !admin_client.is_afk()) return 1 return 0 /datum/ticket/proc/log_to_db() if (status != TICKET_CLOSED) return if (!establish_db_connection(dbcon)) return var/DBQuery/Q = dbcon.NewQuery({"INSERT INTO ss13_tickets (game_id, message_count, admin_count, admin_list, opened_by, taken_by, closed_by, response_delay, opened_at, closed_at) VALUES (:g_id:, :m_count:, :a_count:, :a_list:, :opened_by:, :taken_by:, :closed_by:, :delay:, :opened_at:, :closed_at:)"}) Q.Execute(list( "g_id" = game_id, "m_count" = length(msgs), "a_count" = length(assigned_admins), "a_list" = json_encode(assigned_admins), "opened_by" = owner, "taken_by" = length(assigned_admins) ? assigned_admins[1] : null, "closed_by" = closed_by, "delay" = response_time || -1, "opened_at" = SQLtime(opened_rt), "closed_at" = SQLtime(closed_rt) )) /datum/ticket/proc/append_message(m_from, m_to, msg) msgs += new /datum/ticket_msg(m_from, m_to, msg) if (!response_time && m_from != owner) response_time = round((world.time - opened_time) / 10) update_ticket_panels() /datum/ticket_msg var/msg_from var/msg_to var/msg var/time_stamp /datum/ticket_msg/New(var/msg_from, var/msg_to, var/msg) src.msg_from = msg_from src.msg_to = msg_to src.msg = msg src.time_stamp = time_stamp() /datum/ticket_panel var/datum/ticket/open_ticket = null var/datum/browser/ticket_panel_window /datum/ticket_panel/proc/get_dat() var/client/C = ticket_panel_window.user.client if(!C) return var/list/dat = list() var/valid_holder = check_rights(R_MOD|R_ADMIN, FALSE, ticket_panel_window.user) var/list/ticket_dat = list() for(var/id = tickets.len, id >= 1, id--) var/datum/ticket/ticket = tickets[id] if(valid_holder || ticket.owner == C.ckey) var/client/owner_client = client_by_ckey(ticket.owner) var/status = "Unknown status" var/color = "#6aa84f" switch(ticket.status) if(TICKET_OPEN) status = "Opened [round((world.time - ticket.opened_time) / (1 MINUTE))] minute\s ago, unassigned" if(TICKET_ASSIGNED) status = "Assigned to [english_list(ticket.assigned_admins, "no one")]" color = "#ffffff" if(TICKET_CLOSED) status = "Closed by [ticket.closed_by]" color = "#cc2222" ticket_dat += "
Available tickets:
\[X\] Messages for ticket #[open_ticket.id]:
" var/list/msg_dat = list() for(var/datum/ticket_msg/msg in open_ticket.msgs) var/msg_to = msg.msg_to ? msg.msg_to : "Adminhelp" msg_dat += "No messages to display.
" else dat += "No tickets to display.
" dat += "