import os import sys from collections import Counter from datetime import datetime from shutil import copyfile import aiohttp import discord from dateutil.relativedelta import relativedelta from discord.ext import commands from firetail.lib import ESI, db from firetail.utils import ExitCodes # Lets check the config file exists before we continue.. if os.getenv("CONFIG") is not None: if not os.path.exists(os.getenv("CONFIG") + "/config.py"): print("Copying example_config.py to " + os.getenv("CONFIG") + "/config.py") copyfile("/firetail/firetail/example_config.py", "/config/config.py") # for some reason os.getcwd() doesn't work inside a container ?? sys.exit(1) if os.getenv("CONFIG") is not None: sys.path.insert(0, os.getenv("CONFIG")) import config else: from firetail import config async def prefix_manager(bot, message): if not message.guild: return commands.when_mentioned_or(bot.default_prefix)(bot, message) prefix = bot.prefixes.get(message.guild.id) or bot.default_prefix return commands.when_mentioned_or(prefix)(bot, message) class Firetail(commands.Bot): def __init__(self, **kwargs): self.default_prefix = config.bot_prefix self.owner = config.bot_master self._shutdown_mode = ExitCodes.CRITICAL self.counter = Counter() self.core_dir = os.path.dirname(os.path.realpath(__file__)) self.config = config self.default_prefix = config.bot_prefix[0] self.prefixes = {} self.bot_users = [] self.repeat_offender = [] self.last_command = None self.token = config.bot_token self.req_perms = discord.Permissions(config.bot_permissions) self.co_owners = config.bot_coowners self.preload_ext = config.preload_extensions kwargs["command_prefix"] = prefix_manager kwargs["pm_help"] = True # kwargs["command_prefix"] = self.db.prefix_manager kwargs["owner_id"] = self.owner super().__init__(**kwargs) self.session = aiohttp.ClientSession(loop=self.loop) self.esi_data = ESI(self.session) self.loop.create_task(self.load_db()) async def load_db(self): await db.create_tables() data = await db.select("SELECT * FROM prefixes") self.prefixes = dict(data) async def send_cmd_help(self, ctx): if ctx.invoked_subcommand: pages = await self.formatter.format_help_for( ctx, ctx.invoked_subcommand) for page in pages: await ctx.author.send(page) else: pages = await self.formatter.format_help_for( ctx, ctx.command) for page in pages: await ctx.author.send(page) async def shutdown(self, *, restart=False): """Shutdown the bot. Safely ends the bot connection while passing the exit code based on if the intention was to restart or close. """ if not restart: self._shutdown_mode = ExitCodes.SHUTDOWN else: self._shutdown_mode = ExitCodes.RESTART await self.logout() @discord.utils.cached_property def invite_url(self): invite_url = discord.utils.oauth_url(self.user.id, permissions=self.req_perms) return invite_url @property def uptime(self): return relativedelta(datetime.utcnow(), self.launch_time) @property def uptime_str(self): uptime = self.uptime year_str, month_str, day_str, hour_str = ('',)*4 if uptime.years >= 1: year_str = "{0}y ".format(uptime.years) if uptime.months >= 1 or year_str: month_str = "{0}m ".format(uptime.months) if uptime.days >= 1 or month_str: d_unit = 'd' if month_str else ' days' day_str = "{0}{1} ".format(uptime.days, d_unit) if uptime.hours >= 1 or day_str: h_unit = ':' if month_str else ' hrs' hour_str = "{0}{1}".format(uptime.hours, h_unit) m_unit = '' if month_str else ' mins' mins = uptime.minutes if month_str else ' {0}'.format(uptime.minutes) secs = '' if day_str else ' {0} secs'.format(uptime.seconds) min_str = "{0}{1}{2}".format(mins, m_unit, secs) uptime_str = ''.join((year_str, month_str, day_str, hour_str, min_str)) return uptime_str @property def command_count(self): return self.counter["processed_commands"] @property def message_count(self): return self.counter["messages_read"] @property def resumed_count(self): return self.counter["sessions_resumed"]