better way to handle socket's call inside thread instead of fake internal messages

This commit is contained in:
Nicolas Coevoet 2016-01-08 18:33:25 +01:00
parent 31911a8cdd
commit ecaa309c30
2 changed files with 72 additions and 97 deletions

View File

@ -152,11 +152,11 @@ conf.registerChannelValue(ChanTracker, 'keepOp',
conf.registerChannelValue(ChanTracker, 'kickMode', conf.registerChannelValue(ChanTracker, 'kickMode',
registry.CommaSeparatedListOfStrings(['b'], """bot will kick affected users when mode is triggered, registry.CommaSeparatedListOfStrings(['b'], """bot will kick affected users when mode is triggered,
use if with caution, if an op bans *!*@*, bot will kick everyone on the channel""")) use with caution, if an op bans *!*@*, bot will kick everyone on the channel"""))
conf.registerChannelValue(ChanTracker, 'kickOnMode', conf.registerChannelValue(ChanTracker, 'kickOnMode',
registry.Boolean(False, """bot will kick affected users when kickMode is triggered by someone, registry.Boolean(False, """bot will kick affected users when kickMode is triggered by someone,
use if with caution""")) use with caution"""))
conf.registerChannelValue(ChanTracker, 'kickMax', conf.registerChannelValue(ChanTracker, 'kickMax',
registry.Integer(-1,"""if > 0, disable kick if affected users > kickMax, avoid to cleanup entire channel with ban like *!*@*""")) registry.Integer(-1,"""if > 0, disable kick if affected users > kickMax, avoid to cleanup entire channel with ban like *!*@*"""))
@ -198,7 +198,7 @@ conf.registerChannelValue(ChanTracker, 'skynet',
#clone #clone
conf.registerChannelValue(ChanTracker, 'clonePermit', conf.registerChannelValue(ChanTracker, 'clonePermit',
registry.Integer(-1,"""Number of messages allowed , -1 to disable""")) registry.Integer(-1,"""Number of clones allowed , -1 to disable"""))
conf.registerChannelValue(ChanTracker, 'cloneMode', conf.registerChannelValue(ChanTracker, 'cloneMode',
registry.String('d',"""mode used by the bot when clone detection is triggered""")) registry.String('d',"""mode used by the bot when clone detection is triggered"""))
conf.registerChannelValue(ChanTracker, 'cloneDuration', conf.registerChannelValue(ChanTracker, 'cloneDuration',

159
plugin.py
View File

@ -83,25 +83,6 @@ def matchHostmask (pattern,n,resolve):
if host.find('/') != -1: if host.find('/') != -1:
if host.startswith('gateway/web/freenode/ip.'): if host.startswith('gateway/web/freenode/ip.'):
n.ip = cache[n.prefix] = host.split('ip.')[1] n.ip = cache[n.prefix] = host.split('ip.')[1]
#elif resolve:
#if not n.prefix in cache:
#try:
#r = socket.getaddrinfo(host,None)
#if r != None:
#u = {}
#L = []
#for item in r:
#if not item[4][0] in u:
#u[item[4][0]] = item[4][0]
#L.append(item[4][0])
#if len(L) == 1:
#n.setIp(L[0])
#except:
#t = ''
#if n.ip != None:
#cache[n.prefix] = n.ip
#else:
#cache[n.prefix] = host
try: try:
if n.ip != None and pattern.find('@') != -1 and mcidr.match(pattern.split('@')[1]) and IPAddress(u'%s' % n.ip) in IPNetwork(u'%s' % pattern.split('@')[1]): if n.ip != None and pattern.find('@') != -1 and mcidr.match(pattern.split('@')[1]) and IPAddress(u'%s' % n.ip) in IPNetwork(u'%s' % pattern.split('@')[1]):
if ircutils.hostmaskPatternEqual('%s@*' % pattern.split('@')[0],'%s!%s@%s' % (nick,ident,n.ip)): if ircutils.hostmaskPatternEqual('%s@*' % pattern.split('@')[0],'%s!%s@%s' % (nick,ident,n.ip)):
@ -1197,34 +1178,6 @@ class ChanTracker(callbacks.Plugin,plugins.ChannelDBHandler):
if self.registryValue('announceNagInterval') > 0: if self.registryValue('announceNagInterval') > 0:
schedule.addEvent(self.checkNag,time.time()+self.registryValue('announceNagInterval')) schedule.addEvent(self.checkNag,time.time()+self.registryValue('announceNagInterval'))
def resolve (self,irc,msg,args,nick):
"""internaly used by the bot if resolveIp is True and usefull with supybot.debug.threadAllCommands to True"""
irc.noReply();
if msg.prefix == irc.prefix:
i = self.getIrc(irc)
n = self.getNick(irc,nick)
if n:
(nick,ident,host) = ircutils.splitHostmask(n.prefix)
if not n.prefix in cache and host.find('/') == -1:
try:
r = socket.getaddrinfo(host,None)
if r != None:
u = {}
L = []
for item in r:
if not item[4][0] in u:
u[item[4][0]] = item[4][0]
L.append(item[4][0])
if len(L) == 1:
n.setIp(L[0])
except:
t = ''
if n.ip != None:
cache[n.prefix] = n.ip
else:
cache[n.prefix] = host
resolve = wrap(resolve,['text'])
def checkNag (self): def checkNag (self):
if world: if world:
if world.ircs: if world.ircs:
@ -2364,6 +2317,67 @@ class ChanTracker(callbacks.Plugin,plugins.ChannelDBHandler):
i.lowQueue.enqueue(ircmsgs.privmsg(logChannel,message)) i.lowQueue.enqueue(ircmsgs.privmsg(logChannel,message))
self.forceTickle = True self.forceTickle = True
def resolve (self,irc,channels,prefix):
i = self.getIrc(irc)
(nick,ident,host) = ircutils.splitHostmask(prefix)
n = self.getNick(irc,nick)
if n:
(nick,ident,host) = ircutils.splitHostmask(n.prefix)
if not n.prefix in cache and host.find('/') == -1:
try:
r = socket.getaddrinfo(host,None)
if r != None:
u = {}
L = []
for item in r:
if not item[4][0] in u:
u[item[4][0]] = item[4][0]
L.append(item[4][0])
if len(L) == 1:
n.setIp(L[0])
except:
t = ''
if n.ip != None:
cache[n.prefix] = n.ip
else:
cache[n.prefix] = host
for channel in channels:
if ircutils.isChannel(channel) and channel in irc.state.channels:
best = getBestPattern(n,irc,self.registryValue('useIpForGateway',channel=channel),self.registryValue('resolveIp'))[0]
chan = self.getChan(irc,channel)
banned = False
if self.registryValue('checkEvade',channel=channel) and prefix.find('/ip.') != -1:
items = chan.getItemsFor('b')
for k in items:
item = items[k]
if ircutils.isUserHostmask(item.value):
n = Nick(0)
n.setPrefix(item.value)
if match('*!*@%s' % prefix.split('ip.')[1],n,irc,self.registryValue('resolveIp')):
self._act (irc,channel,'b',best,self.registryValue('autoExpire',channel=channel),'evade of [#%s +%s %s]' % (item.uid,item.mode,item.value))
f = None
banned = True
self.forceTickle = True
if self.registryValue('announceBotMark',channel=channel):
f = self._logChan
i.mark(irc,item.uid,'evade with %s --> %s' % (prefix,best),irc.prefix,self.getDb(irc.network),f,self)
break
if not banned:
items = chan.getItemsFor('q')
for k in items:
item = items[k]
if ircutils.isUserHostmask(item.value):
n = Nick(0)
n.setPrefix(item.value)
pat = '*!*@%s' % prefix.split('ip.')[1]
if pat != item.value and match(pat,n,irc,self.registryValue('resolveIp')):
f = None
if self.registryValue('announceBotMark',channel=channel):
f = self._logChan
i.mark(irc,item.uid,'evade with %s --> %s' % (prefix,best),irc.prefix,self.getDb(irc.network),f,self)
break
self._tickle(irc)
def doJoin (self,irc,msg): def doJoin (self,irc,msg):
channels = msg.args[0].split(',') channels = msg.args[0].split(',')
n = self.getNick(irc,msg.nick) n = self.getNick(irc,msg.nick)
@ -2377,52 +2391,19 @@ class ChanTracker(callbacks.Plugin,plugins.ChannelDBHandler):
self._tickle(irc) self._tickle(irc)
return return
if self.registryValue('resolveIp') and msg.prefix.split('@')[1].find('/') == -1: if self.registryValue('resolveIp') and msg.prefix.split('@')[1].find('/') == -1:
mp = ircmsgs.IrcMsg('',command='PRIVMSG') t = world.SupyThread(target=self.resolve,name=format('Resolving %s for %s', msg.prefix, channels),args=(irc,channels,msg.prefix))
mp.prefix = irc.prefix t.setDaemon(True)
mp.args = [irc.nick] t.start()
command = 'resolve %s' % msg.nick
tokens = callbacks.tokenize(command)
self.Proxy(irc.irc, mp, tokens)
for channel in channels: for channel in channels:
if ircutils.isChannel(channel) and channel in irc.state.channels: if ircutils.isChannel(channel) and channel in irc.state.channels:
best = getBestPattern(n,irc,self.registryValue('useIpForGateway',channel=channel),self.registryValue('resolveIp'))[0] best = getBestPattern(n,irc,self.registryValue('useIpForGateway',channel=channel),self.registryValue('resolveIp'))[0]
chan = self.getChan(irc,channel) chan = self.getChan(irc,channel)
chan.nicks[msg.nick] = True chan.nicks[msg.nick] = True
n.addLog(channel,'has joined') n.addLog(channel,'has joined')
c = ircdb.channels.getChannel(channel)
banned = False banned = False
c = ircdb.channels.getChannel(channel)
if not self._isVip(irc,channel,n) and not chan.netsplit: if not self._isVip(irc,channel,n) and not chan.netsplit:
if self.registryValue('checkEvade',channel=channel) and msg.prefix.find('/ip.') != -1 and self.registryValue('resolveIp'): if c.bans and len(c.bans) and self.registryValue('useChannelBansForPermanentBan',channel=channel):
items = chan.getItemsFor('b')
for k in items:
item = items[k]
if ircutils.isUserHostmask(item.value):
n = Nick(0)
n.setPrefix(item.value)
if match('*!*@%s' % msg.prefix.split('ip.')[1],n,irc,self.registryValue('resolveIp')):
self._act (irc,channel,'b',best,self.registryValue('autoExpire',channel=channel),'evade of [#%s +%s %s]' % (item.uid,item.mode,item.value))
f = None
banned = True
self.forceTickle = True
if self.registryValue('announceBotMark',channel=channel):
f = self._logChan
i.mark(irc,item.uid,'evade with %s --> %s' % (msg.prefix,best),irc.prefix,self.getDb(irc.network),f,self)
break
if not banned:
items = chan.getItemsFor('q')
for k in items:
item = items[k]
if ircutils.isUserHostmask(item.value):
n = Nick(0)
n.setPrefix(item.value)
pat = '*!*@%s' % msg.prefix.split('ip.')[1]
if pat != item.value and match(pat,n,irc,self.registryValue('resolveIp')):
f = None
if self.registryValue('announceBotMark',channel=channel):
f = self._logChan
i.mark(irc,item.uid,'evade with %s --> %s' % (msg.prefix,best),irc.prefix,self.getDb(irc.network),f,self)
break
if not banned and c.bans and len(c.bans) and self.registryValue('useChannelBansForPermanentBan',channel=channel):
for ban in list(c.bans): for ban in list(c.bans):
if match (ban,n,irc,self.registryValue('resolveIp')): if match (ban,n,irc,self.registryValue('resolveIp')):
if i.add(irc,channel,'b',best,self.registryValue('autoExpire',channel=channel),irc.prefix,self.getDb(irc.network)): if i.add(irc,channel,'b',best,self.registryValue('autoExpire',channel=channel),irc.prefix,self.getDb(irc.network)):
@ -2466,9 +2447,6 @@ class ChanTracker(callbacks.Plugin,plugins.ChannelDBHandler):
r = self.getIrcdMode(irc,self.registryValue('cloneMode',channel=channel),best) r = self.getIrcdMode(irc,self.registryValue('cloneMode',channel=channel),best)
self._act(irc,channel,r[0],r[1],self.registryValue('cloneDuration',channel=channel),self.registryValue('cloneComment',channel)) self._act(irc,channel,r[0],r[1],self.registryValue('cloneDuration',channel=channel),self.registryValue('cloneComment',channel))
self.forceTickle = True self.forceTickle = True
if msg.nick == irc.nick:
self.forceTickle = True
self._tickle(irc) self._tickle(irc)
def doPart (self,irc,msg): def doPart (self,irc,msg):
@ -3519,7 +3497,7 @@ class ChanTracker(callbacks.Plugin,plugins.ChannelDBHandler):
idents[ident] = [] idents[ident] = []
idents[ident].append(n) idents[ident].append(n)
if n.realname and not n.realname in users: if n.realname and not n.realname in users:
users[n.realname] users[n.realname] = []
if n.realname: if n.realname:
users[n.realname].append(n) users[n.realname].append(n)
fident = None fident = None
@ -3626,7 +3604,6 @@ class ChanTracker(callbacks.Plugin,plugins.ChannelDBHandler):
pattern = None pattern = None
for msg in logs: for msg in logs:
if self._strcompare(message,msg) >= trigger: if self._strcompare(message,msg) >= trigger:
# self.log.debug('mass repeat "%s" matchs "%s"' % (message,msg))
if self.registryValue('massRepeatPatternLength',channel=channel) > 0: if self.registryValue('massRepeatPatternLength',channel=channel) > 0:
pattern = self._largestpattern(message,msg) pattern = self._largestpattern(message,msg)
if pattern and len(pattern) > self.registryValue('massRepeatPatternLength',channel=channel): if pattern and len(pattern) > self.registryValue('massRepeatPatternLength',channel=channel):
@ -3637,11 +3614,9 @@ class ChanTracker(callbacks.Plugin,plugins.ChannelDBHandler):
break break
if flag: if flag:
result = self._isSomething(irc,channel,channel,'massRepeat') result = self._isSomething(irc,channel,channel,'massRepeat')
# self.log.debug('mass repeat flagged and %s : "%s" / %s' % (result,message,pattern))
if result and pattern: if result and pattern:
if not patchan in chan.repeatLogs or chan.repeatLogs[patchan].timeout != self.registryValue('massRepeatPatternLife',channel=channel): if not patchan in chan.repeatLogs or chan.repeatLogs[patchan].timeout != self.registryValue('massRepeatPatternLife',channel=channel):
chan.repeatLogs[patchan] = utils.structures.TimeoutQueue(self.registryValue('massRepeatPatternLife',channel=channel)) chan.repeatLogs[patchan] = utils.structures.TimeoutQueue(self.registryValue('massRepeatPatternLife',channel=channel))
# self.log.debug('mass repeat pattern added "%s"' % pattern)
chan.repeatLogs[patchan].enqueue(pattern) chan.repeatLogs[patchan].enqueue(pattern)
chan.repeatLogs[channel].enqueue(message) chan.repeatLogs[channel].enqueue(message)
return result return result