Skip to content

Instantly share code, notes, and snippets.

@supposedly
Created February 20, 2018 18:10
Show Gist options
  • Select an option

  • Save supposedly/a612aa66b41ed9f13a4e311b6777256e to your computer and use it in GitHub Desktop.

Select an option

Save supposedly/a612aa66b41ed9f13a4e311b6777256e to your computer and use it in GitHub Desktop.

Revisions

  1. supposedly created this gist Feb 20, 2018.
    182 changes: 182 additions & 0 deletions dpy_msg_relay.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,182 @@
    import pkg_resources
    import platform
    import os
    from collections import defaultdict
    from inspect import cleandoc

    import asyncpg
    import discord
    from discord.ext import commands


    DISCORD_PUBLIC_VERSION = pkg_resources.get_distribution('discord.py').parsed_version.public
    PY_VERSION = platform.python_version()

    bot = commands.Bot(command_prefix=commands.when_mentioned_or('+/'))
    bot.chns = defaultdict(set)
    bot.msgs = set()


    class ChannelConv:
    @classmethod
    async def convert(cls, ctx, chn_id):
    if chn_id != ctx.channel.id:
    return bot.get_channel(int(chn_id))


    def getchn(chn_id: str) -> discord.TextChannel:
    return bot.get_channel(int(chn_id))


    @bot.event
    async def on_ready():
    #########################################
    # THIS WORKS OUT-OF-THE-BOX ON HEROKU #
    # IF NOT ON HEROKU REPLACE WITH YOUR #
    # OWN INITIALIZATION PARAMETERS #
    bot.pool = await asyncpg.create_pool(os.getenv('DATABASE_URL'))
    # ALSO IF NOT ON HEROKU, MAKE SURE YOU #
    # CREATE A PROPER ROLE/ACCT IN POSTGRES #
    # FOR THE BOT (INSTEAD OF DOING IT IN #
    # ONE SPOT LIKE BELOW) #
    await bot.pool.execute('''CREATE TABLE IF NOT EXISTS chlinks (source BIGINT, dest BIGINT, PRIMARY KEY (source, dest))''')
    #########################################
    for i in await bot.pool.fetch('''SELECT source, dest FROM chlinks'''):
    bot.chns[getchn(i['source'])].add(getchn(i['dest']))
    print('oof')


    @bot.event
    async def on_message(msg):
    st = 0
    for i in bot.msgs.copy():
    if i.content in msg.content or i.author.id != bot.user.id:
    bot.msgs ^= {i}
    st += i.content in msg.content
    if st < 1:
    if msg.channel in bot.chns:
    for chn in bot.chns[msg.channel]:
    try:
    await chn.send(f'**<`{msg.guild.name}`/`#{msg.channel.name}`:{msg.author.nick or msg.author.name}>** {msg.content}')
    bot.msgs.add(msg)
    except Exception as e:
    print(f'Error sending {msg.id} from {msg.channel.name} in {msg.guild.name} to {chn.name} in {chn.guild.name}. {e.__class__.__name__}: {e}')
    await bot.process_commands(msg)


    @bot.event
    async def on_command_error(ctx, e):
    await ctx.message.add_reaction('πŸ‘Ž')
    if not isinstance(e, commands.errors.CommandNotFound):
    await ctx.send(f'`{e.__class__.__name__}: {e}`')


    @bot.group()
    async def relay(ctx):
    """
    Relay commands between channels.
    ``````apache
    +/relay to [chnID chnID chnID ...]
    # Send to this channel from the others #
    ``````apache
    +/relay from [chnID chnID chnID ...]
    # Send from this channel to the others #
    ``````apache
    +/relay both [chnID chnID chnID ...]
    # Send both ways between this channel and the others #
    ``````
    """
    pass

    @relay.command('from')
    async def from_(ctx, *chns: ChannelConv):
    """
    Send to current channel from the given ones.
    ``````apache
    +/relay from [chnID chnID chnID ...]
    """
    async with bot.pool.acquire() as conn:
    await conn.copy_records_to_table(
    'chlinks',
    records = list({(i.id, ctx.channel.id) for i in filter(None, chns)}),
    columns = ['source', 'dest']
    )
    for chn in chns:
    bot.chns[chn].add(ctx.channel)
    await ctx.message.add_reaction('πŸ‘')

    @relay.command()
    async def to(ctx, *chns: ChannelConv):
    """
    Send from current channel to the given ones.
    ``````apache
    +/relay to [chnID chnID chnID ...]
    """
    async with bot.pool.acquire() as conn:
    await conn.copy_records_to_table(
    'chlinks',
    records = list({(ctx.channel.id, i.id) for i in filter(None, chns)}),
    columns = ['source', 'dest']
    )
    bot.chns[ctx.channel].update(chns)
    await ctx.message.add_reaction('πŸ‘')

    @relay.command(aliases=['between', 'btwn'])
    async def both(ctx, *chns: ChannelConv):
    """
    Send between current channel and the given ones.
    ``````apache
    +/relay both [chnID chnID chnID ...]
    """
    recs = {(ctx.channel.id, i.id) for i in filter(None, chns)}
    async with bot.pool.acquire() as conn:
    await conn.copy_records_to_table(
    'chlinks',
    records = list(recs) + [i[::-1] for i in recs],
    columns = ['source', 'dest']
    )
    bot.chns[ctx.channel].update(chns)
    for chn in chns:
    bot.chns[chn].add(ctx.channel)
    await ctx.message.add_reaction('πŸ‘')

    @bot.command()
    async def unlink(ctx, *chns: ChannelConv):
    """
    Unlink current channel from each given no matter their relation.
    ``````apache
    +/unlink [chnID chnID chnID ...]
    """
    bot.chns[ctx.channel] ^= set(chns) & bot.chns[ctx.channel]
    for chn in chns:
    if ctx.channel in bot.chns[chn]:
    bot.chns[chn] ^= {ctx.channel}
    await bot.pool.execute('''
    DELETE FROM chlinks
    WHERE (source = $1::bigint AND dest = $2::bigint)
    OR (dest = $1::bigint AND source = $2::bigint)
    ''',
    ctx.channel.id,
    chn.id
    )
    await ctx.message.add_reaction('πŸ‘')

    @bot.command(aliases=['about'])
    async def info(ctx):
    """About this bot."""
    desc = f'''**```ini
    {'[An inter-guild message-relaying demo bot]': ^45}```**
    **Version numbers:**
    python {PY_VERSION}
    discord.py {DISCORD_PUBLIC_VERSION} (rewrite)
    **Links:**
    β€’ [The original Reddit comment](https://reddit.com/comments/7yr4ur//dujbrym/)
    **By Wright#9480**
    ```FORTRAN
    {f"'+/help' for command info": ^45}```
    '''
    await ctx.send(embed=discord.Embed(description=cleandoc(desc)))

    bot.run('TOKEN HERE')