""" Contains the Gwendolyn class, and runs it when run as script. *Classes* --------- Gwendolyn(discord.ext.commands.Bot) """ import os # Used for loading cogs in Gwendolyn.addCogs import finnhub # Used to add a finhub client to the bot import platform # Used to test if the bot is running on windows, in # order to fix a bug with asyncio import asyncio # used to set change the loop policy if the bot is # running on windows import discord # Used for discord.Intents and discord.Status import discord_slash # Used to initialized SlashCommands object from discord.ext import commands # Used to inherit from commands.bot from pymongo import MongoClient # Used for database management from funcs import Money, StarWars, Games, Other, LookupFuncs from utils import (Options, Credentials, logThis, makeFiles, databaseFuncs, EventHandler, ErrorHandler, longStrings) class Gwendolyn(commands.Bot): """ A multifunctional Discord bot. *Methods* --------- log(messages: Union[str, list], channel: str = "", level: int = 20) stop(ctx: discord_slash.context.SlashContext) defer(ctx: discord_slash.context.SlashContext) """ def __init__(self): """Initialize the bot.""" intents = discord.Intents.default() intents.members = True initParams = { "command_prefix": " ", "case_insensitive": True, "intents": intents, "status": discord.Status.dnd } super().__init__(**initParams) self._addClientsAndOptions() self._addUtilClasses() self._addFunctionContainers() self._addCogs() def _addClientsAndOptions(self): """Add all the client, option and credentials objects.""" self.longStrings = longStrings() self.options = Options() self.credentials = Credentials() finnhubKey = self.credentials.finnhubKey self.finnhubClient = finnhub.Client(api_key=finnhubKey) mongoUser = self.credentials.mongoDBUser mongoPassword = self.credentials.mongoDBPassword mongoLink = f"mongodb+srv://{mongoUser}:{mongoPassword}@gwendolyn" mongoLink += ".qkwfy.mongodb.net/Gwendolyn?retryWrites=true&w=majority" dataBaseClient = MongoClient(mongoLink) if self.options.testing: self.log("Testing mode") self.database = dataBaseClient["Gwendolyn-Test"] else: self.database = dataBaseClient["Gwendolyn"] def _addUtilClasses(self): """Add all the classes used as utility.""" self.databaseFuncs = databaseFuncs(self) self.eventHandler = EventHandler(self) self.errorHandler = ErrorHandler(self) slashParams = { "sync_commands": True, "sync_on_cog_reload": True, "override_type": True } self.slash = discord_slash.SlashCommand(self, **slashParams) def _addFunctionContainers(self): """Add all the function containers used for commands.""" self.starWars = StarWars(self) self.other = Other(self) self.lookupFuncs = LookupFuncs(self) self.games = Games(self) self.money = Money(self) def _addCogs(self): """Load cogs.""" for filename in os.listdir("./cogs"): if filename.endswith(".py"): self.load_extension(f"cogs.{filename[:-3]}") def log(self, messages, channel: str = "", level: int = 20): """Log a message. Described in utils/utilFunctions.py.""" logThis(messages, channel, level) async def stop(self, ctx: discord_slash.context.SlashContext): """ Stop the bot, and stop running games. Only stops the bot if the user in ctx.author is one of the admins given in options.txt. *parameters* ------------ ctx: discord_slash.context.SlashContext The context of the "/stop" slash command. """ if f"#{ctx.author.id}" in self.options.admins: await ctx.send("Pulling git repo and restarting...") await self.change_presence(status=discord.Status.offline) self.databaseFuncs.wipeGames() self.log("Logging out", level=25) await self.close() else: logMessage = f"{ctx.author.display_name} tried to stop me!" self.log(logMessage, str(ctx.channel_id)) await ctx.send(f"I don't think I will, {ctx.author.display_name}") async def defer(self, ctx: discord_slash.context.SlashContext): """Send a "Gwendolyn is thinking" message to the user.""" try: await ctx.defer() except discord_slash.error.AlreadyResponded: self.log("defer failed") if __name__ == "__main__": if platform.system() == "Windows": asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy()) # Creates the required files makeFiles() # Creates the Bot bot = Gwendolyn() try: # Runs the whole shabang bot.run(bot.credentials.token) except Exception: bot.log(bot.longStrings["Can't log in"])