Exemple #1
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"))
Exemple #2
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 - "))
Exemple #3
0
    async def retrieve_emoji(self) -> typing.Tuple[str, str]:

        sent_emoji = self.config.get("sent_emoji", "✅")
        blocked_emoji = self.config.get("blocked_emoji", "🚫")

        if sent_emoji != "disable":
            try:
                sent_emoji = await self.convert_emoji(sent_emoji)
            except commands.BadArgument:
                logger.warning(info("Removed sent emoji (%s)."), sent_emoji)
                del self.config.cache["sent_emoji"]
                await self.config.update()
                sent_emoji = "✅"

        if blocked_emoji != "disable":
            try:
                blocked_emoji = await self.convert_emoji(blocked_emoji)
            except commands.BadArgument:
                logger.warning(info("Removed blocked emoji (%s)."),
                               blocked_emoji)
                del self.config.cache["blocked_emoji"]
                await self.config.update()
                blocked_emoji = "🚫"

        return sent_emoji, blocked_emoji
Exemple #4
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))
Exemple #5
0
    async def retrieve_emoji(self):

        # TODO: use a function to convert emojis

        ctx = SimpleNamespace(bot=self, guild=self.modmail_guild)
        converter = commands.EmojiConverter()

        sent_emoji = self.config.get('sent_emoji', '✅')
        blocked_emoji = self.config.get('blocked_emoji', '🚫')

        if sent_emoji not in UNICODE_EMOJI:
            try:
                sent_emoji = await converter.convert(ctx,
                                                     sent_emoji.strip(':'))
            except commands.BadArgument:
                if sent_emoji != 'disable':
                    logger.warning(
                        info(f'Sent Emoji ({sent_emoji}) '
                             f'is not a valid emoji.'))
                    del self.config.cache['sent_emoji']
                    await self.config.update()

        if blocked_emoji not in UNICODE_EMOJI:
            try:
                blocked_emoji = await converter.convert(
                    ctx, blocked_emoji.strip(':'))
            except commands.BadArgument:
                if blocked_emoji != 'disable':
                    logger.warning(
                        info(f'Blocked emoji ({blocked_emoji}) '
                             'is not a valid emoji.'))
                    del self.config.cache['blocked_emoji']
                    await self.config.update()

        return sent_emoji, blocked_emoji
Exemple #6
0
 def actions(self):
     """
     Executes every action
     """
     at("actions")
     for action in self.timeline.actions():
         info(action, "is execing")
         action.listeners['exec']()
Exemple #7
0
    async def autoupdate_loop(self):
        await self.wait_until_ready()

        if self.config.get("disable_autoupdates"):
            logger.warning(info("Autoupdates disabled."))
            logger.info(LINE)
            return

        if not self.config.get("github_access_token"):
            logger.warning(info("GitHub access token not found."))
            logger.warning(info("Autoupdates disabled."))
            logger.info(LINE)
            return

        logger.info(info("Autoupdate loop started."))

        while not self.is_closed():
            changelog = await Changelog.from_url(self)
            latest = changelog.latest_version

            if parse_version(self.version) < parse_version(latest.version):
                data = await self.api.update_repository()

                embed = discord.Embed(color=discord.Color.green())

                commit_data = data["data"]
                user = data["user"]
                embed.set_author(
                    name=user["username"] + " - Updating Bot",
                    icon_url=user["avatar_url"],
                    url=user["url"],
                )

                embed.set_footer(
                    text=f"Updating Modmail v{self.version} " f"-> v{latest.version}"
                )

                embed.description = latest.description
                for name, value in latest.fields.items():
                    embed.add_field(name=name, value=value)

                if commit_data:
                    message = commit_data["commit"]["message"]
                    html_url = commit_data["html_url"]
                    short_sha = commit_data["sha"][:6]
                    embed.add_field(
                        name="Merge Commit",
                        value=f"[`{short_sha}`]({html_url}) "
                        f"{message} - {user['username']}",
                    )
                    logger.info(info("Bot has been updated."))
                    channel = self.log_channel
                    await channel.send(embed=embed)

            await asyncio.sleep(3600)
Exemple #8
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}'))
Exemple #9
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)
Exemple #10
0
    async def autoupdate_loop(self):
        await self.wait_until_ready()

        if self.config.get('disable_autoupdates'):
            logger.warning(info('Autoupdates disabled.'))
            logger.info(LINE)
            return

        if not self.config.get('github_access_token'):
            logger.warning(info('GitHub access token not found.'))
            logger.warning(info('Autoupdates disabled.'))
            logger.info(LINE)
            return

        logger.info(info('Autoupdate loop started.'))

        while not self.is_closed():
            changelog = await Changelog.from_url(self)
            latest = changelog.latest_version

            if parse_version(self.version) < parse_version(latest.version):
                data = await self.api.update_repository()

                embed = discord.Embed(color=discord.Color.green())

                commit_data = data['data']
                user = data['user']
                embed.set_author(name=user['username'] + ' - Updating Bot',
                                 icon_url=user['avatar_url'],
                                 url=user['url'])

                embed.set_footer(text=f'Updating Modmail v{self.version} '
                                 f'-> v{latest.version}')

                embed.description = latest.description
                for name, value in latest.fields.items():
                    embed.add_field(name=name, value=value)

                if commit_data:
                    message = commit_data['commit']['message']
                    html_url = commit_data["html_url"]
                    short_sha = commit_data['sha'][:6]
                    embed.add_field(name='Merge Commit',
                                    value=f"[`{short_sha}`]({html_url}) "
                                    f"{message} - {user['username']}")
                    logger.info(info('Bot has been updated.'))
                    channel = self.log_channel
                    await channel.send(embed=embed)

            await asyncio.sleep(3600)
Exemple #11
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

            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"],
            )

        logger.info(LINE)
Exemple #12
0
    async def load_plugin(self, username, repo, plugin_name):
        ext = f'plugins.{username}-{repo}.{plugin_name}.{plugin_name}'
        dirname = f'plugins/{username}-{repo}/{plugin_name}'
        if 'requirements.txt' in os.listdir(dirname):
            # Install PIP requirements
            try:
                await self.bot.loop.run_in_executor(
                    None, self._asubprocess_run,
                    f'python3 -m pip install -U -r {dirname}/'
                    'requirements.txt --user -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:
                    raise DownloadError(
                        f'Unable to download requirements: ```\n{error}\n```'
                    ) from exc
            else:
                if not os.path.exists(site.USER_SITE):
                    os.makedirs(site.USER_SITE)

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

        try:
            self.bot.load_extension(ext)
        except commands.ExtensionError as exc:
            raise DownloadError('Invalid plugin') from exc
        else:
            msg = f'Loaded plugins.{username}-{repo}.{plugin_name}'
            logger.info(info(msg))
Exemple #13
0
    async def metadata_loop(self):
        await self.wait_until_ready()
        owner = (await self.application_info()).owner

        while not self.is_closed():
            data = {
                "owner_name": str(owner),
                "owner_id": owner.id,
                "bot_id": self.user.id,
                "bot_name": str(self.user),
                "avatar_url": str(self.user.avatar_url),
                "guild_id": self.guild_id,
                "guild_name": self.guild.name,
                "member_count": len(self.guild.members),
                "uptime":
                (datetime.utcnow() - self.start_time).total_seconds(),
                "latency": f"{self.ws.latency * 1000:.4f}",
                "version": self.version,
                "selfhosted": True,
                "last_updated": str(datetime.utcnow()),
            }

            async with self.session.post("https://api.modmail.tk/metadata",
                                         json=data):
                logger.debug(info("Uploading metadata to Modmail server."))

            await asyncio.sleep(3600)
Exemple #14
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."))
Exemple #15
0
    async def on_connect(self):
        logger.info(LINE)
        if not self.self_hosted:
            logger.info(info('MODE: Using the Modmail API'))
            logger.info(LINE)
            await self.validate_api_token()
            logger.info(LINE)
        else:
            logger.info(info('Mode: Self-hosting logs.'))
            await self.validate_database_connection()
            logger.info(LINE)
        logger.info(info('Connected to gateway.'))

        await self.config.refresh()
        if self.db:
            await self.setup_indexes()
        self._connected.set()
Exemple #16
0
    async def setup_indexes(self):
        """Setup text indexes so we can use the $search operator"""
        coll = self.db.logs
        index_name = 'messages.content_text_messages.author.name_text'

        index_info = await coll.index_information()

        # Backwards compatibility
        old_index = 'messages.content_text'
        if old_index in index_info:
            logger.info(info(f'Dropping old index: {old_index}'))
            await coll.drop_index(old_index)

        if index_name not in index_info:
            logger.info(info('Creating "text" index for logs collection.'))
            logger.info(info('Name: ' + index_name))
            await coll.create_index([('messages.content', 'text'),
                                     ('messages.author.name', 'text')])
Exemple #17
0
    async def on_connect(self):
        logger.info(LINE)
        await self.validate_database_connection()
        logger.info(LINE)
        logger.info(info("Connected to gateway."))

        await self.config.refresh()
        if self.db:
            await self.setup_indexes()
        self._connected.set()
Exemple #18
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.'))
Exemple #19
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_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'))
Exemple #20
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_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"))
Exemple #21
0
    async def convert_emoji(self, name: str) -> str:
        ctx = SimpleNamespace(bot=self, guild=self.modmail_guild)
        converter = commands.EmojiConverter()

        if name not in UNICODE_EMOJI:
            try:
                name = await converter.convert(ctx, name.strip(":"))
            except commands.BadArgument:
                logger.warning(info("%s is not a valid emoji."), name)
                raise
        return name
Exemple #22
0
    async def setup_indexes(self):
        """Setup text indexes so we can use the $search operator"""
        coll = self.db.logs
        index_name = "messages.content_text_messages.author.name_text_key_text"

        index_info = await coll.index_information()

        # Backwards compatibility
        old_index = "messages.content_text_messages.author.name_text"
        if old_index in index_info:
            logger.info(info(f"Dropping old index: {old_index}"))
            await coll.drop_index(old_index)

        if index_name not in index_info:
            logger.info(info('Creating "text" index for logs collection.'))
            logger.info(info("Name: " + index_name))
            await coll.create_index([
                ("messages.content", "text"),
                ("messages.author.name", "text"),
                ("key", "text"),
            ])
Exemple #23
0
 def check_exits(self, dep):
     """
     Checks if any of the exits dependant on dep trigger, and cleans up
     after him (remove, recursivly call deps)
     """
     at("check_exits")
     for exit in self.exits[dep]:
         #Loops through all the exits dependant on this change
         for being in self.being_list:
             if exit.condition(being, self):
                 info(exit.name, "triggered, changes:", exit.changes)
                 exit.effect(being, self)
                 self.remove_being(being)
                 for change in exit.changes:
                     info("checking", change)
                     self.check_exits(change)
                 if not len(self.beings):
                     #If the length has a False value (e.g, 0)
                     self.end = True
                 else:
                     print(len(self.beings), "beings left")
Exemple #24
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))
Exemple #25
0
    async def retrieve_emoji(self) -> typing.Tuple[str, str]:

        sent_emoji = self.config.get('sent_emoji', '✅')
        blocked_emoji = self.config.get('blocked_emoji', '🚫')

        if sent_emoji != 'disable':
            try:
                sent_emoji = await self.convert_emoji(sent_emoji)
            except commands.BadArgument:
                logger.warning(info('Removed sent emoji (%s).'), sent_emoji)
                del self.config.cache['sent_emoji']
                await self.config.update()
                sent_emoji = '✅'

        if blocked_emoji != 'disable':
            try:
                blocked_emoji = await self.convert_emoji(blocked_emoji)
            except commands.BadArgument:
                logger.warning(info('Removed blocked emoji (%s).'), blocked_emoji)
                del self.config.cache['blocked_emoji']
                await self.config.update()
                blocked_emoji = '🚫'

        return sent_emoji, blocked_emoji
Exemple #26
0
    async def load_plugin(self, username, repo, plugin_name):
        ext = f"plugins.{username}-{repo}.{plugin_name}.{plugin_name}"
        dirname = f"plugins/{username}-{repo}/{plugin_name}"

        if "requirements.txt" in os.listdir(dirname):
            # Install PIP requirements
            try:
                if os.name == "nt":  # Windows
                    await self.bot.loop.run_in_executor(
                        None,
                        self._asubprocess_run,
                        f"pip install -r {dirname}/requirements.txt -q -q",
                    )
                else:
                    await self.bot.loop.run_in_executor(
                        None,
                        self._asubprocess_run,
                        f"python3 -m pip install -U -r {dirname}/"
                        "requirements.txt --user -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:
                    raise DownloadError(
                        f"Unable to download requirements: ```\n{error}\n```"
                    ) from exc
            else:
                if not os.path.exists(site.USER_SITE):
                    os.makedirs(site.USER_SITE)

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

        try:
            self.bot.load_extension(ext)
        except commands.ExtensionError as exc:
            # TODO: Add better error handling for plugin load faliure
            import traceback
            traceback.print_exc()
            raise DownloadError("Invalid plugin") from exc
        else:
            msg = f"Loaded plugins.{username}-{repo}.{plugin_name}"
            logger.info(info(msg))
Exemple #27
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.'))
Exemple #28
0
 async def update_perms(self, name, value, add=True):
     if isinstance(name, PermissionLevel):
         permissions = self.config.level_permissions
         name = name.name
     else:
         permissions = self.config.command_permissions
     if name not in permissions:
         if add:
             permissions[name] = [value]
     else:
         if add:
             if value not in permissions[name]:
                 permissions[name].append(value)
         else:
             if value in permissions[name]:
                 permissions[name].remove(value)
     logger.info(
         info(f'Updating permissions for {name}, {value} (add={add}).'))
     await self.config.update()
Exemple #29
0
 async def update_perms(
     self, name: typing.Union[PermissionLevel, str], value: int, add: bool = True
 ) -> None:
     if isinstance(name, PermissionLevel):
         permissions = self.config.level_permissions
         name = name.name
     else:
         permissions = self.config.command_permissions
     if name not in permissions:
         if add:
             permissions[name] = [value]
     else:
         if add:
             if value not in permissions[name]:
                 permissions[name].append(value)
         else:
             if value in permissions[name]:
                 permissions[name].remove(value)
     logger.info(info(f"Updating permissions for {name}, {value} (add={add})."))
     await self.config.update()
Exemple #30
0
    async def login(cls, bot: Bot) -> 'GitHub':
        """
        Logs in to GitHub with configuration variable information.

        Parameters
        ----------
        bot : Bot
            The Modmail bot.

        Returns
        -------
        GitHub
            The newly created `GitHub` object.
        """
        self = cls(bot, bot.config.get('github_access_token'), )
        resp: dict = await self.request('https://api.github.com/user')
        self.username: str = resp['login']
        self.avatar_url: str = resp['avatar_url']
        self.url: str = resp['html_url']
        logger.info(info(f'GitHub logged in to: {self.username}'))
        return self
Exemple #31
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."))
Exemple #32
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}"))