diff --git a/code/controllers/subsystem/tickets/mentor_tickets.dm b/code/controllers/subsystem/tickets/mentor_tickets.dm index 97f84263a45..706a498aa64 100644 --- a/code/controllers/subsystem/tickets/mentor_tickets.dm +++ b/code/controllers/subsystem/tickets/mentor_tickets.dm @@ -10,6 +10,9 @@ GLOBAL_REAL(SSmentor_tickets, /datum/controller/subsystem/tickets/mentor_tickets ticket_system_name = "Mentor Tickets" ticket_name = "Mentor Ticket" span_class = "mentorhelp" + anchor_link_extra = ";is_mhelp=1" + ticket_help_type = "Mentorhelp" + ticket_help_span = "mentorhelp" other_ticket_name = "Admin" other_ticket_permission = R_ADMIN close_rights = R_MENTOR | R_ADMIN @@ -21,8 +24,11 @@ GLOBAL_REAL(SSmentor_tickets, /datum/controller/subsystem/tickets/mentor_tickets "Your [ticket_name] has now been closed.") return ..() -/datum/controller/subsystem/tickets/mentor_tickets/message_staff(msg) - message_mentorTicket(msg) +/datum/controller/subsystem/tickets/mentor_tickets/message_staff(msg, prefix_type = NONE, important = FALSE) + 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.title) + SStickets.newTicket(get_client_by_ckey(T.client_ckey), T.content, T.raw_title) + +/datum/controller/subsystem/tickets/mentor_tickets/autoRespond(N) + return diff --git a/code/controllers/subsystem/tickets/tickets.dm b/code/controllers/subsystem/tickets/tickets.dm index 60f3a5fa8dd..30c4c13166c 100644 --- a/code/controllers/subsystem/tickets/tickets.dm +++ b/code/controllers/subsystem/tickets/tickets.dm @@ -10,6 +10,9 @@ #define TICKET_RESOLVED 3 #define TICKET_STALE 4 +#define TICKET_STAFF_MESSAGE_ADMIN_CHANNEL 1 +#define TICKET_STAFF_MESSAGE_PREFIX 2 + SUBSYSTEM_DEF(tickets) name = "Admin Tickets" init_order = INIT_ORDER_TICKETS @@ -24,6 +27,11 @@ SUBSYSTEM_DEF(tickets) var/close_rights = R_ADMIN var/rights_needed = R_ADMIN | R_MOD + /// Text that will be added to the anchor link + var/anchor_link_extra = "" + + var/ticket_help_type = "Adminhelp" + var/ticket_help_span = "adminhelp" /// The name of the other ticket type to convert to var/other_ticket_name = "Mentor" /// Which permission to look for when seeing if there is staff available for the other ticket type @@ -34,7 +42,8 @@ SUBSYSTEM_DEF(tickets) var/ticketCounter = 1 /datum/controller/subsystem/tickets/Initialize() - close_messages = list("- [ticket_name] Rejected! -", + if(!close_messages) + close_messages = list("- [ticket_name] Rejected! -", "Please try to be calm, clear, and descriptive in admin helps, do not assume the staff member has seen any related events, and clearly state the names of anybody you are reporting. If you asked a question, please ensure it was clear what you were asking.", "Your [ticket_name] has now been closed.") return ..() @@ -76,22 +85,56 @@ SUBSYSTEM_DEF(tickets) var/datum/ticket/T = i resolveTicket(T.ticketNum) +/** + * Will either make a new ticket using the given text or will add the text to an existing ticket. + * Staff will get a message + * Arguments: + * C - The client who requests help + * text - The text the client send + */ +/datum/controller/subsystem/tickets/proc/newHelpRequest(client/C, text) + var/ticketNum // Holder for the ticket number + var/datum/ticket/T + // Get the open ticket assigned to the client and add a response. If no open tickets then make a new one + if((T = checkForOpenTicket(C))) + ticketNum = T.ticketNum + T.addResponse(C, text) + T.setCooldownPeriod() + to_chat(C.mob, "Your [ticket_name] #[ticketNum] remains open! Visit \"My tickets\" under the Admin Tab to view it.") + var/url_message = makeUrlMessage(C, text, ticketNum) + message_staff(url_message, NONE, TRUE) + else + newTicket(C, text, text) + +/** + * Will add the URLs usable by staff to the message and return it + * Arguments: + * C - The client who send the message + * msg - The raw message + * ticketNum - Which ticket number the ticket has + */ +/datum/controller/subsystem/tickets/proc/makeUrlMessage(client/C, msg, ticketNum) + var/list/L = list() + L += "[ticket_help_type]: [key_name(C, TRUE, ticket_help_type)] " + L += "([ADMIN_QUE(C.mob,"?")]) ([ADMIN_PP(C.mob,"PP")]) ([ADMIN_VV(C.mob,"VV")]) ([ADMIN_TP(C.mob,"TP")]) ([ADMIN_SM(C.mob,"SM")]) " + L += "([admin_jump_link(C.mob)]) (TICKET) " + L += "[isAI(C.mob) ? "(CL)" : ""] (TAKE) " + L += "(RESOLVE) (AUTO) " + L += "(CONVERT) : [msg]" + return L.Join() + //Open a new ticket and populate details then add to the list of open tickets /datum/controller/subsystem/tickets/proc/newTicket(client/C, passedContent, title) if(!C || !passedContent) return - //Check if the user has an open ticket already within the cooldown period, if so we don't create a new one and re-set the cooldown period - var/datum/ticket/existingTicket = checkForOpenTicket(C) - if(existingTicket) - existingTicket.setCooldownPeriod() - to_chat(C.mob, "Your [ticket_name] #[existingTicket.ticketNum] remains open! Visit \"My tickets\" under the Admin Tab to view it.") - return - if(!title) title = passedContent - var/datum/ticket/T = new(title, passedContent, getTicketCounterAndInc()) + 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) allTickets += T T.client_ckey = C.ckey T.locationSent = C.mob.loc.name @@ -102,6 +145,8 @@ SUBSYSTEM_DEF(tickets) var/ticket_open_sound = sound('sound/effects/adminticketopen.ogg') SEND_SOUND(C, ticket_open_sound) + message_staff(url_title, NONE, TRUE) + //Set ticket state with key N to open /datum/controller/subsystem/tickets/proc/openTicket(N) var/datum/ticket/T = allTickets[N] @@ -148,7 +193,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.title) + SSmentor_tickets.newTicket(C, T.content, T.raw_title) /datum/controller/subsystem/tickets/proc/autoRespond(N) if(!check_rights(rights_needed)) @@ -250,6 +295,7 @@ SUBSYSTEM_DEF(tickets) var/client_ckey var/timeOpened // Time the ticket was opened var/title //The initial message with links + var/raw_title // The title without URLs added var/list/content // content of the staff help var/lastStaffResponse // Last staff member who responded var/lastResponseTime // When the staff last responded @@ -260,8 +306,9 @@ SUBSYSTEM_DEF(tickets) var/ticketCooldown // Cooldown before allowing the user to open another ticket. var/client/staffAssigned // Staff member who has assigned themselves to this ticket -/datum/ticket/New(tit, cont, num) +/datum/ticket/New(tit, raw_tit, cont, num) title = tit + raw_title = raw_tit content = list() content += cont timeOpened = worldtime2text() @@ -440,9 +487,21 @@ UI STUFF to_chat(target, text) return TRUE -//Sends a message to the designated staff -/datum/controller/subsystem/tickets/proc/message_staff(var/msg, var/alt = FALSE) - message_adminTicket(msg, alt) +/** + * Sends a message to the designated staff + * Arguments: + * msg - The message being send + * alt - If an alternative prefix should be used or not. Defaults to TICKET_STAFF_MESSAGE_PREFIX + * important - If the message is important. If TRUE it will ignore the CHAT_NO_TICKETLOGS preferences, + send a sound and flash the window. Defaults to FALSE + */ +/datum/controller/subsystem/tickets/proc/message_staff(msg, prefix_type = TICKET_STAFF_MESSAGE_PREFIX, important = FALSE) + switch(prefix_type) + if(TICKET_STAFF_MESSAGE_ADMIN_CHANNEL) + msg = "ADMIN TICKET: [msg]" + if(TICKET_STAFF_MESSAGE_PREFIX) + msg = "ADMIN TICKET: [msg]" + message_adminTicket(msg, important) /datum/controller/subsystem/tickets/Topic(href, href_list) @@ -524,7 +583,7 @@ UI STUFF if(span_class == "mentorhelp") message_staff("[usr.client] / ([usr]) has taken [ticket_name] number [index]") else - message_staff("[usr.client] / ([usr]) has taken [ticket_name] number [index]", TRUE) + message_staff("[usr.client] / ([usr]) has taken [ticket_name] number [index]", TICKET_STAFF_MESSAGE_ADMIN_CHANNEL) to_chat_safe(returnClient(index), "Your [ticket_name] is being handled by [usr.client].") /datum/controller/subsystem/tickets/proc/unassignTicket(index) @@ -535,4 +594,7 @@ UI STUFF if(span_class == "mentorhelp") message_staff("[usr.client] / ([usr]) has unassigned [ticket_name] number [index]") else - message_staff("[usr.client] / ([usr]) has unassigned [ticket_name] number [index]", TRUE) + message_staff("[usr.client] / ([usr]) has unassigned [ticket_name] number [index]", TICKET_STAFF_MESSAGE_ADMIN_CHANNEL) + +#undef TICKET_STAFF_MESSAGE_ADMIN_CHANNEL +#undef TICKET_STAFF_MESSAGE_PREFIX diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm index 45971e6993e..8bd4381b195 100644 --- a/code/modules/admin/admin.dm +++ b/code/modules/admin/admin.dm @@ -20,22 +20,39 @@ GLOBAL_VAR_INIT(nologevent, 0) if(C.prefs.atklog <= loglevel) to_chat(C, msg) - -/proc/message_adminTicket(var/msg, var/alt = FALSE) - if(alt) - msg = "ADMIN TICKET: [msg]" - else - msg = "ADMIN TICKET: [msg]" +/** + * Sends a message to the staff able to see admin tickets + * Arguments: + * msg - The message being send + * important - If the message is important. If TRUE it will ignore the CHAT_NO_TICKETLOGS preferences, + send a sound and flash the window. Defaults to FALSE + */ +/proc/message_adminTicket(msg, important = FALSE) for(var/client/C in GLOB.admins) if(R_ADMIN & C.holder.rights) - if(C.prefs && !(C.prefs.toggles & CHAT_NO_TICKETLOGS)) + if(important || (C.prefs && !(C.prefs.toggles & CHAT_NO_TICKETLOGS))) to_chat(C, msg) + if(important) + if(C.prefs?.sound & SOUND_ADMINHELP) + SEND_SOUND(C, 'sound/effects/adminhelp.ogg') + window_flash(C) -/proc/message_mentorTicket(var/msg) +/** + * Sends a message to the staff able to see mentor tickets + * Arguments: + * msg - The message being send + * important - If the message is important. If TRUE it will ignore the CHAT_NO_TICKETLOGS preferences, + send a sound and flash the window. Defaults to FALSE + */ +/proc/message_mentorTicket(msg, important = FALSE) for(var/client/C in GLOB.admins) if(check_rights(R_ADMIN | R_MENTOR | R_MOD, 0, C.mob)) - if(C.prefs && !(C.prefs.toggles & CHAT_NO_MENTORTICKETLOGS)) + if(important || (C.prefs && !(C.prefs.toggles & CHAT_NO_MENTORTICKETLOGS))) to_chat(C, msg) + if(important) + if(C.prefs?.sound & SOUND_MENTORHELP) + SEND_SOUND(C, 'sound/effects/adminhelp.ogg') + window_flash(C) /proc/admin_ban_mobsearch(var/mob/M, var/ckey_to_find, var/mob/admin_to_notify) if(!M || !M.ckey) diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm index 262fab1775c..72893e18cf5 100644 --- a/code/modules/admin/topic.dm +++ b/code/modules/admin/topic.dm @@ -26,17 +26,16 @@ message_admins("[key_name_admin(usr)] rejected [key_name_admin(C.mob)]'s admin help") log_admin("[key_name(usr)] rejected [key_name(C.mob)]'s admin help") - if(href_list["openadminticket"]) - if(!check_rights(R_ADMIN)) - return - var/ticketID = text2num(href_list["openadminticket"]) - SStickets.showDetailUI(usr, ticketID) - - if(href_list["openmentorticket"]) - if(!check_rights(R_MENTOR|R_MOD|R_ADMIN)) - return - var/ticketID = text2num(href_list["openmentorticket"]) - SSmentor_tickets.showDetailUI(usr, ticketID) + if(href_list["openticket"]) + var/ticketID = text2num(href_list["openticket"]) + if(!href_list["is_mhelp"]) + if(!check_rights(R_ADMIN)) + return + SStickets.showDetailUI(usr, ticketID) + else + if(!check_rights(R_MENTOR|R_MOD|R_ADMIN)) + return + SSmentor_tickets.showDetailUI(usr, ticketID) if(href_list["stickyban"]) stickyban(href_list["stickyban"],href_list) @@ -1669,6 +1668,9 @@ SStickets.resolveTicket(index) else if(href_list["autorespond"]) + if(href_list["is_mhelp"]) + to_chat(usr, "Auto responses are not available for mentor helps.") + return var/index = text2num(href_list["autorespond"]) if(!check_rights(R_ADMIN|R_MOD)) return diff --git a/code/modules/admin/verbs/adminhelp.dm b/code/modules/admin/verbs/adminhelp.dm index 0b88d6030bb..4289df8ffbc 100644 --- a/code/modules/admin/verbs/adminhelp.dm +++ b/code/modules/admin/verbs/adminhelp.dm @@ -29,64 +29,12 @@ GLOBAL_LIST_INIT(adminhelp_ignored_words, list("unknown","the","a","an","of","mo msg = sanitize_simple(copytext(msg,1,MAX_MESSAGE_LEN)) if(!msg) return - var/original_msg = msg + if(selected_type == "Mentorhelp") + SSmentor_tickets.newHelpRequest(src, msg) + else + SStickets.newHelpRequest(src, msg) - //explode the input msg into a list - var/list/msglist = splittext(msg, " ") - - //generate keywords lookup - var/list/surnames = list() - var/list/forenames = list() - var/list/ckeys = list() - for(var/mob/M in GLOB.mob_list) - var/list/indexing = list(M.real_name, M.name) - if(M.mind) indexing += M.mind.name - - for(var/string in indexing) - var/list/L = splittext(string, " ") - var/surname_found = 0 - //surnames - for(var/i=L.len, i>=1, i--) - var/word = ckey(L[i]) - if(word) - surnames[word] = M - surname_found = i - break - //forenames - for(var/i=1, iTICKET) " - finalised_msg += "[ai_found ? "(CL)" : ""] (TAKE) " - finalised_msg += "(RESOLVE) [isMhelp ? "" : "(AUTO)"] " - finalised_msg += "(CONVERT) : [span][msg]" - - if(isMhelp) - //Open a new adminticket and inform the user. - SSmentor_tickets.newTicket(src, prunedmsg, finalised_msg) - for(var/client/X in mentorholders + modholders + adminholders) - if(X.prefs.sound & SOUND_MENTORHELP) - SEND_SOUND(X, 'sound/effects/adminhelp.ogg') - to_chat(X, finalised_msg) - else //Ahelp - //Open a new adminticket and inform the user. - SStickets.newTicket(src, prunedmsg, finalised_msg) - for(var/client/X in modholders + adminholders) - if(X.prefs.sound & SOUND_ADMINHELP) - SEND_SOUND(X, 'sound/effects/adminhelp.ogg') - window_flash(X) - to_chat(X, finalised_msg) - - //show it to the person adminhelping too - to_chat(src, "[selected_type]: [original_msg]") + to_chat(src, "[selected_type]: [msg]") var/admin_number_present = adminholders.len - admin_number_afk - log_admin("[selected_type]: [key_name(src)]: [original_msg] - heard by [admin_number_present] non-AFK admins.") + log_admin("[selected_type]: [key_name(src)]: [msg] - heard by [admin_number_present] non-AFK admins.") if(admin_number_present <= 0) if(!admin_number_afk) - send2adminirc("[selected_type] from [key_name(src)]: [original_msg] - !!No admins online!!") + send2adminirc("[selected_type] from [key_name(src)]: [msg] - !!No admins online!!") else - send2adminirc("[selected_type] from [key_name(src)]: [original_msg] - !!All admins AFK ([admin_number_afk])!!") + send2adminirc("[selected_type] from [key_name(src)]: [msg] - !!All admins AFK ([admin_number_afk])!!") else - send2adminirc("[selected_type] from [key_name(src)]: [original_msg]") + send2adminirc("[selected_type] from [key_name(src)]: [msg]") feedback_add_details("admin_verb","AH") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! return