#define EXTERNALREPLYCOUNT 2 //allows right clicking mobs to send an admin PM to their client, forwards the selected mob's client to cmd_admin_pm /client/proc/cmd_admin_pm_context(mob/M in GLOB.mob_list) set category = null set name = "Admin PM Mob" if(!holder) to_chat(src, type = MESSAGE_TYPE_ADMINPM, html = span_danger("Error: Admin-PM-Context: Only administrators may use this command."), confidential = TRUE) return if(!ismob(M) || !M.client) return cmd_admin_pm(M.client,null) SSblackbox.record_feedback("tally", "admin_verb", 1, "Admin PM Mob") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! //shows a list of clients we could send PMs to, then forwards our choice to cmd_admin_pm /client/proc/cmd_admin_pm_panel() set category = "Admin" set name = "Admin PM" if(!holder) to_chat(src, type = MESSAGE_TYPE_ADMINPM, html = span_danger("Error: Admin-PM-Panel: Only administrators may use this command."), confidential = TRUE) return var/list/targets = list() for(var/client/client as anything in GLOB.clients) if(client.mob) if(isnewplayer(client.mob)) targets["(New Player) - [client]"] = client else if(isobserver(client.mob)) targets["[client.mob.name](Ghost) - [client]"] = client else targets["[client.mob.real_name](as [client.mob.name]) - [client]"] = client else targets["(No Mob) - [client]"] = client var/target = input(src,"To whom shall we send a message?","Admin PM",null) as null|anything in sortList(targets) cmd_admin_pm(targets[target],null) SSblackbox.record_feedback("tally", "admin_verb", 1, "Admin PM") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! /client/proc/cmd_ahelp_reply(whom) if(prefs.muted & MUTE_ADMINHELP) to_chat(src, type = MESSAGE_TYPE_ADMINPM, html = span_danger("Error: Admin-PM: You are unable to use admin PM-s (muted)."), confidential = TRUE) return var/client/C if(istext(whom)) if(whom[1] == "@") whom = findStealthKey(whom) C = GLOB.directory[whom] else if(istype(whom, /client)) C = whom if(!C) if(holder) to_chat(src, type = MESSAGE_TYPE_ADMINPM, html = span_danger("Error: Admin-PM: Client not found."), confidential = TRUE) return var/datum/admin_help/AH = C.current_ticket if(AH) message_admins("[key_name_admin(src)] has started replying to [key_name_admin(C, 0, 0)]'s admin help.") var/msg = input(src,"Message:", "Private message to [C.holder?.fakekey ? "an Administrator" : key_name(C, 0, 0)].") as message|null if (!msg) message_admins("[key_name_admin(src)] has cancelled their reply to [key_name_admin(C, 0, 0)]'s admin help.") return if(!C) //We lost the client during input, disconnected or relogged. if(GLOB.directory[AH.initiator_ckey]) // Client has reconnected, lets try to recover whom = GLOB.directory[AH.initiator_ckey] else to_chat(src, type = MESSAGE_TYPE_ADMINPM, html = span_danger("Error: Admin-PM: Client not found."), confidential = TRUE) to_chat(src, type = MESSAGE_TYPE_ADMINPM, html = "[span_danger("Message not sent:")]
[msg]", confidential = TRUE) AH.AddInteraction("No client found, message not sent:
[msg]") return cmd_admin_pm(whom, msg) //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) if(prefs.muted & MUTE_ADMINHELP) to_chat(src, type = MESSAGE_TYPE_ADMINPM, html = span_danger("Error: Admin-PM: You are unable to use admin PM-s (muted)."), confidential = TRUE) return if(!holder && !current_ticket) //no ticket? https://www.youtube.com/watch?v=iHSPf6x1Fdo to_chat(src, type = MESSAGE_TYPE_ADMINPM, html = span_danger("You can no longer reply to this ticket, please open another one by using the Adminhelp verb if need be."), confidential = TRUE) to_chat(src, type = MESSAGE_TYPE_ADMINPM, html = span_notice("Message: [msg]"), confidential = TRUE) return var/client/recipient var/recipient_ckey // Stored in case client is deleted between this and after the message is input var/datum/admin_help/recipient_ticket // Stored in case client is deleted between this and after the message is input var/external = 0 if(istext(whom)) if(whom[1] == "@") whom = findStealthKey(whom) if(whom == "IRCKEY") external = 1 else recipient = GLOB.directory[whom] else if(istype(whom, /client)) recipient = whom if(!recipient) to_chat(src, type = MESSAGE_TYPE_ADMINPM, html = span_danger("Error: Admin-PM: Client not found."), confidential = TRUE) return recipient_ckey = recipient.ckey recipient_ticket = recipient.current_ticket if(external) if(!externalreplyamount) //to prevent people from spamming irc/discord return if(!msg) msg = input(src,"Message:", "Private message to Administrator") as message|null if(!msg) return if(holder) to_chat(src, type = MESSAGE_TYPE_ADMINPM, html = span_danger("Error: Use the admin IRC/Discord channel, nerd."), confidential = TRUE) return else //get message text, limit it's length.and clean/escape html if(!msg) msg = input(src,"Message:", "Private message to [recipient.holder?.fakekey ? "an Administrator" : key_name(recipient, 0, 0)].") as message|null msg = trim(msg) if(!msg) return if(!recipient) if(GLOB.directory[recipient_ckey]) // Client has reconnected, lets try to recover recipient = GLOB.directory[recipient_ckey] else if(holder) to_chat(src, type = MESSAGE_TYPE_ADMINPM, html = span_danger("Error: Admin-PM: Client not found."), confidential = TRUE) to_chat(src, type = MESSAGE_TYPE_ADMINPM, html = "[span_danger("Message not sent:")]
[msg]", confidential = TRUE) if(recipient_ticket) recipient_ticket.AddInteraction("No client found, message not sent:
[msg]") return else current_ticket.MessageNoRecipient(msg) return if(prefs.muted & MUTE_ADMINHELP) to_chat(src, type = MESSAGE_TYPE_ADMINPM, html = span_danger("Error: Admin-PM: You are unable to use admin PM-s (muted)."), confidential = TRUE) return if (src.handle_spam_prevention(msg,MUTE_ADMINHELP)) return //clean the message if it's not sent by a high-rank admin if(!check_rights(R_SERVER|R_DEBUG,0)||external)//no sending html to the poor bots msg = sanitize(copytext_char(msg, 1, MAX_MESSAGE_LEN)) if(!msg) return var/rawmsg = msg if(holder) msg = emoji_parse(msg) var/keywordparsedmsg = keywords_lookup(msg) if(external) to_chat(src, type = MESSAGE_TYPE_ADMINPM, html = span_notice("PM to-Admins: [rawmsg]"), confidential = TRUE) var/datum/admin_help/AH = admin_ticket_log(src, "Reply PM from-[key_name(src, TRUE, TRUE)] to External: [keywordparsedmsg]") AH.AddInteractionPlayer("Reply PM from-[key_name(src, TRUE, FALSE)] to External: [keywordparsedmsg]") // SKYRAT EDIT ADDITION -- Player ticket viewing externalreplyamount-- send2adminchat("[AH ? "#[AH.id] " : ""]Reply: [ckey]", rawmsg) else var/badmin = FALSE //Lets figure out if an admin is getting bwoinked. if(holder && recipient.holder && !current_ticket) //Both are admins, and this is not a reply to our own ticket. badmin = TRUE if(recipient.holder && !badmin) SEND_SIGNAL(current_ticket, COMSIG_ADMIN_HELP_REPLIED) if(holder) to_chat(recipient, type = MESSAGE_TYPE_ADMINPM, html = span_danger("Admin PM from-[key_name(src, recipient, 1)]: [keywordparsedmsg]"), confidential = TRUE) to_chat(src, type = MESSAGE_TYPE_ADMINPM, html = span_notice("Admin PM to-[key_name(recipient, src, 1)]: [keywordparsedmsg]"), confidential = TRUE) //omg this is dumb, just fill in both their tickets var/interaction_message = "PM from-[key_name(src, recipient, 1)] to-[key_name(recipient, src, 1)]: [keywordparsedmsg]" // admin_ticket_log(src, interaction_message) // SKYRAT EDIT ORIGINAL admin_ticket_log(src, interaction_message, FALSE) // SKYRAT EDIT CHANGE -- Player ticket viewing if(recipient != src)//reeee // admin_ticket_log(recipient, interaction_message) // SKYRAT EDIT ORIGINAL admin_ticket_log(recipient, interaction_message, FALSE) // SKYRAT EDIT CHANGE -- Player ticket viewing SSblackbox.LogAhelp(current_ticket.id, "Reply", msg, recipient.ckey, src.ckey) else //recipient is an admin but sender is not var/replymsg = "Reply PM from-[key_name(src, recipient, 1)]: [keywordparsedmsg]" // admin_ticket_log(src, "[replymsg]") // SKYRAT EDIT ORIGINAL admin_ticket_log(src, "[replymsg]", FALSE) // SKYRAT EDIT CHANGE -- Player ticket viewing to_chat(recipient, type = MESSAGE_TYPE_ADMINPM, html = span_danger("[replymsg]"), confidential = TRUE) to_chat(src, type = MESSAGE_TYPE_ADMINPM, html = span_notice("PM to-Admins: [msg]"), confidential = TRUE) SSblackbox.LogAhelp(current_ticket.id, "Reply", msg, recipient.ckey, src.ckey) //play the receiving admin the adminhelp sound (if they have them enabled) if(recipient.prefs.toggles & SOUND_ADMINHELP) SEND_SOUND(recipient, sound('sound/effects/adminhelp.ogg')) else if(holder) //sender is an admin but recipient is not. Do BIG RED TEXT var/already_logged = FALSE if(!recipient.current_ticket) //new /datum/admin_help(msg, recipient, TRUE) //ORIGINAL new /datum/admin_help(msg, recipient, TRUE, src) //SKYRAT EDIT CHANGE - ADMIN already_logged = TRUE SSblackbox.LogAhelp(recipient.current_ticket.id, "Ticket Opened", msg, recipient.ckey, src.ckey) //SKYRAT EDIT ADDITION BEGIN - ADMIN if(recipient.current_ticket.handler) if(recipient.current_ticket.handler != usr.ckey) var/response = tgui_alert(usr, "This ticket is already being handled by [recipient.current_ticket.handler]. Do you want to continue?", "Ticket already assigned", list("Yes", "No")) if(response == "No") return else recipient.current_ticket.HandleIssue() //SKYRAT EDIT ADDITION END to_chat(recipient, type = MESSAGE_TYPE_ADMINPM, html = "-- Administrator private message --", confidential = TRUE) to_chat(recipient, type = MESSAGE_TYPE_ADMINPM, html = span_adminsay("Admin PM from-[key_name(src, recipient, 0)]: [msg]"), confidential = TRUE) to_chat(recipient, type = MESSAGE_TYPE_ADMINPM, html = span_adminsay("Click on the administrator's name to reply."), confidential = TRUE) to_chat(src, type = MESSAGE_TYPE_ADMINPM, html = span_notice("Admin PM to-[key_name(recipient, src, 1)]: [msg]"), confidential = TRUE) // admin_ticket_log(recipient, "PM From [key_name_admin(src)]: [keywordparsedmsg]") // SKYRAT EDIT ORIGINAL admin_ticket_log(recipient, "PM From [key_name_admin(src, FALSE)]: [keywordparsedmsg]", FALSE) // SKYRAT EDIT CHANGE -- Player ticket viewing if(!already_logged) //Reply to an existing ticket SSblackbox.LogAhelp(recipient.current_ticket.id, "Reply", msg, recipient.ckey, src.ckey) //always play non-admin recipients the adminhelp sound SEND_SOUND(recipient, sound('sound/effects/adminhelp.ogg')) else //neither are admins if(!current_ticket) to_chat(src, type = MESSAGE_TYPE_ADMINPM, html = span_danger("Error: Admin-PM: Non-admin to non-admin PM communication is forbidden."), confidential = TRUE) to_chat(src, type = MESSAGE_TYPE_ADMINPM, html = "[span_danger("Message not sent:")]
[msg]", confidential = TRUE) return current_ticket.MessageNoRecipient(msg) if(external) log_admin_private("PM: [key_name(src)]->External: [rawmsg]") for(var/client/X in GLOB.admins) to_chat(X, type = MESSAGE_TYPE_ADMINPM, html = span_notice("PM: [key_name(src, X, 0)]->External: [keywordparsedmsg]"), confidential = TRUE) else window_flash(recipient, ignorepref = TRUE) log_admin_private("PM: [key_name(src)]->[key_name(recipient)]: [rawmsg]") //we don't use message_admins here because the sender/receiver might get it too for(var/client/X in GLOB.admins) if(X.key!=key && X.key!=recipient.key) //check client/X is an admin and isn't the sender or recipient to_chat(X, type = MESSAGE_TYPE_ADMINPM, html = span_notice("PM: [key_name(src, X, 0)]->[key_name(recipient, X, 0)]: [keywordparsedmsg]") , confidential = TRUE) #define TGS_AHELP_USAGE "Usage: ticket " /proc/TgsPm(target,msg,sender) target = ckey(target) var/client/C = GLOB.directory[target] var/datum/admin_help/ticket = C ? C.current_ticket : GLOB.ahelp_tickets.CKey2ActiveTicket(target) var/compliant_msg = trim(lowertext(msg)) var/tgs_tagged = "[sender](TGS/External)" var/list/splits = splittext(compliant_msg, " ") if(splits.len && splits[1] == "ticket") if(splits.len < 2) return TGS_AHELP_USAGE switch(splits[2]) if("close") if(ticket) ticket.Close(tgs_tagged) return "Ticket #[ticket.id] successfully closed" if("resolve") if(ticket) ticket.Resolve(tgs_tagged) return "Ticket #[ticket.id] successfully resolved" if("icissue") if(ticket) ticket.ICIssue(tgs_tagged) return "Ticket #[ticket.id] successfully marked as IC issue" if("reject") if(ticket) ticket.Reject(tgs_tagged) return "Ticket #[ticket.id] successfully rejected" if("reopen") if(ticket) return "Error: [target] already has ticket #[ticket.id] open" var/fail = splits.len < 3 ? null : -1 if(!isnull(fail)) fail = text2num(splits[3]) if(isnull(fail)) return "Error: No/Invalid ticket id specified. [TGS_AHELP_USAGE]" var/datum/admin_help/AH = GLOB.ahelp_tickets.TicketByID(fail) if(!AH) return "Error: Ticket #[fail] not found" if(AH.initiator_ckey != target) return "Error: Ticket #[fail] belongs to [AH.initiator_ckey]" AH.Reopen() return "Ticket #[ticket.id] successfully reopened" if("list") var/list/tickets = GLOB.ahelp_tickets.TicketsByCKey(target) if(!tickets.len) return "None" . = "" for(var/I in tickets) var/datum/admin_help/AH = I if(.) . += ", " if(AH == ticket) . += "Active: " . += "#[AH.id]" return else return TGS_AHELP_USAGE return "Error: Ticket could not be found" var/static/stealthkey var/adminname = CONFIG_GET(flag/show_irc_name) ? tgs_tagged : "Administrator" if(!C) return "Error: No client" if(!stealthkey) stealthkey = GenTgsStealthKey() msg = sanitize(copytext_char(msg, 1, MAX_MESSAGE_LEN)) if(!msg) return "Error: No message" message_admins("External message from [sender] to [key_name_admin(C)] : [msg]") log_admin_private("External PM: [sender] -> [key_name(C)] : [msg]") msg = emoji_parse(msg) to_chat(C, type = MESSAGE_TYPE_ADMINPM, html = "-- Administrator private message --", confidential = TRUE) to_chat(C, type = MESSAGE_TYPE_ADMINPM, html = span_adminsay("Admin PM from-[adminname]: [msg]"), confidential = TRUE) to_chat(C, type = MESSAGE_TYPE_ADMINPM, html = span_adminsay("Click on the administrator's name to reply."), confidential = TRUE) admin_ticket_log(C, "PM From [tgs_tagged]: [msg]") window_flash(C, ignorepref = TRUE) //always play non-admin recipients the adminhelp sound SEND_SOUND(C, 'sound/effects/adminhelp.ogg') C.externalreplyamount = EXTERNALREPLYCOUNT return "Message Successful" /proc/GenTgsStealthKey() var/num = (rand(0,1000)) var/i = 0 while(i == 0) i = 1 for(var/P in GLOB.stealthminID) if(num == GLOB.stealthminID[P]) num++ i = 0 var/stealth = "@[num2text(num)]" GLOB.stealthminID["IRCKEY"] = stealth return stealth #undef EXTERNALREPLYCOUNT