🔀 Merging with master
This commit is contained in:
4
.gitignore
vendored
4
.gitignore
vendored
@ -153,11 +153,11 @@ static
|
|||||||
token.txt
|
token.txt
|
||||||
credentials.txt
|
credentials.txt
|
||||||
options.txt
|
options.txt
|
||||||
resources/starWars/destinyPoints.txt
|
resources/star_wars/destinyPoints.txt
|
||||||
resources/bedreNetflix/
|
resources/bedreNetflix/
|
||||||
resources/games/hilo/
|
resources/games/hilo/
|
||||||
resources/games/blackjackTables/
|
resources/games/blackjackTables/
|
||||||
resources/games/oldImages/
|
resources/games/old_images/
|
||||||
resources/games/connect4Boards/
|
resources/games/connect4Boards/
|
||||||
resources/games/hexBoards/
|
resources/games/hexBoards/
|
||||||
resources/games/hangmanBoards/
|
resources/games/hangmanBoards/
|
||||||
|
137
Gwendolyn.py
137
Gwendolyn.py
@ -1,63 +1,138 @@
|
|||||||
import os, finnhub, platform, asyncio, discord
|
"""
|
||||||
|
Contains the Gwendolyn class, and runs it when run as script.
|
||||||
|
|
||||||
from discord.ext import commands
|
*Classes*
|
||||||
from discord_slash import SlashCommand
|
---------
|
||||||
from pymongo import MongoClient
|
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 funcs import Money, StarWars, Games, Other, LookupFuncs
|
||||||
from utils import Options, Credentials, logThis, makeFiles, databaseFuncs, EventHandler, ErrorHandler
|
from utils import (Options, Credentials, logThis, makeFiles, databaseFuncs,
|
||||||
|
EventHandler, ErrorHandler, longStrings)
|
||||||
|
|
||||||
|
|
||||||
class Gwendolyn(commands.Bot):
|
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):
|
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.options = Options()
|
||||||
self.credentials = Credentials()
|
self.credentials = Credentials()
|
||||||
self.finnhubClient = finnhub.Client(api_key = self.credentials.finnhubKey)
|
finnhubKey = self.credentials.finnhubKey
|
||||||
self.MongoClient = MongoClient(f"mongodb+srv://{self.credentials.mongoDBUser}:{self.credentials.mongoDBPassword}@gwendolyn.qkwfy.mongodb.net/Gwendolyn?retryWrites=true&w=majority")
|
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:
|
if self.options.testing:
|
||||||
self.log("Testing mode")
|
self.log("Testing mode")
|
||||||
self.database = self.MongoClient["Gwendolyn-Test"]
|
self.database = dataBaseClient["Gwendolyn-Test"]
|
||||||
else:
|
else:
|
||||||
self.database = self.MongoClient["Gwendolyn"]
|
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.starWars = StarWars(self)
|
||||||
self.other = Other(self)
|
self.other = Other(self)
|
||||||
self.lookupFuncs = LookupFuncs(self)
|
self.lookupFuncs = LookupFuncs(self)
|
||||||
self.games = Games(self)
|
self.games = Games(self)
|
||||||
self.money = Money(self)
|
self.money = Money(self)
|
||||||
self.databaseFuncs = databaseFuncs(self)
|
|
||||||
self.eventHandler = EventHandler(self)
|
|
||||||
self.errorHandler = ErrorHandler(self)
|
|
||||||
|
|
||||||
intents = discord.Intents.default()
|
def _addCogs(self):
|
||||||
intents.members = True
|
"""Load cogs."""
|
||||||
|
for filename in os.listdir("./cogs"):
|
||||||
|
if filename.endswith(".py"):
|
||||||
|
self.load_extension(f"cogs.{filename[:-3]}")
|
||||||
|
|
||||||
super().__init__(command_prefix=" ", case_insensitive=True, intents = intents, status = discord.Status.dnd)
|
def log(self, messages, channel: str = "", level: int = 20):
|
||||||
|
"""Log a message. Described in utils/utilFunctions.py."""
|
||||||
def log(self, messages, channel : str = "", level : int = 20):
|
|
||||||
logThis(messages, channel, level)
|
logThis(messages, channel, level)
|
||||||
|
|
||||||
async def stop(self, ctx):
|
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:
|
if f"#{ctx.author.id}" in self.options.admins:
|
||||||
await ctx.send("Pulling git repo and restarting...")
|
await ctx.send("Pulling git repo and restarting...")
|
||||||
|
|
||||||
await self.change_presence(status = discord.Status.offline)
|
await self.change_presence(status=discord.Status.offline)
|
||||||
|
|
||||||
self.databaseFuncs.stopServer()
|
self.databaseFuncs.wipeGames()
|
||||||
|
|
||||||
self.log("Logging out", level = 25)
|
self.log("Logging out", level=25)
|
||||||
await self.close()
|
await self.close()
|
||||||
else:
|
else:
|
||||||
self.log(f"{ctx.author.display_name} tried to stop me! (error code 201)",str(ctx.channel_id))
|
logMessage = f"{ctx.author.display_name} tried to stop me!"
|
||||||
await ctx.send(f"I don't think I will, {ctx.author.display_name} (error code 201)")
|
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):
|
async def defer(self, ctx: discord_slash.context.SlashContext):
|
||||||
|
"""Send a "Gwendolyn is thinking" message to the user."""
|
||||||
try:
|
try:
|
||||||
await ctx.defer()
|
await ctx.defer()
|
||||||
except:
|
except discord_slash.error.AlreadyResponded:
|
||||||
self.log("defer failed")
|
self.log("defer failed")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
if platform.system() == "Windows":
|
if platform.system() == "Windows":
|
||||||
asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
|
asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
|
||||||
@ -67,15 +142,9 @@ if __name__ == "__main__":
|
|||||||
|
|
||||||
# Creates the Bot
|
# Creates the Bot
|
||||||
bot = Gwendolyn()
|
bot = Gwendolyn()
|
||||||
bot.slash = SlashCommand(bot, sync_commands=True, sync_on_cog_reload=True, override_type=True)
|
|
||||||
|
|
||||||
#Loads cogs
|
|
||||||
for filename in os.listdir("./cogs"):
|
|
||||||
if filename.endswith(".py"):
|
|
||||||
bot.load_extension(f"cogs.{filename[:-3]}")
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Runs the whole shabang
|
# Runs the whole shabang
|
||||||
bot.run(bot.credentials.token)
|
bot.run(bot.credentials.token)
|
||||||
except:
|
except Exception:
|
||||||
bot.log("Could not log in. Remember to write your bot token in the credentials.txt file")
|
bot.log(bot.longStrings["Can't log in"])
|
||||||
|
@ -1,34 +1,40 @@
|
|||||||
from discord.ext import commands
|
"""Contains the EventCog, which runs code for specific bot events."""
|
||||||
|
from discord.ext import commands # Has the cog class
|
||||||
|
|
||||||
|
|
||||||
class EventCog(commands.Cog):
|
class EventCog(commands.Cog):
|
||||||
|
"""Handles bot events."""
|
||||||
|
|
||||||
def __init__(self, bot):
|
def __init__(self, bot):
|
||||||
|
"""Initialize the bot."""
|
||||||
self.bot = bot
|
self.bot = bot
|
||||||
self.bot.on_error = self.on_error
|
self.bot.on_error = self.on_error
|
||||||
|
|
||||||
# Syncs commands, sets the game, and logs when the bot logs in
|
|
||||||
@commands.Cog.listener()
|
@commands.Cog.listener()
|
||||||
async def on_ready(self):
|
async def on_ready(self):
|
||||||
|
"""Log and set bot status when bot logs in."""
|
||||||
await self.bot.eventHandler.on_ready()
|
await self.bot.eventHandler.on_ready()
|
||||||
|
|
||||||
# Logs when user sends a command
|
|
||||||
@commands.Cog.listener()
|
@commands.Cog.listener()
|
||||||
async def on_slash_command(self, ctx):
|
async def on_slash_command(self, ctx):
|
||||||
|
"""Log when a slash command is run."""
|
||||||
await self.bot.eventHandler.on_slash_command(ctx)
|
await self.bot.eventHandler.on_slash_command(ctx)
|
||||||
|
|
||||||
# Logs if a command experiences an error
|
|
||||||
@commands.Cog.listener()
|
@commands.Cog.listener()
|
||||||
async def on_slash_command_error(self, ctx, error):
|
async def on_slash_command_error(self, ctx, error):
|
||||||
|
"""Log when a slash error occurs."""
|
||||||
await self.bot.errorHandler.on_slash_command_error(ctx, error)
|
await self.bot.errorHandler.on_slash_command_error(ctx, error)
|
||||||
|
|
||||||
# Logs if on error occurs
|
|
||||||
async def on_error(self, method, *args, **kwargs):
|
async def on_error(self, method, *args, **kwargs):
|
||||||
|
"""Log when an error occurs."""
|
||||||
await self.bot.errorHandler.on_error(method)
|
await self.bot.errorHandler.on_error(method)
|
||||||
|
|
||||||
# If someone reacted to a message, checks if it's a reaction it's
|
|
||||||
# Gwendolyn has been waiting for, and then does something
|
|
||||||
@commands.Cog.listener()
|
@commands.Cog.listener()
|
||||||
async def on_reaction_add(self, reaction, user):
|
async def on_reaction_add(self, reaction, user):
|
||||||
|
"""Handle when someone reacts to a message."""
|
||||||
await self.bot.eventHandler.on_reaction_add(reaction, user)
|
await self.bot.eventHandler.on_reaction_add(reaction, user)
|
||||||
|
|
||||||
|
|
||||||
def setup(bot):
|
def setup(bot):
|
||||||
|
"""Add the eventcog to the bot."""
|
||||||
bot.add_cog(EventCog(bot))
|
bot.add_cog(EventCog(bot))
|
||||||
|
112
cogs/GameCogs.py
112
cogs/GameCogs.py
@ -1,155 +1,177 @@
|
|||||||
from discord.ext import commands
|
"""Contains all the cogs that deal with game commands."""
|
||||||
from discord_slash import cog_ext
|
from discord.ext import commands # Has the cog class
|
||||||
|
from discord_slash import cog_ext # Used for slash commands
|
||||||
|
|
||||||
from utils import getParams
|
from utils import getParams # pylint: disable=import-error
|
||||||
|
|
||||||
params = getParams()
|
params = getParams()
|
||||||
|
|
||||||
|
|
||||||
class GamesCog(commands.Cog):
|
class GamesCog(commands.Cog):
|
||||||
def __init__(self,bot):
|
"""Contains miscellaneous game commands."""
|
||||||
"""Runs game stuff."""
|
|
||||||
|
def __init__(self, bot):
|
||||||
|
"""Initialize the cog."""
|
||||||
self.bot = bot
|
self.bot = bot
|
||||||
|
|
||||||
# Checks user balance
|
|
||||||
@cog_ext.cog_slash(**params["balance"])
|
@cog_ext.cog_slash(**params["balance"])
|
||||||
async def balance(self, ctx):
|
async def balance(self, ctx):
|
||||||
|
"""Check user balance."""
|
||||||
await self.bot.money.sendBalance(ctx)
|
await self.bot.money.sendBalance(ctx)
|
||||||
|
|
||||||
# Gives another user an amount of GwendoBucks
|
|
||||||
@cog_ext.cog_slash(**params["give"])
|
@cog_ext.cog_slash(**params["give"])
|
||||||
async def give(self, ctx, user, amount):
|
async def give(self, ctx, user, amount):
|
||||||
|
"""Give another user an amount of GwendoBucks."""
|
||||||
await self.bot.money.giveMoney(ctx, user, amount)
|
await self.bot.money.giveMoney(ctx, user, amount)
|
||||||
|
|
||||||
# Invest GwendoBucks in the stock market
|
|
||||||
@cog_ext.cog_slash(**params["invest"])
|
@cog_ext.cog_slash(**params["invest"])
|
||||||
async def invest(self, ctx, parameters = "check"):
|
async def invest(self, ctx, parameters="check"):
|
||||||
|
"""Invest GwendoBucks in the stock market."""
|
||||||
await self.bot.games.invest.parseInvest(ctx, parameters)
|
await self.bot.games.invest.parseInvest(ctx, parameters)
|
||||||
|
|
||||||
# Runs a game of trivia
|
|
||||||
@cog_ext.cog_slash(**params["trivia"])
|
@cog_ext.cog_slash(**params["trivia"])
|
||||||
async def trivia(self, ctx, answer = ""):
|
async def trivia(self, ctx, answer=""):
|
||||||
|
"""Run a game of trivia."""
|
||||||
await self.bot.games.trivia.triviaParse(ctx, answer)
|
await self.bot.games.trivia.triviaParse(ctx, answer)
|
||||||
|
|
||||||
|
|
||||||
class BlackjackCog(commands.Cog):
|
class BlackjackCog(commands.Cog):
|
||||||
def __init__(self,bot):
|
"""Contains the blackjack commands."""
|
||||||
"""Runs game stuff."""
|
|
||||||
|
def __init__(self, bot):
|
||||||
|
"""Initialize the cog."""
|
||||||
self.bot = bot
|
self.bot = bot
|
||||||
|
|
||||||
# Starts a game of blackjack
|
|
||||||
@cog_ext.cog_subcommand(**params["blackjackStart"])
|
@cog_ext.cog_subcommand(**params["blackjackStart"])
|
||||||
async def blackjackStart(self, ctx):
|
async def blackjackStart(self, ctx):
|
||||||
|
"""Start a game of blackjack."""
|
||||||
await self.bot.games.blackjack.start(ctx)
|
await self.bot.games.blackjack.start(ctx)
|
||||||
|
|
||||||
@cog_ext.cog_subcommand(**params["blackjackBet"])
|
@cog_ext.cog_subcommand(**params["blackjackBet"])
|
||||||
async def blackjackBet(self, ctx, bet):
|
async def blackjackBet(self, ctx, bet):
|
||||||
|
"""Enter the game of blackjack with a bet."""
|
||||||
await self.bot.games.blackjack.playerDrawHand(ctx, bet)
|
await self.bot.games.blackjack.playerDrawHand(ctx, bet)
|
||||||
|
|
||||||
@cog_ext.cog_subcommand(**params["blackjackStand"])
|
@cog_ext.cog_subcommand(**params["blackjackStand"])
|
||||||
async def blackjackStand(self, ctx, hand = ""):
|
async def blackjackStand(self, ctx, hand=""):
|
||||||
|
"""Stand on your hand in blackjack."""
|
||||||
await self.bot.games.blackjack.stand(ctx, hand)
|
await self.bot.games.blackjack.stand(ctx, hand)
|
||||||
|
|
||||||
@cog_ext.cog_subcommand(**params["blackjackHit"])
|
@cog_ext.cog_subcommand(**params["blackjackHit"])
|
||||||
async def blackjackHit(self, ctx, hand = 0):
|
async def blackjackHit(self, ctx, hand=0):
|
||||||
|
"""Hit on your hand in blackjack."""
|
||||||
await self.bot.games.blackjack.hit(ctx, hand)
|
await self.bot.games.blackjack.hit(ctx, hand)
|
||||||
|
|
||||||
@cog_ext.cog_subcommand(**params["blackjackDouble"])
|
@cog_ext.cog_subcommand(**params["blackjackDouble"])
|
||||||
async def blackjackDouble(self, ctx, hand = 0):
|
async def blackjackDouble(self, ctx, hand=0):
|
||||||
|
"""Double in blackjack."""
|
||||||
await self.bot.games.blackjack.double(ctx, hand)
|
await self.bot.games.blackjack.double(ctx, hand)
|
||||||
|
|
||||||
@cog_ext.cog_subcommand(**params["blackjackSplit"])
|
@cog_ext.cog_subcommand(**params["blackjackSplit"])
|
||||||
async def blackjackSplit(self, ctx, hand = 0):
|
async def blackjackSplit(self, ctx, hand=0):
|
||||||
|
"""Split your hand in blackjack."""
|
||||||
await self.bot.games.blackjack.split(ctx, hand)
|
await self.bot.games.blackjack.split(ctx, hand)
|
||||||
|
|
||||||
@cog_ext.cog_subcommand(**params["blackjackHilo"])
|
@cog_ext.cog_subcommand(**params["blackjackHilo"])
|
||||||
async def blackjackHilo(self, ctx):
|
async def blackjackHilo(self, ctx):
|
||||||
|
"""Get the hilo value for the deck in blackjack."""
|
||||||
await self.bot.games.blackjack.hilo(ctx)
|
await self.bot.games.blackjack.hilo(ctx)
|
||||||
|
|
||||||
@cog_ext.cog_subcommand(**params["blackjackShuffle"])
|
@cog_ext.cog_subcommand(**params["blackjackShuffle"])
|
||||||
async def blackjackShuffle(self, ctx):
|
async def blackjackShuffle(self, ctx):
|
||||||
|
"""Shuffle the blackjack game."""
|
||||||
await self.bot.games.blackjack.shuffle(ctx)
|
await self.bot.games.blackjack.shuffle(ctx)
|
||||||
|
|
||||||
@cog_ext.cog_subcommand(**params["blackjackCards"])
|
@cog_ext.cog_subcommand(**params["blackjackCards"])
|
||||||
async def blackjackCards(self, ctx):
|
async def blackjackCards(self, ctx):
|
||||||
|
"""Get the amount of cards left in the blackjack deck."""
|
||||||
await self.bot.games.blackjack.cards(ctx)
|
await self.bot.games.blackjack.cards(ctx)
|
||||||
|
|
||||||
|
|
||||||
class ConnectFourCog(commands.Cog):
|
class ConnectFourCog(commands.Cog):
|
||||||
def __init__(self,bot):
|
"""Contains all the connect four commands."""
|
||||||
"""Runs game stuff."""
|
|
||||||
|
def __init__(self, bot):
|
||||||
|
"""Initialize the cog."""
|
||||||
self.bot = bot
|
self.bot = bot
|
||||||
|
|
||||||
# Start a game of connect four against a user
|
|
||||||
@cog_ext.cog_subcommand(**params["connectFourStartUser"])
|
@cog_ext.cog_subcommand(**params["connectFourStartUser"])
|
||||||
async def connectFourStartUser(self, ctx, user):
|
async def connectFourStartUser(self, ctx, user):
|
||||||
|
"""Start a game of connect four against another user."""
|
||||||
await self.bot.games.connectFour.start(ctx, user)
|
await self.bot.games.connectFour.start(ctx, user)
|
||||||
|
|
||||||
# Start a game of connect four against gwendolyn
|
|
||||||
@cog_ext.cog_subcommand(**params["connectFourStartGwendolyn"])
|
@cog_ext.cog_subcommand(**params["connectFourStartGwendolyn"])
|
||||||
async def connectFourStartGwendolyn(self, ctx, difficulty = 3):
|
async def connectFourStartGwendolyn(self, ctx, difficulty=3):
|
||||||
|
"""Start a game of connect four against Gwendolyn."""
|
||||||
await self.bot.games.connectFour.start(ctx, difficulty)
|
await self.bot.games.connectFour.start(ctx, difficulty)
|
||||||
|
|
||||||
# Stop the current game of connect four
|
|
||||||
@cog_ext.cog_subcommand(**params["connectFourSurrender"])
|
@cog_ext.cog_subcommand(**params["connectFourSurrender"])
|
||||||
async def connectFourSurrender(self, ctx):
|
async def connectFourSurrender(self, ctx):
|
||||||
|
"""Surrender the game of connect four."""
|
||||||
await self.bot.games.connectFour.surrender(ctx)
|
await self.bot.games.connectFour.surrender(ctx)
|
||||||
|
|
||||||
|
|
||||||
class HangmanCog(commands.Cog):
|
class HangmanCog(commands.Cog):
|
||||||
def __init__(self,bot):
|
"""Contains all the hangman commands."""
|
||||||
"""Runs game stuff."""
|
|
||||||
|
def __init__(self, bot):
|
||||||
|
"""Initialize the cog."""
|
||||||
self.bot = bot
|
self.bot = bot
|
||||||
|
|
||||||
# Starts a game of Hangman
|
|
||||||
@cog_ext.cog_subcommand(**params["hangmanStart"])
|
@cog_ext.cog_subcommand(**params["hangmanStart"])
|
||||||
async def hangmanStart(self, ctx):
|
async def hangmanStart(self, ctx):
|
||||||
|
"""Start a game of hangman."""
|
||||||
await self.bot.games.hangman.start(ctx)
|
await self.bot.games.hangman.start(ctx)
|
||||||
|
|
||||||
# Stops a game of Hangman
|
|
||||||
@cog_ext.cog_subcommand(**params["hangmanStop"])
|
@cog_ext.cog_subcommand(**params["hangmanStop"])
|
||||||
async def hangmanStop(self, ctx):
|
async def hangmanStop(self, ctx):
|
||||||
|
"""Stop the current game of hangman."""
|
||||||
await self.bot.games.hangman.stop(ctx)
|
await self.bot.games.hangman.stop(ctx)
|
||||||
|
|
||||||
|
|
||||||
class HexCog(commands.Cog):
|
class HexCog(commands.Cog):
|
||||||
def __init__(self,bot):
|
"""Contains all the hex commands."""
|
||||||
"""Runs game stuff."""
|
|
||||||
self.bot = bot
|
def __init__(self, bot):
|
||||||
|
"""Initialize the cog."""
|
||||||
|
self.bot = bot
|
||||||
|
self.hex = self.bot.games.hex
|
||||||
|
|
||||||
# Start a game of Hex against another user
|
|
||||||
@cog_ext.cog_subcommand(**params["hexStartUser"])
|
@cog_ext.cog_subcommand(**params["hexStartUser"])
|
||||||
async def hexStartUser(self, ctx, user):
|
async def hexStartUser(self, ctx, user):
|
||||||
await self.bot.games.hex.start(ctx, user)
|
"""Start a game of hex against another player."""
|
||||||
|
await self.hex.start(ctx, user)
|
||||||
|
|
||||||
# Start a game of Hex against Gwendolyn
|
|
||||||
@cog_ext.cog_subcommand(**params["hexStartGwendolyn"])
|
@cog_ext.cog_subcommand(**params["hexStartGwendolyn"])
|
||||||
async def hexStartGwendolyn(self, ctx, difficulty = 2):
|
async def hexStartGwendolyn(self, ctx, difficulty=2):
|
||||||
await self.bot.games.hex.start(ctx, difficulty)
|
"""Start a game of hex against Gwendolyn."""
|
||||||
|
await self.hex.start(ctx, difficulty)
|
||||||
|
|
||||||
# Place a piece in the hex game
|
|
||||||
@cog_ext.cog_subcommand(**params["hexPlace"])
|
@cog_ext.cog_subcommand(**params["hexPlace"])
|
||||||
async def hexPlace(self, ctx, coordinates):
|
async def hexPlace(self, ctx, coordinates):
|
||||||
await self.bot.games.hex.placeHex(ctx, coordinates, f"#{ctx.author.id}")
|
"""Place a piece in the hex game."""
|
||||||
|
await self.hex.placeHex(ctx, coordinates, f"#{ctx.author.id}")
|
||||||
|
|
||||||
# Undo your last hex move
|
|
||||||
@cog_ext.cog_subcommand(**params["hexUndo"])
|
@cog_ext.cog_subcommand(**params["hexUndo"])
|
||||||
async def hexUndo(self, ctx):
|
async def hexUndo(self, ctx):
|
||||||
await self.bot.games.hex.undo(ctx)
|
"""Undo your last hex move."""
|
||||||
|
await self.hex.undo(ctx)
|
||||||
|
|
||||||
# Perform a hex swap
|
|
||||||
@cog_ext.cog_subcommand(**params["hexSwap"])
|
@cog_ext.cog_subcommand(**params["hexSwap"])
|
||||||
async def hexSwap(self, ctx):
|
async def hexSwap(self, ctx):
|
||||||
await self.bot.games.hex.swap(ctx)
|
"""Perform a hex swap."""
|
||||||
|
await self.hex.swap(ctx)
|
||||||
|
|
||||||
# Surrender the hex game
|
|
||||||
@cog_ext.cog_subcommand(**params["hexSurrender"])
|
@cog_ext.cog_subcommand(**params["hexSurrender"])
|
||||||
async def hexSurrender(self, ctx):
|
async def hexSurrender(self, ctx):
|
||||||
await self.bot.games.hex.surrender(ctx)
|
"""Surrender the hex game."""
|
||||||
|
await self.hex.surrender(ctx)
|
||||||
|
|
||||||
|
|
||||||
def setup(bot):
|
def setup(bot):
|
||||||
|
"""Add all the cogs to the bot."""
|
||||||
bot.add_cog(GamesCog(bot))
|
bot.add_cog(GamesCog(bot))
|
||||||
bot.add_cog(BlackjackCog(bot))
|
bot.add_cog(BlackjackCog(bot))
|
||||||
bot.add_cog(ConnectFourCog(bot))
|
bot.add_cog(ConnectFourCog(bot))
|
||||||
bot.add_cog(HangmanCog(bot))
|
bot.add_cog(HangmanCog(bot))
|
||||||
bot.add_cog(HexCog(bot))
|
bot.add_cog(HexCog(bot))
|
||||||
|
@ -1,24 +1,32 @@
|
|||||||
from discord.ext import commands
|
"""Contains the LookupCog, which deals with the lookup commands."""
|
||||||
from discord_slash import cog_ext
|
from discord.ext import commands # Has the cog class
|
||||||
|
from discord_slash import cog_ext # Used for slash commands
|
||||||
|
|
||||||
from utils import getParams
|
from utils import getParams # pylint: disable=import-error
|
||||||
|
|
||||||
params = getParams()
|
params = getParams()
|
||||||
|
|
||||||
|
|
||||||
class LookupCog(commands.Cog):
|
class LookupCog(commands.Cog):
|
||||||
|
"""Contains the lookup commands."""
|
||||||
|
|
||||||
def __init__(self, bot):
|
def __init__(self, bot):
|
||||||
"""Runs lookup commands."""
|
"""Initialize the cog."""
|
||||||
self.bot = bot
|
self.bot = bot
|
||||||
|
|
||||||
# Looks up a spell
|
# Looks up a spell
|
||||||
@cog_ext.cog_slash(**params["spell"])
|
@cog_ext.cog_slash(**params["spell"])
|
||||||
async def spell(self, ctx, query):
|
async def spell(self, ctx, query):
|
||||||
|
"""Look up a spell."""
|
||||||
await self.bot.lookupFuncs.spellFunc(ctx, query)
|
await self.bot.lookupFuncs.spellFunc(ctx, query)
|
||||||
|
|
||||||
# Looks up a monster
|
# Looks up a monster
|
||||||
@cog_ext.cog_slash(**params["monster"])
|
@cog_ext.cog_slash(**params["monster"])
|
||||||
async def monster(self, ctx, query):
|
async def monster(self, ctx, query):
|
||||||
|
"""Look up a monster."""
|
||||||
await self.bot.lookupFuncs.monsterFunc(ctx, query)
|
await self.bot.lookupFuncs.monsterFunc(ctx, query)
|
||||||
|
|
||||||
|
|
||||||
def setup(bot):
|
def setup(bot):
|
||||||
bot.add_cog(LookupCog(bot))
|
"""Add the cog to the bot."""
|
||||||
|
bot.add_cog(LookupCog(bot))
|
||||||
|
@ -1,94 +1,99 @@
|
|||||||
import discord, codecs, string, json
|
"""Contains the MiscCog, which deals with miscellaneous commands."""
|
||||||
from discord.ext import commands
|
from discord.ext import commands # Has the cog class
|
||||||
from discord_slash import cog_ext
|
from discord_slash import cog_ext # Used for slash commands
|
||||||
|
|
||||||
from utils import getParams # pylint: disable=import-error
|
from utils import getParams # pylint: disable=import-error
|
||||||
|
|
||||||
params = getParams()
|
params = getParams()
|
||||||
|
|
||||||
|
|
||||||
class MiscCog(commands.Cog):
|
class MiscCog(commands.Cog):
|
||||||
|
"""Contains the miscellaneous commands."""
|
||||||
|
|
||||||
def __init__(self, bot):
|
def __init__(self, bot):
|
||||||
"""Runs misc commands."""
|
"""Initialize the cog."""
|
||||||
self.bot = bot
|
self.bot = bot
|
||||||
self.bot.remove_command("help")
|
self.bot.remove_command("help")
|
||||||
self.generators = bot.other.generators
|
self.generators = bot.other.generators
|
||||||
self.bedreNetflix = bot.other.bedreNetflix
|
self.bedreNetflix = bot.other.bedreNetflix
|
||||||
self.nerdShit = bot.other.nerdShit
|
self.nerdShit = bot.other.nerdShit
|
||||||
|
|
||||||
# Sends the bot's latency
|
|
||||||
@cog_ext.cog_slash(**params["ping"])
|
@cog_ext.cog_slash(**params["ping"])
|
||||||
async def ping(self, ctx):
|
async def ping(self, ctx):
|
||||||
|
"""Send the bot's latency."""
|
||||||
await ctx.send(f"Pong!\nLatency is {round(self.bot.latency * 1000)}ms")
|
await ctx.send(f"Pong!\nLatency is {round(self.bot.latency * 1000)}ms")
|
||||||
|
|
||||||
# Restarts the bot
|
|
||||||
@cog_ext.cog_slash(**params["stop"])
|
@cog_ext.cog_slash(**params["stop"])
|
||||||
async def stop(self, ctx):
|
async def stop(self, ctx):
|
||||||
|
"""Stop the bot."""
|
||||||
await self.bot.stop(ctx)
|
await self.bot.stop(ctx)
|
||||||
|
|
||||||
# Gets help for specific command
|
|
||||||
@cog_ext.cog_slash(**params["help"])
|
@cog_ext.cog_slash(**params["help"])
|
||||||
async def helpCommand(self, ctx, command = ""):
|
async def helpCommand(self, ctx, command=""):
|
||||||
|
"""Get help for commands."""
|
||||||
await self.bot.other.helpFunc(ctx, command)
|
await self.bot.other.helpFunc(ctx, command)
|
||||||
|
|
||||||
# Lets you thank the bot
|
|
||||||
@cog_ext.cog_slash(**params["thank"])
|
@cog_ext.cog_slash(**params["thank"])
|
||||||
async def thank(self, ctx):
|
async def thank(self, ctx):
|
||||||
|
"""Thank the bot."""
|
||||||
await ctx.send("You're welcome :blush:")
|
await ctx.send("You're welcome :blush:")
|
||||||
|
|
||||||
# Sends a friendly message
|
|
||||||
@cog_ext.cog_slash(**params["hello"])
|
@cog_ext.cog_slash(**params["hello"])
|
||||||
async def hello(self, ctx):
|
async def hello(self, ctx):
|
||||||
|
"""Greet the bot."""
|
||||||
await self.bot.other.helloFunc(ctx)
|
await self.bot.other.helloFunc(ctx)
|
||||||
|
|
||||||
# Rolls dice
|
|
||||||
@cog_ext.cog_slash(**params["roll"])
|
@cog_ext.cog_slash(**params["roll"])
|
||||||
async def roll(self, ctx, dice = "1d20"):
|
async def roll(self, ctx, dice="1d20"):
|
||||||
|
"""Roll dice."""
|
||||||
await self.bot.other.rollDice(ctx, dice)
|
await self.bot.other.rollDice(ctx, dice)
|
||||||
|
|
||||||
# Sends a random image
|
|
||||||
@cog_ext.cog_slash(**params["image"])
|
@cog_ext.cog_slash(**params["image"])
|
||||||
async def image(self, ctx):
|
async def image(self, ctx):
|
||||||
|
"""Get a random image from Bing."""
|
||||||
await self.bot.other.imageFunc(ctx)
|
await self.bot.other.imageFunc(ctx)
|
||||||
|
|
||||||
# Finds a random movie
|
|
||||||
@cog_ext.cog_slash(**params["movie"])
|
@cog_ext.cog_slash(**params["movie"])
|
||||||
async def movie(self, ctx):
|
async def movie(self, ctx):
|
||||||
|
"""Get a random movie from the Plex server."""
|
||||||
await self.bot.other.movieFunc(ctx)
|
await self.bot.other.movieFunc(ctx)
|
||||||
|
|
||||||
# Generates a random name
|
|
||||||
@cog_ext.cog_slash(**params["name"])
|
@cog_ext.cog_slash(**params["name"])
|
||||||
async def name(self, ctx):
|
async def name(self, ctx):
|
||||||
|
"""Generate a random name."""
|
||||||
await self.generators.nameGen(ctx)
|
await self.generators.nameGen(ctx)
|
||||||
|
|
||||||
# Generates a random tavern name
|
|
||||||
@cog_ext.cog_slash(**params["tavern"])
|
@cog_ext.cog_slash(**params["tavern"])
|
||||||
async def tavern(self, ctx):
|
async def tavern(self, ctx):
|
||||||
|
"""Generate a random tavern name."""
|
||||||
await self.generators.tavernGen(ctx)
|
await self.generators.tavernGen(ctx)
|
||||||
|
|
||||||
# Finds a page on the Senkulpa wiki
|
|
||||||
@cog_ext.cog_slash(**params["wiki"])
|
@cog_ext.cog_slash(**params["wiki"])
|
||||||
async def wiki(self, ctx, wikiPage = ""):
|
async def wiki(self, ctx, wikiPage=""):
|
||||||
|
"""Get a page on a fandom wiki."""
|
||||||
await self.bot.other.findWikiPage(ctx, wikiPage)
|
await self.bot.other.findWikiPage(ctx, wikiPage)
|
||||||
|
|
||||||
#Searches for movie and adds it to Bedre Netflix
|
|
||||||
@cog_ext.cog_slash(**params["addMovie"])
|
@cog_ext.cog_slash(**params["addMovie"])
|
||||||
async def addMovie(self, ctx, movie):
|
async def addMovie(self, ctx, movie):
|
||||||
|
"""Search for a movie and add it to the Plex server."""
|
||||||
await self.bedreNetflix.requestMovie(ctx, movie)
|
await self.bedreNetflix.requestMovie(ctx, movie)
|
||||||
|
|
||||||
#Searches for show and adds it to Bedre Netflix
|
|
||||||
@cog_ext.cog_slash(**params["addShow"])
|
@cog_ext.cog_slash(**params["addShow"])
|
||||||
async def addShow(self, ctx, show):
|
async def addShow(self, ctx, show):
|
||||||
|
"""Search for a show and add it to the Plex server."""
|
||||||
await self.bedreNetflix.requestShow(ctx, show)
|
await self.bedreNetflix.requestShow(ctx, show)
|
||||||
|
|
||||||
#Returns currently downloading torrents
|
|
||||||
@cog_ext.cog_slash(**params["downloading"])
|
@cog_ext.cog_slash(**params["downloading"])
|
||||||
async def downloading(self, ctx, parameters = "-d"):
|
async def downloading(self, ctx, parameters="-d"):
|
||||||
|
"""Get the current downloading torrents."""
|
||||||
await self.bedreNetflix.downloading(ctx, parameters)
|
await self.bedreNetflix.downloading(ctx, parameters)
|
||||||
|
|
||||||
#Looks up on Wolfram Alpha
|
|
||||||
@cog_ext.cog_slash(**params["wolf"])
|
@cog_ext.cog_slash(**params["wolf"])
|
||||||
async def wolf(self, ctx, query):
|
async def wolf(self, ctx, query):
|
||||||
|
"""Perform a search on Wolfram Alpha."""
|
||||||
await self.nerdShit.wolfSearch(ctx, query)
|
await self.nerdShit.wolfSearch(ctx, query)
|
||||||
|
|
||||||
|
|
||||||
def setup(bot):
|
def setup(bot):
|
||||||
|
"""Add the cog to the bot."""
|
||||||
bot.add_cog(MiscCog(bot))
|
bot.add_cog(MiscCog(bot))
|
||||||
|
@ -1,37 +1,40 @@
|
|||||||
import discord, string, json
|
"""Contains the StarWarsCog, which deals with Star Wars commands."""
|
||||||
from discord.ext import commands
|
from discord.ext import commands
|
||||||
from discord_slash import cog_ext
|
from discord_slash import cog_ext
|
||||||
|
|
||||||
from utils import getParams
|
from utils import getParams # pylint: disable=import-error
|
||||||
|
|
||||||
params = getParams()
|
params = getParams()
|
||||||
|
|
||||||
class starWarsCog(commands.Cog):
|
|
||||||
|
class StarWarsCog(commands.Cog):
|
||||||
|
"""Contains the Star Wars commands."""
|
||||||
|
|
||||||
def __init__(self, bot):
|
def __init__(self, bot):
|
||||||
"""Runs star wars commands."""
|
"""Initialize the cog."""
|
||||||
self.bot = bot
|
self.bot = bot
|
||||||
|
|
||||||
# Rolls star wars dice
|
|
||||||
@cog_ext.cog_slash(**params["starWarsRoll"])
|
@cog_ext.cog_slash(**params["starWarsRoll"])
|
||||||
async def starWarsRoll(self, ctx, dice = ""):
|
async def starWarsRoll(self, ctx, dice=""):
|
||||||
|
"""Roll Star Wars dice."""
|
||||||
await self.bot.starWars.roll.parseRoll(ctx, dice)
|
await self.bot.starWars.roll.parseRoll(ctx, dice)
|
||||||
|
|
||||||
# Controls destiny points
|
|
||||||
@cog_ext.cog_slash(**params["starWarsDestiny"])
|
@cog_ext.cog_slash(**params["starWarsDestiny"])
|
||||||
async def starWarsDestiny(self, ctx, parameters = ""):
|
async def starWarsDestiny(self, ctx, parameters=""):
|
||||||
|
"""Control Star Wars destiny points."""
|
||||||
await self.bot.starWars.destiny.parseDestiny(ctx, parameters)
|
await self.bot.starWars.destiny.parseDestiny(ctx, parameters)
|
||||||
|
|
||||||
# Rolls for critical injuries
|
|
||||||
@cog_ext.cog_slash(**params["starWarsCrit"])
|
@cog_ext.cog_slash(**params["starWarsCrit"])
|
||||||
async def starWarsCrit(self, ctx, severity : int = 0):
|
async def starWarsCrit(self, ctx, severity: int = 0):
|
||||||
|
"""Roll for critical injuries."""
|
||||||
await self.bot.starWars.roll.critRoll(ctx, severity)
|
await self.bot.starWars.roll.critRoll(ctx, severity)
|
||||||
|
|
||||||
# Accesses and changes character sheet data with the parseChar function
|
|
||||||
# from funcs/starWarsFuncs/starWarsCharacter.py
|
|
||||||
@cog_ext.cog_slash(**params["starWarsCharacter"])
|
@cog_ext.cog_slash(**params["starWarsCharacter"])
|
||||||
async def starWarsCharacter(self, ctx, parameters = ""):
|
async def starWarsCharacter(self, ctx, parameters=""):
|
||||||
|
"""Access and change Star Wars character sheet data."""
|
||||||
await self.bot.starWars.character.parseChar(ctx, parameters)
|
await self.bot.starWars.character.parseChar(ctx, parameters)
|
||||||
|
|
||||||
|
|
||||||
def setup(bot):
|
def setup(bot):
|
||||||
bot.add_cog(starWarsCog(bot))
|
"""Add the cog to the bot."""
|
||||||
|
bot.add_cog(StarWarsCog(bot))
|
||||||
|
4
resources/longStrings.json
Normal file
4
resources/longStrings.json
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"missing parameters" : "Missing command parameters. Try using `!help [command]` to find out how to use the command.",
|
||||||
|
"Can't log in": "Could not log in. Remember to write your bot token in the credentials.txt file"
|
||||||
|
}
|
@ -1,7 +1,10 @@
|
|||||||
"""A collections of utilities used by Gwendolyn and her functions"""
|
"""A collections of utilities used by Gwendolyn and her functions."""
|
||||||
|
|
||||||
__all__ = ["Options", "Credentials", "databaseFuncs", "EventHandler", "ErrorHandler", "getParams", "logThis", "cap", "makeFiles", "replaceMultiple", "emojiToCommand"]
|
__all__ = ["Options", "Credentials", "databaseFuncs", "EventHandler",
|
||||||
|
"ErrorHandler", "getParams", "logThis", "cap", "makeFiles",
|
||||||
|
"replaceMultiple", "emojiToCommand"]
|
||||||
|
|
||||||
from .helperClasses import Options, Credentials, databaseFuncs
|
from .helperClasses import Options, Credentials, databaseFuncs
|
||||||
from .eventHandlers import EventHandler, ErrorHandler
|
from .eventHandlers import EventHandler, ErrorHandler
|
||||||
from .utilFunctions import getParams, logThis, cap, makeFiles, replaceMultiple, emojiToCommand
|
from .utilFunctions import (getParams, logThis, cap, makeFiles,
|
||||||
|
replaceMultiple, emojiToCommand, longStrings)
|
||||||
|
@ -1,13 +1,52 @@
|
|||||||
import discord, traceback, discord_slash, sys
|
"""
|
||||||
from discord.ext import commands
|
Classes used to handle bot events and errors.
|
||||||
|
|
||||||
|
*Classes*
|
||||||
|
---------
|
||||||
|
EventHandler
|
||||||
|
ErrorHandler
|
||||||
|
"""
|
||||||
|
import discord # Used to init discord.Game and discord.Status, as well
|
||||||
|
# as compare errors to discord errors and as typehints
|
||||||
|
import traceback # Used to get the traceback of errors
|
||||||
|
import sys # Used to get traceback when the specific error is not
|
||||||
|
# available
|
||||||
|
from discord.ext import commands # Used to compare errors with command
|
||||||
|
# errors
|
||||||
|
|
||||||
|
from discord_slash.context import SlashContext
|
||||||
|
from utils.utilFunctions import emojiToCommand
|
||||||
|
|
||||||
from .utilFunctions import emojiToCommand
|
|
||||||
|
|
||||||
class EventHandler():
|
class EventHandler():
|
||||||
|
"""
|
||||||
|
Handles bot events.
|
||||||
|
|
||||||
|
*Methods*
|
||||||
|
---------
|
||||||
|
on_ready()
|
||||||
|
on_slash_command(ctx: discord_slash.context.SlashContext)
|
||||||
|
on_reaction_add(ctx: discord_slash.context.SlashContext)
|
||||||
|
"""
|
||||||
|
|
||||||
def __init__(self, bot):
|
def __init__(self, bot):
|
||||||
|
"""Initialize the handler."""
|
||||||
self.bot = bot
|
self.bot = bot
|
||||||
|
|
||||||
async def on_slash_command(self, ctx):
|
async def on_ready(self):
|
||||||
|
"""Log and sets status when it logs in."""
|
||||||
|
await self.bot.databaseFuncs.syncCommands()
|
||||||
|
name = self.bot.user.name
|
||||||
|
userid = str(self.bot.user.id)
|
||||||
|
loggedInMessage = f"Logged in as {name}, {userid}"
|
||||||
|
self.bot.log(loggedInMessage, level=25)
|
||||||
|
game = discord.Game("Use /help for commands")
|
||||||
|
|
||||||
|
onlineStatus = discord.Status.online
|
||||||
|
await self.bot.change_presence(activity=game, status=onlineStatus)
|
||||||
|
|
||||||
|
async def on_slash_command(self, ctx: SlashContext):
|
||||||
|
"""Log when a slash command is given."""
|
||||||
if ctx.subcommand_name is not None:
|
if ctx.subcommand_name is not None:
|
||||||
subcommand = f" {ctx.subcommand_name} "
|
subcommand = f" {ctx.subcommand_name} "
|
||||||
else:
|
else:
|
||||||
@ -21,100 +60,117 @@ class EventHandler():
|
|||||||
args = " ".join([str(i) for i in ctx.args])
|
args = " ".join([str(i) for i in ctx.args])
|
||||||
fullCommand = f"/{ctx.command}{subcommand}{subcommandGroup}{args}"
|
fullCommand = f"/{ctx.command}{subcommand}{subcommandGroup}{args}"
|
||||||
logMessage = f"{ctx.author.display_name} ran {fullCommand}"
|
logMessage = f"{ctx.author.display_name} ran {fullCommand}"
|
||||||
self.bot.log(logMessage, str(ctx.channel_id), level = 25)
|
self.bot.log(logMessage, str(ctx.channel_id), level=25)
|
||||||
|
|
||||||
async def on_ready(self):
|
async def on_reaction_add(self, reaction: discord.Reaction,
|
||||||
await self.bot.databaseFuncs.syncCommands()
|
user: discord.User):
|
||||||
self.bot.log("Logged in as "+self.bot.user.name+", "+str(self.bot.user.id), level = 25)
|
"""Take action if the reaction is on a command message."""
|
||||||
game = discord.Game("Use /help for commands")
|
if not user.bot:
|
||||||
await self.bot.change_presence(activity=game, status = discord.Status.online)
|
tests = self.bot.databaseFuncs
|
||||||
|
|
||||||
async def on_reaction_add(self, reaction : discord.Reaction, user):
|
|
||||||
if user.bot == False:
|
|
||||||
message = reaction.message
|
message = reaction.message
|
||||||
channel = message.channel
|
channel = message.channel
|
||||||
self.bot.log(f"{user.display_name} reacted to a message",str(channel.id))
|
reactedMessage = f"{user.display_name} reacted to a message"
|
||||||
try:
|
self.bot.log(reactedMessage, str(channel.id))
|
||||||
connectFourTheirTurn, piece = self.bot.databaseFuncs.connectFourReactionTest(channel,message,"#"+str(user.id))
|
plexData = tests.bedreNetflixReactionTest(message)
|
||||||
except:
|
# plexData is a list containing 3 elements: whether it was
|
||||||
connectFourTheirTurn = False
|
# the addshow/addmovie command message the reaction was to
|
||||||
|
# (bool), whether it's a movie (bool) (if false, it's a
|
||||||
|
# show), and the imdb ids/names for the for the movies or
|
||||||
|
# shows listed in the message (list).
|
||||||
|
|
||||||
bedreNetflixMessage, addMovie, imdbIds = self.bot.databaseFuncs.bedreNetflixReactionTest(channel, message)
|
reactionTestParams = [message, f"#{str(user.id)}"]
|
||||||
|
|
||||||
if connectFourTheirTurn:
|
if tests.connectFourReactionTest(*reactionTestParams):
|
||||||
column = emojiToCommand(reaction.emoji)
|
column = emojiToCommand(reaction.emoji)
|
||||||
await self.bot.games.connectFour.placePiece(message, f"#{user.id}", column-1)
|
params = [message, f"#{user.id}", column-1]
|
||||||
elif bedreNetflixMessage and addMovie:
|
await self.bot.games.connectFour.placePiece(*params)
|
||||||
moviePick = emojiToCommand(reaction.emoji)
|
|
||||||
if moviePick == "none":
|
|
||||||
imdbID = None
|
|
||||||
else:
|
|
||||||
imdbID = imdbIds[moviePick-1]
|
|
||||||
|
|
||||||
if isinstance(channel, discord.DMChannel):
|
if plexData[0]:
|
||||||
await message.delete()
|
plexFuncs = self.bot.other.bedreNetflix
|
||||||
await self.bot.other.bedreNetflix.addMovie(message, imdbID, False)
|
if plexData[1]:
|
||||||
else:
|
moviePick = emojiToCommand(reaction.emoji)
|
||||||
await message.clear_reactions()
|
if moviePick == "none":
|
||||||
await self.bot.other.bedreNetflix.addMovie(message, imdbID)
|
imdbID = None
|
||||||
elif bedreNetflixMessage and not addMovie:
|
else:
|
||||||
showPick = emojiToCommand(reaction.emoji)
|
imdbID = plexData[2][moviePick-1]
|
||||||
if showPick == "none":
|
|
||||||
imdbName = None
|
|
||||||
else:
|
|
||||||
imdbName = imdbIds[showPick-1]
|
|
||||||
|
|
||||||
if isinstance(channel, discord.DMChannel):
|
if isinstance(channel, discord.DMChannel):
|
||||||
await message.delete()
|
await message.delete()
|
||||||
await self.bot.other.bedreNetflix.addShow(message, imdbName, False)
|
await plexFuncs.addMovie(message, imdbID, False)
|
||||||
|
else:
|
||||||
|
await message.clear_reactions()
|
||||||
|
await plexFuncs.addMovie(message, imdbID)
|
||||||
else:
|
else:
|
||||||
await message.clear_reactions()
|
showPick = emojiToCommand(reaction.emoji)
|
||||||
await self.bot.other.bedreNetflix.addShow(message, imdbName)
|
if showPick == "none":
|
||||||
|
imdbName = None
|
||||||
|
else:
|
||||||
|
imdbName = plexData[2][showPick-1]
|
||||||
|
|
||||||
elif self.bot.databaseFuncs.hangmanReactionTest(channel, message, f"#{user.id}"):
|
if isinstance(channel, discord.DMChannel):
|
||||||
|
await message.delete()
|
||||||
|
await plexFuncs.addShow(message, imdbName, False)
|
||||||
|
else:
|
||||||
|
await message.clear_reactions()
|
||||||
|
await plexFuncs.addShow(message, imdbName)
|
||||||
|
|
||||||
|
elif tests.hangmanReactionTest(*reactionTestParams):
|
||||||
self.bot.log("They reacted to the hangman message")
|
self.bot.log("They reacted to the hangman message")
|
||||||
if ord(reaction.emoji) in range(127462,127488):
|
if ord(reaction.emoji) in range(127462, 127488):
|
||||||
|
# The range is letter-emojis
|
||||||
guess = chr(ord(reaction.emoji)-127397)
|
guess = chr(ord(reaction.emoji)-127397)
|
||||||
await self.bot.games.hangman.guess(message, f"#{user.id}", guess)
|
# Converts emoji to letter
|
||||||
|
params = [message, f"#{user.id}", guess]
|
||||||
|
await self.bot.games.hangman.guess(*params)
|
||||||
else:
|
else:
|
||||||
self.bot.log("Bot they didn't react with a valid guess")
|
self.bot.log("Bot they didn't react with a valid guess")
|
||||||
|
|
||||||
|
|
||||||
class ErrorHandler():
|
class ErrorHandler():
|
||||||
|
"""
|
||||||
|
Handles errors.
|
||||||
|
|
||||||
|
*Methods*
|
||||||
|
---------
|
||||||
|
on_slash_command_error(ctx: discord_slash.context.SlashContext,
|
||||||
|
error: Exception)
|
||||||
|
on_error(method: str)
|
||||||
|
"""
|
||||||
|
|
||||||
def __init__(self, bot):
|
def __init__(self, bot):
|
||||||
|
"""Initialize the handler."""
|
||||||
self.bot = bot
|
self.bot = bot
|
||||||
|
|
||||||
async def on_slash_command_error(self, ctx, error):
|
async def on_slash_command_error(self, ctx: SlashContext,
|
||||||
|
error: Exception):
|
||||||
|
"""Log when there's a slash command."""
|
||||||
if isinstance(error, commands.CommandNotFound):
|
if isinstance(error, commands.CommandNotFound):
|
||||||
await ctx.send("That's not a command (error code 001)")
|
await ctx.send("That's not a command")
|
||||||
elif isinstance(error, discord.errors.NotFound):
|
elif isinstance(error, discord.errors.NotFound):
|
||||||
self.bot.log("Deleted message before I could add all reactions")
|
self.bot.log("Deleted message before I could add all reactions")
|
||||||
elif isinstance(error, commands.errors.MissingRequiredArgument):
|
elif isinstance(error, commands.errors.MissingRequiredArgument):
|
||||||
self.bot.log(f"{error}",str(ctx.channel_id))
|
self.bot.log(f"{error}", str(ctx.channel_id))
|
||||||
await ctx.send("Missing command parameters (error code 002). Try using `!help [command]` to find out how to use the command.")
|
await ctx.send(self.bot.longStrings["missing parameters"])
|
||||||
else:
|
else:
|
||||||
exception = traceback.format_exception(type(error), error, error.__traceback__)
|
params = [type(error), error, error.__traceback__]
|
||||||
stopAt = "\nThe above exception was the direct cause of the following exception:\n\n"
|
exception = traceback.format_exception(*params)
|
||||||
if stopAt in exception:
|
|
||||||
index = exception.index(stopAt)
|
|
||||||
exception = exception[:index]
|
|
||||||
|
|
||||||
exceptionString = "".join(exception)
|
exceptionString = "".join(exception)
|
||||||
self.bot.log([f"exception in /{ctx.name}", f"{exceptionString}"],str(ctx.channel_id), 40)
|
logMessages = [f"exception in /{ctx.name}", f"{exceptionString}"]
|
||||||
|
self.bot.log(logMessages, str(ctx.channel_id), 40)
|
||||||
if isinstance(error, discord.errors.NotFound):
|
if isinstance(error, discord.errors.NotFound):
|
||||||
self.bot.log("Context is non-existant", level = 40)
|
self.bot.log("Context is non-existant", level=40)
|
||||||
else:
|
else:
|
||||||
await ctx.send("Something went wrong (error code 000)")
|
await ctx.send("Something went wrong (error code 000)")
|
||||||
|
|
||||||
async def on_error(self, method):
|
async def on_error(self, method: str):
|
||||||
|
"""Log when there's an error."""
|
||||||
errorType = sys.exc_info()[0]
|
errorType = sys.exc_info()[0]
|
||||||
if errorType == discord.errors.NotFound:
|
if errorType == discord.errors.NotFound:
|
||||||
self.bot.log("Deleted message before I could add all reactions")
|
self.bot.log("Deleted message before I could add all reactions")
|
||||||
else:
|
else:
|
||||||
exception = traceback.format_exc()
|
exception = traceback.format_exc()
|
||||||
stopAt = "\nThe above exception was the direct cause of the following exception:\n\n"
|
|
||||||
if stopAt in exception:
|
|
||||||
index = exception.index(stopAt)
|
|
||||||
exception = exception[:index]
|
|
||||||
|
|
||||||
exceptionString = "".join(exception)
|
exceptionString = "".join(exception)
|
||||||
self.bot.log([f"exception in {method}", f"{exceptionString}"], level = 40)
|
logMessages = [f"exception in {method}", f"{exceptionString}"]
|
||||||
|
self.bot.log(logMessages, level=40)
|
||||||
|
@ -1,6 +1,44 @@
|
|||||||
import re, git, os, json, time
|
"""
|
||||||
|
Contains classes used for utilities.
|
||||||
|
|
||||||
def sanitize(data : str, options : bool = False):
|
*Functions*
|
||||||
|
-----------
|
||||||
|
Sanitize(data: str, lowerCaseValue: bool = false) -> dict
|
||||||
|
|
||||||
|
*Classes*
|
||||||
|
---------
|
||||||
|
Options()
|
||||||
|
Credentials()
|
||||||
|
DatabaseFuncs()
|
||||||
|
"""
|
||||||
|
import re # Used in getID
|
||||||
|
import git # Used to pull when stopping
|
||||||
|
import os # Used to test if files exist
|
||||||
|
import json # Used to read the data about addmovie/addshow
|
||||||
|
import time # Used to test how long it's been since commands were synced
|
||||||
|
import discord # Used for type hints
|
||||||
|
|
||||||
|
|
||||||
|
def sanitize(data: str, lowerCaseValue: bool = False):
|
||||||
|
"""
|
||||||
|
Sanitize and create a dictionary from a string.
|
||||||
|
|
||||||
|
Each element is created from a line with a : in it. The key is left
|
||||||
|
of the :, the value is right of it.
|
||||||
|
|
||||||
|
*Parameters*
|
||||||
|
------------
|
||||||
|
data: str
|
||||||
|
The string to create a dict from.
|
||||||
|
lowerCaseValue: bool = False
|
||||||
|
Whether the value of each element should be lowercase.
|
||||||
|
|
||||||
|
*Returns*
|
||||||
|
---------
|
||||||
|
dct: dict
|
||||||
|
The sanitized dictionary of elements.
|
||||||
|
|
||||||
|
"""
|
||||||
data = data.splitlines()
|
data = data.splitlines()
|
||||||
dct = {}
|
dct = {}
|
||||||
for line in data:
|
for line in data:
|
||||||
@ -8,7 +46,7 @@ def sanitize(data : str, options : bool = False):
|
|||||||
lineValues = line.split(":")
|
lineValues = line.split(":")
|
||||||
lineValues[0] = lineValues[0].lower()
|
lineValues[0] = lineValues[0].lower()
|
||||||
lineValues[1] = lineValues[1].replace(" ", "")
|
lineValues[1] = lineValues[1].replace(" ", "")
|
||||||
if options:
|
if lowerCaseValue:
|
||||||
lineValues[1] = lineValues[1].lower()
|
lineValues[1] = lineValues[1].lower()
|
||||||
|
|
||||||
if lineValues[0] in ["testing guild ids", "admins"]:
|
if lineValues[0] in ["testing guild ids", "admins"]:
|
||||||
@ -23,18 +61,26 @@ def sanitize(data : str, options : bool = False):
|
|||||||
|
|
||||||
return dct
|
return dct
|
||||||
|
|
||||||
|
|
||||||
class Options():
|
class Options():
|
||||||
|
"""Contains the options for the bot."""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
with open("options.txt","r") as f:
|
"""Initialize the options."""
|
||||||
|
with open("options.txt", "r") as f:
|
||||||
data = sanitize(f.read(), True)
|
data = sanitize(f.read(), True)
|
||||||
|
|
||||||
self.testing = data["testing"]
|
self.testing = data["testing"]
|
||||||
self.guildIds = data["testing guild ids"]
|
self.guildIds = data["testing guild ids"]
|
||||||
self.admins = data["admins"]
|
self.admins = data["admins"]
|
||||||
|
|
||||||
|
|
||||||
class Credentials():
|
class Credentials():
|
||||||
|
"""Contains the credentials for the bot and apis."""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
with open("credentials.txt","r") as f:
|
"""Initialize the credentials."""
|
||||||
|
with open("credentials.txt", "r") as f:
|
||||||
data = sanitize(f.read())
|
data = sanitize(f.read())
|
||||||
|
|
||||||
self.token = data["bot token"]
|
self.token = data["bot token"]
|
||||||
@ -46,34 +92,99 @@ class Credentials():
|
|||||||
self.radarrKey = data["radarr api key"]
|
self.radarrKey = data["radarr api key"]
|
||||||
self.sonarrKey = data["sonarr api key"]
|
self.sonarrKey = data["sonarr api key"]
|
||||||
|
|
||||||
|
|
||||||
class databaseFuncs():
|
class databaseFuncs():
|
||||||
|
"""
|
||||||
|
Manages database functions.
|
||||||
|
|
||||||
|
*Methods*
|
||||||
|
---------
|
||||||
|
getName(userID: str) -> str
|
||||||
|
getID(userName: str) -> str
|
||||||
|
deleteGame(gameType: str, channel: str)
|
||||||
|
wipeGames()
|
||||||
|
connectFourReactionTest(message: discord.Message,
|
||||||
|
user: discord.User) -> bool
|
||||||
|
hangmanReactionTest(message: discord.Message,
|
||||||
|
user: discord.User) -> bool
|
||||||
|
BedreNetflixReactionTest(message: discord.Message,
|
||||||
|
user: discord.User) -> bool, bool,
|
||||||
|
list
|
||||||
|
syncCommands()
|
||||||
|
"""
|
||||||
|
|
||||||
def __init__(self, bot):
|
def __init__(self, bot):
|
||||||
|
"""Initialize the class."""
|
||||||
self.bot = bot
|
self.bot = bot
|
||||||
|
|
||||||
def getName(self, userID):
|
def getName(self, userID: str):
|
||||||
user = self.bot.database["users"].find_one({"_id":userID})
|
"""
|
||||||
|
Get the name of a user you have the # id of.
|
||||||
|
|
||||||
|
*Parameters:
|
||||||
|
------------
|
||||||
|
userID: str
|
||||||
|
The id of the user you want the name of. The format is
|
||||||
|
"#" + str(discord.User.id)
|
||||||
|
|
||||||
|
*Returns*
|
||||||
|
---------
|
||||||
|
userName: str
|
||||||
|
The name of the user. If the user couldn't be found,
|
||||||
|
returns the userID.
|
||||||
|
"""
|
||||||
|
user = self.bot.database["users"].find_one({"_id": userID})
|
||||||
|
|
||||||
if userID == f"#{self.bot.user.id}":
|
if userID == f"#{self.bot.user.id}":
|
||||||
return "Gwendolyn"
|
return "Gwendolyn"
|
||||||
elif user != None:
|
elif user is not None:
|
||||||
return user["user name"]
|
return user["user name"]
|
||||||
else:
|
else:
|
||||||
self.bot.log(f"Couldn't find user {userID}")
|
self.bot.log(f"Couldn't find user {userID}")
|
||||||
return userID
|
return userID
|
||||||
|
|
||||||
def getID(self,userName):
|
def getID(self, userName: str):
|
||||||
user = self.bot.database["users"].find_one({"user name":re.compile(userName, re.IGNORECASE)})
|
"""
|
||||||
|
Get the id of a user you have the username of.
|
||||||
|
|
||||||
if user != None:
|
*Parameters:
|
||||||
|
------------
|
||||||
|
userName: str
|
||||||
|
The name of the user you want the id of.
|
||||||
|
|
||||||
|
*Returns*
|
||||||
|
---------
|
||||||
|
userID: str
|
||||||
|
The id of the user in the format "#" +
|
||||||
|
str(discord.User.id). If the user couldn't be found,
|
||||||
|
returns the userName.
|
||||||
|
"""
|
||||||
|
userSearch = {"user name": re.compile(userName, re.IGNORECASE)}
|
||||||
|
user = self.bot.database["users"].find_one(userSearch)
|
||||||
|
|
||||||
|
if user is not None:
|
||||||
return user["_id"]
|
return user["_id"]
|
||||||
else:
|
else:
|
||||||
self.bot.log("Couldn't find user "+userName)
|
self.bot.log("Couldn't find user "+userName)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def deleteGame(self, gameType, channel):
|
def deleteGame(self, gameType: str, channel: str):
|
||||||
self.bot.database[gameType].delete_one({"_id":channel})
|
"""
|
||||||
|
Remove a game from the database.
|
||||||
|
|
||||||
def stopServer(self):
|
*Parameters*
|
||||||
|
------------
|
||||||
|
gameType: str
|
||||||
|
The name of the collection the game is in, like
|
||||||
|
"hangman games", "blackjack games" etc.
|
||||||
|
channel: str
|
||||||
|
The channel id of the channel the game is on as a
|
||||||
|
string.
|
||||||
|
"""
|
||||||
|
self.bot.database[gameType].delete_one({"_id": channel})
|
||||||
|
|
||||||
|
def wipeGames(self):
|
||||||
|
"""Delete all running games and pull from git."""
|
||||||
self.bot.database["trivia questions"].delete_many({})
|
self.bot.database["trivia questions"].delete_many({})
|
||||||
self.bot.database["blackjack games"].delete_many({})
|
self.bot.database["blackjack games"].delete_many({})
|
||||||
self.bot.database["connect 4 games"].delete_many({})
|
self.bot.database["connect 4 games"].delete_many({})
|
||||||
@ -84,35 +195,80 @@ class databaseFuncs():
|
|||||||
g = git.cmd.Git("")
|
g = git.cmd.Git("")
|
||||||
g.pull()
|
g.pull()
|
||||||
|
|
||||||
def connectFourReactionTest(self,channel,message,user):
|
def connectFourReactionTest(self, message: discord.Message,
|
||||||
game = self.bot.database["connect 4 games"].find_one({"_id":str(channel.id)})
|
user: discord.User):
|
||||||
|
"""
|
||||||
|
Test if the given message is the current connect four game.
|
||||||
|
|
||||||
with open("resources/games/oldImages/connectFour"+str(channel.id), "r") as f:
|
Also tests if the given user is the one who's turn it is.
|
||||||
|
|
||||||
|
*Parameters*
|
||||||
|
------------
|
||||||
|
message: discord.Message
|
||||||
|
The message to test.
|
||||||
|
user: discord.User
|
||||||
|
The user to test.
|
||||||
|
*Returns*
|
||||||
|
---------
|
||||||
|
: bool
|
||||||
|
Whether the given message is the current connect four
|
||||||
|
game and if the user who reacted is the user who's turn
|
||||||
|
it is.
|
||||||
|
"""
|
||||||
|
channel = message.channel
|
||||||
|
channelSearch = {"_id": str(channel.id)}
|
||||||
|
game = self.bot.database["connect 4 games"].find_one(channelSearch)
|
||||||
|
|
||||||
|
filePath = f"resources/games/oldImages/connectFour{channel.id}"
|
||||||
|
with open(filePath, "r") as f:
|
||||||
oldImage = int(f.read())
|
oldImage = int(f.read())
|
||||||
|
|
||||||
if message.id == oldImage:
|
if message.id == oldImage:
|
||||||
self.bot.log("They reacted to the connectFour game")
|
self.bot.log("They reacted to the connectFour game")
|
||||||
turn = game["turn"]
|
turn = game["turn"]
|
||||||
if user == game["players"][turn]:
|
if user == game["players"][turn]:
|
||||||
return True, turn+1
|
return True
|
||||||
else:
|
else:
|
||||||
self.bot.log("It wasn't their turn")
|
self.bot.log("It wasn't their turn")
|
||||||
return False, 0
|
return False
|
||||||
else:
|
else:
|
||||||
return False, 0
|
return False
|
||||||
|
|
||||||
def hangmanReactionTest(self, channel, message, user):
|
def hangmanReactionTest(self, message: discord.Message,
|
||||||
try:
|
user: discord.User):
|
||||||
with open("resources/games/oldImages/hangman"+str(channel.id), "r") as f:
|
"""
|
||||||
|
Test if the given message is the current hangman game.
|
||||||
|
|
||||||
|
Also tests if the given user is the one who's playing hangman.
|
||||||
|
|
||||||
|
*Parameters*
|
||||||
|
------------
|
||||||
|
message: discord.Message
|
||||||
|
The message to test.
|
||||||
|
user: discord.User
|
||||||
|
The user to test.
|
||||||
|
*Returns*
|
||||||
|
---------
|
||||||
|
: bool
|
||||||
|
Whether the given message is the current hangman game
|
||||||
|
and if the user who reacted is the user who's playing
|
||||||
|
hangman.
|
||||||
|
"""
|
||||||
|
channel = message.channel
|
||||||
|
filePath = f"resources/games/oldImages/hangman{channel.id}"
|
||||||
|
if os.path.isfile(filePath):
|
||||||
|
with open(filePath, "r") as f:
|
||||||
oldMessages = f.read().splitlines()
|
oldMessages = f.read().splitlines()
|
||||||
except:
|
else:
|
||||||
return False
|
return False
|
||||||
gameMessage = False
|
gameMessage = False
|
||||||
|
|
||||||
for oldMessage in oldMessages:
|
for oldMessage in oldMessages:
|
||||||
oldMessageID = int(oldMessage)
|
oldMessageID = int(oldMessage)
|
||||||
if message.id == oldMessageID:
|
if message.id == oldMessageID:
|
||||||
game = self.bot.database["hangman games"].find_one({"_id":str(channel.id)})
|
database = self.bot.database["hangman games"]
|
||||||
|
channelSearch = {"_id": str(channel.id)}
|
||||||
|
game = database.find_one(channelSearch)
|
||||||
if user == game["player"]:
|
if user == game["player"]:
|
||||||
gameMessage = True
|
gameMessage = True
|
||||||
|
|
||||||
@ -120,9 +276,30 @@ class databaseFuncs():
|
|||||||
|
|
||||||
return gameMessage
|
return gameMessage
|
||||||
|
|
||||||
def bedreNetflixReactionTest(self, channel, message):
|
def bedreNetflixReactionTest(self, message: discord.Message):
|
||||||
if os.path.isfile(f"resources/bedreNetflix/oldMessage{str(channel.id)}"):
|
"""
|
||||||
with open("resources/bedreNetflix/oldMessage"+str(channel.id),"r") as f:
|
Test if the given message is the response to a plex request.
|
||||||
|
|
||||||
|
*Parameters*
|
||||||
|
------------
|
||||||
|
message: discord.Message
|
||||||
|
The message to test.
|
||||||
|
|
||||||
|
*Returns*
|
||||||
|
---------
|
||||||
|
: bool
|
||||||
|
Whether the message is the response to a plex request.
|
||||||
|
: bool
|
||||||
|
Whether it was a movie request (false for a show
|
||||||
|
request)
|
||||||
|
: list
|
||||||
|
A list of ids or names of the shows or movies that
|
||||||
|
Gwendolyn presented after the request.
|
||||||
|
"""
|
||||||
|
channel = message.channel
|
||||||
|
filePath = f"resources/bedreNetflix/oldMessage{str(channel.id)}"
|
||||||
|
if os.path.isfile(filePath):
|
||||||
|
with open(filePath, "r") as f:
|
||||||
data = json.load(f)
|
data = json.load(f)
|
||||||
else:
|
else:
|
||||||
return False, None, None
|
return False, None, None
|
||||||
@ -136,6 +313,7 @@ class databaseFuncs():
|
|||||||
return False, None, None
|
return False, None, None
|
||||||
|
|
||||||
async def syncCommands(self):
|
async def syncCommands(self):
|
||||||
|
"""Sync the slash commands with the discord API."""
|
||||||
collection = self.bot.database["last synced"]
|
collection = self.bot.database["last synced"]
|
||||||
lastSynced = collection.find_one()
|
lastSynced = collection.find_one()
|
||||||
now = time.time()
|
now = time.time()
|
||||||
@ -144,6 +322,6 @@ class databaseFuncs():
|
|||||||
self.bot.log(f"Updating commands: {slashCommandList}")
|
self.bot.log(f"Updating commands: {slashCommandList}")
|
||||||
await self.bot.slash.sync_all_commands()
|
await self.bot.slash.sync_all_commands()
|
||||||
idNumber = lastSynced["_id"]
|
idNumber = lastSynced["_id"]
|
||||||
queryFilter = {"_id" : idNumber}
|
queryFilter = {"_id": idNumber}
|
||||||
update = {"$set" : {"last synced" : now}}
|
update = {"$set": {"last synced": now}}
|
||||||
collection.update_one(queryFilter, update)
|
collection.update_one(queryFilter, update)
|
||||||
|
@ -1,3 +1,18 @@
|
|||||||
|
"""
|
||||||
|
Contains utility functions used by parts of the bot.
|
||||||
|
|
||||||
|
*Functions*
|
||||||
|
-----------
|
||||||
|
longstrings() -> dict
|
||||||
|
getParams() -> dict
|
||||||
|
logThis(messages: Union[str, list], channel: str = "",
|
||||||
|
level: int = 20)
|
||||||
|
cap(s: str) -> str
|
||||||
|
makeFiles()
|
||||||
|
replaceMultiple(mainString: str, toBeReplaced: list,
|
||||||
|
newString: str) -> str
|
||||||
|
emojiToCommand(emoji: str) -> str
|
||||||
|
"""
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
@ -5,22 +20,55 @@ import sys
|
|||||||
import imdb
|
import imdb
|
||||||
from .helperClasses import Options
|
from .helperClasses import Options
|
||||||
|
|
||||||
|
|
||||||
|
# All of this is logging configuration
|
||||||
FORMAT = " %(asctime)s | %(name)-16s | %(levelname)-8s | %(message)s"
|
FORMAT = " %(asctime)s | %(name)-16s | %(levelname)-8s | %(message)s"
|
||||||
PRINTFORMAT = "%(asctime)s - %(message)s"
|
PRINTFORMAT = "%(asctime)s - %(message)s"
|
||||||
DATEFORMAT = "%Y-%m-%d %H:%M:%S"
|
DATEFORMAT = "%Y-%m-%d %H:%M:%S"
|
||||||
|
|
||||||
logging.addLevelName(25, "PRINT")
|
logging.addLevelName(25, "PRINT")
|
||||||
logging.basicConfig(format=FORMAT, datefmt=DATEFORMAT, level=logging.INFO, filename="gwendolyn.log")
|
loggingConfigParams = {
|
||||||
|
"format": FORMAT,
|
||||||
|
"datefmt": DATEFORMAT,
|
||||||
|
"level": logging.INFO,
|
||||||
|
"filename": "gwendolyn.log"
|
||||||
|
}
|
||||||
|
logging.basicConfig(**loggingConfigParams)
|
||||||
logger = logging.getLogger("Gwendolyn")
|
logger = logging.getLogger("Gwendolyn")
|
||||||
printer = logging.getLogger("printer")
|
printer = logging.getLogger("printer")
|
||||||
handler = logging.StreamHandler(sys.stdout)
|
handler = logging.StreamHandler(sys.stdout)
|
||||||
handler.setFormatter(logging.Formatter(fmt = PRINTFORMAT, datefmt=DATEFORMAT))
|
handler.setFormatter(logging.Formatter(fmt=PRINTFORMAT, datefmt=DATEFORMAT))
|
||||||
printer.addHandler(handler)
|
printer.addHandler(handler)
|
||||||
printer.propagate = False
|
printer.propagate = False
|
||||||
|
|
||||||
imdb._logging.setLevel("CRITICAL")
|
imdb._logging.setLevel("CRITICAL") # Basically disables imdbpy
|
||||||
|
# logging, since it's printed to the terminal.
|
||||||
|
|
||||||
|
|
||||||
|
def longStrings():
|
||||||
|
"""
|
||||||
|
Get the data from resources/longStrings.json.
|
||||||
|
|
||||||
|
*Returns*
|
||||||
|
---------
|
||||||
|
data: dict
|
||||||
|
The long strings and their keys.
|
||||||
|
"""
|
||||||
|
with open("resources/longStrings.json", "r") as f:
|
||||||
|
data = json.load(f)
|
||||||
|
|
||||||
|
return data
|
||||||
|
|
||||||
|
|
||||||
def getParams():
|
def getParams():
|
||||||
|
"""
|
||||||
|
Get the slash command parameters.
|
||||||
|
|
||||||
|
*Returns*
|
||||||
|
---------
|
||||||
|
params: dict
|
||||||
|
The parameters for every slash command.
|
||||||
|
"""
|
||||||
with open("resources/slashParameters.json", "r") as f:
|
with open("resources/slashParameters.json", "r") as f:
|
||||||
params = json.load(f)
|
params = json.load(f)
|
||||||
|
|
||||||
@ -32,8 +80,25 @@ def getParams():
|
|||||||
|
|
||||||
return params
|
return params
|
||||||
|
|
||||||
def logThis(messages, channel : str = "", level : int = 20):
|
|
||||||
channel = channel.replace("Direct Message with ","")
|
def logThis(messages, channel: str = "", level: int = 20):
|
||||||
|
"""
|
||||||
|
Log something in Gwendolyn's logs.
|
||||||
|
|
||||||
|
*Parameters*
|
||||||
|
------------
|
||||||
|
messages: Union[str, list]
|
||||||
|
A string or list of strings to be logged. If there are
|
||||||
|
multiple strings and the level is PRINT (25) or higher,
|
||||||
|
only the first string will be printed.
|
||||||
|
channel: str = ""
|
||||||
|
The channel the event to be logged occurred in. Will be
|
||||||
|
logged along with the message(s).
|
||||||
|
level: int = 20
|
||||||
|
The level to log the message(s) at. If PRINT (25) or
|
||||||
|
higher, the first message will be printed to the console.
|
||||||
|
"""
|
||||||
|
channel = channel.replace("Direct Message with ", "")
|
||||||
if type(messages) is str:
|
if type(messages) is str:
|
||||||
messages = [messages]
|
messages = [messages]
|
||||||
|
|
||||||
@ -41,9 +106,11 @@ def logThis(messages, channel : str = "", level : int = 20):
|
|||||||
|
|
||||||
for x, msg in enumerate(messages):
|
for x, msg in enumerate(messages):
|
||||||
if channel != "":
|
if channel != "":
|
||||||
messages[x] = f"{msg} - ({channel})"
|
messages[x] = f"{msg} - ({channel})" # Adds channel to log
|
||||||
|
# messages
|
||||||
|
|
||||||
if len(messages) > 1:
|
if len(messages) > 1: # Tells user to check the log if there are
|
||||||
|
# more messages there
|
||||||
printMessage += " (details in log)"
|
printMessage += " (details in log)"
|
||||||
|
|
||||||
if level >= 25:
|
if level >= 25:
|
||||||
@ -52,10 +119,24 @@ def logThis(messages, channel : str = "", level : int = 20):
|
|||||||
for logMessage in messages:
|
for logMessage in messages:
|
||||||
logger.log(level, logMessage)
|
logger.log(level, logMessage)
|
||||||
|
|
||||||
# Capitalizes all words except some of them
|
|
||||||
def cap(s):
|
def cap(s: str):
|
||||||
no_caps_list = ["of","the"]
|
"""
|
||||||
# Capitalizes a strink like a movie title
|
Capitalize a string like a movie title.
|
||||||
|
|
||||||
|
That means "of" and "the" are not capitalized.
|
||||||
|
|
||||||
|
*Parameters*
|
||||||
|
------------
|
||||||
|
s: str
|
||||||
|
The string to capitalized.
|
||||||
|
|
||||||
|
*Returns*
|
||||||
|
---------
|
||||||
|
res: str
|
||||||
|
The capitalized string.
|
||||||
|
"""
|
||||||
|
no_caps_list = ["of", "the"]
|
||||||
word_number = 0
|
word_number = 0
|
||||||
lst = s.split()
|
lst = s.split()
|
||||||
res = ''
|
res = ''
|
||||||
@ -67,22 +148,25 @@ def cap(s):
|
|||||||
res = res[:-1]
|
res = res[:-1]
|
||||||
return res
|
return res
|
||||||
|
|
||||||
def makeFiles():
|
|
||||||
def makeJsonFile(path,content):
|
|
||||||
# Creates json file if it doesn't exist
|
|
||||||
if not os.path.isfile(path):
|
|
||||||
logThis(path.split("/")[-1]+" didn't exist. Making it now.")
|
|
||||||
with open(path,"w") as f:
|
|
||||||
json.dump(content,f,indent = 4)
|
|
||||||
|
|
||||||
def makeTxtFile(path,content):
|
def makeFiles():
|
||||||
# Creates txt file if it doesn't exist
|
"""Create all the files and directories needed by Gwendolyn."""
|
||||||
|
def makeJsonFile(path, content):
|
||||||
|
"""Create json file if it doesn't exist."""
|
||||||
if not os.path.isfile(path):
|
if not os.path.isfile(path):
|
||||||
logThis(path.split("/")[-1]+" didn't exist. Making it now.")
|
logThis(path.split("/")[-1]+" didn't exist. Making it now.")
|
||||||
with open(path,"w") as f:
|
with open(path, "w") as f:
|
||||||
|
json.dump(content, f, indent=4)
|
||||||
|
|
||||||
|
def makeTxtFile(path, content):
|
||||||
|
"""Create txt file if it doesn't exist."""
|
||||||
|
if not os.path.isfile(path):
|
||||||
|
logThis(path.split("/")[-1]+" didn't exist. Making it now.")
|
||||||
|
with open(path, "w") as f:
|
||||||
f.write(content)
|
f.write(content)
|
||||||
|
|
||||||
def directory(path):
|
def directory(path):
|
||||||
|
"""Create directory if it doesn't exist."""
|
||||||
if not os.path.isdir(path):
|
if not os.path.isdir(path):
|
||||||
os.makedirs(path)
|
os.makedirs(path)
|
||||||
logThis("The "+path.split("/")[-1]+" directory didn't exist")
|
logThis("The "+path.split("/")[-1]+" directory didn't exist")
|
||||||
@ -90,27 +174,58 @@ def makeFiles():
|
|||||||
with open("resources/startingFiles.json") as f:
|
with open("resources/startingFiles.json") as f:
|
||||||
data = json.load(f)
|
data = json.load(f)
|
||||||
|
|
||||||
|
for path, content in data["json"].items():
|
||||||
|
makeJsonFile(path, content)
|
||||||
|
|
||||||
|
for path, content in data["txt"].items():
|
||||||
|
makeTxtFile(path, content)
|
||||||
|
|
||||||
for path in data["folder"]:
|
for path in data["folder"]:
|
||||||
directory(path)
|
directory(path)
|
||||||
|
|
||||||
for path, content in data["json"].items():
|
|
||||||
makeJsonFile(path,content)
|
|
||||||
|
|
||||||
for path, content in data["txt"].items():
|
def replaceMultiple(mainString: str, toBeReplaced: list, newString: str):
|
||||||
makeTxtFile(path,content)
|
"""
|
||||||
|
Replace multiple substrings in a string with the same substring.
|
||||||
|
|
||||||
# Replaces multiple things with the same thing
|
*Parameters*
|
||||||
def replaceMultiple(mainString, toBeReplaces, newString):
|
------------
|
||||||
|
mainString: str
|
||||||
|
The string to replace substrings in.
|
||||||
|
toBeReplaced: list
|
||||||
|
The substrings to replace.
|
||||||
|
newString: str
|
||||||
|
The string to replace the substrings with.
|
||||||
|
|
||||||
|
*Returns*
|
||||||
|
---------
|
||||||
|
mainString: str
|
||||||
|
The string with the substrings replaced.
|
||||||
|
"""
|
||||||
# Iterate over the strings to be replaced
|
# Iterate over the strings to be replaced
|
||||||
for elem in toBeReplaces :
|
for elem in toBeReplaced:
|
||||||
# Check if string is in the main string
|
# Check if string is in the main string
|
||||||
if elem in mainString :
|
if elem in mainString:
|
||||||
# Replace the string
|
# Replace the string
|
||||||
mainString = mainString.replace(elem, newString)
|
mainString = mainString.replace(elem, newString)
|
||||||
|
|
||||||
return mainString
|
return mainString
|
||||||
|
|
||||||
def emojiToCommand(emoji):
|
|
||||||
|
def emojiToCommand(emoji: str):
|
||||||
|
"""
|
||||||
|
Convert emoji to text.
|
||||||
|
|
||||||
|
*Parameters*
|
||||||
|
------------
|
||||||
|
emoji: str
|
||||||
|
The emoji to decipher.
|
||||||
|
|
||||||
|
*Returns*
|
||||||
|
---------
|
||||||
|
: str
|
||||||
|
The deciphered string.
|
||||||
|
"""
|
||||||
if emoji == "1️⃣":
|
if emoji == "1️⃣":
|
||||||
return 1
|
return 1
|
||||||
elif emoji == "2️⃣":
|
elif emoji == "2️⃣":
|
||||||
@ -131,4 +246,5 @@ def emojiToCommand(emoji):
|
|||||||
return "none"
|
return "none"
|
||||||
elif emoji == "✔️":
|
elif emoji == "✔️":
|
||||||
return 1
|
return 1
|
||||||
else: return ""
|
else:
|
||||||
|
return ""
|
||||||
|
Reference in New Issue
Block a user