Commit 2ee0b6fd authored by Cool Fire's avatar Cool Fire

Add WIP floodprotect plugin

parent 54783ad9
Pipeline #2494 failed with stages
in 4 minutes and 19 seconds
#!/usr/bin/env ruby
# Plugin to prevent people from flooding channels
# Keeps track of the number of messages per nickname
# in a sliding window.
class Floodprotect
require 'date'
def initialize( status, config, output, irc, timer )
@status = status
@config = config
@output = output
@irc = irc
@timer = timer
@channels = ['#shells']
@window = 15
@max = 10
@counters = {}
@warnings = {}
@bantime = 86400 # 24 hours
end
def messaged( nick, _user, _host, from, _message )
if @channels.include? from
raisecounter(nick, from)
end
end
# Function to send help about this plugin (Can also be called by the help plugin.)
def help( nick, _user, _host, _from, _msg, _arguments, con )
help = [
'Plugin to prevent channel flooding.',
' floodprotect reset [nick] - Reset counters for a nickname.',
' floodprotect window [second] - Length of time to track.',
' floodprotect max [number] - Number of messages per window.',
' floodprotect addchannel [channel] - Add a channel to the protection list.',
' floodprotect delchannel [channel] - Delete a channel from the protection list.'
]
# Print out help
help.each do |line|
if( con )
@output.c( line + "\n" )
else
@irc.notice( nick, line )
end
end
end
# Reset counter for a nickname
def reset( nick, _user, host, from, _msg, _arguments, con )
if( @config.auth( host, con ) )
# Admin only code goes in here
@irc.message( from, nick + " called \"reset\" from " + from + "." )
end
end
# Set length of sliding window to track
def window( nick, _user, host, from, _msg, _arguments, con )
if( @config.auth( host, con ) )
# Admin only code goes in here
@irc.message( from, nick + " called \"window\" from " + from + "." )
end
end
# Set number of messages allowed in the sliding window
def max( nick, _user, host, from, _msg, _arguments, con )
if( @config.auth( host, con ) )
# Admin only code goes in here
@irc.message( from, nick + " called \"max\" from " + from + "." )
end
end
private
# Check if a nick is in the counter list, and add it if not
def check_nick_exists(nick)
@counters[nick] = [] unless @counters.key? nick
end
# Clear up old entries
def clean_counters
@counters.each_key do |nick|
tmp = []
@counters[nick].each do |timestamp|
tmp.push timestamp if ((DateTime.now - timestamp) * 86400).to_i <= @window
end
@counters[nick] = tmp
end
end
# Check if a nick has violated the limits
def check_counters(nick, from)
take_action(nick, from) if @counters[nick].size >= @max
@counters.delete nick if @counters[nick].size == 0
end
# See if a user has recently been warned
def check_warnings(nick)
if @warnings.key? nick
if (DateTime.now - @warnings[nick]).to_i > 0
@warnings[nick] = DateTime.now
return false
else
@warnings[nick] = DateTime.now
return true
end
else
@warnings[nick] = DateTime.now
return false
end
end
# Do something to stop a user flooding
def take_action(nick, from)
# Either kick or kickban a user
if check_warnings(nick)
@irc.mode(from, '+b', "#{nick}!*@*", true)
@irc.kick(from, nick, 'Banned for 24h (Flooding)', true)
@timer.action(@bantime, "@irc.mode( \"#{from}\", \"-b\", \"#{nick}!*@*\", true )")
else
@irc.kick(from, nick, 'Flooding', true)
end
end
def raisecounter(nick, from)
check_nick_exists(nick)
@counters[nick].push DateTime.now
clean_counters
check_counters(nick, from)
end
end
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment