.BANCHO. Add spam protection, better silence handling

This commit is contained in:
Nyo 2016-06-07 22:46:31 +02:00
parent c8f9825e6b
commit ef35697772
7 changed files with 103 additions and 17 deletions

View File

@ -62,3 +62,9 @@ class apiException(Exception):
class invalidArgumentsException(Exception):
pass
class messageTooLongWarnException(Exception):
pass
class messageTooLongException(Exception):
pass

View File

@ -164,16 +164,10 @@ def silence(fro, chan, message):
if silenceTime > 604800:
return "Invalid silence time. Max silence time is 7 days."
# Calculate silence end time
endTime = int(time.time())+silenceTime
# Update silence end in db
userHelper.silence(targetUserID, endTime, reason)
# Send silence packet to target if he's connected
targetToken = glob.tokens.getTokenFromUsername(target)
if targetToken != None:
targetToken.enqueue(serverPackets.silenceEndTime(silenceTime))
targetToken.silence(silenceTime, reason)
# Log message
msg = "{} has been silenced for the following reason: {}".format(target, reason)

View File

@ -171,6 +171,9 @@ def channelInfoEnd():
def channelKicked(chan):
return packetHelper.buildPacket(packetIDs.server_channelKicked, [[chan, dataTypes.string]])
def userSilenced(userID):
return packetHelper.buildPacket(packetIDs.server_userSilenced, [[userID, dataTypes.uInt32]])
""" Spectator packets """
def addSpectator(userID):

View File

@ -7,7 +7,9 @@ from objects import fokabot
from constants import exceptions
from constants import messageTemplates
from helpers import generalFunctions
from helpers import userHelper
from helpers import logHelper as log
import time
def handle(userToken, packetData):
"""
@ -20,10 +22,18 @@ def handle(userToken, packetData):
try:
# Get usertoken username
username = userToken.username
userID = userToken.userID
# Private message packet
packetData = clientPackets.sendPrivateMessage(packetData)
# Check message length
if len(packetData["message"]) > 256:
if userToken.longMessageWarning == True:
raise exceptions.messageTooLongException
else:
raise exceptions.messageTooLongWarnException
if packetData["to"] == "FokaBot":
# FokaBot command check
fokaMessage = fokabot.fokabotResponse(username, packetData["to"], packetData["message"])
@ -47,12 +57,18 @@ def handle(userToken, packetData):
if token.awayMessage != "":
userToken.enqueue(serverPackets.sendMessage(packetData["to"], username, "This user is away: {}".format(token.awayMessage)))
# Spam protection
userToken.spamProtection()
# Console and file output
log.pm("{} -> {}: {}".format(username, packetData["to"], packetData["message"]))
# Log to chatlog_private
#with open(".data/chatlog_private.txt", "a") as f:
# f.write("[{date}] {fro} -> {to}: {message}\n".format(date=generalFunctions.getTimestamp(), fro=username, to=packetData["to"], message=str(packetData["message"].encode("utf-8"))[2:-1]))
except exceptions.tokenNotFoundException:
# Token not found, user disconnected
log.warning("{} tried to send a message to {}, but their token couldn't be found".format(username, packetData["to"]))
except exceptions.messageTooLongWarnException:
# Message > 256 warn
userToken.longMessageWarning = True
userToken.enqueue(serverPackets.sendMessage("FokaBot", username, "Your message was too long and has not been sent. Please keep your messages under 256 characters. This is your last warning."))
except exceptions.messageTooLongException:
# Message > 256 silence
userToken.silence(2*3600, "Sending messages longer than 256 characters")

View File

@ -5,6 +5,8 @@ from objects import fokabot
from constants import serverPackets
from helpers import discordBotHelper
from helpers import logHelper as log
from helpers import userHelper
import time
def handle(userToken, packetData):
"""
@ -26,6 +28,14 @@ def handle(userToken, packetData):
# Receivers
who = []
# Check message length
if len(packetData["message"]) > 256:
if userToken.longMessageWarning == True:
raise exceptions.messageTooLongException
else:
raise exceptions.messageTooLongWarnException
# Get receivers list
# Check #spectator
if packetData["to"] == "#spectator":
# Spectator channel
@ -87,7 +97,7 @@ def handle(userToken, packetData):
if userID in who:
who.remove(userID)
# We have receivers
# Send packet to required users
glob.tokens.multipleEnqueue(serverPackets.sendMessage(username, packetData["to"], packetData["message"]), who, False)
@ -98,6 +108,9 @@ def handle(userToken, packetData):
glob.tokens.multipleEnqueue(serverPackets.sendMessage("FokaBot", packetData["to"], fokaMessage), who, False)
log.chat("FokaBot @ {}: {}".format(packetData["to"], str(fokaMessage.encode("UTF-8"))))
# Spam protection
userToken.spamProtection()
# Console and file log
log.chat("{fro} @ {to}: {message}".format(fro=username, to=packetData["to"], message=str(packetData["message"].encode("utf-8"))))
@ -109,3 +122,10 @@ def handle(userToken, packetData):
log.warning("{} tried to send a message to an unknown channel ({})".format(username, packetData["to"]))
except exceptions.channelNoPermissionsException:
log.warning("{} tried to send a message to channel {}, but they have no write permissions".format(username, packetData["to"]))
except exceptions.messageTooLongWarnException:
# Message > 256 warn
userToken.longMessageWarning = True
userToken.enqueue(serverPackets.sendMessage("FokaBot", username, "Your message was too long and has not been sent. Please keep your messages under 256 characters. This is your last warning."))
except exceptions.messageTooLongException:
# Message > 256 silence
userToken.silence(2*3600, "Sending messages longer than 256 characters")

View File

@ -1,12 +1,12 @@
import uuid
from constants import actions
from constants import gameModes
from helpers import userHelper
import time
from helpers import consoleHelper
from constants import bcolors
from constants import serverPackets
from events import logoutEvent
from helpers import logHelper as log
from objects import glob
import uuid
import time
import threading
class token:
@ -95,6 +95,12 @@ class token:
self.tillerino = [0,0,-1.0] # beatmap, mods, acc
self.queue = bytes()
self.longMessageWarning = False
# Spam protection
self.spamRate = 0
self.lastMessagetime = 0
# Generate/set token
if __token != None:
self.token = __token
@ -229,9 +235,47 @@ class token:
def kick(self):
"""Kick this user from the server"""
# Send packet to target
consoleHelper.printColored("> {} has been disconnected. (kick)".format(self.username), bcolors.YELLOW)
log.info("{} has been disconnected. (kick)".format(self.username))
self.enqueue(serverPackets.notification("You have been kicked from the server. Please login again."))
self.enqueue(serverPackets.loginFailed())
# Logout event
logoutEvent.handle(self, None)
def silence(self, seconds, reason):
"""
Silences this user (both db and packet)
seconds -- silence length in seconds
reason -- silence reason
"""
# Silence user in db
userHelper.silence(self.userID, int(time.time())+seconds, reason)
# Send silence packet to target
self.enqueue(serverPackets.silenceEndTime(seconds))
# Send silenced packet to everyone else
glob.tokens.enqueueAll(serverPackets.userSilenced(self.userID))
# Log
log.info("{} has been silenced for {} seconds for the following reason: {}".format(self.username, seconds, reason), True)
def spamProtection(self, increaseSpamRate = True):
"""
Silences the user if is spamming.
increaseSpamRate -- pass True if the user has sent a new message. Optional. Default: True
"""
if increaseSpamRate == True:
# Reset spam rate every 10 seconds
if int(time.time())-self.lastMessagetime >= 10:
self.spamRate = 0
else:
self.spamRate += 1
# Update last message time
self.lastMessagetime = time.time()
# Silence the user if needed
if self.spamRate > 10:
self.silence(1800, "Spamming (auto spam protection)")

View File

@ -2,6 +2,9 @@ from objects import osuToken
import time
import threading
from events import logoutEvent
from helpers import logHelper as log
from constants import serverPackets
from helpers import userHelper
class tokenList:
"""