From 80fa0b96723619627f0c16ac2c8bab711a6230c3 Mon Sep 17 00:00:00 2001 From: Nicolas Coevoet Date: Fri, 25 Jun 2021 09:55:27 +0200 Subject: [PATCH] Sorry ... autopep8 --in-place --- config.py | 273 ++--- plugin.py | 2979 ++++++++++++++++++++++++++++++----------------------- 2 files changed, 1850 insertions(+), 1402 deletions(-) diff --git a/config.py b/config.py index b086767..61b7514 100644 --- a/config.py +++ b/config.py @@ -31,6 +31,7 @@ import supybot.conf as conf import supybot.registry as registry + def configure(advanced): # This will be called by supybot to configure this module. advanced is # a bool that specifies whether the user identified himself as an advanced @@ -43,346 +44,346 @@ def configure(advanced): ChanTracker = conf.registerPlugin('ChanTracker') conf.registerGlobalValue(ChanTracker, 'pool', - registry.Integer(-1, """delay between two checks about mode removal, in seconds. Note, check is also based on irc activity, so removal may be delayed a bit, -1 to disable delay""")) + registry.Integer(-1, """delay between two checks about mode removal, in seconds. Note, check is also based on irc activity, so removal may be delayed a bit, -1 to disable delay""")) conf.registerGlobalValue(ChanTracker, 'logsSize', - registry.PositiveInteger(60, """number of messages to keep in logs. Note, this is per nick - not per nick per channel""")) + registry.PositiveInteger(60, """number of messages to keep in logs. Note, this is per nick - not per nick per channel""")) conf.registerGlobalValue(ChanTracker, 'quietCommand', - registry.String("PRIVMSG ChanServ :QUIET $channel $hostmask","""command issued to quiet a user; $channel and $hostmask will be replaced at runtime""")) + registry.String("PRIVMSG ChanServ :QUIET $channel $hostmask", """command issued to quiet a user; $channel and $hostmask will be replaced at runtime""")) conf.registerGlobalValue(ChanTracker, 'unquietCommand', - registry.String("PRIVMSG ChanServ :UNQUIET $channel $hostmask","""command issued to unquiet a user $channel and $hostmask will be replaced at runtime""")) + registry.String("PRIVMSG ChanServ :UNQUIET $channel $hostmask", """command issued to unquiet a user $channel and $hostmask will be replaced at runtime""")) conf.registerGlobalValue(ChanTracker, 'announceNagInterval', - registry.Integer(-1,"""interval between two check about announceNagMode, this setting is global.""")) + registry.Integer(-1, """interval between two check about announceNagMode, this setting is global.""")) -conf.registerGlobalValue(ChanTracker, 'resolveIp', - registry.Boolean(True, """trying to resolve host's ip with socket, could add latency""")) +conf.registerGlobalValue(ChanTracker, 'resolveIp', + registry.Boolean(True, """trying to resolve host's ip with socket, could add latency""")) # per channel settings conf.registerChannelValue(ChanTracker, 'useAccountBanIfPossible', - registry.Boolean(False, """bot will choose account bans when user is identified, only works for b,q,e,I,note commands not automated bans""")) + registry.Boolean(False, """bot will choose account bans when user is identified, only works for b,q,e,I,note commands not automated bans""")) -conf.registerChannelValue(ChanTracker, 'avoidOverlap', - registry.Boolean(False, """avoid overlap between items, bot will try to use existing items against users, some limitations with extended bans""")) +conf.registerChannelValue(ChanTracker, 'avoidOverlap', + registry.Boolean(False, """avoid overlap between items, bot will try to use existing items against users, some limitations with extended bans""")) -conf.registerChannelValue(ChanTracker, 'useIpForGateway', - registry.Boolean(False, """use *!*@*ip bans instead of *!ident@gateway/* when gateways cloak is found and ends with ip.*""")) +conf.registerChannelValue(ChanTracker, 'useIpForGateway', + registry.Boolean(False, """use *!*@*ip bans instead of *!ident@gateway/* when gateways cloak is found and ends with ip.*""")) -conf.registerChannelValue(ChanTracker, 'triggerOps', - registry.Boolean(False, """!ops triggers a message in logChannel""")) +conf.registerChannelValue(ChanTracker, 'triggerOps', + registry.Boolean(False, """!ops triggers a message in logChannel""")) conf.registerChannelValue(ChanTracker, 'allowOpToConfig', - registry.Boolean(False, """grant channel operators the ability to configure some chantracker protections for their channel""")) + registry.Boolean(False, """grant channel operators the ability to configure some chantracker protections for their channel""")) conf.registerChannelValue(ChanTracker, 'opCommand', - registry.String("PRIVMSG ChanServ :OP $channel $nick", """command used to obtain channel operator mode"""), opSettable=False) + registry.String("PRIVMSG ChanServ :OP $channel $nick", """command used to obtain channel operator mode"""), opSettable=False) conf.registerChannelValue(ChanTracker, 'modesToAsk', - registry.CommaSeparatedListOfStrings(['b','q'], """list of channel modes to sync into the bot's tracking database when it joins the channel""")) + registry.CommaSeparatedListOfStrings(['b', 'q'], """list of channel modes to sync into the bot's tracking database when it joins the channel""")) conf.registerChannelValue(ChanTracker, 'modesToAskWhenOpped', - registry.CommaSeparatedListOfStrings(['e','I'], """list of channel modes to sync into the bot's tracking database when it is opped""")) + registry.CommaSeparatedListOfStrings(['e', 'I'], """list of channel modes to sync into the bot's tracking database when it is opped""")) # related to ban tracking conf.registerChannelValue(ChanTracker, 'autoExpire', - registry.Integer(-1, """default expiration time for newly placed bans; -1 disables auto-expiration, otherwise it's in seconds""")) + registry.Integer(-1, """default expiration time for newly placed bans; -1 disables auto-expiration, otherwise it's in seconds""")) -conf.registerChannelValue(ChanTracker, 'removeAllBans', - registry.Boolean(False, """prevent accidental removal of all bans""")) -conf.registerChannelValue(ChanTracker, 'removeAllQuiets', - registry.Boolean(False, """prevent accidental removal of all quiets""")) -conf.registerChannelValue(ChanTracker, 'removeAllExempts', - registry.Boolean(False, """prevent accidental removal of all exempts""")) +conf.registerChannelValue(ChanTracker, 'removeAllBans', + registry.Boolean(False, """prevent accidental removal of all bans""")) +conf.registerChannelValue(ChanTracker, 'removeAllQuiets', + registry.Boolean(False, """prevent accidental removal of all quiets""")) +conf.registerChannelValue(ChanTracker, 'removeAllExempts', + registry.Boolean(False, """prevent accidental removal of all exempts""")) conf.registerChannelValue(ChanTracker, 'removeAllInvites', - registry.Boolean(False, """prevent accidental removal of all invites""")) + registry.Boolean(False, """prevent accidental removal of all invites""")) # announces related to logChannel conf.registerChannelValue(ChanTracker, 'logChannel', - registry.String("", """where bot announces op's actions; it is highly recommended to set an appropriate operator's channel to receive the various useful messages, nick can be used"""),opSettable=False) + registry.String("", """where bot announces op's actions; it is highly recommended to set an appropriate operator's channel to receive the various useful messages, nick can be used"""), opSettable=False) conf.registerChannelValue(ChanTracker, 'useColorForAnnounces', - registry.Boolean(False, """use colors for announce messages""")) + registry.Boolean(False, """use colors for announce messages""")) conf.registerChannelValue(ChanTracker, 'announceOthers', - registry.Boolean(True,"""forward messages from quieted/banned users to logChannel; used when bot stays opped and channel is +z (reduced moderation). + registry.Boolean(True, """forward messages from quieted/banned users to logChannel; used when bot stays opped and channel is +z (reduced moderation). Messages from users flagged as bad, or when channel is under attack will not be forwarded""")) conf.registerChannelValue(ChanTracker, 'announceModeMadeByIgnored', - registry.Boolean(True,"""announce channel modes made by ignored user""")) + registry.Boolean(True, """announce channel modes made by ignored user""")) conf.registerChannelValue(ChanTracker, 'announceWithNotice', - registry.Boolean(False,"""use NOTICE instead of PRIVMSG to logChannel""")) + registry.Boolean(False, """use NOTICE instead of PRIVMSG to logChannel""")) conf.registerChannelValue(ChanTracker, 'announceModes', - registry.CommaSeparatedListOfStrings(['b','q','e','I','r','l','v','o','h','k','n','t','F','i','t','s','n','c','C'],"""announce modes listed to logChannel""")) + registry.CommaSeparatedListOfStrings(['b', 'q', 'e', 'I', 'r', 'l', 'v', 'o', 'h', 'k', 'n', 't', 'F', 'i', 't', 's', 'n', 'c', 'C'], """announce modes listed to logChannel""")) conf.registerChannelValue(ChanTracker, 'announceModeSync', - registry.Boolean(False,"""announce to logChannel that synchronisation of channel modes to tracking database has completed""")) + registry.Boolean(False, """announce to logChannel that synchronisation of channel modes to tracking database has completed""")) conf.registerChannelValue(ChanTracker, 'announceKick', - registry.Boolean(True,"""announce kick, remove, kill and kline to logChannel""")) + registry.Boolean(True, """announce kick, remove, kill and kline to logChannel""")) conf.registerChannelValue(ChanTracker, 'announceTopic', - registry.Boolean(True,"""announce topic changes to logChannel""")) + registry.Boolean(True, """announce topic changes to logChannel""")) conf.registerChannelValue(ChanTracker, 'announceEdit', - registry.Boolean(True,"""announce tracker item description edits to logChannel""")) + registry.Boolean(True, """announce tracker item description edits to logChannel""")) conf.registerChannelValue(ChanTracker, 'announceMark', - registry.Boolean(True,"""announce item expiration settings (marks) to logChannel""")) + registry.Boolean(True, """announce item expiration settings (marks) to logChannel""")) conf.registerChannelValue(ChanTracker, 'announceInTimeEditAndMark', - registry.Boolean(False,"""announce new comments (edits) and expiries (marks) to logChannel when they are created by the do, q, b, e, i commands""")) + registry.Boolean(False, """announce new comments (edits) and expiries (marks) to logChannel when they are created by the do, q, b, e, i commands""")) conf.registerChannelValue(ChanTracker, 'announceMassRemoval', - registry.Boolean(False,"""announce mass ban removals 'undo *', 'uq *', 'ub *' to logChannel""")) + registry.Boolean(False, """announce mass ban removals 'undo *', 'uq *', 'ub *' to logChannel""")) conf.registerChannelValue(ChanTracker, 'announceBotEdit', - registry.Boolean(False,"""when banning based on a channel protection trigger (such as flood prevention), announce the items comment (edit) to logChannel""")) + registry.Boolean(False, """when banning based on a channel protection trigger (such as flood prevention), announce the items comment (edit) to logChannel""")) conf.registerChannelValue(ChanTracker, 'announceBotMark', - registry.Boolean(False,"""when banning based on a channel protection trigger (such as flood prevention), announce the items expiry (mark) to logChannel""")) + registry.Boolean(False, """when banning based on a channel protection trigger (such as flood prevention), announce the items expiry (mark) to logChannel""")) conf.registerChannelValue(ChanTracker, 'announceNotice', - registry.Boolean(True,"""announce channel notices to logChannel""")) + registry.Boolean(True, """announce channel notices to logChannel""")) conf.registerChannelValue(ChanTracker, 'announceCtcp', - registry.Boolean(True,"""announce channel ctcps to logChannel""")) + registry.Boolean(True, """announce channel ctcps to logChannel""")) conf.registerChannelValue(ChanTracker, 'announceNagMode', - registry.CommaSeparatedListOfStrings([], """bot will announce that channel has such mode at announceNagInterval""")) + registry.CommaSeparatedListOfStrings([], """bot will announce that channel has such mode at announceNagInterval""")) # others settings conf.registerChannelValue(ChanTracker, 'doNothingAboutOwnOpStatus', - registry.Boolean(True, """bot will never try to change his own op status""")) + registry.Boolean(True, """bot will never try to change his own op status""")) conf.registerChannelValue(ChanTracker, 'keepOp', - registry.Boolean(False, """bot stays opped""")) + registry.Boolean(False, """bot stays opped""")) 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 with caution, if an op bans *!*@*, bot will kick everyone on the channel""")) 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 with caution""")) 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 *!*@*""")) + conf.registerChannelValue(ChanTracker, 'kickMessage', - registry.CommaSeparatedListOfStrings(["You are banned from this channel"], """bot kick reasons""")) + registry.CommaSeparatedListOfStrings(["You are banned from this channel"], """bot kick reasons""")) conf.registerChannelValue(ChanTracker, 'quietMessage', - registry.String("", """leave empty if you don't want the bot to tell something to the user when he has been quieted ( by/via the bot ), in any case, if channel is under attack: bot will not send message""")) + registry.String("", """leave empty if you don't want the bot to tell something to the user when he has been quieted ( by/via the bot ), in any case, if channel is under attack: bot will not send message""")) conf.registerChannelValue(ChanTracker, 'quietNotice', - registry.Boolean(False, """if False, private message is used, if 'quietMessage' is not empty""")) + registry.Boolean(False, """if False, private message is used, if 'quietMessage' is not empty""")) conf.registerChannelValue(ChanTracker, 'trackAffected', - registry.Boolean(True, """bot tracks affected users by mode change, if you encounter too much lags/cpu usage, you could disable this feature, but bot will never kick again affected users or remove voice/op/exempt etc of affected users""")) + registry.Boolean(True, """bot tracks affected users by mode change, if you encounter too much lags/cpu usage, you could disable this feature, but bot will never kick again affected users or remove voice/op/exempt etc of affected users""")) conf.registerChannelValue(ChanTracker, 'doActionAgainstAffected', - registry.Boolean(True, """devoice, deop, dehalfop user affected by a mode change""")) - + registry.Boolean(True, """devoice, deop, dehalfop user affected by a mode change""")) + conf.registerChannelValue(ChanTracker, 'useChannelBansForPermanentBan', - registry.Boolean(True, """when users join the channel, check if user matchs a permanent ban set in Channel plugin""")) + registry.Boolean(True, """when users join the channel, check if user matchs a permanent ban set in Channel plugin""")) conf.registerChannelValue(ChanTracker, 'addKickMessageInComment', - registry.Boolean(False, """add kick message to mode comment in tracking database""")) - + registry.Boolean(False, """add kick message to mode comment in tracking database""")) + conf.registerChannelValue(ChanTracker, 'askOpAboutMode', - registry.Boolean(False,"""In a private message, ask the op who added a mode about the duration of the ban and a comment on why it was set""")) + registry.Boolean(False, """In a private message, ask the op who added a mode about the duration of the ban and a comment on why it was set""")) conf.registerChannelValue(ChanTracker, 'checkEvade', - registry.Boolean(True,"""bot will apply same duration and mode as the evaded ban, currently only works when someone identifies to an account, and the account is banned $a:account, and has ip computed""")) + registry.Boolean(True, """bot will apply same duration and mode as the evaded ban, currently only works when someone identifies to an account, and the account is banned $a:account, and has ip computed""")) conf.registerChannelValue(ChanTracker, 'useChanServForQuiets', - registry.Boolean(False,"""if bot is not opped, use services for quiet / unquiets""")) + registry.Boolean(False, """if bot is not opped, use services for quiet / unquiets""")) # related to channel's protection -#clone +# clone conf.registerChannelValue(ChanTracker, 'clonePermit', -registry.Integer(-1,"""Number of clones allowed , -1 to disable""")) + registry.Integer(-1, """Number of clones allowed , -1 to disable""")) 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', -registry.PositiveInteger(60,"""punishment duration in seconds""")) + registry.PositiveInteger(60, """punishment duration in seconds""")) conf.registerChannelValue(ChanTracker, 'cloneComment', -registry.String('clone detected',"""comment added on mode changes database, empty for no comment""")) + registry.String('clone detected', """comment added on mode changes database, empty for no comment""")) # flood detection settings conf.registerChannelValue(ChanTracker, 'floodPermit', -registry.Integer(-1,"""Number of messages allowed during floodLife, -1 to disable""")) + registry.Integer(-1, """Number of messages allowed during floodLife, -1 to disable""")) conf.registerChannelValue(ChanTracker, 'floodLife', -registry.PositiveInteger(7,"""Duration of messages's life in flood counter, in seconds""")) + registry.PositiveInteger(7, """Duration of messages's life in flood counter, in seconds""")) conf.registerChannelValue(ChanTracker, 'floodMode', -registry.String('q',"""mode used by the bot when flood detection is triggered""")) + registry.String('q', """mode used by the bot when flood detection is triggered""")) conf.registerChannelValue(ChanTracker, 'floodDuration', -registry.PositiveInteger(60,"""punishment duration in seconds""")) + registry.PositiveInteger(60, """punishment duration in seconds""")) conf.registerChannelValue(ChanTracker, 'floodComment', -registry.String('flood detected',"""comment added on mode changes database, empty for no comment""")) + registry.String('flood detected', """comment added on mode changes database, empty for no comment""")) # another flood queue, for user with throttled irc client, who copy / paste long text conf.registerChannelValue(ChanTracker, 'lowFloodPermit', -registry.Integer(-1,"""Number of messages allowed during lowFloodLife, -1 to disable""")) + registry.Integer(-1, """Number of messages allowed during lowFloodLife, -1 to disable""")) conf.registerChannelValue(ChanTracker, 'lowFloodLife', -registry.Integer(13,"""Duration of messages's life in lowFlood counter, in seconds""")) + registry.Integer(13, """Duration of messages's life in lowFlood counter, in seconds""")) conf.registerChannelValue(ChanTracker, 'lowFloodMode', -registry.String('q',"""mode used by the bot when low flood detection is triggered""")) + registry.String('q', """mode used by the bot when low flood detection is triggered""")) conf.registerChannelValue(ChanTracker, 'lowFloodDuration', -registry.PositiveInteger(180,"""punishment duration in seconds""")) + registry.PositiveInteger(180, """punishment duration in seconds""")) conf.registerChannelValue(ChanTracker, 'lowFloodComment', -registry.String('low flood detected',"""comment added on mode changes database, empty for no comment""")) + registry.String('low flood detected', """comment added on mode changes database, empty for no comment""")) # repeat abuse conf.registerChannelValue(ChanTracker, 'repeatPermit', -registry.Integer(-1,"""number of triggers allowed, -1 to disable""")) + registry.Integer(-1, """number of triggers allowed, -1 to disable""")) conf.registerChannelValue(ChanTracker, 'repeatLife', -registry.PositiveInteger(12,"""life duration of triggers in seconds""")) + registry.PositiveInteger(12, """life duration of triggers in seconds""")) conf.registerChannelValue(ChanTracker, 'repeatMode', -registry.String('q',"""action when repeatPermit is triggered""")) + registry.String('q', """action when repeatPermit is triggered""")) conf.registerChannelValue(ChanTracker, 'repeatDuration', -registry.PositiveInteger(180,"""punishment duration in seconds""")) + registry.PositiveInteger(180, """punishment duration in seconds""")) conf.registerChannelValue(ChanTracker, 'repeatComment', -registry.String('repeat detected',"""comment added on mode changes database, empty for no comment""")) + registry.String('repeat detected', """comment added on mode changes database, empty for no comment""")) # repeat detection conf.registerChannelValue(ChanTracker, 'repeatMinimum', -registry.PositiveInteger(8,"""minimal candidates patterns length to detect repetitions""")) + registry.PositiveInteger(8, """minimal candidates patterns length to detect repetitions""")) conf.registerChannelValue(ChanTracker, 'repeatPercent', -registry.Probability(0.85,"""percent of similarity between messages or pattern candidates""")) + registry.Probability(0.85, """percent of similarity between messages or pattern candidates""")) conf.registerChannelValue(ChanTracker, 'repeatCount', -registry.PositiveInteger(5,"""numbers of occurences of candidates patterns""")) + registry.PositiveInteger(5, """numbers of occurences of candidates patterns""")) conf.registerChannelValue(ChanTracker, 'repeatPatternMinimum', -registry.Integer(-1,"""minimal length to create automated pattern, if found, triggers same punishment than repeatMode/repeatDuration, -1 to disable""")) + registry.Integer(-1, """minimal length to create automated pattern, if found, triggers same punishment than repeatMode/repeatDuration, -1 to disable""")) conf.registerChannelValue(ChanTracker, 'repeatPatternLife', -registry.PositiveInteger(300,"""duration of pattern life""")) + registry.PositiveInteger(300, """duration of pattern life""")) # YES IT'S ANNOYING conf.registerChannelValue(ChanTracker, 'capPermit', -registry.Integer(-1,"""Number of UPPERCASE messages allowed, -1 to disable. see capPercent for definition of an UPPERCASE message""")) + registry.Integer(-1, """Number of UPPERCASE messages allowed, -1 to disable. see capPercent for definition of an UPPERCASE message""")) conf.registerChannelValue(ChanTracker, 'capLife', -registry.PositiveInteger(30,"""Duration in seconds before messages are removed from count""")) + registry.PositiveInteger(30, """Duration in seconds before messages are removed from count""")) conf.registerChannelValue(ChanTracker, 'capPercent', -registry.Probability(0.75,"""percentage of uppercase chars in a message to trigger a cap count""")) + registry.Probability(0.75, """percentage of uppercase chars in a message to trigger a cap count""")) conf.registerChannelValue(ChanTracker, 'capMode', -registry.String('q',"""mode used by the bot when cap is triggered""")) + registry.String('q', """mode used by the bot when cap is triggered""")) conf.registerChannelValue(ChanTracker, 'capDuration', -registry.PositiveInteger(180,"""punition in seconds""")) + registry.PositiveInteger(180, """punition in seconds""")) conf.registerChannelValue(ChanTracker, 'capComment', -registry.String('capslock detected',"""comment added on mode changes database, empty for no comment""")) + registry.String('capslock detected', """comment added on mode changes database, empty for no comment""")) # hilight conf.registerChannelValue(ChanTracker, 'hilightPermit', -registry.Integer(-1,"""Number of nick allowed per message, -1 to disable, note : it doesn't care if it's the same nick""")) + registry.Integer(-1, """Number of nick allowed per message, -1 to disable, note : it doesn't care if it's the same nick""")) conf.registerChannelValue(ChanTracker, 'hilightMode', -registry.String('q',"""mode used by the bot when hilight is triggered""")) + registry.String('q', """mode used by the bot when hilight is triggered""")) conf.registerChannelValue(ChanTracker, 'hilightDuration', -registry.PositiveInteger(180,"""punishment duration in seconds""")) + registry.PositiveInteger(180, """punishment duration in seconds""")) conf.registerChannelValue(ChanTracker, 'hilightComment', -registry.String('hilight detected',"""comment added on mode changes database, empty for no comment""")) + registry.String('hilight detected', """comment added on mode changes database, empty for no comment""")) # channel's notices conf.registerChannelValue(ChanTracker, 'noticePermit', -registry.Integer(-1,"""Number of messages allowed, -1 to disable, advice 0""")) + registry.Integer(-1, """Number of messages allowed, -1 to disable, advice 0""")) conf.registerChannelValue(ChanTracker, 'noticeLife', -registry.PositiveInteger(3,"""Duration in seconds before messages are removed from count""")) + registry.PositiveInteger(3, """Duration in seconds before messages are removed from count""")) conf.registerChannelValue(ChanTracker, 'noticeMode', -registry.String('q',"""mode used by the bot when notice is triggered""")) + registry.String('q', """mode used by the bot when notice is triggered""")) conf.registerChannelValue(ChanTracker, 'noticeDuration', -registry.PositiveInteger(300,"""punishment duration in seconds""")) + registry.PositiveInteger(300, """punishment duration in seconds""")) conf.registerChannelValue(ChanTracker, 'noticeComment', -registry.String('notice detected',"""comment added on mode changes database, empty for no comment""")) + registry.String('notice detected', """comment added on mode changes database, empty for no comment""")) # channel ctcps conf.registerChannelValue(ChanTracker, 'ctcpPermit', -registry.Integer(-1,"""Number of messages allowed, -1 to disable""")) + registry.Integer(-1, """Number of messages allowed, -1 to disable""")) conf.registerChannelValue(ChanTracker, 'ctcpLife', -registry.PositiveInteger(3,"""Duration in seconds before messages are removed from count""")) + registry.PositiveInteger(3, """Duration in seconds before messages are removed from count""")) conf.registerChannelValue(ChanTracker, 'ctcpMode', -registry.String('b',"""mode used by the bot when ctcp detection is triggered""")) + registry.String('b', """mode used by the bot when ctcp detection is triggered""")) conf.registerChannelValue(ChanTracker, 'ctcpDuration', -registry.PositiveInteger(1800,"""punishment duration in seconds""")) + registry.PositiveInteger(1800, """punishment duration in seconds""")) conf.registerChannelValue(ChanTracker, 'ctcpComment', -registry.String('ctcp detected',"""comment added on mode changes database, empty for no comment""")) + registry.String('ctcp detected', """comment added on mode changes database, empty for no comment""")) # channel join/part flood conf.registerChannelValue(ChanTracker, 'cyclePermit', -registry.Integer(-1,"""Number of cycles allowed, -1 to disable, count part and quit""")) + registry.Integer(-1, """Number of cycles allowed, -1 to disable, count part and quit""")) conf.registerChannelValue(ChanTracker, 'cycleLife', -registry.PositiveInteger(180,"""Duration in seconds before cycles are removed from count""")) + registry.PositiveInteger(180, """Duration in seconds before cycles are removed from count""")) conf.registerChannelValue(ChanTracker, 'cycleMode', -registry.String('b',"""mode used by the bot when cycle detection is triggered""")) + registry.String('b', """mode used by the bot when cycle detection is triggered""")) conf.registerChannelValue(ChanTracker, 'cycleDuration', -registry.PositiveInteger(1800,"""punishment duration in seconds""")) + registry.PositiveInteger(1800, """punishment duration in seconds""")) conf.registerChannelValue(ChanTracker, 'cycleComment', -registry.String('cycle detected',"""comment added on mode changes database, empty for no comment""")) + registry.String('cycle detected', """comment added on mode changes database, empty for no comment""")) conf.registerChannelValue(ChanTracker, 'cycleForward', -registry.String('',"""if your ircd supports that, you can forward the user to a specific channel""")) + registry.String('', """if your ircd supports that, you can forward the user to a specific channel""")) # channel massJoin from an host conf.registerChannelValue(ChanTracker, 'massJoinPermit', -registry.Integer(-1,"""Number of joins allowed, -1 to disable, note, it could mixup a bit with cycle detection""")) + registry.Integer(-1, """Number of joins allowed, -1 to disable, note, it could mixup a bit with cycle detection""")) conf.registerChannelValue(ChanTracker, 'massJoinLife', -registry.PositiveInteger(60,"""Duration in seconds before messages are removed from count""")) + registry.PositiveInteger(60, """Duration in seconds before messages are removed from count""")) conf.registerChannelValue(ChanTracker, 'massJoinMode', -registry.String('+rq-z $~a',"""mode used by the bot when massjoin is triggered""")) + registry.String('+rq-z $~a', """mode used by the bot when massjoin is triggered""")) conf.registerChannelValue(ChanTracker, 'massJoinDuration', -registry.PositiveInteger(300,"""punishment duration in seconds""")) + registry.PositiveInteger(300, """punishment duration in seconds""")) conf.registerChannelValue(ChanTracker, 'massJoinUnMode', -registry.String('-rq+z $~a',"""mode used by the bot when massJoinDuration is finished""")) + registry.String('-rq+z $~a', """mode used by the bot when massJoinDuration is finished""")) # nick changes flood conf.registerChannelValue(ChanTracker, 'nickPermit', -registry.Integer(-1,"""Number of nick changes allowed, -1 to disable""")) + registry.Integer(-1, """Number of nick changes allowed, -1 to disable""")) conf.registerChannelValue(ChanTracker, 'nickLife', -registry.Integer(300,"""Duration in seconds before nick changes are removed from count""")) + registry.Integer(300, """Duration in seconds before nick changes are removed from count""")) conf.registerChannelValue(ChanTracker, 'nickMode', -registry.String('q',"""mode used by the bot when nick is triggered""")) + registry.String('q', """mode used by the bot when nick is triggered""")) conf.registerChannelValue(ChanTracker, 'nickDuration', -registry.PositiveInteger(300,"""punishment duration in seconds""")) + registry.PositiveInteger(300, """punishment duration in seconds""")) conf.registerChannelValue(ChanTracker, 'nickComment', -registry.String('nick changes flood detected',"""comment added on mode changes database, empty for no comment""")) + registry.String('nick changes flood detected', """comment added on mode changes database, empty for no comment""")) # if you enable this, each time someone trigger other protection that will increase this queue conf.registerChannelValue(ChanTracker, 'badPermit', -registry.Integer(-1,"""Number of bad action allowed, -1 to disable, each time bot had to acts on a user, it increase this item""")) + registry.Integer(-1, """Number of bad action allowed, -1 to disable, each time bot had to acts on a user, it increase this item""")) conf.registerChannelValue(ChanTracker, 'badLife', -registry.Integer(600,"""Duration in seconds before actions are removed from count""")) + registry.Integer(600, """Duration in seconds before actions are removed from count""")) conf.registerChannelValue(ChanTracker, 'badMode', -registry.String('b',"""mode used by the bot when bad is triggered""")) + registry.String('b', """mode used by the bot when bad is triggered""")) conf.registerChannelValue(ChanTracker, 'badDuration', -registry.PositiveInteger(86400,"""punishment duration in seconds""")) + registry.PositiveInteger(86400, """punishment duration in seconds""")) conf.registerChannelValue(ChanTracker, 'badComment', -registry.String('bad detected',"""comment added on mode changes database, empty for no comment""")) + registry.String('bad detected', """comment added on mode changes database, empty for no comment""")) # if you enable this, each time someone trigger bad in a channel that will increase this queue conf.registerChannelValue(ChanTracker, 'attackPermit', -registry.Integer(-1,"""Number of bad action allowed, -1 to disable, each time bot flags user as bad, it increase this item""")) + registry.Integer(-1, """Number of bad action allowed, -1 to disable, each time bot flags user as bad, it increase this item""")) conf.registerChannelValue(ChanTracker, 'attackLife', -registry.Integer(600,"""Duration in seconds before actions are removed from count""")) + registry.Integer(600, """Duration in seconds before actions are removed from count""")) conf.registerChannelValue(ChanTracker, 'attackDuration', -registry.PositiveInteger(1800,"""punishment duration in seconds""")) + registry.PositiveInteger(1800, """punishment duration in seconds""")) conf.registerChannelValue(ChanTracker, 'attackMode', -registry.String('+rq-z $~a',"""mode used by the bot when attack is triggered""")) + registry.String('+rq-z $~a', """mode used by the bot when attack is triggered""")) conf.registerChannelValue(ChanTracker, 'attackUnMode', -registry.String('-rq+z $~a',"""mode used by the bot when attackDuration is finished""")) + registry.String('-rq+z $~a', """mode used by the bot when attackDuration is finished""")) # netsplit conf.registerChannelValue(ChanTracker, 'netsplitModes', -registry.String('',"""leave empty for no modes changes""")) + registry.String('', """leave empty for no modes changes""")) conf.registerChannelValue(ChanTracker, 'netsplitUnmodes', -registry.String('',"""leave empty for no modes changes""")) + registry.String('', """leave empty for no modes changes""")) conf.registerChannelValue(ChanTracker, 'netsplitDuration', -registry.PositiveInteger(600,"""duration of netsplit state when detected, it disables massJoin and cycle detection, and could set specific modes""")) + registry.PositiveInteger(600, """duration of netsplit state when detected, it disables massJoin and cycle detection, and could set specific modes""")) diff --git a/plugin.py b/plugin.py index e7a713d..9a35744 100644 --- a/plugin.py +++ b/plugin.py @@ -30,6 +30,8 @@ ### +import supybot.world as world +import threading import os import time import supybot.utils as utils @@ -54,7 +56,7 @@ from operator import itemgetter from ipaddress import ip_address as IPAddress from ipaddress import ip_network as IPNetwork -#due to more kind of pattern checked, increase size +# due to more kind of pattern checked, increase size ircutils._hostmaskPatternEqualCache = utils.structures.CacheDict(10000) @@ -62,7 +64,6 @@ ircutils._hostmaskPatternEqualCache = utils.structures.CacheDict(10000) cache = utils.structures.CacheDict(10000) - def applymodes(channel, args=(), prefix='', msg=None): """Returns a MODE that applies changes on channel.""" modes = args @@ -70,10 +71,12 @@ def applymodes(channel, args=(), prefix='', msg=None): prefix = msg.prefix return ircmsgs.IrcMsg(prefix=prefix, command='MODE', args=[channel] + ircutils.joinModes(modes), msg=msg) + mcidr = re.compile(r'^(\d{1,3}\.){0,3}\d{1,3}/\d{1,2}$') m6cidr = re.compile(r'^([0-9a-f]{0,4}:){2,7}[0-9a-f]{0,4}/\d{1,3}$') -def compareString (a,b): + +def compareString(a, b): """return 0 to 1 float percent of similarity ( 0.85 seems to be a good average )""" if a == b: return 1 @@ -84,13 +87,16 @@ def compareString (a,b): jacc = n / float(len(sa) + len(sb) - n) return jacc + repetr = re.compile(r"(.+?)\1+") + def repetitions(s): for match in repetr.finditer(s): yield (match.group(1), len(match.group(0))/len(match.group(1))) -def largestString (s1,s2): + +def largestString(s1, s2): """return largest pattern available in 2 strings""" # From https://en.wikibooks.org/wiki/Algorithm_Implementation/Strings/Longest_common_substring#Python2 # License: CC BY-SA @@ -106,7 +112,8 @@ def largestString (s1,s2): else: m[x][y] = 0 return s1[x_longest - longest: x_longest] - + + def findPattern(text, minimalCount, minimalLength, minimalPercent): items = list(repetitions(text)) size = len(text) @@ -120,11 +127,12 @@ def findPattern(text, minimalCount, minimalLength, minimalPercent): candidates.sort(key=len, reverse=True) return None if len(candidates) == 0 else candidates[0] -def matchHostmask (pattern,n,resolve): + +def matchHostmask(pattern, n, resolve): # return the matched pattern for Nick if n.prefix == None or not ircutils.isUserHostmask(n.prefix): return None - (nick,ident,host) = ircutils.splitHostmask(n.prefix) + (nick, ident, host) = ircutils.splitHostmask(n.prefix) if '/' in host: if host.startswith('gateway/web/freenode/ip.'): n.ip = cache[n.prefix] = host.split('ip.')[1] @@ -132,20 +140,21 @@ def matchHostmask (pattern,n,resolve): address = IPAddress('%s' % n.ip) network = IPNetwork('%s' % pattern.split('@')[1], strict=False) if address in network: - return '%s!%s@%s' % (nick,ident,n.ip) + return '%s!%s@%s' % (nick, ident, n.ip) elif n.ip != None and '@' in pattern and n.ip.find('*') == -1 and m6cidr.match(pattern.split('@')[1]): address = IPAddress('%s' % n.ip) network = IPNetwork('%s' % pattern.split('@')[1], strict=False) if address in network: - return '%s!%s@%s' % (nick,ident,n.ip) + return '%s!%s@%s' % (nick, ident, n.ip) if ircutils.isUserHostmask(pattern): - if n.ip != None and ircutils.hostmaskPatternEqual(pattern,'%s!%s@%s' % (nick,ident,n.ip)): - return '%s!%s@%s' % (nick,ident,n.ip) - if ircutils.hostmaskPatternEqual(pattern,n.prefix): + if n.ip != None and ircutils.hostmaskPatternEqual(pattern, '%s!%s@%s' % (nick, ident, n.ip)): + return '%s!%s@%s' % (nick, ident, n.ip) + if ircutils.hostmaskPatternEqual(pattern, n.prefix): return n.prefix return None -def matchAccount (pattern,pat,negate,n,extprefix): + +def matchAccount(pattern, pat, negate, n, extprefix): # for $a, $~a, $a: extended pattern result = None if negate: @@ -154,46 +163,49 @@ def matchAccount (pattern,pat,negate,n,extprefix): else: if len(pat): if n.account != None and ircutils.hostmaskPatternEqual('*!*@%s' % pat, '*!*@%s' % n.account): - result = '%sa:%s' % (extprefix,n.account) + result = '%sa:%s' % (extprefix, n.account) else: if n.account != None: - result = '%sa:%s' % (extprefix,n.account) + result = '%sa:%s' % (extprefix, n.account) return result -def matchRealname (pattern,pat,negate,n,extprefix): + +def matchRealname(pattern, pat, negate, n, extprefix): # for $~r $r: extended pattern if n.realname == None: return None if negate: if len(pat): if not ircutils.hostmaskPatternEqual('*!*@%s' % pat, '*!*@%s' % n.realname): - return '%sr:%s' % (extprefix,n.realname.replace(' ','?')) + return '%sr:%s' % (extprefix, n.realname.replace(' ', '?')) else: if len(pat): if ircutils.hostmaskPatternEqual('*!*@%s' % pat, '*!*@%s' % n.realname): - return '%sr:%s' % (extprefix,n.realname.replace(' ','?')) + return '%sr:%s' % (extprefix, n.realname.replace(' ', '?')) return None -def matchGecos (pattern,pat,negate,n,extprefix): + +def matchGecos(pattern, pat, negate, n, extprefix): # for $~x, $x: extended pattern if n.realname == None: return None tests = [] - (nick,ident,host) = ircutils.splitHostmask(n.prefix) + (nick, ident, host) = ircutils.splitHostmask(n.prefix) tests.append(n.prefix) if n.ip != None: - tests.append('%s!%s@%s' % (nick,ident,n.ip)) + tests.append('%s!%s@%s' % (nick, ident, n.ip)) for test in tests: - test = '%s#%s' % (test,n.realname.replace(' ','?')) + test = '%s#%s' % (test, n.realname.replace(' ', '?')) if negate: - if not ircutils.hostmaskPatternEqual(pat,test): + if not ircutils.hostmaskPatternEqual(pat, test): return test else: - if ircutils.hostmaskPatternEqual(pat,test): + if ircutils.hostmaskPatternEqual(pat, test): return test return None -def match (pattern,n,irc,resolve): + +def match(pattern, n, irc, resolve): if not pattern: return None if not n.prefix: @@ -224,44 +236,45 @@ def match (pattern,n,irc,resolve): p = p.split(extprefix)[0] #p = p[(p.rfind(extprefix)+1):] if t == 'a': - cache[key] = matchAccount (pattern,p,negate,n,extprefix) + cache[key] = matchAccount(pattern, p, negate, n, extprefix) elif t == 'r': - cache[key] = matchRealname (pattern,p,negate,n,extprefix) + cache[key] = matchRealname(pattern, p, negate, n, extprefix) elif t == 'x': - cache[key] = matchGecos (pattern,p,negate,n,extprefix) + cache[key] = matchGecos(pattern, p, negate, n, extprefix) elif t == 'z': return None else: # bug if ipv6 used .. k = pattern[(pattern.rfind(':')+1):] - cache[key] = matchHostmask(k,n,resolve) + cache[key] = matchHostmask(k, n, resolve) else: p = pattern if extprefix in p: p = p.split(extprefix)[0] - cache[key] = matchHostmask(p,n,resolve) + cache[key] = matchHostmask(p, n, resolve) return cache[key] -def getBestPattern (n,irc,useIp=False,resolve=True): + +def getBestPattern(n, irc, useIp=False, resolve=True): # return best pattern for a given Nick - match(n.prefix,n,irc,resolve) + match(n.prefix, n, irc, resolve) results = [] if not n.prefix or not ircutils.isUserHostmask(n.prefix): return [] - (nick,ident,host) = ircutils.splitHostmask(n.prefix) + (nick, ident, host) = ircutils.splitHostmask(n.prefix) if host.startswith('gateway/web/freenode/ip.') or host.startswith('gateway/tor-sasl/') or host.startswith('gateway/vpn/') or host.startswith('unaffiliated/') or ident.startswith('~') or n.realname == 'https://webchat.freenode.net': - ident = '*' + ident = '*' if n.ip != None: if len(n.ip.split(':')) > 4: # large ipv6, for now, use the full ipv6 #a = n.ip.split(':') #m = a[0]+':'+a[1]+':'+a[2]+':'+a[3]+':*' - results.append('*!%s@%s' % (ident,n.ip)) + results.append('*!%s@%s' % (ident, n.ip)) else: if useIp: - results.append('*!%s@*%s' % (ident,n.ip)) + results.append('*!%s@*%s' % (ident, n.ip)) else: - results.append('*!%s@%s' % (ident,n.ip)) + results.append('*!%s@%s' % (ident, n.ip)) if '/' in host: # cloaks if host.startswith('gateway/'): @@ -276,12 +289,12 @@ def getBestPattern (n,irc,useIp=False,resolve=True): if len(h) > 3: p = '/*' h = h[:3] - host = '%s%s' % ('/'.join(h),p) + host = '%s%s' % ('/'.join(h), p) elif host.startswith('nat/'): - h = host.replace('nat/','') + h = host.replace('nat/', '') if '/' in h: host = 'nat/%s/*' % h.split('/')[0] - k = '*!%s@%s' % (ident,host) + k = '*!%s@%s' % (ident, host) if not k in results: results.append(k) extprefix = '' @@ -291,12 +304,13 @@ def getBestPattern (n,irc,useIp=False,resolve=True): extprefix = ext.split(',')[0] extmodes = ext.split(',')[1] if n.account: - results.append('%sa:%s' % (extprefix,n.account)) + results.append('%sa:%s' % (extprefix, n.account)) if n.realname: - results.append('%sr:%s' % (extprefix,n.realname.replace(' ','?'))) + results.append('%sr:%s' % (extprefix, n.realname.replace(' ', '?'))) return results -def clearExtendedBanPattern (pattern,irc): + +def clearExtendedBanPattern(pattern, irc): # a little method to cleanup extended pattern extprefix = '' extmodes = '' @@ -313,18 +327,22 @@ def clearExtendedBanPattern (pattern,irc): pattern = pattern[1:] return pattern -def floatToGMT (t): + +def floatToGMT(t): f = None try: f = float(t) except: return None - return time.strftime('%Y-%m-%d %H:%M:%S GMT',time.gmtime(f)) + return time.strftime('%Y-%m-%d %H:%M:%S GMT', time.gmtime(f)) + class Ircd (object): - __slots__ = ('irc', 'name', 'channels', 'nicks', 'queue', 'lowQueue', 'logsSize', 'askedItems') + __slots__ = ('irc', 'name', 'channels', 'nicks', 'queue', + 'lowQueue', 'logsSize', 'askedItems') # define an ircd, keeps Chan and Nick items - def __init__(self,irc,logsSize): + + def __init__(self, irc, logsSize): object.__init__(self) self.irc = irc self.name = irc.network @@ -337,15 +355,15 @@ class Ircd (object): self.logsSize = logsSize self.askedItems = {} - def getChan (self,irc,channel): + def getChan(self, irc, channel): if not channel or not irc: return None self.irc = irc if not channel in self.channels: - self.channels[channel] = Chan (self,channel) + self.channels[channel] = Chan(self, channel) return self.channels[channel] - def getNick (self,irc,nick): + def getNick(self, irc, nick): if not nick or not irc: return None self.irc = irc @@ -353,12 +371,12 @@ class Ircd (object): self.nicks[nick] = Nick(self.logsSize) return self.nicks[nick] - def getItem (self,irc,uid): + def getItem(self, irc, uid): # return active item if not irc or not uid: return None for channel in list(self.channels.keys()): - chan = self.getChan(irc,channel) + chan = self.getChan(irc, channel) items = chan.getItems() for type in list(items.keys()): for value in items[type]: @@ -368,23 +386,26 @@ class Ircd (object): # TODO maybe uid under modes that needs op to be shown ? return None - def info (self,irc,uid,prefix,db): + def info(self, irc, uid, prefix, db): # return mode changes summary if not uid or not prefix: return [] c = db.cursor() - c.execute("""SELECT channel,oper,kind,mask,begin_at,end_at,removed_at,removed_by FROM bans WHERE id=? LIMIT 1""",(uid,)) + c.execute( + """SELECT channel,oper,kind,mask,begin_at,end_at,removed_at,removed_by FROM bans WHERE id=? LIMIT 1""", (uid,)) L = c.fetchall() if not len(L): c.close() return [] - (channel,oper,kind,mask,begin_at,end_at,removed_at,removed_by) = L[0] + (channel, oper, kind, mask, begin_at, + end_at, removed_at, removed_by) = L[0] if not ircdb.checkCapability(prefix, '%s,op' % channel): c.close() return [] results = [] current = time.time() - results.append('[%s] [%s] %s sets +%s %s' % (channel,floatToGMT(begin_at),oper,kind,mask)) + results.append('[%s] [%s] %s sets +%s %s' % + (channel, floatToGMT(begin_at), oper, kind, mask)) if not removed_at: if begin_at == end_at: results.append('set forever') @@ -394,22 +415,25 @@ class Ircd (object): s = s + ' and ends at [%s]' % floatToGMT(end_at) results.append(s) else: - s = 'was active %s and ended on [%s]' % (utils.timeElapsed(removed_at-begin_at),floatToGMT(removed_at)) + s = 'was active %s and ended on [%s]' % ( + utils.timeElapsed(removed_at-begin_at), floatToGMT(removed_at)) if end_at != begin_at: - s = s + ' ,initialy for %s' % utils.timeElapsed(end_at-begin_at) + s = s + \ + ' ,initialy for %s' % utils.timeElapsed(end_at-begin_at) s = s + ', removed by %s' % removed_by results.append(s) - c.execute("""SELECT oper, comment FROM comments WHERE ban_id=? ORDER BY at DESC""",(uid,)) + c.execute( + """SELECT oper, comment FROM comments WHERE ban_id=? ORDER BY at DESC""", (uid,)) L = c.fetchall() if len(L): for com in L: - (oper,comment) = com - results.append('"%s" by %s' % (comment,oper)) - c.execute("""SELECT full,log FROM nicks WHERE ban_id=?""",(uid,)) + (oper, comment) = com + results.append('"%s" by %s' % (comment, oper)) + c.execute("""SELECT full,log FROM nicks WHERE ban_id=?""", (uid,)) L = c.fetchall() if len(L) == 1: for affected in L: - (full,log) = affected + (full, log) = affected message = "" for line in log.split('\n'): message = '%s' % line @@ -417,24 +441,24 @@ class Ircd (object): results.append(message) elif len(L) > 1: results.append('affects %s users' % len(L)) - #if len(L): - #for affected in L: - #(full,log) = affected - #message = full - #for line in log.split('\n'): - #message = '[%s]' % line - #break - #results.append(message) + # if len(L): + # for affected in L: + #(full,log) = affected + #message = full + # for line in log.split('\n'): + #message = '[%s]' % line + # break + # results.append(message) c.close() return results - def pending(self,irc,channel,mode,prefix,pattern,db,never,ids,duration): + def pending(self, irc, channel, mode, prefix, pattern, db, never, ids, duration): # returns active items for a channel mode if not channel or not mode or not prefix: return [] if not ircdb.checkCapability(prefix, '%s,op' % channel): return [] - chan = self.getChan(irc,channel) + chan = self.getChan(irc, channel) results = [] r = [] c = db.cursor() @@ -446,45 +470,51 @@ class Ircd (object): item = items[item] if never: if item.when == item.expire or not item.expire: - r.append([item.uid,item.mode,item.value,item.by,item.when,item.expire]) + r.append([item.uid, item.mode, item.value, + item.by, item.when, item.expire]) else: if duration > 0: #log.debug('%s -> %s : %s' % (duration,item.when,(t-item.when))) if (t - item.when) > duration: - r.append([item.uid,item.mode,item.value,item.by,item.when,item.expire]) + r.append([item.uid, item.mode, item.value, + item.by, item.when, item.expire]) else: - r.append([item.uid,item.mode,item.value,item.by,item.when,item.expire]) + r.append([item.uid, item.mode, item.value, + item.by, item.when, item.expire]) r.sort(reverse=True) if len(r): for item in r: - (uid,mode,value,by,when,expire) = item + (uid, mode, value, by, when, expire) = item if pattern != None: if not by.startswith(pattern): - if not ircutils.hostmaskPatternEqual(pattern,by): + if not ircutils.hostmaskPatternEqual(pattern, by): continue - c.execute("""SELECT oper, comment FROM comments WHERE ban_id=? ORDER BY at DESC LIMIT 1""",(uid,)) + c.execute( + """SELECT oper, comment FROM comments WHERE ban_id=? ORDER BY at DESC LIMIT 1""", (uid,)) L = c.fetchall() if len(L): - (oper,comment) = L[0] + (oper, comment) = L[0] message = ' "%s"' % comment else: message = '' if ids: results.append('%s' % uid) elif expire and expire != when: - results.append('[#%s +%s %s by %s expires at %s]%s' % (uid,mode,value,by,floatToGMT(expire),message)) + results.append('[#%s +%s %s by %s expires at %s]%s' % + (uid, mode, value, by, floatToGMT(expire), message)) else: - results.append('[#%s +%s %s by %s on %s]%s' % (uid,mode,value,by,floatToGMT(when),message)) + results.append('[#%s +%s %s by %s on %s]%s' % + (uid, mode, value, by, floatToGMT(when), message)) c.close() return results - def against (self,irc,channel,n,prefix,db,ct): + def against(self, irc, channel, n, prefix, db, ct): # returns active items which matchs n if not channel or not n or not db: return [] if not ircdb.checkCapability(prefix, '%s,op' % channel): return [] - chan = self.getChan(irc,channel) + chan = self.getChan(irc, channel) results = [] r = [] c = db.cursor() @@ -494,66 +524,73 @@ class Ircd (object): if len(items): for item in items: item = items[item] - if match(item.value,n,irc,ct.registryValue('resolveIp')): - r.append([item.uid,item.mode,item.value,item.by,item.when,item.expire]) + if match(item.value, n, irc, ct.registryValue('resolveIp')): + r.append([item.uid, item.mode, item.value, + item.by, item.when, item.expire]) elif item.value.find('$j:') == 0: - channels.append(item.value.replace('$j:','')) + channels.append(item.value.replace('$j:', '')) ct.log.info('channels %s' % ','.join(channels)) if len(channels): for ch in channels: - cha = self.getChan(irc,ch) + cha = self.getChan(irc, ch) for k in list(cha.getItems()): items = cha.getItemsFor(k) - ct.log.info('for %s (%s): %s' % (ch,k,','.join(items))) + ct.log.info('for %s (%s): %s' % (ch, k, ','.join(items))) if len(items): for item in items: item = items[item] - if match(item.value,n,irc,ct.registryValue('resolveIp')): - r.append([item.uid,item.mode,item.value,item.by,item.when,item.expire]) + if match(item.value, n, irc, ct.registryValue('resolveIp')): + r.append([item.uid, item.mode, item.value, + item.by, item.when, item.expire]) r.sort(reverse=True) if len(r): for item in r: - (uid,mode,value,by,when,expire) = item - c.execute("""SELECT oper, comment FROM comments WHERE ban_id=? ORDER BY at DESC LIMIT 1""",(uid,)) + (uid, mode, value, by, when, expire) = item + c.execute( + """SELECT oper, comment FROM comments WHERE ban_id=? ORDER BY at DESC LIMIT 1""", (uid,)) L = c.fetchall() if len(L): - (oper,comment) = L[0] + (oper, comment) = L[0] message = ' "%s"' % comment else: message = '' if expire and expire != when: - results.append('[#%s +%s %s by %s expires at %s]%s' % (uid,mode,value,by,floatToGMT(expire),message)) + results.append('[#%s +%s %s by %s expires at %s]%s' % + (uid, mode, value, by, floatToGMT(expire), message)) else: - results.append('[#%s +%s %s by %s on %s]%s' % (uid,mode,value,by,floatToGMT(when),message)) + results.append('[#%s +%s %s by %s on %s]%s' % + (uid, mode, value, by, floatToGMT(when), message)) c.close() return results - def log (self,irc,uid,prefix,db): + def log(self, irc, uid, prefix, db): # return log of affected users by a mode change if not uid or not prefix: return [] c = db.cursor() - c.execute("""SELECT channel,oper,kind,mask,begin_at,end_at,removed_at,removed_by FROM bans WHERE id=?""",(uid,)) + c.execute( + """SELECT channel,oper,kind,mask,begin_at,end_at,removed_at,removed_by FROM bans WHERE id=?""", (uid,)) L = c.fetchall() if not len(L): c.close() return [] - (channel,oper,kind,mask,begin_at,end_at,removed_at,removed_by) = L[0] + (channel, oper, kind, mask, begin_at, + end_at, removed_at, removed_by) = L[0] if not ircdb.checkCapability(prefix, '%s,op' % channel): c.close() return [] results = [] #c.execute("""SELECT oper, comment, at FROM comments WHERE ban_id=? ORDER BY at DESC""",(uid,)) #L = c.fetchall() - #if len(L): - #for com in L: - #(oper,comment,at) = com - #results.append('"%s" by %s on %s' % (comment,oper,floatToGMT(at))) - c.execute("""SELECT full,log FROM nicks WHERE ban_id=?""",(uid,)) + # if len(L): + # for com in L: + #(oper,comment,at) = com + #results.append('"%s" by %s on %s' % (comment,oper,floatToGMT(at))) + c.execute("""SELECT full,log FROM nicks WHERE ban_id=?""", (uid,)) L = c.fetchall() if len(L): for item in L: - (full,log) = item + (full, log) = item results.append('For [%s]' % full) for line in log.split('\n'): results.append(line) @@ -562,28 +599,29 @@ class Ircd (object): c.close() return results - def search (self,irc,pattern,prefix,db,deep,active,never,channel,ids): + def search(self, irc, pattern, prefix, db, deep, active, never, channel, ids): # deep search inside database, # results filtered depending prefix capability c = db.cursor() bans = {} results = [] - isOwner = ircdb.checkCapability(prefix, 'owner') or prefix == irc.prefix + isOwner = ircdb.checkCapability( + prefix, 'owner') or prefix == irc.prefix glob = '*%s*' % pattern like = '%'+pattern+'%' if pattern.startswith('$'): - pattern = clearExtendedBanPattern(pattern,irc) + pattern = clearExtendedBanPattern(pattern, irc) glob = '*%s*' % pattern like = '%'+pattern+'%' elif ircutils.isUserHostmask(pattern): - (n,i,h) = ircutils.splitHostmask(pattern) + (n, i, h) = ircutils.splitHostmask(pattern) if n == '*': n = None if i == '*': i = None if h == '*': h = None - items = [n,i,h] + items = [n, i, h] subpattern = '' for item in items: if item: @@ -594,43 +632,47 @@ class Ircd (object): items = c.fetchall() if len(items): for item in items: - (uid,mask) = item - if ircutils.hostmaskPatternEqual(pattern,mask): + (uid, mask) = item + if ircutils.hostmaskPatternEqual(pattern, mask): bans[uid] = uid c.execute("""SELECT ban_id, full FROM nicks ORDER BY ban_id DESC""") items = c.fetchall() if len(items): for item in items: - (uid,full) = item - if ircutils.hostmaskPatternEqual(pattern,full): + (uid, full) = item + if ircutils.hostmaskPatternEqual(pattern, full): bans[uid] = uid if deep: - c.execute("""SELECT ban_id, full FROM nicks WHERE full GLOB ? OR full LIKE ? OR log GLOB ? OR log LIKE ? ORDER BY ban_id DESC""",(glob,like,glob,like)) + c.execute("""SELECT ban_id, full FROM nicks WHERE full GLOB ? OR full LIKE ? OR log GLOB ? OR log LIKE ? ORDER BY ban_id DESC""", (glob, like, glob, like)) else: - c.execute("""SELECT ban_id, full FROM nicks WHERE full GLOB ? OR full LIKE ? ORDER BY ban_id DESC""",(glob,like)) + c.execute( + """SELECT ban_id, full FROM nicks WHERE full GLOB ? OR full LIKE ? ORDER BY ban_id DESC""", (glob, like)) items = c.fetchall() if len(items): for item in items: - (uid,full) = item + (uid, full) = item bans[uid] = uid - c.execute("""SELECT id, mask FROM bans WHERE mask GLOB ? OR mask LIKE ? ORDER BY id DESC""",(glob,like)) + c.execute( + """SELECT id, mask FROM bans WHERE mask GLOB ? OR mask LIKE ? ORDER BY id DESC""", (glob, like)) items = c.fetchall() if len(items): for item in items: - (uid,full) = item + (uid, full) = item bans[uid] = uid - c.execute("""SELECT ban_id, comment FROM comments WHERE comment GLOB ? OR comment LIKE ? ORDER BY ban_id DESC""",(glob,like)) + c.execute( + """SELECT ban_id, comment FROM comments WHERE comment GLOB ? OR comment LIKE ? ORDER BY ban_id DESC""", (glob, like)) items = c.fetchall() if len(items): for item in items: - (uid,full) = item + (uid, full) = item bans[uid] = uid if len(bans): for uid in bans: - c.execute("""SELECT id, mask, kind, channel, begin_at, end_at, removed_at FROM bans WHERE id=? ORDER BY id DESC LIMIT 1""",(uid,)) + c.execute( + """SELECT id, mask, kind, channel, begin_at, end_at, removed_at FROM bans WHERE id=? ORDER BY id DESC LIMIT 1""", (uid,)) items = c.fetchall() for item in items: - (uid,mask,kind,chan,begin_at,end_at,removed_at) = item + (uid, mask, kind, chan, begin_at, end_at, removed_at) = item if isOwner or ircdb.checkCapability(prefix, '%s,op' % chan): if never or active: if removed_at: @@ -641,45 +683,47 @@ class Ircd (object): if channel and len(channel): if chan != channel: continue - results.append([uid,mask,kind,chan]) + results.append([uid, mask, kind, chan]) if len(results): results.sort(reverse=True) i = 0 msgs = [] while i < len(results): - (uid,mask,kind,chan) = results[i] + (uid, mask, kind, chan) = results[i] if ids: msgs.append('%s' % uid) elif channel and len(channel): - msgs.append('[#%s +%s %s]' % (uid,kind,mask)) + msgs.append('[#%s +%s %s]' % (uid, kind, mask)) else: - msgs.append('[#%s +%s %s in %s]' % (uid,kind,mask,chan)) + msgs.append('[#%s +%s %s in %s]' % (uid, kind, mask, chan)) i = i+1 c.close() return msgs c.close() return [] - def affect (self,irc,uid,prefix,db): + def affect(self, irc, uid, prefix, db): # return affected users by a mode change if not uid or not prefix: return [] c = db.cursor() - c.execute("""SELECT channel,oper,kind,mask,begin_at,end_at,removed_at,removed_by FROM bans WHERE id=?""",(uid,)) + c.execute( + """SELECT channel,oper,kind,mask,begin_at,end_at,removed_at,removed_by FROM bans WHERE id=?""", (uid,)) L = c.fetchall() if not len(L): c.close() return [] - (channel,oper,kind,mask,begin_at,end_at,removed_at,removed_by) = L[0] + (channel, oper, kind, mask, begin_at, + end_at, removed_at, removed_by) = L[0] if not ircdb.checkCapability(prefix, '%s,op' % channel): c.close() return [] results = [] - c.execute("""SELECT full,log FROM nicks WHERE ban_id=?""",(uid,)) + c.execute("""SELECT full,log FROM nicks WHERE ban_id=?""", (uid,)) L = c.fetchall() if len(L): for item in L: - (full,log) = item + (full, log) = item message = full for line in log.split('\n'): message = '[%s]' % line @@ -690,152 +734,159 @@ class Ircd (object): c.close() return results - def markremoved (self,irc,uid,message,prefix,db,ct): + def markremoved(self, irc, uid, message, prefix, db, ct): # won't use channel,mode,value, because Item may be removed already # it's a duplicate of mark, only used to compute logChannel on a removed item if not prefix or not message: return False c = db.cursor() - c.execute("""SELECT id,channel,kind,mask FROM bans WHERE id=?""",(uid,)) + c.execute("""SELECT id,channel,kind,mask FROM bans WHERE id=?""", (uid,)) L = c.fetchall() b = False if len(L): - (uid,channel,kind,mask) = L[0] - if not ircdb.checkCapability(prefix,'%s,op' % channel): + (uid, channel, kind, mask) = L[0] + if not ircdb.checkCapability(prefix, '%s,op' % channel): if prefix != irc.prefix: c.close() return False current = time.time() - c.execute("""INSERT INTO comments VALUES (?, ?, ?, ?)""",(uid,prefix,current,message)) + c.execute("""INSERT INTO comments VALUES (?, ?, ?, ?)""", + (uid, prefix, current, message)) db.commit() f = None - if prefix != irc.prefix and ct.registryValue('announceMark',channel=channel): + if prefix != irc.prefix and ct.registryValue('announceMark', channel=channel): f = ct._logChan - elif prefix == irc.prefix and ct.registryValue('announceBotMark',channel=channel): + elif prefix == irc.prefix and ct.registryValue('announceBotMark', channel=channel): f = ct._logChan if f: - if ct.registryValue('useColorForAnnounces',channel=channel): - f(irc,channel,'[%s] [#%s %s %s] marked by %s: %s' % (ircutils.bold(channel),ircutils.mircColor(uid,'yellow','black'),ircutils.bold(ircutils.mircColor('+%s' % kind,'red')),ircutils.mircColor(mask,'light blue'),prefix.split('!')[0],message)) + if ct.registryValue('useColorForAnnounces', channel=channel): + f(irc, channel, '[%s] [#%s %s %s] marked by %s: %s' % (ircutils.bold(channel), ircutils.mircColor(uid, 'yellow', 'black'), ircutils.bold( + ircutils.mircColor('+%s' % kind, 'red')), ircutils.mircColor(mask, 'light blue'), prefix.split('!')[0], message)) else: - f(irc,channel,'[%s] [#%s +%s %s] marked by %s: %s' % (channel,uid,kind,mask,prefix.split('!')[0],message)) + f(irc, channel, '[%s] [#%s +%s %s] marked by %s: %s' % + (channel, uid, kind, mask, prefix.split('!')[0], message)) b = True c.close() return b - def mark (self,irc,uid,message,prefix,db,logFunction,ct): + def mark(self, irc, uid, message, prefix, db, logFunction, ct): # won't use channel,mode,value, because Item may be removed already if not prefix or not message: return False c = db.cursor() - c.execute("""SELECT id,channel,kind,mask FROM bans WHERE id=?""",(uid,)) + c.execute("""SELECT id,channel,kind,mask FROM bans WHERE id=?""", (uid,)) L = c.fetchall() b = False if len(L): - (uid,channel,kind,mask) = L[0] - if not ircdb.checkCapability(prefix,'%s,op' % channel): + (uid, channel, kind, mask) = L[0] + if not ircdb.checkCapability(prefix, '%s,op' % channel): if prefix != irc.prefix: c.close() return False current = time.time() - c.execute("""INSERT INTO comments VALUES (?, ?, ?, ?)""",(uid,prefix,current,message)) + c.execute("""INSERT INTO comments VALUES (?, ?, ?, ?)""", + (uid, prefix, current, message)) db.commit() if logFunction: - if ct.registryValue('useColorForAnnounces',channel=channel): - logFunction(irc,channel,'[%s] [#%s %s %s] marked by %s: %s' % (ircutils.bold(channel),ircutils.mircColor(uid,'yellow','black'),ircutils.bold(ircutils.mircColor('+%s' % kind,'red')),ircutils.mircColor(mask,'light blue'),prefix.split('!')[0],message)) + if ct.registryValue('useColorForAnnounces', channel=channel): + logFunction(irc, channel, '[%s] [#%s %s %s] marked by %s: %s' % (ircutils.bold(channel), ircutils.mircColor(uid, 'yellow', 'black'), ircutils.bold( + ircutils.mircColor('+%s' % kind, 'red')), ircutils.mircColor(mask, 'light blue'), prefix.split('!')[0], message)) else: - logFunction(irc,channel,'[%s] [#%s +%s %s] marked by %s: %s' % (channel,uid,kind,mask,prefix.split('!')[0],message)) + logFunction(irc, channel, '[%s] [#%s +%s %s] marked by %s: %s' % ( + channel, uid, kind, mask, prefix.split('!')[0], message)) b = True c.close() return b - def submark (self,irc,channel,mode,value,message,prefix,db,logFunction,ct): + def submark(self, irc, channel, mode, value, message, prefix, db, logFunction, ct): # add mark to an item which is not already in lists if not channel or not mode or not value or not prefix: return False - if not ircdb.checkCapability(prefix,'%s,op' % channel): + if not ircdb.checkCapability(prefix, '%s,op' % channel): if prefix != irc.prefix: return False c = db.cursor() - c.execute("""SELECT id,oper FROM bans WHERE channel=? AND kind=? AND mask=? AND removed_at is NULL ORDER BY id LIMIT 1""",(channel,mode,value)) + c.execute("""SELECT id,oper FROM bans WHERE channel=? AND kind=? AND mask=? AND removed_at is NULL ORDER BY id LIMIT 1""", (channel, mode, value)) L = c.fetchall() if len(L): # item exists - (uid,oper) = L[0] + (uid, oper) = L[0] c.close() # must not be occurs, but .. - return self.mark(irc,uid,message,prefix,db,logFunction,ct) + return self.mark(irc, uid, message, prefix, db, logFunction, ct) else: c.close() if channel in self.channels: - chan = self.getChan(irc,channel) - item = chan.getItem(mode,value) + chan = self.getChan(irc, channel) + item = chan.getItem(mode, value) if not item: - hash = '%s%s' % (mode,value) + hash = '%s%s' % (mode, value) # prepare item update after being set ( we don't have id yet ) - chan.mark[hash] = [mode,value,message,prefix] + chan.mark[hash] = [mode, value, message, prefix] return True return False - def add (self,irc,channel,mode,value,seconds,prefix,db): + def add(self, irc, channel, mode, value, seconds, prefix, db): # add new eIqb item - if not ircdb.checkCapability(prefix,'%s,op' % channel): + if not ircdb.checkCapability(prefix, '%s,op' % channel): if prefix != irc.prefix: return False if not channel or not mode or not value or not prefix: return False c = db.cursor() - c.execute("""SELECT id,oper FROM bans WHERE channel=? AND kind=? AND mask=? AND removed_at is NULL ORDER BY id LIMIT 1""",(channel,mode,value)) + c.execute("""SELECT id,oper FROM bans WHERE channel=? AND kind=? AND mask=? AND removed_at is NULL ORDER BY id LIMIT 1""", (channel, mode, value)) L = c.fetchall() if len(L): - (id,oper) = L[0] + (id, oper) = L[0] c.close() if channel in self.channels: - chan = self.getChan(irc,channel) - hash = '%s%s' % (mode,value) - chan.update[hash] = [mode,value,seconds,prefix] + chan = self.getChan(irc, channel) + hash = '%s%s' % (mode, value) + chan.update[hash] = [mode, value, seconds, prefix] return True return False else: c.close() if channel in self.channels: - chan = self.getChan(irc,channel) - hash = '%s%s' % (mode,value) + chan = self.getChan(irc, channel) + hash = '%s%s' % (mode, value) # prepare item update after being set ( we don't have id yet ) - chan.update[hash] = [mode,value,seconds,prefix] + chan.update[hash] = [mode, value, seconds, prefix] # enqueue mode changes - chan.queue.enqueue(('+%s' % mode,value)) + chan.queue.enqueue(('+%s' % mode, value)) return True return False - def remove (self,id,db): + def remove(self, id, db): c = db.cursor() - c.execute("""SELECT id,channel,kind,mask FROM bans WHERE id=? LIMIT 1""",(id,)) + c.execute( + """SELECT id,channel,kind,mask FROM bans WHERE id=? LIMIT 1""", (id,)) L = c.fetchall() b = False if len(L): - (uid,channel,kind,mask) = L[0] - c.execute("""DELETE FROM bans WHERE id=? LIMIT 1""",(uid,)) - c.execute("""DELETE FROM comments WHERE ban_id=?""",(uid,)) - c.execute("""DELETE FROM nicks WHERE ban_id=?""",(uid,)) + (uid, channel, kind, mask) = L[0] + c.execute("""DELETE FROM bans WHERE id=? LIMIT 1""", (uid,)) + c.execute("""DELETE FROM comments WHERE ban_id=?""", (uid,)) + c.execute("""DELETE FROM nicks WHERE ban_id=?""", (uid,)) c.close() db.commit() b = True return b - def edit (self,irc,channel,mode,value,seconds,prefix,db,scheduleFunction,logFunction,ct): + def edit(self, irc, channel, mode, value, seconds, prefix, db, scheduleFunction, logFunction, ct): # edit eIqb duration if not channel or not mode or not value or not prefix: return False - if not ircdb.checkCapability(prefix,'%s,op' % channel): + if not ircdb.checkCapability(prefix, '%s,op' % channel): if prefix != irc.prefix: return False c = db.cursor() - c.execute("""SELECT id,channel,kind,mask,begin_at,end_at FROM bans WHERE channel=? AND kind=? AND mask=? AND removed_at is NULL ORDER BY id LIMIT 1""",(channel,mode,value)) + c.execute("""SELECT id,channel,kind,mask,begin_at,end_at FROM bans WHERE channel=? AND kind=? AND mask=? AND removed_at is NULL ORDER BY id LIMIT 1""", (channel, mode, value)) L = c.fetchall() b = False if len(L): - (uid,channel,kind,mask,begin_at,end_at) = L[0] - chan = self.getChan(irc,channel) + (uid, channel, kind, mask, begin_at, end_at) = L[0] + chan = self.getChan(irc, channel) current = float(time.time()) if begin_at == end_at and seconds < 0: c.close() @@ -843,41 +894,49 @@ class Ircd (object): if begin_at == end_at: text = 'was forever' else: - text = 'ended [%s] for %s' % (floatToGMT(end_at),utils.timeElapsed(end_at-begin_at)) + text = 'ended [%s] for %s' % (floatToGMT( + end_at), utils.timeElapsed(end_at-begin_at)) if seconds < 0: newEnd = begin_at reason = 'never expires' elif seconds == 0: - newEnd = current # force expires for next tickle - reason = 'expires at [%s], for %s in total' % (floatToGMT(newEnd),utils.timeElapsed(newEnd-begin_at)) + newEnd = current # force expires for next tickle + reason = 'expires at [%s], for %s in total' % ( + floatToGMT(newEnd), utils.timeElapsed(newEnd-begin_at)) else: newEnd = current+seconds - reason = 'expires at [%s], for %s in total' % (floatToGMT(newEnd),utils.timeElapsed(newEnd-begin_at)) - text = '%s, now %s' % (text,reason) - c.execute("""INSERT INTO comments VALUES (?, ?, ?, ?)""",(uid,prefix,current,text)) - c.execute("""UPDATE bans SET end_at=? WHERE id=?""", (newEnd,int(uid))) + reason = 'expires at [%s], for %s in total' % ( + floatToGMT(newEnd), utils.timeElapsed(newEnd-begin_at)) + text = '%s, now %s' % (text, reason) + c.execute("""INSERT INTO comments VALUES (?, ?, ?, ?)""", + (uid, prefix, current, text)) + c.execute("""UPDATE bans SET end_at=? WHERE id=?""", + (newEnd, int(uid))) db.commit() - i = chan.getItem(kind,mask) + i = chan.getItem(kind, mask) if i: if newEnd == begin_at: i.expire = None else: i.expire = newEnd if scheduleFunction and newEnd != current: - scheduleFunction(irc,newEnd) + scheduleFunction(irc, newEnd) if logFunction: - if ct.registryValue('useColorForAnnounces',channel=channel): - logFunction(irc,channel,'[%s] [#%s %s %s] edited by %s: %s' % (ircutils.bold(channel),ircutils.mircColor(str(uid),'yellow','black'),ircutils.bold(ircutils.mircColor('+%s' % kind,'red')),ircutils.mircColor(mask,'light blue'),prefix.split('!')[0],reason)) + if ct.registryValue('useColorForAnnounces', channel=channel): + logFunction(irc, channel, '[%s] [#%s %s %s] edited by %s: %s' % (ircutils.bold(channel), ircutils.mircColor(str(uid), 'yellow', 'black'), ircutils.bold( + ircutils.mircColor('+%s' % kind, 'red')), ircutils.mircColor(mask, 'light blue'), prefix.split('!')[0], reason)) else: - logFunction(irc,channel,'[%s] [#%s +%s %s] edited by %s: %s' % (channel,uid,kind,mask,prefix.split('!')[0],reason)) + logFunction(irc, channel, '[%s] [#%s +%s %s] edited by %s: %s' % ( + channel, uid, kind, mask, prefix.split('!')[0], reason)) b = True c.close() return b - def resync (self,irc,channel,mode,db,logFunction,ct): + def resync(self, irc, channel, mode, db, logFunction, ct): # here sync mode lists, if items were removed when bot was offline, mark records as removed c = db.cursor() - c.execute("""SELECT id,channel,mask FROM bans WHERE channel=? AND kind=?AND removed_at is NULL ORDER BY id""",(channel,mode)) + c.execute( + """SELECT id,channel,mask FROM bans WHERE channel=? AND kind=?AND removed_at is NULL ORDER BY id""", (channel, mode)) L = c.fetchall() current = time.time() commits = 0 @@ -885,41 +944,49 @@ class Ircd (object): if len(L): current = time.time() if channel in irc.state.channels: - chan = self.getChan(irc,channel) + chan = self.getChan(irc, channel) if mode in chan.dones: for record in L: - (uid,channel,mask) = record - item = chan.getItem(mode,mask) + (uid, channel, mask) = record + item = chan.getItem(mode, mask) if not item: - c.execute("""UPDATE bans SET removed_at=?, removed_by=? WHERE id=?""", (current,'offline!offline@offline',int(uid))) + c.execute("""UPDATE bans SET removed_at=?, removed_by=? WHERE id=?""", ( + current, 'offline!offline@offline', int(uid))) commits = commits + 1 - if ct.registryValue('useColorForAnnounces',channel=channel): - msgs.append('[#%s %s]' % (ircutils.mircColor(uid,'yellow','black'),ircutils.mircColor(mask,'light blue'))) + if ct.registryValue('useColorForAnnounces', channel=channel): + msgs.append('[#%s %s]' % (ircutils.mircColor( + uid, 'yellow', 'black'), ircutils.mircColor(mask, 'light blue'))) else: - msgs.append('[#%s %s]' % (uid,mask)) + msgs.append('[#%s %s]' % (uid, mask)) if commits > 0: db.commit() if logFunction: - if ct.registryValue('useColorForAnnounces',channel=channel): - logFunction(irc,channel,'[%s] [%s] %s removed: %s' % (ircutils.bold(channel),ircutils.mircColor(mode,'green'),commits, ' '.join(msgs))) + if ct.registryValue('useColorForAnnounces', channel=channel): + logFunction(irc, channel, '[%s] [%s] %s removed: %s' % (ircutils.bold( + channel), ircutils.mircColor(mode, 'green'), commits, ' '.join(msgs))) else: - logFunction(irc,channel,'[%s] [%s] %s removed: %s' % (channel,mode,commits, ' '.join(msgs))) + logFunction(irc, channel, '[%s] [%s] %s removed: %s' % ( + channel, mode, commits, ' '.join(msgs))) # todo restore patterns - c.execute("""SELECT id, pattern, regexp, trigger, life, mode, duration FROM patterns WHERE channel=? ORDER BY id""",(channel,)) + c.execute("""SELECT id, pattern, regexp, trigger, life, mode, duration FROM patterns WHERE channel=? ORDER BY id""", (channel,)) L = c.fetchall() if len(L): if channel in irc.state.channels: - chan = self.getChan(irc,channel) + chan = self.getChan(irc, channel) for record in L: (uid, pattern, regexp, trigger, life, mode, duration) = record - chan.patterns[uid] = Pattern(uid,pattern,int(regexp) == 1, trigger, life, mode, duration) + chan.patterns[uid] = Pattern(uid, pattern, int( + regexp) == 1, trigger, life, mode, duration) c.close() + class Chan (object): - __slots__ = ('ircd', 'name', '_lists', 'queue', 'update', 'mark', 'action', 'dones', 'syn', 'opAsked', 'deopAsked', 'deopPending', 'spam', 'repeatLogs', 'nicks', 'netsplit', 'attacked', 'patterns') + __slots__ = ('ircd', 'name', '_lists', 'queue', 'update', 'mark', 'action', 'dones', 'syn', 'opAsked', + 'deopAsked', 'deopPending', 'spam', 'repeatLogs', 'nicks', 'netsplit', 'attacked', 'patterns') # in memory and in database stores +eIqb list -ov # no user action from here, only ircd messages - def __init__(self,ircd,name): + + def __init__(self, ircd, name): object.__init__(self) self.ircd = ircd self.name = name @@ -946,31 +1013,32 @@ class Chan (object): self.attacked = False self.patterns = {} - def isWrong (self,pattern): + def isWrong(self, pattern): if 'bad' in self.spam and pattern in self.spam['bad']: if len(self.spam['bad'][pattern]) > 0: return True return False - def getItems (self): + def getItems(self): # [X][Item.value] is Item return self._lists - def getItemsFor (self,mode): + def getItemsFor(self, mode): if not mode in self._lists: self._lists[mode] = ircutils.IrcDict() return self._lists[mode] - def summary (self,db): + def summary(self, db): r = [] c = db.cursor() - c.execute("""SELECT id,oper,kind,removed_at FROM bans WHERE channel=?""",(self.name,)) + c.execute( + """SELECT id,oper,kind,removed_at FROM bans WHERE channel=?""", (self.name,)) L = c.fetchall() total = {} opers = {} if len(L): for item in L: - (id,oper,kind,removed_at) = item + (id, oper, kind, removed_at) = item if not kind in total: total[kind] = {} total[kind]['active'] = 0 @@ -990,15 +1058,17 @@ class Chan (object): else: opers[oper][kind]['removed'] = opers[oper][kind]['removed'] + 1 for kind in total: - r.append('+%s: %s/%s (active/total)' % (kind,total[kind]['active'],total[kind]['active']+total[kind]['removed'])) + r.append('+%s: %s/%s (active/total)' % (kind, + total[kind]['active'], total[kind]['active']+total[kind]['removed'])) for oper in opers: r.append('%s:' % oper) for kind in opers[oper]: - r.append('+%s: %s/%s (active/total)' % (kind,opers[oper][kind]['active'],opers[oper][kind]['active']+opers[oper][kind]['removed'])) + r.append('+%s: %s/%s (active/total)' % ( + kind, opers[oper][kind]['active'], opers[oper][kind]['active']+opers[oper][kind]['removed'])) c.close() return r - def addItem (self,mode,value,by,when,db,checkUser=True,ct=None): + def addItem(self, mode, value, by, when, db, checkUser=True, ct=None): # eqIb(+*) (-ov) pattern prefix when # mode : eqIb -ov + ? if mode != 'm': @@ -1015,21 +1085,23 @@ class Chan (object): uid = None expire = when c = db.cursor() - c.execute("""SELECT id,oper,begin_at,end_at FROM bans WHERE channel=? AND kind=? AND mask=? AND removed_at is NULL ORDER BY id LIMIT 1""",(self.name,mode,value)) + c.execute("""SELECT id,oper,begin_at,end_at FROM bans WHERE channel=? AND kind=? AND mask=? AND removed_at is NULL ORDER BY id LIMIT 1""", (self.name, mode, value)) L = c.fetchall() if len(L): # restoring stored informations, due to netsplit server's values may be wrong - (uid,by,when,expire) = L[0] - c.execute("""SELECT ban_id,full FROM nicks WHERE ban_id=?""",(uid,)) + (uid, by, when, expire) = L[0] + c.execute( + """SELECT ban_id,full FROM nicks WHERE ban_id=?""", (uid,)) L = c.fetchall() i.isNew = False if len(L): for item in L: - (uid,full) = item + (uid, full) = item i.affects.append(full) else: # if begin_at == end_at --> that means forever - c.execute("""INSERT INTO bans VALUES (NULL, ?, ?, ?, ?, ?, ?,NULL, NULL)""", (self.name,by,mode,value,when,when)) + c.execute("""INSERT INTO bans VALUES (NULL, ?, ?, ?, ?, ?, ?,NULL, NULL)""", + (self.name, by, mode, value, when, when)) i.isNew = True uid = c.lastrowid # leave channel's users list management to supybot @@ -1039,13 +1111,15 @@ class Chan (object): for nick in list(self.ircd.irc.state.channels[self.name].users): L.append(nick) for nick in L: - n = self.ircd.getNick(self.ircd.irc,nick) + n = self.ircd.getNick(self.ircd.irc, nick) if not n.prefix: try: - n.setPrefix(self.ircd.irc.state.nickToHostmask(nick)) + n.setPrefix( + self.ircd.irc.state.nickToHostmask(nick)) except: pass - m = match(value,n,self.ircd.irc,ct.registryValue('resolveIp')) + m = match(value, n, self.ircd.irc, + ct.registryValue('resolveIp')) if m: i.affects.append(n.prefix) # insert logs @@ -1053,12 +1127,14 @@ class Chan (object): logs = [] logs.append('%s' % n) for line in n.logs: - (ts,target,message) = n.logs[index] + (ts, target, message) = n.logs[index] index += 1 if target == self.name or target == 'ALL': - logs.append('[%s] <%s> %s' % (floatToGMT(ts),nick,message)) - c.execute("""INSERT INTO nicks VALUES (?, ?, ?, ?)""",(uid,value,n.prefix,'\n'.join(logs))) - ns.append([n,m]) + logs.append('[%s] <%s> %s' % ( + floatToGMT(ts), nick, message)) + c.execute("""INSERT INTO nicks VALUES (?, ?, ?, ?)""", + (uid, value, n.prefix, '\n'.join(logs))) + ns.append([n, m]) db.commit() c.close() i.uid = uid @@ -1070,22 +1146,22 @@ class Chan (object): l[value].isNew = False return l[value] - def getItem (self,mode,value): + def getItem(self, mode, value): if mode in self._lists: if value in self._lists[mode]: return self._lists[mode][value] return None - def removeItem (self,mode,value,by,c): + def removeItem(self, mode, value, by, c): # flag item as removed in database, we use a cursor as argument because otherwise database tends to be locked removed_at = float(time.time()) - i = self.getItem(mode,value) + i = self.getItem(mode, value) created = False if not i: - c.execute("""SELECT id,oper,begin_at,end_at FROM bans WHERE channel=? AND kind=? AND mask=? AND removed_at is NULL ORDER BY id LIMIT 1""",(self.name,mode,value)) + c.execute("""SELECT id,oper,begin_at,end_at FROM bans WHERE channel=? AND kind=? AND mask=? AND removed_at is NULL ORDER BY id LIMIT 1""", (self.name, mode, value)) L = c.fetchall() if len(L): - (uid,by,when,expire) = L[0] + (uid, by, when, expire) = L[0] i = Item() i.uid = uid i.mode = mode @@ -1095,38 +1171,43 @@ class Chan (object): i.when = float(when) i.expire = float(expire) if i: - c.execute("""UPDATE bans SET removed_at=?, removed_by=? WHERE id=?""", (removed_at,by,int(i.uid))) + c.execute("""UPDATE bans SET removed_at=?, removed_by=? WHERE id=?""", + (removed_at, by, int(i.uid))) i.removed_by = by i.removed_at = removed_at self._lists[mode].pop(value) return i - def addpattern (self,prefix,limit,life,mode,duration,pattern,regexp,db): - if not ircdb.checkCapability(prefix,'%s,op' % self.name): + def addpattern(self, prefix, limit, life, mode, duration, pattern, regexp, db): + if not ircdb.checkCapability(prefix, '%s,op' % self.name): if prefix != irc.prefix: return False c = db.cursor() - c.execute("""INSERT INTO patterns VALUES (NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, 0)""", (self.name,prefix,time.time(),pattern,regexp,limit,life,mode,duration)) + c.execute("""INSERT INTO patterns VALUES (NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, 0)""", + (self.name, prefix, time.time(), pattern, regexp, limit, life, mode, duration)) uid = c.lastrowid - self.patterns[uid] = Pattern(uid,pattern,regexp == 1,limit,life,mode,duration) + self.patterns[uid] = Pattern( + uid, pattern, regexp == 1, limit, life, mode, duration) db.commit() c.close() r = '' if regexp == 1: r = ' *' - return '[#%s "%s"%s]' % (uid,pattern,r) + return '[#%s "%s"%s]' % (uid, pattern, r) - def rmpattern (self,prefix,uid,db): - if not ircdb.checkCapability(prefix,'%s,op' % self.name): + def rmpattern(self, prefix, uid, db): + if not ircdb.checkCapability(prefix, '%s,op' % self.name): if prefix != irc.prefix: return False c = db.cursor() uid = int(uid) - c.execute("""SELECT id, channel, pattern, regexp FROM patterns WHERE id=? and channel=? LIMIT 1""",(uid,self.name)) + c.execute( + """SELECT id, channel, pattern, regexp FROM patterns WHERE id=? and channel=? LIMIT 1""", (uid, self.name)) items = c.fetchall() if len(items): - (id,channel,pattern,regexp) = items[0] - c.execute("""DELETE FROM patterns WHERE id=? and channel=? LIMIT 1""",(uid,self.name)) + (id, channel, pattern, regexp) = items[0] + c.execute( + """DELETE FROM patterns WHERE id=? and channel=? LIMIT 1""", (uid, self.name)) if uid in self.patterns: del self.patterns[uid] prop = 'Pattern%s' % id @@ -1137,21 +1218,23 @@ class Chan (object): r = '' if regexp == 1: r = ' *' - return '[#%s "%s"%s]' % (uid,pattern,r) + return '[#%s "%s"%s]' % (uid, pattern, r) c.close() return False - def countpattern (self,uid,db): + def countpattern(self, uid, db): c = db.cursor() - c.execute("""SELECT id, count FROM patterns WHERE id=? and channel=? LIMIT 1""",(uid,self.name)) + c.execute( + """SELECT id, count FROM patterns WHERE id=? and channel=? LIMIT 1""", (uid, self.name)) items = c.fetchall() (id, count) = items[0] - c.execute("""UPDATE patterns SET count=? WHERE id=?""", (int(count)+1,int(uid))) + c.execute("""UPDATE patterns SET count=? WHERE id=?""", + (int(count)+1, int(uid))) db.commit() c.close() - def lspattern (self,prefix,pattern,db): - if not ircdb.checkCapability(prefix,'%s,op' % self.name): + def lspattern(self, prefix, pattern, db): + if not ircdb.checkCapability(prefix, '%s,op' % self.name): if prefix != irc.prefix: return [] c = db.cursor() @@ -1164,34 +1247,41 @@ class Chan (object): except: i = None if i: - c.execute("""SELECT id, channel, pattern, oper, at, trigger, life, mode, duration, count, regexp FROM patterns WHERE id=? AND channel=? LIMIT 1""",(i,self.name)) + c.execute("""SELECT id, channel, pattern, oper, at, trigger, life, mode, duration, count, regexp FROM patterns WHERE id=? AND channel=? LIMIT 1""", (i, self.name)) items = c.fetchall() if len(items): - (uid,channel,pattern,oper,at,limit,life,mode,duration,count, regexp) = items[0] + (uid, channel, pattern, oper, at, limit, life, + mode, duration, count, regexp) = items[0] r = '' if regexp == 1: r = ' *' - results.append('[#%s by %s on %s (%s calls) %s/%ss -> %s for %ss: "%s"%s]' % (uid,oper,floatToGMT(at),count,limit,life,mode,duration,pattern,r)) + results.append('[#%s by %s on %s (%s calls) %s/%ss -> %s for %ss: "%s"%s]' % ( + uid, oper, floatToGMT(at), count, limit, life, mode, duration, pattern, r)) items = [] else: glob = '*%s*' % pattern like = '%'+pattern+'%' - c.execute("""SELECT id, channel, pattern, oper, at, trigger, life, mode, duration, count, regexp FROM patterns WHERE (pattern GLOB ? or pattern LIKE ?) AND channel=? ORDER BY id DESC""",(glob,like,self.name)) + c.execute("""SELECT id, channel, pattern, oper, at, trigger, life, mode, duration, count, regexp FROM patterns WHERE (pattern GLOB ? or pattern LIKE ?) AND channel=? ORDER BY id DESC""", (glob, like, self.name)) items = c.fetchall() else: - c.execute("""SELECT id, channel, pattern, oper, at, trigger, life, mode, duration, count, regexp FROM patterns WHERE channel=? ORDER BY id DESC""",(self.name,)) + c.execute("""SELECT id, channel, pattern, oper, at, trigger, life, mode, duration, count, regexp FROM patterns WHERE channel=? ORDER BY id DESC""", (self.name,)) items = c.fetchall() if len(items): for item in items: - (uid,channel,pattern,oper,at,limit,life,mode,duration,count, regexp) = item + (uid, channel, pattern, oper, at, limit, + life, mode, duration, count, regexp) = item r = '' if regexp == 1: r = ' *' - results.append('[#%s (%s calls) %s/%ss -> %s for %ss: "%s"%s]' % (uid,count,limit,life,mode,duration,pattern,r)) + results.append('[#%s (%s calls) %s/%ss -> %s for %ss: "%s"%s]' % + (uid, count, limit, life, mode, duration, pattern, r)) return results + class Item (object): - __slots__ = ('channel', 'mode', 'value', 'by', 'when', 'uid', 'expire', 'removed_at', 'removed_by', 'asked', 'affects', 'isNew') + __slots__ = ('channel', 'mode', 'value', 'by', 'when', 'uid', + 'expire', 'removed_at', 'removed_by', 'asked', 'affects', 'isNew') + def __init__(self): object.__init__(self) self.channel = None @@ -1211,11 +1301,13 @@ class Item (object): end = self.expire if self.when == self.expire: end = None - return 'Item(%s [%s][%s] by %s on %s, expire on %s, removed on %s by %s)' % (self.uid,self.mode,self.value,self.by,floatToGMT(self.when),floatToGMT(end),floatToGMT(self.removed_at),self.removed_by) + return 'Item(%s [%s][%s] by %s on %s, expire on %s, removed on %s by %s)' % (self.uid, self.mode, self.value, self.by, floatToGMT(self.when), floatToGMT(end), floatToGMT(self.removed_at), self.removed_by) + class Nick (object): __slots__ = ('prefix', 'ip', 'realname', 'account', 'logSize', 'logs') - def __init__(self,logSize): + + def __init__(self, logSize): object.__init__(self) self.prefix = None self.ip = None @@ -1227,31 +1319,31 @@ class Nick (object): # target can be a channel, or 'ALL' when it's related to nick itself ( account changes, nick changes, host changes, etc ) # [float(timestamp),target,message] - def setPrefix (self,prefix): + def setPrefix(self, prefix): if self.prefix != prefix: self.ip = None self.prefix = prefix return self - def setIp (self,ip): + def setIp(self, ip): if not ip == self.ip and not ip == '255.255.255.255' and utils.net.isIP(ip): self.ip = ip return self - def setAccount (self,account): + def setAccount(self, account): if account == '*': account = None self.account = account return self - def setRealname (self,realname): + def setRealname(self, realname): self.realname = realname return self - def addLog (self,target,message): + def addLog(self, target, message): if len(self.logs) == self.logSize: self.logs.pop(0) - self.logs.append([time.time(),target,message]) + self.logs.append([time.time(), target, message]) return self def __repr__(self): @@ -1264,10 +1356,13 @@ class Nick (object): realname = self.realname if realname is None: realname = '' - return '%s ip:%s account:%s username:%s' % (self.prefix,ip,account,realname) + return '%s ip:%s account:%s username:%s' % (self.prefix, ip, account, realname) + class Pattern (object): - __slots__ = ('uid', 'pattern', 'regexp', 'limit', 'life', 'mode', 'duration','_match') + __slots__ = ('uid', 'pattern', 'regexp', 'limit', + 'life', 'mode', 'duration', '_match') + def __init__(self, uid, pattern, regexp, limit, life, mode, duration): self.uid = uid self.pattern = pattern @@ -1279,15 +1374,17 @@ class Pattern (object): if regexp: self._match = utils.str.perlReToPythonRe(pattern) - def match (self, text): + def match(self, text): if self._match: - return self._match.search (text) != None + return self._match.search(text) != None return self.pattern in text + def _getRe(f): def get(irc, msg, args, state): original = args[:] s = args.pop(0) + def isRe(s): try: foo = f(s) @@ -1298,7 +1395,7 @@ def _getRe(f): while len(s) < 512 and not isRe(s): s += ' ' + args.pop(0) if len(s) < 512: - state.args.append([s,f(s)]) + state.args.append([s, f(s)]) else: state.errorInvalid('regular expression', s) except IndexError: @@ -1306,13 +1403,14 @@ def _getRe(f): state.errorInvalid('regular expression', s) return get + getPatternAndMatcher = _getRe(utils.str.perlReToPythonRe) addConverter('getPatternAndMatcher', getPatternAndMatcher) # Taken from plugins.Time.seconds -def getTs (irc, msg, args, state): +def getTs(irc, msg, args, state): """[y] [w] [d] [h] [m] [s] Returns the number of seconds in the number of , , @@ -1354,13 +1452,15 @@ def getTs (irc, msg, args, state): i = 1 seconds += i elif kind == '-': - state.args.append(float(seconds)) - raise callbacks.ArgumentError + state.args.append(float(seconds)) + raise callbacks.ArgumentError args.pop(0) state.args.append(float(seconds)) + addConverter('getTs', getTs) + def getProba(irc, msg, args, state): try: v = float(args[0]) @@ -1371,16 +1471,16 @@ def getProba(irc, msg, args, state): except ValueError: raise callbacks.ArgumentError + addConverter('proba', getProba) -import threading -import supybot.world as world -def getDuration (seconds): +def getDuration(seconds): if not len(seconds): return -1 return seconds[0] + def getWrapper(name): parts = registry.split(name) group = getattr(conf, parts.pop(0)) @@ -1392,18 +1492,20 @@ def getWrapper(name): raise registry.InvalidRegistryName(name) return group + def listGroup(group): L = [] for (vname, v) in group._children.items(): if hasattr(group, 'channelValue') and group.channelValue and \ - ircutils.isChannel(vname) and not v._children: + ircutils.isChannel(vname) and not v._children: continue if hasattr(v, 'channelValue') and v.channelValue: L.append(vname) utils.sortBy(str.lower, L) return L -class ChanTracker(callbacks.Plugin,plugins.ChannelDBHandler): + +class ChanTracker(callbacks.Plugin, plugins.ChannelDBHandler): """This plugin keeps records of channel mode changes and permits to manage them over time it also have some channel protection features """ @@ -1423,39 +1525,42 @@ class ChanTracker(callbacks.Plugin,plugins.ChannelDBHandler): self.recaps = re.compile("[A-Z]") self.starting = world.starting if self.registryValue('announceNagInterval') > 0: - schedule.addEvent(self.checkNag,time.time()+self.registryValue('announceNagInterval')) + schedule.addEvent(self.checkNag, time.time() + + self.registryValue('announceNagInterval')) - def checkNag (self): + def checkNag(self): if world: if world.ircs: for irc in world.ircs: for channel in irc.state.channels: - if self.registryValue('logChannel',channel=channel) in irc.state.channels: + if self.registryValue('logChannel', channel=channel) in irc.state.channels: toNag = '' - for mode in self.registryValue('announceNagMode',channel=channel): + for mode in self.registryValue('announceNagMode', channel=channel): if mode in irc.state.channels[channel].modes: toNag = mode break if len(toNag): - message = '[%s] has %s mode' % (channel,toNag) - if self.registryValue('useColorForAnnounces',channel=channel): - message = '[%s] has %s mode' % (ircutils.bold(channel),ircutils.mircColor(toNag,'red')) - self._logChan(irc,channel,message) + message = '[%s] has %s mode' % (channel, toNag) + if self.registryValue('useColorForAnnounces', channel=channel): + message = '[%s] has %s mode' % (ircutils.bold( + channel), ircutils.mircColor(toNag, 'red')) + self._logChan(irc, channel, message) if self.registryValue('announceNagInterval') > 0: - schedule.addEvent(self.checkNag,time.time()+self.registryValue('announceNagInterval')) + schedule.addEvent(self.checkNag, time.time() + + self.registryValue('announceNagInterval')) - def summary (self,irc,msg,args,channel): + def summary(self, irc, msg, args, channel): """[] returns various statistics about channel activity""" - c = self.getChan(irc,channel) + c = self.getChan(irc, channel) messages = c.summary(self.getDb(irc.network)) for message in messages: - irc.queueMsg(ircmsgs.privmsg(msg.nick,message)) + irc.queueMsg(ircmsgs.privmsg(msg.nick, message)) irc.replySuccess() - summary = wrap(summary,['op','channel']) + summary = wrap(summary, ['op', 'channel']) - def extract (self,irc,msg,args,channel,newChannel): + def extract(self, irc, msg, args, channel, newChannel): """[] [] returns a snapshot of ChanTracker's settings for the given , if provided, settings are copied""" @@ -1465,17 +1570,19 @@ class ChanTracker(callbacks.Plugin,plugins.ChannelDBHandler): msgs = [] props = [] for prop in L: - p = getWrapper('%s.%s' % (namespace,prop)) + p = getWrapper('%s.%s' % (namespace, prop)) if p.channelValue: value = str(p) or '' channelValue = str(p.get(channel)) if value != channelValue: - props.append([prop,channelValue]) - msgs.append(ircmsgs.privmsg(msg.nick,'config channel %s %s.%s %s' % (channel,namespace,prop,channelValue))) + props.append([prop, channelValue]) + msgs.append(ircmsgs.privmsg(msg.nick, 'config channel %s %s.%s %s' % ( + channel, namespace, prop, channelValue))) if len(msgs): if newChannel: for prop in props: - newChan = getWrapper('%s.%s.%s' % (namespace,prop[0],newChannel)) + newChan = getWrapper('%s.%s.%s' % + (namespace, prop[0], newChannel)) newChan.set(prop[1]) else: for m in msgs: @@ -1483,9 +1590,10 @@ class ChanTracker(callbacks.Plugin,plugins.ChannelDBHandler): irc.replySuccess() else: irc.reply("%s uses global's settings" % channel) - extract = wrap(extract,['owner','private','channel',optional('validChannel')]) + extract = wrap(extract, ['owner', 'private', + 'channel', optional('validChannel')]) - def editandmark (self,irc,msg,args,user,ids,seconds,reason): + def editandmark(self, irc, msg, args, user, ids, seconds, reason): """[,] [y] [w] [d] [h] [m] [s] [<-1s> means forever, <0s> means remove] [] change expiration and mark of an active mode change, if you got this message while the bot prompted you, your changes were not saved""" @@ -1494,23 +1602,25 @@ class ChanTracker(callbacks.Plugin,plugins.ChannelDBHandler): for id in ids: be = False bm = False - item = i.getItem(irc,id) + item = i.getItem(irc, id) if item: f = None if msg.args[1] != reason: - if self.registryValue('announceEdit',channel=item.channel): + if self.registryValue('announceEdit', channel=item.channel): f = self._logChan - if getDuration(seconds) == 0 and not self.registryValue('announceInTimeEditAndMark',channel=item.channel): + if getDuration(seconds) == 0 and not self.registryValue('announceInTimeEditAndMark', channel=item.channel): f = None - be = i.edit(irc,item.channel,item.mode,item.value,getDuration(seconds),msg.prefix,self.getDb(irc.network),self._schedule,f,self) + be = i.edit(irc, item.channel, item.mode, item.value, getDuration( + seconds), msg.prefix, self.getDb(irc.network), self._schedule, f, self) else: be = True f = None - if self.registryValue('announceMark',channel=item.channel): + if self.registryValue('announceMark', channel=item.channel): f = self._logChan if be: if reason and len(reason): - bm = i.mark(irc,id,reason,msg.prefix,self.getDb(irc.network),f,self) + bm = i.mark(irc, id, reason, msg.prefix, + self.getDb(irc.network), f, self) else: bm = True b = b and be and bm @@ -1519,11 +1629,13 @@ class ChanTracker(callbacks.Plugin,plugins.ChannelDBHandler): if b: irc.replySuccess() else: - irc.reply('item not found, already removed or not enough rights to modify it') + irc.reply( + 'item not found, already removed or not enough rights to modify it') self.forceTickle = True - editandmark = wrap(editandmark,['user',commalist('int'),any('getTs',True),optional('text')]) + editandmark = wrap(editandmark, ['user', commalist( + 'int'), any('getTs', True), optional('text')]) - def edit (self,irc,msg,args,user,ids,seconds): + def edit(self, irc, msg, args, user, ids, seconds): """ [,] [y] [w] [d] [h] [m] [s] [<-1s>] means forever change expiration of some active modes""" @@ -1533,86 +1645,90 @@ class ChanTracker(callbacks.Plugin,plugins.ChannelDBHandler): if not len(ids) > 1: sf = self._schedule for id in ids: - item = i.getItem(irc,id) + item = i.getItem(irc, id) if item: f = None - if msg.prefix != irc.prefix and self.registryValue('announceEdit',channel=item.channel): + if msg.prefix != irc.prefix and self.registryValue('announceEdit', channel=item.channel): f = self._logChan - elif msg.prefix == irc.prefix and self.registryValue('announceBotEdit',channel=item.channel): + elif msg.prefix == irc.prefix and self.registryValue('announceBotEdit', channel=item.channel): f = self._logChan - if getDuration(seconds) == 0 and not self.registryValue('announceInTimeEditAndMark',channel=item.channel): + if getDuration(seconds) == 0 and not self.registryValue('announceInTimeEditAndMark', channel=item.channel): f = None - b = b and i.edit(irc,item.channel,item.mode,item.value,getDuration(seconds),msg.prefix,self.getDb(irc.network),sf,f,self) + b = b and i.edit(irc, item.channel, item.mode, item.value, getDuration( + seconds), msg.prefix, self.getDb(irc.network), sf, f, self) else: - b = False; + b = False if not sf and getDuration(seconds) > 0: - self._schedule(irc,float(time.time())+getDuration(seconds)) + self._schedule(irc, float(time.time())+getDuration(seconds)) if not msg.nick == irc.nick: if b: irc.replySuccess() else: - irc.reply('item not found, already removed or not enough rights to modify it') + irc.reply( + 'item not found, already removed or not enough rights to modify it') self.forceTickle = True self._tickle(irc) - edit = wrap(edit,['user',commalist('int'),any('getTs')]) + edit = wrap(edit, ['user', commalist('int'), any('getTs')]) - def info (self,irc,msg,args,user,id): + def info(self, irc, msg, args, user, id): """ summary of a mode change""" i = self.getIrc(irc) - results = i.info(irc,id,msg.prefix,self.getDb(irc.network)) + results = i.info(irc, id, msg.prefix, self.getDb(irc.network)) if len(results): for message in results: - irc.queueMsg(ircmsgs.privmsg(msg.nick,message)) + irc.queueMsg(ircmsgs.privmsg(msg.nick, message)) else: irc.reply('item not found or not enough rights to see information') self._tickle(irc) - info = wrap(info,['user','int']) + info = wrap(info, ['user', 'int']) - def detail (self,irc,msg,args,user,uid): + def detail(self, irc, msg, args, user, uid): """ logs of a mode change""" i = self.getIrc(irc) - results = i.log (irc,uid,msg.prefix,self.getDb(irc.network)) + results = i.log(irc, uid, msg.prefix, self.getDb(irc.network)) if len(results): - irc.replies(results,None,None,False) + irc.replies(results, None, None, False) else: irc.reply('item not found or not enough rights to see detail') self._tickle(irc) - detail = wrap(detail,['user','int']) + detail = wrap(detail, ['user', 'int']) - def affect (self,irc,msg,args,user,uid): + def affect(self, irc, msg, args, user, uid): """ list users affected by a mode change""" i = self.getIrc(irc) - results = i.affect (irc,uid,msg.prefix,self.getDb(irc.network)) + results = i.affect(irc, uid, msg.prefix, self.getDb(irc.network)) if len(results): - irc.replies(results,None,None,False) + irc.replies(results, None, None, False) else: irc.reply('item not found or not enough rights to see affected users') self._tickle(irc) - affect = wrap(affect, ['user','int']) + affect = wrap(affect, ['user', 'int']) - def mark(self,irc,msg,args,user,ids,message): + def mark(self, irc, msg, args, user, ids, message): """ [,] add comment on a mode change""" i = self.getIrc(irc) b = True for id in ids: - item = i.getItem(irc,id) + item = i.getItem(irc, id) if item: f = None - if msg.prefix != irc.prefix and self.registryValue('announceMark',channel=item.channel): + if msg.prefix != irc.prefix and self.registryValue('announceMark', channel=item.channel): f = self._logChan - elif msg.prefix == irc.prefix and self.registryValue('announceBotMark',channel=item.channel): + elif msg.prefix == irc.prefix and self.registryValue('announceBotMark', channel=item.channel): f = self._logChan - b = b and i.mark(irc,id,message,msg.prefix,self.getDb(irc.network),f,self) + b = b and i.mark(irc, id, message, msg.prefix, + self.getDb(irc.network), f, self) else: - b = b and i.markremoved(irc,id,message,msg.prefix,self.getDb(irc.network),self) + b = b and i.markremoved( + irc, id, message, msg.prefix, self.getDb(irc.network), self) if not msg.nick == irc.nick: if b: irc.replySuccess() @@ -1620,9 +1736,9 @@ class ChanTracker(callbacks.Plugin,plugins.ChannelDBHandler): irc.reply('item not found or not enough rights to mark it') self.forceTickle = True self._tickle(irc) - mark = wrap(mark,['user',commalist('int'),'text']) + mark = wrap(mark, ['user', commalist('int'), 'text']) - def query (self,irc,msg,args,user,optlist,text): + def query(self, irc, msg, args, user, optlist, text): """[--deep] [--never] [--active] [--ids] [--channel=] search inside ban database, --deep to search on log, --never returns items set forever and active, @@ -1646,14 +1762,16 @@ class ChanTracker(callbacks.Plugin,plugins.ChannelDBHandler): ids = True if never: active = True - results = i.search(irc,text,msg.prefix,self.getDb(irc.network),deep,active,never,channel,ids) + results = i.search(irc, text, msg.prefix, self.getDb( + irc.network), deep, active, never, channel, ids) if len(results): - irc.replies(results,None,None,False) + irc.replies(results, None, None, False) else: irc.reply('nothing found') - query = wrap(query,['user',getopts({'deep': '', 'never': '', 'ids':'', 'active' : '','channel':'channel'}),'text']) + query = wrap(query, ['user', getopts( + {'deep': '', 'never': '', 'ids': '', 'active': '', 'channel': 'channel'}), 'text']) - def pending (self, irc, msg, args, channel, optlist): + def pending(self, irc, msg, args, channel, optlist): """[] [--mode=] [--oper=] [--never] [--ids] [--count] [--flood] [--duration [y] [w] [d] [h] [m] [s]] returns active items for --mode, filtered by --oper, --never (never expire), --ids (only ids), --duration (item longer than), --count returns the total, --flood one message per mode""" @@ -1684,11 +1802,13 @@ class ChanTracker(callbacks.Plugin,plugins.ChannelDBHandler): return i = self.getIrc(irc) if oper in i.nicks: - oper = self.getNick(irc,oper).prefix + oper = self.getNick(irc, oper).prefix results = [] if not mode: - mode = self.registryValue('modesToAskWhenOpped',channel=channel) + self.registryValue('modesToAsk',channel=channel) - results = i.pending(irc,channel,mode,msg.prefix,oper,self.getDb(irc.network),never,ids,duration) + mode = self.registryValue( + 'modesToAskWhenOpped', channel=channel) + self.registryValue('modesToAsk', channel=channel) + results = i.pending(irc, channel, mode, msg.prefix, + oper, self.getDb(irc.network), never, ids, duration) if len(results): if count: irc.reply('%s items' % len(results), private=True) @@ -1700,13 +1820,14 @@ class ChanTracker(callbacks.Plugin,plugins.ChannelDBHandler): irc.queueMsg(ircmsgs.privmsg(msg.nick, result)) else: irc.reply('no result') - pending = wrap(pending,['op',getopts({'flood':'','mode': 'letter', 'never': '', 'oper' : 'somethingWithoutSpaces', 'ids' : '', 'count': '', 'duration' : 'getTs'})]) + pending = wrap(pending, ['op', getopts({'flood': '', 'mode': 'letter', 'never': '', + 'oper': 'somethingWithoutSpaces', 'ids': '', 'count': '', 'duration': 'getTs'})]) - def _modes (self,numModes,chan,modes,f): + def _modes(self, numModes, chan, modes, f): for i in range(0, len(modes), numModes): chan.action.enqueue(f(modes[i:i + numModes])) - def modes (self, irc, msg, args, channel, delay, modes): + def modes(self, irc, msg, args, channel, delay, modes): """[] [y] [w] [d] [h] [m] [s] [ ...] Sets the mode in to , sending the arguments given. @@ -1714,42 +1835,51 @@ class ChanTracker(callbacks.Plugin,plugins.ChannelDBHandler): itself. is optional """ def f(L): - return applymodes(channel,L) + return applymodes(channel, L) + def la(): - self._modes(irc.state.supported.get('modes', 1),self.getChan(irc,channel),ircutils.separateModes(modes),f) + self._modes(irc.state.supported.get('modes', 1), self.getChan( + irc, channel), ircutils.separateModes(modes), f) self.forceTickle = True self._tickle(irc) duration = getDuration(delay) if duration > 0: - schedule.addEvent(la,time.time()+duration) + schedule.addEvent(la, time.time()+duration) else: la() irc.replySuccess() - modes = wrap(modes, ['op', any('getTs',True), many('something')]) + modes = wrap(modes, ['op', any('getTs', True), many('something')]) - def do (self,irc,msg,args,channel,mode,items,seconds,reason): + def do(self, irc, msg, args, channel, mode, items, seconds, reason): """[] [,] [y] [w] [d] [h] [m] [s] [<-1> or empty means forever] + targets for duration is mandatory""" - if mode in self.registryValue('modesToAsk',channel=channel) or mode in self.registryValue('modesToAskWhenOpped',channel=channel): - b = self._adds(irc,msg,args,channel,mode,items,getDuration(seconds),reason,False) + if mode in self.registryValue('modesToAsk', channel=channel) or mode in self.registryValue('modesToAskWhenOpped', channel=channel): + b = self._adds(irc, msg, args, channel, mode, items, + getDuration(seconds), reason, False) if not msg.nick == irc.nick and not b: - irc.reply('nicks not found or hostmasks invalids or targets are already +%s' % mode) + irc.reply( + 'nicks not found or hostmasks invalids or targets are already +%s' % mode) else: - irc.reply('selected mode is not supported by config, see modesToAsk and modesToAskWhenOpped') + irc.reply( + 'selected mode is not supported by config, see modesToAsk and modesToAskWhenOpped') - do = wrap(do,['op','letter',commalist('something'),any('getTs',True),rest('text')]) + do = wrap(do, ['op', 'letter', commalist('something'), + any('getTs', True), rest('text')]) - def q (self,irc,msg,args,channel,items,seconds,reason): + def q(self, irc, msg, args, channel, items, seconds, reason): """[] [,] [y] [w] [d] [h] [m] [s] [<-1> or empty means forever] +q targets for duration is mandatory""" - b = self._adds(irc,msg,args,channel,'q',items,getDuration(seconds),reason,False) + b = self._adds(irc, msg, args, channel, 'q', items, + getDuration(seconds), reason, False) if not msg.nick == irc.nick and not b: - irc.reply('nicks not found or hostmasks invalids or targets are already +q') - q = wrap(q,['op',commalist('something'),any('getTs',True),rest('text')]) + irc.reply( + 'nicks not found or hostmasks invalids or targets are already +q') + q = wrap(q, ['op', commalist('something'), + any('getTs', True), rest('text')]) - def b (self, irc, msg, args, channel, optlist, items, seconds, reason): + def b(self, irc, msg, args, channel, optlist, items, seconds, reason): """[] [--perm] [,] [y] [w] [d] [h] [m] [s] [<-1> or empty means forever] +b targets for duration is mandatory, add --perm if you want to add it to permanent bans of Channel""" @@ -1757,39 +1887,49 @@ class ChanTracker(callbacks.Plugin,plugins.ChannelDBHandler): for (option, arg) in optlist: if option == 'perm': perm = True - b = self._adds(irc,msg,args,channel,'b',items,getDuration(seconds),reason,perm) + b = self._adds(irc, msg, args, channel, 'b', items, + getDuration(seconds), reason, perm) if not msg.nick == irc.nick and not b: - irc.reply('nicks not found or hostmasks invalids or targets are already +b') - b = wrap(b,['op',getopts({'perm':''}),commalist('something'),any('getTs',True),rest('text')]) + irc.reply( + 'nicks not found or hostmasks invalids or targets are already +b') + b = wrap(b, ['op', getopts({'perm': ''}), commalist( + 'something'), any('getTs', True), rest('text')]) - def i (self, irc, msg, args, channel, items, seconds, reason): + def i(self, irc, msg, args, channel, items, seconds, reason): """[] [,] [y] [w] [d] [h] [m] [s] [<-1> or empty means forever] +I targets for duration is mandatory""" - b = self._adds(irc,msg,args,channel,'I',items,getDuration(seconds),reason,False) + b = self._adds(irc, msg, args, channel, 'I', items, + getDuration(seconds), reason, False) if not msg.nick == irc.nick and not b: - irc.reply('nicks not found or hostmasks invalids or targets are already +I') - i = wrap(i,['op',commalist('something'),any('getTs',True),rest('text')]) + irc.reply( + 'nicks not found or hostmasks invalids or targets are already +I') + i = wrap(i, ['op', commalist('something'), + any('getTs', True), rest('text')]) - def e (self, irc, msg, args, channel, items, seconds, reason): + def e(self, irc, msg, args, channel, items, seconds, reason): """[] [,] [y] [w] [d] [h] [m] [s] [<-1> or empty means forever] +e targets for duration is mandatory""" - b = self._adds(irc,msg,args,channel,'e',items,getDuration(seconds),reason,False) + b = self._adds(irc, msg, args, channel, 'e', items, + getDuration(seconds), reason, False) if not msg.nick == irc.nick and not b: - irc.reply('nicks not found or hostmasks invalids or targets are already +e') - e = wrap(e,['op',commalist('something'),any('getTs',True),rest('text')]) + irc.reply( + 'nicks not found or hostmasks invalids or targets are already +e') + e = wrap(e, ['op', commalist('something'), + any('getTs', True), rest('text')]) - def undo (self, irc, msg, args, channel, mode, items): + def undo(self, irc, msg, args, channel, mode, items): """[] [] sets - on them, if * found, remove them all""" - b = self._removes(irc,msg,args,channel,mode,items,False) + b = self._removes(irc, msg, args, channel, mode, items, False) if not msg.nick == irc.nick and not b: - irc.reply('nicks not found or hostmasks invalids or targets are not +%s' % mode) - undo = wrap(undo,['op','letter',many('something')]) + irc.reply( + 'nicks not found or hostmasks invalids or targets are not +%s' % mode) + undo = wrap(undo, ['op', 'letter', many('something')]) - def uq (self, irc, msg, args, channel, items): + def uq(self, irc, msg, args, channel, items): """[] [] sets -q on them, if * found, remove them all""" @@ -1797,15 +1937,16 @@ class ChanTracker(callbacks.Plugin,plugins.ChannelDBHandler): for item in items: if item == '*': isMass = True - if isMass and not self.registryValue('removeAllQuiets',channel=channel): + if isMass and not self.registryValue('removeAllQuiets', channel=channel): irc.reply('removal of all quiets has been disabled for %s' % channel) return - b = self._removes(irc,msg,args,channel,'q',items,False) + b = self._removes(irc, msg, args, channel, 'q', items, False) if not msg.nick == irc.nick and not b: - irc.reply('nicks not found or hostmasks invalids or targets are not +q') - uq = wrap(uq,['op',many('something')]) + irc.reply( + 'nicks not found or hostmasks invalids or targets are not +q') + uq = wrap(uq, ['op', many('something')]) - def ub (self, irc, msg, args, channel, optlist, items): + def ub(self, irc, msg, args, channel, optlist, items): """[] [--perm] [] sets -b on them, if * found, remove them all, --perm to remove them for permanent bans""" @@ -1817,21 +1958,24 @@ class ChanTracker(callbacks.Plugin,plugins.ChannelDBHandler): for item in items: if item == '*': isMass = True - if isMass and not self.registryValue('removeAllBans',channel=channel): + if isMass and not self.registryValue('removeAllBans', channel=channel): irc.reply('removal of all bans has been disabled for %s' % channel) return - b = self._removes(irc,msg,args,channel,'b',items,perm) + b = self._removes(irc, msg, args, channel, 'b', items, perm) if not msg.nick == irc.nick and not b: if perm: if len(items) == 1: - irc.reply('nicks not found or hostmasks invalids or targets are not +b, you may try "channel ban remove %s %s"' % (channel,items[0])) + irc.reply( + 'nicks not found or hostmasks invalids or targets are not +b, you may try "channel ban remove %s %s"' % (channel, items[0])) else: - irc.reply('nicks not found or hostmasks invalids or targets are not +b, you may try "channel ban remove %s %s"' % (channel,'')) + irc.reply( + 'nicks not found or hostmasks invalids or targets are not +b, you may try "channel ban remove %s %s"' % (channel, '')) else: - irc.reply('nicks not found or hostmasks invalids or targets are not +b') - ub = wrap(ub,['op',getopts({'perm':''}),many('something')]) + irc.reply( + 'nicks not found or hostmasks invalids or targets are not +b') + ub = wrap(ub, ['op', getopts({'perm': ''}), many('something')]) - def ui (self, irc, msg, args, channel, items): + def ui(self, irc, msg, args, channel, items): """[] [] sets -I on them, if * found, remove them all""" @@ -1839,15 +1983,16 @@ class ChanTracker(callbacks.Plugin,plugins.ChannelDBHandler): for item in items: if item == '*': isMass = True - if isMass and not self.registryValue('removeAllInvites',channel=channel): + if isMass and not self.registryValue('removeAllInvites', channel=channel): irc.reply('removal of all invites has been disabled for %s' % channel) return - b = self._removes(irc,msg,args,channel,'I',items,False) + b = self._removes(irc, msg, args, channel, 'I', items, False) if not msg.nick == irc.nick and not b: - irc.reply('nicks not found or hostmasks invalids or targets are not +I') - ui = wrap(ui,['op',many('something')]) + irc.reply( + 'nicks not found or hostmasks invalids or targets are not +I') + ui = wrap(ui, ['op', many('something')]) - def ue (self, irc, msg, args, channel, items): + def ue(self, irc, msg, args, channel, items): """[] [] sets -e on them, if * found, remove them all""" @@ -1855,46 +2000,48 @@ class ChanTracker(callbacks.Plugin,plugins.ChannelDBHandler): for item in items: if item == '*': isMass = True - if isMass and not self.registryValue('removeAllExempts',channel=channel): + if isMass and not self.registryValue('removeAllExempts', channel=channel): irc.reply('removal of all exempts has been disabled for %s' % channel) return - b = self._removes(irc,msg,args,channel,'e',items,False) + b = self._removes(irc, msg, args, channel, 'e', items, False) if not msg.nick == irc.nick and not b: - irc.reply('nicks not found or hostmasks invalids or targets are not +e') - ue = wrap(ue,['op',many('something')]) + irc.reply( + 'nicks not found or hostmasks invalids or targets are not +e') + ue = wrap(ue, ['op', many('something')]) - def r (self,irc,msg,args,channel,nick,reason): + def r(self, irc, msg, args, channel, nick, reason): """[] [] force a part on with if provided""" - chan = self.getChan(irc,channel) + chan = self.getChan(irc, channel) if not reason: reason = msg.nick - chan.action.enqueue(ircmsgs.IrcMsg('REMOVE %s %s :%s' % (channel,nick,reason))) + chan.action.enqueue(ircmsgs.IrcMsg( + 'REMOVE %s %s :%s' % (channel, nick, reason))) self.forceTickle = True self._tickle(irc) - r = wrap(r,['op','nickInChannel',additional('text')]) + r = wrap(r, ['op', 'nickInChannel', additional('text')]) - def k (self,irc,msg,args,channel,nick,reason): + def k(self, irc, msg, args, channel, nick, reason): """[] [] kick with if provided""" - chan = self.getChan(irc,channel) + chan = self.getChan(irc, channel) if not reason: reason = msg.nick - chan.action.enqueue(ircmsgs.kick(channel,nick,reason)) + chan.action.enqueue(ircmsgs.kick(channel, nick, reason)) self.forceTickle = True self._tickle(irc) - k = wrap(k,['op','nickInChannel',additional('text')]) + k = wrap(k, ['op', 'nickInChannel', additional('text')]) - def overlap (self,irc,msg,args,channel,mode): + def overlap(self, irc, msg, args, channel, mode): """[] returns overlapping modes, there is limitation with extended bans""" results = [] - if mode in self.registryValue('modesToAsk',channel=channel) or mode in self.registryValue('modesToAskWhenOpped',channel=channel): - chan = self.getChan(irc,channel) - modes = chan.getItemsFor(self.getIrcdMode(irc,mode,'*!*@*')[0]) + if mode in self.registryValue('modesToAsk', channel=channel) or mode in self.registryValue('modesToAskWhenOpped', channel=channel): + chan = self.getChan(irc, channel) + modes = chan.getItemsFor(self.getIrcdMode(irc, mode, '*!*@*')[0]) if len(modes): L = [] for m in modes: @@ -1906,39 +2053,40 @@ class ChanTracker(callbacks.Plugin,plugins.ChannelDBHandler): if ircutils.isUserHostmask(i.value): n = Nick(0) n.setPrefix(i.value) - if match(item.value,n,irc,self.registryValue('resolveIp')): - results.append('[#%s %s] matches [#%s %s]' % (item.uid,item.value,i.uid,i.value)) + if match(item.value, n, irc, self.registryValue('resolveIp')): + results.append('[#%s %s] matches [#%s %s]' % ( + item.uid, item.value, i.uid, i.value)) item = L.pop() if len(results): irc.reply(' '.join(results), private=True) else: irc.reply('no results, or unknown mode') self._tickle(irc) - overlap = wrap(overlap,['op','text']) + overlap = wrap(overlap, ['op', 'text']) - def ops (self,irc,msg,args,channel,text): + def ops(self, irc, msg, args, channel, text): """[] triggers ops in the operators channels""" - if not self.registryValue('triggerOps',channel=channel): + if not self.registryValue('triggerOps', channel=channel): return if not text: text = '' schannel = channel - if self.registryValue('useColorForAnnounces',channel=channel): + if self.registryValue('useColorForAnnounces', channel=channel): schannel = ircutils.bold(channel) - self._logChan(irc,channel,"[%s] %s wants attention from ops (%s)" % (schannel,msg.prefix,text)) - ops = wrap(ops,['channel',optional('text')]) + self._logChan(irc, channel, "[%s] %s wants attention from ops (%s)" % ( + schannel, msg.prefix, text)) + ops = wrap(ops, ['channel', optional('text')]) - - def match (self,irc,msg,args,channel,prefix): + def match(self, irc, msg, args, channel, prefix): """[] returns active mode that targets nick given, nick must be in a channel shared with the bot""" i = self.getIrc(irc) n = None if prefix in i.nicks: - n = self.getNick(irc,prefix) + n = self.getNick(irc, prefix) else: if ircutils.isUserHostmask(prefix): n = Nick(0) @@ -1957,15 +2105,16 @@ class ChanTracker(callbacks.Plugin,plugins.ChannelDBHandler): else: irc.reply('unknow nick') return - results = i.against(irc,channel,n,msg.prefix,self.getDb(irc.network),self) + results = i.against(irc, channel, n, msg.prefix, + self.getDb(irc.network), self) if len(results): irc.reply(' '.join(results), private=True) else: irc.reply('no results') self._tickle(irc) - match = wrap(match,['op','text']) + match = wrap(match, ['op', 'text']) - def check (self,irc,msg,args,channel,pattern): + def check(self, irc, msg, args, channel, pattern): """[] returns a list of affected users by a pattern""" @@ -1973,24 +2122,24 @@ class ChanTracker(callbacks.Plugin,plugins.ChannelDBHandler): results = [] i = self.getIrc(irc) for nick in list(irc.state.channels[channel].users): - n = self.getNick(irc,nick) + n = self.getNick(irc, nick) if not n.prefix: try: n.setPrefix(self.ircd.irc.state.nickToHostmask(nick)) except: pass - m = match(pattern,n,irc,self.registryValue('resolveIp')) + m = match(pattern, n, irc, self.registryValue('resolveIp')) if m: - results.append('[%s - %s]' % (nick,m)) + results.append('[%s - %s]' % (nick, m)) if len(results): - irc.reply('%s user(s): %s' % (len(results),' '.join(results))) + irc.reply('%s user(s): %s' % (len(results), ' '.join(results))) else: irc.reply('nobody will be affected') else: irc.reply('invalid pattern given') - check = wrap (check,['op','text']) + check = wrap(check, ['op', 'text']) - def cpmode (self,irc,msg,args,channel,sourceMode,target,targetMode,seconds,reason): + def cpmode(self, irc, msg, args, channel, sourceMode, target, targetMode, seconds, reason): """[] [y] [w] [d] [h] [m] [s] [<-1> or empty means forever] copy elments in on """ @@ -1998,25 +2147,28 @@ class ChanTracker(callbacks.Plugin,plugins.ChannelDBHandler): if not ircdb.checkCapability(msg.prefix, op): irc.replyError('you are missing %s,op capability' % target) return - chan = self.getChan(irc,channel) + chan = self.getChan(irc, channel) targets = set([]) - L = chan.getItemsFor(self.getIrcdMode(irc,sourceMode,'*!*@*')[0]) + L = chan.getItemsFor(self.getIrcdMode(irc, sourceMode, '*!*@*')[0]) for element in L: targets.add(L[element].value) - self._adds(irc,msg,args,target,targetMode,targets,getDuration(seconds),reason,False) + self._adds(irc, msg, args, target, targetMode, targets, + getDuration(seconds), reason, False) irc.replySuccess() - cpmode = wrap (cpmode,['op','letter','validChannel','letter',any('getTs',True),rest('text')]) + cpmode = wrap(cpmode, ['op', 'letter', 'validChannel', + 'letter', any('getTs', True), rest('text')]) - def getmask (self,irc,msg,args,channel,prefix): + def getmask(self, irc, msg, args, channel, prefix): """[] returns a list of hostmask's pattern, best first, mostly used for debug""" i = self.getIrc(irc) if prefix in i.nicks: - irc.reply(' '.join(getBestPattern(self.getNick(irc,prefix),irc,self.registryValue('useIpForGateway',channel=channel),self.registryValue('resolveIp')))) + irc.reply(' '.join(getBestPattern(self.getNick(irc, prefix), irc, self.registryValue( + 'useIpForGateway', channel=channel), self.registryValue('resolveIp')))) else: n = Nick(0) - #gecos ( $x ) + # gecos ( $x ) if '#' in prefix: a = prefix.split('#') username = a[1] @@ -2026,33 +2178,35 @@ class ChanTracker(callbacks.Plugin,plugins.ChannelDBHandler): else: n.setPrefix(prefix) if ircutils.isUserHostmask(prefix): - irc.reply(' '.join(getBestPattern(n,irc,self.registryValue('useIpForGateway',channel=channel),self.registryValue('resolveIp')))) + irc.reply(' '.join(getBestPattern(n, irc, self.registryValue( + 'useIpForGateway', channel=channel), self.registryValue('resolveIp')))) return irc.reply('nick not found or wrong hostmask given') - getmask = wrap(getmask,['op','text']) + getmask = wrap(getmask, ['op', 'text']) - def isvip (self,irc,msg,args,channel,nick): + def isvip(self, irc, msg, args, channel, nick): """[] tell if is vip in , mostly used for debug""" i = self.getIrc(irc) if nick in i.nicks: - irc.reply(self._isVip(irc,channel,self.getNick(irc,nick))) + irc.reply(self._isVip(irc, channel, self.getNick(irc, nick))) else: irc.reply('nick not found') - isvip = wrap(isvip,['op','nick']) + isvip = wrap(isvip, ['op', 'nick']) - def isbad (self,irc,msg,args,channel,nick): + def isbad(self, irc, msg, args, channel, nick): """[] tell if is flagged as bad in , mostly used for debug""" i = self.getIrc(irc) if nick in i.nicks: - chan = self.getChan(irc,channel) - n = self.getNick(irc,nick) - bests = getBestPattern(n,irc,self.registryValue('useIpForGateway',channel=channel),self.registryValue('resolveIp')) + chan = self.getChan(irc, channel) + n = self.getNick(irc, nick) + bests = getBestPattern(n, irc, self.registryValue( + 'useIpForGateway', channel=channel), self.registryValue('resolveIp')) best = bests[0] - if self.registryValue('useAccountBanIfPossible',channel=channel) and n.account: + if self.registryValue('useAccountBanIfPossible', channel=channel) and n.account: for p in bests: if p.startswith('$a:'): best = p @@ -2060,31 +2214,32 @@ class ChanTracker(callbacks.Plugin,plugins.ChannelDBHandler): irc.reply(chan.isWrong(best)) else: irc.reply('nick not found') - isbad = wrap(isbad,['op','nick']) + isbad = wrap(isbad, ['op', 'nick']) - def vacuum (self,irc,msg,args): + def vacuum(self, irc, msg, args): """VACUUM the database""" db = self.getDb(irc.network) c = db.cursor() c.execute('VACUUM') c.close() irc.replySuccess() - vacuum = wrap(vacuum,['owner']) + vacuum = wrap(vacuum, ['owner']) - def m (self,irc,msg,args,channel,items,reason): + def m(self, irc, msg, args, channel, items, reason): """[] [,] store a new item in database under the mode 'm', markeable but not editable""" i = self.getIrc(irc) targets = [] - chan = self.getChan(irc,channel) + chan = self.getChan(irc, channel) for item in items: if item in chan.nicks or item in irc.state.channels[channel].users: - n = self.getNick(irc,item) - patterns = getBestPattern(n,irc,self.registryValue('useIpForGateway',channel=channel),self.registryValue('resolveIp')) + n = self.getNick(irc, item) + patterns = getBestPattern(n, irc, self.registryValue( + 'useIpForGateway', channel=channel), self.registryValue('resolveIp')) if len(patterns): pattern = patterns[0] - if self.registryValue('useAccountBanIfPossible',channel=channel) and n.account: + if self.registryValue('useAccountBanIfPossible', channel=channel) and n.account: for p in patterns: if p.startswith('$a:'): pattern = p @@ -2093,288 +2248,365 @@ class ChanTracker(callbacks.Plugin,plugins.ChannelDBHandler): elif ircutils.isUserHostmask(item) or self.getIrcdExtbansPrefix(irc) in item: targets.append(item) for target in targets: - item = chan.addItem ('m',target,msg.prefix,time.time(),self.getDb(irc.network),self.registryValue('doActionAgainstAffected',channel=channel),self) + item = chan.addItem('m', target, msg.prefix, time.time(), self.getDb( + irc.network), self.registryValue('doActionAgainstAffected', channel=channel), self) f = None - if msg.prefix != irc.prefix and self.registryValue('announceMark',channel=channel): + if msg.prefix != irc.prefix and self.registryValue('announceMark', channel=channel): f = self._logChan db = self.getDb(irc.network) c = db.cursor() - c.execute("""UPDATE bans SET removed_at=?, removed_by=? WHERE id=?""", (time.time()+1,msg.prefix,int(item.uid))) + c.execute("""UPDATE bans SET removed_at=?, removed_by=? WHERE id=?""", + (time.time()+1, msg.prefix, int(item.uid))) db.commit() c.close() - i.mark(irc,item.uid,reason,msg.prefix,self.getDb(irc.network),f,self) + i.mark(irc, item.uid, reason, msg.prefix, + self.getDb(irc.network), f, self) if not msg.nick == irc.nick: if len(targets): irc.replySuccess() else: irc.reply('unknown patterns') - m = wrap(m,['op',commalist('something'),rest('text')]) + m = wrap(m, ['op', commalist('something'), rest('text')]) - def addpattern (self, irc, msg, args, channel, limit, life, mode, duration, pattern): + def addpattern(self, irc, msg, args, channel, limit, life, mode, duration, pattern): """[] (bqeIkrd) [y] [w] [d] [h] [m] [s] add a which triggers for if the appears more than (0 for immediate action) during in seconds""" - chan = self.getChan(irc,channel) - result = chan.addpattern(msg.prefix,limit,life,mode,getDuration(duration),pattern,0,self.getDb(irc.network)) + chan = self.getChan(irc, channel) + result = chan.addpattern(msg.prefix, limit, life, mode, getDuration( + duration), pattern, 0, self.getDb(irc.network)) if result: irc.reply(result) else: irc.reply('not enough rights to add a pattern on %s' % channel) - addpattern = wrap (addpattern,['op','nonNegativeInt','positiveInt', 'letter', any('getTs',True), rest('text')]) + addpattern = wrap(addpattern, [ + 'op', 'nonNegativeInt', 'positiveInt', 'letter', any('getTs', True), rest('text')]) - - def addregexpattern (self, irc, msg, args, channel, limit, life, mode, duration, pattern): + def addregexpattern(self, irc, msg, args, channel, limit, life, mode, duration, pattern): """[] (bqeIkrd) [y] [w] [d] [h] [m] [s] // add a which triggers for if the appears more than (0 for immediate action) during in seconds""" - chan = self.getChan(irc,channel) - result = chan.addpattern(msg.prefix,limit,life,mode,getDuration(duration),pattern[0],1,self.getDb(irc.network)) + chan = self.getChan(irc, channel) + result = chan.addpattern(msg.prefix, limit, life, mode, getDuration( + duration), pattern[0], 1, self.getDb(irc.network)) if result: irc.reply(result) else: irc.reply('not enough rights to add a pattern on %s' % channel) - addregexpattern = wrap (addregexpattern,['op','nonNegativeInt','positiveInt', 'letter', any('getTs',True), rest('getPatternAndMatcher')]) + addregexpattern = wrap(addregexpattern, ['op', 'nonNegativeInt', 'positiveInt', 'letter', any( + 'getTs', True), rest('getPatternAndMatcher')]) - def rmpattern (self, irc, msg, args, channel, ids): + def rmpattern(self, irc, msg, args, channel, ids): """[] [] remove patterns by """ results = [] - chan = self.getChan(irc,channel) + chan = self.getChan(irc, channel) for id in ids: - result = chan.rmpattern(msg.prefix,id,self.getDb(irc.network)) + result = chan.rmpattern(msg.prefix, id, self.getDb(irc.network)) if result: results.append(result) if len(results): - irc.reply('%s removed: %s' % (len(results),','.join(results))) + irc.reply('%s removed: %s' % (len(results), ','.join(results))) else: irc.reply('not found or not enough rights') - rmpattern = wrap(rmpattern,['op',many('positiveInt')]) + rmpattern = wrap(rmpattern, ['op', many('positiveInt')]) - def lspattern (self, irc, msg, args, channel, pattern): + def lspattern(self, irc, msg, args, channel, pattern): """[] [] return patterns in filtered by optional """ results = [] - chan = self.getChan(irc,channel) - results = chan.lspattern(msg.prefix,pattern,self.getDb(irc.network)) - if len (results): - irc.replies(results,None,None,False) + chan = self.getChan(irc, channel) + results = chan.lspattern(msg.prefix, pattern, self.getDb(irc.network)) + if len(results): + irc.replies(results, None, None, False) else: irc.reply('nothing found') - lspattern = wrap(lspattern,['op',optional('text')]) + lspattern = wrap(lspattern, ['op', optional('text')]) - def rmmode (self,irc,msg,args,ids): + def rmmode(self, irc, msg, args, ids): """,[,] remove entries from database, bot's owner command only""" i = self.getIrc(irc) results = [] for id in ids: - b = i.remove(id,self.getDb(irc.network)) + b = i.remove(id, self.getDb(irc.network)) if b: results.append(id) irc.reply('%s' % ', '.join(results)) - rmmode = wrap(rmmode,['owner',commalist('int')]) - - def cflood (self, irc, msg, args, channel, permit, life, mode, duration): + rmmode = wrap(rmmode, ['owner', commalist('int')]) + + def cflood(self, irc, msg, args, channel, permit, life, mode, duration): """[] [] [] [] [] - + return channel protections configuration""" cap = ircdb.canonicalCapability('owner') - if self.registryValue('allowOpToConfig',channel=channel) or ircdb.checkCapability(msg.prefix, cap): + if self.registryValue('allowOpToConfig', channel=channel) or ircdb.checkCapability(msg.prefix, cap): results = ['for %s' % channel] if permit and life and mode and duration: - self.setRegistryValue('floodPermit',permit,channel=channel) - self.setRegistryValue('floodLife',life,channel=channel) - self.setRegistryValue('floodMode',mode,channel=channel) - self.setRegistryValue('floodDuration',duration,channel=channel) - results.append('floodPermit: %s' % self.registryValue('floodPermit',channel=channel)) - results.append('floodLife: %s' % self.registryValue('floodLife',channel=channel)) - results.append('floodMode: %s' % self.registryValue('floodMode',channel=channel)) - results.append('floodDuration: %s' % self.registryValue('floodDuration',channel=channel)) - irc.replies(results,None,None,False) + self.setRegistryValue('floodPermit', permit, channel=channel) + self.setRegistryValue('floodLife', life, channel=channel) + self.setRegistryValue('floodMode', mode, channel=channel) + self.setRegistryValue( + 'floodDuration', duration, channel=channel) + results.append('floodPermit: %s' % + self.registryValue('floodPermit', channel=channel)) + results.append('floodLife: %s' % + self.registryValue('floodLife', channel=channel)) + results.append('floodMode: %s' % + self.registryValue('floodMode', channel=channel)) + results.append('floodDuration: %s' % + self.registryValue('floodDuration', channel=channel)) + irc.replies(results, None, None, False) return - irc.reply("Operators aren't allowed to see or change protection configuration in %s" % channel) - cflood = wrap(cflood,['op', optional('int'), optional('positiveInt'), optional('letter'),optional('positiveInt')]) - - def crepeat (self, irc, msg, args, channel, permit, life, mode, duration, minimum, probability, count, patternLength, patternLife): + irc.reply( + "Operators aren't allowed to see or change protection configuration in %s" % channel) + cflood = wrap(cflood, ['op', optional('int'), optional( + 'positiveInt'), optional('letter'), optional('positiveInt')]) + + def crepeat(self, irc, msg, args, channel, permit, life, mode, duration, minimum, probability, count, patternLength, patternLife): """[] [] [] [] [] [] [] [] [] [] - + return channel protections configuration, is a float between 0 and 1""" cap = ircdb.canonicalCapability('owner') - if self.registryValue('allowOpToConfig',channel=channel) or ircdb.checkCapability(msg.prefix, cap): + if self.registryValue('allowOpToConfig', channel=channel) or ircdb.checkCapability(msg.prefix, cap): results = ['for %s' % channel] if permit and life and mode and duration and minimum and probability and count and patternLength and patternLife: - self.setRegistryValue('repeatPermit',permit,channel=channel) - self.setRegistryValue('repeatLife',life,channel=channel) - self.setRegistryValue('repeatMode',mode,channel=channel) - self.setRegistryValue('repeatDuration',duration,channel=channel) - self.setRegistryValue('repeatMinimum',minimum,channel=channel) - self.setRegistryValue('repeatPercent',probability,channel=channel) - self.setRegistryValue('repeatCount',count,channel=channel) - self.setRegistryValue('repeatPatternMinimum',patternLength,channel=channel) - self.setRegistryValue('repeatPatternLife',patternLife,channel=channel) - results.append('repeatPermit: %s' % self.registryValue('repeatPermit',channel=channel)) - results.append('repeatLife: %s' % self.registryValue('repeatLife',channel=channel)) - results.append('repeatMode: %s' % self.registryValue('repeatMode',channel=channel)) - results.append('repeatDuration: %s' % self.registryValue('repeatDuration',channel=channel)) - results.append('repeatMinimum: %s' % self.registryValue('repeatMinimum',channel=channel)) - results.append('repeatPercent: %s' % self.registryValue('repeatPercent',channel=channel)) - results.append('repeatCount: %s' % self.registryValue('repeatCount',channel=channel)) - results.append('repeatPatternMinimum: %s' % self.registryValue('repeatPatternMinimum',channel=channel)) - results.append('repeatPatternLife: %s' % self.registryValue('repeatPatternLife',channel=channel)) - irc.replies(results,None,None,False) + self.setRegistryValue('repeatPermit', permit, channel=channel) + self.setRegistryValue('repeatLife', life, channel=channel) + self.setRegistryValue('repeatMode', mode, channel=channel) + self.setRegistryValue( + 'repeatDuration', duration, channel=channel) + self.setRegistryValue( + 'repeatMinimum', minimum, channel=channel) + self.setRegistryValue( + 'repeatPercent', probability, channel=channel) + self.setRegistryValue('repeatCount', count, channel=channel) + self.setRegistryValue( + 'repeatPatternMinimum', patternLength, channel=channel) + self.setRegistryValue( + 'repeatPatternLife', patternLife, channel=channel) + results.append('repeatPermit: %s' % + self.registryValue('repeatPermit', channel=channel)) + results.append('repeatLife: %s' % + self.registryValue('repeatLife', channel=channel)) + results.append('repeatMode: %s' % + self.registryValue('repeatMode', channel=channel)) + results.append('repeatDuration: %s' % self.registryValue( + 'repeatDuration', channel=channel)) + results.append('repeatMinimum: %s' % + self.registryValue('repeatMinimum', channel=channel)) + results.append('repeatPercent: %s' % + self.registryValue('repeatPercent', channel=channel)) + results.append('repeatCount: %s' % + self.registryValue('repeatCount', channel=channel)) + results.append('repeatPatternMinimum: %s' % self.registryValue( + 'repeatPatternMinimum', channel=channel)) + results.append('repeatPatternLife: %s' % self.registryValue( + 'repeatPatternLife', channel=channel)) + irc.replies(results, None, None, False) return - irc.reply("Operators aren't allowed to see or change protection configuration in %s" % channel) - crepeat = wrap(crepeat,['op', optional('int'), optional('positiveInt'), optional('letter'), optional('positiveInt'), optional('int'), optional('proba'), optional('positiveInt'), optional('int'), optional('positiveInt')]) + irc.reply( + "Operators aren't allowed to see or change protection configuration in %s" % channel) + crepeat = wrap(crepeat, ['op', optional('int'), optional('positiveInt'), optional('letter'), optional( + 'positiveInt'), optional('int'), optional('proba'), optional('positiveInt'), optional('int'), optional('positiveInt')]) - def ccap (self, irc, msg, args, channel, permit, life, mode, duration, probability): + def ccap(self, irc, msg, args, channel, permit, life, mode, duration, probability): """[] [] [] [] [] [] - + return channel protections configuration, is a float between 0 and 1""" cap = ircdb.canonicalCapability('owner') - if self.registryValue('allowOpToConfig',channel=channel) or ircdb.checkCapability(msg.prefix, cap): + if self.registryValue('allowOpToConfig', channel=channel) or ircdb.checkCapability(msg.prefix, cap): results = ['for %s' % channel] if permit and life and mode and duration and probability: - self.setRegistryValue('capPermit',permit,channel=channel) - self.setRegistryValue('capLife',life,channel=channel) - self.setRegistryValue('capMode',mode,channel=channel) - self.setRegistryValue('capDuration',duration,channel=channel) - self.setRegistryValue('capPercent',probability,channel=channel) - results.append('capPermit: %s' % self.registryValue('capPermit',channel=channel)) - results.append('capLife: %s' % self.registryValue('capLife',channel=channel)) - results.append('capMode: %s' % self.registryValue('capMode',channel=channel)) - results.append('capDuration: %s' % self.registryValue('capDuration',channel=channel)) - results.append('capPercent: %s' % self.registryValue('capPercent',channel=channel)) - irc.replies(results,None,None,False) + self.setRegistryValue('capPermit', permit, channel=channel) + self.setRegistryValue('capLife', life, channel=channel) + self.setRegistryValue('capMode', mode, channel=channel) + self.setRegistryValue('capDuration', duration, channel=channel) + self.setRegistryValue( + 'capPercent', probability, channel=channel) + results.append('capPermit: %s' % + self.registryValue('capPermit', channel=channel)) + results.append('capLife: %s' % + self.registryValue('capLife', channel=channel)) + results.append('capMode: %s' % + self.registryValue('capMode', channel=channel)) + results.append('capDuration: %s' % + self.registryValue('capDuration', channel=channel)) + results.append('capPercent: %s' % + self.registryValue('capPercent', channel=channel)) + irc.replies(results, None, None, False) return - irc.reply("Operators aren't allowed to see or change flood configuration in %s" % channel) - ccap = wrap(ccap,['op', optional('int'), optional('positiveInt'), optional('letter'),optional('positiveInt'), optional('proba')]) + irc.reply( + "Operators aren't allowed to see or change flood configuration in %s" % channel) + ccap = wrap(ccap, ['op', optional('int'), optional('positiveInt'), optional( + 'letter'), optional('positiveInt'), optional('proba')]) - def chl (self, irc, msg, args, channel, permit, life, mode, duration): + def chl(self, irc, msg, args, channel, permit, life, mode, duration): """[] [] [] [] - + return channel protections configuration""" cap = ircdb.canonicalCapability('owner') - if self.registryValue('allowOpToConfig',channel=channel) or ircdb.checkCapability(msg.prefix, cap): + if self.registryValue('allowOpToConfig', channel=channel) or ircdb.checkCapability(msg.prefix, cap): results = ['for %s' % channel] if permit and mode and duration: - self.setRegistryValue('hilightPermit',permit,channel=channel) - self.setRegistryValue('hilightMode',mode,channel=channel) - self.setRegistryValue('hilightDuration',duration,channel=channel) - results.append('hilightPermit: %s' % self.registryValue('hilightPermit',channel=channel)) - results.append('hilightMode: %s' % self.registryValue('hilightMode',channel=channel)) - results.append('hilightDuration: %s' % self.registryValue('hilightDuration',channel=channel)) - irc.replies(results,None,None,False) + self.setRegistryValue('hilightPermit', permit, channel=channel) + self.setRegistryValue('hilightMode', mode, channel=channel) + self.setRegistryValue( + 'hilightDuration', duration, channel=channel) + results.append('hilightPermit: %s' % + self.registryValue('hilightPermit', channel=channel)) + results.append('hilightMode: %s' % + self.registryValue('hilightMode', channel=channel)) + results.append('hilightDuration: %s' % self.registryValue( + 'hilightDuration', channel=channel)) + irc.replies(results, None, None, False) return - irc.reply("Operators aren't allowed to see or change flood configuration in %s" % channel) - chl = wrap(chl,['op', optional('int'), optional('letter'),optional('positiveInt')]) - - def cclone (self, irc, msg, args, channel, permit, life, mode, duration): + irc.reply( + "Operators aren't allowed to see or change flood configuration in %s" % channel) + chl = wrap(chl, ['op', optional('int'), optional( + 'letter'), optional('positiveInt')]) + + def cclone(self, irc, msg, args, channel, permit, life, mode, duration): """[] [] [] [] - + return channel protections configuration""" cap = ircdb.canonicalCapability('owner') - if self.registryValue('allowOpToConfig',channel=channel) or ircdb.checkCapability(msg.prefix, cap): + if self.registryValue('allowOpToConfig', channel=channel) or ircdb.checkCapability(msg.prefix, cap): results = ['for %s' % channel] if permit and mode and duration: - self.setRegistryValue('clonePermit',permit,channel=channel) - self.setRegistryValue('cloneMode',mode,channel=channel) - self.setRegistryValue('hilightDuration',duration,channel=channel) - results.append('clonePermit: %s' % self.registryValue('clonePermit',channel=channel)) - results.append('cloneMode: %s' % self.registryValue('cloneMode',channel=channel)) - results.append('cloneDuration: %s' % self.registryValue('cloneDuration',channel=channel)) - irc.replies(results,None,None,False) + self.setRegistryValue('clonePermit', permit, channel=channel) + self.setRegistryValue('cloneMode', mode, channel=channel) + self.setRegistryValue( + 'hilightDuration', duration, channel=channel) + results.append('clonePermit: %s' % + self.registryValue('clonePermit', channel=channel)) + results.append('cloneMode: %s' % + self.registryValue('cloneMode', channel=channel)) + results.append('cloneDuration: %s' % + self.registryValue('cloneDuration', channel=channel)) + irc.replies(results, None, None, False) return - irc.reply("Operators aren't allowed to see or change flood configuration in %s" % channel) - cclone = wrap(cclone,['op', optional('int'), optional('letter'),optional('positiveInt')]) - - def cnotice (self, irc, msg, args, channel, permit, life, mode, duration): - """[] [] [] [] [] - - return channel protections configuration""" - cap = ircdb.canonicalCapability('owner') - if self.registryValue('allowOpToConfig',channel=channel) or ircdb.checkCapability(msg.prefix, cap): - results = ['for %s' % channel] - if permit and life and mode and duration: - self.setRegistryValue('noticePermit',permit,channel=channel) - self.setRegistryValue('noticeLife',life,channel=channel) - self.setRegistryValue('floodMode',mode,channel=channel) - self.setRegistryValue('floodDuration',duration,channel=channel) - results.append('noticePermit: %s' % self.registryValue('noticePermit',channel=channel)) - results.append('noticeLife: %s' % self.registryValue('noticeLife',channel=channel)) - results.append('noticeMode: %s' % self.registryValue('noticeMode',channel=channel)) - results.append('noticeDuration: %s' % self.registryValue('noticeDuration',channel=channel)) - irc.replies(results,None,None,False) - return - irc.reply("Operators aren't allowed to see or change protection configuration in %s" % channel) - cnotice = wrap(cnotice,['op', optional('int'), optional('positiveInt'), optional('letter'),optional('positiveInt')]) + irc.reply( + "Operators aren't allowed to see or change flood configuration in %s" % channel) + cclone = wrap(cclone, ['op', optional('int'), + optional('letter'), optional('positiveInt')]) - def ccycle (self, irc, msg, args, channel, permit, life, mode, duration): + def cnotice(self, irc, msg, args, channel, permit, life, mode, duration): """[] [] [] [] [] - - return channel protections configuration""" - cap = ircdb.canonicalCapability('owner') - if self.registryValue('allowOpToConfig',channel=channel) or ircdb.checkCapability(msg.prefix, cap): - results = ['for %s' % channel] - if permit and life and mode and duration: - self.setRegistryValue('cyclePermit',permit,channel=channel) - self.setRegistryValue('cycleLife',life,channel=channel) - self.setRegistryValue('cycleMode',mode,channel=channel) - self.setRegistryValue('cycleDuration',duration,channel=channel) - results.append('cyclePermit: %s' % self.registryValue('cyclePermit',channel=channel)) - results.append('cycleLife: %s' % self.registryValue('cycleLife',channel=channel)) - results.append('cycleMode: %s' % self.registryValue('cycleMode',channel=channel)) - results.append('cycleDuration: %s' % self.registryValue('cycleDuration',channel=channel)) - irc.replies(results,None,None,False) - return - irc.reply("Operators aren't allowed to see or change protection configuration in %s" % channel) - ccycle = wrap(ccycle,['op', optional('int'), optional('positiveInt'), optional('letter'),optional('positiveInt')]) - - def cnick (self, irc, msg, args, channel, permit, life, mode, duration): - """[] [] [] [] [] - - return channel protections configuration""" - cap = ircdb.canonicalCapability('owner') - if self.registryValue('allowOpToConfig',channel=channel) or ircdb.checkCapability(msg.prefix, cap): - results = ['for %s' % channel] - if permit and life and mode and duration: - self.setRegistryValue('nickPermit',permit,channel=channel) - self.setRegistryValue('nickLife',life,channel=channel) - self.setRegistryValue('nickMode',mode,channel=channel) - self.setRegistryValue('cycleDuration',duration,channel=channel) - results.append('nickPermit: %s' % self.registryValue('nickPermit',channel=channel)) - results.append('nickLife: %s' % self.registryValue('nickLife',channel=channel)) - results.append('nickMode: %s' % self.registryValue('nickMode',channel=channel)) - results.append('nickDuration: %s' % self.registryValue('nickDuration',channel=channel)) - irc.replies(results,None,None,False) - return - irc.reply("Operators aren't allowed to see or change protection configuration in %s" % channel) - cnick = wrap(cnick,['op', optional('int'), optional('positiveInt'), optional('letter'),optional('positiveInt')]) - def cbad (self, irc, msg, args, channel, permit, life, mode, duration): - """[] [] [] [] [] - return channel protections configuration""" cap = ircdb.canonicalCapability('owner') - if self.registryValue('allowOpToConfig',channel=channel) or ircdb.checkCapability(msg.prefix, cap): + if self.registryValue('allowOpToConfig', channel=channel) or ircdb.checkCapability(msg.prefix, cap): results = ['for %s' % channel] if permit and life and mode and duration: - self.setRegistryValue('badPermit',permit,channel=channel) - self.setRegistryValue('badLife',life,channel=channel) - self.setRegistryValue('badMode',mode,channel=channel) - self.setRegistryValue('cycleDuration',duration,channel=channel) - results.append('badPermit: %s' % self.registryValue('badPermit',channel=channel)) - results.append('badLife: %s' % self.registryValue('badLife',channel=channel)) - results.append('badMode: %s' % self.registryValue('badMode',channel=channel)) - results.append('badDuration: %s' % self.registryValue('badDuration',channel=channel)) - irc.replies(results,None,None,False) + self.setRegistryValue('noticePermit', permit, channel=channel) + self.setRegistryValue('noticeLife', life, channel=channel) + self.setRegistryValue('floodMode', mode, channel=channel) + self.setRegistryValue( + 'floodDuration', duration, channel=channel) + results.append('noticePermit: %s' % + self.registryValue('noticePermit', channel=channel)) + results.append('noticeLife: %s' % + self.registryValue('noticeLife', channel=channel)) + results.append('noticeMode: %s' % + self.registryValue('noticeMode', channel=channel)) + results.append('noticeDuration: %s' % self.registryValue( + 'noticeDuration', channel=channel)) + irc.replies(results, None, None, False) return - irc.reply("Operators aren't allowed to see or change protection configuration in %s" % channel) - cbad = wrap(cbad,['op', optional('int'), optional('positiveInt'), optional('letter'),optional('positiveInt')]) + irc.reply( + "Operators aren't allowed to see or change protection configuration in %s" % channel) + cnotice = wrap(cnotice, ['op', optional('int'), optional( + 'positiveInt'), optional('letter'), optional('positiveInt')]) - def getIrcdMode (self,irc,mode,pattern): + def ccycle(self, irc, msg, args, channel, permit, life, mode, duration): + """[] [] [] [] [] + + return channel protections configuration""" + cap = ircdb.canonicalCapability('owner') + if self.registryValue('allowOpToConfig', channel=channel) or ircdb.checkCapability(msg.prefix, cap): + results = ['for %s' % channel] + if permit and life and mode and duration: + self.setRegistryValue('cyclePermit', permit, channel=channel) + self.setRegistryValue('cycleLife', life, channel=channel) + self.setRegistryValue('cycleMode', mode, channel=channel) + self.setRegistryValue( + 'cycleDuration', duration, channel=channel) + results.append('cyclePermit: %s' % + self.registryValue('cyclePermit', channel=channel)) + results.append('cycleLife: %s' % + self.registryValue('cycleLife', channel=channel)) + results.append('cycleMode: %s' % + self.registryValue('cycleMode', channel=channel)) + results.append('cycleDuration: %s' % + self.registryValue('cycleDuration', channel=channel)) + irc.replies(results, None, None, False) + return + irc.reply( + "Operators aren't allowed to see or change protection configuration in %s" % channel) + ccycle = wrap(ccycle, ['op', optional('int'), optional( + 'positiveInt'), optional('letter'), optional('positiveInt')]) + + def cnick(self, irc, msg, args, channel, permit, life, mode, duration): + """[] [] [] [] [] + + return channel protections configuration""" + cap = ircdb.canonicalCapability('owner') + if self.registryValue('allowOpToConfig', channel=channel) or ircdb.checkCapability(msg.prefix, cap): + results = ['for %s' % channel] + if permit and life and mode and duration: + self.setRegistryValue('nickPermit', permit, channel=channel) + self.setRegistryValue('nickLife', life, channel=channel) + self.setRegistryValue('nickMode', mode, channel=channel) + self.setRegistryValue( + 'cycleDuration', duration, channel=channel) + results.append('nickPermit: %s' % + self.registryValue('nickPermit', channel=channel)) + results.append('nickLife: %s' % + self.registryValue('nickLife', channel=channel)) + results.append('nickMode: %s' % + self.registryValue('nickMode', channel=channel)) + results.append('nickDuration: %s' % + self.registryValue('nickDuration', channel=channel)) + irc.replies(results, None, None, False) + return + irc.reply( + "Operators aren't allowed to see or change protection configuration in %s" % channel) + cnick = wrap(cnick, ['op', optional('int'), optional( + 'positiveInt'), optional('letter'), optional('positiveInt')]) + + def cbad(self, irc, msg, args, channel, permit, life, mode, duration): + """[] [] [] [] [] + + return channel protections configuration""" + cap = ircdb.canonicalCapability('owner') + if self.registryValue('allowOpToConfig', channel=channel) or ircdb.checkCapability(msg.prefix, cap): + results = ['for %s' % channel] + if permit and life and mode and duration: + self.setRegistryValue('badPermit', permit, channel=channel) + self.setRegistryValue('badLife', life, channel=channel) + self.setRegistryValue('badMode', mode, channel=channel) + self.setRegistryValue( + 'cycleDuration', duration, channel=channel) + results.append('badPermit: %s' % + self.registryValue('badPermit', channel=channel)) + results.append('badLife: %s' % + self.registryValue('badLife', channel=channel)) + results.append('badMode: %s' % + self.registryValue('badMode', channel=channel)) + results.append('badDuration: %s' % + self.registryValue('badDuration', channel=channel)) + irc.replies(results, None, None, False) + return + irc.reply( + "Operators aren't allowed to see or change protection configuration in %s" % channel) + cbad = wrap(cbad, ['op', optional('int'), optional( + 'positiveInt'), optional('letter'), optional('positiveInt')]) + + def getIrcdMode(self, irc, mode, pattern): # here we try to know which kind of mode and pattern should be computed : # based on supported modes and extbans on the ircd # works for q in charibys, and should work for unreal and inspire @@ -2396,35 +2628,37 @@ class ChanTracker(callbacks.Plugin,plugins.ChannelDBHandler): mode = 'b' if pattern and not pattern.startswith('m:'): pattern = prefix + 'm' + ':' + pattern - return [mode,pattern] + return [mode, pattern] - def getIrcdExtbansPrefix (self,irc): + def getIrcdExtbansPrefix(self, irc): if 'extban' in irc.state.supported: return irc.state.supported['extban'].split(',')[0] return '' - def _adds (self,irc,msg,args,channel,mode,items,duration,reason,perm): + def _adds(self, irc, msg, args, channel, mode, items, duration, reason, perm): i = self.getIrc(irc) targets = [] - if mode in self.registryValue('modesToAsk',channel=channel) or mode in self.registryValue('modesToAskWhenOpped',channel=channel): - chan = self.getChan(irc,channel) + if mode in self.registryValue('modesToAsk', channel=channel) or mode in self.registryValue('modesToAskWhenOpped', channel=channel): + chan = self.getChan(irc, channel) for item in items: if item in chan.nicks or item in irc.state.channels[channel].users: - n = self.getNick(irc,item) + n = self.getNick(irc, item) found = False - if self.registryValue('avoidOverlap',channel=channel): - modes = chan.getItemsFor(self.getIrcdMode(irc,mode,n.prefix)[0]) + if self.registryValue('avoidOverlap', channel=channel): + modes = chan.getItemsFor( + self.getIrcdMode(irc, mode, n.prefix)[0]) if len(modes): for m in modes: md = modes[m] - if match(md.value,n,irc,self.registryValue('resolveIp')): + if match(md.value, n, irc, self.registryValue('resolveIp')): targets.append(md.value) found = True if not found: - patterns = getBestPattern(n,irc,self.registryValue('useIpForGateway',channel=channel),self.registryValue('resolveIp')) + patterns = getBestPattern(n, irc, self.registryValue( + 'useIpForGateway', channel=channel), self.registryValue('resolveIp')) if len(patterns): pattern = patterns[0] - if self.registryValue('useAccountBanIfPossible',channel=channel) and n.account: + if self.registryValue('useAccountBanIfPossible', channel=channel) and n.account: for p in patterns: if p.startswith('$a:'): pattern = p @@ -2432,82 +2666,87 @@ class ChanTracker(callbacks.Plugin,plugins.ChannelDBHandler): targets.append(pattern) elif ircutils.isUserHostmask(item) or self.getIrcdExtbansPrefix(irc) in item: found = False - if self.registryValue('avoidOverlap',channel=channel): - modes = chan.getItemsFor(self.getIrcdMode(irc,mode,item)[0]) + if self.registryValue('avoidOverlap', channel=channel): + modes = chan.getItemsFor( + self.getIrcdMode(irc, mode, item)[0]) if len(modes): for m in modes: md = modes[m] if ircutils.isUserHostmask(item): n = Nick(0) n.setPrefix(item) - if match(md.value,n,irc,self.registryValue('resolveIp')): + if match(md.value, n, irc, self.registryValue('resolveIp')): targets.append(md.value) found = True if not found: targets.append(item) n = 0 for item in targets: - r = self.getIrcdMode(irc,mode,item) - if i.add(irc,channel,r[0],r[1],duration,msg.prefix,self.getDb(irc.network)): + r = self.getIrcdMode(irc, mode, item) + if i.add(irc, channel, r[0], r[1], duration, msg.prefix, self.getDb(irc.network)): if perm: chan = ircdb.channels.getChannel(channel) - chan.addBan(r[1],0) + chan.addBan(r[1], 0) ircdb.channels.setChannel(channel, chan) if reason: f = None - if self.registryValue('announceInTimeEditAndMark',channel=channel): - if msg.prefix != irc.prefix and self.registryValue('announceMark',channel=channel): + if self.registryValue('announceInTimeEditAndMark', channel=channel): + if msg.prefix != irc.prefix and self.registryValue('announceMark', channel=channel): f = self._logChan - elif msg.prefix == irc.prefix and self.registryValue('announceBotMark',channel=channel): + elif msg.prefix == irc.prefix and self.registryValue('announceBotMark', channel=channel): f = self._logChan - i.submark(irc,channel,mode,item,reason,msg.prefix,self.getDb(irc.network),self._logChan,self) + i.submark(irc, channel, mode, item, reason, msg.prefix, + self.getDb(irc.network), self._logChan, self) n = n+1 self.forceTickle = True self._tickle(irc) return len(items) <= n - def _removes (self,irc,msg,args,channel,mode,items,perm=False): + def _removes(self, irc, msg, args, channel, mode, items, perm=False): i = self.getIrc(irc) - chan = self.getChan(irc,channel) + chan = self.getChan(irc, channel) targets = set([]) massremove = False count = 0 - LL = chan.getItemsFor(self.getIrcdMode(irc,mode,'*!*@*')[0]) - if mode in self.registryValue('modesToAsk',channel=channel) or mode in self.registryValue('modesToAskWhenOpped',channel=channel): + LL = chan.getItemsFor(self.getIrcdMode(irc, mode, '*!*@*')[0]) + if mode in self.registryValue('modesToAsk', channel=channel) or mode in self.registryValue('modesToAskWhenOpped', channel=channel): for item in items: if item in i.nicks or item in irc.state.channels[channel].users: - n = self.getNick(irc,item) + n = self.getNick(irc, item) # here we check active items against Nick and add each pattern which matchs him - L = chan.getItemsFor(self.getIrcdMode(irc,mode,n.prefix)[0]) + L = chan.getItemsFor( + self.getIrcdMode(irc, mode, n.prefix)[0]) for pattern in L: - m = match(L[pattern].value,n,irc,self.registryValue('resolveIp')) + m = match(L[pattern].value, n, irc, + self.registryValue('resolveIp')) if m: targets.add(L[pattern].value) elif ircutils.isUserHostmask(item) or self.getIrcdExtbansPrefix(irc) in item: # previously we were adding directly the item to remove, now we check it agaisnt the active list # that allows to uq $a:* and delete all the quiets on $a:something for pattern in LL: - if ircutils.hostmaskPatternEqual(item,LL[pattern].value): + if ircutils.hostmaskPatternEqual(item, LL[pattern].value): targets.add(LL[pattern].value) elif item == '*': massremove = True targets = [] if channel in list(irc.state.channels.keys()): - L = chan.getItemsFor(self.getIrcdMode(irc,mode,'*!*@*')[0]) + L = chan.getItemsFor( + self.getIrcdMode(irc, mode, '*!*@*')[0]) for pattern in L: targets.add(L[pattern].value) break f = None if massremove: - if self.registryValue('announceMassRemoval',channel=channel): + if self.registryValue('announceMassRemoval', channel=channel): f = self._logChan else: - if msg.prefix != irc.prefix and self.registryValue('announceEdit',channel=channel): + if msg.prefix != irc.prefix and self.registryValue('announceEdit', channel=channel): f = self._logChan - elif msg.prefix == irc.prefix and self.registryValue('announceBotEdit',channel=channel): + elif msg.prefix == irc.prefix and self.registryValue('announceBotEdit', channel=channel): f = self._logChan for item in targets: - r = self.getIrcdMode(irc,mode,item) + r = self.getIrcdMode(irc, mode, item) if perm: chan = ircdb.channels.getChannel(channel) try: @@ -2515,53 +2754,61 @@ class ChanTracker(callbacks.Plugin,plugins.ChannelDBHandler): except: self.log.info('%s is not in Channel.ban' % item) ircdb.channels.setChannel(channel, chan) - if i.edit(irc,channel,r[0],r[1],0,msg.prefix,self.getDb(irc.network),None,f,self): + if i.edit(irc, channel, r[0], r[1], 0, msg.prefix, self.getDb(irc.network), None, f, self): count = count + 1 self.forceTickle = True self._tickle(irc) return len(items) <= count or massremove - def getIrc (self,irc): + def getIrc(self, irc): # init irc db if not irc.network in self._ircs: - i = self._ircs[irc.network] = Ircd (irc,self.registryValue('logsSize')) + i = self._ircs[irc.network] = Ircd( + irc, self.registryValue('logsSize')) return self._ircs[irc.network] - def getChan (self,irc,channel): + def getChan(self, irc, channel): i = self.getIrc(irc) if not channel in i.channels: # restore channel state, loads lists - modesToAsk = ''.join(self.registryValue('modesToAsk',channel=channel)) - modesWhenOpped = ''.join(self.registryValue('modesToAskWhenOpped',channel=channel)) + modesToAsk = ''.join(self.registryValue( + 'modesToAsk', channel=channel)) + modesWhenOpped = ''.join(self.registryValue( + 'modesToAskWhenOpped', channel=channel)) if channel in irc.state.channels: if irc.state.channels[channel].isHalfopPlus(irc.nick): if len(modesToAsk) or len(modesWhenOpped): for m in modesWhenOpped: - i.queue.enqueue(ircmsgs.IrcMsg('MODE %s %s' % (channel,m))) + i.queue.enqueue(ircmsgs.IrcMsg( + 'MODE %s %s' % (channel, m))) for m in modesToAsk: - i.lowQueue.enqueue(ircmsgs.IrcMsg('MODE %s %s' % (channel,m))) + i.lowQueue.enqueue(ircmsgs.IrcMsg( + 'MODE %s %s' % (channel, m))) elif len(modesToAsk): for m in modesToAsk: - i.lowQueue.enqueue(ircmsgs.IrcMsg('MODE %s %s' % (channel,m))) + i.lowQueue.enqueue(ircmsgs.IrcMsg( + 'MODE %s %s' % (channel, m))) if not self.starting: i.lowQueue.enqueue(ircmsgs.ping(channel)) - i.lowQueue.enqueue(ircmsgs.who(channel, args=('%tuhnairf,1',))) + i.lowQueue.enqueue(ircmsgs.who( + channel, args=('%tuhnairf,1',))) self.forceTickle = True - return i.getChan (irc,channel) + return i.getChan(irc, channel) - def getNick (self,irc,nick): - return self.getIrc(irc).getNick(irc,nick) + def getNick(self, irc, nick): + return self.getIrc(irc).getNick(irc, nick) def makeDb(self, filename): """ Create a database and connect to it. """ if os.path.exists(filename): - db = sqlite3.connect(filename,timeout=10) + db = sqlite3.connect(filename, timeout=10) db.text_factory = str if self.dbUpgraded: return db c = db.cursor() try: - c.execute("""SELECT id, pattern FROM patterns WHERE count=? LIMIT 1""",(0,)) + c.execute( + """SELECT id, pattern FROM patterns WHERE count=? LIMIT 1""", (0,)) c.close() except: try: @@ -2639,19 +2886,19 @@ class ChanTracker(callbacks.Plugin,plugins.ChannelDBHandler): db.isolation_level = None return db - def doPong (self,irc,msg): + def doPong(self, irc, msg): self._tickle(irc) - def doPing (self,irc,msg): + def doPing(self, irc, msg): self._tickle(irc) - def _sendModes (self, irc, modes, f): + def _sendModes(self, irc, modes, f): numModes = irc.state.supported.get('modes', 1) ircd = self.getIrc(irc) for i in range(0, len(modes), numModes): ircd.queue.enqueue(f(modes[i:i + numModes])) - def _tickle (self,irc): + def _tickle(self, irc): # Called each time messages are received from irc, it avoid using schedulers which can fail silency # For performance, that may be change in future ... t = time.time() @@ -2668,22 +2915,23 @@ class ChanTracker(callbacks.Plugin,plugins.ChannelDBHandler): # send waiting msgs, here we mostly got kick messages while len(i.queue): irc.queueMsg(i.queue.dequeue()) + def f(L): - return applymodes(channel,L) + return applymodes(channel, L) for channel in list(irc.state.channels.keys()): - chan = self.getChan(irc,channel) + chan = self.getChan(irc, channel) # check expired items for mode in list(chan.getItems().keys()): for value in list(chan._lists[mode].keys()): item = chan._lists[mode][value] if item.expire != None and item.expire != item.when and not item.asked and item.expire <= t: - if mode == 'q' and self.registryValue('useChanServForQuiets',channel=channel) and not irc.state.channels[channel].isHalfopPlus(irc.nick) and len(chan.queue) == 0: + if mode == 'q' and self.registryValue('useChanServForQuiets', channel=channel) and not irc.state.channels[channel].isHalfopPlus(irc.nick) and len(chan.queue) == 0: s = self.registryValue('unquietCommand') - s = s.replace('$channel',channel) - s = s.replace('$hostmask',item.value) + s = s.replace('$channel', channel) + s = s.replace('$hostmask', item.value) i.queue.enqueue(ircmsgs.IrcMsg(s)) else: - chan.queue.enqueue(('-'+item.mode,item.value)) + chan.queue.enqueue(('-'+item.mode, item.value)) # avoid adding it multi times until servers returns changes item.asked = True retickle = True @@ -2693,36 +2941,40 @@ class ChanTracker(callbacks.Plugin,plugins.ChannelDBHandler): if len(chan.queue): index = 0 for item in list(chan.queue): - (mode,value) = item - if mode == '+q' and self.registryValue('useChanServForQuiets',channel=channel) and not irc.state.channels[channel].isHalfopPlus(irc.nick) and len(chan.queue) == 1: + (mode, value) = item + if mode == '+q' and self.registryValue('useChanServForQuiets', channel=channel) and not irc.state.channels[channel].isHalfopPlus(irc.nick) and len(chan.queue) == 1: s = self.registryValue('quietCommand') - s = s.replace('$channel',channel) - s = s.replace('$hostmask',value) + s = s.replace('$channel', channel) + s = s.replace('$hostmask', value) i.queue.enqueue(ircmsgs.IrcMsg(s)) chan.queue.pop(index) index = index + 1 if not irc.state.channels[channel].isHalfopPlus(irc.nick): chan.deopAsked = False chan.deopPending = False - if chan.syn and not irc.state.channels[channel].isHalfopPlus(irc.nick) and not chan.opAsked and self.registryValue('keepOp',channel=channel): + if chan.syn and not irc.state.channels[channel].isHalfopPlus(irc.nick) and not chan.opAsked and self.registryValue('keepOp', channel=channel): # chan.syn is necessary, otherwise, bot can't call owner if rights missed ( see doNotice ) - if not self.registryValue('doNothingAboutOwnOpStatus',channel=channel): + if not self.registryValue('doNothingAboutOwnOpStatus', channel=channel): chan.opAsked = True - def f (): + + def f(): chan.opAsked = False - schedule.addEvent(f,time.time() + 300) - irc.queueMsg(ircmsgs.IrcMsg(self.registryValue('opCommand',channel=channel).replace('$channel',channel).replace('$nick',irc.nick))) + schedule.addEvent(f, time.time() + 300) + irc.queueMsg(ircmsgs.IrcMsg(self.registryValue('opCommand', channel=channel).replace( + '$channel', channel).replace('$nick', irc.nick))) retickle = True if len(chan.queue) or len(chan.action): if not irc.state.channels[channel].isHalfopPlus(irc.nick) and not chan.opAsked: # pending actions, but not opped if not chan.deopAsked: - if not self.registryValue('doNothingAboutOwnOpStatus',channel=channel): + if not self.registryValue('doNothingAboutOwnOpStatus', channel=channel): chan.opAsked = True - def f (): + + def f(): chan.opAsked = False - schedule.addEvent(f,time.time() + 300) - irc.queueMsg(ircmsgs.IrcMsg(self.registryValue('opCommand',channel=channel).replace('$channel',channel).replace('$nick',irc.nick))) + schedule.addEvent(f, time.time() + 300) + irc.queueMsg(ircmsgs.IrcMsg(self.registryValue('opCommand', channel=channel).replace( + '$channel', channel).replace('$nick', irc.nick))) retickle = True elif irc.state.channels[channel].isHalfopPlus(irc.nick): if not chan.deopAsked: @@ -2732,11 +2984,11 @@ class ChanTracker(callbacks.Plugin,plugins.ChannelDBHandler): adding = False while len(chan.queue): L.append(chan.queue.pop()) - mm = L[index][0].replace("+","") - if '+' in L[index][0] and mm in self.registryValue('modesToAsk',channel=channel): - if mm in self.registryValue('kickMode',channel=channel) or self.registryValue('doActionAgainstAffected',channel=channel): + mm = L[index][0].replace("+", "") + if '+' in L[index][0] and mm in self.registryValue('modesToAsk', channel=channel): + if mm in self.registryValue('kickMode', channel=channel) or self.registryValue('doActionAgainstAffected', channel=channel): adding = True - if mm in self.registryValue('modesToAskWhenOpped',channel=channel): + if mm in self.registryValue('modesToAskWhenOpped', channel=channel): adding = True index = index + 1 # remove duplicates ( should not happens but .. ) @@ -2746,13 +2998,13 @@ class ChanTracker(callbacks.Plugin,plugins.ChannelDBHandler): r.append(item) # if glich, just comment this if... if not len(chan.action) and not adding and not chan.attacked: - if not self.registryValue('keepOp',channel=channel) and not self.registryValue('doNothingAboutOwnOpStatus',channel=channel): + if not self.registryValue('keepOp', channel=channel) and not self.registryValue('doNothingAboutOwnOpStatus', channel=channel): chan.deopPending = True chan.deopAsked = True - r.append(('-o',irc.nick)) + r.append(('-o', irc.nick)) if len(r): # create IrcMsg - self._sendModes(irc,r,f) + self._sendModes(irc, r, f) if len(chan.action): while len(chan.action): i.queue.enqueue(chan.action.pop()) @@ -2763,12 +3015,12 @@ class ChanTracker(callbacks.Plugin,plugins.ChannelDBHandler): irc.queueMsg(i.queue.dequeue()) # updates duration for channel in list(irc.state.channels.keys()): - chan = self.getChan(irc,channel) + chan = self.getChan(irc, channel) # check items to update - duration # that allows to set mode, and apply duration to Item created after mode changes # otherwise, we should create db records before applying mode changes ... which, well don't do that :p if len(chan.update): - overexpire = self.registryValue('autoExpire',channel=channel) + overexpire = self.registryValue('autoExpire', channel=channel) if overexpire > 0: # won't override duration pushed by someone else if default is forever # [mode,value,seconds,prefix] @@ -2778,28 +3030,30 @@ class ChanTracker(callbacks.Plugin,plugins.ChannelDBHandler): o = {} index = 0 for k in L: - (m,value,expire,prefix) = L[index] + (m, value, expire, prefix) = L[index] if expire == -1 or expire is None: if overexpire != expire: - chan.update['%s%s' % (m,value)] = [m,value,overexpire,irc.prefix] + chan.update['%s%s' % (m, value)] = [ + m, value, overexpire, irc.prefix] index = index + 1 L = [] for update in list(chan.update.keys()): L.append(chan.update[update]) for update in L: - (m,value,expire,prefix) = update + (m, value, expire, prefix) = update # todo need to protect cycle call between i.edit scheduler and _tickle here. - item = chan.getItem(m,value) + item = chan.getItem(m, value) if item and item.expire != expire: f = None - if self.registryValue('announceInTimeEditAndMark',channel=item.channel): - if prefix != irc.prefix and self.registryValue('announceEdit',channel=item.channel): + if self.registryValue('announceInTimeEditAndMark', channel=item.channel): + if prefix != irc.prefix and self.registryValue('announceEdit', channel=item.channel): f = self._logChan - elif prefix == irc.prefix and self.registryValue('announceBotEdit',channel=item.channel): + elif prefix == irc.prefix and self.registryValue('announceBotEdit', channel=item.channel): f = self._logChan - key = '%s%s' % (m,value) + key = '%s%s' % (m, value) del chan.update[key] - b = i.edit(irc,item.channel,item.mode,item.value,expire,prefix,self.getDb(irc.network),self._schedule,f,self) + b = i.edit(irc, item.channel, item.mode, item.value, expire, prefix, self.getDb( + irc.network), self._schedule, f, self) retickle = True # update marks if len(chan.mark): @@ -2807,22 +3061,23 @@ class ChanTracker(callbacks.Plugin,plugins.ChannelDBHandler): for mark in list(chan.mark.keys()): L.append(chan.mark[mark]) for mark in L: - (m,value,reason,prefix) = mark - item = chan.getItem(m,value) + (m, value, reason, prefix) = mark + item = chan.getItem(m, value) if item: f = None - if self.registryValue('announceInTimeEditAndMark',channel=item.channel): - if prefix != irc.prefix and self.registryValue('announceMark',channel=item.channel): + if self.registryValue('announceInTimeEditAndMark', channel=item.channel): + if prefix != irc.prefix and self.registryValue('announceMark', channel=item.channel): f = self._logChan - elif prefix == irc.prefix and self.registryValue('announceBotMark',channel=item.channel): + elif prefix == irc.prefix and self.registryValue('announceBotMark', channel=item.channel): f = self._logChan - i.mark(irc,item.uid,reason,prefix,self.getDb(irc.network),f,self) - key = '%s%s' % (m,value) + i.mark(irc, item.uid, reason, prefix, + self.getDb(irc.network), f, self) + key = '%s%s' % (m, value) del chan.mark[key] - if irc.state.channels[channel].isHalfopPlus(irc.nick) and not self.registryValue('keepOp',channel=channel) and not chan.deopPending and not chan.deopAsked: + if irc.state.channels[channel].isHalfopPlus(irc.nick) and not self.registryValue('keepOp', channel=channel) and not chan.deopPending and not chan.deopAsked: # ask for deop, delay it a bit - if not self.registryValue('doNothingAboutOwnOpStatus',channel=channel): - self.unOp(irc,channel) + if not self.registryValue('doNothingAboutOwnOpStatus', channel=channel): + self.unOp(irc, channel) # moslty logChannel, and maybe few sync msgs if len(i.lowQueue): retickle = True @@ -2833,98 +3088,106 @@ class ChanTracker(callbacks.Plugin,plugins.ChannelDBHandler): else: self.forceTickle = False - def _addChanModeItem (self,irc,channel,mode,value,prefix,date): + def _addChanModeItem(self, irc, channel, mode, value, prefix, date): # bqeI* -ov if irc.isChannel(channel) and channel in irc.state.channels: - if mode in self.registryValue('modesToAsk',channel=channel) or mode in self.registryValue('modesToAskWhenOpped',channel=channel): - chan = self.getChan(irc,channel) - item = chan.addItem(mode,value,prefix,float(date),self.getDb(irc.network),False,self) + if mode in self.registryValue('modesToAsk', channel=channel) or mode in self.registryValue('modesToAskWhenOpped', channel=channel): + chan = self.getChan(irc, channel) + item = chan.addItem(mode, value, prefix, float( + date), self.getDb(irc.network), False, self) # added expire date if new modes were added when the bot was offline - expire = self.registryValue('autoExpire',channel=item.channel) + expire = self.registryValue('autoExpire', channel=item.channel) if expire > 0 and item.isNew: f = None - if self.registryValue('announceBotEdit',channel=item.channel): + if self.registryValue('announceBotEdit', channel=item.channel): f = self._logChan i = self.getIrc(irc) - i.edit(irc,item.channel,item.mode,item.value,expire,irc.prefix,self.getDb(irc.network),self._schedule,f,self) + i.edit(irc, item.channel, item.mode, item.value, expire, irc.prefix, self.getDb( + irc.network), self._schedule, f, self) item.isNew = False self.forceTickle = True item.isNew = False - def _endList (self,irc,msg,channel,mode): + def _endList(self, irc, msg, channel, mode): if irc.isChannel(channel) and channel in irc.state.channels: - chan = self.getChan(irc,channel) + chan = self.getChan(irc, channel) b = False if not mode in chan.dones: chan.dones.append(mode) b = True i = self.getIrc(irc) f = None - if self.registryValue('announceModeSync',channel=channel): + if self.registryValue('announceModeSync', channel=channel): f = self._logChan if b: - if self.registryValue('useColorForAnnounces',channel=channel): - f(irc,channel,'[%s] sync %s' % (ircutils.bold(channel),chan.dones)) + if self.registryValue('useColorForAnnounces', channel=channel): + f(irc, channel, '[%s] sync %s' % + (ircutils.bold(channel), chan.dones)) else: - f(irc,channel,'[%s] sync %s' % (channel,chan.dones)) - i.resync(irc,channel,mode,self.getDb(irc.network),f,self) + f(irc, channel, '[%s] sync %s' % (channel, chan.dones)) + i.resync(irc, channel, mode, self.getDb(irc.network), f, self) self._tickle(irc) - def do346 (self,irc,msg): + def do346(self, irc, msg): # /mode #channel I - self._addChanModeItem(irc,msg.args[1],'I',msg.args[2],msg.args[3],msg.args[4]) + self._addChanModeItem( + irc, msg.args[1], 'I', msg.args[2], msg.args[3], msg.args[4]) - def do347 (self,irc,msg): + def do347(self, irc, msg): # end of I list - self._endList(irc,msg,msg.args[1],'I') + self._endList(irc, msg, msg.args[1], 'I') - def do348 (self,irc,msg): + def do348(self, irc, msg): # /mode #channel e - self._addChanModeItem(irc,msg.args[1],'e',msg.args[2],msg.args[3],msg.args[4]) + self._addChanModeItem( + irc, msg.args[1], 'e', msg.args[2], msg.args[3], msg.args[4]) - def do349 (self,irc,msg): + def do349(self, irc, msg): # end of e list - self._endList(irc,msg,msg.args[1],'e') + self._endList(irc, msg, msg.args[1], 'e') - def do367 (self,irc,msg): + def do367(self, irc, msg): # /mode #channel b - self._addChanModeItem(irc,msg.args[1],'b',msg.args[2],msg.args[3],msg.args[4]) + self._addChanModeItem( + irc, msg.args[1], 'b', msg.args[2], msg.args[3], msg.args[4]) - def do368 (self,irc,msg): + def do368(self, irc, msg): # end of b list - self._endList(irc,msg,msg.args[1],'b') + self._endList(irc, msg, msg.args[1], 'b') - def do728 (self,irc,msg): + def do728(self, irc, msg): # extended channel's list ( q atm ) - self._addChanModeItem(irc,msg.args[1],msg.args[2],msg.args[3],msg.args[4],msg.args[5]) + self._addChanModeItem( + irc, msg.args[1], msg.args[2], msg.args[3], msg.args[4], msg.args[5]) - def do729 (self,irc,msg): + def do729(self, irc, msg): # end of extended list ( q ) - self._endList(irc,msg,msg.args[1],msg.args[2]) + self._endList(irc, msg, msg.args[1], msg.args[2]) def do352(self, irc, msg): # WHO $channel (nick, ident, host) = (msg.args[5], msg.args[2], msg.args[3]) - n = self.getNick(irc,nick) - n.setPrefix('%s!%s@%s' % (nick,ident,host)) - chan = self.getChan(irc,msg.args[1]) + n = self.getNick(irc, nick) + n.setPrefix('%s!%s@%s' % (nick, ident, host)) + chan = self.getChan(irc, msg.args[1]) chan.nicks[nick] = True # channel = msg.args[1] - def do329 (self,irc,msg): + def do329(self, irc, msg): # channel timestamp channel = msg.args[1] self._tickle(irc) - def do354 (self,irc,msg): + def do354(self, irc, msg): # WHO $channel %tnuhiar,42 # irc.nick 42 ident ip host nick account realname if len(msg.args) == 9 and msg.args[1] == '1': - (garbage,digit,ident,ip,host,nick,status,account,realname) = msg.args + (garbage, digit, ident, ip, host, nick, + status, account, realname) = msg.args if account == '0': account = None - n = self.getNick(irc,nick) - prefix = '%s!%s@%s' % (nick,ident,host) + n = self.getNick(irc, nick) + prefix = '%s!%s@%s' % (nick, ident, host) n.setPrefix(prefix) if self.registryValue('resolveIp') and n.ip == None and ip != '255.255.255.255': # validate ip @@ -2934,54 +3197,59 @@ class ChanTracker(callbacks.Plugin,plugins.ChannelDBHandler): #channel = msg.args[1] self._tickle(irc) - def do315 (self,irc,msg): + def do315(self, irc, msg): # end of extended WHO $channel channel = msg.args[1] if irc.isChannel(channel) and channel in irc.state.channels: - chan = self.getChan(irc,channel) + chan = self.getChan(irc, channel) if not chan.syn: chan.syn = True - if self.registryValue('announceModeSync',channel=channel): - if self.registryValue('useColorForAnnounces',channel=channel): - self._logChan(irc,channel,"[%s] is ready" % ircutils.bold(channel)) + if self.registryValue('announceModeSync', channel=channel): + if self.registryValue('useColorForAnnounces', channel=channel): + self._logChan( + irc, channel, "[%s] is ready" % ircutils.bold(channel)) else: - self._logChan(irc,channel,"[%s] is ready" % channel) + self._logChan(irc, channel, "[%s] is ready" % channel) for nick in list(irc.state.channels[channel].users): chan.nicks[nick] = True self._tickle(irc) - def _logChan (self,irc,channel,message): + def _logChan(self, irc, channel, message): # send messages to logChannel if configured for if channel in irc.state.channels: - logChannel = self.registryValue('logChannel',channel=channel) + logChannel = self.registryValue('logChannel', channel=channel) i = self.getIrc(irc) if logChannel in irc.state.channels: - if logChannel == channel and irc.state.channels[channel].isHalfopPlus(irc.nick) and self.registryValue('keepOp',channel=channel): - if self.registryValue ('announceWithNotice',channel=channel): - i.lowQueue.enqueue(ircmsgs.IrcMsg('NOTICE @%s :%s' % (logChannel,message))) + if logChannel == channel and irc.state.channels[channel].isHalfopPlus(irc.nick) and self.registryValue('keepOp', channel=channel): + if self.registryValue('announceWithNotice', channel=channel): + i.lowQueue.enqueue(ircmsgs.IrcMsg( + 'NOTICE @%s :%s' % (logChannel, message))) else: - i.lowQueue.enqueue(ircmsgs.IrcMsg('PRIVMSG @%s :%s' % (logChannel,message))) + i.lowQueue.enqueue(ircmsgs.IrcMsg( + 'PRIVMSG @%s :%s' % (logChannel, message))) else: - if self.registryValue ('announceWithNotice',channel=channel): - i.lowQueue.enqueue(ircmsgs.IrcMsg('NOTICE %s :%s' % (logChannel,message))) + if self.registryValue('announceWithNotice', channel=channel): + i.lowQueue.enqueue(ircmsgs.IrcMsg( + 'NOTICE %s :%s' % (logChannel, message))) else: - i.lowQueue.enqueue(ircmsgs.IrcMsg('PRIVMSG %s :%s' % (logChannel,message))) + i.lowQueue.enqueue(ircmsgs.IrcMsg( + 'PRIVMSG %s :%s' % (logChannel, message))) elif len(logChannel) > 0: - if self.registryValue ('announceWithNotice',channel=channel): - i.lowQueue.enqueue(ircmsgs.notice(logChannel,message)) + if self.registryValue('announceWithNotice', channel=channel): + i.lowQueue.enqueue(ircmsgs.notice(logChannel, message)) else: - i.lowQueue.enqueue(ircmsgs.privmsg(logChannel,message)) + i.lowQueue.enqueue(ircmsgs.privmsg(logChannel, message)) self.forceTickle = True - def resolve (self,irc,channels,prefix): + def resolve(self, irc, channels, prefix): i = self.getIrc(irc) - (nick,ident,host) = ircutils.splitHostmask(prefix) - n = self.getNick(irc,nick) + (nick, ident, host) = ircutils.splitHostmask(prefix) + n = self.getNick(irc, nick) if n: - (nick,ident,host) = ircutils.splitHostmask(n.prefix) + (nick, ident, host) = ircutils.splitHostmask(n.prefix) if not n.prefix in cache and not '/' in host: try: - r = socket.getaddrinfo(host,None) + r = socket.getaddrinfo(host, None) if r != None: u = {} L = [] @@ -2999,24 +3267,27 @@ class ChanTracker(callbacks.Plugin,plugins.ChannelDBHandler): 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) + 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 '/ip.' in prefix: + if self.registryValue('checkEvade', channel=channel) and '/ip.' in prefix: 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)) + 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): + 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) + 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') @@ -3026,25 +3297,26 @@ class ChanTracker(callbacks.Plugin,plugins.ChannelDBHandler): 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')): + if pat != item.value and match(pat, n, irc, self.registryValue('resolveIp')): f = None - if self.registryValue('announceBotMark',channel=channel): + 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) + i.mark(irc, item.uid, 'evade with %s --> %s' % (prefix, + best), irc.prefix, self.getDb(irc.network), f, self) break self._tickle(irc) - def doChghost (self,irc,msg): - n = self.getNick(irc,msg.nick) + def doChghost(self, irc, msg): + n = self.getNick(irc, msg.nick) (user, host) = msg.args hostmask = '%s!%s@%s' % (msg.nick, user, host) n.setPrefix(hostmask) if 'account' in msg.server_tags: n.setAccount(msg.server_tags['account']) - def doJoin (self,irc,msg): + def doJoin(self, irc, msg): channels = msg.args[0].split(',') - n = self.getNick(irc,msg.nick) + n = self.getNick(irc, msg.nick) n.setPrefix(msg.prefix) i = self.getIrc(irc) if len(msg.args) == 3: @@ -3058,83 +3330,100 @@ class ChanTracker(callbacks.Plugin,plugins.ChannelDBHandler): return if not '/' in msg.prefix.split('@')[1] and n.ip == None: if self.registryValue('resolveIp'): - t = world.SupyThread(target=self.resolve,name=format('Resolving %s for %s', msg.prefix, channels),args=(irc,channels,msg.prefix)) + t = world.SupyThread(target=self.resolve, name=format( + 'Resolving %s for %s', msg.prefix, channels), args=(irc, channels, msg.prefix)) t.setDaemon(True) t.start() elif utils.net.isIP(msg.prefix.split('@')[1]): n.setIp(msg.prefix.split('@')[1]) for channel in channels: if ircutils.isChannel(channel) and channel in irc.state.channels: - bests = getBestPattern(n,irc,self.registryValue('useIpForGateway',channel=channel),self.registryValue('resolveIp')) + bests = getBestPattern(n, irc, self.registryValue( + 'useIpForGateway', channel=channel), self.registryValue('resolveIp')) best = bests[0] - if self.registryValue('useAccountBanIfPossible',channel=channel) and n.account: + if self.registryValue('useAccountBanIfPossible', channel=channel) and n.account: for p in bests: if p.startswith('$a:'): best = p break - chan = self.getChan(irc,channel) + chan = self.getChan(irc, channel) chan.nicks[msg.nick] = True - n.addLog(channel,'has joined') + n.addLog(channel, 'has joined') banned = False c = ircdb.channels.getChannel(channel) - if not self._isVip(irc,channel,n) and not chan.netsplit: - if c.bans and len(c.bans) and self.registryValue('useChannelBansForPermanentBan',channel=channel): + if not self._isVip(irc, channel, n) and not chan.netsplit: + if c.bans and len(c.bans) and self.registryValue('useChannelBansForPermanentBan', channel=channel): for ban in list(c.bans): - 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 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)): f = None - if self.registryValue('announceInTimeEditAndMark',channel=channel): - if self.registryValue('announceBotMark',channel=channel): + if self.registryValue('announceInTimeEditAndMark', channel=channel): + if self.registryValue('announceBotMark', channel=channel): f = self._logChan - i.submark(irc,channel,'b',best,"permanent ban %s" % ban,irc.prefix,self.getDb(irc.network),f,self) + i.submark(irc, channel, 'b', best, "permanent ban %s" % + ban, irc.prefix, self.getDb(irc.network), f, self) banned = True self.forceTickle = True break if not banned: - isMassJoin = self._isSomething(irc,channel,channel,'massJoin') + isMassJoin = self._isSomething( + irc, channel, channel, 'massJoin') if isMassJoin: - if self.registryValue('massJoinMode',channel=channel) == 'd': - if self.registryValue('useColorForAnnounces',channel=channel): - self._logChan(irc,channel,'[%s] massJoinMode applied' % ircutils.bold(channel)) + if self.registryValue('massJoinMode', channel=channel) == 'd': + if self.registryValue('useColorForAnnounces', channel=channel): + self._logChan( + irc, channel, '[%s] massJoinMode applied' % ircutils.bold(channel)) else: - self._logChan(irc,channel,'[%s] massJoinMode applied' % channel) + self._logChan( + irc, channel, '[%s] massJoinMode applied' % channel) else: - chan.action.enqueue(ircmsgs.IrcMsg('MODE %s %s' % (channel,self.registryValue('massJoinMode',channel=channel)))) + chan.action.enqueue(ircmsgs.IrcMsg('MODE %s %s' % ( + channel, self.registryValue('massJoinMode', channel=channel)))) + def unAttack(): if channel in list(irc.state.channels.keys()): - if self.registryValue('massJoinUnMode',channel=channel) == 'd': - if self.registryValue('useColorForAnnounces',channel=channel): - self._logChan(irc,channel,'[%s] massJoinUnMode applied' % ircutils.bold(channel)) + if self.registryValue('massJoinUnMode', channel=channel) == 'd': + if self.registryValue('useColorForAnnounces', channel=channel): + self._logChan( + irc, channel, '[%s] massJoinUnMode applied' % ircutils.bold(channel)) else: - self._logChan(irc,channel,'[%s] massJoinUnMode applied' % channel) + self._logChan( + irc, channel, '[%s] massJoinUnMode applied' % channel) else: - chan.action.enqueue(ircmsgs.IrcMsg('MODE %s %s' % (channel,self.registryValue('massJoinUnMode',channel=channel)))) - schedule.addEvent(unAttack,float(time.time()+self.registryValue('massJoinDuration',channel=channel))) + chan.action.enqueue(ircmsgs.IrcMsg('MODE %s %s' % ( + channel, self.registryValue('massJoinUnMode', channel=channel)))) + schedule.addEvent(unAttack, float( + time.time()+self.registryValue('massJoinDuration', channel=channel))) self.forceTickle = True - flag = ircdb.makeChannelCapability(channel,'clone') - if not banned and ircdb.checkCapability(msg.prefix,flag): - permit = self.registryValue('clonePermit',channel=channel) + flag = ircdb.makeChannelCapability(channel, 'clone') + if not banned and ircdb.checkCapability(msg.prefix, flag): + permit = self.registryValue( + 'clonePermit', channel=channel) if permit > -1: clones = [] for nick in list(irc.state.channels[channel].users): - n = self.getNick(irc,nick) - m = match(best,n,irc,self.registryValue('resolveIp')) + n = self.getNick(irc, nick) + m = match(best, n, irc, + self.registryValue('resolveIp')) if m: clones.append(nick) if len(clones) > permit: - if self.registryValue('cloneMode',channel=channel) == 'd': - self._logChan(irc,channel,'[%s] clones (%s) detected (%s)' % (ircutils.bold(channel),best,', '.join(clones))) + if self.registryValue('cloneMode', channel=channel) == 'd': + self._logChan(irc, channel, '[%s] clones (%s) detected (%s)' % ( + ircutils.bold(channel), best, ', '.join(clones))) else: - 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)) + 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.forceTickle = True self._tickle(irc) - def doPart (self,irc,msg): + def doPart(self, irc, msg): isBot = msg.prefix == irc.prefix channels = msg.args[0].split(',') i = self.getIrc(irc) - n = self.getNick(irc,msg.nick) + n = self.getNick(irc, msg.nick) n.setPrefix(msg.prefix) reason = '' if len(msg.args) == 2: @@ -3145,27 +3434,31 @@ class ChanTracker(callbacks.Plugin,plugins.ChannelDBHandler): del i.channels[channel] continue if ircutils.isChannel(channel) and channel in irc.state.channels: - bests = getBestPattern(n,irc,self.registryValue('useIpForGateway',channel=channel),self.registryValue('resolveIp')) + bests = getBestPattern(n, irc, self.registryValue( + 'useIpForGateway', channel=channel), self.registryValue('resolveIp')) best = bests[0] - if self.registryValue('useAccountBanIfPossible',channel=channel) and n.account: + if self.registryValue('useAccountBanIfPossible', channel=channel) and n.account: for p in bests: if p.startswith('$a:'): best = p break if len(reason): - if reason.startswith('requested by') and self.registryValue('announceKick',channel=channel): - if self.registryValue('useColorForAnnounces',channel=channel): - self._logChan(irc,channel,'[%s] %s has left (%s)' % (ircutils.bold(channel),ircutils.mircColor(msg.prefix,'light blue'),reason)) + if reason.startswith('requested by') and self.registryValue('announceKick', channel=channel): + if self.registryValue('useColorForAnnounces', channel=channel): + self._logChan(irc, channel, '[%s] %s has left (%s)' % (ircutils.bold( + channel), ircutils.mircColor(msg.prefix, 'light blue'), reason)) else: - self._logChan(irc,channel,'[%s] %s has left (%s)' % (channel,msg.prefix,reason)) - if self.registryValue('addKickMessageInComment',channel=channel): - chan = self.getChan(irc,channel) + self._logChan(irc, channel, '[%s] %s has left (%s)' % ( + channel, msg.prefix, reason)) + if self.registryValue('addKickMessageInComment', channel=channel): + chan = self.getChan(irc, channel) found = None - for mode in self.registryValue('modesToAsk',channel=channel): + for mode in self.registryValue('modesToAsk', channel=channel): items = chan.getItemsFor(mode) for k in items: item = items[k] - f = match(item.value,n,irc,self.registryValue('resolveIp')) + f = match(item.value, n, irc, + self.registryValue('resolveIp')) if f: found = item break @@ -3173,45 +3466,53 @@ class ChanTracker(callbacks.Plugin,plugins.ChannelDBHandler): break if found: f = None - if self.registryValue('announceBotMark',channel=channel): + if self.registryValue('announceBotMark', channel=channel): f = self._logChan - i.mark(irc,found.uid,reason,irc.prefix,self.getDb(irc.network),f,self) - n.addLog(channel,'has left [%s]' % (reason)) + i.mark(irc, found.uid, reason, irc.prefix, + self.getDb(irc.network), f, self) + n.addLog(channel, 'has left [%s]' % (reason)) else: - n.addLog(channel,'has left') + n.addLog(channel, 'has left') if not isBot: - chan = self.getChan(irc,channel) + chan = self.getChan(irc, channel) if msg.nick in chan.nicks: del chan.nicks[msg.nick] if msg.nick in irc.state.channels[channel].users: canRemove = False - if not self._isVip(irc,channel,n): - isCycle = self._isSomething(irc,channel,best,'cycle') + if not self._isVip(irc, channel, n): + isCycle = self._isSomething( + irc, channel, best, 'cycle') if isCycle: - isBad = self._isSomething(irc,channel,best,'bad') + isBad = self._isSomething( + irc, channel, best, 'bad') kind = None if isBad: kind = 'bad' else: kind = 'cycle' - mode = self.registryValue('%sMode' % kind,channel=channel) - duration = self.registryValue('%sDuration' % kind,channel=channel) - comment = self.registryValue('%sComment' % kind,channel=channel) - forward = self.registryValue('cycleForward',channel=channel) + mode = self.registryValue( + '%sMode' % kind, channel=channel) + duration = self.registryValue( + '%sDuration' % kind, channel=channel) + comment = self.registryValue( + '%sComment' % kind, channel=channel) + forward = self.registryValue( + 'cycleForward', channel=channel) if kind == 'cycle' and len(forward): best = best + '$' + forward - r = self.getIrcdMode(irc,mode,best) - self._act(irc,channel,r[0],r[1],duration,comment) + r = self.getIrcdMode(irc, mode, best) + self._act(irc, channel, + r[0], r[1], duration, comment) self.forceTickle = True if canRemove: - self._rmNick(irc,n) + self._rmNick(irc, n) self._tickle(irc) - def doKick (self,irc,msg): + def doKick(self, irc, msg): if len(msg.args) == 3: - (channel,target,reason) = msg.args + (channel, target, reason) = msg.args else: - (channel,target) = msg.args + (channel, target) = msg.args reason = '' isBot = target == irc.nick if isBot: @@ -3220,21 +3521,24 @@ class ChanTracker(callbacks.Plugin,plugins.ChannelDBHandler): del i.channels[channel] self._tickle(irc) return - n = self.getNick(irc,target) - n.addLog(channel,'kicked by %s (%s)' % (msg.prefix,reason)) - if self.registryValue('announceKick',channel=channel): - if self.registryValue('useColorForAnnounces',channel=channel): - self._logChan(irc,channel,'[%s] %s kicks %s (%s)' % (ircutils.bold(channel),msg.nick,ircutils.mircColor(n.prefix,'light blue'),reason)) + n = self.getNick(irc, target) + n.addLog(channel, 'kicked by %s (%s)' % (msg.prefix, reason)) + if self.registryValue('announceKick', channel=channel): + if self.registryValue('useColorForAnnounces', channel=channel): + self._logChan(irc, channel, '[%s] %s kicks %s (%s)' % (ircutils.bold( + channel), msg.nick, ircutils.mircColor(n.prefix, 'light blue'), reason)) else: - self._logChan(irc,channel,'[%s] %s kicks %s (%s)' % (channel,msg.nick,n.prefix,reason)) - if len(reason) and msg.prefix != irc.prefix and self.registryValue('addKickMessageInComment',channel=channel): - chan = self.getChan(irc,channel) + self._logChan(irc, channel, '[%s] %s kicks %s (%s)' % ( + channel, msg.nick, n.prefix, reason)) + if len(reason) and msg.prefix != irc.prefix and self.registryValue('addKickMessageInComment', channel=channel): + chan = self.getChan(irc, channel) found = None - for mode in self.registryValue('modesToAsk',channel=channel): + for mode in self.registryValue('modesToAsk', channel=channel): items = chan.getItemsFor(mode) for k in items: item = items[k] - f = match(item.value,n,irc,self.registryValue('resolveIp')) + f = match(item.value, n, irc, + self.registryValue('resolveIp')) if f: found = item break @@ -3242,40 +3546,43 @@ class ChanTracker(callbacks.Plugin,plugins.ChannelDBHandler): break if found: f = None - if self.registryValue('announceBotMark',channel=channel): + if self.registryValue('announceBotMark', channel=channel): f = self._logChan i = self.getIrc(irc) - i.mark(irc,found.uid,'kicked by %s (%s)' % (msg.nick,reason),irc.prefix,self.getDb(irc.network),f,self) + i.mark(irc, found.uid, 'kicked by %s (%s)' % ( + msg.nick, reason), irc.prefix, self.getDb(irc.network), f, self) if not isBot: - chan = self.getChan(irc,channel) + chan = self.getChan(irc, channel) if target in chan.nicks: del chan.nicks[target] self._tickle(irc) - def _rmNick (self,irc,n): + def _rmNick(self, irc, n): def nrm(): - patterns = getBestPattern(n,irc,self.registryValue('useIpForGateway'),self.registryValue('resolveIp')) + patterns = getBestPattern(n, irc, self.registryValue( + 'useIpForGateway'), self.registryValue('resolveIp')) i = self.getIrc(irc) if not len(patterns): return found = False - (nick,ident,hostmask) = ircutils.splitHostmask(n.prefix) + (nick, ident, hostmask) = ircutils.splitHostmask(n.prefix) for channel in irc.state.channels: if nick in irc.state.channels[channel].users: - found = True + found = True if not found: if nick in i.nicks: del i.nicks[nick] for channel in irc.state.channels: - bests = getBestPattern(n,irc,self.registryValue('useIpForGateway',channel=channel),self.registryValue('resolveIp')) + bests = getBestPattern(n, irc, self.registryValue( + 'useIpForGateway', channel=channel), self.registryValue('resolveIp')) best = bests[0] - if self.registryValue('useAccountBanIfPossible',channel=channel) and n.account: + if self.registryValue('useAccountBanIfPossible', channel=channel) and n.account: for p in bests: if p.startswith('$a:'): best = p break if channel in i.channels: - chan = self.getChan(irc,channel) + chan = self.getChan(irc, channel) if nick in chan.nicks: del chan.nicks[nick] if best in chan.repeatLogs: @@ -3283,200 +3590,227 @@ class ChanTracker(callbacks.Plugin,plugins.ChannelDBHandler): for k in chan.spam: if best in chan.spam[k]: del chan.spam[k][best] - schedule.addEvent(nrm,time.time()+self.registryValue('cycleLife')+10) + schedule.addEvent(nrm, time.time()+self.registryValue('cycleLife')+10) - def _split (self,irc,channel): - chan = self.getChan(irc,channel) + def _split(self, irc, channel): + chan = self.getChan(irc, channel) if not chan.netsplit: def f(L): - return applymodes(channel,L) + return applymodes(channel, L) chan.netsplit = True - def d (): + + def d(): chan.netsplit = False - unmodes = self.registryValue('netsplitUnmodes',channel=channel) + unmodes = self.registryValue( + 'netsplitUnmodes', channel=channel) if len(unmodes): if unmodes == 'd': - if self.registryValue('useColorForAnnounces',channel=channel): - self._logChan(irc,channel,'[%s] netsplitUnmodes applied' % ircutils.bold(channel)) + if self.registryValue('useColorForAnnounces', channel=channel): + self._logChan( + irc, channel, '[%s] netsplitUnmodes applied' % ircutils.bold(channel)) else: - self._logChan(irc,channel,'[%s] netsplitUnmodes applied' % channel) + self._logChan( + irc, channel, '[%s] netsplitUnmodes applied' % channel) else: - chan.action.enqueue(ircmsgs.IrcMsg('MODE %s %s' % (channel,unmodes))) + chan.action.enqueue(ircmsgs.IrcMsg( + 'MODE %s %s' % (channel, unmodes))) self.forceTickle = True self._tickle(irc) - schedule.addEvent(d,time.time()+self.registryValue('netsplitDuration',channel=channel)+1) - modes = self.registryValue('netsplitModes',channel=channel) + schedule.addEvent( + d, time.time()+self.registryValue('netsplitDuration', channel=channel)+1) + modes = self.registryValue('netsplitModes', channel=channel) if len(modes): if modes == 'd': - if self.registryValue('useColorForAnnounces',channel=channel): - self._logChan(irc,channel,'[%s] netsplitModes applied' % ircutils.bold(channel)) + if self.registryValue('useColorForAnnounces', channel=channel): + self._logChan( + irc, channel, '[%s] netsplitModes applied' % ircutils.bold(channel)) else: - self._logChan(irc,channel,'[%s] netsplitModes applied' % channel) + self._logChan( + irc, channel, '[%s] netsplitModes applied' % channel) else: - chan.action.enqueue(ircmsgs.IrcMsg('MODE %s %s' % (channel,modes))) + chan.action.enqueue(ircmsgs.IrcMsg( + 'MODE %s %s' % (channel, modes))) self.forceTickle = True self._tickle(irc) - def doQuit (self,irc,msg): + def doQuit(self, irc, msg): isBot = msg.nick == irc.nick reason = None if len(msg.args) == 1: reason = msg.args[0].lstrip().rstrip() if reason and reason == '*.net *.split': for channel in irc.state.channels: - chan = self.getChan(irc,channel) + chan = self.getChan(irc, channel) if msg.nick in chan.nicks and not chan.netsplit: - self._split(irc,channel) + self._split(irc, channel) removeNick = True if isBot: self._ircs = ircutils.IrcDict() return if not isBot: - n = self.getNick(irc,msg.nick) - bests = getBestPattern(n,irc,self.registryValue('useIpForGateway'),self.registryValue('resolveIp')) + n = self.getNick(irc, msg.nick) + bests = getBestPattern(n, irc, self.registryValue( + 'useIpForGateway'), self.registryValue('resolveIp')) best = None if len(bests): best = bests[0] if not best: return if reason: - n.addLog('ALL','has quit [%s]' % reason) + n.addLog('ALL', 'has quit [%s]' % reason) else: - n.addLog('ALL','has quit') - #,'Excess Flood','Max SendQ exceeded' + n.addLog('ALL', 'has quit') + # ,'Excess Flood','Max SendQ exceeded' if reason and reason in ['Changing host']: # keeping this nick, may trigger cycle check removeNick = False elif reason and reason.startswith('Killed (') or reason.startswith('K-Lined'): if not 'Nickname regained by services' in reason and not 'NickServ (GHOST command used by ' in reason: for channel in irc.state.channels: - chan = self.getChan(irc,channel) + chan = self.getChan(irc, channel) if msg.nick in chan.nicks: - if self.registryValue('announceKick',channel=channel): - if self.registryValue('useColorForAnnounces',channel=channel): - self._logChan(irc,channel,'[%s] %s has quit (%s)' % (ircutils.bold(channel),ircutils.mircColor(msg.prefix,'light blue'),ircutils.mircColor(reason,'red'))) + if self.registryValue('announceKick', channel=channel): + if self.registryValue('useColorForAnnounces', channel=channel): + self._logChan(irc, channel, '[%s] %s has quit (%s)' % (ircutils.bold( + channel), ircutils.mircColor(msg.prefix, 'light blue'), ircutils.mircColor(reason, 'red'))) else: - self._logChan(irc,channel,'[%s] %s has quit (%s)' % (channel,msg.prefix,reason)) + self._logChan(irc, channel, '[%s] %s has quit (%s)' % ( + channel, msg.prefix, reason)) for channel in irc.state.channels: - chan = self.getChan(irc,channel) + chan = self.getChan(irc, channel) if msg.nick in chan.nicks: - if not self._isVip(irc,channel,n): - bests = getBestPattern(n,irc,self.registryValue('useIpForGateway',channel=channel),self.registryValue('resolveIp')) + if not self._isVip(irc, channel, n): + bests = getBestPattern(n, irc, self.registryValue( + 'useIpForGateway', channel=channel), self.registryValue('resolveIp')) best = bests[0] - if self.registryValue('useAccountBanIfPossible',channel=channel) and n.account: + if self.registryValue('useAccountBanIfPossible', channel=channel) and n.account: for p in bests: if p.startswith('$a:'): best = p break - isCycle = self._isSomething(irc,channel,best,'cycle') + isCycle = self._isSomething( + irc, channel, best, 'cycle') if isCycle: - isBad = self._isSomething(irc,channel,best,'bad') + isBad = self._isSomething( + irc, channel, best, 'bad') kind = None if isBad: kind = 'bad' else: kind = 'cycle' - mode = self.registryValue('%sMode' % kind,channel=channel) - duration = self.registryValue('%sDuration' % kind,channel=channel) - comment = self.registryValue('%sComment' % kind,channel=channel) - forward = self.registryValue('cycleForward',channel=channel) + mode = self.registryValue( + '%sMode' % kind, channel=channel) + duration = self.registryValue( + '%sDuration' % kind, channel=channel) + comment = self.registryValue( + '%sComment' % kind, channel=channel) + forward = self.registryValue( + 'cycleForward', channel=channel) if kind == 'cycle' and len(forward): best = best + '$' + forward - r = self.getIrcdMode(irc,mode,best) - self._act(irc,channel,r[0],r[1],duration,comment) + r = self.getIrcdMode(irc, mode, best) + self._act(irc, channel, + r[0], r[1], duration, comment) self.forceTickle = True if removeNick: i = self.getIrc(irc) if msg.nick in i.nicks: n = i.nicks[msg.nick] - self._rmNick(irc,n) + self._rmNick(irc, n) self._tickle(irc) - def doNick (self,irc,msg): + def doNick(self, irc, msg): oldNick = msg.prefix.split('!')[0] newNick = msg.args[0] - i = self.getIrc (irc) + i = self.getIrc(irc) n = None if oldNick in i.nicks: - n = self.getNick(irc,oldNick) + n = self.getNick(irc, oldNick) del i.nicks[oldNick] if n.prefix: - prefixNew = '%s!%s' % (newNick,n.prefix.split('!')[1]) + prefixNew = '%s!%s' % (newNick, n.prefix.split('!')[1]) n.setPrefix(prefixNew) i.nicks[newNick] = n - n = self.getNick(irc,newNick) - n.addLog('ALL','%s is now known as %s' % (oldNick,newNick)) + n = self.getNick(irc, newNick) + n.addLog('ALL', '%s is now known as %s' % (oldNick, newNick)) best = None - patterns = getBestPattern(n,irc,self.registryValue('useIpForGateway'),self.registryValue('resolveIp')) + patterns = getBestPattern(n, irc, self.registryValue( + 'useIpForGateway'), self.registryValue('resolveIp')) if len(patterns): best = patterns[0] if not best: return for channel in irc.state.channels: - bests = getBestPattern(n,irc,self.registryValue('useIpForGateway',channel=channel),self.registryValue('resolveIp')) + bests = getBestPattern(n, irc, self.registryValue( + 'useIpForGateway', channel=channel), self.registryValue('resolveIp')) best = bests[0] - if self.registryValue('useAccountBanIfPossible',channel=channel) and n.account: + if self.registryValue('useAccountBanIfPossible', channel=channel) and n.account: for p in bests: if p.startswith('$a:'): best = p break if newNick in irc.state.channels[channel].users: - chan = self.getChan(irc,channel) + chan = self.getChan(irc, channel) if oldNick in chan.nicks: del chan.nicks[oldNick] chan.nicks[msg.nick] = True - if self._isVip(irc,channel,n): + if self._isVip(irc, channel, n): continue - isNick = self._isSomething(irc,channel,best,'nick') + isNick = self._isSomething(irc, channel, best, 'nick') if isNick: - isBad = self._isBad(irc,channel,best) + isBad = self._isBad(irc, channel, best) kind = None if isBad: kind = 'bad' else: kind = 'nick' - mode = self.registryValue('%sMode' % kind,channel=channel) + mode = self.registryValue( + '%sMode' % kind, channel=channel) if len(mode) > 1: mode = mode[0] - duration = self.registryValue('%sDuration' % kind,channel=channel) - comment = self.registryValue('%sComment' % kind,channel=channel) - r = self.getIrcdMode(irc,mode,best) - self._act(irc,channel,r[0],r[1],duration,comment) + duration = self.registryValue( + '%sDuration' % kind, channel=channel) + comment = self.registryValue( + '%sComment' % kind, channel=channel) + r = self.getIrcdMode(irc, mode, best) + self._act(irc, channel, r[0], r[1], duration, comment) self.forceTickle = True self._tickle(irc) - def doCap (self,irc,msg): + def doCap(self, irc, msg): self._tickle(irc) - def doAccount (self,irc,msg): + def doAccount(self, irc, msg): # update nick's model n = None if ircutils.isUserHostmask(msg.prefix): nick = ircutils.nickFromHostmask(msg.prefix) - n = self.getNick(irc,nick) + n = self.getNick(irc, nick) acc = msg.args[0] old = n.account if acc == '*': acc = None n.setAccount(acc) - n.addLog('ALL','%s is now identified as %s' % (old,acc)) + n.addLog('ALL', '%s is now identified as %s' % (old, acc)) else: return if n and n.account and n.ip: i = self.getIrc(irc) for channel in irc.state.channels: - if self.registryValue('checkEvade',channel=channel): + if self.registryValue('checkEvade', channel=channel): if nick in irc.state.channels[channel].users: - modes = self.registryValue('modesToAsk',channel=channel) + modes = self.registryValue( + 'modesToAsk', channel=channel) found = False - chan = self.getChan(irc,channel) + chan = self.getChan(irc, channel) for mode in modes: if mode == 'b': items = chan.getItemsFor(mode) for item in items: # only check against ~a:,$a: bans if items[item].value.startswith(self.getIrcdExtbansPrefix(irc)) and items[item].value[1] == 'a': - f = match(items[item].value,n,irc,self.registryValue('resolveIp')) + f = match( + items[item].value, n, irc, self.registryValue('resolveIp')) if f: found = items[item] if found: @@ -3487,17 +3821,20 @@ class ChanTracker(callbacks.Plugin,plugins.ChannelDBHandler): duration = -1 if found.expire and found.expire != found.when: duration = int(found.expire-time.time()) - r = self.getIrcdMode(irc,found.mode,getBestPattern(n,irc,self.registryValue('useIpForGateway',channel=channel),self.registryValue('resolveIp'))[0]) - self._act (irc,channel,r[0],r[1],duration,'evade of [#%s +%s %s]' % (found.uid,found.mode,found.value)) + r = self.getIrcdMode(irc, found.mode, getBestPattern(n, irc, self.registryValue( + 'useIpForGateway', channel=channel), self.registryValue('resolveIp'))[0]) + self._act(irc, channel, r[0], r[1], duration, 'evade of [#%s +%s %s]' % ( + found.uid, found.mode, found.value)) f = None - if self.registryValue('announceBotMark',channel=found.channel): + if self.registryValue('announceBotMark', channel=found.channel): f = self._logChan - i.mark(irc,found.uid,'evade with %s --> %s' % (msg.prefix,getBestPattern(n,irc,self.registryValue('useIpForGateway',channel=channel),self.registryValue('resolveIp'))[0]),irc.prefix,self.getDb(irc.network),f,self) + i.mark(irc, found.uid, 'evade with %s --> %s' % (msg.prefix, getBestPattern(n, irc, self.registryValue( + 'useIpForGateway', channel=channel), self.registryValue('resolveIp'))[0]), irc.prefix, self.getDb(irc.network), f, self) self.forceTickle = True self._tickle(irc) - def doNotice (self,irc,msg): + def doNotice(self, irc, msg): (targets, text) = msg.args if not ircutils.isUserHostmask(irc.prefix): return @@ -3506,10 +3843,11 @@ class ChanTracker(callbacks.Plugin,plugins.ChannelDBHandler): else: if msg.nick == irc.nick: return - n = self.getNick(irc,msg.nick) + n = self.getNick(irc, msg.nick) if 'account' in msg.server_tags: n.setAccount(msg.server_tags['account']) - patterns = getBestPattern(n,irc,self.registryValue('useIpForGateway'),self.registryValue('resolveIp')) + patterns = getBestPattern(n, irc, self.registryValue( + 'useIpForGateway'), self.registryValue('resolveIp')) best = False if len(patterns): best = patterns[0] @@ -3517,57 +3855,66 @@ class ChanTracker(callbacks.Plugin,plugins.ChannelDBHandler): return for channel in targets.split(','): if channel.startswith('@'): - channel = channel.replace('@','',1) + channel = channel.replace('@', '', 1) if channel.startswith('+'): - channel = channel.replace('+','',1) + channel = channel.replace('+', '', 1) if irc.isChannel(channel) and channel in irc.state.channels: - bests = getBestPattern(n,irc,self.registryValue('useIpForGateway',channel=channel),self.registryValue('resolveIp')) + bests = getBestPattern(n, irc, self.registryValue( + 'useIpForGateway', channel=channel), self.registryValue('resolveIp')) best = bests[0] - if self.registryValue('useAccountBanIfPossible',channel=channel) and n.account: + if self.registryValue('useAccountBanIfPossible', channel=channel) and n.account: for p in bests: if p.startswith('$a:'): best = p break - chan = self.getChan(irc,channel) - n.addLog(channel,'NOTICE | %s' % text) - isVip = self._isVip(irc,channel,n) + chan = self.getChan(irc, channel) + n.addLog(channel, 'NOTICE | %s' % text) + isVip = self._isVip(irc, channel, n) if not isVip: - isNotice = self._isSomething(irc,channel,best,'notice') + isNotice = self._isSomething( + irc, channel, best, 'notice') isBad = False if isNotice: - isBad = self._isSomething(irc,channel,best,'bad') + isBad = self._isSomething( + irc, channel, best, 'bad') if isNotice or isBad: kind = None if isBad: kind = 'bad' else: kind = 'notice' - mode = self.registryValue('%sMode' % kind,channel=channel) - duration = self.registryValue('%sDuration' % kind,channel=channel) - comment = self.registryValue('%sComment' % kind,channel=channel) - r = self.getIrcdMode(irc,mode,best) - self._act(irc,channel,r[0],r[1],duration,comment) + mode = self.registryValue( + '%sMode' % kind, channel=channel) + duration = self.registryValue( + '%sDuration' % kind, channel=channel) + comment = self.registryValue( + '%sComment' % kind, channel=channel) + r = self.getIrcdMode(irc, mode, best) + self._act(irc, channel, + r[0], r[1], duration, comment) self.forceTickle = True - if self.registryValue('announceNotice',channel=channel): + if self.registryValue('announceNotice', channel=channel): if not chan.isWrong(best): - if self.registryValue('useColorForAnnounces',channel=channel): - self._logChan(irc,channel,'[%s] %s notice "%s"' % (ircutils.bold(channel),ircutils.mircColor(msg.prefix,'light blue'),text)) + if self.registryValue('useColorForAnnounces', channel=channel): + self._logChan(irc, channel, '[%s] %s notice "%s"' % (ircutils.bold( + channel), ircutils.mircColor(msg.prefix, 'light blue'), text)) else: - self._logChan(irc,channel,'[%s] %s notice "%s"' % (channel,msg.prefix,text)) + self._logChan(irc, channel, '[%s] %s notice "%s"' % ( + channel, msg.prefix, text)) self._tickle(irc) - def _schedule(self,irc,end): + def _schedule(self, irc, end): if end > time.time(): def do(): self.forceTickle = True self._tickle(irc) - schedule.addEvent(do,end) + schedule.addEvent(do, end) else: self.forceTickle = True self._tickle(irc) - def _isVip (self,irc,channel,n): + def _isVip(self, irc, channel, n): if n.prefix == irc.prefix: return True if ircdb.checkCapability(n.prefix, 'trusted'): @@ -3579,7 +3926,7 @@ class ChanTracker(callbacks.Plugin,plugins.ChannelDBHandler): return True return False - def doPrivmsg (self,irc,msg): + def doPrivmsg(self, irc, msg): if msg.nick == irc.nick: self._tickle(irc) return @@ -3596,8 +3943,9 @@ class ChanTracker(callbacks.Plugin,plugins.ChannelDBHandler): patterns = None i = self.getIrc(irc) if ircutils.isUserHostmask(msg.prefix): - n = self.getNick(irc,msg.nick) - patterns = getBestPattern(n,irc,self.registryValue('useIpForGateway'),self.registryValue('resolveIp')) + n = self.getNick(irc, msg.nick) + patterns = getBestPattern(n, irc, self.registryValue( + 'useIpForGateway'), self.registryValue('resolveIp')) if len(patterns): best = patterns[0] # if it fails here stacktrace @@ -3609,53 +3957,54 @@ class ChanTracker(callbacks.Plugin,plugins.ChannelDBHandler): n.setAccount(msg.server_tags['account']) for channel in recipients.split(','): if channel.startswith('@'): - channel = channel.replace('@','',1) + channel = channel.replace('@', '', 1) if channel.startswith('+'): - channel = channel.replace('+','',1) + channel = channel.replace('+', '', 1) if irc.isChannel(channel) and channel in irc.state.channels: - bests = getBestPattern(n,irc,self.registryValue('useIpForGateway',channel=channel),self.registryValue('resolveIp')) + bests = getBestPattern(n, irc, self.registryValue( + 'useIpForGateway', channel=channel), self.registryValue('resolveIp')) best = bests[0] - if self.registryValue('useAccountBanIfPossible',channel=channel) and n.account: + if self.registryValue('useAccountBanIfPossible', channel=channel) and n.account: for p in bests: if p.startswith('$a:'): best = p break - chan = self.getChan(irc,channel) + chan = self.getChan(irc, channel) message = text if isCtcpMsg and not isAction: message = 'CTCP | %s' % text elif isAction: message = '- %s -' % text - n.addLog(channel,message) + n.addLog(channel, message) # protection features - isVip = self._isVip(irc,channel,n) + isVip = self._isVip(irc, channel, n) if not isVip: isCtcp = False if isCtcpMsg and not isAction: - isCtcp = self._isSomething(irc,channel,best,'ctcp') - flag = ircdb.makeChannelCapability(channel,'flood') + isCtcp = self._isSomething(irc, channel, best, 'ctcp') + flag = ircdb.makeChannelCapability(channel, 'flood') isFlood = False - if ircdb.checkCapability(msg.prefix,flag): - isFlood = self._isFlood(irc,channel,best) - flag = ircdb.makeChannelCapability(channel,'lowFlood') + if ircdb.checkCapability(msg.prefix, flag): + isFlood = self._isFlood(irc, channel, best) + flag = ircdb.makeChannelCapability(channel, 'lowFlood') isLowFlood = False - if ircdb.checkCapability(msg.prefix,flag): - isLowFlood = self._isLowFlood(irc,channel,best) - flag = ircdb.makeChannelCapability(channel,'repeat') + if ircdb.checkCapability(msg.prefix, flag): + isLowFlood = self._isLowFlood(irc, channel, best) + flag = ircdb.makeChannelCapability(channel, 'repeat') isRepeat = False - if ircdb.checkCapability(msg.prefix,flag): - isRepeat = self._isRepeat(irc,channel,best,text) - flag = ircdb.makeChannelCapability(channel,'hilight') + if ircdb.checkCapability(msg.prefix, flag): + isRepeat = self._isRepeat(irc, channel, best, text) + flag = ircdb.makeChannelCapability(channel, 'hilight') isHilight = False - if ircdb.checkCapability(msg.prefix,flag): - isHilight = self._isHilight(irc,channel,best,text) - flag = ircdb.makeChannelCapability(channel,'cap') + if ircdb.checkCapability(msg.prefix, flag): + isHilight = self._isHilight(irc, channel, best, text) + flag = ircdb.makeChannelCapability(channel, 'cap') isCap = False - if ircdb.checkCapability(msg.prefix,flag): - isCap = self._isCap(irc,channel,best,text) - flag = ircdb.makeChannelCapability(channel,'pattern') + if ircdb.checkCapability(msg.prefix, flag): + isCap = self._isCap(irc, channel, best, text) + flag = ircdb.makeChannelCapability(channel, 'pattern') isPattern = False - if ircdb.checkCapability(msg.prefix,flag): + if ircdb.checkCapability(msg.prefix, flag): for p in chan.patterns: pattern = chan.patterns[p] if pattern.match(text): @@ -3668,18 +4017,21 @@ class ChanTracker(callbacks.Plugin,plugins.ChannelDBHandler): if not prop in chan.spam: chan.spam[prop] = {} if not key in chan.spam[prop] or chan.spam[prop][key].timeout != pattern.life: - chan.spam[prop][key] = utils.structures.TimeoutQueue(pattern.life) + chan.spam[prop][key] = utils.structures.TimeoutQueue( + pattern.life) chan.spam[prop][key].enqueue(key) if len(chan.spam[prop][key]) > pattern.limit: chan.spam[prop][key].reset() isPattern = pattern break if isPattern: - r = self.getIrcdMode(irc,isPattern.mode,best) - self._act(irc,channel,r[0],r[1],isPattern.duration,'matches #%s' % isPattern.uid) - isBad = self._isBad(irc,channel,best) - self.forceTickle = True - chan.countpattern(isPattern.uid,self.getDb(irc.network)) + r = self.getIrcdMode(irc, isPattern.mode, best) + self._act( + irc, channel, r[0], r[1], isPattern.duration, 'matches #%s' % isPattern.uid) + isBad = self._isBad(irc, channel, best) + self.forceTickle = True + chan.countpattern( + isPattern.uid, self.getDb(irc.network)) isTemporaryPattern = False if not isPattern and not isRepeat: key = 'pattern%s' % channel @@ -3690,111 +4042,135 @@ class ChanTracker(callbacks.Plugin,plugins.ChannelDBHandler): isTemporaryPattern = pattern break if isTemporaryPattern: - chan.repeatLogs[key].enqueue(isTemporaryPattern) - r = self.getIrcdMode(irc,self.registryValue('repeatMode',channel=channel),best) - self._act(irc,channel,r[0],r[1],self.registryValue('repeatDuration',channel=channel),'') # hidden reason matches "%s"' % isTemporaryPattern - isBad = self._isBad(irc,channel,best) + chan.repeatLogs[key].enqueue( + isTemporaryPattern) + r = self.getIrcdMode(irc, self.registryValue( + 'repeatMode', channel=channel), best) + # hidden reason matches "%s"' % isTemporaryPattern + self._act(irc, channel, r[0], r[1], self.registryValue( + 'repeatDuration', channel=channel), '') + isBad = self._isBad(irc, channel, best) self.forceTickle = True elif not isPattern and not isTemporaryPattern: if isFlood or isHilight or isRepeat or isCap or isCtcp or isLowFlood: - isBad = self._isBad(irc,channel,best) + isBad = self._isBad(irc, channel, best) kind = None duration = 0 if isBad: kind = 'bad' - duration = self.registryValue('badDuration',channel=channel) + duration = self.registryValue( + 'badDuration', channel=channel) else: if isFlood: - d = self.registryValue('floodDuration',channel=channel) + d = self.registryValue( + 'floodDuration', channel=channel) if d > duration: kind = 'flood' duration = d if isLowFlood: - d = self.registryValue('lowFloodDuration',channel=channel) + d = self.registryValue( + 'lowFloodDuration', channel=channel) if d > duration: kind = 'lowFlood' duration = d if isRepeat: - d = self.registryValue('repeatDuration',channel=channel) + d = self.registryValue( + 'repeatDuration', channel=channel) if d > duration: kind = 'repeat' duration = d if isHilight: - d = self.registryValue('hilightDuration',channel=channel) + d = self.registryValue( + 'hilightDuration', channel=channel) if d > duration: kind = 'hilight' duration = d if isCap: - d = self.registryValue('capDuration',channel=channel) + d = self.registryValue( + 'capDuration', channel=channel) if d > duration: kind = 'cap' duration = d if isCtcp: - d = self.registryValue('ctcpDuration',channel=channel) + d = self.registryValue( + 'ctcpDuration', channel=channel) if d > duration: kind = 'ctcp' duration = d - mode = self.registryValue('%sMode' % kind,channel=channel) + mode = self.registryValue( + '%sMode' % kind, channel=channel) if len(mode) > 1: mode = mode[0] - duration = self.registryValue('%sDuration' % kind,channel=channel) - comment = self.registryValue('%sComment' % kind,channel=channel) - r = self.getIrcdMode(irc,mode,best) - self._act(irc,channel,r[0],r[1],duration,comment) + duration = self.registryValue( + '%sDuration' % kind, channel=channel) + comment = self.registryValue( + '%sComment' % kind, channel=channel) + r = self.getIrcdMode(irc, mode, best) + self._act(irc, channel, + r[0], r[1], duration, comment) self.forceTickle = True if not chan.isWrong(best): # prevent the bot to flood logChannel with bad user craps - if self.registryValue('announceCtcp',channel=channel) and isCtcpMsg and not isAction: - if self.registryValue('useColorForAnnounces',channel=channel): - self._logChan(irc,channel,'[%s] %s ctcps "%s"' % (ircutils.bold(channel),ircutils.mircColor(msg.prefix,'light blue'),text)) + if self.registryValue('announceCtcp', channel=channel) and isCtcpMsg and not isAction: + if self.registryValue('useColorForAnnounces', channel=channel): + self._logChan(irc, channel, '[%s] %s ctcps "%s"' % (ircutils.bold( + channel), ircutils.mircColor(msg.prefix, 'light blue'), text)) else: - self._logChan(irc,channel,'[%s] %s ctcps "%s"' % (channel,msg.prefix,text)) + self._logChan(irc, channel, '[%s] %s ctcps "%s"' % ( + channel, msg.prefix, text)) self.forceTickle = True else: - if self.registryValue('announceOthers',channel=channel) and irc.state.channels[channel].isHalfopPlus(irc.nick) and 'z' in irc.state.channels[channel].modes: + if self.registryValue('announceOthers', channel=channel) and irc.state.channels[channel].isHalfopPlus(irc.nick) and 'z' in irc.state.channels[channel].modes: message = None if 'm' in irc.state.channels[channel].modes: if not msg.nick in irc.state.channels[channel].voices and not irc.state.channels[channel].isHalfopPlus(msg.nick): - if self.registryValue('useColorForAnnounces',channel=channel): - message = '[%s] [+m] <%s> %s' % (ircutils.bold(channel),ircutils.mircColor(msg.prefix,'light blue'),text) + if self.registryValue('useColorForAnnounces', channel=channel): + message = '[%s] [+m] <%s> %s' % (ircutils.bold( + channel), ircutils.mircColor(msg.prefix, 'light blue'), text) else: - message = '[%s] [+m] <%s> %s' % (channel,msg.prefix,text) + message = '[%s] [+m] <%s> %s' % ( + channel, msg.prefix, text) if not message: if not msg.nick in irc.state.channels[channel].voices and not irc.state.channels[channel].isHalfopPlus(msg.nick): - modes = self.registryValue('modesToAsk',channel=channel) + modes = self.registryValue( + 'modesToAsk', channel=channel) found = False for mode in modes: items = chan.getItemsFor(mode) for item in items: - f = match(items[item].value,n,irc,self.registryValue('resolveIp')) + f = match( + items[item].value, n, irc, self.registryValue('resolveIp')) if f: - found = [items[item],f] + found = [items[item], f] if found: break if found: break if found: - if self.registryValue('useColorForAnnounces',channel=channel): - message = '[%s] [#%s +%s %s] <%s> %s' % (ircutils.bold(channel),found[0].uid,ircutils.mircColor(found[0].mode,'red'),ircutils.mircColor(found[0].value,'light blue'),msg.nick,text) + if self.registryValue('useColorForAnnounces', channel=channel): + message = '[%s] [#%s +%s %s] <%s> %s' % (ircutils.bold(channel), found[0].uid, ircutils.mircColor( + found[0].mode, 'red'), ircutils.mircColor(found[0].value, 'light blue'), msg.nick, text) else: - message = '[%s] [#%s +%s %s] <%s> %s' % (channel,found[0].uid,found[0].mode,found[0].value,msg.nick,text) + message = '[%s] [#%s +%s %s] <%s> %s' % ( + channel, found[0].uid, found[0].mode, found[0].value, msg.nick, text) if message: - self._logChan(irc,channel,message) + self._logChan(irc, channel, message) elif irc.nick == channel: - found = self.hasAskedItems(irc,msg.prefix,True) + found = self.hasAskedItems(irc, msg.prefix, True) if found: - tokens = callbacks.tokenize('ChanTracker editAndMark %s %s' % (found[0],text)) + tokens = callbacks.tokenize( + 'ChanTracker editAndMark %s %s' % (found[0], text)) msg.command = 'PRIVMSG' msg.prefix = msg.prefix self.Proxy(irc.irc, msg, tokens) - found = self.hasAskedItems(irc,msg.prefix,False) + found = self.hasAskedItems(irc, msg.prefix, False) if found: i.askedItems[msg.prefix][found[0]][6] = True - i.lowQueue.enqueue(ircmsgs.privmsg(msg.nick,found[5])) + i.lowQueue.enqueue(ircmsgs.privmsg(msg.nick, found[5])) self.forceTickle = True self._tickle(irc) - def hasAskedItems(self,irc,prefix,remove): + def hasAskedItems(self, irc, prefix, remove): i = self.getIrc(irc) if prefix in i.askedItems: found = None @@ -3802,14 +4178,14 @@ class ChanTracker(callbacks.Plugin,plugins.ChannelDBHandler): if not found or item < found[0] and not found[6]: found = i.askedItems[prefix][item] if found: - chan = self.getChan(irc,found[3]) + chan = self.getChan(irc, found[3]) items = chan.getItemsFor(found[1]) active = None if len(items): for item in items: item = items[item] if item.uid == found[0]: - active = item; + active = item break if remove: del i.askedItems[prefix][found[0]] @@ -3819,7 +4195,7 @@ class ChanTracker(callbacks.Plugin,plugins.ChannelDBHandler): return found return None - def addToAsked (self,irc,prefix,data,nick): + def addToAsked(self, irc, prefix, data, nick): toAsk = False endTime = time.time() + 180 i = self.getIrc(irc) @@ -3829,87 +4205,95 @@ class ChanTracker(callbacks.Plugin,plugins.ChannelDBHandler): i.askedItems[prefix][data[0]] = data if toAsk: i.askedItems[prefix][data[0]][6] = True - i.lowQueue.enqueue(ircmsgs.privmsg(nick,data[5])) + i.lowQueue.enqueue(ircmsgs.privmsg(nick, data[5])) self.forceTickle = True + def unAsk(): if prefix in i.askedItems: if data[0] in i.askedItems[prefix]: del i.askedItems[prefix][data[0]] if not len(list(i.askedItems[prefix])): del i.askedItems[prefix] - found = self.hasAskedItems(irc,prefix,False) + found = self.hasAskedItems(irc, prefix, False) if found: i.askedItems[prefix][found[0]][6] = True - i.lowQueue.enqueue(ircmsgs.privmsg(nick,found[5])) + i.lowQueue.enqueue(ircmsgs.privmsg(nick, found[5])) self.forceTickle - schedule.addEvent(unAsk,time.time() + 300 * len(list(i.askedItems[prefix]))) + schedule.addEvent(unAsk, time.time() + 300 * + len(list(i.askedItems[prefix]))) def doTopic(self, irc, msg): if len(msg.args) == 1: return if ircutils.isUserHostmask(msg.prefix): - n = self.getNick(irc,msg.nick) + n = self.getNick(irc, msg.nick) channel = msg.args[0] if 'account' in msg.server_tags: n.setAccount(msg.server_tags['account']) if channel in irc.state.channels: if n: - n.addLog(channel,'sets topic "%s"' % msg.args[1]) - if self.registryValue('announceTopic',channel=channel): - if self.registryValue('useColorForAnnounces',channel=channel): - self._logChan(irc,channel,'[%s] %s sets topic "%s"' % (ircutils.bold(channel),ircutils.mircColor(msg.prefix,'light blue'),msg.args[1])) + n.addLog(channel, 'sets topic "%s"' % msg.args[1]) + if self.registryValue('announceTopic', channel=channel): + if self.registryValue('useColorForAnnounces', channel=channel): + self._logChan(irc, channel, '[%s] %s sets topic "%s"' % (ircutils.bold( + channel), ircutils.mircColor(msg.prefix, 'light blue'), msg.args[1])) else: - self._logChan(irc,channel,'[%s] %s sets topic "%s"' % (channel,msg.prefix,msg.args[1])) + self._logChan(irc, channel, '[%s] %s sets topic "%s"' % ( + channel, msg.prefix, msg.args[1])) self.forceTickle = True self._tickle(irc) - def unOp (self,irc,channel): + def unOp(self, irc, channel): # remove irc.nick from op, if nothing pending if channel in irc.state.channels: i = self.getIrc(irc) - chan = self.getChan(irc,channel) + chan = self.getChan(irc, channel) if chan.deopPending: return + def unOpBot(): if channel in irc.state.channels: if not len(i.queue) and not len(chan.queue): - if irc.state.channels[channel].isHalfopPlus(irc.nick) and not self.registryValue('keepOp',channel=channel): + if irc.state.channels[channel].isHalfopPlus(irc.nick) and not self.registryValue('keepOp', channel=channel): if not chan.deopAsked: chan.deopPending = False chan.deopAsked = True - irc.queueMsg(ircmsgs.IrcMsg('MODE %s -o %s' % (channel,irc.nick))) + irc.queueMsg(ircmsgs.IrcMsg( + 'MODE %s -o %s' % (channel, irc.nick))) # little trick here, tickle before setting deopFlag self.forceTickle = True self._tickle(irc) else: # reask for deop - if irc.state.channels[channel].isHalfopPlus(irc.nick) and not self.registryValue('keepOp',channel=channel) and not chan.deopAsked: + if irc.state.channels[channel].isHalfopPlus(irc.nick) and not self.registryValue('keepOp', channel=channel) and not chan.deopAsked: self.deopPending = False - self.unOp(irc,channel) + self.unOp(irc, channel) chan.deopPending = True - schedule.addEvent(unOpBot,float(time.time()+10)) + schedule.addEvent(unOpBot, float(time.time()+10)) - def hasExtendedSharedBan (self,irc,fromChannel,target,mode): + def hasExtendedSharedBan(self, irc, fromChannel, target, mode): # todo add support for others ircd if supported, currently only freenode - b = '%sj:%s' % (self.getIrcdExtbansPrefix(irc),fromChannel) + b = '%sj:%s' % (self.getIrcdExtbansPrefix(irc), fromChannel) kicks = [] for channel in irc.state.channels: - if b in irc.state.channels[channel].bans and mode in self.registryValue('kickMode',channel=channel) and not target.startswith('m:'): + if b in irc.state.channels[channel].bans and mode in self.registryValue('kickMode', channel=channel) and not target.startswith('m:'): L = [] for nick in list(irc.state.channels[channel].users): L.append(nick) for nick in L: - if not self._isVip(irc,channel,self.getNick(irc,nick)): - n = self.getNick(irc,nick) - m = match(target,n,irc,self.registryValue('resolveIp')) + if not self._isVip(irc, channel, self.getNick(irc, nick)): + n = self.getNick(irc, nick) + m = match(target, n, irc, + self.registryValue('resolveIp')) if m: - if len(kicks) < self.registryValue('kickMax',channel=channel): + if len(kicks) < self.registryValue('kickMax', channel=channel): if nick != irc.nick: - kicks.append([nick,channel]) + kicks.append([nick, channel]) if len(kicks): for kick in kicks: - chan = self.getChan(irc,kick[1]) - chan.action.enqueue(ircmsgs.kick(kick[1],kick[0],random.choice(self.registryValue('kickMessage',channel=kick[1])))) + chan = self.getChan(irc, kick[1]) + chan.action.enqueue(ircmsgs.kick(kick[1], kick[0], random.choice( + self.registryValue('kickMessage', channel=kick[1])))) self.forceTickle = True def doMode(self, irc, msg): @@ -3919,7 +4303,7 @@ class ChanTracker(callbacks.Plugin,plugins.ChannelDBHandler): i = self.getIrc(irc) if ircutils.isUserHostmask(msg.prefix): # prevent server.netsplit to create a Nick - n = self.getNick(irc,msg.nick) + n = self.getNick(irc, msg.nick) n.setPrefix(msg.prefix) if 'account' in msg.server_tags: n.setAccount(msg.server_tags['account']) @@ -3931,24 +4315,29 @@ class ChanTracker(callbacks.Plugin,plugins.ChannelDBHandler): tolift = [] if irc.isChannel(channel) and msg.args[1:] and channel in irc.state.channels: modes = ircutils.separateModes(msg.args[1:]) - chan = self.getChan(irc,channel) + chan = self.getChan(irc, channel) msgs = [] - announces = list(self.registryValue('announceModes',channel=channel)) - overexpire = self.registryValue('autoExpire',channel=channel) + announces = list(self.registryValue( + 'announceModes', channel=channel)) + overexpire = self.registryValue('autoExpire', channel=channel) for change in modes: - (mode,value) = change + (mode, value) = change m = mode[1:] if value: value = str(value).lstrip().rstrip() item = None if '+' in mode: - if m in self.registryValue('modesToAskWhenOpped',channel=channel) or m in self.registryValue('modesToAsk',channel=channel): - item = chan.addItem(m,value,msg.prefix,now,self.getDb(irc.network),self.registryValue('trackAffected',channel=channel),self) - if msg.nick != irc.nick and self.registryValue('askOpAboutMode',channel=channel) and ircdb.checkCapability(msg.prefix, '%s,op' % channel): - data = [item.uid,m,value,channel,msg.prefix,'For [#%s %s %s in %s - %s user(s)] , you have 5 minutes (example: 10m offtopic)' % (item.uid,'+%s' % m,value,channel,len(item.affects)),False] - if self.registryValue('useColorForAnnounces',channel=channel): - data[5] = 'For [#%s %s %s in %s - %s user(s)] type , you have 5 minutes (example: 10m offtopic)' % (ircutils.mircColor(item.uid,'yellow','black'),ircutils.bold(ircutils.mircColor('+%s' % m,'green')),ircutils.mircColor(value,'light blue'),channel,len(item.affects)) - self.addToAsked (irc,msg.prefix,data,msg.nick) + if m in self.registryValue('modesToAskWhenOpped', channel=channel) or m in self.registryValue('modesToAsk', channel=channel): + item = chan.addItem(m, value, msg.prefix, now, self.getDb( + irc.network), self.registryValue('trackAffected', channel=channel), self) + if msg.nick != irc.nick and self.registryValue('askOpAboutMode', channel=channel) and ircdb.checkCapability(msg.prefix, '%s,op' % channel): + data = [item.uid, m, value, channel, msg.prefix, 'For [#%s %s %s in %s - %s user(s)] , you have 5 minutes (example: 10m offtopic)' % ( + item.uid, '+%s' % m, value, channel, len(item.affects)), False] + if self.registryValue('useColorForAnnounces', channel=channel): + data[5] = 'For [#%s %s %s in %s - %s user(s)] type , you have 5 minutes (example: 10m offtopic)' % (ircutils.mircColor( + item.uid, 'yellow', 'black'), ircutils.bold(ircutils.mircColor('+%s' % m, 'green')), ircutils.mircColor(value, 'light blue'), channel, len(item.affects)) + self.addToAsked( + irc, msg.prefix, data, msg.nick) if overexpire > 0: if msg.nick != irc.nick: toexpire.append(item) @@ -3956,203 +4345,244 @@ class ChanTracker(callbacks.Plugin,plugins.ChannelDBHandler): if item and len(item.affects): for affected in item.affects: nick = affected.split('!')[0] - if self._isVip(irc,channel,self.getNick(irc,nick)): + if self._isVip(irc, channel, self.getNick(irc, nick)): continue - if m in self.registryValue('modesToAsk',channel=channel) and self.registryValue('doActionAgainstAffected',channel=channel) and not irc.nick == nick: + if m in self.registryValue('modesToAsk', channel=channel) and self.registryValue('doActionAgainstAffected', channel=channel) and not irc.nick == nick: for k in list(chan.getItems()): - if k in self.registryValue('modesToAskWhenOpped',channel=channel): + if k in self.registryValue('modesToAskWhenOpped', channel=channel): items = chan.getItemsFor(k) if len(items): for active in items: active = items[active] - if match(active.value,self.getNick(irc,nick),irc,self.registryValue('resolveIp')): + if match(active.value, self.getNick(irc, nick), irc, self.registryValue('resolveIp')): tolift.append(active) kicked = False - if m in self.registryValue('kickMode',channel=channel) and not value.startswith('m:'): # and not value.startswith(self.getIrcdExtbans(irc)) works for unreal - if msg.nick == irc.nick or msg.nick == 'ChanServ' or self.registryValue('kickOnMode',channel=channel): - if self.registryValue('kickMax',channel=channel) < 0 or len(item.affects) < self.registryValue('kickMax',channel=channel): + # and not value.startswith(self.getIrcdExtbans(irc)) works for unreal + if m in self.registryValue('kickMode', channel=channel) and not value.startswith('m:'): + if msg.nick == irc.nick or msg.nick == 'ChanServ' or self.registryValue('kickOnMode', channel=channel): + if self.registryValue('kickMax', channel=channel) < 0 or len(item.affects) < self.registryValue('kickMax', channel=channel): if nick in irc.state.channels[channel].users and nick != irc.nick: - chan.action.enqueue(ircmsgs.kick(channel,nick,random.choice(self.registryValue('kickMessage',channel=channel)))) + chan.action.enqueue(ircmsgs.kick(channel, nick, random.choice( + self.registryValue('kickMessage', channel=channel)))) self.forceTickle = True kicked = True - if not kicked and m in self.registryValue('modesToAsk',channel=channel) and self.registryValue('doActionAgainstAffected',channel=channel): - if msg.nick == irc.nick or msg.nick == 'ChanServ': + if not kicked and m in self.registryValue('modesToAsk', channel=channel) and self.registryValue('doActionAgainstAffected', channel=channel): + if msg.nick == irc.nick: if nick in irc.state.channels[channel].ops and not nick == irc.nick: - chan.queue.enqueue(('-o',nick)) + chan.queue.enqueue(('-o', nick)) if nick in irc.state.channels[channel].halfops and not nick == irc.nick: - chan.queue.enqueue(('-h',nick)) + chan.queue.enqueue(('-h', nick)) if nick in irc.state.channels[channel].voices and not nick == irc.nick: - chan.queue.enqueue(('-v',nick)) - if m == 'q' and len(self.registryValue('quietMessage',channel=channel)) and not chan.attacked: - qm = self.registryValue('quietMessage',channel=channel) - if self.registryValue('quietNotice',channel=channel): - irc.queueMsg(ircmsgs.notice(nick,qm)) + chan.queue.enqueue(('-v', nick)) + if m == 'q' and len(self.registryValue('quietMessage', channel=channel)) and not chan.attacked: + qm = self.registryValue( + 'quietMessage', channel=channel) + log.info( + '[%s] warned %s by pm' % (channel, nick)) + if self.registryValue('quietNotice', channel=channel): + irc.queueMsg( + ircmsgs.notice(nick, qm)) else: - irc.queueMsg(ircmsgs.privmsg(nick,qm)) - if m in self.registryValue('kickMode',channel=channel) and not value.startswith('m:') and self.registryValue('kickOnMode',channel=channel): - self.hasExtendedSharedBan(irc,channel,value,m) + irc.queueMsg( + ircmsgs.privmsg(nick, qm)) + if m in self.registryValue('kickMode', channel=channel) and not value.startswith('m:') and self.registryValue('kickOnMode', channel=channel): + self.hasExtendedSharedBan(irc, channel, value, m) # bot just got op if m == 'o' and value == irc.nick: chan.opAsked = False chan.deopPending = False ms = '' - asked = self.registryValue('modesToAskWhenOpped',channel=channel) + asked = self.registryValue( + 'modesToAskWhenOpped', channel=channel) asked = ''.join(asked) - asked = asked.replace(',','') + asked = asked.replace(',', '') for k in asked: if not k in chan.dones: - irc.queueMsg(ircmsgs.IrcMsg('MODE %s %s' % (channel,k))) + irc.queueMsg(ircmsgs.IrcMsg( + 'MODE %s %s' % (channel, k))) # flush pending queue, if items are waiting self.forceTickle = True else: if m == 'o' and value == irc.nick: # prevent bot to sent many -o modes when server takes time to reply chan.deopAsked = False - if m in self.registryValue('modesToAskWhenOpped',channel=channel) or m in self.registryValue('modesToAsk',channel=channel): + if m in self.registryValue('modesToAskWhenOpped', channel=channel) or m in self.registryValue('modesToAsk', channel=channel): toCommit = True - item = chan.removeItem(m,value,msg.prefix,c) + item = chan.removeItem(m, value, msg.prefix, c) if n: - n.addLog(channel,'sets %s %s' % (mode,value)) + n.addLog(channel, 'sets %s %s' % (mode, value)) if item: if '+' in mode: if not len(item.affects): if m in announces: - if self.registryValue('useColorForAnnounces',channel=channel): - msgs.append('[#%s %s %s]' % (ircutils.mircColor(str(item.uid),'yellow','black'),ircutils.bold(ircutils.mircColor(mode,'red')),ircutils.mircColor(value,'light blue'))) + if self.registryValue('useColorForAnnounces', channel=channel): + msgs.append('[#%s %s %s]' % (ircutils.mircColor(str(item.uid), 'yellow', 'black'), ircutils.bold( + ircutils.mircColor(mode, 'red')), ircutils.mircColor(value, 'light blue'))) else: - msgs.append('[#%s %s %s]' % (str(item.uid),mode,value)) + msgs.append('[#%s %s %s]' % ( + str(item.uid), mode, value)) elif len(item.affects) != 1: if m in announces: - if self.registryValue('useColorForAnnounces',channel=channel): - msgs.append('[#%s %s %s - %s users]' % (ircutils.mircColor(str(item.uid),'yellow','black'),ircutils.bold(ircutils.mircColor(mode,'red')),ircutils.mircColor(value,'light blue'),str(len(item.affects)))) + if self.registryValue('useColorForAnnounces', channel=channel): + msgs.append('[#%s %s %s - %s users]' % (ircutils.mircColor(str(item.uid), 'yellow', 'black'), ircutils.bold( + ircutils.mircColor(mode, 'red')), ircutils.mircColor(value, 'light blue'), str(len(item.affects)))) else: - msgs.append('[#%s %s %s - %s users]' % (str(item.uid),mode,value,str(len(item.affects)))) + msgs.append( + '[#%s %s %s - %s users]' % (str(item.uid), mode, value, str(len(item.affects)))) else: if m in announces: - if self.registryValue('useColorForAnnounces',channel=channel): - msgs.append('[#%s %s %s - %s]' % (ircutils.mircColor(str(item.uid),'yellow','black'),ircutils.bold(ircutils.mircColor(mode,'red')),ircutils.mircColor(value,'light blue'),item.affects[0])) + if self.registryValue('useColorForAnnounces', channel=channel): + msgs.append('[#%s %s %s - %s]' % (ircutils.mircColor(str(item.uid), 'yellow', 'black'), ircutils.bold( + ircutils.mircColor(mode, 'red')), ircutils.mircColor(value, 'light blue'), item.affects[0])) else: - msgs.append('[#%s %s %s - %s]' % (str(item.uid),mode,value,item.affects[0])) + msgs.append( + '[#%s %s %s - %s]' % (str(item.uid), mode, value, item.affects[0])) else: if not len(item.affects): if m in announces: - if self.registryValue('useColorForAnnounces',channel=channel): - msgs.append('[#%s %s %s %s]' % (ircutils.mircColor(str(item.uid),'yellow','black'),ircutils.bold(ircutils.mircColor(mode,'green')),ircutils.mircColor(value,'light blue'),str(utils.timeElapsed(item.removed_at-item.when)))) + if self.registryValue('useColorForAnnounces', channel=channel): + msgs.append('[#%s %s %s %s]' % (ircutils.mircColor(str(item.uid), 'yellow', 'black'), ircutils.bold(ircutils.mircColor( + mode, 'green')), ircutils.mircColor(value, 'light blue'), str(utils.timeElapsed(item.removed_at-item.when)))) else: - msgs.append('[#%s %s %s %s]' % (str(item.uid),mode,value,str(utils.timeElapsed(item.removed_at-item.when)))) + msgs.append('[#%s %s %s %s]' % (str(item.uid), mode, value, str( + utils.timeElapsed(item.removed_at-item.when)))) elif len(item.affects) != 1: if m in announces: - if self.registryValue('useColorForAnnounces',channel=channel): - msgs.append('[#%s %s %s - %s users, %s]' % (ircutils.mircColor(str(item.uid),'yellow','black'),ircutils.bold(ircutils.mircColor(mode,'green')),ircutils.mircColor(value,'light blue'),str(len(item.affects)),str(utils.timeElapsed(item.removed_at-item.when)))) + if self.registryValue('useColorForAnnounces', channel=channel): + msgs.append('[#%s %s %s - %s users, %s]' % (ircutils.mircColor(str(item.uid), 'yellow', 'black'), ircutils.bold(ircutils.mircColor( + mode, 'green')), ircutils.mircColor(value, 'light blue'), str(len(item.affects)), str(utils.timeElapsed(item.removed_at-item.when)))) else: - msgs.append('[#%s %s %s - %s users, %s]' % (str(item.uid),mode,value,str(len(item.affects)),str(utils.timeElapsed(item.removed_at-item.when)))) + msgs.append('[#%s %s %s - %s users, %s]' % (str(item.uid), mode, value, str( + len(item.affects)), str(utils.timeElapsed(item.removed_at-item.when)))) else: if m in announces: - if self.registryValue('useColorForAnnounces',channel=channel): - msgs.append('[#%s %s %s - %s, %s]' % (ircutils.mircColor(str(item.uid),'yellow','black'),ircutils.bold(ircutils.mircColor(mode,'green')),ircutils.mircColor(value,'light blue'),item.affects[0],str(utils.timeElapsed(item.removed_at-item.when)))) + if self.registryValue('useColorForAnnounces', channel=channel): + msgs.append('[#%s %s %s - %s, %s]' % (ircutils.mircColor(str(item.uid), 'yellow', 'black'), ircutils.bold(ircutils.mircColor( + mode, 'green')), ircutils.mircColor(value, 'light blue'), item.affects[0], str(utils.timeElapsed(item.removed_at-item.when)))) else: - msgs.append('[#%s %s %s - %s, %s]' % (str(item.uid),mode,value,item.affects[0],str(utils.timeElapsed(item.removed_at-item.when)))) + msgs.append('[#%s %s %s - %s, %s]' % (str(item.uid), mode, value, item.affects[0], str( + utils.timeElapsed(item.removed_at-item.when)))) else: if m in announces: - if self.registryValue('useColorForAnnounces',channel=channel): + if self.registryValue('useColorForAnnounces', channel=channel): if '+' in mode: - msgs.append('[%s %s]' % (ircutils.bold(ircutils.mircColor(mode,'red')),ircutils.mircColor(value,'light blue'))) + msgs.append('[%s %s]' % (ircutils.bold(ircutils.mircColor( + mode, 'red')), ircutils.mircColor(value, 'light blue'))) else: - msgs.append('[%s %s]' % (ircutils.bold(ircutils.mircColor(mode,'green')),ircutils.mircColor(value,'light blue'))) + msgs.append('[%s %s]' % (ircutils.bold(ircutils.mircColor( + mode, 'green')), ircutils.mircColor(value, 'light blue'))) else: - msgs.append('[%s %s]' % (mode,value)) + msgs.append('[%s %s]' % (mode, value)) else: if n: - n.addLog(channel,'sets %s' % mode) + n.addLog(channel, 'sets %s' % mode) if m in announces: - if self.registryValue('useColorForAnnounces',channel=channel): + if self.registryValue('useColorForAnnounces', channel=channel): if '+' in mode: - msgs.append(ircutils.bold(ircutils.mircColor(mode,'red'))) + msgs.append(ircutils.bold( + ircutils.mircColor(mode, 'red'))) else: - msgs.append(ircutils.bold(ircutils.mircColor(mode,'green'))) + msgs.append(ircutils.bold( + ircutils.mircColor(mode, 'green'))) else: msgs.append(mode) if toCommit: db.commit() - if irc.state.channels[channel].isHalfopPlus(irc.nick) and not self.registryValue('keepOp',channel=channel): + if irc.state.channels[channel].isHalfopPlus(irc.nick) and not self.registryValue('keepOp', channel=channel): self.forceTickle = True - if len(self.registryValue('announceModes',channel=channel)) and len(msgs): - if self.registryValue('announceModeMadeByIgnored',channel=channel) or not ircdb.checkIgnored(msg.prefix,channel): - if self.registryValue('useColorForAnnounces',channel=channel): - self._logChan(irc,channel,'[%s] %s sets %s' % (ircutils.bold(channel),msg.nick,' '.join(msgs))) + if len(self.registryValue('announceModes', channel=channel)) and len(msgs): + if self.registryValue('announceModeMadeByIgnored', channel=channel) or not ircdb.checkIgnored(msg.prefix, channel): + if self.registryValue('useColorForAnnounces', channel=channel): + self._logChan(irc, channel, '[%s] %s sets %s' % ( + ircutils.bold(channel), msg.nick, ' '.join(msgs))) else: - self._logChan(irc,channel,'[%s] %s sets %s' % (channel,msg.nick,' '.join(msgs))) + self._logChan(irc, channel, '[%s] %s sets %s' % ( + channel, msg.nick, ' '.join(msgs))) self.forceTickle = True if len(toexpire): for item in toexpire: f = None - if self.registryValue('announceBotEdit',channel=item.channel): + if self.registryValue('announceBotEdit', channel=item.channel): f = self._logChan - i.edit(irc,item.channel,item.mode,item.value,self.registryValue('autoExpire',channel=item.channel),irc.prefix,self.getDb(irc.network),self._schedule,f,self) + i.edit(irc, item.channel, item.mode, item.value, self.registryValue( + 'autoExpire', channel=item.channel), irc.prefix, self.getDb(irc.network), self._schedule, f, self) self.forceTickle = True if len(tolift): for item in tolift: f = None - if self.registryValue('announceBotEdit',channel=item.channel): + if self.registryValue('announceBotEdit', channel=item.channel): f = self._logChan - i.edit(irc,item.channel,item.mode,item.value,0,irc.prefix,self.getDb(irc.network),self._schedule,f,self) + i.edit(irc, item.channel, item.mode, item.value, 0, irc.prefix, self.getDb( + irc.network), self._schedule, f, self) self.forceTickle = True c.close() # as _tickle now may be a bit too earlier, delay it a bit + def ttickle(): self._tickle(irc) - schedule.addEvent(ttickle,time.time()+1) + schedule.addEvent(ttickle, time.time()+1) - def do474(self,irc,msg): + def do474(self, irc, msg): # bot banned from a channel it's trying to join # server 474 irc.nick #channel :Cannot join channel (+b) - you are banned # TODO talk with owner self._tickle(irc) - def do478(self,irc,msg): + def do478(self, irc, msg): # message when ban list is full after adding something to eqIb list - (nick,channel,ban,info) = msg.args - if self.registryValue('logChannel',channel=channel) in irc.state.channels: + (nick, channel, ban, info) = msg.args + if self.registryValue('logChannel', channel=channel) in irc.state.channels: L = [] - for user in list(irc.state.channels[self.registryValue('logChannel',channel=channel)].users): + for user in list(irc.state.channels[self.registryValue('logChannel', channel=channel)].users): L.append(user) - if self.registryValue('useColorsForAnnounce',channel=channel): - self._logChannel(irc,channel,'[%s] %s : %s' % (ircutils.bold(channel),ircutils.bold(ircutils.mircColor(info,'red')),' '.join(L))) + if self.registryValue('useColorsForAnnounce', channel=channel): + self._logChannel(irc, channel, '[%s] %s : %s' % (ircutils.bold( + channel), ircutils.bold(ircutils.mircColor(info, 'red')), ' '.join(L))) else: - self._logChan(irc,channel,'[%s] %s : %s' % (channel,info,' '.join(L))) + self._logChan(irc, channel, '[%s] %s : %s' % ( + channel, info, ' '.join(L))) self._tickle(irc) # protection features - def _act (self,irc,channel,mode,mask,duration,reason): + def _act(self, irc, channel, mode, mask, duration, reason): if mode == 'd': - if self.registryValue('logChannel',channel=channel) in irc.state.channels: - self._logChan(irc,channel,'[%s] debug %s %s %s %s' % (channel,mode,mask,duration,reason)) + if self.registryValue('logChannel', channel=channel) in irc.state.channels: + announce = '[%s] debug %s %s %s %s' + if self.registryValue('useColorsForAnnounce', channel=channel): + self._logChan(irc, channel, announce % (ircutils.bold( + channel), mode, ircutils.mircColor(mask, 'teal'), ircutils.bold(duration), reason)) + else: + self._logChan(irc, channel, announce % ( + channel, mode, mask, duration, reason)) return - if mode in self.registryValue('modesToAsk',channel=channel) or mode in self.registryValue('modesToAskWhenOpped',channel=channel): + if mode in self.registryValue('modesToAsk', channel=channel) or mode in self.registryValue('modesToAskWhenOpped', channel=channel): i = self.getIrc(irc) - if i.add(irc,channel,mode,mask,duration,irc.prefix,self.getDb(irc.network)): + if i.add(irc, channel, mode, mask, duration, irc.prefix, self.getDb(irc.network)): if reason and len(reason): f = None - if self.registryValue('announceInTimeEditAndMark',channel=channel): - if self.registryValue('announceBotMark',channel=channel): + if self.registryValue('announceInTimeEditAndMark', channel=channel): + if self.registryValue('announceBotMark', channel=channel): f = self._logChan - i.submark(irc,channel,mode,mask,reason,irc.prefix,self.getDb(irc.network),f,self) + i.submark(irc, channel, mode, mask, reason, + irc.prefix, self.getDb(irc.network), f, self) else: # increase duration, until the wrong action stopped f = None - if self.registryValue('announceBotEdit',channel=channel): + if self.registryValue('announceBotEdit', channel=channel): f = self._logChan - chan = self.getChan(irc,channel) - item = chan.getItem(mode,mask) + chan = self.getChan(irc, channel) + item = chan.getItem(mode, mask) oldDuration = int(item.expire-item.when) - i.edit(irc,channel,mode,mask,int(oldDuration+duration),irc.prefix,self.getDb(irc.network),self._schedule,f,self) + i.edit(irc, channel, mode, mask, int(oldDuration+duration), + irc.prefix, self.getDb(irc.network), self._schedule, f, self) if reason and len(reason): f = None - if self.registryValue('announceBotMark',channel=channel): + if self.registryValue('announceBotMark', channel=channel): f = self._logChan - i.mark(irc,item.uid,reason,irc.prefix,self.getDb(irc.network),f,self) + i.mark(irc, item.uid, reason, irc.prefix, + self.getDb(irc.network), f, self) self.forceTickle = True self._tickle(irc) else: @@ -4160,85 +4590,97 @@ class ChanTracker(callbacks.Plugin,plugins.ChannelDBHandler): i = self.getIrc(irc) for nick in list(irc.state.channels[channel].users): if nick in i.nicks and nick != irc.nick: - n = self.getNick(irc,nick) - m = match(mask,n,irc,self.registryValue('resolveIp')) + n = self.getNick(irc, nick) + m = match(mask, n, irc, self.registryValue('resolveIp')) if m: results.append(nick) if len(results) and mode in 'kr': - chan = self.getChan(irc,channel) + chan = self.getChan(irc, channel) if not reason or not len(reason): - reason = random.choice(self.registryValue('kickMessage',channel=channel)) + reason = random.choice(self.registryValue( + 'kickMessage', channel=channel)) for n in results: if mode == 'k': - chan.action.enqueue(ircmsgs.IrcMsg('KICK %s %s :%s' % (channel,n,reason))) + chan.action.enqueue(ircmsgs.IrcMsg( + 'KICK %s %s :%s' % (channel, n, reason))) self.forceTickle = True elif mode == 'r': - chan.action.enqueue(ircmsgs.IrcMsg('REMOVE %s %s :%s' % (channel,n,reason))) + chan.action.enqueue(ircmsgs.IrcMsg( + 'REMOVE %s %s :%s' % (channel, n, reason))) self.forceTickle = True self._tickle(irc) else: - log.error('%s %s %s %s %s unsupported mode' % (channel,mode,mask,duration,reason)) + log.error('%s %s %s %s %s unsupported mode' % + (channel, mode, mask, duration, reason)) - def _isSomething (self,irc,channel,key,prop): - chan = self.getChan(irc,channel) + def _isSomething(self, irc, channel, key, prop): + chan = self.getChan(irc, channel) if prop == 'massJoin' or prop == 'cycle': if chan.netsplit: return False - limit = self.registryValue('%sPermit' % prop,channel=channel) + limit = self.registryValue('%sPermit' % prop, channel=channel) if limit < 0: return False flag = ircdb.makeChannelCapability(channel, prop) if not ircdb.checkCapability(key, flag): return False - chan = self.getChan(irc,channel) - life = self.registryValue('%sLife' % prop,channel=channel) + chan = self.getChan(irc, channel) + life = self.registryValue('%sLife' % prop, channel=channel) if not prop in chan.spam: chan.spam[prop] = {} if not key in chan.spam[prop] or chan.spam[prop][key].timeout != life: chan.spam[prop][key] = utils.structures.TimeoutQueue(life) chan.spam[prop][key].enqueue(key) if len(chan.spam[prop][key]) > limit: - log.debug('[%s] %s is detected as %s' % (channel,key,prop)) + log.info('[%s] %s is detected as %s' % (channel, key, prop)) chan.spam[prop][key].reset() return True return False - def _isBad (self,irc,channel,key): - b = self._isSomething(irc,channel,key,'bad') + def _isBad(self, irc, channel, key): + b = self._isSomething(irc, channel, key, 'bad') if b: - chan = self.getChan(irc,channel) - if self._isSomething(irc,channel,channel,'attack') and not chan.attacked: + chan = self.getChan(irc, channel) + if self._isSomething(irc, channel, channel, 'attack') and not chan.attacked: # if number of bad users raise the allowed limit, bot has to set channel attackmode # todo retreive all wrong users and find the best pattern to use against them chan.attacked = True - if self.registryValue('attackMode',channel=channel) == 'd': - if self.registryValue('useColorForAnnounces',channel=channel): - self._logChan(irc,channel,'[%s] attackMode applied' % ircutils.bold(channel)) + if self.registryValue('attackMode', channel=channel) == 'd': + if self.registryValue('useColorForAnnounces', channel=channel): + self._logChan( + irc, channel, '[%s] attackMode applied' % ircutils.bold(channel)) else: - self._logChan(irc,channel,'[%s] attackMode applied' % channel) + self._logChan( + irc, channel, '[%s] attackMode applied' % channel) else: - chan.action.enqueue(ircmsgs.IrcMsg('MODE %s %s' % (channel,self.registryValue('attackMode',channel=channel)))) + chan.action.enqueue(ircmsgs.IrcMsg('MODE %s %s' % ( + channel, self.registryValue('attackMode', channel=channel)))) + def unAttack(): if channel in list(irc.state.channels.keys()): - if self.registryValue('attackUnMode',channel=channel) == 'd': - if self.registryValue('useColorForAnnounces',channel=channel): - self._logChan(irc,channel,'[%s] attackUnMode applied' % ircutils.bold(channel)) + if self.registryValue('attackUnMode', channel=channel) == 'd': + if self.registryValue('useColorForAnnounces', channel=channel): + self._logChan( + irc, channel, '[%s] attackUnMode applied' % ircutils.bold(channel)) else: - self._logChan(irc,channel,'[%s] attackUnMode applied' % channel) + self._logChan( + irc, channel, '[%s] attackUnMode applied' % channel) else: - chan.action.enqueue(ircmsgs.IrcMsg('MODE %s %s' % (channel,self.registryValue('attackUnMode',channel=channel)))) + chan.action.enqueue(ircmsgs.IrcMsg('MODE %s %s' % ( + channel, self.registryValue('attackUnMode', channel=channel)))) chan.attacked = False - schedule.addEvent(unAttack,float(time.time()+self.registryValue('attackDuration',channel=channel))) + schedule.addEvent(unAttack, float( + time.time()+self.registryValue('attackDuration', channel=channel))) return b - def _isFlood(self,irc,channel,key): - return self._isSomething(irc,channel,key,'flood') + def _isFlood(self, irc, channel, key): + return self._isSomething(irc, channel, key, 'flood') - def _isLowFlood(self,irc,channel,key): - return self._isSomething(irc,channel,key,'lowFlood') + def _isLowFlood(self, irc, channel, key): + return self._isSomething(irc, channel, key, 'lowFlood') - def _isHilight (self,irc,channel,key,message): - limit = self.registryValue('hilightPermit',channel=channel) + def _isHilight(self, irc, channel, key, message): + limit = self.registryValue('hilightPermit', channel=channel) if limit == -1: return False count = 0 @@ -4248,89 +4690,94 @@ class ChanTracker(callbacks.Plugin,plugins.ChannelDBHandler): if len(user) > 2: users.append(user.lower()) for user in users: - if user in msg: - count = count + 1 + if user in msg: + count = count + 1 return count > limit - - def _addTemporaryPattern(self,irc,channel,pattern,level): - patternLength = self.registryValue('repeatPatternMinimum',channel=channel) + + def _addTemporaryPattern(self, irc, channel, pattern, level): + patternLength = self.registryValue( + 'repeatPatternMinimum', channel=channel) key = 'pattern%s' % channel if patternLength < 0: return if len(pattern) < patternLength: return - life = self.registryValue('repeatPatternLife',channel=channel) - chan = self.getChan(irc,channel) + life = self.registryValue('repeatPatternLife', channel=channel) + chan = self.getChan(irc, channel) if not key in chan.repeatLogs or chan.repeatLogs[key].timeout != life: chan.repeatLogs[key] = utils.structures.TimeoutQueue(life) - self._logChan(irc,channel,'[%s] pattern created "%s" (%s)' % (channel,pattern,level)) + self._logChan(irc, channel, '[%s] pattern created "%s" (%s)' % ( + channel, pattern, level)) chan.repeatLogs[key].enqueue(pattern) - - def _computePattern(self,message,logs,probability,patternLength): + + def _computePattern(self, message, logs, probability, patternLength): candidate = None bad = False for msg in logs: - if compareString(message,msg) >= probability: + if compareString(message, msg) >= probability: bad = True if patternLength > -1: - found = largestString(message,msg) + found = largestString(message, msg) if found and len(found) > patternLength: if candidate: if len(candidate) < len(found): candidate = found else: candidate = found - return (bad,candidate) - - def _isRepeat(self,irc,channel,key,message): - if self.registryValue('repeatPermit',channel=channel) < 0: + return (bad, candidate) + + def _isRepeat(self, irc, channel, key, message): + if self.registryValue('repeatPermit', channel=channel) < 0: return False - chan = self.getChan(irc,channel) - timeout = self.registryValue('repeatLife',channel=channel) + chan = self.getChan(irc, channel) + timeout = self.registryValue('repeatLife', channel=channel) if not key in chan.repeatLogs or chan.repeatLogs[key].timeout != timeout: chan.repeatLogs[key] = utils.structures.TimeoutQueue(timeout) - count = self.registryValue('repeatCount',channel=channel) - probability = self.registryValue('repeatPercent',channel=channel) - minimum = self.registryValue('repeatMinimum',channel=channel) - pattern = findPattern(message,count,minimum,100 * probability) + count = self.registryValue('repeatCount', channel=channel) + probability = self.registryValue('repeatPercent', channel=channel) + minimum = self.registryValue('repeatMinimum', channel=channel) + pattern = findPattern(message, count, minimum, 100 * probability) if pattern: - self._addTemporaryPattern(irc,channel,pattern,'single msg') - if self._isSomething(irc,channel,key,'repeat'): + self._addTemporaryPattern(irc, channel, pattern, 'single msg') + if self._isSomething(irc, channel, key, 'repeat'): return True - patternLength = self.registryValue('repeatPatternMinimum',channel=channel) + patternLength = self.registryValue( + 'repeatPatternMinimum', channel=channel) logs = chan.repeatLogs[key] - (flag, pattern) = self._computePattern(message,logs,probability,patternLength) + (flag, pattern) = self._computePattern( + message, logs, probability, patternLength) result = False if flag: - result = self._isSomething(irc,channel,key,'repeat') + result = self._isSomething(irc, channel, key, 'repeat') chan.repeatLogs[key].enqueue(message) if result: if pattern: - self._addTemporaryPattern(irc,channel,pattern,'single src') + self._addTemporaryPattern(irc, channel, pattern, 'single src') return result if not channel in chan.repeatLogs or chan.repeatLogs[channel].timeout != timeout: chan.repeatLogs[channel] = utils.structures.TimeoutQueue(timeout) logs = chan.repeatLogs[channel] - (flag, pattern) = self._computePattern(message,logs,probability,patternLength) + (flag, pattern) = self._computePattern( + message, logs, probability, patternLength) chan.repeatLogs[channel].enqueue(message) result = False if flag: - result = self._isSomething(irc,channel,channel,'repeat') + result = self._isSomething(irc, channel, channel, 'repeat') if result: if pattern: - self._addTemporaryPattern(irc,channel,pattern,'all src') + self._addTemporaryPattern(irc, channel, pattern, 'all src') return result - def _isCap(self,irc,channel,key,message): - limit = self.registryValue('capPermit',channel=channel) + def _isCap(self, irc, channel, key, message): + limit = self.registryValue('capPermit', channel=channel) if limit == -1: return False - trigger = self.registryValue('capPercent',channel=channel) + trigger = self.registryValue('capPercent', channel=channel) matchs = self.recaps.findall(message) if len(matchs) and len(message): percent = len(matchs) / (len(message) * 1.0) if percent >= trigger: - return self._isSomething(irc,channel,key,'cap') + return self._isSomething(irc, channel, key, 'cap') return False