diff --git a/code/__DEFINES/chat.dm b/code/__DEFINES/chat.dm index 149f5d85698..44bcdcd2a19 100644 --- a/code/__DEFINES/chat.dm +++ b/code/__DEFINES/chat.dm @@ -16,6 +16,7 @@ #define MESSAGE_TYPE_DEADCHAT "deadchat" #define MESSAGE_TYPE_OOC "ooc" #define MESSAGE_TYPE_ADMINPM "adminpm" +#define MESSAGE_TYPE_MENTORPM "mentorpm" #define MESSAGE_TYPE_COMBAT "combat" #define MESSAGE_TYPE_ADMINCHAT "adminchat" #define MESSAGE_TYPE_MENTORCHAT "mentorchat" diff --git a/code/controllers/subsystem/tickets/tickets.dm b/code/controllers/subsystem/tickets/tickets.dm index 55881a681de..655f6eda086 100644 --- a/code/controllers/subsystem/tickets/tickets.dm +++ b/code/controllers/subsystem/tickets/tickets.dm @@ -110,8 +110,9 @@ SUBSYSTEM_DEF(tickets) 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) + return T else - newTicket(C, text, text) + return newTicket(C, text, text) /** * Will add the URLs usable by staff to the message and return it @@ -126,13 +127,13 @@ SUBSYSTEM_DEF(tickets) if(istype(target, /datum/ticket)) var/datum/ticket/T = target M = get_mob_by_ckey(T.client_ckey) - key_and_name = M ? key_name(M, TRUE, ticket_help_type) : "[T.client_ckey] (DC)/(DELETED)" + key_and_name = M ? key_name(M, TRUE, ticket_help_type, ticket_id = T.ticketNum) : "[T.client_ckey] (DC)/(DELETED)" msg = T.title ticketNum = T.ticketNum else if(isclient(target)) var/client/C = target M = C.mob - key_and_name = key_name(M, TRUE, ticket_help_type) + key_and_name = key_name(M, TRUE, ticket_help_type, ticket_id = ticketNum) var/list/L = list() L += "[ticket_help_type]: [key_and_name] " @@ -165,12 +166,14 @@ SUBSYSTEM_DEF(tickets) SEND_SOUND(C, sound('sound/effects/adminticketopen.ogg')) message_staff(url_title, NONE, TRUE) + return T //Set ticket state with key N to open /datum/controller/subsystem/tickets/proc/openTicket(N) var/datum/ticket/T = allTickets[N] if(T.ticketState != TICKET_OPEN) message_staff("[usr.client] / ([usr]) re-opened [ticket_name] number [N]") + to_chat_safe(returnClient(N), "Your [ticket_name] has been re-opened.") T.ticketState = TICKET_OPEN return TRUE @@ -183,6 +186,12 @@ SUBSYSTEM_DEF(tickets) to_chat_safe(returnClient(N), "Your [ticket_name] has now been resolved.") return TRUE +/datum/controller/subsystem/tickets/proc/addResponse(list/tickets, who, message) + var/list/ticket_numbers = list() + for(var/datum/ticket/T in tickets) + ticket_numbers += T.ticketNum + T.addResponse(who, message) + /datum/controller/subsystem/tickets/proc/convert_to_other_ticket(ticketId) if(!check_rights(rights_needed)) return @@ -195,6 +204,7 @@ SUBSYSTEM_DEF(tickets) to_chat(usr, "This ticket has already been converted!") return convert_ticket(T) + message_staff("[usr.client] / ([usr]) converted [ticket_name] number [ticketId]") /datum/controller/subsystem/tickets/proc/other_ticket_system_staff_check() var/list/staff = staff_countup(other_ticket_permission) @@ -301,7 +311,9 @@ SUBSYSTEM_DEF(tickets) return FALSE //Check if the user has ANY ticket not resolved or closed. -/datum/controller/subsystem/tickets/proc/checkForTicket(client/C) +/datum/controller/subsystem/tickets/proc/checkForTicket(client/C, ticket_id = -1) + if(ticket_id > 0 && ticket_id <= length(allTickets)) + return list(allTickets[ticket_id]) var/list/tickets = list() for(var/datum/ticket/T in allTickets) if(T.client_ckey == C.ckey && (T.ticketState == TICKET_OPEN || T.ticketState == TICKET_STALE)) diff --git a/code/defines/procs/admin_keyname_procs.dm b/code/defines/procs/admin_keyname_procs.dm index 6bebe06b5f2..efd26bab4c1 100644 --- a/code/defines/procs/admin_keyname_procs.dm +++ b/code/defines/procs/admin_keyname_procs.dm @@ -1,11 +1,11 @@ // Always return "Something/(Something)", even if it's an error message. -/proc/key_name(whom, include_link = FALSE, type = null) - return key_name_helper(whom, TRUE, include_link, type) +/proc/key_name(whom, include_link = FALSE, type = null, ticket_id = null) + return key_name_helper(whom, TRUE, include_link, type, ticket_id = ticket_id) -/proc/key_name_hidden(whom, include_link = FALSE, type = null) - return key_name_helper(whom, FALSE, include_link, type) +/proc/key_name_hidden(whom, include_link = FALSE, type = null, ticket_id = null) + return key_name_helper(whom, FALSE, include_link, type, ticket_id = ticket_id) -/proc/key_name_helper(whom, include_name, include_link = FALSE, type = null) +/proc/key_name_helper(whom, include_name, include_link = FALSE, type = null, ticket_id = null) if(include_link != FALSE && include_link != TRUE) stack_trace("Key_name was called with an incorrect include_link [include_link]") @@ -42,11 +42,11 @@ if(key) if(C && C.holder && C.holder.fakekey && !include_name) if(include_link) - . += "" + . += "" . += "Administrator" else if(include_link && C) - . += "" + . += "" . += key // See if the player is on the watchlist. Requires admin permissions. if(check_rights(R_ADMIN, FALSE) && C && C.watchlisted) diff --git a/code/modules/admin/misc_admin_procs.dm b/code/modules/admin/misc_admin_procs.dm index 35b1a6c8121..0609b8f91fd 100644 --- a/code/modules/admin/misc_admin_procs.dm +++ b/code/modules/admin/misc_admin_procs.dm @@ -44,7 +44,7 @@ GLOBAL_VAR_INIT(nologevent, 0) for(var/client/C in GLOB.admins) if(check_rights(R_ADMIN | R_MENTOR | R_MOD, 0, C.mob)) if(important || (C.prefs && !(C.prefs.toggles & PREFTOGGLE_CHAT_NO_TICKETLOGS))) - to_chat(C, msg, MESSAGE_TYPE_MENTORCHAT, confidential = TRUE) + to_chat(C, msg, MESSAGE_TYPE_MENTORPM, confidential = TRUE) if(important) if(C.prefs?.sound & SOUND_MENTORHELP) SEND_SOUND(C, sound('sound/effects/adminhelp.ogg')) diff --git a/code/modules/admin/verbs/adminhelp.dm b/code/modules/admin/verbs/adminhelp.dm index 475877cb210..78febb17ac3 100644 --- a/code/modules/admin/verbs/adminhelp.dm +++ b/code/modules/admin/verbs/adminhelp.dm @@ -25,13 +25,20 @@ if(!msg) // No message after sanitisation return + var/span_type + var/message_type + var/datum/ticket/T if(selected_type == "Mentorhelp") - SSmentor_tickets.newHelpRequest(src, msg) // Mhelp + T = SSmentor_tickets.newHelpRequest(src, msg) // Mhelp + span_type = "mentorhelp" + message_type = MESSAGE_TYPE_MENTORPM else - SStickets.newHelpRequest(src, msg) // Ahelp + T = SStickets.newHelpRequest(src, msg) // Ahelp + span_type = "adminhelp" + message_type = MESSAGE_TYPE_ADMINPM //show it to the person adminhelping too - to_chat(src, "[selected_type]: [msg]", MESSAGE_TYPE_ADMINPM, confidential = TRUE) + to_chat(src, "[selected_type]: [msg]", message_type, confidential = TRUE) SSblackbox.record_feedback("tally", "admin_verb", 1, "Adminhelp") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! switch(selected_type) @@ -41,11 +48,11 @@ var/active_admins = admincount[1] log_admin("[selected_type]: [key_name(src)]: [msg] - heard by [active_admins] non-AFK admins.") - GLOB.discord_manager.send2discord_simple_noadmins("**\[Adminhelp]** [key_name(src)]: [msg]", check_send_always = TRUE) + GLOB.discord_manager.send2discord_simple_noadmins("**\[Adminhelp]** Ticket [T.ticketNum], [key_name(src)]: [msg]", check_send_always = TRUE) if("Mentorhelp") var/list/mentorcount = staff_countup(R_MENTOR) var/active_mentors = mentorcount[1] log_admin("[selected_type]: [key_name(src)]: [msg] - heard by [active_mentors] non-AFK mentors.") - GLOB.discord_manager.send2discord_simple_mentor("[key_name(src)]: [msg]") + GLOB.discord_manager.send2discord_simple_mentor("Ticket [T.ticketNum], [key_name(src)]: [msg]") diff --git a/code/modules/admin/verbs/adminpm.dm b/code/modules/admin/verbs/adminpm.dm index a6abcf6e0d1..98f8570eb40 100644 --- a/code/modules/admin/verbs/adminpm.dm +++ b/code/modules/admin/verbs/adminpm.dm @@ -60,7 +60,7 @@ //takes input from cmd_admin_pm_context, cmd_admin_pm_panel or /client/Topic and sends them a PM. //Fetching a message if needed. src is the sender and C is the target client -/client/proc/cmd_admin_pm(whom, msg, type = "PM") +/client/proc/cmd_admin_pm(whom, msg, type = "PM", ticket_id = -1) if(check_mute(ckey, MUTE_ADMINHELP)) to_chat(src, "Error: Private-Message: You are unable to use PM-s (muted).") return @@ -112,21 +112,30 @@ else msg = admin_pencode_to_html(msg) - var/recieve_span = "playerreply" + var/send_span + var/recieve_span var/send_pm_type = " " var/recieve_pm_type = "Player" + var/message_type + var/datum/controller/subsystem/tickets/tickets_system + // We treat PMs as mentorhelps if we were explicitly so, or if neither + // party is an admin. + if(type == "Mentorhelp" || !(check_rights(R_ADMIN|R_MOD, 0, C.mob) || check_rights(R_ADMIN|R_MOD, 0, src.mob))) + send_span = "mentorhelp" + recieve_span = "mentorhelp" + message_type = MESSAGE_TYPE_MENTORPM + tickets_system = SSmentor_tickets + else + send_span = "adminhelp" + recieve_span = "adminhelp" + message_type = MESSAGE_TYPE_ADMINPM + tickets_system = SStickets if(holder) - //mod PMs are maroon //PMs sent from admins and mods display their rank - if(holder) - if(check_rights(R_MOD|R_MENTOR,0) && !check_rights(R_ADMIN,0)) - recieve_span = "mentorhelp" - else - recieve_span = "adminhelp" - send_pm_type = holder.rank + " " - recieve_pm_type = holder.rank + send_pm_type = holder.rank + " " + recieve_pm_type = holder.rank else if(!C.holder) to_chat(src, "Error: Admin-PM: Non-admin to non-admin PM communication is forbidden.") @@ -159,12 +168,12 @@ var/emoji_msg = "[msg]" - recieve_message = chat_box_red("[type] from-[recieve_pm_type] [C.holder ? key_name(src, TRUE, type) : key_name_hidden(src, TRUE, type)]:

[emoji_msg]
") + recieve_message = chat_box_red("[type] from-[recieve_pm_type] [C.holder ? key_name(src, TRUE, type, ticket_id = ticket_id) : key_name_hidden(src, TRUE, type, ticket_id = ticket_id)]:

[emoji_msg]
") to_chat(C, recieve_message) var/ping_link = check_rights(R_ADMIN, 0, mob) ? "(
PING)" : "" var/window_link = "(WINDOW)" var/alert_link = check_rights(R_ADMIN, FALSE, mob) ? " (ALERT)" : "" - to_chat(src, "[send_pm_type][type] to-[holder ? key_name(C, TRUE, type) : key_name_hidden(C, TRUE, type)]: [emoji_msg] [ping_link] [window_link][alert_link]", MESSAGE_TYPE_ADMINPM) + to_chat(src, "[send_pm_type][type] to-[holder ? key_name(C, TRUE, type, ticket_id = ticket_id) : key_name_hidden(C, TRUE, type, ticket_id = ticket_id)]: [emoji_msg] [ping_link] [window_link][alert_link]", message_type) /*if(holder && !C.holder) C.last_pm_recieved = world.time @@ -182,38 +191,31 @@ if(X == C || X == src) continue if(X.key != key && X.key != C.key) - switch(type) - if("Mentorhelp") - if(check_rights(R_ADMIN|R_MOD|R_MENTOR, 0, X.mob)) - to_chat(X, "[type]: [key_name(src, TRUE, type)]->[key_name(C, TRUE, type)]: [emoji_msg]", type = MESSAGE_TYPE_MENTORCHAT) - if("Adminhelp") - if(check_rights(R_ADMIN|R_MOD, 0, X.mob)) - to_chat(X, "[type]: [key_name(src, TRUE, type)]->[key_name(C, TRUE, type)]: [emoji_msg]", type = MESSAGE_TYPE_ADMINCHAT) - else - if(check_rights(R_ADMIN|R_MOD, 0, X.mob)) - to_chat(X, "[type]: [key_name(src, TRUE, type)]->[key_name(C, TRUE, type)]: [emoji_msg]", type = MESSAGE_TYPE_ADMINCHAT) + if(message_type == MESSAGE_TYPE_MENTORPM) + if(check_rights(R_ADMIN|R_MOD|R_MENTOR, 0, X.mob)) + to_chat(X, "[type]: [key_name(src, TRUE, type, ticket_id = ticket_id)]->[key_name(C, TRUE, type, ticket_id = ticket_id)]: [emoji_msg]", type = message_type) + else + if(check_rights(R_ADMIN|R_MOD, 0, X.mob)) + to_chat(X, "[type]: [key_name(src, TRUE, type, ticket_id = ticket_id)]->[key_name(C, TRUE, type, ticket_id = ticket_id)]: [emoji_msg]", type = message_type) - //Check if the mob being PM'd has any open admin tickets. - var/tickets = list() - if(type == "Mentorhelp") - tickets = SSmentor_tickets.checkForTicket(C) - else - tickets = SStickets.checkForTicket(C) - if(tickets) - for(var/datum/ticket/i in tickets) - i.addResponse(src, msg) // Add this response to their open tickets. + //Check if the mob being PM'd has any open tickets. + var/list/tickets = tickets_system.checkForTicket(C, ticket_id) + + if(length(tickets)) + tickets_system.addResponse(tickets, src, msg) return - if(type == "Mentorhelp") - if(check_rights(R_ADMIN|R_MOD|R_MENTOR, 0, C.mob)) //Is the person being pm'd an admin? If so we check if the pm'er has open tickets + + // If we didn't find a specific ticket by the target mob, we check for + // tickets by the source mob. + if(message_type == MESSAGE_TYPE_MENTORPM) + if(check_rights(R_ADMIN|R_MOD|R_MENTOR, 0, C.mob)) tickets = SSmentor_tickets.checkForTicket(src) - else // Ahelp - if(check_rights(R_ADMIN|R_MOD, 0, C.mob)) //Is the person being pm'd an admin? If so we check if the pm'er has open tickets + else + if(check_rights(R_ADMIN|R_MOD, 0, C.mob)) tickets = SStickets.checkForTicket(src) - if(tickets) - for(var/datum/ticket/i in tickets) - i.addResponse(src, msg) - return + if(length(tickets)) + tickets_system.addResponse(tickets, src, msg) /client/proc/cmd_admin_discord_pm() if(check_mute(ckey, MUTE_ADMINHELP)) diff --git a/code/modules/client/client_procs.dm b/code/modules/client/client_procs.dm index d8031cc4f49..bc0de582ba8 100644 --- a/code/modules/client/client_procs.dm +++ b/code/modules/client/client_procs.dm @@ -105,7 +105,7 @@ if(href_list["priv_msg"]) var/ckey_txt = href_list["priv_msg"] - cmd_admin_pm(ckey_txt, null, href_list["type"]) + cmd_admin_pm(ckey_txt, null, href_list["type"], ticket_id = text2num(href_list["ticket_id"])) return if(href_list["discord_msg"]) diff --git a/code/modules/tgui/tgui_panel/to_chat.dm b/code/modules/tgui/tgui_panel/to_chat.dm index beb0f70be6d..7489b162606 100644 --- a/code/modules/tgui/tgui_panel/to_chat.dm +++ b/code/modules/tgui/tgui_panel/to_chat.dm @@ -7,7 +7,7 @@ * Circumvents the message queue and sends the message to the recipient (target) as soon as possible. * trailing_newline, confidential, and handle_whitespace currently have no effect, please fix this in the future or remove the arguments to lower cache! */ -/proc/to_chat_immediate(target, html, type, text, avoid_highlighting = FALSE, handle_whitespace = TRUE, trailing_newline = TRUE, confidential = FALSE) +/proc/to_chat_immediate(target, html, type, text, avoid_highlighting = FALSE, handle_whitespace = TRUE, trailing_newline = TRUE, confidential = FALSE, ticket_id = -1) // Useful where the integer 0 is the entire message. Use case is enabling to_chat(target, some_boolean) while preventing to_chat(target, "") html = "[html]" text = "[text]" @@ -29,6 +29,8 @@ message["html"] = html if(avoid_highlighting) message["avoidHighlighting"] = avoid_highlighting + if(ticket_id != -1) + message["ticket_id"] = ticket_id // send it immediately SSchat.send_immediate(target, message) @@ -48,7 +50,7 @@ * AVOID_HIGHLIGHTING: Unused * trailing_newline, confidential, and handle_whitespace currently have no effect, please fix this in the future or remove the arguments to lower cache! */ -/proc/to_chat(target, html, type, text, avoid_highlighting, handle_whitespace = TRUE, trailing_newline = TRUE, confidential = FALSE) +/proc/to_chat(target, html, type, text, avoid_highlighting, handle_whitespace = TRUE, trailing_newline = TRUE, confidential = FALSE, ticket_id = -1) if(Master.current_runlevel == RUNLEVEL_INIT || !SSchat?.initialized) to_chat_immediate(target, html, type, text) return @@ -74,4 +76,6 @@ message["html"] = html if(avoid_highlighting) message["avoidHighlighting"] = avoid_highlighting + if(ticket_id != -1) + message["ticket_id"] = ticket_id SSchat.queue(target, message) diff --git a/tgui/packages/tgui-panel/chat/constants.js b/tgui/packages/tgui-panel/chat/constants.js index bdef964f5e7..91fc756802c 100644 --- a/tgui/packages/tgui-panel/chat/constants.js +++ b/tgui/packages/tgui-panel/chat/constants.js @@ -29,6 +29,7 @@ export const MESSAGE_TYPE_WARNING = 'warning'; export const MESSAGE_TYPE_DEADCHAT = 'deadchat'; export const MESSAGE_TYPE_OOC = 'ooc'; export const MESSAGE_TYPE_ADMINPM = 'adminpm'; +export const MESSAGE_TYPE_MENTORPM = 'mentorpm'; export const MESSAGE_TYPE_COMBAT = 'combat'; export const MESSAGE_TYPE_ADMINCHAT = 'adminchat'; export const MESSAGE_TYPE_MENTORCHAT = 'mentorchat'; @@ -90,7 +91,13 @@ export const MESSAGE_TYPES = [ type: MESSAGE_TYPE_ADMINPM, name: 'Admin PMs', description: 'Messages to/from admins (adminhelp)', - selector: '.pm, .adminhelp', + selector: '.adminpm, .adminhelp, .adminticket, .adminticketalt', + }, + { + type: MESSAGE_TYPE_MENTORPM, + name: 'Mentor PMs', + description: 'Messages to/from mentors (mentorhelp)', + selector: '.mentorpm, .mentorhelp', }, { type: MESSAGE_TYPE_COMBAT, diff --git a/tgui/public/tgui-panel.bundle.js b/tgui/public/tgui-panel.bundle.js index c1eb6b12aaf..0785f57e7ad 100644 --- a/tgui/public/tgui-panel.bundle.js +++ b/tgui/public/tgui-panel.bundle.js @@ -114,11 +114,11 @@ * @file * @copyright 2020 Aleksej Komarov * @license MIT - */var o=e.loadChat=(0,n.createAction)("chat/load"),a=e.rebuildChat=(0,n.createAction)("chat/rebuild"),u=e.clearChat=(0,n.createAction)("chat/clear"),l=e.updateMessageCount=(0,n.createAction)("chat/updateMessageCount"),c=e.addChatPage=(0,n.createAction)("chat/addPage",function(){return{payload:(0,r.createPage)()}}),h=e.changeChatPage=(0,n.createAction)("chat/changePage"),v=e.updateChatPage=(0,n.createAction)("chat/updatePage"),i=e.toggleAcceptedType=(0,n.createAction)("chat/toggleAcceptedType"),d=e.removeChatPage=(0,n.createAction)("chat/removePage"),s=e.changeScrollTracking=(0,n.createAction)("chat/changeScrollTracking"),p=e.saveChatToDisk=(0,n.createAction)("chat/saveToDisk"),f=e.moveChatPageLeft=(0,n.createAction)("chat/movePageLeft"),g=e.moveChatPageRight=(0,n.createAction)("chat/movePageRight")},67392:function(E,e){"use strict";e.__esModule=!0,e.MESSAGE_TYPE_WARNING=e.MESSAGE_TYPE_UNKNOWN=e.MESSAGE_TYPE_SYSTEM=e.MESSAGE_TYPE_RADIO=e.MESSAGE_TYPE_OOC=e.MESSAGE_TYPE_MENTORCHAT=e.MESSAGE_TYPE_LOCALCHAT=e.MESSAGE_TYPE_INTERNAL=e.MESSAGE_TYPE_INFO=e.MESSAGE_TYPE_EVENTCHAT=e.MESSAGE_TYPE_DEBUG=e.MESSAGE_TYPE_DEADCHAT=e.MESSAGE_TYPE_COMBAT=e.MESSAGE_TYPE_ATTACKLOG=e.MESSAGE_TYPE_ADMINPM=e.MESSAGE_TYPE_ADMINLOG=e.MESSAGE_TYPE_ADMINCHAT=e.MESSAGE_TYPES=e.MESSAGE_SAVE_INTERVAL=e.MESSAGE_PRUNE_INTERVAL=e.MAX_VISIBLE_MESSAGES=e.MAX_PERSISTED_MESSAGES=e.IMAGE_RETRY_MESSAGE_AGE=e.IMAGE_RETRY_LIMIT=e.IMAGE_RETRY_DELAY=e.COMBINE_MAX_TIME_WINDOW=e.COMBINE_MAX_MESSAGES=void 0;/** + */var o=e.loadChat=(0,n.createAction)("chat/load"),a=e.rebuildChat=(0,n.createAction)("chat/rebuild"),u=e.clearChat=(0,n.createAction)("chat/clear"),l=e.updateMessageCount=(0,n.createAction)("chat/updateMessageCount"),c=e.addChatPage=(0,n.createAction)("chat/addPage",function(){return{payload:(0,r.createPage)()}}),h=e.changeChatPage=(0,n.createAction)("chat/changePage"),v=e.updateChatPage=(0,n.createAction)("chat/updatePage"),i=e.toggleAcceptedType=(0,n.createAction)("chat/toggleAcceptedType"),d=e.removeChatPage=(0,n.createAction)("chat/removePage"),s=e.changeScrollTracking=(0,n.createAction)("chat/changeScrollTracking"),p=e.saveChatToDisk=(0,n.createAction)("chat/saveToDisk"),f=e.moveChatPageLeft=(0,n.createAction)("chat/movePageLeft"),g=e.moveChatPageRight=(0,n.createAction)("chat/movePageRight")},67392:function(E,e){"use strict";e.__esModule=!0,e.MESSAGE_TYPE_WARNING=e.MESSAGE_TYPE_UNKNOWN=e.MESSAGE_TYPE_SYSTEM=e.MESSAGE_TYPE_RADIO=e.MESSAGE_TYPE_OOC=e.MESSAGE_TYPE_MENTORPM=e.MESSAGE_TYPE_MENTORCHAT=e.MESSAGE_TYPE_LOCALCHAT=e.MESSAGE_TYPE_INTERNAL=e.MESSAGE_TYPE_INFO=e.MESSAGE_TYPE_EVENTCHAT=e.MESSAGE_TYPE_DEBUG=e.MESSAGE_TYPE_DEADCHAT=e.MESSAGE_TYPE_COMBAT=e.MESSAGE_TYPE_ATTACKLOG=e.MESSAGE_TYPE_ADMINPM=e.MESSAGE_TYPE_ADMINLOG=e.MESSAGE_TYPE_ADMINCHAT=e.MESSAGE_TYPES=e.MESSAGE_SAVE_INTERVAL=e.MESSAGE_PRUNE_INTERVAL=e.MAX_VISIBLE_MESSAGES=e.MAX_PERSISTED_MESSAGES=e.IMAGE_RETRY_MESSAGE_AGE=e.IMAGE_RETRY_LIMIT=e.IMAGE_RETRY_DELAY=e.COMBINE_MAX_TIME_WINDOW=e.COMBINE_MAX_MESSAGES=void 0;/** * @file * @copyright 2020 Aleksej Komarov * @license MIT - */var t=e.MAX_VISIBLE_MESSAGES=2500,n=e.MAX_PERSISTED_MESSAGES=1e3,r=e.MESSAGE_SAVE_INTERVAL=1e4,o=e.MESSAGE_PRUNE_INTERVAL=6e4,a=e.COMBINE_MAX_TIME_WINDOW=5e3,u=e.COMBINE_MAX_MESSAGES=5,l=e.IMAGE_RETRY_DELAY=250,c=e.IMAGE_RETRY_LIMIT=10,h=e.IMAGE_RETRY_MESSAGE_AGE=6e4,v=e.MESSAGE_TYPE_UNKNOWN="unknown",i=e.MESSAGE_TYPE_INTERNAL="internal",d=e.MESSAGE_TYPE_SYSTEM="system",s=e.MESSAGE_TYPE_LOCALCHAT="localchat",p=e.MESSAGE_TYPE_RADIO="radio",f=e.MESSAGE_TYPE_INFO="info",g=e.MESSAGE_TYPE_WARNING="warning",m=e.MESSAGE_TYPE_DEADCHAT="deadchat",b=e.MESSAGE_TYPE_OOC="ooc",I=e.MESSAGE_TYPE_ADMINPM="adminpm",O=e.MESSAGE_TYPE_COMBAT="combat",C=e.MESSAGE_TYPE_ADMINCHAT="adminchat",S=e.MESSAGE_TYPE_MENTORCHAT="mentorchat",y=e.MESSAGE_TYPE_EVENTCHAT="eventchat",T=e.MESSAGE_TYPE_ADMINLOG="adminlog",P=e.MESSAGE_TYPE_ATTACKLOG="attacklog",N=e.MESSAGE_TYPE_DEBUG="debug",M=e.MESSAGE_TYPES=[{type:d,name:"System Messages",description:"Messages from your client, always enabled",selector:".boldannounceooc",important:!0},{type:s,name:"Local",description:"In-character local messages (say, emote, etc)",selector:".say, .emote"},{type:p,name:"Radio",description:"All departments of radio messages",selector:".alert, .syndradio, .centradio, .airadio, .entradio, .comradio, .secradio, .engradio, .medradio, .sciradio, .supradio, .srvradio, .expradio, .radio, .deptradio, .newscaster"},{type:f,name:"Info",description:"Non-urgent messages from the game and items",selector:".notice:not(.pm), .adminnotice, .info, .sinister, .cult"},{type:g,name:"Warnings",description:"Urgent messages from the game and items",selector:".warning:not(.pm), .critical, .userdanger, .italics, .boldannounceic, .boldwarning"},{type:m,name:"Deadchat",description:"All of deadchat",selector:".deadsay"},{type:b,name:"OOC",description:"The bluewall of global OOC messages",selector:".ooc, .adminooc"},{type:I,name:"Admin PMs",description:"Messages to/from admins (adminhelp)",selector:".pm, .adminhelp"},{type:O,name:"Combat Log",description:"Urist McTraitor has stabbed you with a knife!",selector:".danger"},{type:v,name:"Unsorted",description:"Everything we could not sort, always enabled"},{type:C,name:"Admin Chat",description:"ASAY messages",selector:".admin_channel, .adminsay",admin:!0},{type:S,name:"Mentor Chat",description:"MSAY messages",selector:".mentor_channel",admin:!0},{type:T,name:"Admin Log",description:"ADMIN LOG: Urist McAdmin has jumped to coordinates X, Y, Z",selector:".log_message",admin:!0},{type:P,name:"Attack Log",description:"Urist McTraitor has shot John Doe",admin:!0},{type:N,name:"Debug Log",description:"DEBUG: SSPlanets subsystem Recover().",selector:".pr_announce, .debug",admin:!0}]},23360:function(E,e,t){"use strict";e.__esModule=!0,e.chatReducer=e.chatMiddleware=e.ChatTabs=e.ChatPanel=e.ChatPageSettings=void 0;var n=t(59216);e.ChatPageSettings=n.ChatPageSettings;var r=t(49084);e.ChatPanel=r.ChatPanel;var o=t(54213);e.ChatTabs=o.ChatTabs;var a=t(13172);e.chatMiddleware=a.chatMiddleware;var u=t(7912);e.chatReducer=u.chatReducer},13172:function(E,e,t){"use strict";e.__esModule=!0,e.chatMiddleware=void 0;var n=i(t(85966)),r=t(96417),o=t(91577),a=t(65910),u=t(3578),l=t(67392),c=t(92863),h=t(57218),v=t(87919);function i(S){return S&&S.__esModule?S:{default:S}}function d(S,y){var T=typeof Symbol!="undefined"&&S[Symbol.iterator]||S["@@iterator"];if(T)return(T=T.call(S)).next.bind(T);if(Array.isArray(S)||(T=s(S))||y&&S&&typeof S.length=="number"){T&&(S=T);var P=0;return function(){return P>=S.length?{done:!0}:{done:!1,value:S[P++]}}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function s(S,y){if(S){if(typeof S=="string")return p(S,y);var T=Object.prototype.toString.call(S).slice(8,-1);if(T==="Object"&&S.constructor&&(T=S.constructor.name),T==="Map"||T==="Set")return Array.from(S);if(T==="Arguments"||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(T))return p(S,y)}}function p(S,y){(y==null||y>S.length)&&(y=S.length);for(var T=0,P=new Array(y);T=0;--Et){var it=this.tryEntries[Et],pt=it.completion;if(it.tryLoc==="root")return gt("end");if(it.tryLoc<=this.prev){var rt=P.call(it,"catchLoc"),_=P.call(it,"finallyLoc");if(rt&&_){if(this.prev=0;--gt){var Et=this.tryEntries[gt];if(Et.tryLoc<=this.prev&&P.call(Et,"finallyLoc")&&this.prev=0;--ot){var gt=this.tryEntries[ot];if(gt.finallyLoc===Z)return this.complete(gt.completion,gt.afterLoc),Nt(gt),Y}}return J}(),catch:function(){function J(Z){for(var ot=this.tryEntries.length-1;ot>=0;--ot){var gt=this.tryEntries[ot];if(gt.tryLoc===Z){var Et=gt.completion;if(Et.type==="throw"){var it=Et.arg;Nt(gt)}return it}}throw new Error("illegal catch attempt")}return J}(),delegateYield:function(){function J(Z,ot,gt){return this.delegate={iterator:dt(Z),resultName:ot,nextLoc:gt},this.method==="next"&&(this.arg=S),Y}return J}()},y}function g(S,y,T,P,N,M,R){try{var L=S[M](R),K=L.value}catch(U){T(U);return}L.done?y(K):Promise.resolve(K).then(P,N)}function m(S){return function(){var y=this,T=arguments;return new Promise(function(P,N){var M=S.apply(y,T);function R(K){g(M,P,N,R,L,"next",K)}function L(K){g(M,P,N,R,L,"throw",K)}R(void 0)})}}/** + */var t=e.MAX_VISIBLE_MESSAGES=2500,n=e.MAX_PERSISTED_MESSAGES=1e3,r=e.MESSAGE_SAVE_INTERVAL=1e4,o=e.MESSAGE_PRUNE_INTERVAL=6e4,a=e.COMBINE_MAX_TIME_WINDOW=5e3,u=e.COMBINE_MAX_MESSAGES=5,l=e.IMAGE_RETRY_DELAY=250,c=e.IMAGE_RETRY_LIMIT=10,h=e.IMAGE_RETRY_MESSAGE_AGE=6e4,v=e.MESSAGE_TYPE_UNKNOWN="unknown",i=e.MESSAGE_TYPE_INTERNAL="internal",d=e.MESSAGE_TYPE_SYSTEM="system",s=e.MESSAGE_TYPE_LOCALCHAT="localchat",p=e.MESSAGE_TYPE_RADIO="radio",f=e.MESSAGE_TYPE_INFO="info",g=e.MESSAGE_TYPE_WARNING="warning",m=e.MESSAGE_TYPE_DEADCHAT="deadchat",b=e.MESSAGE_TYPE_OOC="ooc",I=e.MESSAGE_TYPE_ADMINPM="adminpm",O=e.MESSAGE_TYPE_MENTORPM="mentorpm",C=e.MESSAGE_TYPE_COMBAT="combat",S=e.MESSAGE_TYPE_ADMINCHAT="adminchat",y=e.MESSAGE_TYPE_MENTORCHAT="mentorchat",T=e.MESSAGE_TYPE_EVENTCHAT="eventchat",P=e.MESSAGE_TYPE_ADMINLOG="adminlog",N=e.MESSAGE_TYPE_ATTACKLOG="attacklog",M=e.MESSAGE_TYPE_DEBUG="debug",R=e.MESSAGE_TYPES=[{type:d,name:"System Messages",description:"Messages from your client, always enabled",selector:".boldannounceooc",important:!0},{type:s,name:"Local",description:"In-character local messages (say, emote, etc)",selector:".say, .emote"},{type:p,name:"Radio",description:"All departments of radio messages",selector:".alert, .syndradio, .centradio, .airadio, .entradio, .comradio, .secradio, .engradio, .medradio, .sciradio, .supradio, .srvradio, .expradio, .radio, .deptradio, .newscaster"},{type:f,name:"Info",description:"Non-urgent messages from the game and items",selector:".notice:not(.pm), .adminnotice, .info, .sinister, .cult"},{type:g,name:"Warnings",description:"Urgent messages from the game and items",selector:".warning:not(.pm), .critical, .userdanger, .italics, .boldannounceic, .boldwarning"},{type:m,name:"Deadchat",description:"All of deadchat",selector:".deadsay"},{type:b,name:"OOC",description:"The bluewall of global OOC messages",selector:".ooc, .adminooc"},{type:I,name:"Admin PMs",description:"Messages to/from admins (adminhelp)",selector:".adminpm, .adminhelp, .adminticket, .adminticketalt"},{type:O,name:"Mentor PMs",description:"Messages to/from mentors (mentorhelp)",selector:".mentorpm, .mentorhelp"},{type:C,name:"Combat Log",description:"Urist McTraitor has stabbed you with a knife!",selector:".danger"},{type:v,name:"Unsorted",description:"Everything we could not sort, always enabled"},{type:S,name:"Admin Chat",description:"ASAY messages",selector:".admin_channel, .adminsay",admin:!0},{type:y,name:"Mentor Chat",description:"MSAY messages",selector:".mentor_channel",admin:!0},{type:P,name:"Admin Log",description:"ADMIN LOG: Urist McAdmin has jumped to coordinates X, Y, Z",selector:".log_message",admin:!0},{type:N,name:"Attack Log",description:"Urist McTraitor has shot John Doe",admin:!0},{type:M,name:"Debug Log",description:"DEBUG: SSPlanets subsystem Recover().",selector:".pr_announce, .debug",admin:!0}]},23360:function(E,e,t){"use strict";e.__esModule=!0,e.chatReducer=e.chatMiddleware=e.ChatTabs=e.ChatPanel=e.ChatPageSettings=void 0;var n=t(59216);e.ChatPageSettings=n.ChatPageSettings;var r=t(49084);e.ChatPanel=r.ChatPanel;var o=t(54213);e.ChatTabs=o.ChatTabs;var a=t(13172);e.chatMiddleware=a.chatMiddleware;var u=t(7912);e.chatReducer=u.chatReducer},13172:function(E,e,t){"use strict";e.__esModule=!0,e.chatMiddleware=void 0;var n=i(t(85966)),r=t(96417),o=t(91577),a=t(65910),u=t(3578),l=t(67392),c=t(92863),h=t(57218),v=t(87919);function i(S){return S&&S.__esModule?S:{default:S}}function d(S,y){var T=typeof Symbol!="undefined"&&S[Symbol.iterator]||S["@@iterator"];if(T)return(T=T.call(S)).next.bind(T);if(Array.isArray(S)||(T=s(S))||y&&S&&typeof S.length=="number"){T&&(S=T);var P=0;return function(){return P>=S.length?{done:!0}:{done:!1,value:S[P++]}}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function s(S,y){if(S){if(typeof S=="string")return p(S,y);var T=Object.prototype.toString.call(S).slice(8,-1);if(T==="Object"&&S.constructor&&(T=S.constructor.name),T==="Map"||T==="Set")return Array.from(S);if(T==="Arguments"||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(T))return p(S,y)}}function p(S,y){(y==null||y>S.length)&&(y=S.length);for(var T=0,P=new Array(y);T=0;--Et){var it=this.tryEntries[Et],pt=it.completion;if(it.tryLoc==="root")return gt("end");if(it.tryLoc<=this.prev){var rt=P.call(it,"catchLoc"),_=P.call(it,"finallyLoc");if(rt&&_){if(this.prev=0;--gt){var Et=this.tryEntries[gt];if(Et.tryLoc<=this.prev&&P.call(Et,"finallyLoc")&&this.prev=0;--ot){var gt=this.tryEntries[ot];if(gt.finallyLoc===Z)return this.complete(gt.completion,gt.afterLoc),Nt(gt),Y}}return J}(),catch:function(){function J(Z){for(var ot=this.tryEntries.length-1;ot>=0;--ot){var gt=this.tryEntries[ot];if(gt.tryLoc===Z){var Et=gt.completion;if(Et.type==="throw"){var it=Et.arg;Nt(gt)}return it}}throw new Error("illegal catch attempt")}return J}(),delegateYield:function(){function J(Z,ot,gt){return this.delegate={iterator:dt(Z),resultName:ot,nextLoc:gt},this.method==="next"&&(this.arg=S),Y}return J}()},y}function g(S,y,T,P,N,M,R){try{var L=S[M](R),K=L.value}catch(U){T(U);return}L.done?y(K):Promise.resolve(K).then(P,N)}function m(S){return function(){var y=this,T=arguments;return new Promise(function(P,N){var M=S.apply(y,T);function R(K){g(M,P,N,R,L,"next",K)}function L(K){g(M,P,N,R,L,"throw",K)}R(void 0)})}}/** * @file * @copyright 2020 Aleksej Komarov * @license MIT