136 lines
5.0 KiB
Python
136 lines
5.0 KiB
Python
"""
|
|
Contains the Gwendolyn class, a subclass of the discord command bot.
|
|
|
|
*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 discord # Used for discord.Intents and discord.Status
|
|
import discord_slash # Used to initialized SlashCommands object
|
|
import git # Used to pull when stopping
|
|
|
|
from discord.ext import commands # Used to inherit from commands.bot
|
|
from pymongo import MongoClient # Used for database management
|
|
from gwendolyn.funcs import Money, StarWars, Games, Other, LookupFuncs
|
|
from gwendolyn.utils import (get_options, get_credentials, log_this,
|
|
DatabaseFuncs, EventHandler, ErrorHandler,
|
|
long_strings)
|
|
|
|
|
|
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)
|
|
"""
|
|
# pylint: disable=too-many-instance-attributes
|
|
|
|
def __init__(self):
|
|
"""Initialize the bot."""
|
|
intents = discord.Intents.default()
|
|
intents.members = True
|
|
initiation_parameters = {
|
|
"command_prefix": " ",
|
|
"case_insensitive": True,
|
|
"intents": intents,
|
|
"status": discord.Status.dnd
|
|
}
|
|
super().__init__(**initiation_parameters)
|
|
|
|
self._add_clients_and_options()
|
|
self._add_util_classes()
|
|
self._add_function_containers()
|
|
self._add_cogs()
|
|
|
|
def _add_clients_and_options(self):
|
|
"""Add all the client, option and credentials objects."""
|
|
self.long_strings = long_strings()
|
|
self.options = get_options()
|
|
self.credentials = get_credentials()
|
|
finnhub_key = self.credentials["finnhub_key"]
|
|
self.finnhub_client = finnhub.Client(api_key=finnhub_key)
|
|
mongo_user = self.credentials["mongo_db_user"]
|
|
mongo_password = self.credentials["mongo_db_password"]
|
|
mongo_url = f"mongodb+srv://{mongo_user}:{mongo_password}@gwendolyn"
|
|
mongo_url += ".qkwfy.mongodb.net/Gwendolyn?retryWrites=true&w=majority"
|
|
database_clint = MongoClient(mongo_url)
|
|
|
|
if self.options["testing"]:
|
|
self.log("Testing mode")
|
|
self.database = database_clint["Gwendolyn-Test"]
|
|
else:
|
|
self.database = database_clint["Gwendolyn"]
|
|
|
|
def _add_util_classes(self):
|
|
"""Add all the classes used as utility."""
|
|
self.database_funcs = DatabaseFuncs(self)
|
|
self.event_handler = EventHandler(self)
|
|
self.error_handler = ErrorHandler(self)
|
|
slash_parameters = {
|
|
"sync_commands": True,
|
|
"sync_on_cog_reload": True,
|
|
"override_type": True
|
|
}
|
|
self.slash = discord_slash.SlashCommand(self, **slash_parameters)
|
|
|
|
def _add_function_containers(self):
|
|
"""Add all the function containers used for commands."""
|
|
self.star_wars = StarWars(self)
|
|
self.other = Other(self)
|
|
self.lookup_funcs = LookupFuncs(self)
|
|
self.games = Games(self)
|
|
self.money = Money(self)
|
|
|
|
def _add_cogs(self):
|
|
"""Load cogs."""
|
|
for filename in os.listdir("./gwendolyn/cogs"):
|
|
if filename.endswith(".py"):
|
|
self.load_extension(f"gwendolyn.cogs.{filename[:-3]}")
|
|
|
|
def log(self, messages, channel: str = "", level: int = 20):
|
|
"""Log a message. Described in utils/util_functions.py."""
|
|
log_this(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.database_funcs.wipe_games()
|
|
if not self.options["testing"]:
|
|
git_client = git.cmd.Git("")
|
|
git_client.pull()
|
|
|
|
self.log("Logging out", level=25)
|
|
await self.close()
|
|
else:
|
|
log_message = f"{ctx.author.display_name} tried to stop me!"
|
|
self.log(log_message, 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")
|