Ejemplo n.º 1
0
 def expiry(self):
     """Utility function to get a string like "expires in 10 minutes"."""
     if self.deleted:
         return _('lifted %s') % str_from_timediff(int(itime())-self.deleted)
     elif not self.length:
         return _('permanent')
     elif self.length + self.start < itime():
         return _('expired %s') % str_from_timediff(int(itime())-self.length-self.start)
     else:
         return _("expires %s") % str_from_timediff(self.length+self.start-int(itime()), future=True)
Ejemplo n.º 2
0
        def _check_update(args, contents):
            author, channel_, set, modes, args = args

            if channel_ != channel:
                return

            admin = author.split('!')[0]

            changes = []
            for mode, arg in zip(modes, args):
                if mode == 'b':
                    if set:
                        t = itime()
                    else:
                        t = None
                        for mask_, admin_, t_ in contents:
                            if mask_ == arg:
                                t = t_
                                admin = admin_
                        if t == None:
                            continue
                    changes.append((arg, admin, t))

            if set:
                return (changes, [])
            else:
                return ([], changes)
Ejemplo n.º 3
0
        def _insertGame(txn):
            txn.execute("""
                INSERT INTO
                pickup_games(game, time, players, captains)
                VALUES(:game, :time, :players, :captains)
            """,
            {
                'game': game.nick,
                'time': itime(),
                'players': json.dumps(players, separators=(',',':')),
                'captains': json.dumps(captains, separators=(',',':')),
            })

            txn.execute("SELECT last_insert_rowid() AS id")
            result = txn.fetchall()

            id_ = result[0][0]

            def _insertPlayers(playerlist):
                for player in playerlist:
                    if isinstance(player, StringTypes):
                        db.runOperation("""INSERT INTO
                            pickup_players_games(game_id, name, game, time)
                            VALUES(?, ?, ?, ?)
                        """, (id_, player, game.nick, itime()))
                    else:
                        _insertPlayers(player)
            _insertPlayers(players)
            return id_
Ejemplo n.º 4
0
        def _printResult(r):
            if len(r) < 1:
                if args and args[0].startswith('#'):
                    call.reply(_("No record for game #{0}").format(id))
                else:
                    call.reply(_("No game played yet in mode(s): {0}").format(' '.join(games)))
                return
            gamenick, gtime, players_, captains_, id_ = r[0]
            if ',' in players_:
                players = json.loads(players_)
                captains = json.loads(captains_)
            else:
                players = players_.split()
                captains = captains_.split()
            try:
                game = self.pickup.get_game(call, [gamenick])
                gamename = game.name
                teamnameFactory = game.teamname
            except InputError:
                gamename = _("Unknown(%s)") % gamenick
                teamnameFactory = lambda i: _("Team {0}").format(i + 1)

            timestr = str_from_timediff(itime()-gtime)

            if captains:
                call.reply(config.get('Pickup player tracking', 'lastgame').decode('string-escape') % \
                    {
                        'name': gamename,
                        'nick': gamenick,
                        'id': id_,
                        'when': timestr,
                        'playerlist': ', '.join(players),
                        'captainlist': ', '.join(captains)
                    })
            elif not isinstance(players[0], StringTypes):
                call.reply(config.get('Pickup player tracking', 'lastgame autopick').decode('string-escape') % \
                    {
                        'name': gamename,
                        'nick': gamenick,
                        'id': id_,
                        'when': timestr,
                        'teamslist': ', '.join([
                            config.get('Pickup messages', 'game ready autopick team').decode('string-escape')%
                            {
                                'name': teamnameFactory(i),
                                'players': ', '.join(team)
                            }
                            for i, team in enumerate(players)])
                    })
            else:
                call.reply(config.get('Pickup player tracking', 'lastgame nocaptains').decode('string-escape') % \
                    {
                        'name': gamename,
                        'nick': gamenick,
                        'id': id_,
                        'when': timestr,
                        'playerlist': ', '.join(players),
                    })
Ejemplo n.º 5
0
 def _insertPlayers(playerlist):
     for player in playerlist:
         if isinstance(player, StringTypes):
             db.runOperation("""INSERT INTO
                 pickup_players_games(game_id, name, game, time)
                 VALUES(?, ?, ?, ?)
             """, (id_, player, game.nick, itime()))
         else:
             _insertPlayers(player)
Ejemplo n.º 6
0
 def _confirmed(confirmed):
     if not confirmed:
         call.reply(_("Cancelled."))
     else:
         for item in r:
             item.meta['deleted_by'] = call.user
             item.deleted = itime()
             call.reply(_("{item} lifted.").format(item=item).capitalize())
         self.periodic_check()
Ejemplo n.º 7
0
 def __init__(self, tracker, meta, start=0, length=0,
         deleted=0, applied=True, id=None):
     self.tracker = tracker
     self.id = id
     self.meta = meta
     if start:
         self.start = start
     else:
         self.start = itime()
     self.length = length
     self.applied = applied
     self.deleted = deleted
Ejemplo n.º 8
0
 def _purge(self, keep=0):
     """used by clearGames and purgeGames"""
     res = defer.gatherResults([
         db.runOperation("""
             DELETE FROM """ + table + """
             WHERE time < ?
             """, (itime() - keep,))
         for table in ['pickup_games', 'pickup_players_games']
         ])
     def onErr(failure):
         log.err(failure, "purge games, keep = {0}".format(keep))
         return failure
     res.addErrback(onErr)
     return res
Ejemplo n.º 9
0
    def listCmd(self, call, args):
        """!%(name)slist [#id|search]
        
        Shows/searches the active %(name)ss list, or give detailled info
        about one %(name)s."""
        r = self.search( ' '.join(args), self.search_keys, self.get_cmp_funcs(),
            lambda item: not item.expired() or (item.deleted and item.deleted + 86400 > itime() )\
                or not item.deleted and item.start + item.length + 86400 > itime())

        if not r:
            raise InputError(_("No matches."))

        if len(r) == 1:
            call.reply(r[0].long_str(), config.getescaped('Tracker', 'list separator'))
        else:
            call.reply(
                config.getescaped('Tracker', 'list separator')\
                    .join((item.short_str() for item in r)),
                config.getescaped('Tracker', 'list separator')
                )
Ejemplo n.º 10
0
        def _doTransaction(txn):
            params = dict(zip([str(i) for i in range(len(games))], games))
            params.update({'time': itime()-config.getduration("Pickup player tracking", "top10 spread")})
            txn.execute("""
                SELECT name FROM pickup_players_games
                WHERE
                    (""" + \
                    ' OR '.join(['game=:%d' % i for i in range(len(games))]) \
                    + """)
                    AND time>:time""", params )

            players = {}

            for (player,) in txn.fetchall():
                try:
                    players[player] += 1
                except KeyError:
                    players[player] = 1

            ordered = players.items()
            ordered.sort(None, lambda x: x[1], True)

            return ordered[:10]
Ejemplo n.º 11
0
 def sync_with_real(self):
     if self.expired() == self.applied:
         if not self.expired():
             self.deleted = itime()
             self.update_db()
Ejemplo n.º 12
0
    def from_call(cls, tracker, call, args):
        nick = None
        user = None

        if not args:
            if tracker.lastKicked and tracker.lastKickedTime + 120 > itime():
                user = tracker.lastKicked
                reason = tracker.lastKickedReason
            else:
                raise InputError(
                    _("No kick issued recently, so please specify a user or mask to ban."))
        else:
            if '$' == args[0][0]: # that's a server-custom mask
                                  # the user surely knows what they're
                                  # doing there
                user = args.pop(0)
            elif '@' not in args[0] \
            and  '!' not in args[0] \
            and  '*' not in args[0] \
            and  '?' not in args[0]:
                if is_ipv4(args[0]) or is_ipv6(args[0]):
                    user = '******' + args.pop(0) # TODO ban a subnet for
                                                # ivp6 addresses
                else:
                    nick = args.pop(0)
            else:
                if  '@' not in args[0] \
                and '!' not in args[0]:
                    user = args.pop(0)+'!*@*'
                else:
                    if not banmaskRe.match(args[0]):
                        raise InputError(_("Invalid hostmask '%s'")%args[0])
                    elif hostmaskRe.match(args[0]): # full hostmask
                        user = cls.find_banmask(args.pop(0))
                    else: # already a banmask
                        user = args.pop(0)

        if user:
            user_d = defer.succeed([user])
        else:
            def _gotUserList(l):
                for nick_, ident, host, flags in l:
                    if nick == nick_:
                        user = "******" % (nick_, ident, host)
                        return cls.find_banmask(user)
                else:
                    return ['%s!*@*' % nick]

            user_d = FetchedList.get_users(
                tracker.pypickupbot,
                tracker.pypickupbot.channel
                ).get().addCallback(_gotUserList)

        def _gotMasks(masks):
            def _gotUserList(userlist):
                meta = {
                        'ban_masks': masks,
                        'seen_masks': [],
                        'seen_nicks': [],
                    }

                if user:
                    meta['seen_masks'].append(user)
                if nick:
                    meta['seen_nicks'].append(nick)

                to_kick = []
                for nick_, ident, host, flags in userlist:
                    mask_ = '%s!%s@%s' % (nick_, ident, host)
                    if tracker.cmp_masks(
                        mask_,
                        masks
                        ):
                        to_kick.append(nick_)
                        if nick_ not in meta['seen_nicks']:
                            meta['seen_nicks'].append(nick_)
                        if mask_ not in meta['seen_masks']:
                            meta['seen_masks'].append(mask_)


                if tracker.pypickupbot.nickname in to_kick:
                    raise InputError(_("Ain't gonna ban myself."))
                if len(to_kick) > 1:
                    confirm = call.confirm(_("More than 1 client(%s) is affected with this ban, proceed?") % ' '.join(to_kick))
                else:
                    confirm = defer.succeed(True)
                def _confirmed(confirmed):
                    if not confirmed:
                        raise InputError(_("Cancelled."))

                    return cls(
                        tracker,
                        meta
                        )
                return confirm.addCallback(_confirmed)
            return FetchedList.get_users(
                tracker.pypickupbot,
                tracker.pypickupbot.channel
                ).get(_gotUserList).addCallback(_gotUserList)
        return user_d.addCallback(_gotMasks)
Ejemplo n.º 13
0
 def expired(self):
     return bool(self.deleted) or (bool(self.length) and self.start + self.length < itime())
Ejemplo n.º 14
0
    def mainCmd(self, call, args):
        """!%(name)s [#id|hostmask|user [length [reason]]]
        
        Sets a new %(name)s or edits an existing one."""
        length = None
        needle = None

        if args:
            needle = args.pop(0)
            r = self.search( needle, self.search_keys,
                self.get_cmp_funcs(),
                lambda item: not self.ItemClass.expired(item) )
        else:
            r = []

        if r:
            new = False
            if len(r) > 1:
                call.reply(
                    _("More than one match: please specify the id of the item to edit"))
                return
            else:
                item_ = r[0]

                if 'edited_by' not in item_.meta:
                    item_.meta['edited_by'] = []
                item_.meta['edited_by'].append(call.user)

                try:
                    newlen = timediff_from_str(args[0])
                except IndexError:
                    raise InputError(_("Please specify a new {type} length or reason.").format(type=self.name))
                except InvalidTimeDiffString:
                    length = item_.length
                    # assume it's a new reason for the ban
                else:
                    # apply the new length as if the ban started now without changing start time
                    length = itime() - item_.start + newlen
                    args.pop(0)

                item = defer.succeed(item_)
        else:
            new = True
            if args or needle:
                args.insert(0, needle)
                try:
                    length = timediff_from_str(args[1])
                except (InvalidTimeDiffString, IndexError):
                    # Ignore error and let subclass decide the default value for this
                    pass
                else:
                    del args[1]

            def _newItem(item):
                item.meta['author'] = call.user
                return item
            item = self.ItemClass.from_call(self, call, args)
            item.addCallback(_newItem)

        def _gotItem(item, length):
            if args and length == None:
                try:
                    length = timediff_from_str(args.pop(0))
                except InvalidTimeDiffString as e:
                    raise InputError(str(e))
            elif length == None:
                length = config.getduration(
                    self.name.capitalize(), 'default duration')
            item.length = length

            if args:
                item.meta['reason'] = ' '.join(args)

            applied = self.retrieve_real_list().addCallback(item.check_applied)
            def _applied(applied):
                if new:
                    self.listed.append(item)
                    synced = item.sync_with_self()
                else:
                    synced = item.update_db()
                def _reply(self):
                    if new:
                        call.reply(_("{item} created.").format(item=item).capitalize())
                    else:
                        call.reply(_("{item} edited.").format(item=item).capitalize())
                synced.addCallback(_reply)
            applied.addCallback(_applied)

            return item
 
        return item.addCallback(_gotItem, length)