Example #1
0
    async def select(self, ctx, name):
        terminal = sessions().get_by_name(name)
        if not terminal:
            raise TerminalNotFoundException()

        sessions().select(ctx.message.channel, terminal)
        await ctx.send(f"`Selected terminal #{name}`")
Example #2
0
    async def open(self, ctx, name: str = None):
        if name and len(name) > 20:
            raise ArgumentFormatException(
                'Session name length exceeds 20 characters limit')

        # Auto-generated name
        if not name:
            name = str(len(sessions().sessions))

        content = parse_template(settings().get('terminal.template'),
                                 name=name,
                                 state='OPENING',
                                 content='Waiting for tty..')
        message = await ctx.send(content)

        # Prepare terminal
        sh_path = settings().get('terminal.shell_path')
        terminal = Terminal(name,
                            sh_path=sh_path,
                            on_change=sessions().update_message)
        sessions().add(message, terminal)
        terminal.open()

        # Run macro on terminal startup
        startup_macro = settings().get('terminal.startup_macro')
        if startup_macro:
            await execute_macro(ctx, startup_macro)
Example #3
0
    async def close(self, ctx):
        terminal = sessions().get_by_channel(ctx.message.channel)

        if not terminal:
            raise SessionDontExistException()

        terminal.close()
        sessions().remove(terminal)

        await ctx.send(f"`Closed terminal #{terminal.name}`")
Example #4
0
    async def close(self, ctx):
        terminal = sessions().by_channel(ctx.message.channel)

        if not terminal:
            raise SessionDontExistException()

        terminal.close()

        if settings().get('terminal.delete_on_close'):
            message = sessions().find_message(terminal)
            await message.delete()

        sessions().remove(terminal)
        await ctx.send(f"`Closed terminal #{terminal.name}`")
Example #5
0
    async def on_message(self, message: Message):
        if message.author.bot:
            return

        terminal = sessions().get_by_channel(message.channel)

        if self.is_invoke(message):
            await self.process_commands(message)
        elif terminal and terminal.state == TerminalState.OPEN:
            prefix = extract_prefix(message.content)
            if not terminal.interactive and not prefix:
                return

            # We don't remove prefix when in interactive mode
            content = message.content
            if not terminal.interactive:
                content = remove_prefix(content)

            if terminal.auto_submit:
                content += '\n'

            terminal.input(content)

            # Log message
            guild_name = message.channel.guild.name
            channel_name = message.channel.name
            author_name = message.author.name
            self.cmd_logger.info(
                f"[{guild_name}/#{channel_name}/{terminal.name}] {author_name} typed: {content}"
            )
Example #6
0
    async def rename(self, ctx, new_name):
        terminal = sessions().get_by_channel(ctx.message.channel)

        old_name = terminal.name
        terminal.name = new_name
        terminal.refresh()
        await ctx.send(f"`Renamed terminal #{old_name} -> #{new_name}`")
Example #7
0
    async def on_message(self, message: Message):
        if message.author.bot:
            return

        is_owner = await self.is_owner(message.author)
        if not is_owner:
            if settings().get('discord.enable_users_whitelist'):
                users_whitelist = settings().get('discord.users_whitelist', [])

                if message.author.id not in users_whitelist:
                    first_prefix = settings().get('commands.prefixes')[0]
                    embed = Embed(
                        title=f'Only whitelisted users can execute commands',
                        description=
                        f'{first_prefix}.whitelist add {message.author.mention}'
                    )
                    await message.channel.send(embed=embed)
                    return

            if isinstance(message.channel,
                          DMChannel) and settings().get('discord.disable_dm'):
                embed = Embed(title=f'Using bot on DM is disabled',
                              description='discord.disable_dm = true')
                await message.channel.send(embed=embed)
                return

        terminal = sessions().by_channel(message.channel)

        if self.is_invoke(message):
            await self.process_commands(message)
        elif terminal and terminal.state == TerminalState.OPEN:
            prefix = extract_prefix(message.content)
            if not terminal.interactive and not prefix:
                return

            # We don't remove prefix when in interactive mode
            content = message.content
            if not terminal.interactive:
                content = remove_prefix(content)

            if terminal.auto_submit:
                content += '\n'

            terminal.send_input(content)

            # Log message
            guild_name = message.channel.guild.name
            channel_name = message.channel.name
            author_name = message.author.name
            self.cmd_logger.info(
                f"[{guild_name}/#{channel_name}/{terminal.name}] {author_name} typed: {content}"
            )

            should_delete_any = settings().get('terminal.delete_messages')
            should_delete_interactive = settings().get(
                'terminal.interactive.delete_messages')
            if should_delete_any or (should_delete_interactive
                                     and terminal.interactive):
                await message.delete()
Example #8
0
    async def submit(self, ctx: Context):
        terminal = sessions().by_channel(ctx.channel)

        terminal.auto_submit = not terminal.auto_submit
        if terminal.auto_submit:
            await ctx.send(f'`Enabled auto submit mode`')
        else:
            await ctx.send(f'`Disabled auto submit mode`')
Example #9
0
    async def on_reaction_add(self, reaction: Reaction, user: User):
        if user.bot:
            return

        terminal = sessions().by_message(reaction.message)
        if reaction.emoji not in terminal.controls:
            return

        control: TerminalControl = terminal.controls[reaction.emoji]
        terminal.send_input(control.text)
Example #10
0
    async def interactive(self, ctx: Context):
        terminal = sessions().by_channel(ctx.message.channel)

        if not terminal:
            raise SessionDontExistException()

        terminal.interactive = not terminal.interactive

        if terminal.interactive:
            await ctx.send(f"`Entered interactive mode. Repeat command to disable`")
        else:
            await ctx.send(f"`Exited interactive mode`")
Example #11
0
async def execute_macro(ctx, name):
    terminal = sessions().by_channel(ctx.channel)

    if name not in settings().macros:
        raise MacroNotFoundException()

    macro = settings().macros[name]
    for line in macro.split('\n'):
        if extract_prefix(line):
            ctx.message.content = line
            await ctx.bot.process_commands(ctx.message)
        else:
            terminal.send_input(line)
Example #12
0
    async def freeze(self, ctx):
        terminal = sessions().by_channel(ctx.message.channel)

        if not terminal:
            raise SessionDontExistException()

        if terminal.state == TerminalState.FROZEN:
            terminal.state = TerminalState.OPEN
        elif terminal.state == TerminalState.OPEN:
            terminal.state = TerminalState.FROZEN

        terminal.refresh()
        await ctx.send(
            f"`Changed terminal #{terminal.name} state to {terminal.state.name}`"
        )
Example #13
0
    async def here(self, ctx: Context):
        terminal = sessions().by_channel(ctx.channel)
        message = sessions().find_message(terminal)

        await message.delete()
        sessions().remove(terminal)

        message = await ctx.send("Moving terminal...")
        sessions().add(message, terminal)

        terminal.refresh()
Example #14
0
    async def repeat(self, ctx, n: int, *, text):
        terminal = sessions().get_by_channel(ctx.message.channel)
        if not terminal:
            raise SessionDontExistException()

        terminal.input(text * n)
Example #15
0
    async def predicate(ctx):
        if not sessions().by_channel(ctx.message.channel):
            raise SessionDontExistException()

        return True
Example #16
0
    async def remove(self, ctx, emoji_id):
        terminal: Terminal = sessions().get_by_channel(ctx.channel)
        message: Message = sessions().get_message(terminal)

        terminal.remove_control(emoji_id)
        await message.remove_reaction(emoji_id, message.author)
Example #17
0
    async def add(self, ctx, emoji_id, content):
        terminal: Terminal = sessions().get_by_channel(ctx.channel)
        message: Message = sessions().get_message(terminal)

        terminal.add_control(emoji_id, content)
        await message.add_reaction(emoji_id)