예제 #1
0
 def __getitem__(self, guild_id: int):
     typecheck(guild_id, int, 'guild_id')
     if guild_id not in self._prefixes:
         prefix = db.config.get_prefix(guild_id)
         self._prefixes[guild_id] = (self.default
                                     if prefix is None else prefix)
     return self._prefixes[guild_id]
예제 #2
0
def _get_most_recent_update(guild_id: int, channel_id: int,
                            cur: MySQLCursor) -> Optional[dt.datetime]:
    typecheck(guild_id, int, 'guild_id')

    cur.execute(f'''
        SELECT MAX(timestamp) FROM g{guild_id}_messages as msgs
        INNER JOIN channels ON (channels.key_id = msgs.channel)
        WHERE channels.id = %s
        GROUP BY channel;
    ''', (channel_id,))
    timestamp = cur.fetchone()

    return timestamp[0] if timestamp else None
예제 #3
0
def generate_tags(guild_id: int, cur: MySQLCursor = None):
    typecheck(guild_id, int, 'guild_id')
    logger.info(f'Generating part of speech tags for server {guild_id}')

    cur.execute(f'''
        SELECT users.id, channels.id, content FROM g{guild_id}_messages AS msgs
        INNER JOIN users ON (msgs.user = users.key_id)
        INNER JOIN channels ON (msgs.channel = channels.key_id)
        WHERE content <> ''
    ''')

    for user_id, channel_id, content in cur:
        for tag, word in _get_tags(content):
            _insert_word(guild_id, user_id, channel_id, tag, word)
예제 #4
0
def init_guild(guild: Guild, cur: MySQLCursor = None):
    guild_id = guild.id
    typecheck(guild_id, int, 'guild_id')

    cur.execute(f'''
        CREATE TABLE IF NOT EXISTS g{guild_id}_messages (
            id BIGINT UNSIGNED NOT NULL,
            user SMALLINT UNSIGNED NOT NULL,
            channel SMALLINT UNSIGNED NOT NULL,
            timestamp DATETIME NOT NULL,
            content TEXT NOT NULL,
            images TEXT,
            PRIMARY KEY (id),
            INDEX (user),
            INDEX (channel)
        );

        CREATE TABLE IF NOT EXISTS g{guild_id}_markov (
            user SMALLINT UNSIGNED NOT NULL,
            channel SMALLINT UNSIGNED NOT NULL,
            base TEXT,
            potentials MEDIUMTEXT,
            INDEX (user),
            INDEX (channel),
            INDEX (base(32))
        );
        
        CREATE TABLE IF NOT EXISTS g{guild_id}_pos_tags (
            user SMALLINT UNSIGNED NOT NULL,
            channel SMALLINT UNSIGNED NOT NULL,
            tag VARCHAR(8) NOT NULL,
            word TEXT NOT NULL,
            use_count MEDIUMINT UNSIGNED DEFAULT 0,
            INDEX (user),
            INDEX (channel),
            INDEX (tag(3)),
            UNIQUE KEY unique_entry (user, channel, tag, word(32))
        );

        CREATE TABLE IF NOT EXISTS g{guild_id}_pins (
            original BIGINT UNSIGNED NOT NULL,
            pin BIGINT UNSIGNED NOT NULL
        );
    ''', multi=True)

    db_config.add_guild(guild_id)

    for channel in guild.text_channels:
        add_channel(channel)
예제 #5
0
def random_message(guild_id: int,
                   users: Optional[List[int]] = None,
                   channel: Optional[int] = None,
                   word_limit: Optional[LimitTuple] = None,
                   count: int = 1,
                   content: bool = False,
                   images: bool = False,
                   cur: MySQLCursor = None):
    typecheck(guild_id, int, 'guild_id')
    if isinstance(word_limit, Sequence) and not any(word_limit):
        word_limit = None

    # Case insensitivity was screwing with the word limit
    # regex pattern (\S -> \s)
    where_stmt = _create_where_statement(
        user=len(users) if users else 0,
        channel=1 if channel else 0,
        regex=bool(word_limit),
        content=content,
        images=images,
        case_sensitive=True
    )
    word_limit_regex = None
    if word_limit:
        min_ = word_limit[0]-1 if word_limit[0] else ''
        max_ = word_limit[1]-1 if word_limit[1] else ''
        word_limit_regex = (
            rf'^(?:\S+ +){{{min_},{max_}}}\S+$')

    # https://stackoverflow.com/a/41581041
    script = f'''
        SELECT msgs.id as msg_id, channels.id as channel_id,
               users.name as user_name, timestamp, content, images
        FROM g{guild_id}_messages AS msgs
        INNER JOIN channels ON (msgs.channel = channels.key_id)
        INNER JOIN users ON (msgs.user = users.key_id)
        WHERE msgs.id IN (
            SELECT id FROM (
                SELECT id FROM g{guild_id}_messages
                {where_stmt}
                ORDER BY RAND() LIMIT %s
            ) t
        )
    '''
    cur.execute(script, flat_pruned_list(users, channel, word_limit_regex,
                                         count))
    return cur
예제 #6
0
파일: pins.py 프로젝트: Hawkpath/hawkbot
def get_pin_msg_id(guild_id: int,
                   original_msg_id: int,
                   cur: MySQLCursor = None) -> Optional[int]:
    """
    Get the id of the associated pin message Hawkbot sent in a guild's
    designated pins channel

    :param guild_id: guild id
    :param original_msg_id: the id of the original message that was pinned
    :return: the id of the pin message Hawkbot sent linking to the original, or
        None if the original message was not found
    """
    typecheck(guild_id, int, 'guild_id')
    cur.execute(
        f'''
        SELECT pin FROM g{guild_id}_pins WHERE original = %s
    ''', (original_msg_id, ))
    pin_msg_id = cur.fetchone()
    return pin_msg_id[0] if pin_msg_id else None
예제 #7
0
파일: pins.py 프로젝트: Hawkpath/hawkbot
def pin_message(guild_id: int,
                original_msg_id: int,
                pin_msg_id: int,
                cur: MySQLCursor = None):
    """
    Add a mapping between an original message and Hawkbot's pin message sent
    in a guild's designated pins channel

    :param guild_id: guild id
    :param original_msg_id: the id of the original message that was pinned
    :param pin_msg_id: the id of the pin message Hawkbot sent linking to the
        original
    """
    typecheck(guild_id, int, 'guild_id')
    cur.execute(
        f'''
        INSERT INTO g{guild_id}_pins (original, pin) VALUES (%s,%s) 
    ''', (original_msg_id, pin_msg_id))
    cnx.commit()
예제 #8
0
def get_random_words_by_tag(guild_id: int,
                            tag: str,
                            users: Optional[List[int]] = None,
                            channel: Optional[int] = None,
                            count: int = 1,
                            cur: MySQLCursor = None) -> List[str]:
    typecheck(guild_id, int, 'guild_id')
    where_stmt = _create_where_statement(
        len(users) if users else 0, 1 if channel else 0, True)

    cur.execute(
        f'''
        SELECT word FROM g{guild_id}_pos_tags
        {where_stmt}
        ORDER BY RAND() LIMIT %s
    ''', flat_pruned_list(users, channel, tag, count))

    words = [w[0] for w in cur]
    return words
예제 #9
0
def _insert_message(msg: discord.Message, cur: MySQLCursor = None):
    guild_id = msg.guild.id
    typecheck(guild_id, int, 'guild_id')
    images = _get_images_urls(msg)
    if images:
        images = ';'.join(images)

    add_user(msg.author)
    add_channel(msg.channel)
    cur.execute(f'''
        INSERT INTO g{guild_id}_messages (
            id, user, channel, timestamp, content, images
        ) VALUES (
            %s,
            (SELECT key_id FROM users WHERE id=%s),
            (SELECT key_id FROM channels WHERE id=%s),
            %s,%s,%s
        )
    ''', (msg.id, msg.author.id, msg.channel.id, msg.created_at,
          msg.content, images))
    cnx.commit()
예제 #10
0
파일: pins.py 프로젝트: Hawkpath/hawkbot
def unpin_message(guild_id: int,
                  original_msg_id: int,
                  cur: MySQLCursor = None) -> Optional[int]:
    """
    Remove a mapping between an original message and Hawkbot's pin message sent
    in a guild's designated pins channel

    :param guild_id: guild id
    :param original_msg_id: the id of the original message that was pinned
    :return: the id of the pin message Hawkbot sent linking to the original, or
        None if the original message was not found
    """
    typecheck(guild_id, int, 'guild_id')
    pin_msg_id = get_pin_msg_id(guild_id, original_msg_id)
    if pin_msg_id:
        cur.execute(
            f'''
            DELETE FROM g{guild_id}_pins WHERE original = %s
        ''', (original_msg_id, ))
        cnx.commit()
        return pin_msg_id
    return None
예제 #11
0
def message_stats(guild_id: int,
                  pattern: str,
                  users: Optional[List[int]] = None,
                  channels: Optional[List[int]] = None,
                  case_sensitive: bool = False,
                  plot: bool = False,
                  cur: MySQLCursor = None):
    typecheck(guild_id, int, 'guild_id')
    where_stmt = _create_where_statement(
        user=len(users) if users else 0,
        channel=len(channels) if channels else 0,
        regex=True,
        case_sensitive=case_sensitive
    )

    if not plot:
        cur.execute(f'''
            SELECT users.name, COUNT(*)
            FROM g{guild_id}_messages AS msgs
            INNER JOIN channels ON (msgs.channel = channels.key_id)
            INNER JOIN users ON (msgs.user = users.key_id)
            {where_stmt}
            GROUP BY user
            ORDER BY users.name
        ''', flat_pruned_list(users, channels, pattern))
        return cur
    else:
        cur.execute(f'''
            SELECT
                users.id, users.name, DATE_FORMAT(timestamp, '%Y-%m-%d'),
                COUNT(*)
            FROM g{guild_id}_messages AS msgs
            INNER JOIN channels ON (msgs.channel = channels.key_id)
            INNER JOIN users ON (msgs.user = users.key_id)
            {where_stmt}
            GROUP BY user, DATE_FORMAT(timestamp, '%Y-%m-%d')
            ORDER BY timestamp
        ''', flat_pruned_list(users, channels, pattern))
        return cur
예제 #12
0
 def __setitem__(self, guild_id: int, prefix: Optional[str]):
     typecheck(guild_id, int, 'guild_id')
     db.config.set_prefix(guild_id, prefix)
     self._prefixes[guild_id] = self.default if prefix is None else prefix