- Added spam-prevention code. If someone sends the same message 5 times in a row, they will get the message "You are nearing the spam filter limit for identical messages." If they continue to send the same message (if they send it 10 times in total) they will get an auto-mute for the channel they are sending it through. The number of identical messages which triggers a warning and automute can be configured in setup.dm

- Added channel-specific admin muting. Admins can now mute someone from IC (say, me and whisper), OOC, PRAY, ADMINHELP (adminhelp, admin pm and asay) and DEADCHAT (say while dead and dsay)
- Added a (?) to adminhelps and prayers which displays the same quick overview that all the other (?)-s show, but for the person adminhelping or praying.

git-svn-id: http://tgstation13.googlecode.com/svn/trunk@3888 316c924e-a436-60f5-8080-3fe189b3f50e
This commit is contained in:
baloh.matevz@gmail.com
2012-06-22 05:54:43 +00:00
parent 7a95e5c2bc
commit 9a94312431
17 changed files with 193 additions and 78 deletions

View File

@@ -27,9 +27,13 @@
else if (!dooc_allowed && !src.client.holder && (src.client.deadchat != 0))
usr << "\red OOC for dead mobs has been turned off."
return
else if (src.client && (src.client.muted || src.client.muted_complete))
src << "You are muted."
return
else if (src.client)
if(src.client.muted_ooc)
src << "\red You cannot use OOC (muted by admins)."
return
if (src.client.handle_spam_prevention(msg,MUTE_OOC))
return
else if (findtext(msg, "byond://") && !src.client.holder)
src << "<B>Advertising other servers is not allowed.</B>"
log_admin("[key_name(src)] has attempted to advertise in OOC: [msg]")

View File

@@ -752,34 +752,23 @@ var/global/BSACooldown = 0
message_admins("\blue [key_name_admin(usr)] removed [t] from the goonlist.")
remove_goon(t)
*/
if (href_list["mute2"])
if ((src.rank in list( "Moderator", "Temporary Admin", "Admin Candidate", "Trial Admin", "Badmin", "Game Admin", "Game Master" )))
var/mob/M = locate(href_list["mute2"])
if (href_list["mute"])
if ((src.rank in list( "Temporary Admin", "Admin Candidate", "Trial Admin", "Badmin", "Game Admin", "Game Master" )))
var/mob/M = locate(href_list["mute"])
var/mute_type = href_list["mute_type"]
if(istext(mute_type))
mute_type = text2num(mute_type)
if(!isnum(mute_type))
return
if (ismob(M))
if ((M.client && M.client.holder && (M.client.holder.level >= src.level)))
alert("You cannot perform this action. You must be of a higher administrative rank!", null, null, null, null, null)
return
if(!M.client)
src << "This mob doesn't have a client tied to it."
return
M.client.muted = !M.client.muted
log_admin("[key_name(usr)] has [(M.client.muted ? "muted" : "voiced")] [key_name(M)].")
message_admins("\blue [key_name_admin(usr)] has [(M.client.muted ? "muted" : "voiced")] [key_name_admin(M)].", 1)
M << "You have been [(M.client.muted ? "muted" : "voiced")]. Please resolve this in adminhelp."
if (href_list["mute_complete"])
if ((src.rank in list( "Moderator", "Temporary Admin", "Admin Candidate", "Trial Admin", "Badmin", "Game Admin", "Game Master" )))
var/mob/M = locate(href_list["mute_complete"])
if (ismob(M))
if ((M.client && M.client.holder && (M.client.holder.level >= src.level)))
alert("You cannot perform this action. You must be of a higher administrative rank!", null, null, null, null, null)
return
if(!M.client)
src << "This mob doesn't have a client tied to it."
return
M.client.muted_complete = !M.client.muted_complete
log_admin("[key_name(usr)] has [(M.client.muted_complete ? "completely muted" : "voiced (complete)")] [key_name(M)].")
message_admins("\blue [key_name_admin(usr)] has [(M.client.muted_complete ? "completely muted" : "voiced (complete)")] [key_name_admin(M)].", 1)
M << "You have been [(M.client.muted_complete ? "completely muted" : "voiced (complete)")]. You are unable to speak or even adminhelp"
cmd_admin_mute(M, mute_type)
if (href_list["c_mode"])
if ((src.rank in list( "Temporary Admin", "Admin Candidate", "Trial Admin", "Badmin", "Game Admin", "Game Master" )))
@@ -1234,6 +1223,10 @@ var/global/BSACooldown = 0
if (href_list["adminmoreinfo"])
var/mob/M = locate(href_list["adminmoreinfo"])
if(!M)
usr << "\blue The mob no longer exists."
return
if(src && src.owner)
var/location_description = ""
var/special_role_description = ""
@@ -2279,14 +2272,13 @@ var/global/BSACooldown = 0
if(M.client)
body += "| <A HREF='?src=\ref[src];sendtoprison=\ref[M]'>Prison</A> | "
body += "<b>Mute:</b> "
if(M.client.muted_complete)
body += "<b>Completely Muted:</b> (<A href='?src=\ref[src];mute_complete=\ref[M]'>Allow adminhelp</A>)"
else
if(M.client.muted)
body += "<b>Soft Mute:</b> (<A href='?src=\ref[src];mute2=\ref[M]'>Unmute</A>) (<A href='?src=\ref[src];mute_complete=\ref[M]'>Mute adminhelps</A>)"
else
body += "Voiced: (<A href='?src=\ref[src];mute2=\ref[M]'>Mute</A>)"
body += "<br><b>Mute: </b> "
body += "\[<A href='?src=\ref[src];mute=\ref[M];mute_type=[MUTE_IC]'><font color='[(M.client.muted_ic)?"red":"blue"]'>IC</font></a> | "
body += "<A href='?src=\ref[src];mute=\ref[M];mute_type=[MUTE_OOC]'><font color='[(M.client.muted_ooc)?"red":"blue"]'>OOC</font></a> | "
body += "<A href='?src=\ref[src];mute=\ref[M];mute_type=[MUTE_PRAY]'><font color='[(M.client.muted_pray)?"red":"blue"]'>PRAY</font></a> | "
body += "<A href='?src=\ref[src];mute=\ref[M];mute_type=[MUTE_ADMINHELP]'><font color='[(M.client.muted_adminhelp)?"red":"blue"]'>ADMINHELP</font></a> | "
body += "<A href='?src=\ref[src];mute=\ref[M];mute_type=[MUTE_DEADCHAT]'><font color='[(M.client.muted_deadchat)?"red":"blue"]'>DEADCHAT</font></a>\]"
body += "(<A href='?src=\ref[src];mute=\ref[M];mute_type=[MUTE_ALL]'>toggle all</a>)"
body += "<br><br>"
body += "<A href='?src=\ref[src];jumpto=\ref[M]'><b>Jump to</b></A> | "

View File

@@ -1,14 +1,17 @@
//This is a list of words which are ignored by the parser when comparing message contents for names. MUST BE IN LOWER CASE!
var/list/adminhelp_ignored_words = list("unknown","the","a","an", "monkey", "alien")
var/list/adminhelp_ignored_words = list("unknown","the","a","an", "monkey", "alien", "as")
/client/verb/adminhelp(msg as text)
set category = "Admin"
set name = "Adminhelp"
if (muted_complete)
src << "<font color='red'>Error: Admin-PM: You are completely muted.</font>"
if (muted_adminhelp)
src << "<font color='red'>Error: Admin-PM: You cannot send adminhelps (Muted by admins).</font>"
return
if (src.handle_spam_prevention(msg,MUTE_ADMINHELP))
return
if(!msg) return
@@ -80,7 +83,7 @@ var/list/adminhelp_ignored_words = list("unknown","the","a","an", "monkey", "ali
if (X.holder)
if(X.sound_adminhelp)
X << 'adminhelp.ogg'
var/msg_to_send = "\blue <b><font color=red>HELP: </font>[key_name(src, X)] (<A HREF='?src=\ref[X.holder];adminplayeropts=[ref_mob]'>PP</A>) (<A HREF='?src=\ref[X.holder];adminplayervars=[ref_mob]'>VV</A>) (<A HREF='?src=\ref[X.holder];adminplayersubtlemessage=[ref_mob]'>SM</A>) (<A HREF='?src=\ref[X.holder];adminplayerobservejump=[ref_mob]'>JMP</A>) (<A HREF='?src=\ref[X.holder];secretsadmin=check_antagonist'>CA</A>):</b> [msg]"
var/msg_to_send = "\blue <b><font color=red>HELP: </font>[key_name(src, X)] (<A HREF='?src=\ref[X.holder];adminmoreinfo=[ref_mob]'>?</A>) (<A HREF='?src=\ref[X.holder];adminplayeropts=[ref_mob]'>PP</A>) (<A HREF='?src=\ref[X.holder];adminplayervars=[ref_mob]'>VV</A>) (<A HREF='?src=\ref[X.holder];adminplayersubtlemessage=[ref_mob]'>SM</A>) (<A HREF='?src=\ref[X.holder];adminplayerobservejump=[ref_mob]'>JMP</A>) (<A HREF='?src=\ref[X.holder];secretsadmin=check_antagonist'>CA</A>):</b> [msg]"
msg_to_send = dd_replaceText(msg_to_send, "HOLDERREF", "\ref[X.holder]")
msg_to_send = dd_replaceText(msg_to_send, "ADMINREF", "\ref[X]")
X << msg_to_send

View File

@@ -36,8 +36,11 @@
//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(var/client/C, var/msg)
if(src.muted_complete)
src << "<font color='red'>Error: Admin-PM: You are completely muted.</font>"
if(src.muted_adminhelp)
src << "<font color='red'>Error: Admin-PM: You are unable to use admin PM-s (muted by admins).</font>"
return
if (src.handle_spam_prevention(msg,MUTE_ADMINHELP))
return
if( !C || !istype(C,/client) )

View File

@@ -7,8 +7,11 @@
src << "Only administrators may use this command."
return
if (src.muted || src.muted_complete)
src << "You are muted."
if (src.muted_adminhelp)
src << "You cannot send ASAY messages (muted by admins)."
return
if (src.handle_spam_prevention(msg,MUTE_ADMINHELP))
return
msg = copytext(sanitize(msg), 1, MAX_MESSAGE_LEN)

View File

@@ -7,7 +7,11 @@
return
if(!src.mob)
return
if(src.muted || src.muted_complete)
if(src.muted_deadchat)
src << "\red You cannot send DSAY messages (muted by admins)."
return
if (src.handle_spam_prevention(msg,MUTE_DEADCHAT))
return
msg = copytext(sanitize(msg), 1, MAX_MESSAGE_LEN)

View File

@@ -7,14 +7,18 @@
if (!msg)
return
if (usr.client && (usr.client.muted || usr.client.muted_complete))
return
if (usr.client)
if(usr.client.muted_pray)
return
if (src.client.handle_spam_prevention(msg,MUTE_PRAY))
return
var/icon/cross = icon('storage.dmi',"bible")
for (var/mob/M in world)
if (M.client && M.client.holder && M.client.seeprayers)
M << "\blue \icon[cross] <b><font color=purple>PRAY: </font>[key_name(src, M)] (<A HREF='?src=\ref[M.client.holder];adminplayeropts=\ref[src]'>PP</A>) (<A HREF='?src=\ref[M.client.holder];adminplayervars=\ref[src]'>VV</A>) (<A HREF='?src=\ref[M.client.holder];adminplayersubtlemessage=\ref[src]'>SM</A>) (<A HREF='?src=\ref[M.client.holder];adminplayerobservejump=\ref[src]'>JMP</A>) (<A HREF='?src=\ref[M.client.holder];secretsadmin=check_antagonist'>CA</A>) (<A HREF='?src=\ref[M.client.holder];adminspawncookie=\ref[src]'>SC</a>):</b> [msg]"
M << "\blue \icon[cross] <b><font color=purple>PRAY: </font>[key_name(src, M)] (<A HREF='?src=\ref[M.client.holder];adminmoreinfo=\ref[src]'>?</A>) (<A HREF='?src=\ref[M.client.holder];adminplayeropts=\ref[src]'>PP</A>) (<A HREF='?src=\ref[M.client.holder];adminplayervars=\ref[src]'>VV</A>) (<A HREF='?src=\ref[M.client.holder];adminplayersubtlemessage=\ref[src]'>SM</A>) (<A HREF='?src=\ref[M.client.holder];adminplayerobservejump=\ref[src]'>JMP</A>) (<A HREF='?src=\ref[M.client.holder];secretsadmin=check_antagonist'>CA</A>) (<A HREF='?src=\ref[M.client.holder];adminspawncookie=\ref[src]'>SC</a>):</b> [msg]"
usr << "Your prayers have been received by the gods."
feedback_add_details("admin_verb","PR") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!

View File

@@ -123,25 +123,73 @@
message_admins("[key_name_admin(usr)] has toggled [key_name_admin(M)]'s nodamage to [(M.nodamage ? "On" : "Off")]", 1)
feedback_add_details("admin_verb","GOD") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/cmd_admin_mute(mob/M as mob in world)
set category = "Special Verbs"
set name = "Admin Mute"
if(!holder)
src << "Only administrators may use this command."
return
if (M.client && M.client.holder && (M.client.holder.level >= holder.level))
alert("You cannot perform this action. You must be of a higher administrative rank!", null, null, null, null, null)
return
proc/cmd_admin_mute(mob/M as mob, mute_type, automute = 0)
if(!automute)
if(usr && usr.client)
if(!usr.client.holder)
src << "Only administrators may use this command."
return
if (M.client && M.client.holder && (M.client.holder.level >= usr.client.holder.level))
alert("You cannot perform this action. You must be of a higher administrative rank!", null, null, null, null, null)
return
if(!M.client)
src << "This mob doesn't have a client tied to it."
return
M.client.muted = !M.client.muted
log_admin("[key_name(src)] has [(M.client.muted ? "muted" : "voiced")] [key_name(M)].")
message_admins("[key_name_admin(src)] has [(M.client.muted ? "muted" : "voiced")] [key_name_admin(M)].", 1)
var/muteunmute = 0 //0 = unmuted; 1 = muted
var/mute_string = "unknown"
M << "You have been [(M.client.muted ? "muted" : "voiced")]."
feedback_add_details("admin_verb","MUTE") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
//The '| automute' thing ensures that if an automute is being applied by code, it always mutes to prevent any potential for automute to unmute someone who was muted.
switch(mute_type)
if(MUTE_IC)
M.client.muted_ic = !M.client.muted_ic | automute
muteunmute = M.client.muted_ic
mute_string = "IC (say and emote)"
if(MUTE_OOC)
M.client.muted_ooc = !M.client.muted_ooc | automute
muteunmute = M.client.muted_ooc
mute_string = "OOC"
if(MUTE_PRAY)
M.client.muted_pray = !M.client.muted_pray | automute
muteunmute = M.client.muted_pray
mute_string = "pray"
if(MUTE_ADMINHELP)
M.client.muted_adminhelp = !M.client.muted_adminhelp | automute
muteunmute = M.client.muted_adminhelp
mute_string = "adminhelp, admin PM and ASAY"
if(MUTE_DEADCHAT)
M.client.muted_deadchat = !M.client.muted_deadchat | automute
muteunmute = M.client.muted_deadchat
mute_string = "deadchat and DSAY"
if(MUTE_ALL)
mute_string = "everything"
if( M.client.muted_ic )
M.client.muted_ic = 1
M.client.muted_ooc = 1
M.client.muted_pray = 1
M.client.muted_adminhelp = 1
M.client.muted_deadchat = 1
muteunmute = 1
else
M.client.muted_ic = 0
M.client.muted_ooc = 0
M.client.muted_pray = 0
M.client.muted_adminhelp = 0
M.client.muted_deadchat = 0
muteunmute = 0
if(!automute)
log_admin("[key_name(usr)] has [(muteunmute ? "muted" : "voiced")] [key_name(M)] from [mute_string]")
message_admins("[key_name_admin(usr)] has [(muteunmute ? "muted" : "voiced")] [key_name_admin(M)] from [mute_string].", 1)
M << "You have been [(muteunmute ? "muted" : "voiced")] from [mute_string] by [(usr.client.stealth)?"an admin":"[usr.client]"]."
feedback_add_details("admin_verb","MUTE") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
else
log_admin("SPAM AUTOMUTE: [(muteunmute ? "muted" : "voiced")] [key_name(M)] from [mute_string]")
message_admins("SPAM AUTOMUTE: [(muteunmute ? "muted" : "voiced")] [key_name_admin(M)] from [mute_string].", 1)
M << "You have been [(muteunmute ? "muted" : "voiced")] from [mute_string] by the SPAM AUTOMUTE system. Contact an admin."
feedback_add_details("admin_verb","AUTOMUTE") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/cmd_admin_add_random_ai_law()

View File

@@ -9,8 +9,16 @@
var/fakekey = null
var/seeprayers = 0
var/ooccolor = "#b82e00"
var/muted = null //Can't talk in OOC, say, whisper, emote... anything except for adminhelp and admin-pm. An admin punishment
var/muted_complete = null //Can't talk in any way shape or form (muted + can't adminhelp or respond to admin pm-s). An admin punishment
var/muted_ic //can't use 'say' while alive or emotes.
var/muted_ooc //can't speak in ooc
var/muted_deadchat //can't use 'say' while dead or DSAY
var/muted_pray //can't send prayers
var/muted_adminhelp //can't send adminhelps, PM-s or use ASAY
var/last_message = "" //Contains the last message sent by this client - used to protect against copy-paste spamming.
var/last_message_count = 0 //contins a number of how many times a message identical to last_message was sent.
var/warned = 0
var/sound_adminhelp = 0 //If set to 1 this will play a sound when adminhelps are received.

View File

@@ -52,6 +52,20 @@
..() //redirect to [locate(hsrc)]/Topic()
/client/proc/handle_spam_prevention(var/message, var/mute_type)
if(src.last_message == message)
src.last_message_count++
if(src.last_message_count >= SPAM_TRIGGER_AUTOMUTE)
src << "\red You have exceeded the spam filter limit for identical messages. An auto-mute was applied."
cmd_admin_mute(src.mob, mute_type, 1)
return 1
if(src.last_message_count >= SPAM_TRIGGER_WARNING)
src << "\red You are nearing the spam filter limit for identical messages."
return 0
else
last_message = message
src.last_message_count = 0
return 0
//This stops files larger than UPLOAD_LIMIT being sent from client to server via input(), client.Import() etc.
/client/AllowUpload(filename, filelength)

View File

@@ -9,9 +9,13 @@
log_say("Ghost/[src.key] : [message]")
if (src.client && (src.client.muted || src.client.muted_complete))
src << "You are muted."
return
if (src.client)
if(src.client.muted_deadchat)
src << "\red You cannot talk in deadchat (muted by admins)."
return
if (src.client.handle_spam_prevention(message,MUTE_DEADCHAT))
return
. = src.say_dead(message)

View File

@@ -65,9 +65,12 @@
if ("me")
if(silent)
return
if (src.client && (client.muted || client.muted_complete))
src << "You are muted."
return
if (src.client)
if (client.muted_ic)
src << "\red You cannot send IC messages (muted by admins)."
return
if (src.client.handle_spam_prevention(message,MUTE_IC))
return
if (stat)
return
if(!(message))

View File

@@ -10,9 +10,14 @@
log_whisper("[src.name]/[src.key] : [message]")
if (src.client && (src.client.muted || src.client.muted_complete))
src << "You are muted."
return
if (src.client)
if (src.client.muted_ic)
src << "\red You cannot whisper (muted by admins)."
return
if (src.client.handle_spam_prevention(message,MUTE_IC))
return
if (src.stat == 2)
return src.say_dead(message)

View File

@@ -92,9 +92,12 @@ var/list/department_radio_keys = list(
if (silent)
return
if (src.client && (client.muted || src.client.muted_complete))
src << "You are muted."
return
if (src.client)
if(client.muted_ic)
src << "\red You cannot speak in IC (muted by admins)."
return
if (src.client.handle_spam_prevention(message,MUTE_IC))
return
// stat == 2 is handled above, so this stops transmission of uncontious messages
if (stat)

View File

@@ -70,9 +70,12 @@
if ("me")
if(silent)
return
if (src.client && (client.muted || client.muted_complete))
src << "You are muted."
return
if (src.client)
if(client.muted_ic)
src << "You cannot send IC messages (muted by admins)."
return
if (src.client.handle_spam_prevention(message,MUTE_IC))
return
if (stat)
return
if(!(message))

View File

@@ -2,9 +2,12 @@
if (!message)
return
if (src.client && (client.muted || src.client.muted_complete))
src << "You are muted."
return
if (src.client)
if(client.muted_ic)
src << "You cannot send IC messages (muted by admins)."
return
if (src.client.handle_spam_prevention(message,MUTE_IC))
return
if (stat == 2)
message = trim(copytext(sanitize(message), 1, MAX_MESSAGE_LEN))

View File

@@ -361,3 +361,14 @@ var/list/liftable_structures = list(\
/obj/structure/filingcabinet, \
/obj/structure/reagent_dispensers, \
/obj/machinery/portable_atmospherics/canister)
//A set of constants used to determine which type of mute an admin wishes to apply:
#define MUTE_IC 1
#define MUTE_OOC 2
#define MUTE_PRAY 3
#define MUTE_ADMINHELP 4
#define MUTE_DEADCHAT 5
#define MUTE_ALL 6
#define SPAM_TRIGGER_WARNING 5
#define SPAM_TRIGGER_AUTOMUTE 10