diff --git a/bot/bot.py b/bot/bot.py index b3f2be3..dc3ff5f 100644 --- a/bot/bot.py +++ b/bot/bot.py @@ -43,6 +43,7 @@ def schedule_bot(loop, config, db): command_prefix='sex ', description='sexhouse management bot', owner_id=getattr(config, 'owner_id', None), + loop=loop ) bot.db = db diff --git a/bot/ext/rsudo.py b/bot/ext/rsudo.py index 2a5ebd6..00369d3 100644 --- a/bot/ext/rsudo.py +++ b/bot/ext/rsudo.py @@ -2,6 +2,7 @@ import logging import asyncio import discord +from discord.ext import commands from .common import Cog @@ -22,14 +23,13 @@ async def shell(command: str): class Rsudo(Cog): def __init__(self, bot): super().__init__(bot) - self.command_channel = None async def create_request(self, message): - if not self.command_channel: - self.command_channel = self.bot.get_channel( - self.bot.config.command_channel) + command_channel = self.bot.get_channel( + self.bot.config.command_channel + ) - if not self.command_channel: + if command_channel is None: log.warning('command channel not found') return @@ -38,32 +38,78 @@ class Rsudo(Cog): command = ','.join(message.split(',')[:-1]) log.info(f'[rsudo] {uid!r} {command!r}') - e = discord.Embed(title=f'rsudo from uid {uid}') - e.add_field(name='command', value=f'`{command}`') - m = await self.command_channel.send(embed=e) - await m.add_reaction('\N{WHITE HEAVY CHECK MARK}') - await m.add_reaction('\N{CROSS MARK}') + embed = discord.Embed( + title=f'RSudo request from UID {uid}', + description=f'```sh\n{command}```', + color=discord.Color.purple(), + ) + msg = await command_channel.send(embed=embed) - emotes = ['\N{WHITE HEAVY CHECK MARK}', - '\N{CROSS MARK}'] + await msg.add_reaction('\N{WHITE HEAVY CHECK MARK}') + await msg.add_reaction('\N{CROSS MARK}') - def check(reaction, user): - return user and \ - reaction.emoji in emotes and \ - any(x.id == self.bot.config.admin_role for x in user.roles) + emoji = { + '\N{WHITE HEAVY CHECK MARK}': True, + '\N{CROSS MARK}': False, + } - reaction, user = await self.bot.wait_for('reaction_add', check=check) + def check(_reaction, _user): + if _user is None: + return False - if reaction.emoji == emotes[0]: - # do - await self.command_channel.send('executing') - out = await shell(command) - fmt = f'```\n{out}\n```' - await self.command_channel.send(fmt) + if reaction.emoji not in emoji.keys(): + return False + + return discord.utils.get(_user.roles, id=self.bot.config.admin_role) is not None + + reaction, admin = await self.bot.wait_for('reaction_add', check=check) + await msg.clear_reactions() + + should_execute = emoji.get(reaction.emoji) + + user = None + # todo: get user ID from ldap to send results later + + if should_execute: + log.info(f'executing command for {uid}, accepted by {admin} {admin.id}') + + async with command_channel.typing(): + embed.colour = discord.Color.green() + embed.add_field(name='status', value=f'Accepted by {admin} {admin.id}') + + await msg.edit(embed=embed) + + # todo: does this not execute in the wrong directory? + out = await shell(command) + + # output may be very long + paginator = commands.Paginator(prefix='```sh\n', suffix='```') + for line in out.split('\n'): + paginator.add_line(line.strip()) + + for page in paginator.pages: + await command_channel.send(page) + + try: + await user.send(f'Your request for the command {command} was accepted:') + + for page in paginator.pages: + await user.send(page) + except discord.HTTPException: + await command_channel.send(f'Failed to send results to {user}.') else: - # dont do - await self.command_channel.send('denied with success') + log.info(f'not executing command for {uid}, denied by {admin} {admin.id}') + + embed.colour = discord.Color.red() + embed.add_field(name='status', value=f'Denied by {admin} {admin.id}') + + await msg.edit(embed=embed) + + try: + await user.send(f'Your request for the command {command} was denied.') + except discord.HTTPException: + await command_channel.send(f'Failed to send denial message to {user}.') def setup(bot):