.BANCHO. Add spam protection, better silence handling
This commit is contained in:
parent
c8f9825e6b
commit
ef35697772
|
@ -62,3 +62,9 @@ class apiException(Exception):
|
||||||
|
|
||||||
class invalidArgumentsException(Exception):
|
class invalidArgumentsException(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
class messageTooLongWarnException(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class messageTooLongException(Exception):
|
||||||
|
pass
|
||||||
|
|
|
@ -164,16 +164,10 @@ def silence(fro, chan, message):
|
||||||
if silenceTime > 604800:
|
if silenceTime > 604800:
|
||||||
return "Invalid silence time. Max silence time is 7 days."
|
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
|
# Send silence packet to target if he's connected
|
||||||
targetToken = glob.tokens.getTokenFromUsername(target)
|
targetToken = glob.tokens.getTokenFromUsername(target)
|
||||||
if targetToken != None:
|
if targetToken != None:
|
||||||
targetToken.enqueue(serverPackets.silenceEndTime(silenceTime))
|
targetToken.silence(silenceTime, reason)
|
||||||
|
|
||||||
# Log message
|
# Log message
|
||||||
msg = "{} has been silenced for the following reason: {}".format(target, reason)
|
msg = "{} has been silenced for the following reason: {}".format(target, reason)
|
||||||
|
|
|
@ -171,6 +171,9 @@ def channelInfoEnd():
|
||||||
def channelKicked(chan):
|
def channelKicked(chan):
|
||||||
return packetHelper.buildPacket(packetIDs.server_channelKicked, [[chan, dataTypes.string]])
|
return packetHelper.buildPacket(packetIDs.server_channelKicked, [[chan, dataTypes.string]])
|
||||||
|
|
||||||
|
def userSilenced(userID):
|
||||||
|
return packetHelper.buildPacket(packetIDs.server_userSilenced, [[userID, dataTypes.uInt32]])
|
||||||
|
|
||||||
|
|
||||||
""" Spectator packets """
|
""" Spectator packets """
|
||||||
def addSpectator(userID):
|
def addSpectator(userID):
|
||||||
|
|
|
@ -7,7 +7,9 @@ from objects import fokabot
|
||||||
from constants import exceptions
|
from constants import exceptions
|
||||||
from constants import messageTemplates
|
from constants import messageTemplates
|
||||||
from helpers import generalFunctions
|
from helpers import generalFunctions
|
||||||
|
from helpers import userHelper
|
||||||
from helpers import logHelper as log
|
from helpers import logHelper as log
|
||||||
|
import time
|
||||||
|
|
||||||
def handle(userToken, packetData):
|
def handle(userToken, packetData):
|
||||||
"""
|
"""
|
||||||
|
@ -20,10 +22,18 @@ def handle(userToken, packetData):
|
||||||
try:
|
try:
|
||||||
# Get usertoken username
|
# Get usertoken username
|
||||||
username = userToken.username
|
username = userToken.username
|
||||||
|
userID = userToken.userID
|
||||||
|
|
||||||
# Private message packet
|
# Private message packet
|
||||||
packetData = clientPackets.sendPrivateMessage(packetData)
|
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":
|
if packetData["to"] == "FokaBot":
|
||||||
# FokaBot command check
|
# FokaBot command check
|
||||||
fokaMessage = fokabot.fokabotResponse(username, packetData["to"], packetData["message"])
|
fokaMessage = fokabot.fokabotResponse(username, packetData["to"], packetData["message"])
|
||||||
|
@ -47,12 +57,18 @@ def handle(userToken, packetData):
|
||||||
if token.awayMessage != "":
|
if token.awayMessage != "":
|
||||||
userToken.enqueue(serverPackets.sendMessage(packetData["to"], username, "This user is away: {}".format(token.awayMessage)))
|
userToken.enqueue(serverPackets.sendMessage(packetData["to"], username, "This user is away: {}".format(token.awayMessage)))
|
||||||
|
|
||||||
|
# Spam protection
|
||||||
|
userToken.spamProtection()
|
||||||
|
|
||||||
# Console and file output
|
# Console and file output
|
||||||
log.pm("{} -> {}: {}".format(username, packetData["to"], packetData["message"]))
|
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:
|
except exceptions.tokenNotFoundException:
|
||||||
# Token not found, user disconnected
|
# Token not found, user disconnected
|
||||||
log.warning("{} tried to send a message to {}, but their token couldn't be found".format(username, packetData["to"]))
|
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")
|
||||||
|
|
|
@ -5,6 +5,8 @@ from objects import fokabot
|
||||||
from constants import serverPackets
|
from constants import serverPackets
|
||||||
from helpers import discordBotHelper
|
from helpers import discordBotHelper
|
||||||
from helpers import logHelper as log
|
from helpers import logHelper as log
|
||||||
|
from helpers import userHelper
|
||||||
|
import time
|
||||||
|
|
||||||
def handle(userToken, packetData):
|
def handle(userToken, packetData):
|
||||||
"""
|
"""
|
||||||
|
@ -26,6 +28,14 @@ def handle(userToken, packetData):
|
||||||
# Receivers
|
# Receivers
|
||||||
who = []
|
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
|
# Check #spectator
|
||||||
if packetData["to"] == "#spectator":
|
if packetData["to"] == "#spectator":
|
||||||
# Spectator channel
|
# Spectator channel
|
||||||
|
@ -87,7 +97,7 @@ def handle(userToken, packetData):
|
||||||
if userID in who:
|
if userID in who:
|
||||||
who.remove(userID)
|
who.remove(userID)
|
||||||
|
|
||||||
|
# We have receivers
|
||||||
# Send packet to required users
|
# Send packet to required users
|
||||||
glob.tokens.multipleEnqueue(serverPackets.sendMessage(username, packetData["to"], packetData["message"]), who, False)
|
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)
|
glob.tokens.multipleEnqueue(serverPackets.sendMessage("FokaBot", packetData["to"], fokaMessage), who, False)
|
||||||
log.chat("FokaBot @ {}: {}".format(packetData["to"], str(fokaMessage.encode("UTF-8"))))
|
log.chat("FokaBot @ {}: {}".format(packetData["to"], str(fokaMessage.encode("UTF-8"))))
|
||||||
|
|
||||||
|
# Spam protection
|
||||||
|
userToken.spamProtection()
|
||||||
|
|
||||||
# Console and file log
|
# Console and file log
|
||||||
log.chat("{fro} @ {to}: {message}".format(fro=username, to=packetData["to"], message=str(packetData["message"].encode("utf-8"))))
|
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"]))
|
log.warning("{} tried to send a message to an unknown channel ({})".format(username, packetData["to"]))
|
||||||
except exceptions.channelNoPermissionsException:
|
except exceptions.channelNoPermissionsException:
|
||||||
log.warning("{} tried to send a message to channel {}, but they have no write permissions".format(username, packetData["to"]))
|
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")
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
import uuid
|
|
||||||
from constants import actions
|
from constants import actions
|
||||||
from constants import gameModes
|
from constants import gameModes
|
||||||
from helpers import userHelper
|
from helpers import userHelper
|
||||||
import time
|
|
||||||
from helpers import consoleHelper
|
|
||||||
from constants import bcolors
|
|
||||||
from constants import serverPackets
|
from constants import serverPackets
|
||||||
from events import logoutEvent
|
from events import logoutEvent
|
||||||
|
from helpers import logHelper as log
|
||||||
|
from objects import glob
|
||||||
|
import uuid
|
||||||
|
import time
|
||||||
import threading
|
import threading
|
||||||
|
|
||||||
class token:
|
class token:
|
||||||
|
@ -95,6 +95,12 @@ class token:
|
||||||
self.tillerino = [0,0,-1.0] # beatmap, mods, acc
|
self.tillerino = [0,0,-1.0] # beatmap, mods, acc
|
||||||
self.queue = bytes()
|
self.queue = bytes()
|
||||||
|
|
||||||
|
self.longMessageWarning = False
|
||||||
|
|
||||||
|
# Spam protection
|
||||||
|
self.spamRate = 0
|
||||||
|
self.lastMessagetime = 0
|
||||||
|
|
||||||
# Generate/set token
|
# Generate/set token
|
||||||
if __token != None:
|
if __token != None:
|
||||||
self.token = __token
|
self.token = __token
|
||||||
|
@ -229,9 +235,47 @@ class token:
|
||||||
def kick(self):
|
def kick(self):
|
||||||
"""Kick this user from the server"""
|
"""Kick this user from the server"""
|
||||||
# Send packet to target
|
# 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.notification("You have been kicked from the server. Please login again."))
|
||||||
self.enqueue(serverPackets.loginFailed())
|
self.enqueue(serverPackets.loginFailed())
|
||||||
|
|
||||||
# Logout event
|
# Logout event
|
||||||
logoutEvent.handle(self, None)
|
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)")
|
||||||
|
|
|
@ -2,6 +2,9 @@ from objects import osuToken
|
||||||
import time
|
import time
|
||||||
import threading
|
import threading
|
||||||
from events import logoutEvent
|
from events import logoutEvent
|
||||||
|
from helpers import logHelper as log
|
||||||
|
from constants import serverPackets
|
||||||
|
from helpers import userHelper
|
||||||
|
|
||||||
class tokenList:
|
class tokenList:
|
||||||
"""
|
"""
|
||||||
|
|
Loading…
Reference in New Issue
Block a user