Example #1
0
    async def on_command_error(self, ctx, exception):
        def human_join(strings):
            if len(strings) <= 2:
                return ' or '.join(strings)
            else:
                return ', '.join(
                    strings[:len(strings) - 1]) + ' or ' + strings[-1]

        if isinstance(exception, commands.BadUnionArgument):
            msg = 'Could not find the specified ' + human_join(
                [c.__name__ for c in exception.converters])
            await ctx.trigger_typing()
            await ctx.send(
                embed=discord.Embed(color=discord.Color.red(), description=msg)
            )

        elif isinstance(exception, commands.BadArgument):
            await ctx.trigger_typing()
            await ctx.send(embed=discord.Embed(color=discord.Color.red(),
                                               description=str(exception)))
        elif isinstance(exception, commands.MissingRequiredArgument):
            await ctx.invoke(self.get_command('help'),
                             command=str(ctx.command))
        elif isinstance(exception, commands.CommandNotFound):
            logger.warning(error('CommandNotFound: ' + str(exception)))
        elif isinstance(exception, commands.CheckFailure):
            logger.warning(error('CheckFailure: ' + str(exception)))
        else:
            logger.error(error('Unexpected exception:'), exc_info=exception)
Example #2
0
    async def validate_api_token(self):
        try:
            self.config.modmail_api_token
        except KeyError:
            logger.critical(error(f'MODMAIL_API_TOKEN not found.'))
            logger.critical(
                error('Set a config variable called '
                      'MODMAIL_API_TOKEN with a token from '
                      'https://dashboard.modmail.tk.'))
            logger.critical(
                error('If you want to self-host logs, '
                      'input a MONGO_URI config variable.'))
            logger.critical(
                error('A Modmail API token is not needed '
                      'if you are self-hosting logs.'))

            return await self.logout()
        else:
            valid = await self.api.validate_token()
            if not valid:
                logger.critical(
                    error('Invalid MODMAIL_API_TOKEN - get one '
                          'from https://dashboard.modmail.tk'))
                return await self.logout()

        user = await self.api.get_user_info()
        username = user['user']['username']
        logger.info(info('Validated token.'))
        logger.info(info('GitHub user: ' + username))
Example #3
0
    def run(self, *args, **kwargs):
        try:
            self.loop.run_until_complete(self.start(self.token))
        except discord.LoginFailure:
            logger.critical(error("Invalid token"))
        except KeyboardInterrupt:
            pass
        except Exception:
            logger.critical(error("Fatal exception"), exc_info=True)
        finally:
            try:
                self.metadata_task.cancel()
                self.loop.run_until_complete(self.metadata_task)
            except asyncio.CancelledError:
                logger.debug(info("data_task has been cancelled."))
            try:
                self.autoupdate_task.cancel()
                self.loop.run_until_complete(self.autoupdate_task)
            except asyncio.CancelledError:
                logger.debug(info("autoupdate_task has been cancelled."))

            self.loop.run_until_complete(self.logout())
            for task in asyncio.Task.all_tasks():
                task.cancel()
            try:
                self.loop.run_until_complete(
                    asyncio.gather(*asyncio.Task.all_tasks()))
            except asyncio.CancelledError:
                logger.debug(info("All pending tasks has been cancelled."))
            finally:
                self.loop.run_until_complete(self.session.close())
                self.loop.close()
                logger.info(error(" - Shutting down bot - "))
Example #4
0
    async def on_command_error(self, context, exception):
        if isinstance(exception, commands.BadUnionArgument):
            msg = "Could not find the specified " + human_join(
                [c.__name__ for c in exception.converters])
            await context.trigger_typing()
            await context.send(
                embed=discord.Embed(color=discord.Color.red(), description=msg)
            )

        elif isinstance(exception, commands.BadArgument):
            await context.trigger_typing()
            await context.send(embed=discord.Embed(color=discord.Color.red(),
                                                   description=str(exception)))
        elif isinstance(exception, commands.CommandNotFound):
            logger.warning(error("CommandNotFound: " + str(exception)))
        elif isinstance(exception, commands.MissingRequiredArgument):
            await context.send_help(context.command)
        elif isinstance(exception, commands.CheckFailure):
            for check in context.command.checks:
                if not await check(context) and hasattr(check, "fail_msg"):
                    await context.send(embed=discord.Embed(
                        color=discord.Color.red(), description=check.fail_msg))
            logger.warning(error("CheckFailure: " + str(exception)))
        else:
            logger.error(error("Unexpected exception:"), exc_info=exception)
Example #5
0
    async def validate_database_connection(self):
        try:
            await self.db.command("buildinfo")
        except Exception as exc:
            logger.critical(
                error("Something went wrong "
                      "while connecting to the database."))
            message = f"{type(exc).__name__}: {str(exc)}"
            logger.critical(error(message))

            if "ServerSelectionTimeoutError" in message:
                logger.critical(
                    error("This may have been caused by not whitelisting "
                          "IPs correctly. Make sure to whitelist all "
                          "IPs (0.0.0.0/0) https://i.imgur.com/mILuQ5U.png"))

            if "OperationFailure" in message:
                logger.critical(
                    error(
                        "This is due to having invalid credentials in your MONGO_URI."
                    ))
                logger.critical(
                    error(
                        "Recheck the username/password and make sure to url encode them. "
                        "https://www.urlencoder.io/"))

            return await self.logout()
        else:
            logger.info(info("Successfully connected to the database."))
Example #6
0
 async def on_command_error(self, context, exception):
     if isinstance(exception, (commands.MissingRequiredArgument,
                               commands.UserInputError)):
         await context.invoke(self.get_command('help'),
                              command=str(context.command))
     elif isinstance(exception, commands.CommandNotFound):
         logger.warning(error('CommandNotFound: ' + str(exception)))
     else:
         logger.error(error('Unexpected exception:'), exc_info=exception)
Example #7
0
 async def validate_database_connection(self):
     try:
         await self.db.command('buildinfo')
     except Exception as exc:
         logger.critical(error('Something went wrong '
                               'while connecting to the database.'))
         logger.critical(error(f'{type(exc).__name__}: {str(exc)}'))
         return await self.logout()
     else:
         logger.info(info('Successfully connected to the database.'))
Example #8
0
    async def load_plugin(self, username, repo, plugin_name, branch):
        ext = f"plugins.{username}-{repo}-{branch}.{plugin_name}.{plugin_name}"
        dirname = f"plugins/{username}-{repo}-{branch}/{plugin_name}"

        if "requirements.txt" in os.listdir(dirname):
            # Install PIP requirements

            venv = hasattr(sys, "real_prefix")  # in a virtual env
            user_install = "--user" if not venv else ""

            try:
                if os.name == "nt":  # Windows
                    await self.bot.loop.run_in_executor(
                        None,
                        self._asubprocess_run,
                        f"pip install -r {dirname}/requirements.txt {user_install} -q -q",
                    )
                else:
                    await self.bot.loop.run_in_executor(
                        None,
                        self._asubprocess_run,
                        f"python3 -m pip install -U -r {dirname}/"
                        f"requirements.txt {user_install} -q -q",
                    )
                    # -q -q (quiet)
                    # so there's no terminal output unless there's an error
            except subprocess.CalledProcessError as exc:
                err = exc.stderr.decode("utf8").strip()

                if err:
                    msg = f"Requirements Download Error: {username}/{repo}@{branch}[{plugin_name}]"
                    logger.error(error(msg))
                    raise DownloadError(
                        f"Unable to download requirements: ```\n{err}\n```"
                    ) from exc
            else:
                if not os.path.exists(site.USER_SITE):
                    os.makedirs(site.USER_SITE)

                sys.path.insert(0, site.USER_SITE)

        await asyncio.sleep(0.5)
        try:
            self.bot.load_extension(ext)
        except commands.ExtensionError as exc:
            msg = f"Plugin Load Failure: {username}/{repo}@{branch}[{plugin_name}]"
            logger.error(error(msg))
            raise DownloadError("Invalid plugin") from exc
        else:
            msg = f"Loaded Plugin: {username}/{repo}@{branch}[{plugin_name}]"
            logger.info(info(msg))
Example #9
0
def barcode(req, format, barcode=''):
    if format == 'svg':
        bc = Code39(barcode, add_checksum=False)
        mimetype = 'image/svg+xml'
    else:
        if ImageWriter is None:
            return utils.error(req, _('PIL is not installed.'))
        bc = Code39(barcode, ImageWriter(), add_checksum=False)
        mimetype = 'image/{0}'.format(format)
    response = HttpResponse(mimetype=mimetype)
    try:
        bc.write(response, options={'format': format.upper()})
    except KeyError:
        return utils.error(req, _('Unsupported barcode format.'))
    return response
Example #10
0
    async def download_initial_plugins(self):
        await self.bot._connected.wait()
        for i in self.bot.config.plugins:
            parsed_plugin = self.parse_plugin(i)

            try:
                await self.download_plugin_repo(*parsed_plugin[:-1])
            except DownloadError as exc:
                msg = f'{parsed_plugin[0]}/{parsed_plugin[1]} - {exc}'
                logger.error(error(msg))
            else:
                try:
                    await self.load_plugin(*parsed_plugin)
                except DownloadError as exc:
                    msg = f'{parsed_plugin[0]}/{parsed_plugin[1]} - {exc}'
                    logger.error(error(msg))
Example #11
0
    async def predicate(ctx):
        has_perm = await check_permissions(ctx, ctx.command.qualified_name, permission_level)

        if not has_perm and ctx.command.qualified_name != 'help':
            logger.error(error(f'You does not have permission to use this command: '
                               f'`{ctx.command.qualified_name}` ({permission_level.name}).'))
        return has_perm
Example #12
0
    async def send_error_message(self, msg):  # pylint: disable=W0221
        logger.warning(error(f"CommandNotFound: {msg}"))

        embed = Embed(color=Color.red())
        embed.set_footer(
            text=f'Command/Category "{self.context.kwargs.get("command")}" not found.'
        )

        choices = set()

        for name, cmd in self.context.bot.all_commands.items():
            if not cmd.hidden:
                choices.add(name)
        command = self.context.kwargs.get("command")
        closest = get_close_matches(command, choices)
        if closest:
            embed.add_field(
                name=f"Perhaps you meant:", value="\n".join(f"`{x}`" for x in closest)
            )
        else:
            embed.title = "Cannot find command or category"
            embed.set_footer(
                text=f'Type "{self.clean_prefix}{self.command_attrs["name"]}" '
                "for a list of all available commands."
            )
        await self.get_destination().send(embed=embed)
Example #13
0
def export_group_excel(req, gid):
    if Workbook is None:
        return utils.error(u'Die Excelerweiterung ist nicht installiert.')
    group = StudentGroup.objects.select_related().get(id=int(gid))
    wb = Workbook()
    ws = wb.get_active_sheet()
    ws.cell('A1').value = unicode(group)
    ws.cell('A3').value = u'Firma'
    ws.cell('B3').value = u'Name'
    ws.cell('C3').value = u'Vorname'
    row = 4
    for s in group.students.filter(finished=False).order_by(
      'company__short_name', 'lastname'):
        if s.company:
            comp = s.company.short_name
        else:
            comp = u'-'
        ws.cell('A{0}'.format(row)).value = comp
        ws.cell('B{0}'.format(row)).value = s.lastname
        ws.cell('C{0}'.format(row)).value = s.firstname
        row += 1
    dest = os.path.join(
        settings.LATEX_BUILD_DIR, 'excel_exp_{0}.xlsx'.format(time.time())
    )
    wb.save(dest)
    with open(dest, 'rb') as fp:
        response = HttpResponse(
            fp.read(), content_type='application/vnd.'
            'openxmlformats-officedocument.spreadsheetml.sheet'
        )
    response['Content-Disposition'] = 'attachment; filename="{0}.xlsx"'.format(
        group.name())
    os.remove(dest)
    return response
Example #14
0
    def _load_extensions(self):
        """Adds commands automatically"""
        self.remove_command('help')

        logger.info(LINE)
        logger.info(info(' _____  _                       _   ______ _____  '))
        logger.info(info('|  __ \(_)                     | | |  ____|  __ \ '))
        logger.info(info('| |  | |_ ___  ___ ___  _ __ __| | | |__  | |__) |'))
        logger.info(info('| |  | | / __|/ __/ _ \|  __/ _` | |  __| |  _  / '))
        logger.info(info('| |__| | \__ \ (_| (_) | | | (_| |_| |    | | \ \ '))
        logger.info(
            info('|_____/|_|___/\___\___/|_|  \__,_(_)_|    |_|  \_\ '))
        logger.info(info(f'v{__version__}'))
        logger.info(info('Authors: kyb3r, fourjr, Taaku18'))
        logger.info(LINE)

        for file in os.listdir('cogs'):
            if not file.endswith('.py'):
                continue
            cog = f'cogs.{file[:-3]}'
            logger.info(info(f'Loading {cog}'))
            try:
                self.load_extension(cog)
            except Exception:
                logger.exception(error(f'Failed to load {cog}'))
Example #15
0
    async def predicate(ctx):
        """
        Parameters
        ----------
        ctx : Context
            The current discord.py `Context`.

        Returns
        -------
        bool
            `True` if the author is a bot owner, or
            has the ``administrator`` permission.
            Or if the author has all of the required permissions.
            Otherwise, `False`.
        """
        if await ctx.bot.is_owner(ctx.author):
            return True

        resolved = ctx.channel.permissions_for(ctx.author)

        has_perm = resolved.administrator or all(
            getattr(resolved, name, None) == value
            for name, value in perms.items())

        if not has_perm:
            restrictions = ', '.join(
                f'{name.replace("_", " ").title()} ({"yes" if value else "no"})'
                for name, value in perms.items())
            logger.error(
                error(f'Command `{ctx.command.qualified_name}` processes '
                      f'the following restrictions(s): {restrictions}.'))
        return has_perm
Example #16
0
    def _configure_logging(self):
        level_text = self.config.log_level.upper()
        logging_levels = {
            "CRITICAL": logging.CRITICAL,
            "ERROR": logging.ERROR,
            "WARNING": logging.WARNING,
            "INFO": logging.INFO,
            "DEBUG": logging.DEBUG,
        }

        log_file_name = self.config.token.split(".")[0]
        ch_debug = logging.FileHandler(os.path.join(temp_dir,
                                                    f"{log_file_name}.log"),
                                       mode="a+")

        ch_debug.setLevel(logging.DEBUG)
        formatter_debug = FileFormatter(
            "%(asctime)s %(filename)s - "
            "%(levelname)s: %(message)s",
            datefmt="%Y-%m-%d %H:%M:%S",
        )
        ch_debug.setFormatter(formatter_debug)
        logger.addHandler(ch_debug)

        log_level = logging_levels.get(level_text)
        logger.info(LINE)
        if log_level is not None:
            logger.setLevel(log_level)
            ch.setLevel(log_level)
            logger.info(info("Logging level: " + level_text))
        else:
            logger.info(error("Invalid logging level set. "))
            logger.info(info("Using default logging level: INFO"))
Example #17
0
    async def download_initial_plugins(self):
        await self.bot._connected.wait()

        for i in self.bot.config.plugins:
            username, repo, name, branch = self.parse_plugin(i)

            try:
                await self.download_plugin_repo(username, repo, branch)
            except DownloadError as exc:
                msg = f"{username}/{repo}@{branch} - {exc}"
                logger.error(error(msg))
            else:
                try:
                    await self.load_plugin(username, repo, name, branch)
                except DownloadError as exc:
                    msg = f"{username}/{repo}@{branch}[{name}] - {exc}"
                    logger.error(error(msg))
Example #18
0
    async def reply(self, message: discord.Message,
                    anonymous: bool = False) -> None:
        if not message.content and not message.attachments:
            raise MissingRequiredArgument(param(name='msg'))
        if all(not g.get_member(self.id) for g in self.bot.guilds):
            return await message.channel.send(
                embed=discord.Embed(
                    color=discord.Color.red(),
                    description='Your message could not be delivered since '
                                'the recipient shares no servers with the bot.'
                ))

        tasks = []

        try:
            await self.send(message,
                            destination=self.recipient,
                            from_mod=True,
                            anonymous=anonymous)
        except Exception:
            logger.info(error('Message delivery failed:'), exc_info=True)
            tasks.append(message.channel.send(
                embed=discord.Embed(
                    color=discord.Color.red(),
                    description='Your message could not be delivered as '
                                'the recipient is only accepting direct '
                                'messages from friends, or the bot was '
                                'blocked by the recipient.'
                )
            ))
        else:
            # Send the same thing in the thread channel.
            tasks.append(
                self.send(message,
                          destination=self.channel,
                          from_mod=True,
                          anonymous=anonymous)
            )

            tasks.append(
                self.bot.api.append_log(message,
                                        self.channel.id,
                                        type_='anonymous' if anonymous else 'thread_message'
                                        ))

        if self.close_task is not None:
            # Cancel closing if a thread message is sent.
            await self.cancel_closure()
            tasks.append(
                self.channel.send(
                    embed=discord.Embed(
                        color=discord.Color.red(),
                        description='Scheduled close has been cancelled.'
                    )
                )
            )

        await asyncio.gather(*tasks)
Example #19
0
    async def download_initial_plugins(self):
        await self.bot._connected.wait()
        for i in self.bot.config.plugins:
            parsed_plugin = self.parse_plugin(i)

            try:
                await self.download_plugin_repo(*parsed_plugin[:-1])
            except DownloadError as exc:
                msg = f'{parsed_plugin[0]}/{parsed_plugin[1]} - {exc}'
                logger.error(error(msg))
            else:
                try:
                    await self.load_plugin(*parsed_plugin)
                except DownloadError as exc:
                    msg = f'{parsed_plugin[0]}/{parsed_plugin[1]} - {exc}'
                    logger.error(error(msg))
        await async_all(env() for env in self.bot.extra_events.get('on_plugin_ready', []))
        logger.debug(info('on_plugin_ready called.'))
Example #20
0
    async def reply(self,
                    message: discord.Message,
                    anonymous: bool = False) -> None:
        if not message.content and not message.attachments:
            raise MissingRequiredArgument(param(name="msg"))
        if all(not g.get_member(self.id) for g in self.bot.guilds):
            return await message.channel.send(embed=discord.Embed(
                color=discord.Color.red(),
                description="Votre message na pas pu être envoyé :"
                "le destinataire nest pas sur le serveur.",
            ))

        tasks = []

        try:
            await self.send(message,
                            destination=self.recipient,
                            from_mod=True,
                            anonymous=anonymous)
        except Exception:
            logger.info(error("Erreur :"), exc_info=True)
            tasks.append(
                message.channel.send(embed=discord.Embed(
                    color=discord.Color.red(),
                    description="Votre message na pas pu être envoyé :"
                    "Erreur destinataire "
                    "Erreur destinataire "
                    "Le bot est bloqué par le destinataire.",
                )))
        else:
            # Send the same thing in the thread channel.
            tasks.append(
                self.send(
                    message,
                    destination=self.channel,
                    from_mod=True,
                    anonymous=anonymous,
                ))

            tasks.append(
                self.bot.api.append_log(
                    message,
                    self.channel.id,
                    type_="anonymous" if anonymous else "thread_message",
                ))

            # Cancel closing if a thread message is sent.
            if self.close_task is not None:
                await self.cancel_closure()
                tasks.append(
                    self.channel.send(embed=discord.Embed(
                        color=discord.Color.red(),
                        description="Annulé",
                    )))

        await asyncio.gather(*tasks)
Example #21
0
    async def on_ready(self):
        """Bot startup, sets uptime."""
        await self._connected.wait()
        logger.info(LINE)
        logger.info(info("Client ready."))
        logger.info(LINE)
        logger.info(info(f"Logged in as: {self.user}"))
        logger.info(info(f"User ID: {self.user.id}"))
        logger.info(info(f"Prefix: {self.prefix}"))
        logger.info(
            info(f"Guild Name: {self.guild.name if self.guild else 'None'}"))
        logger.info(info(f"Guild ID: {self.guild.id if self.guild else 0}"))

        logger.info(LINE)

        if not self.guild:
            logger.error(
                error("WARNING - The GUILD_ID "
                      "provided does not exist!"))
        else:
            await self.threads.populate_cache()

        # Wait until config cache is populated with stuff from db
        await self.config.wait_until_ready()

        # closures
        closures = self.config.closures.copy()
        logger.info(
            info(f"There are {len(closures)} thread(s) "
                 "pending to be closed."))

        for recipient_id, items in closures.items():
            after = (datetime.fromisoformat(items["time"]) -
                     datetime.utcnow()).total_seconds()
            if after < 0:
                after = 0

            thread = await self.threads.find(recipient_id=int(recipient_id))

            if not thread:
                # If the channel is deleted
                self.config.closures.pop(str(recipient_id))
                await self.config.update()
                continue

            await thread.close(
                closer=self.get_user(items["closer_id"]),
                after=after,
                silent=items["silent"],
                delete_channel=items["delete_channel"],
                message=items["message"],
                auto_close=items.get("auto_close", False),
            )

        logger.info(LINE)
Example #22
0
 def main_color(self) -> typing.Union[discord.Color, int]:
     color = self.config.get("main_color")
     if not color:
         return discord.Color.blurple()
     try:
         color = int(color.lstrip("#"), base=16)
     except ValueError:
         logger.error(error("Invalid main_color provided"))
         return discord.Color.blurple()
     else:
         return color
Example #23
0
 def mod_color(self) -> typing.Union[discord.Color, int]:
     color = self.config.get('mod_color')
     if not color:
         return discord.Color.green()
     try:
         color = int(color.lstrip('#'), base=16)
     except ValueError:
         logger.error(error('Invalid mod_color provided'))
         return discord.Color.green()
     else:
         return color
Example #24
0
    async def plugin_remove(self, ctx, *, plugin_name: str):
        """Remove a plugin."""

        if plugin_name in self.registry:
            details = self.registry[plugin_name]
            plugin_name = (
                details["repository"] + "/" + plugin_name + "@" + details["branch"]
            )

        if plugin_name in self.bot.config.plugins:
            try:
                username, repo, name, branch = self.parse_plugin(plugin_name)

                self.bot.unload_extension(
                    f"plugins.{username}-{repo}-{branch}.{name}.{name}"
                )
            except Exception:
                pass

            self.bot.config.plugins.remove(plugin_name)

            try:
                # BUG: Local variables 'username' and 'repo' might be referenced before assignment
                if not any(
                    i.startswith(f"{username}/{repo}") for i in self.bot.config.plugins
                ):
                    # if there are no more of such repos, delete the folder
                    def onerror(func, path, exc_info):  # pylint: disable=W0613
                        if not os.access(path, os.W_OK):
                            # Is the error an access error?
                            os.chmod(path, stat.S_IWUSR)
                            func(path)

                    shutil.rmtree(
                        f"plugins/{username}-{repo}-{branch}", onerror=onerror
                    )
            except Exception as exc:
                logger.error(str(exc))
                self.bot.config.plugins.append(plugin_name)
                logger.error(error(exc))
                raise exc

            await self.bot.config.update()

            embed = discord.Embed(
                description="The plugin is uninstalled and all its data is erased.",
                color=self.bot.main_color,
            )
            await ctx.send(embed=embed)
        else:
            embed = discord.Embed(
                description="That plugin is not installed.", color=self.bot.main_color
            )
            await ctx.send(embed=embed)
Example #25
0
 def main_color(self):
     color = self.config.get('main_color')
     if not color:
         return discord.Color.blurple()
     try:
         color = int(color.lstrip('#'), base=16)
     except ValueError:
         logger.error(error('Invalid main_color provided'))
         return discord.Color.blurple()
     else:
         return color
Example #26
0
 def recipient_color(self):
     color = self.config.get('recipient_color')
     if not color:
         return discord.Color.gold()
     try:
         color = int(color.lstrip('#'), base=16)
     except ValueError:
         logger.error(error('Invalid recipient_color provided'))
         return discord.Color.gold()
     else:
         return color
Example #27
0
    def validate(cls):
        # Check current machine can run this backup process or not.
        # We compare hostname in config.json with runtime hostname,
        # if they are equal, current machine has privilege to run this script.
        if utils.hostname() != Configure.get('hostname'):
            utils.error(
                'Error: Hostname not match. \n' +
                'Run command [configure] to redump hostname and try again.')

        # Validate required input
        required_keys = [
            'aws_access_key_id',
            'aws_secret_access_key',
            'region_name',
            'bucket',
            'backup_paths',
            'keep_days',
            'retry',
        ]
        for key in required_keys:
            if utils.is_empty(cls.__config[key]):
                utils.error('Error: Config item [%s] is empty' % key)
Example #28
0
    async def download_initial_plugins(self):
        await self.bot._connected.wait()

        for i in self.bot.config.plugins:
            username, repo, name, branch = self.parse_plugin(i)

            try:
                await self.download_plugin_repo(username, repo, branch)
            except DownloadError as exc:
                msg = f"{username}/{repo}@{branch} - {exc}"
                logger.error(error(msg))
            else:
                try:
                    await self.load_plugin(username, repo, name, branch)
                except DownloadError as exc:
                    msg = f"{username}/{repo}@{branch}[{name}] - {exc}"
                    logger.error(error(msg))

        await async_all(
            env() for env in self.bot.extra_events.get("on_plugin_ready", []))

        logger.debug(info("on_plugin_ready called."))
Example #29
0
    async def on_ready(self):
        """Bot startup, sets uptime."""
        await self._connected.wait()
        logger.info(LINE)
        logger.info(info('Client ready.'))
        logger.info(LINE)
        logger.info(info(f'Logged in as: {self.user}'))
        logger.info(info(f'User ID: {self.user.id}'))
        logger.info(info(f'Guild ID: {self.guild.id if self.guild else 0}'))
        logger.info(LINE)

        if not self.guild:
            logger.error(
                error('WARNING - The GUILD_ID '
                      'provided does not exist!'))
        else:
            await self.threads.populate_cache()

        # Wait until config cache is populated with stuff from db
        await self.config.wait_until_ready()

        # closures
        closures = self.config.closures.copy()
        logger.info(
            info(f'There are {len(closures)} thread(s) '
                 'pending to be closed.'))

        for recipient_id, items in closures.items():
            after = (datetime.fromisoformat(items['time']) -
                     datetime.utcnow()).total_seconds()
            if after < 0:
                after = 0
            recipient = self.get_user(int(recipient_id))

            thread = await self.threads.find(recipient=recipient)

            if not thread:
                # If the recipient is gone or channel is deleted
                self.config.closures.pop(str(recipient_id))
                await self.config.update()
                continue

            # TODO: Low priority,
            #  Retrieve messages/replies when bot is down, from history?
            await thread.close(closer=self.get_user(items['closer_id']),
                               after=after,
                               silent=items['silent'],
                               delete_channel=items['delete_channel'],
                               message=items['message'])
        logger.info(LINE)
Example #30
0
    def _load_extensions(self):
        """Adds commands automatically"""
        logger.info(LINE)
        logger.info(info("┌┬┐┌─┐┌┬┐┌┬┐┌─┐┬┬"))
        logger.info(info("││││ │ │││││├─┤││"))
        logger.info(info("┴ ┴└─┘─┴┘┴ ┴┴ ┴┴┴─┘"))
        logger.info(info(f"v{__version__}"))
        logger.info(info("Authors: kyb3r, fourjr, Taaku18"))
        logger.info(LINE)

        for file in os.listdir("cogs"):
            if not file.endswith(".py"):
                continue
            cog = f"cogs.{file[:-3]}"
            logger.info(info(f"Loading {cog}"))
            try:
                self.load_extension(cog)
            except Exception:
                logger.exception(error(f"Failed to load {cog}"))