Beispiel #1
0
 def __init__(self, irc):
     self.__parent = super(Herald, self)
     self.__parent.__init__(irc)
     self.db = HeraldDB(filename)
     world.flushers.append(self.db.flush)
     self.lastParts = plugins.ChannelUserDictionary()
     splitTimeout = conf.supybot.plugins.Herald.throttle.afterSplit
     self.splitters = TimeoutQueue(splitTimeout)
     self.lastHerald = plugins.ChannelUserDictionary()
Beispiel #2
0
 def _addRelayMsg(self, msg):
     channel = msg.args[0]
     if channel in self.lastRelayMsgs:
         q = self.lastRelayMsgs[channel]
     else:
         q = TimeoutQueue(60) # XXX Make this configurable.
         self.lastRelayMsgs[channel] = q
     unformatted = ircutils.stripFormatting(msg.args[1])
     normalized = utils.str.normalizeWhitespace(unformatted)
     q.enqueue(normalized)
Beispiel #3
0
    def __init__(self, irc):
        self.__parent = super(Mantis, self)
        self.__parent.__init__(irc)

        self.saidBugs = ircutils.IrcDict()
        sayTimeout = self.registryValue('bugSnarferTimeout')
        for k in irc.state.channels.keys():
            self.saidBugs[k] = TimeoutQueue(sayTimeout)

        self.urlbase = self.registryValue('urlbase')
        self.privateurlbase = self.registryValue('privateurlbase')

        if self.privateurlbase != "":
            serviceUrl = self.privateurlbase + '/api/soap/mantisconnect.php'
        else:
            serviceUrl = self.urlbase + '/api/soap/mantisconnect.php'

        self.server = SOAPProxy(serviceUrl)._ns(namespace)
        self.username = self.registryValue('username')
        self.password = self.registryValue('password')
        self.oldperiodic = self.registryValue('bugPeriodicCheck')
        self.irc = irc
        self.lastBug = 0

        bugPeriodicCheck = self.oldperiodic
        if bugPeriodicCheck > 0:
            schedule.addPeriodicEvent(self._bugPeriodicCheck,
                                      bugPeriodicCheck,
                                      name=self.name())

        reload(sys)
        sys.setdefaultencoding('utf-8')
 def __init__(self, irc):
     self.__parent = super(Roundup, self)
     self.__parent.__init__(irc)
     self.saidBugs = ircutils.IrcDict()
     self.saidAttachments = ircutils.IrcDict()
     sayTimeout = self.registryValue('bugSnarferTimeout')
     for k in irc.state.channels.keys():
         self.saidBugs[k] = TimeoutQueue(sayTimeout)
         self.saidAttachments[k] = TimeoutQueue(sayTimeout)
     #period = self.registryValue('mboxPollTimeout')
     #schedule.addPeriodicEvent(self._pollMbox, period, name=self.name(),
     #                          now=False)
     for name in self.registryValue('roundups'):
         registerRoundup(name)
     reload(sys)
     sys.setdefaultencoding('utf-8')
 def _shouldSayAttachment(self, attach_id, channel):
     if channel not in self.saidAttachments:
         sayTimeout = self.registryValue('bugSnarferTimeout')
         self.saidAttachments[channel] = TimeoutQueue(sayTimeout)
     if attach_id in self.saidAttachments[channel]:
         return False
     self.saidAttachments[channel].enqueue(attach_id)
     return True
Beispiel #6
0
 def __init__(self, irc):
     self.__parent = super(Greet, self)
     self.__parent.__init__(irc)
     self.db = GreetDB(filename)
     world.flushers.append(self.db.flush)
     self.lastParts = plugins.ChannelUserDictionary()
     splitTimeout = conf.supybot.plugins.Greet.throttle.afterSplit
     self.splitters = TimeoutQueue(splitTimeout)
     self.lastGreet = plugins.ChannelUserDictionary()
Beispiel #7
0
 def __init__(self, irc):
     self.__parent = super(Randomness, self)
     self.__parent.__init__(irc)
     self.dotCounter = TimeoutQueue(10)
     self.vfilename = conf.supybot.directories.data.dirize(irc.network+".votes")
     try:
         with open(self.vfilename, "r") as f:
             self.votes = json.load(f)
     except IOError:
         self.votes = {}
    def _shouldSayBug(self, bug_id, channel):
        if channel not in self.saidBugs:
            sayTimeout = self.registryValue('bugSnarferTimeout')
            self.saidBugs[channel] = TimeoutQueue(sayTimeout)
        if bug_id in self.saidBugs[channel]:
            return False

        self.saidBugs[channel].enqueue(bug_id)
        #self.log.debug('After checking bug %s queue is %r' \
        #                % (bug_id, self.saidBugs[channel]))
        return True
Beispiel #9
0
    def __init__(self, irc):

        self.__parent = super(Redmine, self)
        self.__parent.__init__(irc)

        self.saidBugs = ircutils.IrcDict()
        sayTimeout = self.registryValue('bugSnarferTimeout')
        for k in irc.state.channels.keys():
            self.saidBugs[k] = TimeoutQueue(sayTimeout)

        self.url = self.registryValue('urlbase')
        self.auth = BasicAuth(self.registryValue('apikey'),
                              str(random.random()))
        self.resource = Resource(self.url, filters=[self.auth])
Beispiel #10
0
 def __init__(self, irc):
     self.__parent = super(RelayLink, self)
     self.__parent.__init__(irc)
     self._loadFromConfig()
     self.ircstates = {}
     for IRC in world.ircs:
         self.addIRC(IRC)
     floodProtectTimeout = conf.supybot.plugins.RelayLink.antiflood.seconds
     self.floodCounter = TimeoutQueue(floodProtectTimeout)
     self.floodActivated = False
     try:
         conf.supybot.plugins.RelayLink.substitutes.addCallback(
                 self._loadFromConfig)
         conf.supybot.plugins.RelayLink.relays.addCallback(
                 self._loadFromConfig)
     except registry.NonExistentRegistryEntry:
         log.error("Your version of Supybot is not compatible with "
                   "configuration hooks. So, RelayLink won't be able "
                   "to reload the configuration if you use the Config "
                   "plugin.")
Beispiel #11
0
class Randomness(callbacks.Plugin):
    """Add the help for "@plugin help Randomness" here
    This should describe *how* to use this plugin."""
    threaded = True
    
    def __init__(self, irc):
        self.__parent = super(Randomness, self)
        self.__parent.__init__(irc)
        self.dotCounter = TimeoutQueue(10)
        self.vfilename = conf.supybot.directories.data.dirize(irc.network+".votes")
        try:
            with open(self.vfilename, "r") as f:
                self.votes = json.load(f)
        except IOError:
            self.votes = {}

    def loadVoteDB(self):
        with open(self.vfilename, "r") as f:
            self.votes = json.load(f)
            
    def exportVoteDB(self):
        with open(self.vfilename, 'w') as f:
            json.dump(self.votes, f)
            f.write("\n")
            
    def die(self):
        self.__parent.die()
        try:
            self.exportVoteDB()
        except IOError as e:
            self.log.error("Failed to export Votes DB: " + str(e))

    # The code below contains automatic replies then turned on. Since this
    # is a mostly personal plugin, they will only activate on certain
    # predefined networks.
    def _attack(self, target):
        bde = "%sasE%s4"%('B','6')
        throws = ['poorly written code', 'knives', 
            "Te"+"chman", 'various objects',
            "Techm"+"ango", 'grenades',
            "j4j"+"ackj", 'netsplits']
        spells = ['fire', 'ice', 'death', '\x02DEATH\x02', 
            'poison', 'stupid']
        attacks = throws + spells + ['bricks', 'knives', 
            "idiots from #freenode", "her army of trolls",
            "her ~~godly~~ oper powers",
            'confusingly bad english', 
            "gbyers' immaturity",
            "YnJlbmRpIGhpdGxlciBibG9zc29t".decode(bde)]
        n = random.random()
        if n >= 0.82:
            return 'casts %s at %s'%(random.choice(spells), target)
        elif n >= 0.76:
            return 'drops the bass on %s'%target
        elif n >= 0.72:
            return 'fites %s'%target
        elif n >= 0.48:
            return 'attacks %s with %s'%(target, random.choice(attacks))
        else:
            return 'throws %s at %s'%(random.choice(throws),target)

    def doPrivmsg(self, irc, msg):
        if ircutils.isChannel(msg.args[0]) and self.registryValue("enable", msg.args[0]):
            dots = "." * random.randint(0,10) # added emphasis...............
            ow = "ow"+("w"*random.randint(0,4))
            volatile = ("kicks ", "stabs ", "fites ", "bans ", "ddas ", "packets ", "beats ")
            exclaim = (("!" * random.randint(1,5)) + ("1" * random.randint(0,2))) * \
                random.randint(1,2) + ("!" * random.randint(-1,5))
            gemotes = ["xD", "=']", "\\o/", ":"+"3"*random.randint(1,4), "^_^"]
            bemotes = ("-_-", ":|", ":\\", ":/", ":(")
            semotes = (":<", ";_;", ";-;", "D:", ">:", "x(")
            if irc.network.lower() == "overdrive-irc":
                # if msg.nick.lower() == 'gbyers' and msg.args[1].lower() == 'hi lily':
                    # irc.queueMsg(ircmsgs.kick(msg.args[0], msg.nick, "stfu"))
                if "fishbot" in irc.state.channels[msg.args[0]].users:
                    hurtresponses = [ow, ";_;", ow+" :(", "RIP", "i cry",
                        "ouch", "what was that for "+random.choice(semotes),
                        "!voteban "+msg.nick, "PLS", "rood", "owowowowow", 
                        "omg "+random.choice(semotes), 
                        "bots have feelings too!", "wtf", "watch it!"]
                    if re.match(r"^\x01ACTION ((attacks|stabs) {n} with |"
                        r"(drops|throws|casts|thwacks) (.*? (at|on|with) "
                        r"{n}|{n} (at|on|with) .*?)|fites {n}).*?\x01$".\
                        format(n=irc.nick), msg.args[1].lower(), re.I):
                        sleep(0.4)
                        n = random.random()
                        if n >= 0.58:
                            irc.queueMsg(ircmsgs.action(msg.args[0], self._attack(msg.nick)))
                        elif n >= 0.4:
                            irc.queueMsg(ircmsgs.privmsg(msg.args[0], random.choice(hurtresponses)))
                if "wow" in irc.state.channels[msg.args[0]].ops and \
                    ircutils.stripFormatting(msg.args[1].lower()).startswith("wow"):
                    wowResponses1 = ["what is it",
                                    "hi %s%s" % (msg.nick, dots),
                                    "o/",
                                    "HI %s%s" % (msg.nick.upper(), dots),
                                    "go away "+random.choice(bemotes),
                                    "FFS "+random.choice(bemotes),
                                    "ffs i'm trying to work",
                                    "WHAT DO YOU WANT",
                                    "leave me alone "+random.choice(bemotes),
                                    "hello, you've reached 'wow'. "
                                        "If you actually need to talk to me, "
                                        "press 1. if not, PISS OFF!",
                                    "stop highlighting me" + dots,
                                    "reproted to fbi for harassment" + dots,
                                    "-_-",
                                    msg.nick + " pls",
                                    "need something?",
                                    "r u mad",
                                    "ur made",
                                    "fml",
                                    "?",
                                    ".",
                                    "/join 0",
                                    "/part SCREW U GUYS IM LEAVING AND NEVER COMING "
                                        "BACK AGAIN!! IT'S ALL %s'S FAULT I FKN HATE "
                                        "YOU ALL \x02</3" % msg.nick.upper(),
                                    "stop highlighting me!",
                                    "\x02%s\x02 added to ignore list." % msg.nick,
                                    "!votekline " + msg.nick]
                    n = random.randint(0, 91)
                    if n >= 60:
                        irc.queueMsg(ircmsgs.privmsg("BotServ", "say {} {}".format(msg.args[0],random.choice(wowResponses1))))
                    elif n >= 50:
                        irc.queueMsg(ircmsgs.privmsg("BotServ", "act {} {}".format(msg.args[0],random.choice(volatile)+msg.nick)))
#                elif msg.nick.lower().startswith("brend"):
#                    bad = ["chink", "nigr", "nigger", "chinq"] # Seriously though, racism *sucks*.
#                    for w in bad:
#                        if w in ircutils.stripFormatting(msg.args[1].lower()):
#                            irc.queueMsg(ircmsgs.kick(msg.args[0], msg.nick, "RACIST"))
#                        return
#                    alsobad = ["veggie tales", 'w***e', 'wh0re']
#                    for w in alsobad:
#                        if w in ircutils.stripFormatting(msg.args[1].lower()):
#                            irc.queueMsg(ircmsgs.kick(msg.args[0], msg.nick, "nothx"))
                if ircutils.stripFormatting(msg.args[1]) == ".":
                    dotresponses = ["r u mad?", "lol r u mad", "mmm dots", ",", "no spam pls" + dots, ":D", "ok"]
                    if len(self.dotCounter) >= 2:
                        r = random.random()
                        if r >= 0.5:
                            irc.queueMsg(ircmsgs.privmsg(msg.args[0], random.choice(dotresponses)))
                    else: self.dotCounter.enqueue([0])
                elif ircutils.stripFormatting(msg.args[1]) == "ok":
                    okresponses = ["not ok", "ok", "ko",
                        "okay*", "O.K.", "^why does everyone say that ._.",
                        "\x01ACTION ok's %s\x01" % msg.nick,
                        "no", "Objection! \x02Not\x02 okay!", "meh",
                        "yeah ok w/e man.", "\x01ACTION sighs\x01",
                        "you're pretty ok.", "hmph", "I AGREE WITH YOU, "+msg.nick+dots]
                    r = random.randint(1, 23)
                    if r >= 19:
                        irc.queueMsg(ircmsgs.action(msg.args[0], random.choice(volatile)+msg.nick))
                    elif r >= 8:
                        irc.queueMsg(ircmsgs.privmsg(msg.args[0], random.choice(okresponses)))
            if irc.network.lower() in ("overdrive-irc", "stripechat") and \
                ('aXRsZXIgYmxvc3NvbQ==').decode('base'+'64') in ircutils.stripFormatting(msg.args[1].lower()):
                irc.queueMsg(ircmsgs.privmsg(msg.args[0], msg.nick + ": the entire topic changes" + exclaim))
 #           if irc.network.lower() == "stripechat":
 #               r = random.random()
 #               if msg.args[1].lower().startswith("&topic") and "hackinbot" in msg.args[1].lower() \
 #                   and r >= 0.3:
 #                   irc.queueMsg(ircmsgs.privmsg(msg.args[0], "OH, hackinbot! " + random.choice(gemotes)))

    def _lazyhostmask(self, host):
        return "*!"+host.split("!",1)[1]

    def vote(self, irc, msg, args, action):
        """<thing>

        Votes for something. It doesn't actually perform any actions directly,
        but could be an interesting way to get user feedback."""
        try:
            if self._lazyhostmask(msg.prefix) in self.votes[action][1]:
                irc.reply("You have already voted to %s." % action)
                return
        except KeyError:
            self.votes[action] = [0, []]
        self.votes[action][0] += 1
        try:
            a, b = action.split(" ",1)
        except ValueError:
            irc.error("Not enough arguments.", Raise=True)
        irc.reply("%s voted to \x02%s\x02 %s. (Votes: \x02%s\x02)" % (msg.nick, a, b, self.votes[action][0]))
        self.votes[action][1].append(self._lazyhostmask(msg.prefix))
    vote = wrap(vote, ['text'])
    
    def voteexport(self, irc, msg, args):
        """takes no arguments.
        
        Exports votes stored in memory to file: data/%s(network).votes
        This is done automatically when the plugin is unloaded or reloaded."""
        try:
            self.exportVoteDB()
        except IOError as e:
            irc.error("IOError caught exporting DB: "+str(e))
        else:
            irc.replySuccess()
    voteexport = wrap(voteexport, ['admin'])

    def voteimport(self, irc, msg, args):
        """takes no arguments.
        
        Imports the vote database for the current network."""
        try:
            self.loadVoteDB()
        except IOError as e:
            irc.error("IOError caught importing DB: "+str(e))
        else:
            irc.replySuccess()
    voteimport = wrap(voteimport, ['admin'])
    
    def voteclear(self, irc, msg, args):
        """takes no arguments.
        
        Clears all votes stored in memory. Use with caution!"""
        self.votes = {}
        irc.replySuccess()
    voteclear = wrap(voteclear, ['admin'])
Beispiel #12
0
class Herald(callbacks.Plugin):
    """This plugin allows you to set welcome messages (heralds) to people who
    are recognized by the bot when they join a channel."""
    def __init__(self, irc):
        self.__parent = super(Herald, self)
        self.__parent.__init__(irc)
        self.db = HeraldDB(filename)
        world.flushers.append(self.db.flush)
        self.lastParts = plugins.ChannelUserDictionary()
        splitTimeout = conf.supybot.plugins.Herald.throttle.afterSplit
        self.splitters = TimeoutQueue(splitTimeout)
        self.lastHerald = plugins.ChannelUserDictionary()

    def die(self):
        if self.db.flush in world.flushers:
            world.flushers.remove(self.db.flush)
        self.db.close()
        self.__parent.die()

    def doQuit(self, irc, msg):
        # We want to observe netsplits and keep from heralding users rejoining
        # after one.
        if ircmsgs.isSplit(msg):
            self.splitters.enqueue(msg.nick)
            try:
                id = ircdb.users.getUserId(msg.prefix)
                self.splitters.enqueue(id)
            except KeyError:
                pass

    def doJoin(self, irc, msg):
        if ircutils.strEqual(irc.nick, msg.nick):
            return  # It's us.
        if msg.nick in self.splitters:
            self.log.debug('Not heralding %s, recent split.', msg.nick)
            return  # Recently split.
        channel = msg.args[0]
        irc = callbacks.SimpleProxy(irc, msg)
        if self.registryValue('heralding', channel):
            try:
                id = ircdb.users.getUserId(msg.prefix)
                if id in self.splitters:
                    self.log.debug('Not heralding id #%s, recent split.', id)
                    return
                herald = self.db[channel, id]
            except KeyError:
                default = self.registryValue('default', channel)
                if default:
                    default = ircutils.standardSubstitute(irc, msg, default)
                    msgmaker = ircmsgs.privmsg
                    if self.registryValue('default.notice', channel):
                        msgmaker = ircmsgs.notice
                    target = msg.nick
                    if self.registryValue('default.public', channel):
                        target = channel
                    irc.queueMsg(msgmaker(target, default))
                return
            now = time.time()
            throttle = self.registryValue('throttle', channel)
            if now - self.lastHerald.get((channel, id), 0) > throttle:
                if (channel, id) in self.lastParts:
                    i = self.registryValue('throttle.afterPart', channel)
                    if now - self.lastParts[channel, id] < i:
                        return
                self.lastHerald[channel, id] = now
                herald = ircutils.standardSubstitute(irc, msg, herald)
                irc.reply(herald, prefixNick=False)

    def doPart(self, irc, msg):
        try:
            id = self._getId(irc, msg.prefix)
            self.lastParts[msg.args[0], id] = time.time()
        except KeyError:
            pass

    def _getId(self, irc, userNickHostmask):
        try:
            id = ircdb.users.getUserId(userNickHostmask)
        except KeyError:
            if not ircutils.isUserHostmask(userNickHostmask):
                hostmask = irc.state.nickToHostmask(userNickHostmask)
                id = ircdb.users.getUserId(hostmask)
            else:
                raise KeyError
        return id

    @internationalizeDocstring
    def default(self, irc, msg, args, channel, optlist, text):
        """[<channel>] [--remove|<msg>]

        If <msg> is given, sets the default herald to <msg>.  A <msg> of ""
        will remove the default herald.  If <msg> is not given, returns the
        current default herald.  <channel> is only necessary if the message
        isn't sent in the channel itself.
        """
        if optlist and text:
            raise callbacks.ArgumentError
        for (option, foo) in optlist:
            if option == 'remove':
                self.setRegistryValue('default', '', channel)
                irc.replySuccess()
                return
        if text:
            self.setRegistryValue('default', text, channel)
            irc.replySuccess()
        else:
            resp = self.registryValue('default', channel) or \
                   _('I do not have a default herald set for %s.') % channel
            irc.reply(resp)

    default = wrap(
        default,
        ['channel', getopts({'remove': ''}),
         additional('text')])

    @internationalizeDocstring
    def get(self, irc, msg, args, channel, user):
        """[<channel>] [<user|nick>]

        Returns the current herald message for <user> (or the user
        <nick|hostmask> is currently identified or recognized as).  If <user>
        is not given, defaults to the user giving the command.  <channel>
        is only necessary if the message isn't sent in the channel itself.
        """
        try:
            herald = self.db[channel, user.id]
            irc.reply(herald)
        except KeyError:
            irc.error(_('I have no herald for %s.') % user.name)

    get = wrap(get, ['channel', first('otherUser', 'user')])

    def _preCheck(self, irc, msg, user):
        capability = self.registryValue('requireCapability')
        if capability:
            try:
                u = ircdb.users.getUser(msg.prefix)
            except KeyError:
                irc.errorNotRegistered(Raise=True)
            else:
                if u != user:
                    if not ircdb.checkCapability(msg.prefix, capability):
                        irc.errorNoCapability(capability, Raise=True)

    # I chose not to make <user|nick> optional in this command because
    # if it's not a valid username (e.g., if the user tyops and misspells a
    # username), it may be nice not to clobber the user's herald.
    @internationalizeDocstring
    def add(self, irc, msg, args, channel, user, herald):
        """[<channel>] <user|nick> <msg>

        Sets the herald message for <user> (or the user <nick|hostmask> is
        currently identified or recognized as) to <msg>.  <channel> is only
        necessary if the message isn't sent in the channel itself.
        """
        self._preCheck(irc, msg, user)
        self.db[channel, user.id] = herald
        irc.replySuccess()

    add = wrap(add, ['channel', 'otherUser', 'text'])

    @internationalizeDocstring
    def remove(self, irc, msg, args, channel, user):
        """[<channel>] [<user|nick>]

        Removes the herald message set for <user>, or the user
        <nick|hostmask> is currently identified or recognized as.  If <user>
        is not given, defaults to the user giving the command.
        <channel> is only necessary if the message isn't sent in the channel
        itself.
        """
        self._preCheck(irc, msg, user)
        try:
            del self.db[channel, user.id]
            irc.replySuccess()
        except KeyError:
            irc.error(_('I have no herald for that user.'))

    remove = wrap(remove, ['channel', first('otherUser', 'user')])

    @internationalizeDocstring
    def change(self, irc, msg, args, channel, user, changer):
        """[<channel>] [<user|nick>] <regexp>

        Changes the herald message for <user>, or the user <nick|hostmask> is
        currently identified or recognized as, according to <regexp>.  If
        <user> is not given, defaults to the calling user. <channel> is only
        necessary if the message isn't sent in the channel itself.
        """
        self._preCheck(irc, msg, user)
        s = self.db[channel, user.id]
        newS = changer(s)
        self.db[channel, user.id] = newS
        irc.replySuccess()

    change = wrap(
        change,
        ['channel', first('otherUser', 'user'), 'regexpReplacer'])
Beispiel #13
0
class Bitbucket(callbacks.PluginRegexp):
    """Add the help for "@plugin help Bitbucket" here
    This should describe *how* to use this plugin."""
    threaded = True
    callBefore = ['URL', 'Web']
    unaddressedRegexps = ['snarfPullRequest']

    def __init__(self, irc):
        self.__parent = super(Bitbucket, self)
        self.__parent.__init__(irc)
        self.timeout_queue = TimeoutQueue(self.registryValue('snarferTimeout'))

    def _getResponse(self, id):
        queryurl = 'https://bitbucket.org/api/2.0/repositories/{0}/{1}/pullrequests/{2}'.format(
            self.registryValue('accountname'), self.registryValue('repo_slug'),
            id)
        r = requests.get(queryurl)

        self.log.info('Getting pull request from %s' % queryurl)
        if r.status_code != requests.codes.ok:
            return "pull-request not found: #" + str(id)

        return str(PullRequest(self, r.json()))

    def _check_timeout(self, id):
        if id in self.timeout_queue:
            return False

        self.timeout_queue.enqueue(id)
        return True

    def open(self, irc, msg, args):
        """
        List open pull request."""
        queryurl = 'https://bitbucket.org/api/2.0/repositories/{0}/{1}/pullrequests'.format(
            self.registryValue('accountname'), self.registryValue('repo_slug'))
        r = requests.get(queryurl)

        self.log.info('Getting pull request from %s' % queryurl)
        if r.status_code != requests.codes.ok:
            irc.reply("Url not found: " + queryurl)
            return

        data = r.json()
        if 'values' in data:
            for entry in data['values']:
                irc.reply(str(PullRequest(self, entry)), prefixNick=False)

    def snarfPullRequest(self, irc, msg, match):
        r"""(?P<type>pull request|pull-request|pullrequest)[\s#]*(?P<id>\d+)"""
        channel = msg.args[0]
        #if not self.registryValue('bugSnarfer', channel): return

        id_matches = match.group('id').split()
        type = match.group('type')

        self.log.debug('Snarfed pull request ID(s): ' + ' '.join(id_matches))
        # Check if the bug has been already snarfed in the last X seconds
        msgs = []
        for id in id_matches:
            if not self._check_timeout(id):
                continue
            response = self._getResponse(id)
            if response:
                msgs.append(response)

        for msg in msgs:
            irc.reply(msg, prefixNick=False)
Beispiel #14
0
 def __init__(self, irc):
     self.__parent = super(Bitbucket, self)
     self.__parent.__init__(irc)
     self.timeout_queue = TimeoutQueue(self.registryValue('snarferTimeout'))
Beispiel #15
0
    def relay(self, irc, msg, channel=None):
        channel = (channel or msg.args[0]).lower()
        self.log.debug("RelayNext (%s): got channel %s", irc.network, channel)
        if not channel in irc.state.channels:
            return

        # Check for ignored events first. Checking for "'.' not in msg.nick" is for skipping
        # ignore checks from servers.
        ignoredevents = map(str.upper,
                            self.registryValue('events.userIgnored', channel))
        if msg.command in ignoredevents and msg.nick != irc.nick and '.' not in msg.nick and\
                ircdb.checkIgnored(msg.prefix, channel):
            self.log.debug("RelayNext (%s): ignoring message from %s",
                           irc.network, msg.prefix)
            return

        # Get the source channel
        source = "%s@%s" % (channel, irc.network)
        source = source.lower()

        out_s = self._format(irc, msg, channel)
        if out_s:
            for relay in self.db.values():
                self.log.debug("RelayNext (%s): check if %s in %s",
                               irc.network, source, relay)
                if source in relay:  # If our channel is in a relay
                    self.log.debug("RelayNext: found %s to be in relay %s",
                                   source, relay)

                    # Remove ourselves from the target channels so we don't get duplicated messages
                    targets = list(relay)
                    targets.remove(source)

                    self.log.debug("RelayNext: found targets %s for relay %s",
                                   targets, relay)

                    if self.registryValue("antiflood.enable", channel):
                        # Flood prevention timeout - how long commands of a certain type
                        # should cease being relayed after flood prevention triggers
                        timeout = self.registryValue("antiflood.timeout",
                                                     channel)

                        # If <maximum> messages of the same kind on one channel is
                        # received in <seconds> seconds, flood prevention timeout is
                        # triggered.
                        maximum = self.registryValue("antiflood.maximum",
                                                     channel)
                        seconds = self.registryValue("antiflood.seconds",
                                                     channel)

                        # Store the message in a counter, with the keys taking the
                        # form of (source channel@network, command name). If the counter
                        # doesn't already exist, create one here.
                        try:
                            self.msgcounters[(source,
                                              msg.command)].enqueue(msg.prefix)
                        except KeyError:
                            self.msgcounters[(
                                source, msg.command)] = TimeoutQueue(seconds)

                        # Two different limits: one for messages and one for all others
                        if msg.command == "PRIVMSG":
                            maximum = self.registryValue(
                                "antiflood.maximum", channel)
                        else:
                            maximum = self.registryValue(
                                "antiflood.maximum.nonPrivmsgs", channel)

                        if len(self.msgcounters[(source,
                                                 msg.command)]) > maximum:
                            # Amount of messages in the counter surpassed our limit,
                            # announce the flood and block relaying messages of the
                            # same type for X seconds
                            self.log.debug(
                                "RelayNext (%s): message from %s blocked by "
                                "flood protection.", irc.network, channel)

                            if self.floodTriggered.get((source, msg.command)):
                                # However, only send the announcement once.
                                return

                            c = msg.command
                            e = format(
                                "Flood detected on %s (%s %ss/%s seconds), "
                                "not relaying %ss for %s seconds!", channel,
                                maximum, c, seconds, c, timeout)
                            out_s = self._format(irc,
                                                 msg,
                                                 channel,
                                                 announcement=e)

                            self.floodTriggered[(source, msg.command)] = True
                            self.log.info("RelayNext (%s): %s", irc.network, e)
                        else:
                            self.floodTriggered[(source, msg.command)] = False

                    for cn in targets:
                        # Iterate over all the relay targets for this message:
                        # each target is stored internally as a #channel@netname
                        # string.
                        target, net = cn.split("@")
                        otherIrc = world.getIrc(net)
                        if otherIrc is None:
                            self.log.debug(
                                "RelayNext: message to network %r"
                                " dropped, we are not connected "
                                "there!", net)
                            return

                        target_chanobj = otherIrc.state.channels.get(target)
                        if (not target_chanobj
                            ) or otherIrc.nick not in target_chanobj.users:
                            # We're not in the target relay channel!
                            self.log.debug(
                                "RelayNext: message to %s@%s "
                                "dropped, we are not in that "
                                "channel!", target, net)
                        else:
                            out_msg = ircmsgs.privmsg(target, out_s)

                            # Tag the message as relayed so we (and other relayers) don't
                            # try to relay it again.
                            out_msg.tag('relayedMsg')
                            otherIrc.queueMsg(out_msg)
Beispiel #16
0
class RelayLink(callbacks.Plugin):
    # noIgnore = True
    threaded = True

    class Relay():
        def __init__(self, sourceChannel, sourceNetwork, targetChannel,
                     targetNetwork, channelRegex, networkRegex, messageRegex):
            self.sourceChannel = sourceChannel
            self.sourceNetwork = sourceNetwork
            self.targetChannel = targetChannel
            self.targetNetwork = targetNetwork
            self.channelRegex = channelRegex
            self.networkRegex = networkRegex
            self.messageRegex = messageRegex
            self.hasTargetIRC = False
            self.hasSourceIRCChannels = False

    def __init__(self, irc):
        self.__parent = super(RelayLink, self)
        self.__parent.__init__(irc)
        self._loadFromConfig()
        self.ircstates = {}
        for IRC in world.ircs:
            self.addIRC(IRC)
        floodProtectTimeout = conf.supybot.plugins.RelayLink.antiflood.seconds
        self.floodCounter = TimeoutQueue(floodProtectTimeout)
        self.floodActivated = False
        try:
            conf.supybot.plugins.RelayLink.substitutes.addCallback(
                    self._loadFromConfig)
            conf.supybot.plugins.RelayLink.relays.addCallback(
                    self._loadFromConfig)
        except registry.NonExistentRegistryEntry:
            log.error("Your version of Supybot is not compatible with "
                      "configuration hooks. So, RelayLink won't be able "
                      "to reload the configuration if you use the Config "
                      "plugin.")

    def _loadFromConfig(self, name=None):
        self.relays = []
        for relay in self.registryValue('relays').split(' || '):
            if relay.endswith('|'):
                relay += ' '
            relay = relay.split(' | ')
            if not len(relay) == 5:
                continue
            try:
                self.relays.append(self.Relay(relay[0],
                                          relay[1],
                                          relay[2],
                                          relay[3],
                                          re.compile('^%s$' % relay[0], re.I),
                                          re.compile('^%s$' % relay[1], re.I),
                                          re.compile(relay[4])))
            except:
                log.error('Failed adding relay: %r' % relay)

        self.nickSubstitutions = {}
        for substitute in self.registryValue('substitutes').split(' || '):
            if substitute.endswith('|'):
                substitute += ' '
            substitute = substitute.split(' | ')
            if not len(substitute) == 2:
                continue
            self.nickSubstitutions[substitute[0]] = substitute[1]

    def simpleHash(self, s):
        colors = ["05", "04", "03", "09", "02", "12",
                  "06", "13", "10", "11", "07"]
        num = 0
        for i in s:
            num += ord(i)
        num = num % 11
        return colors[num]

    def getPrivmsgData(self, channel, nick, text, colored):
        color = self.simpleHash(nick)
        nickprefix = ''
        if nick in self.nickSubstitutions:
            nick = self.nickSubstitutions[nick]
        if not self.registryValue('nicks', channel):
            nick = ''
        elif self.registryValue('noHighlight', channel):
            nickprefix = '-'
        if re.match('^\x01ACTION .*\x01$', text):
            text = text.strip('\x01')
            text = text[ 7 : ]
            if colored:
                return ('%(network)s* %(nickprefix)s\x03%(color)s%(nick)s\x03 %(text)s',
                        {'nick': nick, 'color': color, 'text': text,
                        'nickprefix': nickprefix})
            else:
                return ('%(network)s* %(nickprefix)s%(nick)s %(text)s',
                        {'nick': nick, 'text': text, 'nickprefix': nickprefix})
        else:
            if colored:
                return ('%(network)s<%(nickprefix)s\x03%(color)s%(nick)s\x03> %(text)s',
                        {'color': color, 'nick': nick, 'text': text,
                        'nickprefix': nickprefix})
            else:
                return ('%(network)s<%(nickprefix)s%(nick)s> %(text)s',
                        {'nick': nick, 'text': text, 'nickprefix': nickprefix})
        return s

    @internationalizeDocstring
    def list(self, irc, msg, args):
        """takes no arguments

        Returns all the defined relay links."""
        if irc.nested:
            irc.error('This command cannot be nested.', Raise=True)
        elif not self.relays:
            irc.reply(_('This is no relay enabled. Use "RelayLink add" "RelayLink'
                ' addall" to add one.'))
            return
        for relay in self.relays:
            if relay.hasTargetIRC:
                hasIRC = 'Link healthy!'
            else:
                hasIRC = '\x0302IRC object not scraped yet.\017'
            s ='\x02%s\x02 on \x02%s\x02 ==> \x02%s\x02 on \x02%s\x02.  %s'
            if not self.registryValue('color', msg.args[0]):
                s = s.replace('\x02', '')
            irc.reply(s %
                        (relay.sourceChannel,
                         relay.sourceNetwork,
                         relay.targetChannel,
                         relay.targetNetwork,
                         hasIRC), private=True)

    def doPrivmsg(self, irc, msg):
        self.addIRC(irc)
        channel = msg.args[0]
        s = msg.args[1]
        s, args = self.getPrivmsgData(channel, msg.nick, s,
                               self.registryValue('color', channel))
        if channel not in irc.state.channels: # in private
            # cuts off the end of commands, so that passwords
            # won't be revealed in relayed PM's
            if callbacks.addressed(irc.nick, msg):
                if self.registryValue('color', channel):
                    color = '\x0314'
                    match = '(>\017 \w+) .*'
                else:
                    color = ''
                    match = '(> \w+) .*'
                s = re.sub(match, '\\1 %s[%s]' % (color, _('truncated')), s)
            s = '(via PM) %s' % s
        self.sendToOthers(irc, channel, s, args, isPrivmsg=True)

    def outFilter(self, irc, msg):
        if msg.command == 'PRIVMSG':
            if not msg.relayedMsg:
                if msg.args[0] in irc.state.channels:
                    s, args = self.getPrivmsgData(msg.args[0], irc.nick, msg.args[1],
                                    self.registryValue('color', msg.args[0]))
                    self.sendToOthers(irc, msg.args[0], s, args, isPrivmsg=True)
        return msg

    def doPing(self, irc, msg):
        self.addIRC(irc)

    def doMode(self, irc, msg):
        self.addIRC(irc)
        args = {'nick': msg.nick, 'channel': msg.args[0],
                'mode': ' '.join(msg.args[1:]), 'userhost': ''}
        if self.registryValue("noHighlight", msg.args[0]):
            args['nick'] = '-'+msg.nick
        if self.registryValue('color', msg.args[0]):
            args['nick'] = '\x03%s%s\x03' % (self.simpleHash(msg.nick), args['nick'])
        if self.registryValue('hostmasks', msg.args[0]) and "." not in \
            msg.nick:
            args['userhost'] = ' (%s@%s)' % (msg.user, msg.host)
        s = ('%(network)s%(nick)s%(userhost)s set mode %(mode)s on'
             ' %(channel)s')
        self.sendToOthers(irc, msg.args[0], s, args)

    def doJoin(self, irc, msg):
        args = {'nick': msg.nick, 'channel': msg.args[0], 'userhost': ''}
        if self.registryValue("noHighlight", msg.args[0]):
            args['nick'] = '-'+msg.nick
        if irc.nick == msg.nick:
            if self.registryValue('color'):
                s = '%(network)s\x0309*** Relay joined to %(channel)s'
            else:
                s = '%(network)s*** Relay joined to %(channel)s'
        else:
            if self.registryValue('color', msg.args[0]):
                args['nick'] = '\x03%s%s\x03' % (self.simpleHash(msg.nick), args['nick'])
            if self.registryValue('hostmasks', msg.args[0]):
                args['userhost'] = ' (%s@%s)' % (msg.user, msg.host)
            s = '%(network)s%(nick)s%(userhost)s has joined %(channel)s'
        self.addIRC(irc)
        self.sendToOthers(irc, msg.args[0], s, args)

    def doPart(self, irc, msg):
        args = {'nick': msg.nick, 'channel': msg.args[0], 'message': '',
                'userhost': ''}
        if msg.nick == irc.nick:
            if self.registryValue('color'):
                s = '%(network)s\x0308*** Relay parted from %(channel)s'
            else:
                s = '%(network)s*** Relay parted from %(channel)s'
        else:
            if self.registryValue("noHighlight", msg.args[0]):
                args['nick'] = '-'+msg.nick
            self.addIRC(irc)
            if self.registryValue('color', msg.args[0]):
                args['nick'] = '\x03%s%s\x03' % (self.simpleHash(msg.nick), args['nick'])
            if self.registryValue('hostmasks', msg.args[0]):
                args['userhost'] = ' (%s@%s)' % (msg.user, msg.host)
            try:
                args['message'] = ' (%s)' % (msg.args[1])
            except IndexError: pass
            s = '%(network)s%(nick)s%(userhost)s has parted %(channel)s%(message)s'
        self.sendToOthers(irc, msg.args[0], s, args)

    def doKick(self, irc, msg):
        self.addIRC(irc)
        args = {'kicked': msg.args[1], 'channel': msg.args[0],
                'kicker': msg.nick, 'message': msg.args[2], 'userhost': ''}
        if args['kicked'] == irc.nick:
            if self.registryValue('color', msg.args[0]):
                s = '%(network)s\x0308*** Relay kicked from %(channel)s'
            else:
                s = '%(network)s*** Relay kicked from %(channel)s'
        else:
            if self.registryValue('color', msg.args[0]):
                args['kicked'] = '\x03%s%s\x03' % (self.simpleHash(msg.args[1]), args['kicked'])
            if self.registryValue('hostmasks', msg.args[0]):
                # The IRC protocol only sends the hostmask of the kicker, so we'll need
                # to use an alternate method to fetch the host of the person being
                # kicked. (in this case, using ircutils)
                h = ircutils.splitHostmask(irc.state.nickToHostmask(msg.args[1]))
                args['userhost'] = ' (%s@%s)' % (h[1], h[2])
            s = ('%(network)s%(kicked)s%(userhost)s has been kicked from '
                 '%(channel)s by %(kicker)s (%(message)s)')
        self.sendToOthers(irc, msg.args[0], s, args)

    def doNick(self, irc, msg):
        self.addIRC(irc)
        if self.registryValue("noHighlight"):
            args = {'oldnick': '-'+msg.nick, 'newnick': '-'+msg.args[0]}
        else:
            args = {'oldnick': msg.nick, 'newnick': msg.args[0]}
        if self.registryValue('color'):
            args['oldnick'] = '\x03%s%s\x03' % (self.simpleHash(msg.nick), args['oldnick'])
            args['newnick'] = '\x03%s%s\x03' % (self.simpleHash(msg.args[0]), args['newnick'])
        s = '%(network)s%(oldnick)s is now known as %(newnick)s'
        try:
            chandict = irc.state.channels.iteritems()
        except AttributeError: # Python 3 compatibility
             chandict = irc.state.channels.items()
        for (channel, c) in chandict:
            if msg.args[0] in c.users:
                self.sendToOthers(irc, channel, s, args)

    def doQuit(self, irc, msg):
        args = {'nick': msg.nick, 'message': msg.args[0]}
        if self.registryValue("noHighlight"): args['nick'] = '-' + msg.nick
        if msg.nick == irc.nick: # It's us.
            if self.registryValue('color'):
                s = '%(network)s\x0304*** ERROR: Relay disconnected...'
            else:
                s = '%(network)s*** ERROR: Relay disconnected...'
        else:
            if self.registryValue('color'):
                args['nick'] = '\x03%s%s\x03' % (self.simpleHash(msg.nick), args['nick'])
            s = '%(network)s%(nick)s has quit (%(message)s)'
        self.sendToOthers(irc, None, s, args, msg.nick)
        self.addIRC(irc)

    def sendToOthers(self, irc, channel, s, args, nick=None, isPrivmsg=False):
        assert channel is not None or nick is not None
        def format_(relay, s, args):
            if 'network' not in args:
                if self.registryValue('includeNetwork', relay.targetChannel):
                    if self.registryValue('color', relay.targetChannel):
                        args['network'] = "\x02[\x03%s%s\x03]\x02 " % \
                            (self.simpleHash(irc.network), irc.network)
                    else:
                        args['network'] = "[%s] " % irc.network
                    if not isPrivmsg and not self.registryValue("noHighlight", channel):
                        args['network'] += "- "
                else:
                    args['network'] = ''
            return s % args
        def send(s):
            if not relay.hasTargetIRC:
                self.log.info('RelayLink:  IRC %s not yet scraped.' %
                              relay.targetNetwork)
            elif relay.targetIRC.zombie:
                self.log.info('RelayLink:  IRC %s appears to be a zombie'%
                              relay.targetNetwork)
            elif irc.isChannel(relay.targetChannel) and \
                    relay.targetChannel not in relay.targetIRC.state.channels:
                self.log.info('RelayLink:  I\'m not in in %s on %s' %
                              (relay.targetChannel, relay.targetNetwork))
            else:
                if isPrivmsg or \
                        self.registryValue('nonPrivmsgs', channel) == 'privmsg':
                    msg = ircmsgs.privmsg(relay.targetChannel, s)
                elif self.registryValue('nonPrivmsgs', channel) == 'notice':
                    msg = ircmsgs.notice(relay.targetChannel, s)
                else:
                    return
                msg.tag('relayedMsg')
                relay.targetIRC.sendMsg(msg)
        
        msgs = self.registryValue("antiflood.messages")
        if self.registryValue("antiflood.enable") and msgs and \
            len(self.floodCounter) > msgs:
            if not self.floodActivated:
                secs = self.registryValue("antiflood.seconds")
                limit = "({} messages in {} seconds)".format(msgs,secs)
                self.log.info("RelayLink: flood protection triggered on {} {}".format(irc.network,limit))
                s = ("%(network)s*** Flood detected {}. Not relaying messages for {} seconds!".format(limit, secs))
                self.floodActivated = True
                if self.registryValue('antiflood.announce'):
                    for relay in self.relays:
                        new_s = format_(relay, s, args)
                        if relay.channelRegex.match(channel) and \
                            relay.networkRegex.match(irc.network) and \
                            relay.messageRegex.search(new_s):
                            send(new_s)
            return
        else: self.floodActivated = False
        
        if channel is None:
            for relay in self.relays:
                if not relay.hasSourceIRCChannels:
                    continue
                for channel in relay.sourceIRCChannels:
                    new_s = format_(relay, s, args)
                    if nick in relay.sourceIRCChannels[channel].users and \
                            relay.channelRegex.match(channel) and \
                            relay.networkRegex.match(irc.network)and \
                            relay.messageRegex.search(new_s):
                        if nick != irc.nick: self.floodCounter.enqueue(0)
                        send(new_s)
        else:
            for relay in self.relays:
                new_s = format_(relay, s, args)
                if relay.channelRegex.match(channel) and \
                        relay.networkRegex.match(irc.network) and \
                        relay.messageRegex.search(new_s):
                    if nick != irc.nick:
                        if isPrivmsg: self.floodCounter.enqueue(0)
                        else: self.floodCounter.enqueue(0)
                    send(new_s)

    def addIRC(self, irc):
        match = False
        for relay in self.relays:
            if relay.sourceNetwork == irc.network:
                relay.sourceIRCChannels = copy.deepcopy(irc.state.channels)
                relay.hasSourceIRCChannels = True
            if relay.targetNetwork == irc.network and not relay.hasTargetIRC:
                relay.targetIRC = irc
                relay.hasTargetIRC = True

    @internationalizeDocstring
    def nicks(self, irc, msg, args, channel, optlist):
        """[<channel>] [--count]

        Returns the nicks of the people in the linked channels.
        <channel> is only necessary if the message
        isn't sent on the channel itself.
        If --count is specified, only the amount of """
        keys = [option for (option, arg) in optlist]
        if irc.nested and 'count' not in keys:
            irc.error('This command cannot be nested.', Raise=True)
        if msg.nick not in irc.state.channels[channel].users:
            self.log.warning('RelayLink: %s on %s attempted to view'
                ' nicks in %s without being in it.'
                % (msg.nick, irc.network, channel))
            irc.error(('You are not in %s.' % channel), Raise=True)
        # Include the local channel for nicks output
        c = irc.state.channels[channel]
        totalUsers = len(c.users)
        totalChans = 1
        users = []
        for s in c.users:
            s = s.strip()
            if not s:
                continue
            if s in c.ops:
                users.append('@%s' % s)
            elif s in c.halfops:
                users.append('%%%s' % s)
            elif s in c.voices:
                users.append('+%s' % s)
            else:
                users.append(s)
        s = _('%d users in %s on %s:  %s') % (totalUsers,
            channel, irc.network,
            utils.str.commaAndify(users))
        if 'count' not in keys: irc.reply(s, private=True)
        for relay in self.relays:
            if relay.sourceChannel == channel and \
                    relay.sourceNetwork.lower() == irc.network.lower():
                totalChans += 1
                if not relay.hasTargetIRC:
                    irc.reply(_('I haven\'t scraped the IRC object for %s '
                              'yet. Try again in a minute or two.') % \
                              relay.targetNetwork)
                else:
                    users = []
                    ops = []
                    halfops = []
                    voices = []
                    normals = []
                    numUsers = 0
                    target = relay.targetChannel

                    channels = relay.targetIRC.state.channels
                    found = False
                    for key, channel_ in channels.items():
                        #if re.match(relay.targetChannel, key):
                        if ircutils.toLower(relay.targetChannel) \
                            == ircutils.toLower(key):
                            found = True
                            break
                    if not found:
                        continue

                    for s in channel_.users:
                        s = s.strip()
                        if not s:
                            continue
                        numUsers += 1
                        totalUsers += 1
                        if s in channel_.ops:
                            users.append('@%s' % s)
                        elif s in channel_.halfops:
                            users.append('%%%s' % s)
                        elif s in channel_.voices:
                            users.append('+%s' % s)
                        else:
                            users.append(s)
                    #utils.sortBy(ircutils.toLower, ops)
                    #utils.sortBy(ircutils.toLower, halfops)
                    #utils.sortBy(ircutils.toLower, voices)
                    #utils.sortBy(ircutils.toLower, normals)
                    users.sort()
                    msg.tag('relayedMsg')
                    s = _('%d users in %s on %s:  %s') % (numUsers,
                            relay.targetChannel,
                            relay.targetNetwork,
                            utils.str.commaAndify(users))
                    if 'count' not in keys: irc.reply(s, private=True)
        if not irc.nested: 
            irc.reply("Total users across %d channels: %d. " % \
                (totalChans, totalUsers), private=False if 'count' in keys else True)
        else:
            irc.reply(totalUsers)
        irc.noReply()
    nicks = wrap(nicks, ['Channel', getopts({'count':''})])

    # The following functions handle configuration
    def _writeToConfig(self, from_, to, regexp, add):
        from_, to = from_.split('@'), to.split('@')
        args = from_
        args.extend(to)
        args.append(regexp)
        s = ' | '.join(args)

        currentConfig = self.registryValue('relays')
        config = list(map(ircutils.IrcString, currentConfig.split(' || ')))
        if add:
            if s in config:
                return False
            if currentConfig == '':
                self.setRegistryValue('relays', value=s)
            else:
                self.setRegistryValue('relays',
                                      value=' || '.join((currentConfig, s)))
        else:
            if s not in config:
                return False
            config.remove(s)
            self.setRegistryValue('relays', value=' || '.join(config))
        return True

    def _parseOptlist(self, irc, msg, tupleOptlist, batchadd=False):
        optlist = {}
        for key, value in tupleOptlist:
            optlist.update({key: value})
        if not batchadd:
            if 'from' not in optlist and 'to' not in optlist:
                irc.error(_('You must give at least --from or --to.'))
                return
            for name in ('from', 'to'):
                if name not in optlist:
                    optlist.update({name: '%s@%s' % (msg.args[0], irc.network)})
            if 'reciprocal' in optlist:
                optlist.update({'reciprocal': True})
            else:
                optlist.update({'reciprocal': False})
            if not len(optlist['from'].split('@')) == 2:
                irc.error(_('--from should be like "--from #channel@network"'))
                return
            if not len(optlist['to'].split('@')) == 2:
                irc.error(_('--to should be like "--to #channel@network"'))
                return
        if 'regexp' not in optlist:
            optlist.update({'regexp': ''})
        return optlist

    @internationalizeDocstring
    def add(self, irc, msg, args, optlist):
        """[--from <channel>@<network>] [--to <channel>@<network>] [--regexp <regexp>] [--reciprocal]

        Adds a relay to the list. You must give at least --from or --to; if
        one of them is not given, it defaults to the current channel@network.
        Only messages matching <regexp> will be relayed; if <regexp> is not
        given, everything is relayed.
        If --reciprocal is given, another relay will be added automatically,
        in the opposite direction."""
        optlist = self._parseOptlist(irc, msg, optlist)
        if optlist is None:
            return

        failedWrites = 0
        if not self._writeToConfig(optlist['from'], optlist['to'],
                                   optlist['regexp'], True):
            failedWrites += 1
        if optlist['reciprocal']:
            if not self._writeToConfig(optlist['to'], optlist['from'],
                                       optlist['regexp'], True):
                failedWrites += 1

        self._loadFromConfig()
        if failedWrites == 0:
            irc.replySuccess()
        else:
            irc.error(_('One (or more) relay(s) already exists and has not '
                        'been added.'))
    add = wrap(add, [('checkCapability', 'admin'),
                     getopts({'from': 'something',
                              'to': 'something',
                              'regexp': 'something',
                              'reciprocal': ''})])

    def addall(self, irc, msg, args, optlist, channels):
        """[--regexp <regexp>] <channel1@network1> <channel2@network2> [<channel3@network3>] ...
        
        Batch adds all the relays/reciprocals between the channels defined. Useful if you are
        relaying to more than 2 networks/channels with one bot, as a large amount of
        reciprocals easily becomes a mess.
        Only messages matching <regexp> will be relayed; if <regexp> is not
        given, everything is relayed."""
        optlist = self._parseOptlist(irc, msg, optlist, batchadd=True)
        channels = channels.split()
        if len(channels) < 2:
            irc.error('Not enough channels specified to relay! (needs at least 2)', Raise=True)
        if len(channels) > self.registryValue('addall.max'):
            irc.error('Too many channels specified, aborting. (see config plugins.RelayLink.addall.max)', Raise=True)
        for ch in channels:
            if len(ch.split("@")) != 2: 
                irc.error("Channels must be specified in the format #channel@network", Raise=True)
        failedWrites = writes = 0
        # Get all the channel combinations and try to add them one by one
        p = itertools.permutations(channels, 2)
        for c in p:
            if not self._writeToConfig(c[0], c[1],
                                   optlist['regexp'], True):
                failedWrites += 1
                if self.registryValue('logFailedChanges'):
                    self.log.warning("RelayLink: failed to batch add relay: {} -> {}".format(c[0],c[1]))
            writes += 1
        self._loadFromConfig()
        if failedWrites == 0:
            irc.replySuccess()
        else:
            irc.reply('Finished, though {} out of {} relays failed to be added.'.format(failedWrites, writes))
    addall = wrap(addall, [('checkCapability', 'admin'),
                     getopts({'regexp': 'something'}), 'text'])
                     
    def removeall(self, irc, msg, args, optlist, channels):
        """[--regexp <regexp>] <channel1@network1> [<channel2@network2>] [<channel3@network3>] ...
        
        Batch removes relays. If only one channel@network is given, removes all
        relays going to and from the channel.
        Otherwise, removes all relays going between the channels defined (similar to addall)."""
        optlist = self._parseOptlist(irc, msg, optlist, batchadd=True)
        channels = channels.split()
        if len(channels) > self.registryValue('addall.max'):
            irc.error('Too many channels specified, aborting. (see config plugins.RelayLink.addall.max)', Raise=True)
        failedWrites = writes = 0
        for ch in channels:
            if len(ch.split("@")) != 2: 
                irc.error("Channels must be specified in the format #channel@network", Raise=True)
        if len(channels) == 1:
            c = tuple(channels[0].split('@'))
            for relay in self.relays:
                # semi-hack channel matching; not sure if there's a better way to do this
                if c[0] == relay.sourceChannel and c[1] == relay.sourceNetwork:
                    s = "%s@%s" % (relay.targetChannel, relay.targetNetwork)
                    if not self._writeToConfig(channels[0], s,
                        optlist['regexp'], False):
                        # This shouldn't really ever error, but we'll keep it just in case
                        failedWrites += 1
                        if self.registryValue('logFailedChanges'):
                            self.log.warning("RelayLink: failed to batch remove relay: {} -> {}".format(c[0],c[1]))
                    writes += 1
                elif c[0] == relay.targetChannel and c[1] == relay.targetNetwork:
                    s = "%s@%s" % (relay.sourceChannel, relay.sourceNetwork)
                    if not self._writeToConfig(s, channels[0],
                        optlist['regexp'], False):
                        failedWrites += 1
                        if self.registryValue('logFailedChanges'):
                            self.log.warning("RelayLink: failed to batch remove relay: {} -> {}".format(c[0],c[1]))
                    writes += 1
            if writes == 0:
                irc.error("No matching relays for %s found." % channels[0], Raise=True)
        elif len(channels) >= 2:
            # Get all the channel combinations and try to remove them one by one
            p = itertools.permutations(channels, 2)
            for c in p:
                if not self._writeToConfig(c[0], c[1],
                                       optlist['regexp'], False):
                    failedWrites += 1
                    if self.registryValue('logFailedChanges'):
                        self.log.warning("RelayLink: failed to batch remove relay: {} -> {}".format(c[0],c[1]))
                writes += 1
        self._loadFromConfig()
        if failedWrites == 0:
            irc.replySuccess()
        else:
            irc.reply('Finished, though {} out of {} relays failed to be removed.'.format(failedWrites, writes))
    removeall = wrap(removeall, [('checkCapability', 'admin'),
                     getopts({'regexp': 'something'}), 'text'])

    @internationalizeDocstring
    def remove(self, irc, msg, args, optlist):
        """[--from <channel>@<network>] [--to <channel>@<network>] [--regexp <regexp>] [--reciprocal]

        Remove a relay from the list. You must give at least --from or --to; if
        one of them is not given, it defaults to the current channel@network.
        Only messages matching <regexp> will be relayed; if <regexp> is not
        given, everything is relayed.
        If --reciprocal is given, another relay will be removed automatically,
        in the opposite direction."""
        optlist = self._parseOptlist(irc, msg, optlist)
        if optlist is None:
            return

        failedWrites = 0
        if not self._writeToConfig(optlist['from'], optlist['to'],
                                   optlist['regexp'], False):
            failedWrites += 1
        if optlist['reciprocal']:
            if not self._writeToConfig(optlist['to'], optlist['from'],
                                       optlist['regexp'], False):
                failedWrites +=1

        self._loadFromConfig()
        if failedWrites == 0:
            irc.replySuccess()
        else:
            irc.error(_('One (or more) relay(s) did not exist and has not '
                        'been removed.'))
    remove = wrap(remove, [('checkCapability', 'admin'),
                     getopts({'from': 'something',
                              'to': 'something',
                              'regexp': 'something',
                              'reciprocal': ''})])

    def _getSubstitutes(self):
        # Get a list of strings
        substitutes = self.registryValue('substitutes').split(' || ')
        if substitutes == ['']:
            return {}
        # Convert it to a list of tuples
        substitutes = [tuple(x.split(' | ')) for x in substitutes]
        # Finally, make a dictionnary
        substitutes = dict(substitutes)

        return substitutes

    def _setSubstitutes(self, substitutes):
        # Get a list of tuples from the dictionnary
        substitutes = substitutes.items()
        # Make it a list of strings
        substitutes = ['%s | %s' % (x,y) for x,y in substitutes]
        # Finally, get a string
        substitutes = ' || '.join(substitutes)

        self.setRegistryValue('substitutes', value=substitutes)

    @internationalizeDocstring
    def substitute(self, irc, msg, args, regexp, to):
        """<regexp> <replacement>

        Replaces all nicks that matches the <regexp> by the <replacement>
        string."""
        substitutes = self._getSubstitutes()
        # Don't check if it is already in the config: if will be overriden
        # automatically and that is a good thing.
        substitutes.update({regexp: to})
        self._setSubstitutes(substitutes)
        self._loadFromConfig()
        irc.replySuccess()
    substitute = wrap(substitute, [('checkCapability', 'admin'),
                                   'something',
                                   'text'])

    @internationalizeDocstring
    def nosubstitute(self, irc, msg, args, regexp):
        """<regexp>

        Undo a substitution."""
        substitutes = self._getSubstitutes()
        if regexp not in substitutes:
            irc.error(_('This regexp was not in the nick substitutions '
                        'database'))
            return
        # Don't check if it is already in the config: if will be overriden
        # automatically and that is a good thing.
        substitutes.pop(regexp)
        self._setSubstitutes(substitutes)
        self._loadFromConfig()
        irc.replySuccess()
    nosubstitute = wrap(nosubstitute, [('checkCapability', 'admin'),
                                       'something'])
    def rpm(self, irc, msg, args, remoteuser, otherIrc, text):
        """<remoteUser> <network> <text>

        Sends a private message to a user on a remote network."""
        found = found2 = False
        if not self.registryValue("remotepm.enable"):
            irc.error("This command is not enabled; please set 'config plugins.relaylink.remotepm.enable' "
                "to True.", Raise=True)
        for relay in self.relays:
            channels = otherIrc.state.channels
            for key, channel_ in channels.items():
                if ircutils.toLower(relay.targetChannel) \
                    == ircutils.toLower(key) and remoteuser in channel_.users:
                    found = True
                    break
            for ch in irc.state.channels:
                if ircutils.toLower(relay.sourceChannel) == \
                    ircutils.toLower(ch) and msg.nick in irc.state.channels[ch].users:
                    found2 = True
                    break
        if found and found2:
            prefix = msg.prefix if self.registryValue("remotepm.useHostmasks") else msg.nick
            if self.registryValue("remotepm.useNotice"):
                otherIrc.queueMsg(ircmsgs.notice(remoteuser, "Message from %s on %s: %s" % (prefix, irc.network, text)))
            else:
                otherIrc.queueMsg(ircmsgs.privmsg(remoteuser, "Message from %s on %s: %s" % (prefix, irc.network, text)))
        else:
            irc.error("User '%s' does not exist on %s or you are not sharing "
                "a channel with them." % (remoteuser, otherIrc.network), Raise=True)
    rpm = wrap(rpm, ['nick', ('networkIrc', True), 'text'])
Beispiel #17
0
 def __init__(self, irc):
     self.__parent = super(Bitbucket, self)
     self.__parent.__init__(irc)
     self.timeout_queue = TimeoutQueue(self.registryValue('snarferTimeout'))
Beispiel #18
0
class Greet(callbacks.Plugin):
    def __init__(self, irc):
        self.__parent = super(Greet, self)
        self.__parent.__init__(irc)
        self.db = GreetDB(filename)
        world.flushers.append(self.db.flush)
        self.lastParts = plugins.ChannelUserDictionary()
        splitTimeout = conf.supybot.plugins.Greet.throttle.afterSplit
        self.splitters = TimeoutQueue(splitTimeout)
        self.lastGreet = plugins.ChannelUserDictionary()

    def die(self):
        if self.db.flush in world.flushers:
            world.flushers.remove(self.db.flush)
        self.db.close()
        self.__parent.die()

    def doQuit(self, irc, msg):
        # We want to observe netsplits and keep from greeting users rejoining
        # after one.
        if ircmsgs.isSplit(msg):
            self.splitters.enqueue(msg.nick)
            try:
                id = ircdb.users.getUserId(msg.prefix)
                self.splitters.enqueue(id)
            except KeyError:
                pass

    def doJoin(self, irc, msg):
        if ircutils.strEqual(irc.nick, msg.nick):
            return # It's us.
        if msg.nick in self.splitters:
            self.log.debug('Not greeting %s, recent split.', msg.nick)
            return # Recently split.
        channel = msg.args[0]
        irc = callbacks.SimpleProxy(irc, msg)
        if self.registryValue('greeting', channel):
            try:
                id = ircdb.users.getUserId(msg.prefix)
                if id in self.splitters:
                    self.log.debug('Not greeting id #%s, recent split.', id)
                    return
                greet = self.db[channel, id]
            except KeyError:
                default = self.registryValue('default', channel)
                if default:
                    default = ircutils.standardSubstitute(irc, msg, default)
                    msgmaker = ircmsgs.privmsg
                    if self.registryValue('default.notice', channel):
                        msgmaker = ircmsgs.notice
                    target = msg.nick
                    if self.registryValue('default.public', channel):
                        target = channel
                    irc.queueMsg(msgmaker(target, default))
                return
            now = time.time()
            throttle = self.registryValue('throttle', channel)
            if now - self.lastGreet.get((channel, id), 0) > throttle:
                if (channel, id) in self.lastParts:
                   i = self.registryValue('throttle.afterPart', channel)
                   if now - self.lastParts[channel, id] < i:
                       return
                self.lastGreet[channel, id] = now
                greet = ircutils.standardSubstitute(irc, msg, greet)
                if re.search(r"/me ", greet, re.I):
                	greet = greet.replace("/me ","")
                	irc.reply(greet, prefixNick=False, action=True)
                else:
                	irc.reply(greet, prefixNick=True)

    def doPart(self, irc, msg):
        try:
            id = self._getId(irc, msg.prefix)
            self.lastParts[msg.args[0], id] = time.time()
        except KeyError:
            pass

    def _getId(self, irc, userNickHostmask):
        try:
            id = ircdb.users.getUserId(userNickHostmask)
        except KeyError:
            if not ircutils.isUserHostmask(userNickHostmask):
                hostmask = irc.state.nickToHostmask(userNickHostmask)
                id = ircdb.users.getUserId(hostmask)
            else:
                raise KeyError
        return id

    def default(self, irc, msg, args, channel, optlist, text):
        """[<channel>] [--remove|<msg>]

        If <msg> is given, sets the default greet to <msg>.  A <msg> of ""
        will remove the default greet.  If <msg> is not given, returns the
        current default greet.  <channel> is only necessary if the message
        isn't sent in the channel itself.
        """
        if optlist and text:
            raise callbacks.ArgumentError
        for (option, _) in optlist:
            if option == 'remove':
                self.setRegistryValue('default', '', channel)
                irc.replySuccess()
                return
        if text:
            self.setRegistryValue('default', text, channel)
            irc.replySuccess()
        else:
            resp = self.registryValue('default', channel) or \
                   'I do not have a default greet set for %s.' % channel
            irc.reply(resp)
    default = wrap(default, ['channel',
                             getopts({'remove': ''}),
                             additional('text')])

    def get(self, irc, msg, args, channel, user):
        """[<channel>] [<user|nick>]

        Returns the current greet message for <user> (or the user
        <nick|hostmask> is currently identified or recognized as).  If <user>
        is not given, defaults to the user giving the command.  <channel>
        is only necessary if the message isn't sent in the channel itself.
        """
        try:
            greet = self.db[channel, user.id]
            irc.reply(greet)
        except KeyError:
            irc.error('I have no greet for %s.' % user.name)
    get = wrap(get, ['channel', first('otherUser', 'user')])

    def _preCheck(self, irc, msg, user):
        capability = self.registryValue('requireCapability')
        if capability:
            try:
                u = ircdb.users.getUser(msg.prefix)
            except KeyError:
                irc.errorNotRegistered(Raise=True)
            else:
                if u != user:
                    if not ircdb.checkCapability(msg.prefix, capability):
                        irc.errorNoCapability(capability, Raise=True)

    # I chose not to make <user|nick> optional in this command because
    # if it's not a valid username (e.g., if the user tyops and misspells a
    # username), it may be nice not to clobber the user's greet.
    def greet(self, irc, msg, args, channel, user, greet):
        """[<channel>] <user|nick> <msg>

        Sets the greet message for <user> (or the user <nick|hostmask> is
        currently identified or recognized as) to <msg>.  <channel> is only
        necessary if the message isn't sent in the channel itself.
        """
        self._preCheck(irc, msg, user)
        self.db[channel, user.id] = greet
        irc.replySuccess()
    greet = wrap(greet, ['channel', 'otherUser', 'text'])

    def remove(self, irc, msg, args, channel, user):
        """[<channel>] [<user|nick>]

        Removes the greet message set for <user>, or the user
        <nick|hostmask> is currently identified or recognized as.  If <user>
        is not given, defaults to the user giving the command.
        <channel> is only necessary if the message isn't sent in the channel
        itself.
        """
        self._preCheck(irc, msg, user)
        try:
            del self.db[channel, user.id]
            irc.replySuccess()
        except KeyError:
            irc.error('I have no greet for that user.')
    remove = wrap(remove, ['channel', first('otherUser', 'user')])

    def change(self, irc, msg, args, channel, user, changer):
        """[<channel>] [<user|nick>] <regexp>

        Changes the greet message for <user>, or the user <nick|hostmask> is
        currently identified or recognized as, according to <regexp>.  If
        <user> is not given, defaults to the calling user. <channel> is only
        necessary if the message isn't sent in the channel itself.
        """
        self._preCheck(irc, msg, user)
        s = self.db[channel, user.id]
        newS = changer(s)
        self.db[channel, user.id] = newS
        irc.replySuccess()
    change = wrap(change, ['channel',
                          first('otherUser', 'user'),
                           'regexpReplacer'])
Beispiel #19
0
class Randomness(callbacks.Plugin):
    """This plugin contains commands for my own personal use."""
    threaded = True
    
    def __init__(self, irc):
        self.__parent = super(Randomness, self)
        self.__parent.__init__(irc)
        self.dotCounter = TimeoutQueue(10)

    # The code below contains automatic replies then turned on. Since this
    # is a mostly personal plugin, they will only activate on certain
    # predefined networks.
    def _attack(self, target):
        throws = ['poorly written code', 'knives', 
            "Te"+"chman", 'various objects', 'rocks',
            "Techm"+"ango", 'grenades', "IE6", 'axes', 'evil things',
            'hammers', 'Unicode', 'spears', 'spikes', 'sharp things', 
            'whips', 'moldy bread', "j4j"+"ackj", 'netsplits',
            "mojibake", "floppy disks"]
        spells = ['fire', 'ice', 'death', '\x02DEATH\x02', 
            'poison', 'stupid']
        attacks = throws + spells + ['bricks', 'knives', 
            "idiots from #freenode", "her army of trolls",
            "her ~~godly~~ oper powers", "GNOME 3",
            'confusingly bad english', "Windows Me",
            "gbyers' immaturity", "Quicktime for Windows",
            "\x0309,01-Oblivi\x020\x02n Script by mIRCsKripterz-\x03",
            "brendi hi"+"tler blossom",
            "segmentation faults", "???", "relentless spyware",
            "nsa technology"]
        throws += ['nails', 'planets', 'thorns', 'skulls',
            "a fresh, unboxed copy of Windows Me"]
        n = random.random()
        if n >= 0.82:
            return 'casts %s at %s'%(random.choice(spells), target)
        elif n >= 0.76:
            return 'drops the bass on %s'%target
        elif n >= 0.72:
            return 'fites %s'%target
        elif n >= 0.48:
            return 'attacks %s with %s'%(target, random.choice(attacks))
        else:
            return 'throws %s at %s'%(random.choice(throws),target)

    def doPrivmsg(self, irc, msg):
        if ircutils.isChannel(msg.args[0]) and self.registryValue("enable", msg.args[0]):
            dots = "." * random.randint(0,10) # added emphasis...............
            ow = "ow"+("w"*random.randint(0,4))
            volatile = ("kicks ", "stabs ", "fites ", "bans ", "ddas ", "packets ", "beats ")
            exclaim = (("!" * random.randint(1,5)) + ("1" * random.randint(0,2))) * \
                random.randint(1,2) + ("!" * random.randint(-1,5))
            gemotes = ["xD", "=']", "\\o/", ":"+"3"*random.randint(1,4), "^_^"]
            meh = (";/", ":\\", ":/")
            bemotes = meh + (":(", ":|", '-_-')
            semotes = (":<", ";_;", ";-;", "D:", ">:", "x(")
            if irc.network.lower() == "overdrive-irc":
                if "fishbot" in irc.state.channels[msg.args[0]].users:
                    hurtresponses = [ow, random.choice(semotes), 
                        ow+random.choice(semotes), "RIP", "i cry",
                        "ouch", "what was that for "+random.choice(semotes),
                        "!voteban "+msg.nick, "PLS", "rood", "owowowowow", 
                        "omg "+random.choice(semotes), 
                        "hey, bots have feelings too!"+random.choice(semotes),
                        "wtf", "watch it!", "wow"]
                    if re.match(r"^\x01ACTION ((attacks|stabs) {n} with |"
                        r"(drops|throws|casts|thwacks) (.*? (at|on|with) "
                        r"{n}|{n} (at|on|with) .*?)|fites {n}).*?\x01$".\
                        format(n=irc.nick), msg.args[1].lower(), re.I):
                        sleep(0.4)
                        n = random.random()
                        if n >= 0.45:
                            irc.queueMsg(ircmsgs.action(msg.args[0], self._attack(msg.nick)))
                        else:
                            irc.queueMsg(ircmsgs.privmsg(msg.args[0], random.choice(hurtresponses)))
                if "wow" in irc.state.channels[msg.args[0]].ops and \
                    ircutils.stripFormatting(msg.args[1].lower().split()[0]) == "wow":
                    wowResponses1 = ["what is it",
                                    "hi %s%s" % (msg.nick, dots),
                                    "o/",
                                    "HI %s%s" % (msg.nick.upper(), dots),
                                    "go away "+random.choice(bemotes),
                                    "FFS "+random.choice(bemotes),
                                    "ffs i'm trying to work",
                                    "WHAT DO YOU WANT",
                                    "leave me alone "+random.choice(bemotes),
                                    "hello, you've reached 'wow'. "
                                        "If you actually need to talk to me, "
                                        "press 1. if not, PISS OFF!",
                                    "stop highlighting me" + dots,
                                    "reproted to fbi for harassment" + dots,
                                    "-_-",
                                    msg.nick + " pls",
                                    "need something?",
                                    "r u mad",
                                    "ur made",
                                    "fml",
                                    "?",
                                    ".",
                                    "meh "+random.choice(meh),
                                    "/join 0",
                                    "/part SCREW U GUYS IM LEAVING AND NEVER COMING "
                                        "BACK AGAIN!! IT'S ALL %s'S FAULT I FKN HATE "
                                        "YOU ALL \x02</3" % msg.nick.upper(),
                                    "stop highlighting me!",
                                    "\x02%s\x02 added to ignore list." % msg.nick,
                                    "!votekline " + msg.nick]
                    n = random.randint(0, 91)
                    if n >= 60:
                        irc.queueMsg(ircmsgs.privmsg("BotServ", "say {} {}".format(msg.args[0],random.choice(wowResponses1))))
                    elif n >= 50:
                        irc.queueMsg(ircmsgs.privmsg("BotServ", "act {} {}".format(msg.args[0],random.choice(volatile)+msg.nick)))
                if ircutils.stripFormatting(msg.args[1]) == ".":
                    dotresponses = ["r u mad?", "lol r u mad", "mmm dots", ",", "no spam pls" + dots, ":D", "ok"]
                    if len(self.dotCounter) >= 2:
                        r = random.random()
                        if r >= 0.5:
                            irc.queueMsg(ircmsgs.privmsg(msg.args[0], random.choice(dotresponses)))
                    else: self.dotCounter.enqueue([0])
                elif ircutils.stripFormatting(msg.args[1]) == "ok":
                    okresponses = ["not ok", "ok", "ko",
                        "okay*", "O.K.", "^why does everyone say that ._.",
                        "\x01ACTION ok's %s\x01" % msg.nick,
                        "no", "Objection! \x02Not\x02 okay!", "meh "+random.choice(meh),
                        "yeah ok w/e man.", "\x01ACTION sighs\x01",
                        "you're pretty ok.", "hmph", "I AGREE WITH YOU, "+msg.nick+dots]
                    r = random.randint(1, 23)
                    if r >= 19:
                        irc.queueMsg(ircmsgs.action(msg.args[0], random.choice(volatile)+msg.nick))
                    elif r >= 7:
                        irc.queueMsg(ircmsgs.privmsg(msg.args[0], random.choice(okresponses)))
            if irc.network.lower() in ("overdrive-irc", "stripechat") and \
                "hitl"+"er blossom" in ircutils.stripFormatting(msg.args[1].lower()):
                irc.queueMsg(ircmsgs.privmsg(msg.args[0], msg.nick + ": the entire topic changes" + exclaim))
 #           if irc.network.lower() == "stripechat":
 #               r = random.random()
 #               if msg.args[1].lower().startswith("&topic") and "hackinbot" in msg.args[1].lower() \
 #                   and r >= 0.3:
 #                   irc.queueMsg(ircmsgs.privmsg(msg.args[0], "OH, hackinbot! " + random.choice(gemotes)))

    def attack(self, irc, msg, args, user):
        """<nick>
        
        Attacks <nick>."""
        irc.reply(self._attack(user), action=True)
    attack = wrap(attack, ['text'])
Beispiel #20
0
 def __init__(self, irc):
     self.__parent = super(Randomness, self)
     self.__parent.__init__(irc)
     self.dotCounter = TimeoutQueue(10)
Beispiel #21
0
class Bitbucket(callbacks.PluginRegexp):
    """Add the help for "@plugin help Bitbucket" here
    This should describe *how* to use this plugin."""
    threaded = True
    callBefore = ['URL', 'Web']
    unaddressedRegexps = ['snarfPullRequest']
    def __init__(self, irc):
        self.__parent = super(Bitbucket, self)
        self.__parent.__init__(irc)
        self.timeout_queue = TimeoutQueue(self.registryValue('snarferTimeout'))

    def _getResponse(self, id):
        queryurl = 'https://bitbucket.org/api/2.0/repositories/{0}/{1}/pullrequests/{2}'.format(
            self.registryValue('accountname'),self.registryValue('repo_slug'),id)
        r = requests.get(queryurl)

        self.log.info('Getting pull request from %s' % queryurl)
        if r.status_code != requests.codes.ok:
            return "pull-request not found: #" + str(id)

        return str(PullRequest(self,r.json()))

    def _check_timeout(self, id):
        if id in self.timeout_queue:
            return False

        self.timeout_queue.enqueue(id)
        return True

    def open(self, irc, msg, args):
        """
        List open pull request."""
        queryurl = 'https://bitbucket.org/api/2.0/repositories/{0}/{1}/pullrequests'.format(
            self.registryValue('accountname'),self.registryValue('repo_slug'))
        r = requests.get(queryurl)

        self.log.info('Getting pull request from %s' % queryurl)
        if r.status_code != requests.codes.ok:
            irc.reply("Url not found: " + queryurl)
            return

        data = r.json()
        if 'values' in data:
            for entry in data['values']:
                irc.reply(str(PullRequest(self,entry)), prefixNick=False)


    def snarfPullRequest(self, irc, msg, match):
        r"""(?P<type>pull request|pull-request|pullrequest)[\s#]*(?P<id>\d+)"""
        channel = msg.args[0]
        #if not self.registryValue('bugSnarfer', channel): return

        id_matches = match.group('id').split()
        type = match.group('type')

        self.log.debug('Snarfed pull request ID(s): ' + ' '.join(id_matches))
        # Check if the bug has been already snarfed in the last X seconds
        msgs = []
        for id in id_matches:
            if not self._check_timeout(id):
                continue
            response = self._getResponse(id)
            if response:
                msgs.append(response)

        for msg in msgs:
            irc.reply(msg, prefixNick=False)