✨ reworking a bunch of stuff
@ -10,7 +10,6 @@ Gwendolyn is a discord bot that I made. It does a bunch of stuff.
|
||||
* Roll Star Wars RPG dice!
|
||||
* Keep track of Star Wars RPG character sheets!
|
||||
* Query Wolfram Alpha
|
||||
* Invest fake money in the stock market
|
||||
* Play trivia, connect 4, blackjack, hangman and hex
|
||||
|
||||
And much more!!! (not really. That's pretty much all it can do. See help files in resources directory for list of commands)
|
||||
|
@ -1,6 +1,5 @@
|
||||
"""The main module for Gwendolyn."""
|
||||
# pylint: disable=invalid-name
|
||||
|
||||
__all__ = ["funcs", "utils", "Gwendolyn"]
|
||||
__all__ = ["Gwendolyn"]
|
||||
|
||||
from .gwendolyn_client import Gwendolyn
|
||||
|
9
gwendolyn/ext/misc.py
Normal file
@ -0,0 +1,9 @@
|
||||
from interactions import Extension, slash_command, SlashContext
|
||||
|
||||
class MiscExtension(Extension):
|
||||
"""Contains the miscellaneous commands."""
|
||||
|
||||
@slash_command()
|
||||
async def hello(self, ctx: SlashContext):
|
||||
"""Greet the bot."""
|
||||
await ctx.send(f"Hello, I'm {self.bot.user.mention}!")
|
@ -1,286 +0,0 @@
|
||||
"""
|
||||
Contains functions relating to invest commands.
|
||||
|
||||
*Classes*
|
||||
---------
|
||||
Invest
|
||||
Contains all the code for the invest commands.
|
||||
"""
|
||||
import discord # Used for embeds
|
||||
from discord_slash.context import SlashContext # Used for type hints
|
||||
|
||||
|
||||
class Invest():
|
||||
"""
|
||||
Contains all the invest functions.
|
||||
|
||||
*Methods*
|
||||
---------
|
||||
getPrice(symbol: str) -> int
|
||||
getPortfolio(user: str) -> str
|
||||
buyStock(user: str, stock: str: buyAmount: int) -> str
|
||||
sellStock(user: str, stock: str, buyAmount: int) -> str
|
||||
parseInvest(ctx: discord_slash.context.SlashContext,
|
||||
parameters: str)
|
||||
"""
|
||||
|
||||
def __init__(self, bot):
|
||||
"""Initialize the class."""
|
||||
self.bot = bot
|
||||
|
||||
def getPrice(self, symbol: str):
|
||||
"""
|
||||
Get the price of a stock.
|
||||
|
||||
*Parameters*
|
||||
------------
|
||||
symbol: str
|
||||
The symbol of the stock to get the price of.
|
||||
|
||||
*Returns*
|
||||
---------
|
||||
price: int
|
||||
The price of the stock.
|
||||
"""
|
||||
res = self.bot.finnhub_client.quote(symbol.upper())
|
||||
if res == {}:
|
||||
return 0
|
||||
else:
|
||||
return int(res["c"] * 100)
|
||||
|
||||
def getPortfolio(self, user: str):
|
||||
"""
|
||||
Get the stock portfolio of a user.
|
||||
|
||||
*Parameters*
|
||||
------------
|
||||
user: str
|
||||
The id of the user to get the portfolio of.
|
||||
|
||||
*Returns*
|
||||
---------
|
||||
portfolio: str
|
||||
The portfolio.
|
||||
"""
|
||||
investments_database = self.bot.database["investments"]
|
||||
userInvestments = investments_database.find_one({"_id": user})
|
||||
|
||||
user_name = self.bot.database_funcs.get_name(user)
|
||||
|
||||
if userInvestments in [None, {}]:
|
||||
return f"{user_name} does not have a stock portfolio."
|
||||
else:
|
||||
portfolio = f"**Stock portfolio for {user_name}**"
|
||||
|
||||
for key, value in list(userInvestments["investments"].items()):
|
||||
purchaseValue = value["purchased for"]
|
||||
stockPrice = self.getPrice(key)
|
||||
valueAtPurchase = value["value at purchase"]
|
||||
purchasedStock = value["purchased"]
|
||||
valueChange = (stockPrice / valueAtPurchase)
|
||||
currentValue = int(valueChange * purchasedStock)
|
||||
portfolio += f"\n**{key}**: ___{currentValue} GwendoBucks___"
|
||||
|
||||
if purchaseValue != "?":
|
||||
portfolio += f" (purchased for {purchaseValue})"
|
||||
|
||||
return portfolio
|
||||
|
||||
def buyStock(self, user: str, stock: str, buyAmount: int):
|
||||
"""
|
||||
Buy an amount of a specific stock.
|
||||
|
||||
*Paramaters*
|
||||
------------
|
||||
user: str
|
||||
The id of the user buying.
|
||||
stock: str
|
||||
The symbol of the stock to buy.
|
||||
buyAmount: int
|
||||
The amount of GwendoBucks to use to buy the stock.
|
||||
|
||||
*Returns*
|
||||
---------
|
||||
send_message: str
|
||||
The message to return to the user.
|
||||
"""
|
||||
if buyAmount < 100:
|
||||
return "You cannot buy stocks for less than 100 GwendoBucks"
|
||||
elif self.bot.money.checkBalance(user) < buyAmount:
|
||||
return "You don't have enough money for that"
|
||||
elif self.getPrice(stock) <= 0:
|
||||
return f"{stock} is not traded on the american market."
|
||||
else:
|
||||
investments_database = self.bot.database["investments"]
|
||||
stockPrice = self.getPrice(stock)
|
||||
userInvestments = investments_database.find_one({"_id": user})
|
||||
|
||||
self.bot.money.addMoney(user, -1*buyAmount)
|
||||
stock = stock.upper()
|
||||
|
||||
if userInvestments is not None:
|
||||
userInvestments = userInvestments["investments"]
|
||||
if stock in userInvestments:
|
||||
value = userInvestments[stock]
|
||||
valueChange = (stockPrice / value["value at purchase"])
|
||||
currentValue = int(valueChange * value["purchased"])
|
||||
newAmount = currentValue + buyAmount
|
||||
|
||||
value_path = f"investments.{stock}.value at purchase"
|
||||
updater = {"$set": {value_path: stockPrice}}
|
||||
investments_database.update_one({"_id": user}, updater)
|
||||
|
||||
purchased_path = f"investments.{stock}.purchased"
|
||||
updater = {"$set": {purchased_path: newAmount}}
|
||||
investments_database.update_one({"_id": user}, updater)
|
||||
|
||||
if value["purchased for"] != "?":
|
||||
purchasedFor_path = f"investments.{stock}.purchased for"
|
||||
updater = {"$set": {purchasedFor_path: buyAmount}}
|
||||
investments_database.update_one({"_id": user}, updater)
|
||||
else:
|
||||
updater = {
|
||||
"$set": {
|
||||
"investments.{stock}": {
|
||||
"purchased": buyAmount,
|
||||
"value at purchase": stockPrice,
|
||||
"purchased for": buyAmount
|
||||
}
|
||||
}
|
||||
}
|
||||
investments_database.update_one({"_id": user}, updater)
|
||||
else:
|
||||
new_user = {
|
||||
"_id": user,
|
||||
"investments": {
|
||||
stock: {
|
||||
"purchased": buyAmount,
|
||||
"value at purchase": stockPrice,
|
||||
"purchased for": buyAmount
|
||||
}
|
||||
}
|
||||
}
|
||||
investments_database.insert_one(new_user)
|
||||
|
||||
user_name = self.bot.database_funcs.get_name(user)
|
||||
send_message = "{} bought {} GwendoBucks worth of {} stock"
|
||||
send_message = send_message.format(user_name, buyAmount, stock)
|
||||
return send_message
|
||||
|
||||
def sellStock(self, user: str, stock: str, sellAmount: int):
|
||||
"""
|
||||
Sell an amount of a specific stock.
|
||||
|
||||
*Paramaters*
|
||||
------------
|
||||
user: str
|
||||
The id of the user selling.
|
||||
stock: str
|
||||
The symbol of the stock to sell.
|
||||
buyAmount: int
|
||||
The amount of GwendoBucks to sell for.
|
||||
|
||||
*Returns*
|
||||
---------
|
||||
send_message: str
|
||||
The message to return to the user.
|
||||
"""
|
||||
if sellAmount <= 0:
|
||||
return "no"
|
||||
else:
|
||||
investments_database = self.bot.database["investments"]
|
||||
user_data = investments_database.find_one({"_id": user})
|
||||
userInvestments = user_data["investments"]
|
||||
|
||||
stock = stock.upper()
|
||||
|
||||
if userInvestments is not None and stock in userInvestments:
|
||||
value = userInvestments[stock]
|
||||
stockPrice = self.getPrice(stock)
|
||||
priceChange = (stockPrice / value["value at purchase"])
|
||||
purchasedAmount = int(priceChange * value["purchased"])
|
||||
purchased_path = f"investments.{stock}.purchased"
|
||||
updater = {"$set": {purchased_path: purchasedAmount}}
|
||||
investments_database.update_one({"_id": user}, updater)
|
||||
valueAtPurchase_path = f"investments.{stock}.value at purchase"
|
||||
updater = {"$set": {valueAtPurchase_path: stockPrice}}
|
||||
investments_database.update_one({"_id": user}, updater)
|
||||
if value["purchased"] >= sellAmount:
|
||||
self.bot.money.addMoney(user, sellAmount)
|
||||
if sellAmount < value["purchased"]:
|
||||
purchased_path = f"investments.{stock}.purchased"
|
||||
updater = {"$inc": {purchased_path: -sellAmount}}
|
||||
investments_database.update_one({"_id": user}, updater)
|
||||
|
||||
purchasedFor_path = f"investments.{stock}.purchased for"
|
||||
updater = {"$set": {purchasedFor_path: "?"}}
|
||||
investments_database.update_one({"_id": user}, updater)
|
||||
else:
|
||||
updater = {"$unset": {f"investments.{stock}": ""}}
|
||||
investments_database.update_one({"_id": user}, updater)
|
||||
|
||||
user_name = self.bot.database_funcs.get_name(user)
|
||||
send_message = "{} sold {} GwendoBucks worth of {} stock"
|
||||
return send_message.format(user_name, sellAmount, stock)
|
||||
else:
|
||||
return f"You don't have enough {stock} stocks to do that"
|
||||
else:
|
||||
return f"You don't have any {stock} stock"
|
||||
|
||||
async def parseInvest(self, ctx: SlashContext, parameters: str):
|
||||
"""
|
||||
Parse an invest command. TO BE DELETED.
|
||||
|
||||
*Parameters*
|
||||
------------
|
||||
ctx: discord_slash.context.SlashContext
|
||||
The context of the slash command.
|
||||
parameters: str
|
||||
The parameters of the command.
|
||||
"""
|
||||
await self.bot.defer(ctx)
|
||||
user = f"#{ctx.author.id}"
|
||||
|
||||
if parameters.startswith("check"):
|
||||
commands = parameters.split(" ")
|
||||
if len(commands) == 1:
|
||||
response = self.getPortfolio(user)
|
||||
else:
|
||||
price = self.getPrice(commands[1])
|
||||
if price == 0:
|
||||
response = "{} is not traded on the american market."
|
||||
response = response.format(commands[0].upper())
|
||||
else:
|
||||
price = f"{price:,}".replace(",", ".")
|
||||
response = self.bot.long_strings["Stock value"]
|
||||
response = response.format(commands[1].upper(), price)
|
||||
|
||||
elif parameters.startswith("buy"):
|
||||
commands = parameters.split(" ")
|
||||
if len(commands) == 3:
|
||||
response = self.buyStock(user, commands[1], int(commands[2]))
|
||||
else:
|
||||
response = self.bot.long_strings["Stock parameters"]
|
||||
|
||||
elif parameters.startswith("sell"):
|
||||
commands = parameters.split(" ")
|
||||
if len(commands) == 3:
|
||||
response = self.sellStock(user, commands[1], int(commands[2]))
|
||||
else:
|
||||
response = self.bot.long_strings["Stock parameters"]
|
||||
|
||||
else:
|
||||
response = "Incorrect parameters"
|
||||
|
||||
if response.startswith("**"):
|
||||
responses = response.split("\n")
|
||||
text = "\n".join(responses[1:])
|
||||
embedParams = {
|
||||
"title": responses[0],
|
||||
"description": text,
|
||||
"colour": 0x00FF00
|
||||
}
|
||||
em = discord.Embed(**embedParams)
|
||||
await ctx.send(embed=em)
|
||||
else:
|
||||
await ctx.send(response)
|
@ -1,135 +1,40 @@
|
||||
"""
|
||||
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): # pylint:disable=no-self-use
|
||||
"""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")
|
||||
from interactions import Client, Status
|
||||
from gwendolyn.utils import get_options, get_credentials, long_strings, log
|
||||
|
||||
from pymongo import MongoClient # Used for database management
|
||||
|
||||
class Gwendolyn(Client):
|
||||
|
||||
def __init__(self):
|
||||
"""Initialize the bot."""
|
||||
initiation_parameters = {
|
||||
"status": Status.DND,
|
||||
"delete_unused_application_cmds": True
|
||||
}
|
||||
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()
|
||||
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_client = MongoClient(mongo_url)
|
||||
|
||||
if self.options["testing"]:
|
||||
self.log("Testing mode")
|
||||
self.database = database_client["Gwendolyn-Test"]
|
||||
else:
|
||||
self.database = database_client["Gwendolyn"]
|
||||
|
||||
def log(self, messages, channel: str = "", level: int = 20): # pylint:disable=no-self-use
|
||||
"""Log a message. Described in utils/util_functions.py."""
|
||||
log(messages, channel, level)
|
@ -1,3 +0,0 @@
|
||||
`/invest` vil vise dig hvilke aktier du har. `/invest check [symbol]` viser dig en akties nuværende pris, hvor [symbol] er forkortelsen for firmaet. GwendoBucks er lig med 1 amerikans cent.
|
||||
`/invest buy [symbol] [pris]` lader dig købe aktier. [pris] er mængden af GwendoBucks du bruger på at købe. Du kan købe for færre GwendoBucks end en enkelt akties pris, men ikke for mindre end 100 GwendoBucks.
|
||||
`/invest buy [symbol] [pris]` lader dig sælge dine aktier. Du kan godt sælge for mindre end 100 GwendoBucks.
|
@ -10,7 +10,6 @@
|
||||
`/star_wars_character` - Lader dig lave en Star Wars karakter.
|
||||
`/star_wars_roll` - Lader dig rulle Star Wars terninger.
|
||||
`/balance` - Viser dig hvor mange GwendoBucks du har.
|
||||
`/invest` - Lader dig investere dine GwendoBucks i aktiemarkedet.
|
||||
`/blackjack` - Lader dig spille et spil blackjack.
|
||||
`/trivia` - Lader dig spille et spil trivia, hvor du kan tjene GwendoBucks.
|
||||
`/connect_four` - Lader dig spille et spil fire på stribe.
|
||||
|
@ -206,18 +206,6 @@
|
||||
"name" : "undo",
|
||||
"description" : "Undo your last hex move"
|
||||
},
|
||||
"invest" : {
|
||||
"name" : "invest",
|
||||
"description" : "Invest GwendoBucks in the stock market",
|
||||
"options" : [
|
||||
{
|
||||
"name" : "parameters",
|
||||
"description" : "The parameters for the command",
|
||||
"type" : 3,
|
||||
"required" : "false"
|
||||
}
|
||||
]
|
||||
},
|
||||
"image" : {
|
||||
"name" : "image",
|
||||
"description" : "Get a random image from Bing"
|
||||
|
@ -59,7 +59,7 @@
|
||||
"gwendolyn/resources/star_wars/destinyPoints.txt": "",
|
||||
"gwendolyn/resources/movies.txt": "The Room",
|
||||
"gwendolyn/resources/names.txt": "Gandalf\n",
|
||||
"credentials.txt" : "Bot token: TOKEN\nFinnhub API key: KEY\nWordnik API Key: KEY\nMongoDB user: USERNAME\nMongoDB password: PASSWORD\nWolframAlpha AppID: APPID\nRadarr API key: KEY\nSonarr API key: KEY\nqBittorrent username: USER\nqBittorrent password: PASSWORD",
|
||||
"credentials.txt" : "Bot token: TOKEN\nWordnik API Key: KEY\nMongoDB user: USERNAME\nMongoDB password: PASSWORD\nWolframAlpha AppID: APPID\nRadarr API key: KEY\nSonarr API key: KEY\nqBittorrent username: USER\nqBittorrent password: PASSWORD",
|
||||
"options.txt" : "Testing: True\nTesting guild ids:\nAdmins:"
|
||||
},
|
||||
"folder" : [
|
||||
|
@ -1,12 +1,5 @@
|
||||
"""A collections of utilities used by Gwendolyn and her functions."""
|
||||
|
||||
__all__ = ["get_options", "get_credentials", "DatabaseFuncs", "EventHandler",
|
||||
"ErrorHandler", "get_params", "log_this", "cap", "make_files",
|
||||
"replace_multiple", "emoji_to_command"]
|
||||
__all__ = ["make_files","get_options", "get_credentials", "long_strings", "log"]
|
||||
|
||||
from .helper_classes import DatabaseFuncs
|
||||
from .event_handlers import EventHandler, ErrorHandler
|
||||
from .util_functions import (get_params, log_this, cap, make_files,
|
||||
replace_multiple, emoji_to_command, long_strings,
|
||||
sanitize, get_options, get_credentials, encode_id,
|
||||
decode_id)
|
||||
from .util_functions import make_files, get_options, get_credentials, long_strings, log
|
||||
|
@ -1,37 +1,7 @@
|
||||
"""
|
||||
Contains utility functions used by parts of the bot.
|
||||
|
||||
*Functions*
|
||||
-----------
|
||||
sanitize(data: str, lower_case_value: bool = false) -> dict
|
||||
get_options() -> dict
|
||||
get_credentials() -> dict
|
||||
long_strings() -> dict
|
||||
get_params() -> dict
|
||||
log_this(messages: Union[str, list], channel: str = "",
|
||||
level: int = 20)
|
||||
cap(s: str) -> str
|
||||
make_files()
|
||||
replace_multiple(main_string: str, to_be_replaced: list,
|
||||
new_string: str) -> str
|
||||
emoji_to_command(emoji: str) -> str
|
||||
"""
|
||||
import string
|
||||
import json # Used by long_strings(), get_params() and make_files()
|
||||
import logging # Used for logging
|
||||
import os # Used by make_files() to check if files exist
|
||||
import sys # Used to specify printing for logging
|
||||
import imdb # Used to disable logging for the module
|
||||
|
||||
|
||||
BASE_37 = ":" + string.digits + string.ascii_uppercase
|
||||
BASE_128 = list(
|
||||
string.digits +
|
||||
string.ascii_letters +
|
||||
"!#$€£¢¥¤&%()*+,-./;:<=>?@[]_{|}~ `¦§©®«»±µ·¿əʒ" +
|
||||
"ÆØÅÐÉÈÊÇÑÖ" +
|
||||
"æøåðéèêçñö"
|
||||
)
|
||||
|
||||
# All of this is logging configuration
|
||||
FORMAT = " %(asctime)s | %(name)-16s | %(levelname)-8s | %(message)s"
|
||||
@ -53,10 +23,6 @@ handler.setFormatter(logging.Formatter(fmt=PRINTFORMAT, datefmt=DATEFORMAT))
|
||||
printer.addHandler(handler)
|
||||
printer.propagate = False
|
||||
|
||||
imdb._logging.setLevel("CRITICAL") # pylint: disable=protected-access
|
||||
# Basically disables imdbpy logging, since it's being printed to the
|
||||
# terminal.
|
||||
|
||||
def sanitize(data: str, lower_case_value: bool = False):
|
||||
"""
|
||||
Sanitize and create a dictionary from a string.
|
||||
@ -134,7 +100,6 @@ def get_credentials():
|
||||
credentials = {}
|
||||
|
||||
credentials["token"] = data["bot token"]
|
||||
credentials["finnhub_key"] = data["finnhub api key"]
|
||||
credentials["wordnik_key"] = data["wordnik api key"]
|
||||
credentials["mongo_db_user"] = data["mongodb user"]
|
||||
credentials["mongo_db_password"] = data["mongodb password"]
|
||||
@ -161,30 +126,7 @@ def long_strings():
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def get_params():
|
||||
"""
|
||||
Get the slash command parameters.
|
||||
|
||||
*Returns*
|
||||
---------
|
||||
params: dict
|
||||
The parameters for every slash command.
|
||||
"""
|
||||
path = "gwendolyn/resources/slash_parameters.json"
|
||||
with open(path, "r", encoding="utf-8") as file_pointer:
|
||||
slash_parameters = json.load(file_pointer)
|
||||
|
||||
options = get_options()
|
||||
|
||||
if options["testing"]:
|
||||
for parameter in slash_parameters:
|
||||
slash_parameters[parameter]["guild_ids"] = options["guild_ids"]
|
||||
|
||||
return slash_parameters
|
||||
|
||||
|
||||
def log_this(messages, channel: str = "", level: int = 20):
|
||||
def log(messages, channel: str = "", level: int = 20):
|
||||
"""
|
||||
Log something in Gwendolyn's logs.
|
||||
|
||||
@ -222,49 +164,19 @@ def log_this(messages, channel: str = "", level: int = 20):
|
||||
for log_message in messages:
|
||||
logger.log(level, log_message)
|
||||
|
||||
|
||||
def cap(input_string: str):
|
||||
"""
|
||||
Capitalize a string like a movie title.
|
||||
|
||||
That means "of" and "the" are not capitalized.
|
||||
|
||||
*Parameters*
|
||||
------------
|
||||
input_string: str
|
||||
The string to capitalized.
|
||||
|
||||
*Returns*
|
||||
---------
|
||||
return_string: str
|
||||
The capitalized string.
|
||||
"""
|
||||
no_caps_list = ["of", "the"]
|
||||
word_number = 0
|
||||
string_list = input_string.split()
|
||||
return_string = ''
|
||||
for word in string_list:
|
||||
word_number += 1
|
||||
if word not in no_caps_list or word_number == 1:
|
||||
word = word.capitalize()
|
||||
return_string += word+" "
|
||||
return_string = return_string[:-1]
|
||||
return return_string
|
||||
|
||||
|
||||
def make_files():
|
||||
"""Create all the files and directories needed by Gwendolyn."""
|
||||
def make_json_file(path, content):
|
||||
"""Create json file if it doesn't exist."""
|
||||
if not os.path.isfile(path):
|
||||
log_this(path.split("/")[-1]+" didn't exist. Making it now.")
|
||||
log(path.split("/")[-1]+" didn't exist. Making it now.")
|
||||
with open(path, "w", encoding="utf-8") as file_pointer:
|
||||
json.dump(content, file_pointer, indent=4)
|
||||
|
||||
def make_txt_file(path, content):
|
||||
"""Create txt file if it doesn't exist."""
|
||||
if not os.path.isfile(path):
|
||||
log_this(path.split("/")[-1]+" didn't exist. Making it now.")
|
||||
log(path.split("/")[-1]+" didn't exist. Making it now.")
|
||||
with open(path, "w", encoding="utf-8") as file_pointer:
|
||||
file_pointer.write(content)
|
||||
|
||||
@ -272,121 +184,18 @@ def make_files():
|
||||
"""Create directory if it doesn't exist."""
|
||||
if not os.path.isdir(path):
|
||||
os.makedirs(path)
|
||||
log_this("The "+path.split("/")[-1]+" directory didn't exist")
|
||||
log("The "+path.split("/")[-1]+" directory didn't exist")
|
||||
|
||||
file_path = "gwendolyn/resources/starting_files.json"
|
||||
with open(file_path, "r", encoding="utf-8") as file_pointer:
|
||||
data = json.load(file_pointer)
|
||||
|
||||
for path in data["folder"]:
|
||||
directory(path)
|
||||
|
||||
for path, content in data["json"].items():
|
||||
make_json_file(path, content)
|
||||
|
||||
for path, content in data["txt"].items():
|
||||
make_txt_file(path, content)
|
||||
|
||||
for path in data["folder"]:
|
||||
directory(path)
|
||||
|
||||
|
||||
def replace_multiple(main_string: str, to_be_replaced: list, new_string: str):
|
||||
"""
|
||||
Replace multiple substrings in a string with the same substring.
|
||||
|
||||
*Parameters*
|
||||
------------
|
||||
main_string: str
|
||||
The string to replace substrings in.
|
||||
to_be_replaced: list
|
||||
The substrings to replace.
|
||||
new_string: str
|
||||
The string to replace the substrings with.
|
||||
|
||||
*Returns*
|
||||
---------
|
||||
main_string: str
|
||||
The string with the substrings replaced.
|
||||
"""
|
||||
# Iterate over the strings to be replaced
|
||||
for elem in to_be_replaced:
|
||||
# Check if string is in the main string
|
||||
if elem in main_string:
|
||||
# Replace the string
|
||||
main_string = main_string.replace(elem, new_string)
|
||||
|
||||
return main_string
|
||||
|
||||
|
||||
def emoji_to_command(emoji: str):
|
||||
"""
|
||||
Convert emoji to text.
|
||||
|
||||
*Parameters*
|
||||
------------
|
||||
emoji: str
|
||||
The emoji to decipher.
|
||||
|
||||
*Returns*
|
||||
---------
|
||||
: str
|
||||
The deciphered string.
|
||||
"""
|
||||
if emoji == "1️⃣":
|
||||
return_value = 1
|
||||
elif emoji == "2️⃣":
|
||||
return_value = 2
|
||||
elif emoji == "3️⃣":
|
||||
return_value = 3
|
||||
elif emoji == "4️⃣":
|
||||
return_value = 4
|
||||
elif emoji == "5️⃣":
|
||||
return_value = 5
|
||||
elif emoji == "6️⃣":
|
||||
return_value = 6
|
||||
elif emoji == "7️⃣":
|
||||
return_value = 7
|
||||
elif emoji == "🎲":
|
||||
return_value = "roll"
|
||||
elif emoji == "❌":
|
||||
return_value = "none"
|
||||
elif emoji == "✔️":
|
||||
return_value = 1
|
||||
else:
|
||||
return_value = ""
|
||||
|
||||
return return_value
|
||||
|
||||
def encode_id(info: list):
|
||||
letters = list(":".join(info))
|
||||
dec = 0
|
||||
for i, letter in enumerate(letters):
|
||||
try:
|
||||
dec += (37**i) * BASE_37.index(letter.upper())
|
||||
except ValueError:
|
||||
log_this(f"Could not encode letter {letter}", level=30)
|
||||
|
||||
custom_id = []
|
||||
|
||||
while dec:
|
||||
custom_id.append(BASE_128[dec % 128])
|
||||
dec = dec // 128
|
||||
|
||||
custom_id = ''.join(custom_id)
|
||||
log_this(f"Encoded {info} to {custom_id}")
|
||||
return custom_id
|
||||
|
||||
|
||||
def decode_id(custom_id: str):
|
||||
letters = list(custom_id)
|
||||
dec = 0
|
||||
for i, letter in enumerate(letters):
|
||||
dec += (128**i) * BASE_128.index(letter)
|
||||
|
||||
info_string = []
|
||||
|
||||
while dec:
|
||||
info_string.append(BASE_37[dec % 37])
|
||||
dec = dec // 37
|
||||
|
||||
info = ''.join(info_string).split(':')
|
||||
log_this(f"Decoded {custom_id} to be {info}")
|
||||
return ''.join(info_string).split(':')
|
||||
|
6
gwendolyn_old/__init__.py
Normal file
@ -0,0 +1,6 @@
|
||||
"""The main module for Gwendolyn."""
|
||||
# pylint: disable=invalid-name
|
||||
|
||||
__all__ = ["funcs", "utils", "Gwendolyn"]
|
||||
|
||||
from .gwendolyn_client import Gwendolyn
|
@ -1,8 +1,8 @@
|
||||
"""Contains all the cogs that deal with game commands."""
|
||||
from discord.ext import commands # Has the cog class
|
||||
from discord_slash import cog_ext # Used for slash commands
|
||||
from interactions import cog_ext # Used for slash commands
|
||||
|
||||
from gwendolyn.utils import get_params # pylint: disable=import-error
|
||||
from gwendolyn_old.utils import get_params # pylint: disable=import-error
|
||||
|
||||
params = get_params()
|
||||
|
||||
@ -24,11 +24,6 @@ class GamesCog(commands.Cog):
|
||||
"""Give another user an amount of GwendoBucks."""
|
||||
await self.bot.money.giveMoney(ctx, user, amount)
|
||||
|
||||
@cog_ext.cog_slash(**params["invest"])
|
||||
async def invest(self, ctx, parameters="check"):
|
||||
"""Invest GwendoBucks in the stock market."""
|
||||
await self.bot.games.invest.parseInvest(ctx, parameters)
|
||||
|
||||
@cog_ext.cog_slash(**params["trivia"])
|
||||
async def trivia(self, ctx, answer=""):
|
||||
"""Run a game of trivia."""
|
@ -1,8 +1,8 @@
|
||||
"""Contains the LookupCog, which deals with the lookup commands."""
|
||||
from discord.ext import commands # Has the cog class
|
||||
from discord_slash import cog_ext # Used for slash commands
|
||||
from interactions import cog_ext # Used for slash commands
|
||||
|
||||
from gwendolyn.utils import get_params # pylint: disable=import-error
|
||||
from gwendolyn_old.utils import get_params # pylint: disable=import-error
|
||||
|
||||
params = get_params()
|
||||
|
@ -1,9 +1,9 @@
|
||||
"""Contains the MiscCog, which deals with miscellaneous commands."""
|
||||
from discord.ext import commands # Has the cog class
|
||||
from discord_slash import cog_ext # Used for slash commands
|
||||
from discord_slash.context import SlashContext
|
||||
from interactions import cog_ext # Used for slash commands
|
||||
from interactions import SlashContext
|
||||
|
||||
from gwendolyn.utils import get_params # pylint: disable=import-error
|
||||
from gwendolyn_old.utils import get_params # pylint: disable=import-error
|
||||
|
||||
params = get_params()
|
||||
|
@ -1,8 +1,8 @@
|
||||
"""Contains the StarWarsCog, which deals with Star Wars commands."""
|
||||
from discord.ext import commands
|
||||
from discord_slash import cog_ext
|
||||
from interactions import cog_ext
|
||||
|
||||
from gwendolyn.utils import get_params # pylint: disable=import-error
|
||||
from gwendolyn_old.utils import get_params # pylint: disable=import-error
|
||||
|
||||
params = get_params()
|
||||
|
@ -12,13 +12,13 @@ import math # Used for flooring decimal numbers
|
||||
import datetime # Used to generate the game id
|
||||
import asyncio # Used for sleeping
|
||||
|
||||
from discord_slash.context import InteractionContext as IntCont # Used for
|
||||
from interactions import InteractionContext as IntCont # Used for
|
||||
# typehints
|
||||
from discord_slash.context import ComponentContext
|
||||
from interactions import ComponentContext
|
||||
from discord.abc import Messageable
|
||||
from PIL import Image
|
||||
|
||||
from gwendolyn.utils import replace_multiple
|
||||
from gwendolyn_old.utils import replace_multiple
|
||||
|
||||
from .game_base import CardGame, CardDrawer
|
||||
|
@ -15,13 +15,13 @@ import discord # Used for typehints, discord.file and to check whether
|
||||
# the opponent in ConnectFour.start is a discord.User
|
||||
|
||||
from PIL import Image, ImageDraw, ImageFont # Used by DrawConnectFour()
|
||||
from discord_slash.context import SlashContext, ComponentContext # Used for
|
||||
from interactions import SlashContext, ComponentContext # Used for
|
||||
# typehints
|
||||
from discord_slash.utils.manage_components import (create_button,
|
||||
from interactions.utils.manage_components import (create_button,
|
||||
create_actionrow)
|
||||
from discord_slash.model import ButtonStyle
|
||||
from interactions.model import ButtonStyle
|
||||
|
||||
from gwendolyn.utils import encode_id
|
||||
from gwendolyn_old.utils import encode_id
|
||||
from .game_base import BoardGame
|
||||
|
||||
ROWCOUNT = 6
|
@ -4,14 +4,13 @@ from typing import Union
|
||||
|
||||
from discord import File, User
|
||||
from discord.abc import Messageable
|
||||
from discord_slash.utils.manage_components import (create_button,
|
||||
create_actionrow)
|
||||
from discord_slash.context import InteractionContext as IntCont
|
||||
from interactions import Button, ActionRow
|
||||
from interactions import InteractionContext as IntCont
|
||||
|
||||
from PIL import ImageFont, Image, ImageDraw
|
||||
|
||||
from gwendolyn.exceptions import GameNotInDatabase
|
||||
from gwendolyn.utils import encode_id
|
||||
from gwendolyn_old.exceptions import GameNotInDatabase
|
||||
from gwendolyn_old.utils import encode_id
|
||||
|
||||
class GameBase():
|
||||
"""The base class for the games."""
|
||||
@ -29,7 +28,7 @@ class GameBase():
|
||||
button_objects = []
|
||||
for label, data, style in buttons:
|
||||
custom_id = encode_id([self.game_name] + data)
|
||||
button_objects.append(create_button(
|
||||
button_objects.append(Button(
|
||||
style=style,
|
||||
label=label,
|
||||
custom_id=custom_id
|
||||
@ -37,7 +36,7 @@ class GameBase():
|
||||
|
||||
action_rows = []
|
||||
for i in range(((len(button_objects)-1)//5)+1):
|
||||
action_rows.append(create_actionrow(*button_objects[i*5:i*5+5]))
|
||||
action_rows.append(ActionRow(*button_objects[i*5:i*5+5]))
|
||||
|
||||
return action_rows
|
||||
|
@ -8,7 +8,6 @@ Has a container for game functions.
|
||||
"""
|
||||
|
||||
|
||||
from .invest import Invest
|
||||
from .trivia import Trivia
|
||||
from .blackjack import Blackjack
|
||||
from .connect_four import ConnectFour
|
||||
@ -25,8 +24,6 @@ class Games():
|
||||
------------
|
||||
bot: Gwendolyn
|
||||
The instance of Gwendolyn.
|
||||
invest
|
||||
Contains investment functions.
|
||||
blackjack
|
||||
Contains blackjack functions.
|
||||
connect_four
|
||||
@ -41,7 +38,6 @@ class Games():
|
||||
"""Initialize the container."""
|
||||
self.bot = bot
|
||||
|
||||
self.invest = Invest(bot)
|
||||
self.trivia = Trivia(bot)
|
||||
self.blackjack = Blackjack(bot)
|
||||
self.connect_four = ConnectFour(bot)
|
@ -16,14 +16,14 @@ import random # Used to draw poorly
|
||||
import requests # Used for getting the word in Hangman.start()
|
||||
import discord # Used for discord.file and type hints
|
||||
|
||||
from discord_slash.utils.manage_components import (create_button,
|
||||
from interactions.utils.manage_components import (create_button,
|
||||
create_actionrow)
|
||||
from discord_slash.model import ButtonStyle
|
||||
from discord_slash.context import SlashContext, ComponentContext
|
||||
from interactions.model import ButtonStyle
|
||||
from interactions import SlashContext, ComponentContext
|
||||
# Used for typehints
|
||||
from PIL import ImageDraw, Image, ImageFont # Used to draw the image
|
||||
|
||||
from gwendolyn.utils import encode_id
|
||||
from gwendolyn_old.utils import encode_id
|
||||
|
||||
class Hangman():
|
||||
"""
|
@ -6,7 +6,7 @@ Contains the code that deals with money.
|
||||
Money
|
||||
Deals with money.
|
||||
"""
|
||||
import discord_slash # Used for typehints
|
||||
import interactions # Used for typehints
|
||||
import discord # Used for typehints
|
||||
|
||||
|
||||
@ -17,9 +17,9 @@ class Money():
|
||||
*Methods*
|
||||
---------
|
||||
checkBalance(user: str)
|
||||
sendBalance(ctx: discord_slash.context.SlashContext)
|
||||
sendBalance(ctx: interactions.SlashContext)
|
||||
addMoney(user: str, amount: int)
|
||||
giveMoney(ctx: discord_slash.context.SlashContext, user: discord.User,
|
||||
giveMoney(ctx: interactions.SlashContext, user: discord.User,
|
||||
amount: int)
|
||||
|
||||
*Attributes*
|
||||
@ -58,13 +58,13 @@ class Money():
|
||||
else:
|
||||
return 0
|
||||
|
||||
async def sendBalance(self, ctx: discord_slash.context.SlashContext):
|
||||
async def sendBalance(self, ctx: interactions.SlashContext):
|
||||
"""
|
||||
Get your own account balance.
|
||||
|
||||
*Parameters*
|
||||
------------
|
||||
ctx: discord_slash.context.SlashContext
|
||||
ctx: interactions.SlashContext
|
||||
The context of the command.
|
||||
"""
|
||||
await self.bot.defer(ctx)
|
||||
@ -104,14 +104,14 @@ class Money():
|
||||
self.database["users"].insert_one(new_user)
|
||||
|
||||
# Transfers money from one user to another
|
||||
async def giveMoney(self, ctx: discord_slash.context.SlashContext,
|
||||
async def giveMoney(self, ctx: interactions.SlashContext,
|
||||
user: discord.User, amount: int):
|
||||
"""
|
||||
Give someone else money from your account.
|
||||
|
||||
*Parameters*
|
||||
------------
|
||||
ctx: discord_slash.context.SlashContext
|
||||
ctx: interactions.SlashContext
|
||||
The context of the command.
|
||||
user: discord.User
|
||||
The user to give money.
|
@ -11,7 +11,7 @@ import json # Used to read data from api
|
||||
import random # Used to shuffle answers
|
||||
import asyncio # Used to sleep
|
||||
|
||||
from discord_slash.context import SlashContext # Used for type hints
|
||||
from interactions import SlashContext # Used for type hints
|
||||
|
||||
|
||||
class Trivia():
|
@ -5,7 +5,7 @@ from PIL import Image, ImageDraw
|
||||
|
||||
from .game_base import DatabaseGame, BaseDrawer
|
||||
|
||||
from gwendolyn.exceptions import GameNotInDatabase
|
||||
from gwendolyn_old.exceptions import GameNotInDatabase
|
||||
|
||||
IMAGE_MARGIN = 90
|
||||
SQUARE_SIZE = 150
|
@ -2,7 +2,7 @@ import math
|
||||
import json
|
||||
import discord
|
||||
|
||||
from gwendolyn.utils import cap
|
||||
from gwendolyn_old.utils import cap
|
||||
|
||||
STATS = [
|
||||
"strength",
|
@ -7,11 +7,11 @@ import imdb
|
||||
import discord
|
||||
import xmltodict
|
||||
|
||||
from discord_slash.utils.manage_components import (create_button,
|
||||
from interactions.utils.manage_components import (create_button,
|
||||
create_actionrow)
|
||||
from discord_slash.model import ButtonStyle
|
||||
from interactions.model import ButtonStyle
|
||||
|
||||
from gwendolyn.utils import encode_id
|
||||
from gwendolyn_old.utils import encode_id
|
||||
|
||||
class Plex():
|
||||
"""Container for Plex functions and commands."""
|
132
gwendolyn_old/gwendolyn_client.py
Normal file
@ -0,0 +1,132 @@
|
||||
"""
|
||||
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 discord # Used for discord.Intents and discord.Status
|
||||
import interactions # 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_old.funcs import Money, StarWars, Games, Other, LookupFuncs
|
||||
from gwendolyn_old.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: interactions.SlashContext)
|
||||
defer(ctx: interactions.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()
|
||||
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 = interactions.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): # pylint:disable=no-self-use
|
||||
"""Log a message. Described in utils/util_functions.py."""
|
||||
log_this(messages, channel, level)
|
||||
|
||||
async def stop(self, ctx: interactions.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: interactions.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: interactions.SlashContext):
|
||||
"""Send a "Gwendolyn is thinking" message to the user."""
|
||||
try:
|
||||
await ctx.defer()
|
||||
except interactions.error.AlreadyResponded:
|
||||
self.log("defer failed")
|
BIN
gwendolyn_old/resources/fonts/comic-sans-bold.ttf
Normal file
BIN
gwendolyn_old/resources/fonts/futura-bold.ttf
Normal file
BIN
gwendolyn_old/resources/fonts/times-new-roman.ttf
Normal file
BIN
gwendolyn_old/resources/games/cards/0C.png
Normal file
After Width: | Height: | Size: 38 KiB |
BIN
gwendolyn_old/resources/games/cards/0D.png
Normal file
After Width: | Height: | Size: 30 KiB |
BIN
gwendolyn_old/resources/games/cards/0H.png
Normal file
After Width: | Height: | Size: 29 KiB |
BIN
gwendolyn_old/resources/games/cards/0S.png
Normal file
After Width: | Height: | Size: 30 KiB |
BIN
gwendolyn_old/resources/games/cards/2C.png
Normal file
After Width: | Height: | Size: 18 KiB |
BIN
gwendolyn_old/resources/games/cards/2D.png
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
gwendolyn_old/resources/games/cards/2H.png
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
gwendolyn_old/resources/games/cards/2S.png
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
gwendolyn_old/resources/games/cards/3C.png
Normal file
After Width: | Height: | Size: 22 KiB |
BIN
gwendolyn_old/resources/games/cards/3D.png
Normal file
After Width: | Height: | Size: 20 KiB |
BIN
gwendolyn_old/resources/games/cards/3H.png
Normal file
After Width: | Height: | Size: 20 KiB |
BIN
gwendolyn_old/resources/games/cards/3S.png
Normal file
After Width: | Height: | Size: 19 KiB |
BIN
gwendolyn_old/resources/games/cards/4C.png
Normal file
After Width: | Height: | Size: 23 KiB |
BIN
gwendolyn_old/resources/games/cards/4D.png
Normal file
After Width: | Height: | Size: 18 KiB |
BIN
gwendolyn_old/resources/games/cards/4H.png
Normal file
After Width: | Height: | Size: 19 KiB |
BIN
gwendolyn_old/resources/games/cards/4S.png
Normal file
After Width: | Height: | Size: 18 KiB |
BIN
gwendolyn_old/resources/games/cards/5C.png
Normal file
After Width: | Height: | Size: 27 KiB |
BIN
gwendolyn_old/resources/games/cards/5D.png
Normal file
After Width: | Height: | Size: 21 KiB |
BIN
gwendolyn_old/resources/games/cards/5H.png
Normal file
After Width: | Height: | Size: 23 KiB |
BIN
gwendolyn_old/resources/games/cards/5S.png
Normal file
After Width: | Height: | Size: 21 KiB |
BIN
gwendolyn_old/resources/games/cards/6C.png
Normal file
After Width: | Height: | Size: 30 KiB |
BIN
gwendolyn_old/resources/games/cards/6D.png
Normal file
After Width: | Height: | Size: 25 KiB |
BIN
gwendolyn_old/resources/games/cards/6H.png
Normal file
After Width: | Height: | Size: 26 KiB |
BIN
gwendolyn_old/resources/games/cards/6S.png
Normal file
After Width: | Height: | Size: 24 KiB |
BIN
gwendolyn_old/resources/games/cards/7C.png
Normal file
After Width: | Height: | Size: 31 KiB |
BIN
gwendolyn_old/resources/games/cards/7D.png
Normal file
After Width: | Height: | Size: 25 KiB |
BIN
gwendolyn_old/resources/games/cards/7H.png
Normal file
After Width: | Height: | Size: 26 KiB |
BIN
gwendolyn_old/resources/games/cards/7S.png
Normal file
After Width: | Height: | Size: 24 KiB |
BIN
gwendolyn_old/resources/games/cards/8C.png
Normal file
After Width: | Height: | Size: 36 KiB |
BIN
gwendolyn_old/resources/games/cards/8D.png
Normal file
After Width: | Height: | Size: 29 KiB |
BIN
gwendolyn_old/resources/games/cards/8H.png
Normal file
After Width: | Height: | Size: 29 KiB |
BIN
gwendolyn_old/resources/games/cards/8S.png
Normal file
After Width: | Height: | Size: 29 KiB |
BIN
gwendolyn_old/resources/games/cards/9C.png
Normal file
After Width: | Height: | Size: 37 KiB |
BIN
gwendolyn_old/resources/games/cards/9D.png
Normal file
After Width: | Height: | Size: 30 KiB |
BIN
gwendolyn_old/resources/games/cards/9H.png
Normal file
After Width: | Height: | Size: 29 KiB |
BIN
gwendolyn_old/resources/games/cards/9S.png
Normal file
After Width: | Height: | Size: 29 KiB |
BIN
gwendolyn_old/resources/games/cards/AC.png
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
gwendolyn_old/resources/games/cards/AD.png
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
gwendolyn_old/resources/games/cards/AH.png
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
gwendolyn_old/resources/games/cards/AS.png
Normal file
After Width: | Height: | Size: 28 KiB |
BIN
gwendolyn_old/resources/games/cards/JC.png
Normal file
After Width: | Height: | Size: 174 KiB |
BIN
gwendolyn_old/resources/games/cards/JD.png
Normal file
After Width: | Height: | Size: 178 KiB |
BIN
gwendolyn_old/resources/games/cards/JH.png
Normal file
After Width: | Height: | Size: 182 KiB |
BIN
gwendolyn_old/resources/games/cards/JS.png
Normal file
After Width: | Height: | Size: 178 KiB |
BIN
gwendolyn_old/resources/games/cards/KC.png
Normal file
After Width: | Height: | Size: 158 KiB |
BIN
gwendolyn_old/resources/games/cards/KD.png
Normal file
After Width: | Height: | Size: 168 KiB |
BIN
gwendolyn_old/resources/games/cards/KH.png
Normal file
After Width: | Height: | Size: 180 KiB |
BIN
gwendolyn_old/resources/games/cards/KS.png
Normal file
After Width: | Height: | Size: 176 KiB |
BIN
gwendolyn_old/resources/games/cards/QC.png
Normal file
After Width: | Height: | Size: 179 KiB |
BIN
gwendolyn_old/resources/games/cards/QD.png
Normal file
After Width: | Height: | Size: 183 KiB |
BIN
gwendolyn_old/resources/games/cards/QH.png
Normal file
After Width: | Height: | Size: 190 KiB |
BIN
gwendolyn_old/resources/games/cards/QS.png
Normal file
After Width: | Height: | Size: 160 KiB |
BIN
gwendolyn_old/resources/games/cards/blue_back.png
Normal file
After Width: | Height: | Size: 59 KiB |
BIN
gwendolyn_old/resources/games/cards/gray_back.png
Normal file
After Width: | Height: | Size: 59 KiB |
BIN
gwendolyn_old/resources/games/cards/green_back.png
Normal file
After Width: | Height: | Size: 61 KiB |