Beispiel #1
0
    async def react(self, msg: IRCMessage) -> None:
        if msg.command == 'PRIVMSG':
            assert msg.sender is not None

            if msg.sender.identity in self.config.get('ignored_users', []):
                return

            channel = msg.args[0]
            nick = msg.sender.nick
            async with httpx.AsyncClient() as client:
                for url in self.extractor.gen_urls(msg.body):
                    try:
                        title = await self.generate_preview(client, url)
                    except asyncio.TimeoutError:
                        self.client.send(
                            IRCMessage(
                                'PRIVMSG',
                                channel,
                                body=f"{nick}: Preview timed out.",
                            ))
                        self.logger.exception("Error during processing %s",
                                              url)
                    except Exception:
                        self.logger.exception("Error during processing %s",
                                              url)
                    else:
                        if title:
                            self.client.send(
                                IRCMessage(
                                    'PRIVMSG',
                                    channel,
                                    body=f"{nick}: {title}",
                                ))
Beispiel #2
0
    def start(self) -> None:
        super().start()

        channels: Set[str] = set(self.config['channels'])
        join = channels.difference(self.shared_data)
        part = self.shared_data.difference(channels)
        self.shared_data = channels

        for channel in join:
            self.logger.info("Joining %s…", channel)
            self.client.send(IRCMessage('JOIN', channel))
        for channel in part:
            self.logger.info("Parting %s…", channel)
            self.client.send(IRCMessage('PART', channel))
Beispiel #3
0
    async def dump(self, recipient, channel):
        c = self.db.cursor()

        c.execute(
            'SELECT COUNT(*) FROM offline_msg WHERE channel=? AND recipient=?',
            (channel, recipient))
        count = c.fetchone()[0]
        if count == 0:
            self.logger.info("No messages for %s.", recipient)
            return
        self.logger.info("Dumping %d messages for %s.", count, recipient)

        c.execute(
            '''
            SELECT time, sender, body FROM offline_msg
            WHERE channel=? AND recipient=?
            ORDER BY rowid
            ''', (channel, recipient))
        for timestamp, sender, body in c:
            self.client.send(
                IRCMessage('PRIVMSG',
                           channel,
                           body="{time} <{sender}> {body}".format(
                               time=timestamp.strftime("%H:%M"),
                               sender=sender,
                               body=body,
                           )))

        c.execute('DELETE FROM offline_msg WHERE channel=? AND recipient=?',
                  (channel, recipient))
        self.db.commit()
Beispiel #4
0
 async def __show_score(self, sender, channel, match, msg):
     scorable = match[1]
     score = self.score(scorable, channel)
     if score is None:
         body = f"{scorable} has no score."
     else:
         body = f"{scorable}'s score is {score}."
     self.client.send(IRCMessage('PRIVMSG', channel, body=body))
Beispiel #5
0
 async def __del(self, sender, channel, match, msg):
     self.shared_data[channel].discard(match[1])
     self.client.send(
         IRCMessage(
             'PRIVMSG',
             channel,
             body=f"Understood, I'll stop keeping messages for {match[1]}.")
     )
     return True
Beispiel #6
0
    def respond_score(self, sender, nick, channel, operator):
        if sender == nick:
            self.client.send(
                IRCMessage('PRIVMSG',
                           channel,
                           body=f"{sender}: No self-scoring!"))
            return

        value_map = {
            '++': +1,
            '--': -1,
        }
        change = value_map[operator]
        self.change_score(nick, channel, change)
        score = self.score(nick, channel) or 0
        self.client.send(
            IRCMessage('PRIVMSG',
                       channel,
                       body=f"{nick}'s score is now {score}."))
Beispiel #7
0
 async def __add(self, sender, channel, match, msg):
     self.shared_data[channel].add(match[1])
     self.client.send(
         IRCMessage(
             'PRIVMSG',
             channel,
             body=f"Understood, I'll keep the messages for {match[1]}."))
     self.logger.debug("Currently saving messages for: %s",
                       dict(self.shared_data))
     return True
Beispiel #8
0
 async def __erase_scores(self, sender, channel, match, msg):
     nick = match[1]
     c = self.db.cursor()
     c.execute(
         '''
         DELETE FROM score
         WHERE nick=? AND channel=?
         ''', (nick, channel))
     self.db.commit()
     self.client.send(
         IRCMessage('PRIVMSG', channel, body=f"{nick}'s score erased."))
Beispiel #9
0
 async def query_names(self, channel: str) -> Set[str]:
     self.logger.info("No cached names for %s, querying…", channel)
     self.client.send(IRCMessage('NAMES', channel))
     names: Set[str] = set()
     while True:
         response = await self.queue.get()
         if response.command == "366":  # RPL_ENDOFNAMES
             break
         if response.command == "353":  # RPL_NAMREPLY
             if response.args[-1] == channel:
                 names.update(
                     nick.lstrip("@+") for nick in response.body.split())
     self.logger.info("Nicks on %s: %s", channel, names)
     return names
Beispiel #10
0
    async def __list_scores(self, sender, channel, match, msg):
        count = int(match[1] or 5)
        if count < 0:
            count = -count
            order = 'ASC'
        else:
            order = 'DESC'

        max_request = self.config['max_scoreboard_request'] or 10

        try:
            self.auth(sender, channel)
        except NotAuthorizedError:
            auth = False
        else:
            auth = True

        if count > max_request and not auth:
            self.client.send(
                IRCMessage('PRIVMSG',
                           channel,
                           body=f"{sender.nick}: Too many scores requested."))
            return
        c = self.db.cursor()
        c.execute(
            f'''
            SELECT nick, score FROM score
            WHERE channel=?
            ORDER BY score {order}
            LIMIT ?
            ''', (channel, count))
        for nick, score in c:
            self.client.send(
                IRCMessage('PRIVMSG',
                           channel,
                           body=f"{nick}'s score is {score}."))
        self.client.send(IRCMessage('PRIVMSG', channel, body="End of scores."))
Beispiel #11
0
 async def react(self, msg: IRCMessage) -> None:
     if msg.command == 'PING':
         self.client.send(IRCMessage('PONG', body=msg.body))
Beispiel #12
0
 async def __part(self, sender, channel, match, msg) -> None:
     self.client.send(IRCMessage('PART', match[1]))
Beispiel #13
0
 async def __join(self, sender, channel, match, msg) -> None:
     self.client.send(IRCMessage('JOIN', match[1]))