Exemple #1
0
    def __init__(self):
        self.modules = {}
        self.commands = {}
        self.eventhandlers = {
            'privmsg': [self.privmsg_],
            'joined': [self.joined_],
            'joinedHomeChannel':  [self.joinedHomeChannel],
            'irc_JOIN': [self.irc_JOIN_],
            'irc_PART': [self.irc_PART_],
            'irc_QUIT': [self.irc_QUIT_],
            'irc_KICK': [self.irc_KICK_],
            'irc_RPL_WELCOME': [self.welcome_],
        }
        self.fetching_lists={}
        self.channel = None
        self.setTopic = self.topic
        self.topic = None
        try:
            self.password = config.get('Server', 'password')
        except ConfigParser.NoOptionError:
            self.password = None
        try:
            self.username = config.get('Server', 'username')
        except ConfigParser.NoOptionError:
            self.username = None
        try:
            self.realname = config.get('Server', 'realname')
        except ConfigParser.NoOptionError:
            self.realname = None

        self.channelpws = config.getdict('Server', 'channel passwords')
Exemple #2
0
    def help(self, call, args):
        """!help <command>
        
        Gives help on a particular command. Try !commands for a list of
        commands."""

        if len(args) != 1:
            return self.help(call, ['help'])

        cmd = args[0]
        if cmd.startswith(config.get('Bot', 'command prefix')):
            cmd = cmd[len(config.get('Bot', 'command prefix')):]

        if cmd not in self.pypickupbot.commands:
            call.reply(_("Unknown command: %s") % args[0])
            return

        try:
            docstring = getattr(
                self.pypickupbot.commands[cmd][0].im_self,
                self.pypickupbot.commands[cmd][0].__name__ + '_doc'
                )
        except AttributeError:
            docstring = None

        if docstring == None:
            docstring = self.pypickupbot.commands[cmd][0].__doc__

        if docstring == None:
            call.reply(_("No help available for %s") % cmd)
            return

        docstring = '\n'.join([s.lstrip() for s in docstring.split('\n')])

        command, helpstring = docstring.split('\n\n', 1)

        if command[0] == '!':
            command = config.get('Bot', 'command prefix') + command[1:]

        helpstring = helpstring.replace('\n', ' ')

        commandflags = self.pypickupbot.commands[cmd][1]
        commandinfo = []
        if commandflags & COMMAND.NOT_FROM_CHANNEL:
            commandinfo.append(_("not from channel"))
        if commandflags & COMMAND.NOT_FROM_PM:
            commandinfo.append(_("not from PM"))
#        if commandflags & COMMAND.ON_MESSAGE:
#            commandinfo.append(_(""))
        if commandflags & COMMAND.ADMIN:
            commandinfo.append(_("admin command"))

        if len(commandinfo):
            call.reply('\x02'+command+'\x02\x0315'
                     + '('+', '.join(commandinfo)+')\x0f: '
                     + helpstring )
        else:
            call.reply('\x02'+command+'\x02: '
                     + helpstring )
        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),
                    })
 def _cback(playerlist):
     o = [config.get('Pickup player tracking', 'top10 player').decode('string-escape') % {
             'player': player,
             'count': count,
             }
         for player, count in playerlist]
     call.reply(
         config.get('Pickup player tracking', 'top10').decode('string-escape') % {
             'playerlist': ', '.join(o),
             'games': ' '.join(games)
         }, ', ')
Exemple #5
0
    def __str__(self):
        sorted_topic = {
                self.__class__.GRAVITY_BEGINNING : {},
                self.__class__.GRAVITY_NONE : {},
                self.__class__.GRAVITY_END : {},
            }
        as_list = []
        for num, part in self.parts.iteritems():
            s = str(part)
            if len(s) > 0:
                sorted_topic[part.gravity][num] = s
        for i in [self.GRAVITY_BEGINNING, self.GRAVITY_NONE, self.GRAVITY_END]:
            as_list.extend(sorted_topic[i].values())

        return config.get('Topic', 'prefix').decode('string-escape') + config.get('Topic', 'separator').decode('string-escape').join(as_list) + config.get('Topic', 'suffix').decode('string-escape')
Exemple #6
0
 def motd_from_str(self, s):
     sep = config.get('Topic', 'separator').decode('string-escape')
     self.motd_str = re.split(
         '%s|%s' % (
             re.escape(sep),
             re.escape(filter_irc_colors(sep))
         ), s)
Exemple #7
0
 def _split_reply(self, msg, split, times):
     """Splits a reply into multiple messages.
     
     @arg splitpoint: what pattern is it best to split at?"""
     times += 1
     added_len = len("PRIVMSG %s \n"%self.nick)
     if len(msg) + added_len <= 255:
         self.reply(msg)
     else:
         more_suffix = ""
         if times == config.getint("Bot", "max reply splits before waiting"):
             more_suffix = split \
                 + _("Reply is too long, use \x02%(prefix)smore\x02 to continue reading.")\
                 % {'prefix':config.get('Bot', 'command prefix')}
         added_len += len(more_suffix)
         m = re.match("^(?P<send>.{0,%d})%s(?P<rest>.*?)$"\
             % (255-added_len, re.escape(split)), msg)
         if not m:
             # If we can't split conveniently, cut straight in
             self.reply(msg[:255-added_len]+more_suffix)
             rest = msg[255-added_len:]
         else:
             self.reply(m.group('send')+more_suffix)
             rest = m.group('rest')
         if len(more_suffix):
             t = time()
             self.bot.more_buffer[self.nick] = (rest, t)
             reactor.callLater(60, self._dropMoreBuffer, t)
         else:
             self._split_reply(rest, split, times)
 def _printResult(r):
     o = []
     for nick, ts, id in r:
         date = datetime.fromtimestamp(ts)
         o.append(config.get('Pickup player tracking', 'lastgames game').decode('string-escape') % {
             'year': date.year,
             'month': date.month,
             'day': date.day,
             'hour': date.hour,
             'minutes': date.minute,
             'nick': nick,
             'id': id,
         })
     o.reverse()
     call.reply(config.get('Pickup player tracking', 'lastgames').decode('string-escape')%{
         'games': ', '.join(games),
         'lastgames': config.get('Pickup player tracking', 'lastgames separator').decode('string-escape').join(o)
         }, config.get('Pickup player tracking', 'lastgames separator').decode('string-escape'))
Exemple #9
0
 def _handleMore(self):
     if self.nick in self.bot.more_buffer:
         if self.bot.more_buffer[self.nick][1] + 5 > time():
             self.reply(_("Please wait between \x02%(prefix)smore\x02 calls.") \
                 % {'prefix':config.get('Bot', 'command prefix')})
         else:
             self.reply(self.bot.more_buffer[self.nick][0])
     else:
         self.reply(_("There's nothing more."))
Exemple #10
0
        def _knowAdmin(admin):
            if self.last_promote + config.getint('Pickup', 'promote delay') > time() \
                    and not admin:
                raise InputError(_("Can't promote so often."))

            game = self.get_game(call, args)

            if call.nick not in game.players \
                    and not admin:
                raise InputError(_("Join the game yourself before promoting it."))

            self.last_promote = time()
            self.pypickupbot.cmsg(
                config.get('Pickup messages', 'promote').decode('string-escape') % {
                    'bold': '\x02', 'prefix': config.get('Bot', 'command prefix'),
                    'name': game.name, 'nick': game.nick,
                    'command': config.get('Bot', 'command prefix')+'add '+game.nick,
                    'channel': self.pypickupbot.channel,
                    'playersneeded': game.maxplayers-len(game.players),
                    'maxplayers': game.maxplayers, 'numplayers': len(game.players),
                })
Exemple #11
0
    def who(self, call, args):
        """!who [game [game ..]]
        
        Shows who has signed up"""
        games = [i for i in self.get_games(call, args).who() if i != None]
        all = False
        if len(args) < 1 or len(args) == len(self.games):
            all = True
        if len(games):
            if all:
                call.reply(_("All games:")+" "+config.get('Pickup messages', 'who game separator').decode('string-escape').join(games),


                    config.get('Pickup messages', 'who game separator').decode('string-escape'))
            else:
                call.reply(config.get('Pickup messages', 'who game separator').decode('string-escape').join(games),
                    config.get('Pickup messages', 'who game separator').decode('string-escape'))
        else:
            if all:
                call.reply(_("No game going on!"))
            else:
                call.reply(_n("No game in mode %s", "No game in modes %s", len(args)) % ' '.join(args) )
Exemple #12
0
    def update_topic(self):
        """Update the pickup part of the channel topic"""
        config_topic = config.getint('Pickup', 'topic')

        if not config_topic:
            return

        out = []
        for gamenick in self.order:
            game = self.games[gamenick]
            if config_topic == 1 or game.players:
                out.append(
                    config.get('Pickup messages', 'topic game').decode('string-escape')
                    % {
                        'nick': game.nick, 'playernum': len(game.players),
                        'playermax': game.maxplayers, 'name': game.name,
                        'numcaps': game.caps
                    })

        self.topic.update(
            config.get('Pickup messages', 'topic game separator')\
                .decode('string-escape')\
            .join(out)
            )
Exemple #13
0
    def confirm(self, msg, wait=60, split=" ", assume=False):
        """Prompts caller for confirmation.

        @arg wait: time in seconds to wait for confirmation until it is assumed to be dismissed.
        
        @returns deferred fired with True/False"""
        if self.nick in self.bot.prompts[self.channel]:
            self._removePrompt(self.bot.prompts[self.channel][self.nick][1])
        self.reply(
            msg + " " + _("Reply with \x02%(prefix)syes\x02 or \x02%(prefix)sno\x02.")
            % {'prefix':config.get('Bot', 'command prefix')}, split)
        t = time()
        d = defer.Deferred()
        self.bot.prompts[self.channel][self.nick] = (d, t, assume)
        reactor.callLater(60, self._removePrompt, t)
        return d
Exemple #14
0
 def who(self):
     """Who is in this game"""
     if len(self.players):
         return config.get('Pickup messages', 'who game').decode('string-escape') % {'nick': self.nick, 'playernum': len(self.players), 'playermax': self.maxplayers, 'name': self.name, 'numcaps': self.caps, 'playerlist': ', '.join(self.players) }
Exemple #15
0
    def __init__(self, bot, user, channel, message):
        self.bot = bot
        self.user = user
        self.nick = user.split('!',1)[0]
        self.channel = channel
        command = str()

        if channel[0]=='#':
            if message.startswith(config.get('Bot', 'command prefix')):
                command = message[len(config.get('Bot', 'command prefix')):]
                self.context = self.CONTEXT_COMMAND
            else:
                m = re.match( '^'+re.escape(self.bot.nickname)+'[^A-Za-z0-9 ]\W*(.*)', message )
                if m and config.getboolean('Bot', 'allow mentions'):
                    command = m.group(1)
                    self.context = self.CONTEXT_MENTION
                else:
                    # chanmsg
                    return
        elif channel == self.bot.nickname:
            command = message
            self.context = self.CONTEXT_PRIVATE
            self.channel = 'PM'
        else:
            return

        self.args = command.split()
        self.cmd = self.args.pop(0).lower()

        if self.cmd in ['yes', 'no']:
            self._handle_confirm_reply()
            return

        if self.cmd == 'more':
            log.msg(_("{0} asked for more"))
            self._handleMore()
            return

        if self.cmd not in self.bot.commands:
            log.msg(_("{0} attempted to use unknown command {1}.").format(self.nick, self.cmd))
            if config.getboolean('Bot', 'warn on unknown command'):
                self.reply(_("Unknown command %s.") % self.cmd)
            return

        flags = self.bot.commands[self.cmd][1]
        can_run = []
        if flags & COMMAND.ADMIN:
            def _knowIs_admin(is_admin):
                if not is_admin:
                    log.msg(_("{0} attempted to use admin command {1}.").format(self.nick, self.cmd))
                    raise InputError(_("Command %s is only available to admins.") % self.cmd)
                else:
                    return True
            can_run.append(
                self.bot.is_admin(self.user, self.nick)\
                    .addCallback(_knowIs_admin)
                )

        if self.context == self.CONTEXT_PRIVATE and flags & COMMAND.NOT_FROM_PM:
            log.msg(_("{0} attempted to use command {1} in a PM.").format(self.nick, self.cmd))
            can_run.append(defer.fail(InputError(
                _("Command %s cannot be used in private.") % self.cmd)))
        else:
            can_run.append(defer.succeed(True))

        if self.context == self.CONTEXT_COMMAND and flags & COMMAND.NOT_FROM_CHANNEL:
            log.msg(_("{0} attempted to use command {1} in a channel.").format(self.nick, self.cmd))
            can_run.append(defer.fail(InputError(
                _("Command {0} cannot be used in public.").format(self.cmd))))
        else:
            can_run.append(defer.succeed(True))

        def _canRun(true):
            log.msg(message)
            try:
                d = log.callWithContext({'system': 'pypickupbot %s %s'%(self.channel,self.cmd)}, self.bot.commands[self.cmd][0], self, self.args)
                if isinstance(d, defer.Deferred):
                    d.addErrback(_catchInputError).addErrback(_catchInternalError)
            except InputError as e:
                self.reply(str(e))
            except Exception as e:
                self.reply(_("Internal error."))
                log.err()

        def _catchInputError(f):
            t = f.trap(InputError)
            self.reply(str(f.value))
        
        def _catchInternalError(f):
            f.trap(Exception)
            self.reply(_("Internal error."))
            f.printTraceback()

        defer.DeferredList(can_run, fireOnOneErrback=True, consumeErrors=True)\
            .addCallbacks(_canRun, _catchInputError).addErrback(_catchInternalError)
Exemple #16
0
 def __init__(self):
     self.channels = config.getlist('Server', 'channels')
     self.nickname = config.get('Bot', 'nickname')
Exemple #17
0
    def do_start(self):
        """Does the actual starting of the game"""
        if self.abort_start or not self.starting:
            self.abort_start = False
            self.starting = False
            return

        players = self.players[:self.maxplayers]
        for player in players:
            self.pickup.all_games().force_remove(player)

        self.pickup.update_topic()

        self.pickup.pypickupbot.notice(self.pickup.pypickupbot.channel, 
            _("%(gamenick)s game ready to start in %(channel)s")
                % {'gamenick': self.nick, 'channel': self.pickup.pypickupbot.channel})

        captains = []

        if not self.autopick:
            pickpool = sorted(players)
            captains = random.sample(pickpool,2)

            self.pickup.pypickupbot.fire('pickup_game_starting', self, players, captains)
            if len( captains ) > 0:
                self.pickup.pypickupbot.msg( self.pickup.pypickupbot.channel,
                    config.get('Pickup messages', 'game ready').decode('string-escape')%
                    {
                        'nick': self.nick,
                        'playernum': len(self.players),
                        'playermax': self.maxplayers,
                        'name': self.name,
                        'numcaps': self.caps,
                        'playerlist': ', '.join(players),
                        'captainlist': ', '.join(captains)
                    })
                if config.getboolean("Pickup", "PM each player on start"):
                    for player in players:
                        self.pickup.pypickupbot.msg(player, 
                            config.get("Pickup messages", "youre needed").decode('string-escape')%
                            {
                                'channel': self.pickup.pypickupbot.channel,
                                'name': self.name,
                                'nick': self.nick,
                                'numcaps': self.caps,
                                'playerlist': ', '.join(players),
                                'captainlist': ', '.join(captains)
                            })
            else:
                self.pickup.pypickupbot.msg( self.pickup.pypickupbot.channel,
                    config.get('Pickup messages', 'game ready nocaptains').decode('string-escape')%
                    {
                        'nick': self.nick,
                        'playernum': len(self.players),
                        'playermax': self.maxplayers,
                        'name': self.name,
                        'numcaps': self.caps,
                        'playerlist': ', '.join(players)
                    })
                if config.getboolean("Pickup", "PM each player on start"):
                    for player in players:
                        self.pickup.pypickupbot.msg(player, 
                            config.get("Pickup messages", "youre needed nocaptains").decode('string-escape')%
                            {
                                'channel': self.pickup.pypickupbot.channel,
                                'name': self.name,
                                'nick': self.nick,
                                'numcaps': self.caps,
                                'playerlist': ', '.join(players),
                            })
        else:
            teams = [[] for i in range(self.caps)]
            players_ = sorted(players)
            for i in range(len(players)):
                player = random.choice(players_)
                players_.remove(player)
                teams[i % self.caps].append(player)

            self.pickup.pypickupbot.fire('pickup_game_starting', self, teams, captains)
            self.pickup.pypickupbot.cmsg(
                config.get('Pickup messages', 'game ready autopick').decode('string-escape')%
                {
                    'nick': self.nick,
                    'playernum': len(players),
                    'playermax': self.maxplayers,
                    'name': self.name,
                    'numcaps': self.caps,
                    'teamslist': ', '.join([
                        config.get('Pickup messages', 'game ready autopick team').decode('string-escape')%
                        {
                            'name': self.teamname(i),
                            'players': ', '.join(team)
                        }
                        for i, team in enumerate(teams)])
                })

        self.pickup.pypickupbot.fire('pickup_game_started', self, players, captains)

        self.starting = False
Exemple #18
0
 def joinedHomeChannel(self):
     """when home channel joined, set topic"""
     if config.get('Pickup', 'topic'):
         self.topic = self.pypickupbot.topic.add('', Topic.GRAVITY_BEGINNING)
         self.update_topic()