Skip to content

Transceiver

Persists a Discord message to internal models.

process_msg(redis, message)

Persists a Discord Message to PBot Message model in Redis.

Parameters:

Name Type Description Default
redis Redis

Redis connection

required
message Message

Discord Message

required

Returns:

Type Description
None

None

Source code in services/transceiver/src/transceiver/process_msg.py
def process_msg(redis: redis.Redis, message: discord.Message) -> None:
    '''Persists a Discord Message to PBot Message model in Redis.

    Args:
        redis (redis.Redis): Redis connection
        message (discord.Message): Discord Message

    Returns:
        None
    '''

    message_id: str = str(message.id)
    msg_created_timestamp = message.created_at.timestamp()

    # Don't process existing messages. (This can occur when pulling historic
    # messages.)
    if redis.exists(f'{REDIS_KEY_MESSAGE_PREFIX}:{message_id}'):
        return

    # Handle author. -----------------------------------------------------------
    author_id = str(message.author.id)

    if not redis.exists(f'{REDIS_KEY_USER_PREFIX}:{author_id}'):
        user_temp = User().mapping()
        user_temp['id'] = author_id
        user_temp['name'] = message.author.name
        redis.hset(f'{REDIS_KEY_USER_PREFIX}:{author_id}', mapping=user_temp)

        redis.sadd(REDIS_KEY_USERS, author_id)

    # Handle server. -----------------------------------------------------------
    server_id = str(message.guild.id)

    if not redis.exists(f'{REDIS_KEY_SERVER_PREFIX}:{server_id}'):
        server_temp = Server().mapping()
        server_temp['id'] = server_id
        server_temp['name'] = message.guild.name
        redis.hset(f'{REDIS_KEY_SERVER_PREFIX}:{server_id}', mapping=server_temp)

        redis.sadd(REDIS_KEY_SERVERS, server_id)

    # Relations
    redis.sadd(f'{REDIS_KEY_SERVER_PREFIX}:{server_id}:{REDIS_KEY_USERS}', author_id)
    redis.sadd(f'{REDIS_KEY_USER_PREFIX}:{author_id}:{REDIS_KEY_SERVERS}', server_id)

    # Handle channel. ----------------------------------------------------------
    channel_id = str(message.channel.id)

    if not redis.exists(f'{REDIS_KEY_CHANNEL_PREFIX}:{channel_id}'):
        channel_temp = Channel().mapping()
        channel_temp['id'] = channel_id
        channel_temp['name'] = message.channel.name
        channel_temp['server_id'] = server_id
        redis.hset(f'{REDIS_KEY_CHANNEL_PREFIX}:{channel_id}', mapping=channel_temp)

        redis.sadd(f'{REDIS_KEY_SERVER_PREFIX}:{server_id}:{REDIS_KEY_CHANNELS}', channel_id)
        redis.sadd(REDIS_KEY_CHANNELS, channel_id)

    # Relations
    redis.sadd(f'{REDIS_KEY_CHANNEL_PREFIX}:{channel_id}:{REDIS_KEY_USERS}', author_id)
    redis.sadd(f'{REDIS_KEY_USERS}:{author_id}:{REDIS_KEY_CHANNELS}', channel_id)

    # Handle message. ----------------------------------------------------------

    redis.zadd(REDIS_KEY_MESSAGES, {f'{server_id}.{channel_id}-{message_id}': msg_created_timestamp})

    # Handle occasional/changing server-based nick
    nick_name = ''
    if hasattr(message.author, 'nick') and message.author.nick:
        nick_name = message.author.nick

    # Handle changing avatar
    avatar = ''
    if hasattr(message.author, 'display_avatar') and message.author.display_avatar:
        avatar = message.author.display_avatar

    # Relations
    redis.zadd(f'{REDIS_KEY_USER_PREFIX}:{author_id}:{REDIS_KEY_MESSAGES}', {message_id: msg_created_timestamp})
    redis.zadd(f'{REDIS_KEY_CHANNEL_PREFIX}:{channel_id}:{REDIS_KEY_MESSAGES}', {message_id: msg_created_timestamp})
    redis.zadd(f'{REDIS_KEY_SERVER_PREFIX}:{server_id}:{REDIS_KEY_MESSAGES}', {message_id: msg_created_timestamp})

    # Copy & mod message template
    msg_temp = Message().mapping()
    msg_temp['id'] = message_id
    msg_temp['time'] = message.created_at.timestamp()
    msg_temp['content'] = message.clean_content
    msg_temp['origin']['server']['id'] = server_id
    msg_temp['origin']['server']['name'] = message.guild.name
    msg_temp['origin']['server']['channel']['id'] = channel_id
    msg_temp['origin']['server']['channel']['name'] = message.channel.name
    msg_temp['user']['id'] = author_id
    msg_temp['user']['bot'] = int(message.author.bot)
    msg_temp['user']['name'] = message.author.name
    msg_temp['user']['nick'] = nick_name
    msg_temp['user']['avatar'] = str(avatar)

    # Handle any attachments.
    for attachment in message.attachments:
        attachment_temp = Attachment().mapping()
        attachment_temp['id'] = attachment.id
        attachment_temp['url'] = attachment.url
        attachment_temp['filename'] = attachment.filename

        msg_temp['objects']['attachments'].append(attachment_temp)

    # Handle any links.
    for url in urls_from_string(message.clean_content):
        msg_temp['objects']['links'].append(url)

    # Store & expire.
    key = f'{REDIS_KEY_MESSAGE_PREFIX}:{message_id}'
    redis.json().set(key, Path.root_path(), msg_temp)
    redis.expire(key, REDIS_MESSAGE_EXPIRE_SECONDS)

urls_from_string(string)

Returns a list of substrings found to be URLs.

Parameters:

Name Type Description Default
string str

Input string

required

Returns:

Type Description
list[str]

list[str]: List of found URLs

Source code in services/transceiver/src/transceiver/process_msg.py
def urls_from_string(string: str) -> list[str]:
    '''Returns a list of substrings found to be URLs.

    Args:
        string (str): Input string

    Returns:
        list[str]: List of found URLs
    '''
    urls: list[str] = []

    for word in string.split():
        url = urlparse(word)
        if url.scheme and url.netloc:
            urls.append(word)

    return urls