3 Commits

Author SHA1 Message Date
ed1ea1f7af 2025-10-28 17:34:32 +01:00
f79a27aaca Merge branch 'complete-rework' of git.ingemanngade.net:NikolajDanger/Gwendolyn into complete-rework 2025-10-28 15:45:36 +01:00
18d7f318f6 2025-10-28 15:42:26 +01:00
44 changed files with 7182 additions and 7142 deletions

View File

@@ -1,7 +1,7 @@
from interactions import Extension, slash_command, SlashContext
from gwendolyn.utils import PARAMS as params
class BetterNeflixExtension(Extension):
class BetterNetflixExtension(Extension):
"""Contains the Better Netflix commands."""
@slash_command(**params["better_netflix"]["movie"])
async def movie(self, ctx: SlashContext):
@@ -9,4 +9,8 @@ class BetterNeflixExtension(Extension):
@slash_command(**params["better_netflix"]["show"])
async def show(self, ctx: SlashContext):
await self.bot.better_netflix.show(ctx)
await self.bot.better_netflix.show(ctx)
@slash_command(**params["better_netflix"]["downloading"])
async def downloading(self, ctx: SlashContext):
await self.bot.better_netflix.downloading(ctx)

23
gwendolyn/ext/games.py Normal file
View File

@@ -0,0 +1,23 @@
import typing
from interactions import Extension, slash_command, SlashContext, User, Client
from gwendolyn.utils import PARAMS as params
if typing.TYPE_CHECKING:
from gwendolyn_client import Gwendolyn
class GamesExtension(Extension):
"""Contains the game commands."""
def dummy(self):
# For type checking:
self.bot: "Gwendolyn"
@slash_command(**params["games"]["money"]["balance"])
async def balance(self, ctx: SlashContext):
await self.bot.money.sendBalance(ctx)
@slash_command(**params["games"]["money"]["give"])
async def give(self, ctx: SlashContext, user: User, amount: int):
await self.bot.money.giveMoney(ctx, user, amount)

View File

@@ -1,6 +1,7 @@
"""A collection of all Gwendolyn functions."""
__all__ = ["Other","BetterNetflix", "Sonarr", "Radarr", "TMDb", "QBittorrent"]
__all__ = ["Other","BetterNetflix", "Sonarr", "Radarr", "TMDb", "QBittorrent", "Money"]
from .other import Other
from .better_netflix import Radarr, Sonarr, BetterNetflix, TMDb, QBittorrent
from .better_netflix import Radarr, Sonarr, BetterNetflix, TMDb, QBittorrent
from .games import Money, Games

View File

@@ -117,7 +117,7 @@ class BetterNetflix():
if "imdb" in picked_movie['ratings']:
description += f"<:imdb:1301506320603676782> {picked_movie['ratings']['imdb']['value']}"
description += "/10"
description += "/10 "
if "rottenTomatoes" in picked_movie['ratings']:
rt_value = picked_movie['ratings']['rottenTomatoes']['value']
@@ -195,7 +195,7 @@ class BetterNetflix():
return progress_bar
message = [""]
message = []
all_downloaded = True
dm_section_title = "*Torrent Downloads*"
@@ -260,222 +260,45 @@ class BetterNetflix():
torrent["last_activity"] < time()-7200):
message.append(torrent_info)
if download_ratio < 1 and torrent["state"] != "stalledDL":
all_downloaded = False
return message
return message, all_downloaded
async def _generate_download_list(self, show_dm, show_movies, show_shows,
episodes):
async def _generate_download_list(self):
"""Generate a list of all torrents.
*Returns*
message_text: str
A formatted list of all torrents
all_downloaded: bool
Whether all torrents are downloaded
"""
self.bot.log("Generating torrent list")
title_width = 100
message = []
title_width = 90
message = self._draw_torrent_list(title_width)
if show_dm:
m, all_downloaded = self._draw_torrent_list(title_width)
message += m
# if show_movies:
# message.append("")
# movies_section_title = "*Missing movies not downloading*"
# movies_section_line = (
# "-"*((title_width-len(movies_section_title))//2)
# )
# message.append(
# movies_section_line+movies_section_title+movies_section_line
# )
# movie_list = requests.get(
# self.radarr_url+"movie?apiKey="+self.credentials["radarr_key"]
# ).json()
# print(
# self.radarr_url+"movie?apiKey="+self.credentials["radarr_key"]
# )
# movie_queue = requests.get(
# self.radarr_url+"queue?apiKey="+self.credentials["radarr_key"]
# ).json()
# movie_queue_ids = []
# for queue_item in movie_queue["records"]:
# movie_queue_ids.append(queue_item["movieId"])
# for movie in movie_list:
# if (not movie["hasFile"] and
# movie["id"] not in movie_queue_ids):
# movie_name = movie["title"]
# if len(movie_name) > 40:
# if movie_name[36] == " ":
# movie_name = movie_name[:36]+"...."
# else:
# movie_name = movie_name[:37]+"..."
# while len(movie_name) < 41:
# movie_name += " "
# if movie["monitored"]:
# movie_info = movie_name+"Could not find a torrent"
# else:
# movie_info = self.long_strings["No torrent"].format(
# movie_name
# )
# message.append(movie_info)
# if show_shows:
# message.append("")
# show_section_title = "*Missing shows not downloading*"
# show_section_line = "-"*((title_width-len(show_section_title))//2)
# message.append(
# show_section_line+show_section_title+show_section_line
# )
# show_list = requests.get(
# self.sonarr_url+"series?apiKey="+self.credentials["sonarr_key"]
# ).json()
# for show in show_list:
# if show["seasons"][0]["seasonNumber"] == 0:
# seasons = show["seasons"][1:]
# else:
# seasons = show["seasons"]
# if any(
# (
# i["statistics"]["episodeCount"] !=
# i["statistics"]["totalEpisodeCount"]
# ) for i in seasons):
# if all(
# i["statistics"]["episodeCount"] == 0 for i in seasons
# ):
# message.append(show["title"] + " (all episodes)")
# else:
# if episodes:
# missing_episodes = sum(
# (i["statistics"]["totalEpisodeCount"] -
# i["statistics"]["episodeCount"])
# for i in seasons)
# message.append(
# f"{show['title']} ({missing_episodes} episodes)"
# )
message.append("-"*title_width)
message_text = "```"+"\n".join(message[1:])+"```"
message_text = "```"+"\n".join(message)+"```"
if message_text == "``````":
message_text = self.long_strings["No torrents downloading"]
return message_text, all_downloaded
return message_text
# async def downloading(self, ctx, content):
# """Send message with list of all downloading torrents."""
# async def send_long_message(ctx,message_text):
# if len(message_text) <= 1994:
# await ctx.send("```"+message_text+"```")
# else:
# cut_off_index = message_text[:1994].rfind("\n")
# await ctx.send("```"+message_text[:cut_off_index]+"```")
# await send_long_message(ctx,message_text[cut_off_index+1:])
async def downloading(self, ctx: SlashContext):
"""Send message with list of all downloading torrents."""
async def send_long_message(ctx,message_text):
if len(message_text) <= 1994:
await ctx.send("```"+message_text+"```")
else:
cut_off_index = message_text[:1994].rfind("\n")
await ctx.send("```"+message_text[:cut_off_index]+"```")
await send_long_message(ctx,message_text[cut_off_index+1:])
# await self.bot.defer(ctx)
await ctx.defer()
# # showDM, showMovies, showShows, episodes
# parameters = [False, False, False, False]
# show_dm_args = ["d", "dm", "downloading", "downloadmanager"]
# show_movies_args = ["m", "movies"]
# show_shows_args = ["s", "shows", "series"]
# show_episode_args = ["e", "episodes"]
# arg_list = [
# show_dm_args, show_movies_args, show_shows_args, show_episode_args
# ]
# input_args = []
# valid_arguments = True
message_text = await self._generate_download_list()
if not message_text.startswith("```"):
await ctx.send(message_text)
# while content != "" and valid_arguments:
# if content[0] == " ":
# content = content[1:]
# elif content[0] == "-":
# if content[1] == "-":
# arg_start = 2
# if " " in content:
# arg_stop = content.find(" ")
# else:
# arg_stop = None
# else:
# arg_start = 1
# arg_stop = 2
elif len(message_text) > 2000:
message_text = message_text[3:-3]
await send_long_message(ctx,message_text)
# input_args.append(content[arg_start:arg_stop])
# if arg_stop is None:
# content = ""
# else:
# content = content[arg_stop:]
# else:
# valid_arguments = False
else:
await ctx.send(message_text)
# if valid_arguments:
# for arg_index, arg_aliases in enumerate(arg_list):
# arg_in_input = [i in input_args for i in arg_aliases]
# if any(arg_in_input):
# input_args.remove(arg_aliases[arg_in_input.index(True)])
# parameters[arg_index] = True
# if len(input_args) != 0 or (not parameters[2] and parameters[3]):
# valid_arguments = False
# show_anything = any(i for i in parameters)
# if not (valid_arguments and show_anything):
# await ctx.send(self.long_strings["Invalid parameters"])
# else:
# message_text, all_downloaded = await self.__generate_download_list(
# *parameters
# )
# if not message_text.startswith("```"):
# await ctx.send(message_text)
# elif len(message_text) > 2000:
# message_text = message_text[3:-3]
# await send_long_message(ctx,message_text)
# elif all_downloaded:
# await ctx.send(message_text)
# else:
# updates_left = 60
# message_text = self.long_strings["Update"].format(
# message_text[:-3], ceil(updates_left/6)
# )
# old_message = await ctx.send(message_text)
# while ((not all_downloaded) and updates_left > 0):
# await asyncio.sleep(10)
# updates_left -= 1
# message_text, all_downloaded = await (
# self.__generate_download_list(*parameters)
# )
# message_text = self.long_strings["Update"].format(
# message_text[:-3],
# ceil(updates_left/6)
# )
# await old_message.edit(content = message_text)
# message_text, all_downloaded = await (
# self.__generate_download_list(*parameters)
# )
# if message_text.startswith("```"):
# if all_downloaded:
# self.bot.log("All torrents are downloaded")
# else:
# message_text = self.long_strings["No updates"].format(
# message_text[:-3]
# )
# self.bot.log("The message updated 20 times")
# await old_message.edit(content = message_text)

View File

@@ -0,0 +1,11 @@
"""Game functions for Gwendolyn."""
__all__ = ["Money", "Games"]
from .money import Money
class Games():
def __init__(self, bot):
"""Initialize the class."""
self.bot = bot
self.database = bot.database

View File

@@ -0,0 +1,140 @@
"""
Contains the code that deals with money.
*Classes*
---------
Money
Deals with money.
"""
import typing
import interactions # Used for typehints
if typing.TYPE_CHECKING:
from gwendolyn_client import Gwendolyn
class Money():
"""
Deals with money.
*Methods*
---------
checkBalance(user: str)
sendBalance(ctx: interactions.SlashContext)
addMoney(user: str, amount: int)
giveMoney(ctx: interactions.SlashContext, user: discord.User,
amount: int)
*Attributes*
------------
bot: Gwendolyn
The instance of Gwendolyn
database: pymongo.Client
The mongo database
"""
def __init__(self, bot: "Gwendolyn"):
"""Initialize the class."""
self.bot = bot
self.database = bot.database
def checkBalance(self, user: str):
"""
Get the account balance of a user.
*Parameters*
------------
user: str
The user to get the balance of.
*Returns*
---------
balance: int
The balance of the user's account.
"""
self.bot.log("checking "+user+"'s account balance")
user_data = self.database["users"].find_one({"_id": user})
if user_data is not None:
return user_data["money"]
else:
return 0
async def sendBalance(self, ctx: interactions.SlashContext):
"""
Get your own account balance.
*Parameters*
------------
ctx: interactions.SlashContext
The context of the command.
"""
await ctx.defer()
response = self.checkBalance("#"+str(ctx.author.id))
user_name = ctx.author.display_name
if response == 1:
new_message = f"{user_name} has 1 GwendoBuck"
else:
new_message = f"{user_name} has {response} GwendoBucks"
await ctx.send(new_message)
# Adds money to the account of a user
def addMoney(self, user: interactions.User, amount: int):
"""
Add money to a user account.
*Parameters*
------------
user: User
The user to give money.
amount: int
The amount to add to the user's account.
"""
self.bot.log(f"adding {amount} to {user}'s account")
user_id = f"#{user.id}"
user_data = self.database["users"].find_one({"_id": user_id})
if user_data is not None:
updater = {"$inc": {"money": amount}}
self.database["users"].update_one({"_id": user_id}, updater)
else:
new_user = {
"_id": user_id,
"user name": user.display_name,
"money": amount
}
self.database["users"].insert_one(new_user)
# Transfers money from one user to another
async def giveMoney(self, ctx: interactions.SlashContext,
user: interactions.User, amount: int):
"""
Give someone else money from your account.
*Parameters*
------------
ctx: interactions.SlashContext
The context of the command.
user: interactions.User
The user to give money.
amount: int
The amount to transfer.
"""
await ctx.defer()
username = user.display_name
userid = f"#{ctx.author.id}"
user_data = self.database["users"].find_one({"_id": userid})
if amount <= 0:
self.bot.log("They tried to steal")
await ctx.send("Yeah, no. You can't do that")
elif user_data is None or user_data["money"] < amount:
self.bot.log("They didn't have enough GwendoBucks")
await ctx.send("You don't have that many GwendoBuck")
else:
self.addMoney(ctx.author, -1 * amount)
self.addMoney(user, amount)
await ctx.send(f"Transferred {amount} GwendoBucks to {username}")

View File

@@ -7,59 +7,59 @@ from .name_generator import NameGenerator
from .roll import DieRoller
def gen_help_text(commands: list[SlashCommand]):
return '\n'.join([f"`/{i.name}`\t{i.description}" for i in commands])
return '\n'.join(sorted([f"`/{i.name}`\t{i.description}" for i in commands]))
class Other():
def __init__(self, bot):
self.bot = bot
self._name_generator = NameGenerator()
self._roller = DieRoller()
def __init__(self, bot):
self.bot = bot
self._name_generator = NameGenerator()
self._roller = DieRoller()
# Responds with a greeting of a time-appropriate maner
async def hello_func(self, ctx: SlashContext):
def time_in_range(start, end, i):
# Return true if i is in the range [start, end]
if start <= end:
return start <= i <= end
else:
return start <= i or i <= end
# Responds with a greeting of a time-appropriate maner
async def hello_func(self, ctx: SlashContext):
def time_in_range(start, end, i):
# Return true if i is in the range [start, end]
if start <= end:
return start <= i <= end
else:
return start <= i or i <= end
author = ctx.author.display_name
now = datetime.datetime.now()
if time_in_range(now.replace(hour=5, minute=0, second=0, microsecond=0),now.replace(hour=10, minute=0, second=0, microsecond=0), now):
send_message = "Good morning, "+str(author)
elif time_in_range(now.replace(hour=13, minute=0, second=0, microsecond=0),now.replace(hour=18, minute=0, second=0, microsecond=0), now):
send_message = "Good afternoon, "+str(author)
elif time_in_range(now.replace(hour=18, minute=0, second=0, microsecond=0),now.replace(hour=22, minute=0, second=0, microsecond=0), now):
send_message = "Good evening, "+str(author)
elif time_in_range(now.replace(hour=22, minute=0, second=0, microsecond=0),now.replace(hour=23, minute=59, second=59, microsecond=0), now):
send_message = "Good night, "+str(author)
else:
send_message = "Hello, "+str(author)
author = ctx.author.display_name
now = datetime.datetime.now()
if time_in_range(now.replace(hour=5, minute=0, second=0, microsecond=0),now.replace(hour=10, minute=0, second=0, microsecond=0), now):
send_message = "Good morning, "+str(author)
elif time_in_range(now.replace(hour=13, minute=0, second=0, microsecond=0),now.replace(hour=18, minute=0, second=0, microsecond=0), now):
send_message = "Good afternoon, "+str(author)
elif time_in_range(now.replace(hour=18, minute=0, second=0, microsecond=0),now.replace(hour=22, minute=0, second=0, microsecond=0), now):
send_message = "Good evening, "+str(author)
elif time_in_range(now.replace(hour=22, minute=0, second=0, microsecond=0),now.replace(hour=23, minute=59, second=59, microsecond=0), now):
send_message = "Good night, "+str(author)
else:
send_message = "Hello, "+str(author)
await ctx.send(send_message)
await ctx.send(send_message)
async def help_func(self, ctx: SlashContext, command: str):
if command == "":
text = gen_help_text([i for i in self.bot.application_commands if isinstance(i,SlashCommand)])
embed = Embed(title = "Help", description = text,color = 0x59f442)
await ctx.send(embed = embed)
else:
self.bot.log(f"Looking for help-{command}.txt",str(ctx.channel_id))
try:
with open(f"gwendolyn/resources/help/help-{command}.txt",encoding="utf-8") as file_pointer:
text = file_pointer.read()
embed = Embed(title = command.capitalize(), description = text,color = 0x59f442)
await ctx.send(embed = embed)
except:
await ctx.send(f"Could not find a help file for the command '/{command}'")
async def help_func(self, ctx: SlashContext, command: str):
if command == "":
text = gen_help_text([i for i in self.bot.application_commands if isinstance(i,SlashCommand)])
embed = Embed(title = "Help", description = text,color = 0x59f442)
await ctx.send(embed = embed)
else:
self.bot.log(f"Looking for help-{command}.txt",str(ctx.channel_id))
try:
with open(f"gwendolyn/resources/help/help-{command}.txt",encoding="utf-8") as file_pointer:
text = file_pointer.read()
embed = Embed(title = command.capitalize(), description = text,color = 0x59f442)
await ctx.send(embed = embed)
except:
await ctx.send(f"Could not find a help file for the command '/{command}'")
async def generate_name(self, ctx: SlashContext):
await ctx.send(self._name_generator.generate())
async def generate_name(self, ctx: SlashContext):
await ctx.send(self._name_generator.generate())
async def roll_dice(self, ctx: SlashContext, dice: str):
try:
roll = self._roller.roll(dice)
await ctx.send(f":game_die:Rolling dice `{dice}`\n{roll}")
except:
await ctx.send("There was an error in the rolling")
async def roll_dice(self, ctx: SlashContext, dice: str):
try:
roll = self._roller.roll(dice)
await ctx.send(f":game_die:Rolling dice `{dice}`\n{roll}")
except:
await ctx.send("There was an error in the rolling")

View File

@@ -6,77 +6,85 @@ from pymongo import MongoClient # Used for database management
from gwendolyn.utils import log
from gwendolyn.exceptions import NoToken, CannotConnectToService
from gwendolyn.funcs import Other, BetterNetflix, Sonarr, Radarr, TMDb, QBittorrent
from gwendolyn.funcs import Other, BetterNetflix, Sonarr, Radarr, TMDb, QBittorrent, Money, Games
class Gwendolyn(Client):
def __init__(self):
"""Initialize the bot."""
initiation_parameters = {
"status": Status.DND,
"delete_unused_application_cmds": True,
"sync_interactions": True
}
super().__init__(**initiation_parameters)
def __init__(self):
"""Initialize the bot."""
initiation_parameters = {
"status": Status.DND,
"delete_unused_application_cmds": True,
"sync_interactions": True
}
super().__init__(**initiation_parameters)
self._add_clients_and_options()
self._add_functions()
self._add_extensions()
self._add_clients_and_options()
self._add_functions()
self._add_extensions()
def _add_clients_and_options(self):
"""Add all the client, option and credentials objects."""
load_dotenv()
self.testing = getenv("GWENDOLYN_TESTING", "False").lower() in ('true', '1', 't')
self.enable_nework_services = getenv("NETWORK_SERVICES", "False").lower() in ('true', '1', 't')
def _add_clients_and_options(self):
"""Add all the client, option and credentials objects."""
load_dotenv()
self.testing = getenv("GWENDOLYN_TESTING", "False").lower() in ('true', '1', 't')
if self.testing:
self.log("Testing mode", level=25)
self.bot_token = getenv("DISCORD_TOKEN")
self.enable_nework_services = getenv("NETWORK_SERVICES", "False").lower() in ('true', '1', 't')
if self.bot_token == "TOKEN":
raise NoToken()
self.bot_token = getenv("DISCORD_TOKEN")
self.admins = getenv("ADMINS").split(",")
if self.bot_token == "TOKEN":
raise NoToken()
mongo_user = getenv("MONGODB_USER")
mongo_password = getenv("MONGODB_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)
self.admins = getenv("ADMINS").split(",")
try:
database_client.admin.command("ping")
self.log("Connected to Mango Client")
except:
raise CannotConnectToService("Mango Client")
mongo_user = getenv("MONGODB_USER")
mongo_password = getenv("MONGODB_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.testing:
self.log("Testing mode")
self.database = database_client["Gwendolyn-Test"]
self.load_extension("interactions.ext.jurigged")
else:
self.database = database_client["Gwendolyn"]
try:
database_client.admin.command("ping")
self.log("Connected to Mango Client")
except:
raise CannotConnectToService("Mango Client")
def _add_functions(self):
self.other = Other(self)
if self.enable_nework_services:
self.better_netflix = BetterNetflix(
self,
radarr=Radarr(getenv("RADARR_IP"),getenv("RADARR_PORT"),getenv("RADARR_API_KEY")),
sonarr=Sonarr(getenv("SONARR_IP"),getenv("SONARR_PORT"),getenv("SONARR_API_KEY")),
tmdb=TMDb(getenv("TMDB_API_ACCESS_TOKEN")),
qbittorrent=QBittorrent(getenv("QBITTORRENT_IP"),getenv("QBITTORRENT_PORT"),getenv("QBITTORRENT_USERNAME"),getenv("QBITTORRENT_PASSWORD"))
)
if self.testing:
self.log("Testing mode")
self.database = database_client["Gwendolyn-Test"]
else:
self.database = database_client["Gwendolyn"]
def _add_extensions(self):
"""Load cogs."""
for filename in listdir("./gwendolyn/ext"):
if filename.endswith(".py"):
if filename == "better_netflix.py" and not self.enable_nework_services:
continue
def _add_functions(self):
self.other = Other(self)
self.money = Money(self)
if self.enable_nework_services:
self.better_netflix = BetterNetflix(
self,
radarr=Radarr(getenv("RADARR_IP"),getenv("RADARR_PORT"),getenv("RADARR_API_KEY")),
sonarr=Sonarr(getenv("SONARR_IP"),getenv("SONARR_PORT"),getenv("SONARR_API_KEY")),
tmdb=TMDb(getenv("TMDB_API_ACCESS_TOKEN")),
qbittorrent=QBittorrent(
getenv("QBITTORRENT_IP"),
getenv("QBITTORRENT_PORT"),
getenv("QBITTORRENT_USERNAME"),
getenv("QBITTORRENT_PASSWORD")
)
)
self.load_extension(f"gwendolyn.ext.{filename[:-3]}")
def _add_extensions(self):
"""Load cogs."""
for filename in listdir("./gwendolyn/ext"):
if filename.endswith(".py"):
if filename == "better_netflix.py" and not self.enable_nework_services:
continue
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)
self.load_extension(f"gwendolyn.ext.{filename[:-3]}")
def start(self):
super().start(self.bot_token)
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)
def start(self):
super().start(self.bot_token)

View File

@@ -34,7 +34,7 @@
},
"ping" : {
"name" : "ping",
"description" : "Get the Gwendolyn's latency to the server"
"description" : "Get Gwendolyn's latency to the server"
},
"roll" : {
"name": "roll",
@@ -65,6 +65,36 @@
"show": {
"name": "show",
"description": "Get a random show from Better Netflix"
},
"downloading": {
"name": "downloading",
"description": "Get a list of everything being downloaded"
}
},
"games": {
"money": {
"balance" : {
"name" : "balance",
"description" : "See your balance of GwendoBucks"
},
"give" : {
"name" : "give",
"description" : "Give GwendoBucks to another user",
"options" : [
{
"name" : "user",
"description" : "The user you're sending GwendoBucks to",
"type" : 6,
"required" : "true"
},
{
"name" : "amount",
"description" : "The number of GwendoBucks you're sending",
"type" : 4,
"required" : "true"
}
]
}
}
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

View File

@@ -3,38 +3,38 @@ from discord.ext import commands # Has the cog class
class EventCog(commands.Cog):
"""Handles bot events."""
"""Handles bot events."""
def __init__(self, bot):
"""Initialize the bot."""
self.bot = bot
self.bot.on_error = self.on_error
def __init__(self, bot):
"""Initialize the bot."""
self.bot = bot
self.bot.on_error = self.on_error
@commands.Cog.listener()
async def on_ready(self):
"""Log and set bot status when bot logs in."""
await self.bot.event_handler.on_ready()
@commands.Cog.listener()
async def on_ready(self):
"""Log and set bot status when bot logs in."""
await self.bot.event_handler.on_ready()
@commands.Cog.listener()
async def on_slash_command(self, ctx):
"""Log when a slash command is run."""
await self.bot.event_handler.on_slash_command(ctx)
@commands.Cog.listener()
async def on_slash_command(self, ctx):
"""Log when a slash command is run."""
await self.bot.event_handler.on_slash_command(ctx)
@commands.Cog.listener()
async def on_slash_command_error(self, ctx, error):
"""Log when a slash error occurs."""
await self.bot.error_handler.on_slash_command_error(ctx, error)
@commands.Cog.listener()
async def on_slash_command_error(self, ctx, error):
"""Log when a slash error occurs."""
await self.bot.error_handler.on_slash_command_error(ctx, error)
async def on_error(self, method, *args, **kwargs): # pylint: disable=unused-argument
"""Log when an error occurs."""
await self.bot.error_handler.on_error(method)
async def on_error(self, method, *args, **kwargs): # pylint: disable=unused-argument
"""Log when an error occurs."""
await self.bot.error_handler.on_error(method)
@commands.Cog.listener()
async def on_component(self, ctx):
"""Handle when someone reacts to a message."""
await self.bot.event_handler.on_component(ctx)
@commands.Cog.listener()
async def on_component(self, ctx):
"""Handle when someone reacts to a message."""
await self.bot.event_handler.on_component(ctx)
def setup(bot):
"""Add the eventcog to the bot."""
bot.add_cog(EventCog(bot))
"""Add the eventcog to the bot."""
bot.add_cog(EventCog(bot))

View File

@@ -8,153 +8,153 @@ params = get_params()
class GamesCog(commands.Cog):
"""Contains miscellaneous game commands."""
"""Contains miscellaneous game commands."""
def __init__(self, bot):
"""Initialize the cog."""
self.bot = bot
def __init__(self, bot):
"""Initialize the cog."""
self.bot = bot
@cog_ext.cog_slash(**params["balance"])
async def balance(self, ctx):
"""Check user balance."""
await self.bot.money.sendBalance(ctx)
@cog_ext.cog_slash(**params["balance"])
async def balance(self, ctx):
"""Check user balance."""
await self.bot.money.sendBalance(ctx)
@cog_ext.cog_slash(**params["give"])
async def give(self, ctx, user, amount):
"""Give another user an amount of GwendoBucks."""
await self.bot.money.giveMoney(ctx, user, amount)
@cog_ext.cog_slash(**params["give"])
async def give(self, ctx, user, amount):
"""Give another user an amount of GwendoBucks."""
await self.bot.money.giveMoney(ctx, user, amount)
@cog_ext.cog_slash(**params["trivia"])
async def trivia(self, ctx, answer=""):
"""Run a game of trivia."""
await self.bot.games.trivia.triviaParse(ctx, answer)
@cog_ext.cog_slash(**params["trivia"])
async def trivia(self, ctx, answer=""):
"""Run a game of trivia."""
await self.bot.games.trivia.triviaParse(ctx, answer)
class BlackjackCog(commands.Cog):
"""Contains the blackjack commands."""
"""Contains the blackjack commands."""
def __init__(self, bot):
"""Initialize the cog."""
self.bot = bot
def __init__(self, bot):
"""Initialize the cog."""
self.bot = bot
@cog_ext.cog_subcommand(**params["blackjack_start"])
async def blackjack_start(self, ctx):
"""Start a game of blackjack."""
await self.bot.games.blackjack.start(ctx)
@cog_ext.cog_subcommand(**params["blackjack_start"])
async def blackjack_start(self, ctx):
"""Start a game of blackjack."""
await self.bot.games.blackjack.start(ctx)
@cog_ext.cog_subcommand(**params["blackjack_bet"])
async def blackjack_bet(self, ctx, bet):
"""Enter the game of blackjack with a bet."""
await self.bot.games.blackjack.enter_game(ctx, bet)
@cog_ext.cog_subcommand(**params["blackjack_bet"])
async def blackjack_bet(self, ctx, bet):
"""Enter the game of blackjack with a bet."""
await self.bot.games.blackjack.enter_game(ctx, bet)
@cog_ext.cog_subcommand(**params["blackjack_hilo"])
async def blackjack_hilo(self, ctx):
"""Get the hilo value for the deck in blackjack."""
await self.bot.games.blackjack.hilo(ctx)
@cog_ext.cog_subcommand(**params["blackjack_hilo"])
async def blackjack_hilo(self, ctx):
"""Get the hilo value for the deck in blackjack."""
await self.bot.games.blackjack.hilo(ctx)
@cog_ext.cog_subcommand(**params["blackjack_shuffle"])
async def blackjack_shuffle(self, ctx):
"""Shuffle the blackjack game."""
await self.bot.games.blackjack.shuffle(ctx)
@cog_ext.cog_subcommand(**params["blackjack_shuffle"])
async def blackjack_shuffle(self, ctx):
"""Shuffle the blackjack game."""
await self.bot.games.blackjack.shuffle(ctx)
@cog_ext.cog_subcommand(**params["blackjack_cards"])
async def blackjack_cards(self, ctx):
"""Get the amount of cards left in the blackjack deck."""
await self.bot.games.blackjack.cards(ctx)
@cog_ext.cog_subcommand(**params["blackjack_cards"])
async def blackjack_cards(self, ctx):
"""Get the amount of cards left in the blackjack deck."""
await self.bot.games.blackjack.cards(ctx)
class ConnectFourCog(commands.Cog):
"""Contains all the connect four commands."""
"""Contains all the connect four commands."""
def __init__(self, bot):
"""Initialize the cog."""
self.bot = bot
def __init__(self, bot):
"""Initialize the cog."""
self.bot = bot
@cog_ext.cog_subcommand(**params["connect_four_start_user"])
async def connect_four_start_user(self, ctx, user):
"""Start a game of connect four against another user."""
await self.bot.games.connect_four.start(ctx, user)
@cog_ext.cog_subcommand(**params["connect_four_start_user"])
async def connect_four_start_user(self, ctx, user):
"""Start a game of connect four against another user."""
await self.bot.games.connect_four.start(ctx, user)
@cog_ext.cog_subcommand(**params["connect_four_start_gwendolyn"])
async def connect_four_start_gwendolyn(self, ctx, difficulty=3):
"""Start a game of connect four against Gwendolyn."""
await self.bot.games.connect_four.start(ctx, difficulty)
@cog_ext.cog_subcommand(**params["connect_four_start_gwendolyn"])
async def connect_four_start_gwendolyn(self, ctx, difficulty=3):
"""Start a game of connect four against Gwendolyn."""
await self.bot.games.connect_four.start(ctx, difficulty)
class HangmanCog(commands.Cog):
"""Contains all the hangman commands."""
"""Contains all the hangman commands."""
def __init__(self, bot):
"""Initialize the cog."""
self.bot = bot
def __init__(self, bot):
"""Initialize the cog."""
self.bot = bot
@cog_ext.cog_slash(**params["hangman"])
async def hangman(self, ctx):
"""Start a game of hangman."""
await self.bot.games.hangman.start(ctx)
@cog_ext.cog_slash(**params["hangman"])
async def hangman(self, ctx):
"""Start a game of hangman."""
await self.bot.games.hangman.start(ctx)
class WordleCog(commands.Cog):
"""Contains all the wordle commands."""
"""Contains all the wordle commands."""
def __init__(self, bot):
"""Initialize the cog."""
self.bot = bot
def __init__(self, bot):
"""Initialize the cog."""
self.bot = bot
@cog_ext.cog_subcommand(**params["wordle_start"])
async def wordle_start(self, ctx, letters = 5):
"""Start a game of wordle."""
await self.bot.games.wordle.start(ctx, letters)
@cog_ext.cog_subcommand(**params["wordle_start"])
async def wordle_start(self, ctx, letters = 5):
"""Start a game of wordle."""
await self.bot.games.wordle.start(ctx, letters)
@cog_ext.cog_subcommand(**params["wordle_guess"])
async def wordle_guess(self, ctx, guess):
"""Start a game of wordle."""
await self.bot.games.wordle.guess(ctx, guess)
@cog_ext.cog_subcommand(**params["wordle_guess"])
async def wordle_guess(self, ctx, guess):
"""Start a game of wordle."""
await self.bot.games.wordle.guess(ctx, guess)
class HexCog(commands.Cog):
"""Contains all the hex commands."""
"""Contains all the hex commands."""
def __init__(self, bot):
"""Initialize the cog."""
self.bot = bot
self.hex = self.bot.games.hex
def __init__(self, bot):
"""Initialize the cog."""
self.bot = bot
self.hex = self.bot.games.hex
@cog_ext.cog_subcommand(**params["hex_start_user"])
async def hex_start_user(self, ctx, user):
"""Start a game of hex against another player."""
await self.hex.start(ctx, user)
@cog_ext.cog_subcommand(**params["hex_start_user"])
async def hex_start_user(self, ctx, user):
"""Start a game of hex against another player."""
await self.hex.start(ctx, user)
@cog_ext.cog_subcommand(**params["hex_start_gwendolyn"])
async def hex_start_gwendolyn(self, ctx, difficulty=2):
"""Start a game of hex against Gwendolyn."""
await self.hex.start(ctx, difficulty)
@cog_ext.cog_subcommand(**params["hex_start_gwendolyn"])
async def hex_start_gwendolyn(self, ctx, difficulty=2):
"""Start a game of hex against Gwendolyn."""
await self.hex.start(ctx, difficulty)
@cog_ext.cog_subcommand(**params["hex_place"])
async def hex_place(self, ctx, coordinates):
"""Place a piece in the hex game."""
await self.hex.placeHex(ctx, coordinates, f"#{ctx.author.id}")
@cog_ext.cog_subcommand(**params["hex_place"])
async def hex_place(self, ctx, coordinates):
"""Place a piece in the hex game."""
await self.hex.placeHex(ctx, coordinates, f"#{ctx.author.id}")
@cog_ext.cog_subcommand(**params["hex_undo"])
async def hex_undo(self, ctx):
"""Undo your last hex move."""
await self.hex.undo(ctx)
@cog_ext.cog_subcommand(**params["hex_undo"])
async def hex_undo(self, ctx):
"""Undo your last hex move."""
await self.hex.undo(ctx)
@cog_ext.cog_subcommand(**params["hex_swap"])
async def hex_swap(self, ctx):
"""Perform a hex swap."""
await self.hex.swap(ctx)
@cog_ext.cog_subcommand(**params["hex_swap"])
async def hex_swap(self, ctx):
"""Perform a hex swap."""
await self.hex.swap(ctx)
@cog_ext.cog_subcommand(**params["hex_surrender"])
async def hex_surrender(self, ctx):
"""Surrender the hex game."""
await self.hex.surrender(ctx)
@cog_ext.cog_subcommand(**params["hex_surrender"])
async def hex_surrender(self, ctx):
"""Surrender the hex game."""
await self.hex.surrender(ctx)
def setup(bot):
"""Add all the cogs to the bot."""
bot.add_cog(GamesCog(bot))
bot.add_cog(BlackjackCog(bot))
bot.add_cog(ConnectFourCog(bot))
bot.add_cog(HangmanCog(bot))
bot.add_cog(HexCog(bot))
bot.add_cog(WordleCog(bot))
"""Add all the cogs to the bot."""
bot.add_cog(GamesCog(bot))
bot.add_cog(BlackjackCog(bot))
bot.add_cog(ConnectFourCog(bot))
bot.add_cog(HangmanCog(bot))
bot.add_cog(HexCog(bot))
bot.add_cog(WordleCog(bot))

View File

@@ -8,25 +8,25 @@ params = get_params()
class LookupCog(commands.Cog):
"""Contains the lookup commands."""
"""Contains the lookup commands."""
def __init__(self, bot):
"""Initialize the cog."""
self.bot = bot
def __init__(self, bot):
"""Initialize the cog."""
self.bot = bot
# Looks up a spell
@cog_ext.cog_slash(**params["spell"])
async def spell(self, ctx, query):
"""Look up a spell."""
await self.bot.lookup_funcs.spell_func(ctx, query)
# Looks up a spell
@cog_ext.cog_slash(**params["spell"])
async def spell(self, ctx, query):
"""Look up a spell."""
await self.bot.lookup_funcs.spell_func(ctx, query)
# Looks up a monster
@cog_ext.cog_slash(**params["monster"])
async def monster(self, ctx, query):
"""Look up a monster."""
await self.bot.lookup_funcs.monster_func(ctx, query)
# Looks up a monster
@cog_ext.cog_slash(**params["monster"])
async def monster(self, ctx, query):
"""Look up a monster."""
await self.bot.lookup_funcs.monster_func(ctx, query)
def setup(bot):
"""Add the cog to the bot."""
bot.add_cog(LookupCog(bot))
"""Add the cog to the bot."""
bot.add_cog(LookupCog(bot))

View File

@@ -9,92 +9,92 @@ params = get_params()
class MiscCog(commands.Cog):
"""Contains the miscellaneous commands."""
"""Contains the miscellaneous commands."""
def __init__(self, bot):
"""Initialize the cog."""
self.bot = bot
self.bot.remove_command("help")
self.generators = bot.other.generators
self.plex = bot.other.plex
self.nerd_shit = bot.other.nerd_shit
def __init__(self, bot):
"""Initialize the cog."""
self.bot = bot
self.bot.remove_command("help")
self.generators = bot.other.generators
self.plex = bot.other.plex
self.nerd_shit = bot.other.nerd_shit
@cog_ext.cog_slash(**params["ping"])
async def ping(self, ctx: SlashContext):
"""Send the bot's latency."""
await ctx.send(f"Pong!\nLatency is {round(self.bot.latency * 1000)}ms")
@cog_ext.cog_slash(**params["ping"])
async def ping(self, ctx: SlashContext):
"""Send the bot's latency."""
await ctx.send(f"Pong!\nLatency is {round(self.bot.latency * 1000)}ms")
@cog_ext.cog_slash(**params["stop"])
async def stop(self, ctx: SlashContext):
"""Stop the bot."""
await self.bot.stop(ctx)
@cog_ext.cog_slash(**params["stop"])
async def stop(self, ctx: SlashContext):
"""Stop the bot."""
await self.bot.stop(ctx)
@cog_ext.cog_slash(**params["help"])
async def help_command(self, ctx: SlashContext, command=""):
"""Get help for commands."""
await self.bot.other.help_func(ctx, command)
@cog_ext.cog_slash(**params["help"])
async def help_command(self, ctx: SlashContext, command=""):
"""Get help for commands."""
await self.bot.other.help_func(ctx, command)
@cog_ext.cog_slash(**params["thank"])
async def thank(self, ctx: SlashContext):
"""Thank the bot."""
await ctx.send("You're welcome :blush:")
@cog_ext.cog_slash(**params["thank"])
async def thank(self, ctx: SlashContext):
"""Thank the bot."""
await ctx.send("You're welcome :blush:")
@cog_ext.cog_slash(**params["hello"])
async def hello(self, ctx: SlashContext):
"""Greet the bot."""
await self.bot.other.hello_func(ctx)
@cog_ext.cog_slash(**params["hello"])
async def hello(self, ctx: SlashContext):
"""Greet the bot."""
await self.bot.other.hello_func(ctx)
@cog_ext.cog_slash(**params["roll"])
async def roll(self, ctx: SlashContext, dice="1d20"):
"""Roll dice."""
await self.bot.other.roll_dice(ctx, dice)
@cog_ext.cog_slash(**params["roll"])
async def roll(self, ctx: SlashContext, dice="1d20"):
"""Roll dice."""
await self.bot.other.roll_dice(ctx, dice)
@cog_ext.cog_slash(**params["image"])
async def image(self, ctx: SlashContext):
"""Get a random image from Bing."""
await self.bot.other.image_func(ctx)
@cog_ext.cog_slash(**params["image"])
async def image(self, ctx: SlashContext):
"""Get a random image from Bing."""
await self.bot.other.image_func(ctx)
@cog_ext.cog_slash(**params["movie"])
async def movie(self, ctx: SlashContext):
"""Get a random movie from the Plex server."""
await self.bot.other.movie_func(ctx)
@cog_ext.cog_slash(**params["movie"])
async def movie(self, ctx: SlashContext):
"""Get a random movie from the Plex server."""
await self.bot.other.movie_func(ctx)
@cog_ext.cog_slash(**params["name"])
async def name(self, ctx: SlashContext):
"""Generate a random name."""
await self.generators.name_gen(ctx)
@cog_ext.cog_slash(**params["name"])
async def name(self, ctx: SlashContext):
"""Generate a random name."""
await self.generators.name_gen(ctx)
@cog_ext.cog_slash(**params["tavern"])
async def tavern(self, ctx: SlashContext):
"""Generate a random tavern name."""
await self.generators.tavern_gen(ctx)
@cog_ext.cog_slash(**params["tavern"])
async def tavern(self, ctx: SlashContext):
"""Generate a random tavern name."""
await self.generators.tavern_gen(ctx)
@cog_ext.cog_slash(**params["wiki"])
async def wiki(self, ctx: SlashContext, wiki_page=""):
"""Get a page on a fandom wiki."""
await self.bot.other.find_wiki_page(ctx, wiki_page)
@cog_ext.cog_slash(**params["wiki"])
async def wiki(self, ctx: SlashContext, wiki_page=""):
"""Get a page on a fandom wiki."""
await self.bot.other.find_wiki_page(ctx, wiki_page)
@cog_ext.cog_slash(**params["add_movie"])
async def add_movie(self, ctx: SlashContext, movie):
"""Search for a movie and add it to the Plex server."""
await self.plex.request_movie(ctx, movie)
@cog_ext.cog_slash(**params["add_movie"])
async def add_movie(self, ctx: SlashContext, movie):
"""Search for a movie and add it to the Plex server."""
await self.plex.request_movie(ctx, movie)
@cog_ext.cog_slash(**params["add_show"])
async def add_show(self, ctx: SlashContext, show):
"""Search for a show and add it to the Plex server."""
await self.plex.request_show(ctx, show)
@cog_ext.cog_slash(**params["add_show"])
async def add_show(self, ctx: SlashContext, show):
"""Search for a show and add it to the Plex server."""
await self.plex.request_show(ctx, show)
@cog_ext.cog_slash(**params["downloading"])
async def downloading(self, ctx: SlashContext, parameters="-d"):
"""Get the current downloading torrents."""
await self.plex.downloading(ctx, parameters)
@cog_ext.cog_slash(**params["downloading"])
async def downloading(self, ctx: SlashContext, parameters="-d"):
"""Get the current downloading torrents."""
await self.plex.downloading(ctx, parameters)
@cog_ext.cog_slash(**params["wolf"])
async def wolf(self, ctx: SlashContext, query):
"""Perform a search on Wolfram Alpha."""
await self.nerd_shit.wolf_search(ctx, query)
@cog_ext.cog_slash(**params["wolf"])
async def wolf(self, ctx: SlashContext, query):
"""Perform a search on Wolfram Alpha."""
await self.nerd_shit.wolf_search(ctx, query)
def setup(bot):
"""Add the cog to the bot."""
bot.add_cog(MiscCog(bot))
"""Add the cog to the bot."""
bot.add_cog(MiscCog(bot))

View File

@@ -8,33 +8,33 @@ params = get_params()
class StarWarsCog(commands.Cog):
"""Contains the Star Wars commands."""
"""Contains the Star Wars commands."""
def __init__(self, bot):
"""Initialize the cog."""
self.bot = bot
def __init__(self, bot):
"""Initialize the cog."""
self.bot = bot
@cog_ext.cog_slash(**params["star_wars_roll"])
async def star_wars_roll(self, ctx, dice=""):
"""Roll Star Wars dice."""
await self.bot.star_wars.roll.parseRoll(ctx, dice)
@cog_ext.cog_slash(**params["star_wars_roll"])
async def star_wars_roll(self, ctx, dice=""):
"""Roll Star Wars dice."""
await self.bot.star_wars.roll.parseRoll(ctx, dice)
@cog_ext.cog_slash(**params["star_wars_destiny"])
async def star_wars_destiny(self, ctx, parameters=""):
"""Control Star Wars destiny points."""
await self.bot.star_wars.destiny.parseDestiny(ctx, parameters)
@cog_ext.cog_slash(**params["star_wars_destiny"])
async def star_wars_destiny(self, ctx, parameters=""):
"""Control Star Wars destiny points."""
await self.bot.star_wars.destiny.parseDestiny(ctx, parameters)
@cog_ext.cog_slash(**params["star_wars_crit"])
async def star_wars_crit(self, ctx, severity: int = 0):
"""Roll for critical injuries."""
await self.bot.star_wars.roll.critRoll(ctx, severity)
@cog_ext.cog_slash(**params["star_wars_crit"])
async def star_wars_crit(self, ctx, severity: int = 0):
"""Roll for critical injuries."""
await self.bot.star_wars.roll.critRoll(ctx, severity)
@cog_ext.cog_slash(**params["star_wars_character"])
async def star_wars_character(self, ctx, parameters=""):
"""Access and change Star Wars character sheet data."""
await self.bot.star_wars.character.parseChar(ctx, parameters)
@cog_ext.cog_slash(**params["star_wars_character"])
async def star_wars_character(self, ctx, parameters=""):
"""Access and change Star Wars character sheet data."""
await self.bot.star_wars.character.parseChar(ctx, parameters)
def setup(bot):
"""Add the cog to the bot."""
bot.add_cog(StarWarsCog(bot))
"""Add the cog to the bot."""
bot.add_cog(StarWarsCog(bot))

View File

@@ -1,11 +1,11 @@
"""Exceptions for Gwendolyn"""
class GameNotInDatabase(Exception):
def __init__(self, game: str, channel: str):
self.message = f"There is no {game} game in channel {channel}"
super().__init__(self.message)
def __init__(self, game: str, channel: str):
self.message = f"There is no {game} game in channel {channel}"
super().__init__(self.message)
class InvalidInteraction(Exception):
def __init__(self, custom_id: str, decoded: str):
self.message = f"{custom_id = }, {decoded = }"
super().__init__(self.message)
def __init__(self, custom_id: str, decoded: str):
self.message = f"{custom_id = }, {decoded = }"
super().__init__(self.message)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -13,306 +13,306 @@ from gwendolyn_old.exceptions import GameNotInDatabase
from gwendolyn_old.utils import encode_id
class GameBase():
"""The base class for the games."""
"""The base class for the games."""
def __init__(self, bot, game_name: int, drawer):
"""Initialize the class."""
self.bot = bot
self.long_strings = self.bot.long_strings
self.resources = "gwendolyn/resources/games/"
self.game_name = game_name
self.draw = drawer(bot, self)
def __init__(self, bot, game_name: int, drawer):
"""Initialize the class."""
self.bot = bot
self.long_strings = self.bot.long_strings
self.resources = "gwendolyn/resources/games/"
self.game_name = game_name
self.draw = drawer(bot, self)
def _get_action_rows(self, buttons: list[tuple[str, list]]):
self.bot.log("Generation action rows")
button_objects = []
for label, data, style in buttons:
custom_id = encode_id([self.game_name] + data)
button_objects.append(Button(
style=style,
label=label,
custom_id=custom_id
))
def _get_action_rows(self, buttons: list[tuple[str, list]]):
self.bot.log("Generation action rows")
button_objects = []
for label, data, style in buttons:
custom_id = encode_id([self.game_name] + data)
button_objects.append(Button(
style=style,
label=label,
custom_id=custom_id
))
action_rows = []
for i in range(((len(button_objects)-1)//5)+1):
action_rows.append(ActionRow(*button_objects[i*5:i*5+5]))
action_rows = []
for i in range(((len(button_objects)-1)//5)+1):
action_rows.append(ActionRow(*button_objects[i*5:i*5+5]))
return action_rows
return action_rows
async def _send_image(self, channel: Messageable,
buttons: list[tuple[str, list]] = None, delete=True):
self.draw.draw(str(channel.id))
file_path = f"{self.resources}images/{self.game_name}{channel.id}.png"
old_image = await channel.send(
file=File(file_path), delete_after=120 if delete else None)
async def _send_image(self, channel: Messageable,
buttons: list[tuple[str, list]] = None, delete=True):
self.draw.draw(str(channel.id))
file_path = f"{self.resources}images/{self.game_name}{channel.id}.png"
old_image = await channel.send(
file=File(file_path), delete_after=120 if delete else None)
if buttons is not None and len(buttons) < 25:
await old_image.edit(components = self._get_action_rows(buttons))
if buttons is not None and len(buttons) < 25:
await old_image.edit(components = self._get_action_rows(buttons))
return old_image
return old_image
class DatabaseGame(GameBase):
"""The base class for the games."""
"""The base class for the games."""
def __init__(self, bot, game_name, drawer):
"""Initialize the class."""
super().__init__(bot, game_name, drawer)
self.database = self.bot.database
self.old_images_path = f"{self.resources}old_images/{self.game_name}"
def __init__(self, bot, game_name, drawer):
"""Initialize the class."""
super().__init__(bot, game_name, drawer)
self.database = self.bot.database
self.old_images_path = f"{self.resources}old_images/{self.game_name}"
def access_document(self, channel: str, collection_name: str="games",
raise_missing_error: bool=True):
collection = self.bot.database[f"{self.game_name} {collection_name}"]
game = collection.find_one({"_id": channel})
if game is None and raise_missing_error:
raise GameNotInDatabase(self.game_name, channel)
def access_document(self, channel: str, collection_name: str="games",
raise_missing_error: bool=True):
collection = self.bot.database[f"{self.game_name} {collection_name}"]
game = collection.find_one({"_id": channel})
if game is None and raise_missing_error:
raise GameNotInDatabase(self.game_name, channel)
return game
return game
def _test_document(self, channel: str, collection_name: str="games"):
collection = self.bot.database[f"{self.game_name} {collection_name}"]
game = collection.find_one({"_id": channel})
return game is not None
def _test_document(self, channel: str, collection_name: str="games"):
collection = self.bot.database[f"{self.game_name} {collection_name}"]
game = collection.find_one({"_id": channel})
return game is not None
def _update_document(self, channel: str, updater: dict,
collection_name: str="games"):
self.database[f"{self.game_name} {collection_name}"].update_one(
{"_id": channel},
updater,
upsert=True
)
def _update_document(self, channel: str, updater: dict,
collection_name: str="games"):
self.database[f"{self.game_name} {collection_name}"].update_one(
{"_id": channel},
updater,
upsert=True
)
def _delete_document(self, channel: str, collection_name: str="games"):
self.database[f"{self.game_name} {collection_name}"].delete_one(
{"_id": channel}
)
def _delete_document(self, channel: str, collection_name: str="games"):
self.database[f"{self.game_name} {collection_name}"].delete_one(
{"_id": channel}
)
def _insert_document(self, data: dict, collection_name: str="games"):
self.database[f"{self.game_name} {collection_name}"].insert_one(data)
def _insert_document(self, data: dict, collection_name: str="games"):
self.database[f"{self.game_name} {collection_name}"].insert_one(data)
async def _delete_old_image(self, channel: Messageable):
with open(self.old_images_path + str(channel.id), "r") as file_pointer:
old_image = await channel.fetch_message(int(file_pointer.read()))
async def _delete_old_image(self, channel: Messageable):
with open(self.old_images_path + str(channel.id), "r") as file_pointer:
old_image = await channel.fetch_message(int(file_pointer.read()))
await old_image.delete()
await old_image.delete()
async def _send_image(self, channel: Messageable,
buttons: list[tuple[str, list]] = None, delete=True):
old_image = await super()._send_image(channel, buttons, delete)
with open(self.old_images_path + str(channel.id), "w") as file_pointer:
file_pointer.write(str(old_image.id))
async def _send_image(self, channel: Messageable,
buttons: list[tuple[str, list]] = None, delete=True):
old_image = await super()._send_image(channel, buttons, delete)
with open(self.old_images_path + str(channel.id), "w") as file_pointer:
file_pointer.write(str(old_image.id))
async def _start_new(self, channel: Messageable, new_game: dict,
buttons: list[tuple[str, list]] = None,
delete = True):
new_game['_id'] = str(channel.id)
self._insert_document(new_game)
await self._send_image(channel, buttons, delete)
async def _start_new(self, channel: Messageable, new_game: dict,
buttons: list[tuple[str, list]] = None,
delete = True):
new_game['_id'] = str(channel.id)
self._insert_document(new_game)
await self._send_image(channel, buttons, delete)
async def _end_game(self, channel: Messageable):
await self._delete_old_image(channel)
await self._send_image(channel, delete=False)
self._delete_document(str(channel.id))
async def _end_game(self, channel: Messageable):
await self._delete_old_image(channel)
await self._send_image(channel, delete=False)
self._delete_document(str(channel.id))
class CardGame(DatabaseGame):
"""The class for card games."""
def __init__(self, bot, game_name, drawer, deck_used):
"""Initialize the class."""
super().__init__(bot, game_name, drawer)
self.decks_used = deck_used
"""The class for card games."""
def __init__(self, bot, game_name, drawer, deck_used):
"""Initialize the class."""
super().__init__(bot, game_name, drawer)
self.decks_used = deck_used
def _shuffle_cards(self, channel: str):
self.bot.log(f"Shuffling cards for {self.game_name}")
with open(f"{self.resources}deck_of_cards.txt", "r") as file_pointer:
deck = file_pointer.read()
def _shuffle_cards(self, channel: str):
self.bot.log(f"Shuffling cards for {self.game_name}")
with open(f"{self.resources}deck_of_cards.txt", "r") as file_pointer:
deck = file_pointer.read()
all_decks = deck.split("\n") * self.decks_used
random.shuffle(all_decks)
all_decks = deck.split("\n") * self.decks_used
random.shuffle(all_decks)
self._update_document(
channel,
{"$set": {"_id": channel, "cards": all_decks}},
"cards"
)
self._update_document(
channel,
{"$set": {"_id": channel, "cards": all_decks}},
"cards"
)
def _draw_card(self, channel: str):
"""
Draw a card from the stack.
def _draw_card(self, channel: str):
"""
Draw a card from the stack.
*Parameters*
------------
channel: str
The id of the channel the card is drawn in.
"""
self.bot.log("drawing a card")
*Parameters*
------------
channel: str
The id of the channel the card is drawn in.
"""
self.bot.log("drawing a card")
drawn_card = self.access_document(channel, "cards")["cards"][0]
self._update_document(channel, {"$pop": {"cards": -1}}, "cards")
drawn_card = self.access_document(channel, "cards")["cards"][0]
self._update_document(channel, {"$pop": {"cards": -1}}, "cards")
return drawn_card
return drawn_card
class BoardGame(GameBase):
async def _test_opponent(self, ctx: IntCont, opponent: Union[int, User]):
if isinstance(opponent, int):
# Opponent is Gwendolyn
if opponent in range(1, 6):
difficulty = int(opponent)
difficulty_text = f" with difficulty {difficulty}"
opponent = self.bot.user.id
else:
await ctx.send("Difficulty doesn't exist")
self.bot.log("They challenged a difficulty that doesn't exist")
return False
elif isinstance(opponent, User):
if opponent.bot:
# User has challenged a bot
if opponent == self.bot.user:
# It was Gwendolyn
difficulty = 3
difficulty_text = f" with difficulty {difficulty}"
opponent = self.bot.user.id
else:
await ctx.send("You can't challenge a bot!")
self.bot.log("They tried to challenge a bot")
return False
else:
# Opponent is another player
if ctx.author != opponent:
opponent = opponent.id
difficulty = 5
difficulty_text = ""
else:
await ctx.send("You can't play against yourself")
self.bot.log("They tried to play against themself")
return False
async def _test_opponent(self, ctx: IntCont, opponent: Union[int, User]):
if isinstance(opponent, int):
# Opponent is Gwendolyn
if opponent in range(1, 6):
difficulty = int(opponent)
difficulty_text = f" with difficulty {difficulty}"
opponent = self.bot.user.id
else:
await ctx.send("Difficulty doesn't exist")
self.bot.log("They challenged a difficulty that doesn't exist")
return False
elif isinstance(opponent, User):
if opponent.bot:
# User has challenged a bot
if opponent == self.bot.user:
# It was Gwendolyn
difficulty = 3
difficulty_text = f" with difficulty {difficulty}"
opponent = self.bot.user.id
else:
await ctx.send("You can't challenge a bot!")
self.bot.log("They tried to challenge a bot")
return False
else:
# Opponent is another player
if ctx.author != opponent:
opponent = opponent.id
difficulty = 5
difficulty_text = ""
else:
await ctx.send("You can't play against yourself")
self.bot.log("They tried to play against themself")
return False
return opponent, (difficulty, difficulty_text)
return opponent, (difficulty, difficulty_text)
class BaseDrawer():
"""Class for drawing games."""
def __init__(self, bot, game: GameBase):
self.bot = bot
self.game = game
self.fonts_path = "gwendolyn/resources/fonts/"
self.font_name = "futura-bold"
"""Class for drawing games."""
def __init__(self, bot, game: GameBase):
self.bot = bot
self.game = game
self.fonts_path = "gwendolyn/resources/fonts/"
self.font_name = "futura-bold"
self.resources = game.resources
game_name = game.game_name
self.default_image = f"{self.resources}default_images/{game_name}.png"
self.default_size = None
self.default_color = None
self.images_path = f"{self.resources}images/{game_name}"
self.resources = game.resources
game_name = game.game_name
self.default_image = f"{self.resources}default_images/{game_name}.png"
self.default_size = None
self.default_color = None
self.images_path = f"{self.resources}images/{game_name}"
def _get_size(self, game: dict):
return self.default_size
def _get_size(self, game: dict):
return self.default_size
def _draw_image(self, game: dict, image: Image.Image):
pass
def _draw_image(self, game: dict, image: Image.Image):
pass
def draw(self, channel: str):
game = self.game.access_document(channel)
if self.default_image is not None:
image = Image.open(self.default_image)
else:
image = Image.new("RGB", self._get_size(game), self.default_color)
self._draw_image(game, image)
self._save_image(image, channel)
def draw(self, channel: str):
game = self.game.access_document(channel)
if self.default_image is not None:
image = Image.open(self.default_image)
else:
image = Image.new("RGB", self._get_size(game), self.default_color)
self._draw_image(game, image)
self._save_image(image, channel)
def _get_font(self, size: int, font_name: str = None):
if font_name is None:
font_name = self.font_name
return ImageFont.truetype(f"{self.fonts_path}{font_name}.ttf", size)
def _get_font(self, size: int, font_name: str = None):
if font_name is None:
font_name = self.font_name
return ImageFont.truetype(f"{self.fonts_path}{font_name}.ttf", size)
def _adjust_font(self, max_font_size: int, text: str, max_text_size: int,
font_name: str = None):
font_size = max_font_size
font = self._get_font(font_size, font_name)
text_width = font.getsize(text)[0]
def _adjust_font(self, max_font_size: int, text: str, max_text_size: int,
font_name: str = None):
font_size = max_font_size
font = self._get_font(font_size, font_name)
text_width = font.getsize(text)[0]
while text_width > max_text_size:
font_size -= 1
font = self._get_font(font_size, font_name)
text_width = font.getsize(text)[0]
while text_width > max_text_size:
font_size -= 1
font = self._get_font(font_size, font_name)
text_width = font.getsize(text)[0]
return font, font_size
return font, font_size
def _save_image(self, image: Image.Image, channel: str):
self.bot.log("Saving image")
image.save(f"{self.images_path}{channel}.png")
def _save_image(self, image: Image.Image, channel: str):
self.bot.log("Saving image")
image.save(f"{self.images_path}{channel}.png")
def _draw_shadow_text(self, text: str, colors: list[tuple[int, int, int]],
font_size: int):
font = self._get_font(font_size)
offset = font_size//20
shadow_offset = font_size//10
def _draw_shadow_text(self, text: str, colors: list[tuple[int, int, int]],
font_size: int):
font = self._get_font(font_size)
offset = font_size//20
shadow_offset = font_size//10
text_size = list(font.getsize(text))
text_size[0] += 1 + (offset * 2)
text_size[1] += 1 + (offset * 2) + shadow_offset
text_size = list(font.getsize(text))
text_size[0] += 1 + (offset * 2)
text_size[1] += 1 + (offset * 2) + shadow_offset
image = Image.new("RGBA", tuple(text_size), (0, 0, 0, 0))
text_image = ImageDraw.Draw(image)
image = Image.new("RGBA", tuple(text_size), (0, 0, 0, 0))
text_image = ImageDraw.Draw(image)
for color_index, color in enumerate(colors[:-1]):
color_offset = offset//(color_index+1)
if color_index == 0:
color_shadow_offset = shadow_offset
else:
color_shadow_offset = 0
for color_index, color in enumerate(colors[:-1]):
color_offset = offset//(color_index+1)
if color_index == 0:
color_shadow_offset = shadow_offset
else:
color_shadow_offset = 0
for i in range(4):
x_pos = [-1,1][i % 2] * color_offset
y_pos = [-1,1][(i//2) % 2] * color_offset + color_shadow_offset
position = (offset + x_pos, offset + y_pos)
text_image.text(position, text, fill=color, font=font)
for i in range(4):
x_pos = [-1,1][i % 2] * color_offset
y_pos = [-1,1][(i//2) % 2] * color_offset + color_shadow_offset
position = (offset + x_pos, offset + y_pos)
text_image.text(position, text, fill=color, font=font)
text_image.text((offset, offset), text, fill=colors[-1], font=font)
text_image.text((offset, offset), text, fill=colors[-1], font=font)
return image
return image
class CardDrawer(BaseDrawer):
def __init__(self, bot, game: GameBase):
super().__init__(bot, game)
self.cards_path = f"{self.resources}cards/"
def __init__(self, bot, game: GameBase):
super().__init__(bot, game)
self.cards_path = f"{self.resources}cards/"
# pylint: disable=invalid-name
self.CARD_WIDTH = 691
self.CARD_HEIGHT = 1065
# pylint: disable=invalid-name
self.CARD_WIDTH = 691
self.CARD_HEIGHT = 1065
self.CARD_BORDER = 100
self.CARD_OFFSET = 125
# pylint: enable=invalid-name
self.CARD_BORDER = 100
self.CARD_OFFSET = 125
# pylint: enable=invalid-name
def _set_card_size(self, wanted_card_width: int):
ratio = wanted_card_width / self.CARD_WIDTH
self.CARD_WIDTH = wanted_card_width
self.CARD_HEIGHT = int(self.CARD_HEIGHT * ratio)
self.CARD_BORDER = int(self.CARD_BORDER * ratio)
self.CARD_OFFSET = int(self.CARD_OFFSET * ratio)
def _set_card_size(self, wanted_card_width: int):
ratio = wanted_card_width / self.CARD_WIDTH
self.CARD_WIDTH = wanted_card_width
self.CARD_HEIGHT = int(self.CARD_HEIGHT * ratio)
self.CARD_BORDER = int(self.CARD_BORDER * ratio)
self.CARD_OFFSET = int(self.CARD_OFFSET * ratio)
def _draw_cards(self, hand: list[str], hidden_cards: int = 0):
image_width = (self.CARD_BORDER * 2) + self.CARD_WIDTH
image_width += (self.CARD_OFFSET * (len(hand)-1))
image_size = (image_width, (self.CARD_BORDER * 2) + self.CARD_HEIGHT)
background = Image.new("RGBA", image_size, (0, 0, 0, 0))
def _draw_cards(self, hand: list[str], hidden_cards: int = 0):
image_width = (self.CARD_BORDER * 2) + self.CARD_WIDTH
image_width += (self.CARD_OFFSET * (len(hand)-1))
image_size = (image_width, (self.CARD_BORDER * 2) + self.CARD_HEIGHT)
background = Image.new("RGBA", image_size, (0, 0, 0, 0))
for i, card in enumerate(hand):
position = (
self.CARD_BORDER + (self.CARD_OFFSET*i),
self.CARD_BORDER
)
for i, card in enumerate(hand):
position = (
self.CARD_BORDER + (self.CARD_OFFSET*i),
self.CARD_BORDER
)
if i + hidden_cards < len(hand):
card_image = Image.open(f"{self.cards_path}{card.upper()}.png")
else:
card_image = Image.open(f"{self.cards_path}red_back.png")
if i + hidden_cards < len(hand):
card_image = Image.open(f"{self.cards_path}{card.upper()}.png")
else:
card_image = Image.open(f"{self.cards_path}red_back.png")
card_image = card_image.resize(
(self.CARD_WIDTH, self.CARD_HEIGHT),
resample=Image.BILINEAR
)
background.paste(card_image, position, card_image)
card_image = card_image.resize(
(self.CARD_WIDTH, self.CARD_HEIGHT),
resample=Image.BILINEAR
)
background.paste(card_image, position, card_image)
return background
return background

View File

@@ -3,8 +3,8 @@ Has a container for game functions.
*Classes*
---------
Games
Container for game functions.
Games
Container for game functions.
"""
@@ -17,30 +17,30 @@ from .wordle import WordleGame
class Games():
"""
Contains game classes.
"""
Contains game classes.
*Attributes*
------------
bot: Gwendolyn
The instance of Gwendolyn.
blackjack
Contains blackjack functions.
connect_four
Contains connect four functions.
hangman
Contains hangman functions.
hex
Contains hex functions
"""
*Attributes*
------------
bot: Gwendolyn
The instance of Gwendolyn.
blackjack
Contains blackjack functions.
connect_four
Contains connect four functions.
hangman
Contains hangman functions.
hex
Contains hex functions
"""
def __init__(self, bot):
"""Initialize the container."""
self.bot = bot
def __init__(self, bot):
"""Initialize the container."""
self.bot = bot
self.trivia = Trivia(bot)
self.blackjack = Blackjack(bot)
self.connect_four = ConnectFour(bot)
self.hangman = Hangman(bot)
self.hex = HexGame(bot)
self.wordle = WordleGame(bot)
self.trivia = Trivia(bot)
self.blackjack = Blackjack(bot)
self.connect_four = ConnectFour(bot)
self.hangman = Hangman(bot)
self.hex = HexGame(bot)
self.wordle = WordleGame(bot)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -3,149 +3,149 @@ Contains the code that deals with money.
*Classes*
---------
Money
Deals with money.
Money
Deals with money.
"""
import interactions # Used for typehints
import discord # Used for typehints
class Money():
"""
Deals with money.
*Methods*
---------
checkBalance(user: str)
sendBalance(ctx: interactions.SlashContext)
addMoney(user: str, amount: int)
giveMoney(ctx: interactions.SlashContext, user: discord.User,
amount: int)
*Attributes*
------------
bot: Gwendolyn
The instance of Gwendolyn
database: pymongo.Client
The mongo database
"""
def __init__(self, bot):
"""Initialize the class."""
self.bot = bot
self.database = bot.database
def checkBalance(self, user: str):
"""
Deals with money.
Get the account balance of a user.
*Methods*
---------
checkBalance(user: str)
sendBalance(ctx: interactions.SlashContext)
addMoney(user: str, amount: int)
giveMoney(ctx: interactions.SlashContext, user: discord.User,
amount: int)
*Attributes*
*Parameters*
------------
bot: Gwendolyn
The instance of Gwendolyn
database: pymongo.Client
The mongo database
user: str
The user to get the balance of.
*Returns*
---------
balance: int
The balance of the user's account.
"""
self.bot.log("checking "+user+"'s account balance")
def __init__(self, bot):
"""Initialize the class."""
self.bot = bot
self.database = bot.database
user_data = self.database["users"].find_one({"_id": user})
def checkBalance(self, user: str):
"""
Get the account balance of a user.
if user_data is not None:
return user_data["money"]
else:
return 0
*Parameters*
------------
user: str
The user to get the balance of.
async def sendBalance(self, ctx: interactions.SlashContext):
"""
Get your own account balance.
*Returns*
---------
balance: int
The balance of the user's account.
"""
self.bot.log("checking "+user+"'s account balance")
*Parameters*
------------
ctx: interactions.SlashContext
The context of the command.
"""
await self.bot.defer(ctx)
response = self.checkBalance("#"+str(ctx.author.id))
user_name = ctx.author.display_name
if response == 1:
new_message = f"{user_name} has {response} GwendoBuck"
else:
new_message = f"{user_name} has {response} GwendoBucks"
await ctx.send(new_message)
user_data = self.database["users"].find_one({"_id": user})
# Adds money to the account of a user
def addMoney(self, user: str, amount: int):
"""
Add money to a user account.
if user_data is not None:
return user_data["money"]
else:
return 0
*Parameters*
------------
user: str
The id of the user to give money.
amount: int
The amount to add to the user's account.
"""
self.bot.log("adding "+str(amount)+" to "+user+"'s account")
async def sendBalance(self, ctx: interactions.SlashContext):
"""
Get your own account balance.
user_data = self.database["users"].find_one({"_id": user})
*Parameters*
------------
ctx: interactions.SlashContext
The context of the command.
"""
await self.bot.defer(ctx)
response = self.checkBalance("#"+str(ctx.author.id))
user_name = ctx.author.display_name
if response == 1:
new_message = f"{user_name} has {response} GwendoBuck"
else:
new_message = f"{user_name} has {response} GwendoBucks"
await ctx.send(new_message)
if user_data is not None:
updater = {"$inc": {"money": amount}}
self.database["users"].update_one({"_id": user}, updater)
else:
new_user = {
"_id": user,
"user name": self.bot.database_funcs.get_name(user),
"money": amount
}
self.database["users"].insert_one(new_user)
# Adds money to the account of a user
def addMoney(self, user: str, amount: int):
"""
Add money to a user account.
# Transfers money from one user to another
async def giveMoney(self, ctx: interactions.SlashContext,
user: discord.User, amount: int):
"""
Give someone else money from your account.
*Parameters*
------------
user: str
The id of the user to give money.
amount: int
The amount to add to the user's account.
"""
self.bot.log("adding "+str(amount)+" to "+user+"'s account")
*Parameters*
------------
ctx: interactions.SlashContext
The context of the command.
user: discord.User
The user to give money.
amount: int
The amount to transfer.
"""
await self.bot.defer(ctx)
username = user.display_name
if self.bot.database_funcs.get_id(username) is None:
async for member in ctx.guild.fetch_members(limit=None):
if member.display_name.lower() == username.lower():
username = member.display_name
user_id = f"#{member.id}"
new_user = {
"_id": user_id,
"user name": username,
"money": 0
}
self.bot.database["users"].insert_one(new_user)
user_data = self.database["users"].find_one({"_id": user})
userid = f"#{ctx.author.id}"
user_data = self.database["users"].find_one({"_id": userid})
targetUser = self.bot.database_funcs.get_id(username)
if user_data is not None:
updater = {"$inc": {"money": amount}}
self.database["users"].update_one({"_id": user}, updater)
else:
new_user = {
"_id": user,
"user name": self.bot.database_funcs.get_name(user),
"money": amount
}
self.database["users"].insert_one(new_user)
# Transfers money from one user to another
async def giveMoney(self, ctx: interactions.SlashContext,
user: discord.User, amount: int):
"""
Give someone else money from your account.
*Parameters*
------------
ctx: interactions.SlashContext
The context of the command.
user: discord.User
The user to give money.
amount: int
The amount to transfer.
"""
await self.bot.defer(ctx)
username = user.display_name
if self.bot.database_funcs.get_id(username) is None:
async for member in ctx.guild.fetch_members(limit=None):
if member.display_name.lower() == username.lower():
username = member.display_name
user_id = f"#{member.id}"
new_user = {
"_id": user_id,
"user name": username,
"money": 0
}
self.bot.database["users"].insert_one(new_user)
userid = f"#{ctx.author.id}"
user_data = self.database["users"].find_one({"_id": userid})
targetUser = self.bot.database_funcs.get_id(username)
if amount <= 0:
self.bot.log("They tried to steal")
await ctx.send("Yeah, no. You can't do that")
elif targetUser is None:
self.bot.log("They weren't in the system")
await ctx.send("The target doesn't exist")
elif user_data is None or user_data["money"] < amount:
self.bot.log("They didn't have enough GwendoBucks")
await ctx.send("You don't have that many GwendoBuck")
else:
self.addMoney(f"#{ctx.author.id}", -1 * amount)
self.addMoney(targetUser, amount)
await ctx.send(f"Transferred {amount} GwendoBucks to {username}")
if amount <= 0:
self.bot.log("They tried to steal")
await ctx.send("Yeah, no. You can't do that")
elif targetUser is None:
self.bot.log("They weren't in the system")
await ctx.send("The target doesn't exist")
elif user_data is None or user_data["money"] < amount:
self.bot.log("They didn't have enough GwendoBucks")
await ctx.send("You don't have that many GwendoBuck")
else:
self.addMoney(f"#{ctx.author.id}", -1 * amount)
self.addMoney(targetUser, amount)
await ctx.send(f"Transferred {amount} GwendoBucks to {username}")

View File

@@ -3,8 +3,8 @@ Contains code for trivia games.
*Classes*
---------
Trivia
Contains all the code for the trivia commands.
Trivia
Contains all the code for the trivia commands.
"""
import urllib # Used to get data from api
import json # Used to read data from api
@@ -15,191 +15,191 @@ from interactions import SlashContext # Used for type hints
class Trivia():
"""
Contains the code for trivia games.
"""
Contains the code for trivia games.
*Methods*
*Methods*
---------
triviaStart(channel: str) -> str, str, str
triviaAnswer(user: str, channel: str, command: str) -> str
triviaCountPoints(channel: str)
triviaParse(ctx: SlashContext, answer: str)
"""
def __init__(self, bot):
"""Initialize the class."""
self.bot = bot
def triviaStart(self, channel: str):
"""
Start a game of trivia.
Downloads a question with answers, shuffles the wrong answers
with the correct answer and returns the questions and answers.
Also saves the question in the database.
*Parameters*
------------
channel: str
The id of the channel to start the game in
*Returns*
---------
triviaStart(channel: str) -> str, str, str
triviaAnswer(user: str, channel: str, command: str) -> str
triviaCountPoints(channel: str)
triviaParse(ctx: SlashContext, answer: str)
send_message: str
The message to return to the user.
"""
triviaQuestions = self.bot.database["trivia questions"]
question = triviaQuestions.find_one({"_id": channel})
def __init__(self, bot):
"""Initialize the class."""
self.bot = bot
self.bot.log(f"Trying to find a trivia question for {channel}")
def triviaStart(self, channel: str):
"""
Start a game of trivia.
if question is None:
apiUrl = "https://opentdb.com/api.php?amount=10&type=multiple"
with urllib.request.urlopen(apiUrl) as response:
data = json.loads(response.read())
Downloads a question with answers, shuffles the wrong answers
with the correct answer and returns the questions and answers.
Also saves the question in the database.
question = data["results"][0]["question"]
self.bot.log(f"Found the question \"{question}\"")
answers = data["results"][0]["incorrect_answers"]
answers.append(data["results"][0]["correct_answer"])
random.shuffle(answers)
correctAnswer = data["results"][0]["correct_answer"]
correctAnswer = answers.index(correctAnswer) + 97
*Parameters*
------------
channel: str
The id of the channel to start the game in
newQuestion = {
"_id": channel,
"answer": str(chr(correctAnswer)),
"players": {}
}
triviaQuestions.insert_one(newQuestion)
*Returns*
---------
send_message: str
The message to return to the user.
"""
triviaQuestions = self.bot.database["trivia questions"]
question = triviaQuestions.find_one({"_id": channel})
replacements = {
"&#039;": "\'",
"&quot;": "\"",
"&ldquo;": "\"",
"&rdquo;": "\"",
"&eacute;": "é"
}
question = data["results"][0]["question"]
self.bot.log(f"Trying to find a trivia question for {channel}")
for key, value in replacements.items():
question = question.replace(key, value)
if question is None:
apiUrl = "https://opentdb.com/api.php?amount=10&type=multiple"
with urllib.request.urlopen(apiUrl) as response:
data = json.loads(response.read())
for answer in answers:
for key, value in replacements.items():
answer = answer.replace(key, value)
question = data["results"][0]["question"]
self.bot.log(f"Found the question \"{question}\"")
answers = data["results"][0]["incorrect_answers"]
answers.append(data["results"][0]["correct_answer"])
random.shuffle(answers)
correctAnswer = data["results"][0]["correct_answer"]
correctAnswer = answers.index(correctAnswer) + 97
return question, answers, correctAnswer
else:
log_message = "There was already a trivia question for that channel"
self.bot.log(log_message)
return self.bot.long_strings["Trivia going on"], "", ""
newQuestion = {
"_id": channel,
"answer": str(chr(correctAnswer)),
"players": {}
}
triviaQuestions.insert_one(newQuestion)
def triviaAnswer(self, user: str, channel: str, command: str):
"""
Answer the current trivia question.
replacements = {
"&#039;": "\'",
"&quot;": "\"",
"&ldquo;": "\"",
"&rdquo;": "\"",
"&eacute;": "é"
}
question = data["results"][0]["question"]
*Parameters*
------------
user: str
The id of the user who answered.
channel: str
The id of the channel the game is in.
command: str
The user's answer.
for key, value in replacements.items():
question = question.replace(key, value)
*Returns*
---------
send_message: str
The message to send if the function failed.
"""
triviaQuestions = self.bot.database["trivia questions"]
question = triviaQuestions.find_one({"_id": channel})
for answer in answers:
for key, value in replacements.items():
answer = answer.replace(key, value)
if command not in ["a", "b", "c", "d"]:
self.bot.log("I didn't quite understand that")
return "I didn't quite understand that"
elif question is None:
self.bot.log("There's no question right now")
return "There's no question right now"
elif user in question["players"]:
self.bot.log(f"{user} has already answered this question")
return f"{user} has already answered this question"
else:
self.bot.log(f"{user} answered the question in {channel}")
return question, answers, correctAnswer
else:
log_message = "There was already a trivia question for that channel"
self.bot.log(log_message)
return self.bot.long_strings["Trivia going on"], "", ""
updater = {"$set": {f"players.{user}": command}}
triviaQuestions.update_one({"_id": channel}, updater)
return None
def triviaAnswer(self, user: str, channel: str, command: str):
"""
Answer the current trivia question.
def triviaCountPoints(self, channel: str):
"""
Add money to every winner's account.
*Parameters*
------------
user: str
The id of the user who answered.
channel: str
The id of the channel the game is in.
command: str
The user's answer.
*Parameters*
------------
channel: str
The id of the channel the game is in.
"""
triviaQuestions = self.bot.database["trivia questions"]
question = triviaQuestions.find_one({"_id": channel})
*Returns*
---------
send_message: str
The message to send if the function failed.
"""
triviaQuestions = self.bot.database["trivia questions"]
question = triviaQuestions.find_one({"_id": channel})
self.bot.log("Counting points for question in "+channel)
if command not in ["a", "b", "c", "d"]:
self.bot.log("I didn't quite understand that")
return "I didn't quite understand that"
elif question is None:
self.bot.log("There's no question right now")
return "There's no question right now"
elif user in question["players"]:
self.bot.log(f"{user} has already answered this question")
return f"{user} has already answered this question"
else:
self.bot.log(f"{user} answered the question in {channel}")
if question is not None:
for player, answer in question["players"].items():
if answer == question["answer"]:
self.bot.money.addMoney(player, 1)
else:
self.bot.log("Couldn't find the questio")
updater = {"$set": {f"players.{user}": command}}
triviaQuestions.update_one({"_id": channel}, updater)
return None
return None
def triviaCountPoints(self, channel: str):
"""
Add money to every winner's account.
async def triviaParse(self, ctx: SlashContext, answer: str):
"""
Parse a trivia command.
*Parameters*
------------
channel: str
The id of the channel the game is in.
"""
triviaQuestions = self.bot.database["trivia questions"]
question = triviaQuestions.find_one({"_id": channel})
*Parameters*
------------
ctx: SlashContext
The context of the command.
answer: str
The answer, if any.
"""
await self.bot.defer(ctx)
channelId = str(ctx.channel_id)
if answer == "":
question, options, correctAnswer = self.triviaStart(channelId)
if options != "":
results = "**"+question+"**\n"
for x, option in enumerate(options):
results += chr(x+97) + ") "+option+"\n"
self.bot.log("Counting points for question in "+channel)
await ctx.send(results)
if question is not None:
for player, answer in question["players"].items():
if answer == question["answer"]:
self.bot.money.addMoney(player, 1)
else:
self.bot.log("Couldn't find the questio")
await asyncio.sleep(60)
return None
self.triviaCountPoints(channelId)
async def triviaParse(self, ctx: SlashContext, answer: str):
"""
Parse a trivia command.
delete_gameParams = ["trivia questions", channelId]
self.bot.database_funcs.delete_game(*delete_gameParams)
*Parameters*
------------
ctx: SlashContext
The context of the command.
answer: str
The answer, if any.
"""
await self.bot.defer(ctx)
channelId = str(ctx.channel_id)
if answer == "":
question, options, correctAnswer = self.triviaStart(channelId)
if options != "":
results = "**"+question+"**\n"
for x, option in enumerate(options):
results += chr(x+97) + ") "+option+"\n"
self.bot.log("Time's up for the trivia question", channelId)
send_message = self.bot.long_strings["Trivia time up"]
format_parameters = [chr(correctAnswer), options[correctAnswer-97]]
send_message = send_message.format(*format_parameters)
await ctx.send(send_message)
else:
await ctx.send(question, hidden=True)
await ctx.send(results)
await asyncio.sleep(60)
self.triviaCountPoints(channelId)
delete_gameParams = ["trivia questions", channelId]
self.bot.database_funcs.delete_game(*delete_gameParams)
self.bot.log("Time's up for the trivia question", channelId)
send_message = self.bot.long_strings["Trivia time up"]
format_parameters = [chr(correctAnswer), options[correctAnswer-97]]
send_message = send_message.format(*format_parameters)
await ctx.send(send_message)
else:
await ctx.send(question, hidden=True)
elif answer in ["a", "b", "c", "d"]:
userId = f"#{ctx.author.id}"
response = self.triviaAnswer(userId, channelId, answer)
if response is None:
user_name = ctx.author.display_name
await ctx.send(f"{user_name} answered **{answer}**")
else:
await ctx.send(response)
else:
self.bot.log("I didn't understand that", channelId)
await ctx.send("I didn't understand that")
elif answer in ["a", "b", "c", "d"]:
userId = f"#{ctx.author.id}"
response = self.triviaAnswer(userId, channelId, answer)
if response is None:
user_name = ctx.author.display_name
await ctx.send(f"{user_name} answered **{answer}**")
else:
await ctx.send(response)
else:
self.bot.log("I didn't understand that", channelId)
await ctx.send("I didn't understand that")

View File

@@ -25,177 +25,177 @@ PRESENT_COLOR = "#0f7aa8"
COLORS = [INCORRECT_COLOR, PRESENT_COLOR, CORRECT_COLOR]
class WordleGame(DatabaseGame):
"""Implementation of wordle game."""
def __init__(self, bot):
super().__init__(bot, "wordle", WordleDrawer)
self._API_url = "https://api.wordnik.com/v4/words.json/randomWords?" # pylint: disable=invalid-name
api_key = self.bot.credentials["wordnik_key"]
self._APIPARAMS = { # pylint: disable=invalid-name
"hasDictionaryDef": True,
"minCorpusCount": 5000,
"maxCorpusCount": -1,
"minDictionaryCount": 1,
"maxDictionaryCount": -1,
"limit": 1,
"api_key": api_key
}
"""Implementation of wordle game."""
def __init__(self, bot):
super().__init__(bot, "wordle", WordleDrawer)
self._API_url = "https://api.wordnik.com/v4/words.json/randomWords?" # pylint: disable=invalid-name
api_key = self.bot.credentials["wordnik_key"]
self._APIPARAMS = { # pylint: disable=invalid-name
"hasDictionaryDef": True,
"minCorpusCount": 5000,
"maxCorpusCount": -1,
"minDictionaryCount": 1,
"maxDictionaryCount": -1,
"limit": 1,
"api_key": api_key
}
async def start(self, ctx, letters: int):
if self._test_document(str(ctx.channel_id)):
await ctx.send("There is already a wordle game in this channel.")
self.bot.log("There was already a game going on")
return
async def start(self, ctx, letters: int):
if self._test_document(str(ctx.channel_id)):
await ctx.send("There is already a wordle game in this channel.")
self.bot.log("There was already a game going on")
return
params = self._APIPARAMS
params["minLength"] = letters
params["maxLength"] = letters
word = "-"
while "-" in word or "." in word:
response = requests.get(self._API_url, params=params)
if response.json() == []:
ctx.send("Could not find a word. Try again")
return
word = list(response.json()[0]["word"].upper())
params = self._APIPARAMS
params["minLength"] = letters
params["maxLength"] = letters
word = "-"
while "-" in word or "." in word:
response = requests.get(self._API_url, params=params)
if response.json() == []:
ctx.send("Could not find a word. Try again")
return
word = list(response.json()[0]["word"].upper())
self.bot.log(f"Found the word \"{''.join(word)}\"")
game = {"word": word, "guesses": [], "results": []}
await ctx.send("Starting a wordle game.")
await self._start_new(ctx.channel, game, delete=False)
self.bot.log(f"Found the word \"{''.join(word)}\"")
game = {"word": word, "guesses": [], "results": []}
await ctx.send("Starting a wordle game.")
await self._start_new(ctx.channel, game, delete=False)
def _get_result(self, guess: list[str], word: list[str]):
result = ["_" for _ in guess]
for i, letter in enumerate(guess):
if letter == word[i]:
result[i] = "*"
def _get_result(self, guess: list[str], word: list[str]):
result = ["_" for _ in guess]
for i, letter in enumerate(guess):
if letter == word[i]:
result[i] = "*"
for i, letter in enumerate(guess):
if letter in word and result[i] != "*":
same_letter = guess[:i].count(letter)
same_letter += len(
[
l for j,l in
enumerate(guess[i:])
if guess[i:][j] == letter and result[i:][j] == "*"
]
)
if same_letter < word.count(letter):
result[i] = "-"
for i, letter in enumerate(guess):
if letter in word and result[i] != "*":
same_letter = guess[:i].count(letter)
same_letter += len(
[
l for j,l in
enumerate(guess[i:])
if guess[i:][j] == letter and result[i:][j] == "*"
]
)
if same_letter < word.count(letter):
result[i] = "-"
return result
return result
async def guess(self, ctx, guess: str):
if not guess.isalpha():
await ctx.send("You can only use letters in your guess")
return
async def guess(self, ctx, guess: str):
if not guess.isalpha():
await ctx.send("You can only use letters in your guess")
return
guess = list(guess.upper())
try:
game = self.access_document(str(ctx.channel_id))
except GameNotInDatabase:
await ctx.send("No game in channel")
return
guess = list(guess.upper())
try:
game = self.access_document(str(ctx.channel_id))
except GameNotInDatabase:
await ctx.send("No game in channel")
return
if len(guess) != len(game['word']):
await ctx.send(
f"Your guess must be {len(game['word'])} letters long")
return
if len(guess) != len(game['word']):
await ctx.send(
f"Your guess must be {len(game['word'])} letters long")
return
await ctx.send(f"Guessed {''.join(guess)}")
result = self._get_result(guess, game['word'])
await ctx.send(f"Guessed {''.join(guess)}")
result = self._get_result(guess, game['word'])
updater = {
"$set": {
f"guesses.{len(game['guesses'])}": guess,
f"results.{len(game['guesses'])}": result
}
}
self._update_document(str(ctx.channel_id), updater)
updater = {
"$set": {
f"guesses.{len(game['guesses'])}": guess,
f"results.{len(game['guesses'])}": result
}
}
self._update_document(str(ctx.channel_id), updater)
if result == ["*" for _ in game['word']]:
await ctx.send("You guessed the word! Adding 15 GwendoBucks to your account")
self.bot.money.addMoney(f"#{ctx.author_id}", 15)
await self._end_game(ctx.channel)
elif len(game['guesses']) == 5:
await ctx.send(f"You used up all available guesses. The word was '{''.join(game['word'])}'")
await self._end_game(ctx.channel)
else:
print(len(game['guesses']))
await self._delete_old_image(ctx.channel)
await self._send_image(ctx.channel, delete=False)
if result == ["*" for _ in game['word']]:
await ctx.send("You guessed the word! Adding 15 GwendoBucks to your account")
self.bot.money.addMoney(f"#{ctx.author_id}", 15)
await self._end_game(ctx.channel)
elif len(game['guesses']) == 5:
await ctx.send(f"You used up all available guesses. The word was '{''.join(game['word'])}'")
await self._end_game(ctx.channel)
else:
print(len(game['guesses']))
await self._delete_old_image(ctx.channel)
await self._send_image(ctx.channel, delete=False)
class WordleDrawer(BaseDrawer):
def __init__(self, bot, game: WordleGame):
super().__init__(bot, game)
self.default_image = None
self.default_color = BACKGROUND_COLOR
self.default_size = (0, 0)
def __init__(self, bot, game: WordleGame):
super().__init__(bot, game)
self.default_image = None
self.default_color = BACKGROUND_COLOR
self.default_size = (0, 0)
def _get_size(self, game: dict):
width = (
(len(game['word']) * SQUARE_SIZE) +
((len(game['word']) - 1) * SQUARE_PADDING) +
(2 * IMAGE_MARGIN)
)
height = (
(6 * SQUARE_SIZE) +
(5 * ROW_PADDING) +
(2 * IMAGE_MARGIN)
)
size = (width, height)
def _get_size(self, game: dict):
width = (
(len(game['word']) * SQUARE_SIZE) +
((len(game['word']) - 1) * SQUARE_PADDING) +
(2 * IMAGE_MARGIN)
)
height = (
(6 * SQUARE_SIZE) +
(5 * ROW_PADDING) +
(2 * IMAGE_MARGIN)
)
size = (width, height)
return size
return size
def _draw_row(self, row, drawer, font, word: str, colors: list[str] = None,
border_color: str = None):
if colors is None:
colors = [BACKGROUND_COLOR for _ in range(len(word))]
def _draw_row(self, row, drawer, font, word: str, colors: list[str] = None,
border_color: str = None):
if colors is None:
colors = [BACKGROUND_COLOR for _ in range(len(word))]
for i, letter in enumerate(word):
y_pos = IMAGE_MARGIN + (row * (SQUARE_SIZE + ROW_PADDING))
x_pos = IMAGE_MARGIN + (i * (SQUARE_SIZE + SQUARE_PADDING))
top_left = (x_pos, y_pos)
bottom_right = (x_pos + SQUARE_SIZE, y_pos + SQUARE_SIZE)
for i, letter in enumerate(word):
y_pos = IMAGE_MARGIN + (row * (SQUARE_SIZE + ROW_PADDING))
x_pos = IMAGE_MARGIN + (i * (SQUARE_SIZE + SQUARE_PADDING))
top_left = (x_pos, y_pos)
bottom_right = (x_pos + SQUARE_SIZE, y_pos + SQUARE_SIZE)
drawer.rounded_rectangle(
(top_left,bottom_right),
10,
colors[i],
border_color,
3
)
drawer.rounded_rectangle(
(top_left,bottom_right),
10,
colors[i],
border_color,
3
)
text_pos = (
x_pos + (SQUARE_SIZE//2),
y_pos + int(SQUARE_SIZE * 0.6)
)
text_pos = (
x_pos + (SQUARE_SIZE//2),
y_pos + int(SQUARE_SIZE * 0.6)
)
drawer.text(text_pos, letter, TEXT_COLOR, font=font, anchor="mm")
drawer.text(text_pos, letter, TEXT_COLOR, font=font, anchor="mm")
def _determine_colors(self, results):
return [COLORS[["_","-","*"].index(symbol)] for symbol in results]
def _determine_colors(self, results):
return [COLORS[["_","-","*"].index(symbol)] for symbol in results]
def _draw_image(self, game: dict, image: Image.Image):
drawer = ImageDraw.Draw(image)
font = self._get_font(FONT_SIZE)
for i, guess in enumerate(game['guesses']):
colors = self._determine_colors(game['results'][i])
self._draw_row(i, drawer, font, guess, colors)
def _draw_image(self, game: dict, image: Image.Image):
drawer = ImageDraw.Draw(image)
font = self._get_font(FONT_SIZE)
for i, guess in enumerate(game['guesses']):
colors = self._determine_colors(game['results'][i])
self._draw_row(i, drawer, font, guess, colors)
if len(game["guesses"]) < 6:
self._draw_row(
len(game['guesses']),
drawer,
font,
" "*len(game['word']),
border_color=WRITING_BORDER_COLOR
)
if len(game["guesses"]) < 6:
self._draw_row(
len(game['guesses']),
drawer,
font,
" "*len(game['word']),
border_color=WRITING_BORDER_COLOR
)
for i in range(5 - len(game['guesses'])):
self._draw_row(
len(game['guesses']) + i + 1,
drawer,
font, " "*len(game['word']),
border_color=INACTIVE_BORDER_COLOR
)
for i in range(5 - len(game['guesses'])):
self._draw_row(
len(game['guesses']) + i + 1,
drawer,
font, " "*len(game['word']),
border_color=INACTIVE_BORDER_COLOR
)
return super()._draw_image(game, image)
return super()._draw_image(game, image)

View File

@@ -5,217 +5,217 @@ import discord
from gwendolyn_old.utils import cap
STATS = [
"strength",
"dexterity",
"constitution",
"intelligence",
"wisdom",
"charisma"
"strength",
"dexterity",
"constitution",
"intelligence",
"wisdom",
"charisma"
]
def mod(statistic):
"""Calculates D&D modifier."""
modifier = math.floor((statistic-10)/2)
if modifier >= 0:
modifier = "+"+str(modifier)
"""Calculates D&D modifier."""
modifier = math.floor((statistic-10)/2)
if modifier >= 0:
modifier = "+"+str(modifier)
return modifier
return modifier
class LookupFuncs():
def __init__(self, bot):
self.bot = bot
self.saves = [
"strength_save",
"dexterity_save",
"constitution_save",
"intelligence_save",
"wisdom_save",
"charisma_save"
]
self.abilities = [
"acrobatics",
"animal_handling",
"arcana",
"athletics",
"deception",
"history",
"insight",
"intimidation",
"investigation",
"medicine",
"nature",
"perception",
"performance",
"persuasion",
"religion",
"sleight_of_hand",
"stealth",
"survival"
]
def __init__(self, bot):
self.bot = bot
self.saves = [
"strength_save",
"dexterity_save",
"constitution_save",
"intelligence_save",
"wisdom_save",
"charisma_save"
]
self.abilities = [
"acrobatics",
"animal_handling",
"arcana",
"athletics",
"deception",
"history",
"insight",
"intimidation",
"investigation",
"medicine",
"nature",
"perception",
"performance",
"persuasion",
"religion",
"sleight_of_hand",
"stealth",
"survival"
]
def _format_monster(self, monster):
# Looks at the information about the monster and
# returns that information in separate variables,
# allowing Gwendolyn to know where to separate
# the messages
types = monster["type"]
if monster["subtype"] != "":
types += " ("+monster["subtype"]+")"
def _format_monster(self, monster):
# Looks at the information about the monster and
# returns that information in separate variables,
# allowing Gwendolyn to know where to separate
# the messages
types = monster["type"]
if monster["subtype"] != "":
types += " ("+monster["subtype"]+")"
stats = []
for stat in STATS:
value = monster[stat]
stats.append(f"**{cap(stat[:3])}:** {value} ({mod(value)})")
stats = []
for stat in STATS:
value = monster[stat]
stats.append(f"**{cap(stat[:3])}:** {value} ({mod(value)})")
stats = "\t".join(stats[:3]) + "\n" + "\t".join(stats[3:])
stats = "\t".join(stats[:3]) + "\n" + "\t".join(stats[3:])
saving_throws = []
for save in self.saves:
if save in monster:
value = monster[save]
if monster[save] >= 0:
saving_throws.append(f"{cap(save[:3])} +{value}")
else:
saving_throws.append(f"{cap(save[:3])} {value}")
if saving_throws:
saving_throws = f"\n**Saving Throws:** {', '.join(saving_throws)}"
saving_throws = []
for save in self.saves:
if save in monster:
value = monster[save]
if monster[save] >= 0:
saving_throws.append(f"{cap(save[:3])} +{value}")
else:
saving_throws = ""
saving_throws.append(f"{cap(save[:3])} {value}")
skills = []
for skill in self.abilities:
if skill in monster:
skill_name = cap(skill.replace("_"," "))
if monster[skill] >= 0:
skills.append(f"{skill_name} +{monster[skill]}")
else:
skills.append(f"{skill_name} {monster[skill]}")
if saving_throws:
saving_throws = f"\n**Saving Throws:** {', '.join(saving_throws)}"
else:
saving_throws = ""
if skills:
skills = f"\n**Skills:** {', '.join(skills)}"
skills = []
for skill in self.abilities:
if skill in monster:
skill_name = cap(skill.replace("_"," "))
if monster[skill] >= 0:
skills.append(f"{skill_name} +{monster[skill]}")
else:
skills = ""
skills.append(f"{skill_name} {monster[skill]}")
vulnerabilities = monster["damage_vulnerabilities"]
if vulnerabilities != "":
vulnerabilities = "\n**Damage Vulnerabilities** "+vulnerabilities
if skills:
skills = f"\n**Skills:** {', '.join(skills)}"
else:
skills = ""
resistances = monster["damage_resistances"]
if resistances != "":
resistances = "\n**Damage Resistances** "+resistances
vulnerabilities = monster["damage_vulnerabilities"]
if vulnerabilities != "":
vulnerabilities = "\n**Damage Vulnerabilities** "+vulnerabilities
immunities = monster["damage_immunities"]
if immunities != "":
immunities = "\n**Damage Immunities** "+immunities
resistances = monster["damage_resistances"]
if resistances != "":
resistances = "\n**Damage Resistances** "+resistances
c_immunities = monster["condition_immunities"]
if c_immunities != "":
c_immunities = "\n**Condition Immunities** "+c_immunities
immunities = monster["damage_immunities"]
if immunities != "":
immunities = "\n**Damage Immunities** "+immunities
special_abilities = ""
if "special_abilities" in monster:
for ability in monster["special_abilities"]:
special_abilities += "\n\n***"+ability["name"]+".*** "+ability["desc"]
c_immunities = monster["condition_immunities"]
if c_immunities != "":
c_immunities = "\n**Condition Immunities** "+c_immunities
act = ""
if "actions" in monster:
for action in monster["actions"]:
act += "\n\n***"+action["name"]+".*** "+action["desc"]
special_abilities = ""
if "special_abilities" in monster:
for ability in monster["special_abilities"]:
special_abilities += "\n\n***"+ability["name"]+".*** "+ability["desc"]
react = ""
if "reactions" in monster:
for reaction in monster["reactions"]:
react += "\n\n***"+reaction["name"]+".*** "+reaction["desc"]
act = ""
if "actions" in monster:
for action in monster["actions"]:
act += "\n\n***"+action["name"]+".*** "+action["desc"]
legendaryActions = ""
if "legendary_actions" in monster:
for action in monster["legendary_actions"]:
legendaryActions += "\n\n***"+action["name"]+".*** "+action["desc"]
react = ""
if "reactions" in monster:
for reaction in monster["reactions"]:
react += "\n\n***"+reaction["name"]+".*** "+reaction["desc"]
hit_dice = monster["hit_dice"]
dice_amount = int(monster["hit_dice"].replace("d"," ").split()[0])
con_mod = math.floor((monster['constitution']-10)/2)
if con_mod < 0:
hit_dice += f" - {abs(con_mod) * dice_amount}"
elif con_mod > 0:
hit_dice += (f" + {con_mod * dice_amount}")
legendaryActions = ""
if "legendary_actions" in monster:
for action in monster["legendary_actions"]:
legendaryActions += "\n\n***"+action["name"]+".*** "+action["desc"]
new_part = "\n--------------------"
hit_dice = monster["hit_dice"]
dice_amount = int(monster["hit_dice"].replace("d"," ").split()[0])
con_mod = math.floor((monster['constitution']-10)/2)
if con_mod < 0:
hit_dice += f" - {abs(con_mod) * dice_amount}"
elif con_mod > 0:
hit_dice += (f" + {con_mod * dice_amount}")
monster_type = f"*{monster['size']} {types}, {monster['alignment']}*"
new_part = "\n--------------------"
basic_info = "\n**Armor Class** "+str(monster["armor_class"])+"\n**Hit Points** "+str(monster["hit_points"])+" ("+hit_dice+")\n**Speed **"+monster["speed"]+new_part+"\n"
monster_type = f"*{monster['size']} {types}, {monster['alignment']}*"
info = (monster_type+new_part+basic_info+stats+new_part+saving_throws+skills+vulnerabilities+resistances+immunities+c_immunities+"\n**Senses** "+monster["senses"]+"\n**Languages** "+monster["languages"]+"\n**Challenge** "+monster["challenge_rating"])
basic_info = "\n**Armor Class** "+str(monster["armor_class"])+"\n**Hit Points** "+str(monster["hit_points"])+" ("+hit_dice+")\n**Speed **"+monster["speed"]+new_part+"\n"
monster_info = [(info, monster['name']),
(special_abilities, "Special Abilities"),
(act, "Actions"),
(react, "Reactions"),
(legendaryActions, "Legendary Actions")]
info = (monster_type+new_part+basic_info+stats+new_part+saving_throws+skills+vulnerabilities+resistances+immunities+c_immunities+"\n**Senses** "+monster["senses"]+"\n**Languages** "+monster["languages"]+"\n**Challenge** "+monster["challenge_rating"])
self.bot.log("Returning monster information")
return monster_info
monster_info = [(info, monster['name']),
(special_abilities, "Special Abilities"),
(act, "Actions"),
(react, "Reactions"),
(legendaryActions, "Legendary Actions")]
# Looks up a monster
async def monster_func(self, ctx, query):
query = cap(query)
self.bot.log("Looking up "+query)
self.bot.log("Returning monster information")
return monster_info
# 1-letter monsters don't exist
if len(query) < 2:
self.bot.log("Monster name too short")
await ctx.send("I don't know that monster...")
return
# Looks up a monster
async def monster_func(self, ctx, query):
query = cap(query)
self.bot.log("Looking up "+query)
# Opens "monsters.json"
monster_file_path = "gwendolyn/resources/lookup/monsters.json"
with open(monster_file_path,"r", encoding="utf-8") as file_pointer:
data = json.load(file_pointer)
# 1-letter monsters don't exist
if len(query) < 2:
self.bot.log("Monster name too short")
await ctx.send("I don't know that monster...")
return
for monster in data:
if "name" in monster and str(query) == monster["name"]:
self.bot.log("Found it!")
# Opens "monsters.json"
monster_file_path = "gwendolyn/resources/lookup/monsters.json"
with open(monster_file_path,"r", encoding="utf-8") as file_pointer:
data = json.load(file_pointer)
monster_info = self._format_monster(monster)
for monster in data:
if "name" in monster and str(query) == monster["name"]:
self.bot.log("Found it!")
# Sends the received information. Separates into separate messages if
# there is too much text
await ctx.send(f"Result for \"{query}\"")
for text, title in monster_info:
if text != "":
if len(text) < 2000:
em = discord.Embed(title = title, description = text, colour=0xDEADBF)
await ctx.channel.send(embed = em)
else:
index = text[:2000].rfind(".")+1
em1 = discord.Embed(title = title, description = text[:index], colour=0xDEADBF)
await ctx.channel.send(embed = em1)
em2 = discord.Embed(title = "", description = text[index+1:], colour=0xDEADBF)
await ctx.channel.send(embed = em2)
monster_info = self._format_monster(monster)
break
else:
self.bot.log("Monster not in database")
await ctx.send("I don't know that monster...")
# Sends the received information. Separates into separate messages if
# there is too much text
await ctx.send(f"Result for \"{query}\"")
for text, title in monster_info:
if text != "":
if len(text) < 2000:
em = discord.Embed(title = title, description = text, colour=0xDEADBF)
await ctx.channel.send(embed = em)
else:
index = text[:2000].rfind(".")+1
em1 = discord.Embed(title = title, description = text[:index], colour=0xDEADBF)
await ctx.channel.send(embed = em1)
em2 = discord.Embed(title = "", description = text[index+1:], colour=0xDEADBF)
await ctx.channel.send(embed = em2)
# Looks up a spell
async def spell_func(self, ctx, query):
query = cap(query)
self.bot.log("Looking up "+query)
break
else:
self.bot.log("Monster not in database")
await ctx.send("I don't know that monster...")
# Opens "spells.json"
data = json.load(open('gwendolyn/resources/lookup/spells.json', encoding = "utf8"))
if query in data:
self.bot.log("Returning spell information")
send_message = (f"***{query}***\n*{data[query]['level']} level {data[query]['school']}\nCasting Time: {data[query]['casting_time']}\nRange:{data[query]['range']}\nComponents:{data[query]['components']}\nDuration:{data[query]['duration']}*\n \n{data[query]['description']}")
else:
self.bot.log("I don't know that spell")
send_message = "I don't think that's a spell"
# Looks up a spell
async def spell_func(self, ctx, query):
query = cap(query)
self.bot.log("Looking up "+query)
if len(send_message) > 2000:
await ctx.send(send_message[:2000])
await ctx.send(send_message[2000:])
else:
await ctx.send(send_message)
# Opens "spells.json"
data = json.load(open('gwendolyn/resources/lookup/spells.json', encoding = "utf8"))
if query in data:
self.bot.log("Returning spell information")
send_message = (f"***{query}***\n*{data[query]['level']} level {data[query]['school']}\nCasting Time: {data[query]['casting_time']}\nRange:{data[query]['range']}\nComponents:{data[query]['components']}\nDuration:{data[query]['duration']}*\n \n{data[query]['description']}")
else:
self.bot.log("I don't know that spell")
send_message = "I don't think that's a spell"
if len(send_message) > 2000:
await ctx.send(send_message[:2000])
await ctx.send(send_message[2000:])
else:
await ctx.send(send_message)

View File

@@ -1,94 +1,94 @@
import random
class Generators():
def __init__(self, bot):
self.bot = bot
def __init__(self, bot):
self.bot = bot
# Returns a list of all letter pairs in the text
def make_pairs(self, corpus):
for i in range(len(corpus)-1):
yield (corpus[i], corpus[i+1])
# Returns a list of all letter pairs in the text
def make_pairs(self, corpus):
for i in range(len(corpus)-1):
yield (corpus[i], corpus[i+1])
# Returns a list of all letter triplets in the text
def make_triplets(self, corpus):
for i in range(len(corpus)-2):
yield (corpus[i], corpus[i+1], corpus[i+2])
# Returns a list of all letter triplets in the text
def make_triplets(self, corpus):
for i in range(len(corpus)-2):
yield (corpus[i], corpus[i+1], corpus[i+2])
# Generates a random name
async def name_gen(self, ctx):
# Makes a list of all names from "names.txt"
with open("gwendolyn/resources/names.txt", "r", encoding='utf8') as file_pointer:
names = file_pointer.read()
corpus = list(names)
# Generates a random name
async def name_gen(self, ctx):
# Makes a list of all names from "names.txt"
with open("gwendolyn/resources/names.txt", "r", encoding='utf8') as file_pointer:
names = file_pointer.read()
corpus = list(names)
# Makes a list of pairs
pairs = self.make_pairs(corpus)
triplets = self.make_triplets(corpus)
# Makes a list of pairs
pairs = self.make_pairs(corpus)
triplets = self.make_triplets(corpus)
letter_dict = {}
letter_dict = {}
# Makes a dictionary of all letters that come after all other letters
for letter_1, letter_2 in pairs:
if letter_1 in letter_dict:
letter_dict[letter_1].append(letter_2)
else:
letter_dict[letter_1] = [letter_2]
# Makes a dictionary of all letters that come after all other letters
for letter_1, letter_2 in pairs:
if letter_1 in letter_dict:
letter_dict[letter_1].append(letter_2)
else:
letter_dict[letter_1] = [letter_2]
for letter_1, letter_2, letter_3 in triplets:
if letter_1+letter_2 in letter_dict:
letter_dict[letter_1+letter_2].append(letter_3)
else:
letter_dict[letter_1+letter_2] = [letter_3]
for letter_1, letter_2, letter_3 in triplets:
if letter_1+letter_2 in letter_dict:
letter_dict[letter_1+letter_2].append(letter_3)
else:
letter_dict[letter_1+letter_2] = [letter_3]
# Choses a random first letter
first_letter = random.choice(corpus)
# Choses a random first letter
first_letter = random.choice(corpus)
# Makes sure the first letter is not something a name can't start with.
while first_letter.islower() or first_letter == " " or first_letter == "-" or first_letter == "\n":
first_letter = random.choice(corpus)
# Makes sure the first letter is not something a name can't start with.
while first_letter.islower() or first_letter == " " or first_letter == "-" or first_letter == "\n":
first_letter = random.choice(corpus)
# Starts the name
chain = [first_letter]
# Starts the name
chain = [first_letter]
# Picks second letter
second_letter = random.choice(letter_dict[chain[-1]])
# Picks second letter
second_letter = random.choice(letter_dict[chain[-1]])
while second_letter == "\n":
second_letter = random.choice(letter_dict[chain[-1]])
while second_letter == "\n":
second_letter = random.choice(letter_dict[chain[-1]])
chain.append(second_letter)
chain.append(second_letter)
done = False
done = False
# Creates the name one letter at a time
while not done:
if random.randint(1,10) > 1:
try:
new_letter = random.choice(letter_dict[chain[-2]+chain[-1]])
except KeyError():
new_letter = random.choice(letter_dict[chain[-1]])
else:
new_letter = random.choice(letter_dict[chain[-1]])
chain.append(new_letter)
# Ends name if the name ends
if new_letter == "\n":
done = True
gen_name = "".join(chain)
self.bot.log("Generated "+gen_name[:-1])
# Creates the name one letter at a time
while not done:
if random.randint(1,10) > 1:
try:
new_letter = random.choice(letter_dict[chain[-2]+chain[-1]])
except KeyError():
new_letter = random.choice(letter_dict[chain[-1]])
else:
new_letter = random.choice(letter_dict[chain[-1]])
chain.append(new_letter)
# Ends name if the name ends
if new_letter == "\n":
done = True
gen_name = "".join(chain)
self.bot.log("Generated "+gen_name[:-1])
# Returns the name
await ctx.send(gen_name)
# Returns the name
await ctx.send(gen_name)
# Generates a random tavern name
async def tavern_gen(self, ctx):
# _lists first parts, second parts and third parts of tavern names
first_part = ["The Silver","The Golden","The Staggering","The Laughing","The Prancing","The Gilded","The Running","The Howling","The Slaughtered","The Leering","The Drunken","The Leaping","The Roaring","The Frowning","The Lonely","The Wandering","The Mysterious","The Barking","The Black","The Gleaming","The Tap-Dancing","The Sad","The Sexy","The Artificial","The Groovy","The Merciful","The Confused","The Pouting","The Horny","The Okay","The Friendly","The Hungry","The Handicapped","The Fire-breathing","The One-Eyed","The Psychotic","The Mad","The Evil","The Idiotic","The Trusty","The Busty"]
second_part = ["Eel","Dolphin","Dwarf","Pegasus","Pony","Rose","Stag","Wolf","Lamb","Demon","Goat","Spirit","Horde","Jester","Mountain","Eagle","Satyr","Dog","Spider","Star","Dad","Rat","Jeremy","Mouse","Unicorn","Pearl","Ant","Crab","Penguin","Octopus","Lawyer","Ghost","Toad","Handjob","Immigrant","SJW","Dragon","Bard","Sphinx","Soldier","Salmon","Owlbear","Kite","Frost Giant","Arsonist"]
third_part = [" Tavern"," Inn","","","","","","","","",""]
# Generates a random tavern name
async def tavern_gen(self, ctx):
# _lists first parts, second parts and third parts of tavern names
first_part = ["The Silver","The Golden","The Staggering","The Laughing","The Prancing","The Gilded","The Running","The Howling","The Slaughtered","The Leering","The Drunken","The Leaping","The Roaring","The Frowning","The Lonely","The Wandering","The Mysterious","The Barking","The Black","The Gleaming","The Tap-Dancing","The Sad","The Sexy","The Artificial","The Groovy","The Merciful","The Confused","The Pouting","The Horny","The Okay","The Friendly","The Hungry","The Handicapped","The Fire-breathing","The One-Eyed","The Psychotic","The Mad","The Evil","The Idiotic","The Trusty","The Busty"]
second_part = ["Eel","Dolphin","Dwarf","Pegasus","Pony","Rose","Stag","Wolf","Lamb","Demon","Goat","Spirit","Horde","Jester","Mountain","Eagle","Satyr","Dog","Spider","Star","Dad","Rat","Jeremy","Mouse","Unicorn","Pearl","Ant","Crab","Penguin","Octopus","Lawyer","Ghost","Toad","Handjob","Immigrant","SJW","Dragon","Bard","Sphinx","Soldier","Salmon","Owlbear","Kite","Frost Giant","Arsonist"]
third_part = [" Tavern"," Inn","","","","","","","","",""]
# Picks one of each
gen_tav = random.choice(first_part)+" "+random.choice(second_part)+random.choice(third_part)
self.bot.log("Generated "+gen_tav)
# Picks one of each
gen_tav = random.choice(first_part)+" "+random.choice(second_part)+random.choice(third_part)
self.bot.log("Generated "+gen_tav)
# Return the name
await ctx.send(gen_tav)
# Return the name
await ctx.send(gen_tav)

View File

@@ -6,80 +6,80 @@ import wolframalpha
from PIL import Image, ImageDraw, ImageFont
class NerdShit():
def __init__(self, bot):
"""Runs misc commands."""
self.bot = bot
def __init__(self, bot):
"""Runs misc commands."""
self.bot = bot
async def wolf_search(self,ctx,content):
await self.bot.defer(ctx)
font = ImageFont.truetype('gwendolyn/resources/fonts/times-new-roman.ttf', 20)
self.bot.log("Requesting data")
bot = wolframalpha.Client(self.bot.credentials["wolfram_alpha_key"])
res = bot.query(content)
async def wolf_search(self,ctx,content):
await self.bot.defer(ctx)
font = ImageFont.truetype('gwendolyn/resources/fonts/times-new-roman.ttf', 20)
self.bot.log("Requesting data")
bot = wolframalpha.Client(self.bot.credentials["wolfram_alpha_key"])
res = bot.query(content)
self.bot.log("Processing data")
titles = []
pods = []
if int(res.numpods) > 0:
for pod in res.pods:
titles += [pod.title]
for i, sub in enumerate(pod.subpods):
pods += [sub]
if i > 0:
titles += [""]
self.bot.log("Processing data")
titles = []
pods = []
if int(res.numpods) > 0:
for pod in res.pods:
titles += [pod.title]
for i, sub in enumerate(pod.subpods):
pods += [sub]
if i > 0:
titles += [""]
pod_chunks = [pods[x:x+2] for x in range(0, len(pods), 2)]
title_chunks = [titles[x:x+2] for x in range(0, len(titles), 2)]
await ctx.send(f"Response for \"{content}\"")
pod_chunks = [pods[x:x+2] for x in range(0, len(pods), 2)]
title_chunks = [titles[x:x+2] for x in range(0, len(titles), 2)]
await ctx.send(f"Response for \"{content}\"")
for i, chunk in enumerate(pod_chunks):
width = 0
for title in title_chunks[i]:
width = max(width,font.getsize(title)[0])
height = 5
heights = []
for count, pod in enumerate(chunk):
heights += [height]
width = max(width,int(pod.img['@width']))
if title_chunks[i][count] == "":
place_for_text = 0
else:
place_for_text = 30
height += int(pod.img["@height"]) + 10 + place_for_text
for i, chunk in enumerate(pod_chunks):
width = 0
for title in title_chunks[i]:
width = max(width,font.getsize(title)[0])
height = 5
heights = []
for count, pod in enumerate(chunk):
heights += [height]
width = max(width,int(pod.img['@width']))
if title_chunks[i][count] == "":
place_for_text = 0
else:
place_for_text = 30
height += int(pod.img["@height"]) + 10 + place_for_text
width += 10
height += 5
wolf_image = Image.new("RGB",(width,height),color=(255,255,255))
width += 10
height += 5
wolf_image = Image.new("RGB",(width,height),color=(255,255,255))
for count, pod in enumerate(chunk):
response = requests.get(pod.img["@src"])
file = open("gwendolyn/resources/wolfTemp.png", "wb")
file.write(response.content)
file.close()
old_image = Image.open("gwendolyn/resources/wolfTemp.png")
old_size = old_image.size
if title_chunks[i][count] == "":
place_for_text = 0
else:
place_for_text = 30
new_size = (width,int(old_size[1]+10+place_for_text))
new_image = Image.new("RGB",new_size,color=(255,255,255))
new_image.paste(old_image, (int((int(old_size[0]+10)-old_size[0])/2),int(((new_size[1]-place_for_text)-old_size[1])/2)+place_for_text))
if title_chunks[i][count] != "":
drawer = ImageDraw.Draw(new_image,"RGB")
drawer.text((5,7),title_chunks[i][count],font=font,fill=(150,150,150))
for count, pod in enumerate(chunk):
response = requests.get(pod.img["@src"])
file = open("gwendolyn/resources/wolfTemp.png", "wb")
file.write(response.content)
file.close()
old_image = Image.open("gwendolyn/resources/wolfTemp.png")
old_size = old_image.size
if title_chunks[i][count] == "":
place_for_text = 0
else:
place_for_text = 30
new_size = (width,int(old_size[1]+10+place_for_text))
new_image = Image.new("RGB",new_size,color=(255,255,255))
new_image.paste(old_image, (int((int(old_size[0]+10)-old_size[0])/2),int(((new_size[1]-place_for_text)-old_size[1])/2)+place_for_text))
if title_chunks[i][count] != "":
drawer = ImageDraw.Draw(new_image,"RGB")
drawer.text((5,7),title_chunks[i][count],font=font,fill=(150,150,150))
wolf_image.paste(new_image,(0,heights[count]))
new_image.close()
old_image.close()
count += 1
wolf_image.paste(new_image,(0,heights[count]))
new_image.close()
old_image.close()
count += 1
wolf_image.save("gwendolyn/resources/wolf.png")
wolf_image.close()
await ctx.channel.send(file = discord.File("gwendolyn/resources/wolf.png"))
wolf_image.save("gwendolyn/resources/wolf.png")
wolf_image.close()
await ctx.channel.send(file = discord.File("gwendolyn/resources/wolf.png"))
os.remove("gwendolyn/resources/wolf.png")
os.remove("gwendolyn/resources/wolfTemp.png")
else:
self.bot.log("No returned data")
await ctx.send("Could not find anything relating to your search")
os.remove("gwendolyn/resources/wolf.png")
os.remove("gwendolyn/resources/wolfTemp.png")
else:
self.bot.log("No returned data")
await ctx.send("Could not find anything relating to your search")

View File

@@ -17,176 +17,176 @@ fandom.set_lang("da")
fandom.set_wiki("senkulpa")
class MyStringifier(d20.MarkdownStringifier):
def _str_expression(self, node):
if node.comment is None:
result_text = "Result"
else:
result_text = node.comment.capitalize()
def _str_expression(self, node):
if node.comment is None:
result_text = "Result"
else:
result_text = node.comment.capitalize()
return f"**{result_text}**: {self._stringify(node.roll)}\n**Total**: {int(node.total)}"
return f"**{result_text}**: {self._stringify(node.roll)}\n**Total**: {int(node.total)}"
class Other():
def __init__(self, bot):
self.bot = bot
self.plex = Plex(self.bot)
self.nerd_shit = NerdShit(self.bot)
self.generators = Generators(self.bot)
def __init__(self, bot):
self.bot = bot
self.plex = Plex(self.bot)
self.nerd_shit = NerdShit(self.bot)
self.generators = Generators(self.bot)
# Picks a random movie and returns information about it
async def movie_func(self, ctx):
await self.bot.defer(ctx)
# Picks a random movie and returns information about it
async def movie_func(self, ctx):
await self.bot.defer(ctx)
self.bot.log("Creating IMDb object")
imdb_client = imdb.IMDb()
self.bot.log("Creating IMDb object")
imdb_client = imdb.IMDb()
self.bot.log("Picking a movie")
with open("gwendolyn/resources/movies.txt", "r") as file_pointer:
movie_list = file_pointer.read().split("\n")
movie_name = random.choice(movie_list)
self.bot.log("Picking a movie")
with open("gwendolyn/resources/movies.txt", "r") as file_pointer:
movie_list = file_pointer.read().split("\n")
movie_name = random.choice(movie_list)
self.bot.log(f"Searching for {movie_name}")
search_result = imdb_client.search_movie(movie_name)
self.bot.log(f"Searching for {movie_name}")
search_result = imdb_client.search_movie(movie_name)
self.bot.log("Getting the data")
movie = search_result[0]
imdb_client.update(movie)
self.bot.log("Getting the data")
movie = search_result[0]
imdb_client.update(movie)
self.bot.log("Successfully ran /movie")
self.bot.log("Successfully ran /movie")
title = movie["title"]
plot = movie['plot'][0].split("::")[0]
cover = movie['cover url'].replace("150","600").replace("101","404")
cast = ", ".join([i["name"] for i in movie['cast'][:5]])
embed = discord.Embed(title=title, description=plot, color=0x24ec19)
embed.set_thumbnail(url=cover)
embed.add_field(name="Cast", value=cast,inline = True)
await ctx.send(embed = embed)
title = movie["title"]
plot = movie['plot'][0].split("::")[0]
cover = movie['cover url'].replace("150","600").replace("101","404")
cast = ", ".join([i["name"] for i in movie['cast'][:5]])
embed = discord.Embed(title=title, description=plot, color=0x24ec19)
embed.set_thumbnail(url=cover)
embed.add_field(name="Cast", value=cast,inline = True)
await ctx.send(embed = embed)
# Responds with a greeting of a time-appropriate maner
async def hello_func(self, ctx):
def time_in_range(start, end, i):
# Return true if i is in the range [start, end]
if start <= end:
return start <= i <= end
else:
return start <= i or i <= end
# Responds with a greeting of a time-appropriate maner
async def hello_func(self, ctx):
def time_in_range(start, end, i):
# Return true if i is in the range [start, end]
if start <= end:
return start <= i <= end
else:
return start <= i or i <= end
author = ctx.author.display_name
now = datetime.datetime.now()
if time_in_range(now.replace(hour=5, minute=0, second=0, microsecond=0),now.replace(hour=10, minute=0, second=0, microsecond=0), now):
send_message = "Good morning, "+str(author)
elif time_in_range(now.replace(hour=13, minute=0, second=0, microsecond=0),now.replace(hour=18, minute=0, second=0, microsecond=0), now):
send_message = "Good afternoon, "+str(author)
elif time_in_range(now.replace(hour=18, minute=0, second=0, microsecond=0),now.replace(hour=22, minute=0, second=0, microsecond=0), now):
send_message = "Good evening, "+str(author)
elif time_in_range(now.replace(hour=22, minute=0, second=0, microsecond=0),now.replace(hour=23, minute=59, second=59, microsecond=0), now):
send_message = "Good night, "+str(author)
else:
send_message = "Hello, "+str(author)
author = ctx.author.display_name
now = datetime.datetime.now()
if time_in_range(now.replace(hour=5, minute=0, second=0, microsecond=0),now.replace(hour=10, minute=0, second=0, microsecond=0), now):
send_message = "Good morning, "+str(author)
elif time_in_range(now.replace(hour=13, minute=0, second=0, microsecond=0),now.replace(hour=18, minute=0, second=0, microsecond=0), now):
send_message = "Good afternoon, "+str(author)
elif time_in_range(now.replace(hour=18, minute=0, second=0, microsecond=0),now.replace(hour=22, minute=0, second=0, microsecond=0), now):
send_message = "Good evening, "+str(author)
elif time_in_range(now.replace(hour=22, minute=0, second=0, microsecond=0),now.replace(hour=23, minute=59, second=59, microsecond=0), now):
send_message = "Good night, "+str(author)
else:
send_message = "Hello, "+str(author)
await ctx.send(send_message)
await ctx.send(send_message)
# Finds a random picture online
async def image_func(self, ctx):
# Picks a type of camera, which decides the naming scheme
cams = ("one","two","three","four")
cam = random.choice(cams)
self.bot.log("Chose cam type "+cam)
if cam == "one":
# Finds a random picture online
async def image_func(self, ctx):
# Picks a type of camera, which decides the naming scheme
cams = ("one","two","three","four")
cam = random.choice(cams)
self.bot.log("Chose cam type "+cam)
if cam == "one":
search = "img_" + ''.join(
[str(random.randint(0,9)) for _ in range(4)]
)
elif cam == "two":
year = str(random.randint(2012,2016))
month = str(random.randint(1,12)).zfill(2)
day = str(random.randint(1,29)).zfill(2)
search = f"IMG_{year}{month}{day}"
elif cam == "three":
search = f"IMAG_{str(random.randint(1,500)).zfill(4)}"
elif cam == "four":
search = "DSC_" + ''.join(
[str(random.randint(0,9)) for _ in range(4)]
)
search = "img_" + ''.join(
[str(random.randint(0,9)) for _ in range(4)]
)
elif cam == "two":
year = str(random.randint(2012,2016))
month = str(random.randint(1,12)).zfill(2)
day = str(random.randint(1,29)).zfill(2)
search = f"IMG_{year}{month}{day}"
elif cam == "three":
search = f"IMAG_{str(random.randint(1,500)).zfill(4)}"
elif cam == "four":
search = "DSC_" + ''.join(
[str(random.randint(0,9)) for _ in range(4)]
)
self.bot.log("Searching for "+search)
self.bot.log("Searching for "+search)
# Searches for the image and reads the resulting web page
page = urllib.request.urlopen("https://www.bing.com/images/search?q="+search+"&safesearch=off")
read = page.read()
tree = lxml.etree.HTML(read)
images = tree.xpath('//a[@class = "iusc"]/@m')
# Searches for the image and reads the resulting web page
page = urllib.request.urlopen("https://www.bing.com/images/search?q="+search+"&safesearch=off")
read = page.read()
tree = lxml.etree.HTML(read)
images = tree.xpath('//a[@class = "iusc"]/@m')
if len(images) == 0:
await ctx.send("Found no images")
else:
# Picks an image
number = random.randint(1,len(images))-1
image = ast.literal_eval(str(images[number]))
image_url = image["murl"]
if len(images) == 0:
await ctx.send("Found no images")
else:
# Picks an image
number = random.randint(1,len(images))-1
image = ast.literal_eval(str(images[number]))
image_url = image["murl"]
self.bot.log("Picked image number "+str(number))
self.bot.log("Picked image number "+str(number))
# Returns the image
self.bot.log("Successfully returned an image")
# Returns the image
self.bot.log("Successfully returned an image")
await ctx.send(image_url)
await ctx.send(image_url)
# Finds a page from the Senkulpa Wikia
async def find_wiki_page(self, ctx, search : str):
await self.bot.defer(ctx)
found_page = False
# Finds a page from the Senkulpa Wikia
async def find_wiki_page(self, ctx, search : str):
await self.bot.defer(ctx)
found_page = False
if search != "":
self.bot.log("Trying to find wiki page for "+search)
search_results = fandom.search(search)
if len(search_results) > 0:
found_page = True
search_result = search_results[0]
else:
self.bot.log("Couldn't find the page")
await ctx.send("Couldn't find page")
else:
found_page = True
self.bot.log("Searching for a random page")
search_result = fandom.random()
if search != "":
self.bot.log("Trying to find wiki page for "+search)
search_results = fandom.search(search)
if len(search_results) > 0:
found_page = True
search_result = search_results[0]
else:
self.bot.log("Couldn't find the page")
await ctx.send("Couldn't find page")
else:
found_page = True
self.bot.log("Searching for a random page")
search_result = fandom.random()
if found_page:
self.bot.log(f"Found page \"{search_result[0]}\"")
page = fandom.page(pageid = search_result[1])
content = page.summary
if found_page:
self.bot.log(f"Found page \"{search_result[0]}\"")
page = fandom.page(pageid = search_result[1])
content = page.summary
images = page.images
if len(images) > 0:
image = images[0]
else:
image = ""
self.bot.log("Sending the embedded message",str(ctx.channel_id))
content += f"\n[Læs mere]({page.url})"
embed = discord.Embed(title = page.title, description = content, colour=0xDEADBF)
if image != "":
embed.set_thumbnail(url=image)
images = page.images
if len(images) > 0:
image = images[0]
else:
image = ""
self.bot.log("Sending the embedded message",str(ctx.channel_id))
content += f"\n[Læs mere]({page.url})"
embed = discord.Embed(title = page.title, description = content, colour=0xDEADBF)
if image != "":
embed.set_thumbnail(url=image)
await ctx.send(embed = embed)
await ctx.send(embed = embed)
async def roll_dice(self, ctx, roll_string):
user = ctx.author.display_name
while len(roll_string) > 1 and roll_string[0] == " ":
roll_string = roll_string[1:]
async def roll_dice(self, ctx, roll_string):
user = ctx.author.display_name
while len(roll_string) > 1 and roll_string[0] == " ":
roll_string = roll_string[1:]
roll = d20.roll(roll_string, allow_comments=True, stringifier=MyStringifier())
await ctx.send(f"{user} :game_die:\n{roll}")
roll = d20.roll(roll_string, allow_comments=True, stringifier=MyStringifier())
await ctx.send(f"{user} :game_die:\n{roll}")
async def help_func(self, ctx, command):
if command == "":
with open("gwendolyn/resources/help/help.txt",encoding="utf-8") as file_pointer:
text = file_pointer.read()
embed = discord.Embed(title = "Help", description = text,colour = 0x59f442)
await ctx.send(embed = embed)
else:
self.bot.log(f"Looking for help-{command}.txt",str(ctx.channel_id))
with open(f"gwendolyn/resources/help/help-{command}.txt",encoding="utf-8") as file_pointer:
text = file_pointer.read()
embed = discord.Embed(title = command.capitalize(), description = text,colour = 0x59f442)
await ctx.send(embed = embed)
async def help_func(self, ctx, command):
if command == "":
with open("gwendolyn/resources/help/help.txt",encoding="utf-8") as file_pointer:
text = file_pointer.read()
embed = discord.Embed(title = "Help", description = text,colour = 0x59f442)
await ctx.send(embed = embed)
else:
self.bot.log(f"Looking for help-{command}.txt",str(ctx.channel_id))
with open(f"gwendolyn/resources/help/help-{command}.txt",encoding="utf-8") as file_pointer:
text = file_pointer.read()
embed = discord.Embed(title = command.capitalize(), description = text,colour = 0x59f442)
await ctx.send(embed = embed)

File diff suppressed because it is too large Load Diff

View File

@@ -3,8 +3,8 @@ from .star_wars_roll import StarWarsRoll
from .star_wars_destiny import StarWarsDestiny
class StarWars():
def __init__(self, bot):
self.bot = bot
self.character = StarWarsChar(self.bot)
self.roll = StarWarsRoll(self.bot)
self.destiny = StarWarsDestiny(self.bot)
def __init__(self, bot):
self.bot = bot
self.character = StarWarsChar(self.bot)
self.roll = StarWarsRoll(self.bot)
self.destiny = StarWarsDestiny(self.bot)

File diff suppressed because it is too large Load Diff

View File

@@ -1,72 +1,72 @@
class StarWarsDestiny():
def __init__(self, bot):
self.bot = bot
def __init__(self, bot):
self.bot = bot
def destiny_new(self, num : int):
self.bot.log("Creating a new destiny pool with "+str(num)+" players")
roll, dice_results = self.bot.star_wars.roll.roll(0,0,0,0,0,0,num)
roll = "".join(sorted(roll))
def destiny_new(self, num : int):
self.bot.log("Creating a new destiny pool with "+str(num)+" players")
roll, dice_results = self.bot.star_wars.roll.roll(0,0,0,0,0,0,num)
roll = "".join(sorted(roll))
with open("gwendolyn/resources/star_wars/destinyPoints.txt","wt") as file_pointer:
file_pointer.write(roll)
return "Rolled for Destiny Points and got:\n"+self.bot.star_wars.roll.diceResultToEmoji(dice_results)+"\n"+self.bot.star_wars.roll.resultToEmoji(roll)
def destiny_use(self, user : str):
with open("gwendolyn/resources/star_wars/destinyPoints.txt","rt") as file_pointer:
points = file_pointer.read()
if user == "Nikolaj":
self.bot.log("Trying to use a dark side destiny point")
if 'B' in points:
points = points.replace("B","L",1)
points = "".join(sorted(points))
with open("gwendolyn/resources/star_wars/destinyPoints.txt","wt") as file_pointer:
file_pointer.write(roll)
return "Rolled for Destiny Points and got:\n"+self.bot.star_wars.roll.diceResultToEmoji(dice_results)+"\n"+self.bot.star_wars.roll.resultToEmoji(roll)
def destiny_use(self, user : str):
with open("gwendolyn/resources/star_wars/destinyPoints.txt","rt") as file_pointer:
points = file_pointer.read()
if user == "Nikolaj":
self.bot.log("Trying to use a dark side destiny point")
if 'B' in points:
points = points.replace("B","L",1)
points = "".join(sorted(points))
with open("gwendolyn/resources/star_wars/destinyPoints.txt","wt") as file_pointer:
file_pointer.write(points)
self.bot.log("Did it")
return "Used a dark side destiny point. Destiny pool is now:\n"+self.bot.star_wars.roll.resultToEmoji(points)
else:
self.bot.log("There were no dark side destiny points")
return "No dark side destiny points"
else:
self.bot.log("Trying to use a light side destiny point")
if 'L' in points:
points = points.replace("L","B",1)
points = "".join(sorted(points))
with open("gwendolyn/resources/star_wars/destinyPoints.txt","wt") as file_pointer:
file_pointer.write(points)
self.bot.log("Did it")
return "Used a light side destiny point. Destiny pool is now:\n"+self.bot.star_wars.roll.resultToEmoji(points)
else:
self.bot.log("There were no dark side destiny points")
return "No light side destiny points"
async def parse_destiny(self, ctx, cmd : str):
user = f"#{ctx.author.id}"
if cmd != "":
while cmd[0] == ' ':
cmd = cmd[1:]
if cmd == "":
break
file_pointer.write(points)
self.bot.log("Did it")
return "Used a dark side destiny point. Destiny pool is now:\n"+self.bot.star_wars.roll.resultToEmoji(points)
else:
self.bot.log("There were no dark side destiny points")
return "No dark side destiny points"
else:
self.bot.log("Trying to use a light side destiny point")
if 'L' in points:
points = points.replace("L","B",1)
points = "".join(sorted(points))
with open("gwendolyn/resources/star_wars/destinyPoints.txt","wt") as file_pointer:
file_pointer.write(points)
self.bot.log("Did it")
return "Used a light side destiny point. Destiny pool is now:\n"+self.bot.star_wars.roll.resultToEmoji(points)
else:
self.bot.log("There were no dark side destiny points")
return "No light side destiny points"
async def parse_destiny(self, ctx, cmd : str):
user = f"#{ctx.author.id}"
if cmd != "":
while cmd[0] == ' ':
cmd = cmd[1:]
if cmd == "":
self.bot.log("Retrieving destiny pool info")
with open("gwendolyn/resources/star_wars/destinyPoints.txt","rt") as file_pointer:
send_message = self.bot.star_wars.roll.resultToEmoji(file_pointer.read())
else:
commands = cmd.upper().split(" ")
if commands[0] == "N":
if len(commands) > 1:
send_message = self.destiny_new(int(commands[1]))
else:
send_message = "You need to give an amount of players"
elif commands[0] == "U":
send_message = self.destiny_use(user)
else:
send_message = "I didn't quite understand that"
break
message_list = send_message.split("\n")
await ctx.send(message_list[0])
if len(message_list) > 1:
for message_item in message_list[1:]:
await ctx.channel.send(message_item)
if cmd == "":
self.bot.log("Retrieving destiny pool info")
with open("gwendolyn/resources/star_wars/destinyPoints.txt","rt") as file_pointer:
send_message = self.bot.star_wars.roll.resultToEmoji(file_pointer.read())
else:
commands = cmd.upper().split(" ")
if commands[0] == "N":
if len(commands) > 1:
send_message = self.destiny_new(int(commands[1]))
else:
send_message = "You need to give an amount of players"
elif commands[0] == "U":
send_message = self.destiny_use(user)
else:
send_message = "I didn't quite understand that"
message_list = send_message.split("\n")
await ctx.send(message_list[0])
if len(message_list) > 1:
for message_item in message_list[1:]:
await ctx.channel.send(message_item)

View File

@@ -4,388 +4,388 @@ import string
import json
with open("gwendolyn/resources/star_wars/starwarsskills.json", "r") as f:
skill_data = json.load(f)
skill_data = json.load(f)
class StarWarsRoll():
def __init__(self, bot):
self.bot = bot
def __init__(self, bot):
self.bot = bot
# Rolls the specified dice
def roll(self, abi : int = 1, prof : int = 0, dif : int = 3, cha : int = 0, boo : int = 0, setb : int = 0, force : int = 0):
result = ""
dice_result = []
for _ in range(abi):
choice = random.choice(["","S","S","SS","A","A","SA","AA"])
result += choice
dice_result.append("abi"+choice)
# Rolls the specified dice
def roll(self, abi : int = 1, prof : int = 0, dif : int = 3, cha : int = 0, boo : int = 0, setb : int = 0, force : int = 0):
result = ""
dice_result = []
for _ in range(abi):
choice = random.choice(["","S","S","SS","A","A","SA","AA"])
result += choice
dice_result.append("abi"+choice)
for _ in range(prof):
choice = random.choice(["","S","S","SS","SS","A","SA","SA","SA","AA","AA","R"])
result += choice
dice_result.append("prof"+choice)
for _ in range(prof):
choice = random.choice(["","S","S","SS","SS","A","SA","SA","SA","AA","AA","R"])
result += choice
dice_result.append("prof"+choice)
for _ in range(dif):
choice = random.choice(["","F","FF","H","H","H","HH","FH"])
result += choice
dice_result.append("dif"+choice)
for _ in range(dif):
choice = random.choice(["","F","FF","H","H","H","HH","FH"])
result += choice
dice_result.append("dif"+choice)
for _ in range(cha):
choice = random.choice(["","F","F","FF","FF","H","H","FH","FH","HH","HH","D"])
result += choice
dice_result.append("cha"+choice)
for _ in range(cha):
choice = random.choice(["","F","F","FF","FF","H","H","FH","FH","HH","HH","D"])
result += choice
dice_result.append("cha"+choice)
for _ in range(boo):
choice = random.choice(["","","S","SA","AA","A"])
result += choice
dice_result.append("boo"+choice)
for _ in range(boo):
choice = random.choice(["","","S","SA","AA","A"])
result += choice
dice_result.append("boo"+choice)
for _ in range(setb):
choice = random.choice(["","","F","F","H","H"])
result += choice
dice_result.append("setb"+choice)
for _ in range(setb):
choice = random.choice(["","","F","F","H","H"])
result += choice
dice_result.append("setb"+choice)
for _ in range (force):
choice = random.choice(["B","B","B","B","B","B","BB","L","L","LL","LL","LL"])
result += choice
dice_result.append("force"+choice)
for _ in range (force):
choice = random.choice(["B","B","B","B","B","B","BB","L","L","LL","LL","LL"])
result += choice
dice_result.append("force"+choice)
return result, dice_result
return result, dice_result
# Lets dice cancel each other out
def simplify(self, result : str):
self.bot.log("Simplifying "+result)
simp = ""
success = (result.count('S') + result.count('R')) - (result.count('F') + result.count('D'))
advantage = result.count('A') - result.count('H')
result = re.sub("S|A|F|H","",result)
# Lets dice cancel each other out
def simplify(self, result : str):
self.bot.log("Simplifying "+result)
simp = ""
success = (result.count('S') + result.count('R')) - (result.count('F') + result.count('D'))
advantage = result.count('A') - result.count('H')
result = re.sub("S|A|F|H","",result)
if success > 0:
for _ in range(success):
simp += "S"
elif success < 0:
for _ in range(abs(success)):
simp += "F"
if success > 0:
for _ in range(success):
simp += "S"
elif success < 0:
for _ in range(abs(success)):
simp += "F"
if advantage > 0:
for _ in range(advantage):
simp += "A"
elif advantage < 0:
for _ in range(abs(advantage)):
simp += "H"
if advantage > 0:
for _ in range(advantage):
simp += "A"
elif advantage < 0:
for _ in range(abs(advantage)):
simp += "H"
simp += result
simp += result
return simp
return simp
# Returns emoji that symbolize the dice results
def dice_result_to_emoji(self, dice_results : list):
emoji = ""
for result in dice_results:
if result == "abiA":
emoji += "<:abil1a:695267684476125264> "
elif result == "abiSA":
emoji += "<:abil1a1s:695267684484513842> "
elif result == "abiS":
emoji += "<:abil1s:695267684514005013> "
elif result == "abiAA":
emoji += "<:abil2a:695267684547428352> "
elif result == "abiSS":
emoji += "<:abil2s:695267684761206914> "
elif result == "abi":
emoji += "<:abilbla:695267684660674602> "
# Returns emoji that symbolize the dice results
def dice_result_to_emoji(self, dice_results : list):
emoji = ""
for result in dice_results:
if result == "abiA":
emoji += "<:abil1a:695267684476125264> "
elif result == "abiSA":
emoji += "<:abil1a1s:695267684484513842> "
elif result == "abiS":
emoji += "<:abil1s:695267684514005013> "
elif result == "abiAA":
emoji += "<:abil2a:695267684547428352> "
elif result == "abiSS":
emoji += "<:abil2s:695267684761206914> "
elif result == "abi":
emoji += "<:abilbla:695267684660674602> "
elif result == "profA":
emoji += "<:prof1a:695267685361123338> "
elif result == "profSA":
emoji += "<:prof1a1s:695267685067653140> "
elif result == "profR":
emoji += "<:prof1r:695267685067522088> "
elif result == "profS":
emoji += "<:prof1s:695267684899881012> "
elif result == "profAA":
emoji += "<:prof2a:695267684996218982> "
elif result == "profSS":
emoji += "<:prof2s:695267684878647327> "
elif result == "prof":
emoji += "<:profbla:695267684698292235> "
elif result == "profA":
emoji += "<:prof1a:695267685361123338> "
elif result == "profSA":
emoji += "<:prof1a1s:695267685067653140> "
elif result == "profR":
emoji += "<:prof1r:695267685067522088> "
elif result == "profS":
emoji += "<:prof1s:695267684899881012> "
elif result == "profAA":
emoji += "<:prof2a:695267684996218982> "
elif result == "profSS":
emoji += "<:prof2s:695267684878647327> "
elif result == "prof":
emoji += "<:profbla:695267684698292235> "
elif result == "difF":
emoji += "<:dif1f:695267684924915804> "
elif result == "difH":
emoji += "<:dif1h:695267684908138506> "
elif result == "difFH":
emoji += "<:dif1h1f:695267684908269678> "
elif result == "difFF":
emoji += "<:dif2f:695267684924784680> "
elif result == "difHH":
emoji += "<:dif2h:695267685071585340> "
elif result == "dif":
emoji += "<:difbla:695267685000544276> "
elif result == "difF":
emoji += "<:dif1f:695267684924915804> "
elif result == "difH":
emoji += "<:dif1h:695267684908138506> "
elif result == "difFH":
emoji += "<:dif1h1f:695267684908269678> "
elif result == "difFF":
emoji += "<:dif2f:695267684924784680> "
elif result == "difHH":
emoji += "<:dif2h:695267685071585340> "
elif result == "dif":
emoji += "<:difbla:695267685000544276> "
elif result == "chaD":
emoji += "<:cha1d:695267684962533447> "
elif result == "chaF":
emoji += "<:cha1f:695267684601954346> "
elif result == "chaH":
emoji += "<:cha1h:695267685046681620> "
elif result == "chaFH":
emoji += "<:cha1h1f:695267685063327784> "
elif result == "chaFF":
emoji += "<:cha2f:695267684832641097> "
elif result == "chaHH":
emoji += "<:cha2h:695267684631183381> "
elif result == "cha":
emoji += "<:chabla:695267684895686787> "
elif result == "chaD":
emoji += "<:cha1d:695267684962533447> "
elif result == "chaF":
emoji += "<:cha1f:695267684601954346> "
elif result == "chaH":
emoji += "<:cha1h:695267685046681620> "
elif result == "chaFH":
emoji += "<:cha1h1f:695267685063327784> "
elif result == "chaFF":
emoji += "<:cha2f:695267684832641097> "
elif result == "chaHH":
emoji += "<:cha2h:695267684631183381> "
elif result == "cha":
emoji += "<:chabla:695267684895686787> "
elif result == "booA":
emoji += "<:boo1a:695267684975116329> "
elif result == "booSA":
emoji += "<:boo1a1s:695267684970922024> "
elif result == "booS":
emoji += "<:boo1s:695267684979441714> "
elif result == "booAA":
emoji += "<:boo2a:695267685100945488> "
elif result == "boo":
emoji += "<:boobla:695267684757012550> "
elif result == "booA":
emoji += "<:boo1a:695267684975116329> "
elif result == "booSA":
emoji += "<:boo1a1s:695267684970922024> "
elif result == "booS":
emoji += "<:boo1s:695267684979441714> "
elif result == "booAA":
emoji += "<:boo2a:695267685100945488> "
elif result == "boo":
emoji += "<:boobla:695267684757012550> "
elif result == "setbF":
emoji += "<:set1f:695267685054939197> "
elif result == "setbH":
emoji += "<:set1h:695267685147082802> "
elif result == "setb":
emoji += "<:setbla:695267685151408169> "
elif result == "setbF":
emoji += "<:set1f:695267685054939197> "
elif result == "setbH":
emoji += "<:set1h:695267685147082802> "
elif result == "setb":
emoji += "<:setbla:695267685151408169> "
elif result == "forceB":
emoji += "<:for1b:695267684593434677> "
elif result == "forceL":
emoji += "<:for1l:695267684606148640> "
elif result == "forceBB":
emoji += "<:for2b:695267684903944303> "
elif result == "forceLL":
emoji += "<:for2l:695267684992024626> "
elif result == "forceB":
emoji += "<:for1b:695267684593434677> "
elif result == "forceL":
emoji += "<:for1l:695267684606148640> "
elif result == "forceBB":
emoji += "<:for2b:695267684903944303> "
elif result == "forceLL":
emoji += "<:for2l:695267684992024626> "
return emoji
return emoji
# Returns emoji that symbolize the results of the dice rolls
def result_to_emoji(self, result : str):
emoji = ""
for char in result:
if char == 'S':
emoji += "<:success:826026925280854026> "
elif char == 'A':
emoji += "<:advantage:826026925515604009> "
elif char == 'R':
emoji += "<:triumph:826026925319127070> "
elif char == 'F':
emoji += "<:failure:826026925288980511> "
elif char == 'H':
emoji += "<:threat:826026925280985108> "
elif char == 'D':
emoji += "<:despair:826026925272203294> "
elif char == 'L':
emoji += "<:light:826026925059211295>"
elif char == 'B':
emoji += "<:dark:826026925289373717>"
# Returns emoji that symbolize the results of the dice rolls
def result_to_emoji(self, result : str):
emoji = ""
for char in result:
if char == 'S':
emoji += "<:success:826026925280854026> "
elif char == 'A':
emoji += "<:advantage:826026925515604009> "
elif char == 'R':
emoji += "<:triumph:826026925319127070> "
elif char == 'F':
emoji += "<:failure:826026925288980511> "
elif char == 'H':
emoji += "<:threat:826026925280985108> "
elif char == 'D':
emoji += "<:despair:826026925272203294> "
elif char == 'L':
emoji += "<:light:826026925059211295>"
elif char == 'B':
emoji += "<:dark:826026925289373717>"
return emoji
return emoji
# Converts emoji into letters
def emoji_to_result(self, emoji : str):
result = ""
for char in emoji:
if char == "<:light:691010089905029171>":
emoji += 'L'
if char == "<:dark:691010101901000852>":
emoji += 'B'
# Converts emoji into letters
def emoji_to_result(self, emoji : str):
result = ""
for char in emoji:
if char == "<:light:691010089905029171>":
emoji += 'L'
if char == "<:dark:691010101901000852>":
emoji += 'B'
return result
return result
# Returns emoji that symbolize the dice
def dice_to_emoji(self, dice : list):
emoji = ""
# Returns emoji that symbolize the dice
def dice_to_emoji(self, dice : list):
emoji = ""
for _ in range(dice[0]):
emoji += "<:ability:690974213397282826> "
for _ in range(dice[1]):
emoji += "<:proficiency:690973435354153071> "
for _ in range(dice[2]):
emoji += "<:difficulty:690973992470708296> "
for _ in range(dice[3]):
emoji += "<:challenge:690973419906400306> "
for _ in range(dice[4]):
emoji += "<:boost:690972178216386561> "
for _ in range(dice[5]):
emoji += "<:setback:690972157890658415> "
for _ in range(dice[6]):
emoji += "<:force:690973451883774013> "
for _ in range(dice[0]):
emoji += "<:ability:690974213397282826> "
for _ in range(dice[1]):
emoji += "<:proficiency:690973435354153071> "
for _ in range(dice[2]):
emoji += "<:difficulty:690973992470708296> "
for _ in range(dice[3]):
emoji += "<:challenge:690973419906400306> "
for _ in range(dice[4]):
emoji += "<:boost:690972178216386561> "
for _ in range(dice[5]):
emoji += "<:setback:690972157890658415> "
for _ in range(dice[6]):
emoji += "<:force:690973451883774013> "
return emoji
return emoji
# Rolls for obligation
def obligation_roll(self):
self.bot.log("Rolling for obligation")
data = self.bot.database["starwarscharacters"]
# Rolls for obligation
def obligation_roll(self):
self.bot.log("Rolling for obligation")
data = self.bot.database["starwarscharacters"]
table = []
table = []
for character in data:
for obligation in data[character]["Obligations"]:
for _ in range(data[character]["Obligations"][obligation]):
table.append(data[character]["Name"]+", "+obligation)
for character in data:
for obligation in data[character]["Obligations"]:
for _ in range(data[character]["Obligations"][obligation]):
table.append(data[character]["Name"]+", "+obligation)
while len(table) < 100:
table.append("Nothing")
while len(table) < 100:
table.append("Nothing")
return random.choice(table)
return random.choice(table)
# Rolls for critical injury
async def crit_roll(self, ctx, addington : int):
difficulty_die = "<:difficulty:690973992470708296>"
setback_die = "<:setback:690972157890658415>"
boost_die = "<:boost:690972178216386561>"
roll = random.randint(1,100) + addington
injuries = [
"**Minor nick**: The target suffers 1 strain, "+difficulty_die] * 5 + [
"**Slowed down**: The target can only act during the last allied initiative slot this turn, "+difficulty_die] * 5 + [
"**Sudden Jolt**: The target drops whatever is in hand, "+difficulty_die] * 5 + [
"**Distracted**: The target cannot perform a Free maneuver during his next turn, "+difficulty_die] * 5 + [
"**Off-Balance**: The target adds "+setback_die+" to his next skill check, "+difficulty_die] * 5 + [
"**Discouraging Wound**: Flip one light side Destiny point to a dark side Destiny point (reverse if NPC), "+difficulty_die] * 5 + [
"**Stunned**: The target is staggered until the end of his next turn, "+difficulty_die] * 5 + [
"**Stinger**: Increase the difficulty of next check by one, "+difficulty_die] * 5 + [
"**Bowled Over**: The target is knocked prone and suffers 1 strain, "+difficulty_die+difficulty_die] * 5 + [
"**Head Ringer**: The target increases the difficulty of all Intellect and Cunning checks by one until the end of the encounter, "+difficulty_die+difficulty_die] * 5 + [
"**Fearsome Wound**: The target increases the difficulty of all Presence and Willpower checks by one until the end of the encounter, "+difficulty_die+difficulty_die] * 5 + [
"**Agonizing Wound**: The target increases the difficulty of all Brawn and Agility checks by one until the end of the encounter, "+difficulty_die+difficulty_die] * 5 + [
"**Slightly Dazed**: The target is disoriented until the end of the encounter, "+difficulty_die+difficulty_die] * 5 + [
"**Scattered Senses**: The target removes all "+boost_die+" from skill checks until the end of the encounter, "+difficulty_die+difficulty_die] * 5 + [
"**Hamstrung**: The target loses his free maneuver until the end of the encounter, "+difficulty_die+difficulty_die] * 5 + [
"**Overpowered**: The target leaves himself open, and the attacker may immediately attempt another free attack agains him, using the exact same pool as the original, "+difficulty_die+difficulty_die] * 5 + [
"**Winded**: Until the end of the encounter, the target cannot voluntarily suffer strain to activate any abilities or gain additional maneuvers, "+difficulty_die+difficulty_die] * 5 + [
"**Compromised**: Incerase difficulty of all skill checks by one until the end of the encounter, "+difficulty_die+difficulty_die] * 5 + [
"**At the brink**: The target suffers 1 strain each time he performs an action, "+difficulty_die+difficulty_die+difficulty_die] * 5 + [
"**Crippled**: One of the target's limbs (selected by the GM) is crippled until healed or replaced. Increase difficulty of all checks that require use of that limb by one, "+difficulty_die+difficulty_die+difficulty_die] * 5 + [
"**Maimed**: One of the target's limbs (selected by the GM) is permanently lost. Unless the target has a cybernetic replacement, the target cannot perform actions that would require the use of that limb. All other actions gain "+setback_die+", "+difficulty_die+difficulty_die+difficulty_die] * 5 + [
"HI"] * 5 + [
"**Temporarily Lame**: Until this critical injury is healed, the target cannot perform more than one maneuver during his turn, "+difficulty_die+difficulty_die+difficulty_die] * 5 + [
"**Blinded**: The target can no longer see. Upgrade the difficulty of all checks twice. Upgrade the difficulty of perception checks three times, "+difficulty_die+difficulty_die+difficulty_die] * 5 + [
"**Knocked Senseless**: The target is staggered for the remainder of the encounter, "+difficulty_die+difficulty_die+difficulty_die] * 5 + [
"GI"] * 5 + [
"**Bleeding Out**: Every round, the target suffers 1 wound and 1 strain at the beginning of his turn. For every five wounds he suffers beyond his wound threshold, he suffers one additional critical injury. (If he suffers this one again, roll again), "+difficulty_die+difficulty_die+difficulty_die+difficulty_die] * 10 + [
"**The End is Nigh**: The target will die after the last initiative slot during the next round, "+difficulty_die+difficulty_die+difficulty_die+difficulty_die] * 10 + [
"**Dead**: U B Dead :("]
# Rolls for critical injury
async def crit_roll(self, ctx, addington : int):
difficulty_die = "<:difficulty:690973992470708296>"
setback_die = "<:setback:690972157890658415>"
boost_die = "<:boost:690972178216386561>"
roll = random.randint(1,100) + addington
injuries = [
"**Minor nick**: The target suffers 1 strain, "+difficulty_die] * 5 + [
"**Slowed down**: The target can only act during the last allied initiative slot this turn, "+difficulty_die] * 5 + [
"**Sudden Jolt**: The target drops whatever is in hand, "+difficulty_die] * 5 + [
"**Distracted**: The target cannot perform a Free maneuver during his next turn, "+difficulty_die] * 5 + [
"**Off-Balance**: The target adds "+setback_die+" to his next skill check, "+difficulty_die] * 5 + [
"**Discouraging Wound**: Flip one light side Destiny point to a dark side Destiny point (reverse if NPC), "+difficulty_die] * 5 + [
"**Stunned**: The target is staggered until the end of his next turn, "+difficulty_die] * 5 + [
"**Stinger**: Increase the difficulty of next check by one, "+difficulty_die] * 5 + [
"**Bowled Over**: The target is knocked prone and suffers 1 strain, "+difficulty_die+difficulty_die] * 5 + [
"**Head Ringer**: The target increases the difficulty of all Intellect and Cunning checks by one until the end of the encounter, "+difficulty_die+difficulty_die] * 5 + [
"**Fearsome Wound**: The target increases the difficulty of all Presence and Willpower checks by one until the end of the encounter, "+difficulty_die+difficulty_die] * 5 + [
"**Agonizing Wound**: The target increases the difficulty of all Brawn and Agility checks by one until the end of the encounter, "+difficulty_die+difficulty_die] * 5 + [
"**Slightly Dazed**: The target is disoriented until the end of the encounter, "+difficulty_die+difficulty_die] * 5 + [
"**Scattered Senses**: The target removes all "+boost_die+" from skill checks until the end of the encounter, "+difficulty_die+difficulty_die] * 5 + [
"**Hamstrung**: The target loses his free maneuver until the end of the encounter, "+difficulty_die+difficulty_die] * 5 + [
"**Overpowered**: The target leaves himself open, and the attacker may immediately attempt another free attack agains him, using the exact same pool as the original, "+difficulty_die+difficulty_die] * 5 + [
"**Winded**: Until the end of the encounter, the target cannot voluntarily suffer strain to activate any abilities or gain additional maneuvers, "+difficulty_die+difficulty_die] * 5 + [
"**Compromised**: Incerase difficulty of all skill checks by one until the end of the encounter, "+difficulty_die+difficulty_die] * 5 + [
"**At the brink**: The target suffers 1 strain each time he performs an action, "+difficulty_die+difficulty_die+difficulty_die] * 5 + [
"**Crippled**: One of the target's limbs (selected by the GM) is crippled until healed or replaced. Increase difficulty of all checks that require use of that limb by one, "+difficulty_die+difficulty_die+difficulty_die] * 5 + [
"**Maimed**: One of the target's limbs (selected by the GM) is permanently lost. Unless the target has a cybernetic replacement, the target cannot perform actions that would require the use of that limb. All other actions gain "+setback_die+", "+difficulty_die+difficulty_die+difficulty_die] * 5 + [
"HI"] * 5 + [
"**Temporarily Lame**: Until this critical injury is healed, the target cannot perform more than one maneuver during his turn, "+difficulty_die+difficulty_die+difficulty_die] * 5 + [
"**Blinded**: The target can no longer see. Upgrade the difficulty of all checks twice. Upgrade the difficulty of perception checks three times, "+difficulty_die+difficulty_die+difficulty_die] * 5 + [
"**Knocked Senseless**: The target is staggered for the remainder of the encounter, "+difficulty_die+difficulty_die+difficulty_die] * 5 + [
"GI"] * 5 + [
"**Bleeding Out**: Every round, the target suffers 1 wound and 1 strain at the beginning of his turn. For every five wounds he suffers beyond his wound threshold, he suffers one additional critical injury. (If he suffers this one again, roll again), "+difficulty_die+difficulty_die+difficulty_die+difficulty_die] * 10 + [
"**The End is Nigh**: The target will die after the last initiative slot during the next round, "+difficulty_die+difficulty_die+difficulty_die+difficulty_die] * 10 + [
"**Dead**: U B Dead :("]
if roll >= len(injuries):
results = injuries[-1]
if roll >= len(injuries):
results = injuries[-1]
else:
results = injuries[roll]
if results == "HI":
characteristic = random.choice(["brawn"] * 3 + ["agility"] * 3 + ["intellect", "cunning", "presence"])
results = "**Horrific Injury**: Until this criticil injury is healed, treat the target's "+characteristic+" as if it's one lower, "+difficulty_die+difficulty_die+difficulty_die
if results == "GI":
characteristic = random.choice(["brawn"] * 3 + ["agility"] * 3 + ["intellect", "cunning", "presence"])
results = "**Gruesome Injury**: The target's "+characteristic+" is permanently one lower, "+difficulty_die+difficulty_die+difficulty_die+difficulty_die
send_message = "Roll: "+str(roll)+"\nInjury:\n"+results
message_list = send_message.split("\n")
await ctx.send(message_list[0])
if len(message_list) > 1:
for message_item in message_list[1:]:
await ctx.channel.send(message_item)
# Parses the command into something the other functions understand
async def parse_roll(self, ctx, cmd : str = ""):
user = f"#{ctx.author.id}"
cmd = re.sub(' +',' ',cmd.upper()) + " "
if cmd[0] == " ":
cmd = cmd[1:]
cmd = self.bot.star_wars.character.replaceSpaces(string.capwords(cmd))
commands = cmd.split(" ")
valid_command = False
if commands[0] == "":
roll_parameters = [1,0,3,0,0,0,0]
else:
roll_parameters = [0,0,0,0,0,0,0]
if string.capwords(commands[0]) == "Obligations":
send_message = self.obligation_roll()
elif string.capwords(commands[0]) in skill_data:
self.bot.log("Oh look! This guy has skills!")
if self.bot.star_wars.character.userHasChar(user):
self.bot.log("They have a character. That much we know")
skill_level = self.bot.star_wars.character.char_data(user,"Skills " + string.capwords(commands[0]))
if string.capwords(commands[0]) == "Lightsaber":
self.bot.log("The skill is lightsaber")
char_level = self.bot.star_wars.character.char_data(user,"Characteristics " + self.bot.star_wars.character.lightsaberChar(user))
else:
results = injuries[roll]
char_level = self.bot.star_wars.character.char_data(user,"Characteristics " + skill_data[string.capwords(commands[0])])
if results == "HI":
characteristic = random.choice(["brawn"] * 3 + ["agility"] * 3 + ["intellect", "cunning", "presence"])
results = "**Horrific Injury**: Until this criticil injury is healed, treat the target's "+characteristic+" as if it's one lower, "+difficulty_die+difficulty_die+difficulty_die
ability_dice = abs(char_level-skill_level)
proficiency_dice = min(skill_level,char_level)
if results == "GI":
characteristic = random.choice(["brawn"] * 3 + ["agility"] * 3 + ["intellect", "cunning", "presence"])
results = "**Gruesome Injury**: The target's "+characteristic+" is permanently one lower, "+difficulty_die+difficulty_die+difficulty_die+difficulty_die
commands = [str(ability_dice)] + [str(proficiency_dice)] + commands[1:]
self.bot.log("Converted skill to dice")
valid_command = True
else:
self.bot.log("Okay, no they don't i guess")
send_message = "You don't have a user. You can make one with /starwarscharacter"
send_message = "Roll: "+str(roll)+"\nInjury:\n"+results
elif string.capwords(commands[0]) in ["Ranged","Piloting"]:
self.bot.log("They fucked up writing the name of a ranged or piloting skill")
if string.capwords(commands[0]) == "Ranged":
send_message = "Did you mean \"Ranged - Heavy\" or \"Ranged - Light\""
else:
send_message = "Did you mean \"Piloting - Planetary\" or \"Piloting - Space\""
else:
valid_command = True
message_list = send_message.split("\n")
await ctx.send(message_list[0])
if len(message_list) > 1:
for message_item in message_list[1:]:
await ctx.channel.send(message_item)
if valid_command:
self.bot.log("Converting commands to dice")
for i, command in enumerate(commands):
if command != "":
command = command.upper()
if command[0] == "A":
roll_parameters[0] = int(command.replace("A",""))
elif command[0] == "P":
roll_parameters[1] = int(command.replace("P",""))
elif command[0] == "D":
roll_parameters[2] = int(command.replace("D",""))
elif command[0] == "C":
roll_parameters[3] = int(command.replace("C",""))
elif command[0] == "B":
roll_parameters[4] = int(command.replace("B",""))
elif command[0] == "S":
roll_parameters[5] = int(command.replace("S",""))
elif command[0] == "F":
roll_parameters[6] = int(command.replace("F",""))
else:
roll_parameters[i] = int(command)
# Parses the command into something the other functions understand
async def parse_roll(self, ctx, cmd : str = ""):
user = f"#{ctx.author.id}"
cmd = re.sub(' +',' ',cmd.upper()) + " "
if cmd[0] == " ":
cmd = cmd[1:]
cmd = self.bot.star_wars.character.replaceSpaces(string.capwords(cmd))
commands = cmd.split(" ")
valid_command = False
self.bot.log("Rolling "+str(roll_parameters))
roll_results, dice_results = self.roll(roll_parameters[0],roll_parameters[1],roll_parameters[2],roll_parameters[3],roll_parameters[4],roll_parameters[5],roll_parameters[6])
if commands[0] == "":
roll_parameters = [1,0,3,0,0,0,0]
simplified = self.simplify(roll_results)
name = self.bot.star_wars.character.getChar_name(user)
self.bot.log("Returns results and simplified results")
if simplified == "":
send_message = name + " rolls: " + "\n" + self.dice_result_to_emoji(dice_results) + "\nEverything cancels out!"
else:
send_message = name + " rolls: " + "\n" + self.dice_result_to_emoji(dice_results) + "\n" + self.result_to_emoji(simplified)
message_list = send_message.split("\n")
await ctx.send(message_list[0])
if len(message_list) > 1:
for message_item in message_list[1:]:
if message_item == "":
self.bot.log("Tried to send empty message")
else:
roll_parameters = [0,0,0,0,0,0,0]
if string.capwords(commands[0]) == "Obligations":
send_message = self.obligation_roll()
elif string.capwords(commands[0]) in skill_data:
self.bot.log("Oh look! This guy has skills!")
if self.bot.star_wars.character.userHasChar(user):
self.bot.log("They have a character. That much we know")
skill_level = self.bot.star_wars.character.char_data(user,"Skills " + string.capwords(commands[0]))
if string.capwords(commands[0]) == "Lightsaber":
self.bot.log("The skill is lightsaber")
char_level = self.bot.star_wars.character.char_data(user,"Characteristics " + self.bot.star_wars.character.lightsaberChar(user))
else:
char_level = self.bot.star_wars.character.char_data(user,"Characteristics " + skill_data[string.capwords(commands[0])])
ability_dice = abs(char_level-skill_level)
proficiency_dice = min(skill_level,char_level)
commands = [str(ability_dice)] + [str(proficiency_dice)] + commands[1:]
self.bot.log("Converted skill to dice")
valid_command = True
else:
self.bot.log("Okay, no they don't i guess")
send_message = "You don't have a user. You can make one with /starwarscharacter"
elif string.capwords(commands[0]) in ["Ranged","Piloting"]:
self.bot.log("They fucked up writing the name of a ranged or piloting skill")
if string.capwords(commands[0]) == "Ranged":
send_message = "Did you mean \"Ranged - Heavy\" or \"Ranged - Light\""
else:
send_message = "Did you mean \"Piloting - Planetary\" or \"Piloting - Space\""
else:
valid_command = True
if valid_command:
self.bot.log("Converting commands to dice")
for i, command in enumerate(commands):
if command != "":
command = command.upper()
if command[0] == "A":
roll_parameters[0] = int(command.replace("A",""))
elif command[0] == "P":
roll_parameters[1] = int(command.replace("P",""))
elif command[0] == "D":
roll_parameters[2] = int(command.replace("D",""))
elif command[0] == "C":
roll_parameters[3] = int(command.replace("C",""))
elif command[0] == "B":
roll_parameters[4] = int(command.replace("B",""))
elif command[0] == "S":
roll_parameters[5] = int(command.replace("S",""))
elif command[0] == "F":
roll_parameters[6] = int(command.replace("F",""))
else:
roll_parameters[i] = int(command)
self.bot.log("Rolling "+str(roll_parameters))
roll_results, dice_results = self.roll(roll_parameters[0],roll_parameters[1],roll_parameters[2],roll_parameters[3],roll_parameters[4],roll_parameters[5],roll_parameters[6])
simplified = self.simplify(roll_results)
name = self.bot.star_wars.character.getChar_name(user)
self.bot.log("Returns results and simplified results")
if simplified == "":
send_message = name + " rolls: " + "\n" + self.dice_result_to_emoji(dice_results) + "\nEverything cancels out!"
else:
send_message = name + " rolls: " + "\n" + self.dice_result_to_emoji(dice_results) + "\n" + self.result_to_emoji(simplified)
message_list = send_message.split("\n")
await ctx.send(message_list[0])
if len(message_list) > 1:
for message_item in message_list[1:]:
if message_item == "":
self.bot.log("Tried to send empty message")
else:
await ctx.channel.send(message_item)
await ctx.channel.send(message_item)

View File

@@ -3,7 +3,7 @@ Contains the Gwendolyn class, a subclass of the discord command bot.
*Classes*
---------
Gwendolyn(discord.ext.commands.Bot)
Gwendolyn(discord.ext.commands.Bot)
"""
import os # Used for loading cogs in Gwendolyn.addCogs
import discord # Used for discord.Intents and discord.Status
@@ -14,119 +14,119 @@ 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)
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):
"""
A multifunctional Discord bot.
Stop the bot, and stop running games.
*Methods*
---------
log(messages: Union[str, list], channel: str = "",
level: int = 20)
stop(ctx: interactions.SlashContext)
defer(ctx: interactions.SlashContext)
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.
"""
# pylint: disable=too-many-instance-attributes
if f"#{ctx.author.id}" in self.options["admins"]:
await ctx.send("Pulling git repo and restarting...")
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)
await self.change_presence(status=discord.Status.offline)
self._add_clients_and_options()
self._add_util_classes()
self._add_function_containers()
self._add_cogs()
self.database_funcs.wipe_games()
if not self.options["testing"]:
git_client = git.cmd.Git("")
git_client.pull()
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)
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}")
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")
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")

View File

@@ -1,27 +1,27 @@
{
"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",
"Blackjack all players standing": "All players are standing. The dealer now shows his cards and draws.",
"Blackjack first round": ". You can also double down with \"/blackjack double\" or split with \"/blackjack split\"",
"Blackjack commands": "You have 2 minutes to either hit or stand with \"/blackjack hit\" or \"/blackjack stand\"{}. It's assumed you're standing if you don't make a choice.",
"Blackjack double": "Adding another {} GwendoBucks to {}'s bet and drawing another card.",
"Blackjack different cards": "You can only split if your cards have the same value",
"Blackjack split": "Splitting {}'s hand into 2. Adding their original bet to the second hand. You can use \"/blackjack hit/stand/double 1\" and \"/blackjack hit/stand/double 2\" to play the different hands.",
"Blackjack started": "Blackjack game started. Use the buttons or \"/blackjack bet [amount]\" to enter the game within the next 30 seconds.",
"Blackjack going on": "There's already a blackjack game going on. Try again in a few minutes.",
"Stock value": "The current {} stock is valued at **{}** GwendoBucks",
"Stock parameters": "You must give both a stock name and an amount of GwendoBucks you wish to spend.",
"Trivia going on": "There's already a trivia question going on. Try again in like, a minute",
"Trivia time up": "Time's up! The answer was \"*{}) {}*\". Anyone who answered that has gotten 1 GwendoBuck",
"Connect 4 going on": "There's already a connect 4 game going on in this channel",
"Connect 4 placed": "{} placed a piece in column {}. It's now {}'s turn",
"Hangman going on": "There's already a Hangman game going on in the channel",
"Hangman lost game": " You've guessed wrong six times and have lost the game.",
"Hangman guessed word": " You've guessed the word! Congratulations! Adding 15 GwendoBucks to your account",
"Already on Plex": "{} is either already on Plex, downloading, or not available",
"No torrent": "{}No torrent exists. Likely because the movie is not yet released on DVD",
"No torrents downloading": "There are no torrents downloading right. If the torrent you're looking for was added more than 24 hours ago, it might already be on Plex.",
"Update": "{}\nThis message will update every 10 seconds for {} more minutes\n```",
"No updates": "{}\nThis message will not update anymore\n```",
"Invalid parameters": "Invalid or repeated parameters. Use '/help downloading' to see valid parameters."
"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",
"Blackjack all players standing": "All players are standing. The dealer now shows his cards and draws.",
"Blackjack first round": ". You can also double down with \"/blackjack double\" or split with \"/blackjack split\"",
"Blackjack commands": "You have 2 minutes to either hit or stand with \"/blackjack hit\" or \"/blackjack stand\"{}. It's assumed you're standing if you don't make a choice.",
"Blackjack double": "Adding another {} GwendoBucks to {}'s bet and drawing another card.",
"Blackjack different cards": "You can only split if your cards have the same value",
"Blackjack split": "Splitting {}'s hand into 2. Adding their original bet to the second hand. You can use \"/blackjack hit/stand/double 1\" and \"/blackjack hit/stand/double 2\" to play the different hands.",
"Blackjack started": "Blackjack game started. Use the buttons or \"/blackjack bet [amount]\" to enter the game within the next 30 seconds.",
"Blackjack going on": "There's already a blackjack game going on. Try again in a few minutes.",
"Stock value": "The current {} stock is valued at **{}** GwendoBucks",
"Stock parameters": "You must give both a stock name and an amount of GwendoBucks you wish to spend.",
"Trivia going on": "There's already a trivia question going on. Try again in like, a minute",
"Trivia time up": "Time's up! The answer was \"*{}) {}*\". Anyone who answered that has gotten 1 GwendoBuck",
"Connect 4 going on": "There's already a connect 4 game going on in this channel",
"Connect 4 placed": "{} placed a piece in column {}. It's now {}'s turn",
"Hangman going on": "There's already a Hangman game going on in the channel",
"Hangman lost game": " You've guessed wrong six times and have lost the game.",
"Hangman guessed word": " You've guessed the word! Congratulations! Adding 15 GwendoBucks to your account",
"Already on Plex": "{} is either already on Plex, downloading, or not available",
"No torrent": "{}No torrent exists. Likely because the movie is not yet released on DVD",
"No torrents downloading": "There are no torrents downloading right. If the torrent you're looking for was added more than 24 hours ago, it might already be on Plex.",
"Update": "{}\nThis message will update every 10 seconds for {} more minutes\n```",
"No updates": "{}\nThis message will not update anymore\n```",
"Invalid parameters": "Invalid or repeated parameters. Use '/help downloading' to see valid parameters."
}

View File

@@ -1,401 +1,401 @@
{
"add_movie" : {
"name" : "add_movie",
"description" : "Request a movie for Plex",
"options" : [
{
"name" : "movie",
"description" : "The movie to request",
"type" : 3,
"required" : "true"
}
]
},
"add_show" : {
"name" : "add_show",
"description" : "Request a show for Plex",
"options" : [
{
"name" : "show",
"description" : "The show to request",
"type" : 3,
"required" : "true"
}
]
},
"balance" : {
"name" : "balance",
"description" : "See your balance of GwendoBucks"
},
"blackjack_bet" : {
"base" : "blackjack",
"name" : "bet",
"description" : "Enter the current blackjack game with a bet",
"options" : [
{
"name" : "bet",
"description" : "Your bet",
"type" : 4,
"required" : "true"
}
]
},
"blackjack_cards" : {
"base" : "blackjack",
"name" : "cards",
"description" : "Get a count of the cards used in blackjack games"
},
"blackjack_hilo" : {
"base" : "blackjack",
"name" : "hilo",
"description" : "Get the current hi-lo value for the cards used in blackjack games"
},
"blackjack_shuffle" : {
"base" : "blackjack",
"name" : "shuffle",
"description" : "Shuffle the cards used in blackjack games"
},
"blackjack_start" : {
"base" : "blackjack",
"name" : "start",
"description" : "Start a game of blackjack"
},
"connect_four_start_gwendolyn" : {
"base" : "connect_four",
"subcommand_group" : "start",
"name" : "Gwendolyn",
"description" : "Start a game of connect four against Gwendolyn",
"options" : [
{
"name" : "difficulty",
"description" : "The difficulty of Gwendolyn's AI",
"type" : 4,
"required" : "false"
}
]
},
"connect_four_start_user" : {
"base" : "connect_four",
"subcommand_group" : "start",
"name" : "user",
"description" : "Start a game of connect four against another user",
"options" : [
{
"name" : "user",
"description" : "The user to start a game against",
"type" : 6,
"required" : "true"
}
]
},
"downloading" : {
"name" : "downloading",
"description" : "See current downloads for Plex",
"options" : [
{
"name" : "parameters",
"description" : "Parameters for the command",
"type" : 3,
"required" : "false"
}
]
},
"game" : {
"name" : "game",
"description" : "Set the 'playing' text for Gwendolyn",
"options" : [
{
"name" : "game_text",
"description" : "The game to set the 'playing' text to",
"type" : 3,
"required" : "true"
}
]
},
"give" : {
"name" : "give",
"description" : "Give GwendoBucks to another user",
"options" : [
{
"name" : "user",
"description" : "The user you're sending GwendoBucks to",
"type" : 6,
"required" : "true"
},
{
"name" : "amount",
"description" : "The number of GwendoBucks you're sending",
"type" : 4,
"required" : "true"
}
]
},
"hangman" : {
"name" : "hangman",
"description" : "Start a game of hangman"
},
"hello" : {
"name" : "hello",
"description" : "Greet Gwendolyn"
},
"help" : {
"name" : "help",
"description" : "Get help with a command",
"options" : [
{
"name" : "command",
"description" : "The command you want help with",
"type" : 3,
"required" : "false"
}
]
},
"hex_place" : {
"base" : "hex",
"name" : "place",
"description" : "Place a piece on the hex board",
"options" : [
{
"name" : "coordinates",
"description" : "The coordinates to place the piece at",
"type" : 3,
"required" : "true"
}
]
},
"hex_start_gwendolyn" : {
"base" : "hex",
"subcommand_group" : "start",
"name" : "Gwendolyn",
"description" : "Start a game of hex against Gwendolyn",
"options" : [
{
"name" : "difficulty",
"description" : "The difficulty of Gwendolyn's AI",
"type" : 4,
"required" : "false"
}
]
},
"hex_start_user" : {
"base" : "hex",
"subcommand_group" : "start",
"name" : "user",
"description" : "Start a game of hex against another user",
"options" : [
{
"name" : "user",
"description" : "The user to start a game against",
"type" : 6,
"required" : "true"
}
]
},
"hex_surrender" : {
"base" : "hex",
"name" : "surrender",
"description" : "Surrender the game of hex"
},
"hex_swap" : {
"base" : "hex",
"name" : "swap",
"description" : "Perform a hex swap"
},
"hex_undo" : {
"base" : "hex",
"name" : "undo",
"description" : "Undo your last hex move"
},
"image" : {
"name" : "image",
"description" : "Get a random image from Bing"
},
"monster" : {
"name" : "monster",
"description" : "Look up a monster",
"options" : [
{
"name" : "query",
"description" : "The monster to look up",
"type" : 3,
"required" : "true"
}
]
},
"movie" : {
"add_movie" : {
"name" : "add_movie",
"description" : "Request a movie for Plex",
"options" : [
{
"name" : "movie",
"description" : "Get the name and information of a random movie"
},
"name" : {
"name" : "name",
"description" : "Generate a random name"
},
"ping" : {
"name" : "ping",
"description" : "Get the Gwendolyn's latency to the server"
},
"roll" : {
"name" : "roll",
"description" : "Roll rpg dice",
"options" : [
{
"name" : "dice",
"description" : "The dice to roll",
"type" : 3,
"required" : "false"
}
"description" : "The movie to request",
"type" : 3,
"required" : "true"
}
]
},
"add_show" : {
"name" : "add_show",
"description" : "Request a show for Plex",
"options" : [
{
"name" : "show",
"description" : "The show to request",
"type" : 3,
"required" : "true"
}
]
},
"balance" : {
"name" : "balance",
"description" : "See your balance of GwendoBucks"
},
"blackjack_bet" : {
"base" : "blackjack",
"name" : "bet",
"description" : "Enter the current blackjack game with a bet",
"options" : [
{
"name" : "bet",
"description" : "Your bet",
"type" : 4,
"required" : "true"
}
]
},
"blackjack_cards" : {
"base" : "blackjack",
"name" : "cards",
"description" : "Get a count of the cards used in blackjack games"
},
"blackjack_hilo" : {
"base" : "blackjack",
"name" : "hilo",
"description" : "Get the current hi-lo value for the cards used in blackjack games"
},
"blackjack_shuffle" : {
"base" : "blackjack",
"name" : "shuffle",
"description" : "Shuffle the cards used in blackjack games"
},
"blackjack_start" : {
"base" : "blackjack",
"name" : "start",
"description" : "Start a game of blackjack"
},
"connect_four_start_gwendolyn" : {
"base" : "connect_four",
"subcommand_group" : "start",
"name" : "Gwendolyn",
"description" : "Start a game of connect four against Gwendolyn",
"options" : [
{
"name" : "difficulty",
"description" : "The difficulty of Gwendolyn's AI",
"type" : 4,
"required" : "false"
}
]
},
"connect_four_start_user" : {
"base" : "connect_four",
"subcommand_group" : "start",
"name" : "user",
"description" : "Start a game of connect four against another user",
"options" : [
{
"name" : "user",
"description" : "The user to start a game against",
"type" : 6,
"required" : "true"
}
]
},
"downloading" : {
"name" : "downloading",
"description" : "See current downloads for Plex",
"options" : [
{
"name" : "parameters",
"description" : "Parameters for the command",
"type" : 3,
"required" : "false"
}
]
},
"game" : {
"name" : "game",
"description" : "Set the 'playing' text for Gwendolyn",
"options" : [
{
"name" : "game_text",
"description" : "The game to set the 'playing' text to",
"type" : 3,
"required" : "true"
}
]
},
"give" : {
"name" : "give",
"description" : "Give GwendoBucks to another user",
"options" : [
{
"name" : "user",
"description" : "The user you're sending GwendoBucks to",
"type" : 6,
"required" : "true"
},
{
"name" : "amount",
"description" : "The number of GwendoBucks you're sending",
"type" : 4,
"required" : "true"
}
]
},
"hangman" : {
"name" : "hangman",
"description" : "Start a game of hangman"
},
"hello" : {
"name" : "hello",
"description" : "Greet Gwendolyn"
},
"help" : {
"name" : "help",
"description" : "Get help with a command",
"options" : [
{
"name" : "command",
"description" : "The command you want help with",
"type" : 3,
"required" : "false"
}
]
},
"hex_place" : {
"base" : "hex",
"name" : "place",
"description" : "Place a piece on the hex board",
"options" : [
{
"name" : "coordinates",
"description" : "The coordinates to place the piece at",
"type" : 3,
"required" : "true"
}
]
},
"hex_start_gwendolyn" : {
"base" : "hex",
"subcommand_group" : "start",
"name" : "Gwendolyn",
"description" : "Start a game of hex against Gwendolyn",
"options" : [
{
"name" : "difficulty",
"description" : "The difficulty of Gwendolyn's AI",
"type" : 4,
"required" : "false"
}
]
},
"hex_start_user" : {
"base" : "hex",
"subcommand_group" : "start",
"name" : "user",
"description" : "Start a game of hex against another user",
"options" : [
{
"name" : "user",
"description" : "The user to start a game against",
"type" : 6,
"required" : "true"
}
]
},
"hex_surrender" : {
"base" : "hex",
"name" : "surrender",
"description" : "Surrender the game of hex"
},
"hex_swap" : {
"base" : "hex",
"name" : "swap",
"description" : "Perform a hex swap"
},
"hex_undo" : {
"base" : "hex",
"name" : "undo",
"description" : "Undo your last hex move"
},
"image" : {
"name" : "image",
"description" : "Get a random image from Bing"
},
"monster" : {
"name" : "monster",
"description" : "Look up a monster",
"options" : [
{
"name" : "query",
"description" : "The monster to look up",
"type" : 3,
"required" : "true"
}
]
},
"movie" : {
"name" : "movie",
"description" : "Get the name and information of a random movie"
},
"name" : {
"name" : "name",
"description" : "Generate a random name"
},
"ping" : {
"name" : "ping",
"description" : "Get the Gwendolyn's latency to the server"
},
"roll" : {
"name" : "roll",
"description" : "Roll rpg dice",
"options" : [
{
"name" : "dice",
"description" : "The dice to roll",
"type" : 3,
"required" : "false"
}
]
},
"spell" : {
"name" : "spell",
"description" : "Look up a spell",
"options" : [
{
"name" : "query",
"description" : "The spell to look up",
"type" : 3,
"required" : "true"
}
]
},
"star_wars_character" : {
"name" : "star_wars_character",
"description" : "Manage your Star Wars character sheet",
"options" : [
{
"name" : "parameters",
"description" : "The parameters for the command",
"type" : 3,
"required" : "false"
}
]
},
"star_wars_crit" : {
"name" : "star_wars_crit",
"description" : "Roll a Star Wars critical injury",
"options" : [
{
"name" : "severity",
"description" : "The severity of the hit",
"type" : 4,
"required" : "true"
}
]
},
"star_wars_destiny" : {
"name" : "star_wars_destiny",
"description" : "Use and see Star Wars Destiny points",
"options" : [
{
"name" : "parameters",
"description" : "The parameters for the command",
"type" : 3,
"required" : "false"
}
]
},
"star_wars_roll" : {
"name" : "star_wars_roll",
"description" : "Roll Star Wars dice",
"options" : [
{
"name" : "dice",
"description" : "The dice, or ability, to roll",
"type" : 3,
"required" : "false"
}
]
},
"stop" : {
"name" : "stop",
"description" : "Restart Gwendolyn"
},
"tavern" : {
"name" : "tavern",
"description" : "Generate a random tavern"
},
"thank" : {
"name" : "thank",
"description" : "Thank Gwendolyn for her service"
},
"trivia" : {
"name" : "trivia",
"description" : "Play a game of trivia",
"options" : [
{
"name" : "answer",
"description" : "Your answer to the trivia question",
"type" : 3,
"required" : "false",
"choices" : [
{
"name" : "a",
"value" : "a"
},
{
"name" : "b",
"value" : "b"
},
{
"name" : "c",
"value" : "c"
},
{
"name" : "d",
"value" : "d"
}
]
},
"spell" : {
"name" : "spell",
"description" : "Look up a spell",
"options" : [
{
"name" : "query",
"description" : "The spell to look up",
"type" : 3,
"required" : "true"
}
]
},
"star_wars_character" : {
"name" : "star_wars_character",
"description" : "Manage your Star Wars character sheet",
"options" : [
{
"name" : "parameters",
"description" : "The parameters for the command",
"type" : 3,
"required" : "false"
}
]
},
"star_wars_crit" : {
"name" : "star_wars_crit",
"description" : "Roll a Star Wars critical injury",
"options" : [
{
"name" : "severity",
"description" : "The severity of the hit",
"type" : 4,
"required" : "true"
}
]
},
"star_wars_destiny" : {
"name" : "star_wars_destiny",
"description" : "Use and see Star Wars Destiny points",
"options" : [
{
"name" : "parameters",
"description" : "The parameters for the command",
"type" : 3,
"required" : "false"
}
]
},
"star_wars_roll" : {
"name" : "star_wars_roll",
"description" : "Roll Star Wars dice",
"options" : [
{
"name" : "dice",
"description" : "The dice, or ability, to roll",
"type" : 3,
"required" : "false"
}
]
},
"stop" : {
"name" : "stop",
"description" : "Restart Gwendolyn"
},
"tavern" : {
"name" : "tavern",
"description" : "Generate a random tavern"
},
"thank" : {
"name" : "thank",
"description" : "Thank Gwendolyn for her service"
},
"trivia" : {
"name" : "trivia",
"description" : "Play a game of trivia",
"options" : [
{
"name" : "answer",
"description" : "Your answer to the trivia question",
"type" : 3,
"required" : "false",
"choices" : [
{
"name" : "a",
"value" : "a"
},
{
"name" : "b",
"value" : "b"
},
{
"name" : "c",
"value" : "c"
},
{
"name" : "d",
"value" : "d"
}
]
}
]
},
"wiki" : {
"name" : "wiki",
"description" : "Searches for and gets the info for a wiki page",
"options" : [
{
"name" : "page",
"description" : "The page to find",
"type" : 3,
"required" : "false"
}
]
},
"wolf" : {
"name" : "wolf",
"description" : "Performs a search on Wolfram Alpha",
"options" : [
{
"name" : "query",
"description" : "What to search for on Wolfram Alpha",
"type" : 3,
"required" : "true"
}
]
},
"wordle_start": {
"base": "wordle",
"name" : "start",
"description": "Start a game of wordle",
"options": [
{
"name": "letters",
"description" : "How many letters the word should be",
"type": 4,
"required": "false"
}
]
},
"wordle_guess": {
"base": "wordle",
"name" : "guess",
"description": "Guess a word in wordle",
"options": [
{
"name": "guess",
"description" : "Your guess",
"type": 3,
"required": "true"
}
]
}
}
]
},
"wiki" : {
"name" : "wiki",
"description" : "Searches for and gets the info for a wiki page",
"options" : [
{
"name" : "page",
"description" : "The page to find",
"type" : 3,
"required" : "false"
}
]
},
"wolf" : {
"name" : "wolf",
"description" : "Performs a search on Wolfram Alpha",
"options" : [
{
"name" : "query",
"description" : "What to search for on Wolfram Alpha",
"type" : 3,
"required" : "true"
}
]
},
"wordle_start": {
"base": "wordle",
"name" : "start",
"description": "Start a game of wordle",
"options": [
{
"name": "letters",
"description" : "How many letters the word should be",
"type": 4,
"required": "false"
}
]
},
"wordle_guess": {
"base": "wordle",
"name" : "guess",
"description": "Guess a word in wordle",
"options": [
{
"name": "guess",
"description" : "Your guess",
"type": 3,
"required": "true"
}
]
}
}

View File

@@ -1,36 +1,36 @@
{
"Astrogation" : "Intellect",
"Computers" : "Intellect",
"Cool" : "Presence",
"Vigilance" : "Willpower",
"Mechanics" : "Intellect",
"Melee" : "Brawn",
"Perception" : "Cunning",
"Piloting-space" : "Agility",
"Ranged-heavy" : "Agility",
"Ranged-light" : "Agility",
"Athletics" : "Brawn",
"Coercion" : "Willpower",
"Coordination" : "Agility",
"Charm" : "Presence",
"Medicine" : "Intellect",
"Negotiation" : "Presence",
"Piloting-planetary" : "Agility",
"Stealth" : "Agility",
"skulduggery" : "Cunning",
"Brawl" : "Brawn",
"Discipline" : "Willpower",
"Gunnery" : "Agility",
"Core-worlds" : "Intellect",
"Outer-rim" : "Intellect",
"Underworld" : "Intellect",
"Leadership" : "Presence",
"Lore" : "Intellect",
"Resilience" : "Brawn",
"Streetwise" : "Cunning",
"Survival" : "Cunning",
"Xenology" : "Intellect",
"Lightsaber" : "Brawn",
"Education" : "Intellect",
"Deception" : "Cunning"
"Astrogation" : "Intellect",
"Computers" : "Intellect",
"Cool" : "Presence",
"Vigilance" : "Willpower",
"Mechanics" : "Intellect",
"Melee" : "Brawn",
"Perception" : "Cunning",
"Piloting-space" : "Agility",
"Ranged-heavy" : "Agility",
"Ranged-light" : "Agility",
"Athletics" : "Brawn",
"Coercion" : "Willpower",
"Coordination" : "Agility",
"Charm" : "Presence",
"Medicine" : "Intellect",
"Negotiation" : "Presence",
"Piloting-planetary" : "Agility",
"Stealth" : "Agility",
"skulduggery" : "Cunning",
"Brawl" : "Brawn",
"Discipline" : "Willpower",
"Gunnery" : "Agility",
"Core-worlds" : "Intellect",
"Outer-rim" : "Intellect",
"Underworld" : "Intellect",
"Leadership" : "Presence",
"Lore" : "Intellect",
"Resilience" : "Brawn",
"Streetwise" : "Cunning",
"Survival" : "Cunning",
"Xenology" : "Intellect",
"Lightsaber" : "Brawn",
"Education" : "Intellect",
"Deception" : "Cunning"
}

View File

@@ -1,82 +1,82 @@
{
"Character": {
"Name": "New Character",
"Species": "",
"Career": "",
"Specialization-trees": [],
"Soak": 0,
"Wound-threshold": 0,
"Wounds": 0,
"Strain-threshold": 0,
"Strain": 0,
"Defense-ranged": 0,
"Defense-melee": 0,
"Force-rating": 0,
"Characteristics": {
"Brawn": 2,
"Agility": 2,
"Intellect": 2,
"Cunning": 2,
"Willpower": 2,
"Presence": 2
},
"Skills": {
"Astrogation": 0,
"Athletics": 0,
"Brawl": 0,
"Charm": 0,
"Coercion": 0,
"Computers": 0,
"Cool": 0,
"Coordination": 0,
"Core-worlds": 0,
"Discipline": 0,
"Deception": 0,
"Education": 0,
"Gunnery": 0,
"Leadership": 0,
"Lightsaber": 0,
"Lore": 0,
"Mechanics": 0,
"Medicine": 0,
"Melee": 0,
"Negotiation": 0,
"Outer-rim": 0,
"Perception": 0,
"Piloting-planetary": 0,
"Piloting-space": 0,
"Ranged-heavy": 0,
"Ranged-light": 0,
"Resilience": 0,
"skulduggery": 0,
"Stealth": 0,
"Streetwise": 0,
"Survival": 0,
"Underworld": 0,
"Vigilance": 0,
"Xenology": 0
},
"Lightsaber-characteristic": "Brawn",
"Obligations": {},
"Morality": {
"Weakness": "",
"Strength": "",
"Conflict": "",
"Morality": ""
},
"Credits": 0,
"Equipment": [],
"Armor": "",
"Critical-injuries": {},
"Weapons": {},
"Talents": {},
"Force-powers": {}
"Character": {
"Name": "New Character",
"Species": "",
"Career": "",
"Specialization-trees": [],
"Soak": 0,
"Wound-threshold": 0,
"Wounds": 0,
"Strain-threshold": 0,
"Strain": 0,
"Defense-ranged": 0,
"Defense-melee": 0,
"Force-rating": 0,
"Characteristics": {
"Brawn": 2,
"Agility": 2,
"Intellect": 2,
"Cunning": 2,
"Willpower": 2,
"Presence": 2
},
"Weapon": {
"Skill" : "",
"Damage" : 0,
"Range" : "",
"Crit" : 0,
"Special" : []
}
"Skills": {
"Astrogation": 0,
"Athletics": 0,
"Brawl": 0,
"Charm": 0,
"Coercion": 0,
"Computers": 0,
"Cool": 0,
"Coordination": 0,
"Core-worlds": 0,
"Discipline": 0,
"Deception": 0,
"Education": 0,
"Gunnery": 0,
"Leadership": 0,
"Lightsaber": 0,
"Lore": 0,
"Mechanics": 0,
"Medicine": 0,
"Melee": 0,
"Negotiation": 0,
"Outer-rim": 0,
"Perception": 0,
"Piloting-planetary": 0,
"Piloting-space": 0,
"Ranged-heavy": 0,
"Ranged-light": 0,
"Resilience": 0,
"skulduggery": 0,
"Stealth": 0,
"Streetwise": 0,
"Survival": 0,
"Underworld": 0,
"Vigilance": 0,
"Xenology": 0
},
"Lightsaber-characteristic": "Brawn",
"Obligations": {},
"Morality": {
"Weakness": "",
"Strength": "",
"Conflict": "",
"Morality": ""
},
"Credits": 0,
"Equipment": [],
"Armor": "",
"Critical-injuries": {},
"Weapons": {},
"Talents": {},
"Force-powers": {}
},
"Weapon": {
"Skill" : "",
"Damage" : 0,
"Range" : "",
"Crit" : 0,
"Special" : []
}
}

View File

@@ -1,74 +1,74 @@
{
"json":{
"gwendolyn/resources/lookup/spells.json" : {
"Fireball" : {
"casting_time" : "1 action",
"components" : "V, S, M (a tiny ball of bat guano and sulfur)",
"description" : "A bright streak flashes from your pointing finger to a point you choose within range and then blossoms with a low roar into an explosion of flame. Each creature in a 20-foot-radius sphere centered on that point must make a Dexterity saving throw. A target takes 8d6 fire damage on a failed save, or half as much damage on a successful one. The fire spreads around corners. It ignites flammable objects in the area that arent being worn or carried. At Higher Levels. When you cast this spell using a spell slot of 4th level or higher, the damage increases by 1d6 for each slot level above 3rd.",
"duration" : "Instantaneous",
"level" : "3rd",
"range" : "150 feet",
"school" : "Evocation",
"ritual" : false
}
},
"gwendolyn/resources/lookup/monsters.json" : [
{
"name": "Bandit",
"size": "Medium",
"type": "humanoid",
"subtype": "any race",
"alignment": "any non-lawful alignment",
"armor_class": 12,
"hit_points": 11,
"hit_dice": "2d8",
"speed": "30 ft.",
"strength": 11,
"dexterity": 12,
"constitution": 12,
"intelligence": 10,
"wisdom": 10,
"charisma": 10,
"damage_vulnerabilities": "",
"damage_resistances": "",
"damage_immunities": "",
"condition_immunities": "",
"senses": "passive Perception 10",
"languages": "any one language (usually Common)",
"challenge_rating": "1/8",
"actions": [
{
"name": "Scimitar",
"desc": "Melee Weapon Attack: +3 to hit, reach 5 ft., one target. Hit: 4 (1d6 + 1) slashing damage.",
"attack_bonus": 3,
"damage_dice": "1d6",
"damage_bonus": 1
},
{
"name": "Light Crossbow",
"desc": "Ranged Weapon Attack: +3 to hit, range 80 ft./320 ft., one target. Hit: 5 (1d8 + 1) piercing damage.",
"attack_bonus": 3,
"damage_dice": "1d8",
"damage_bonus": 1
}
]
}
"json":{
"gwendolyn/resources/lookup/spells.json" : {
"Fireball" : {
"casting_time" : "1 action",
"components" : "V, S, M (a tiny ball of bat guano and sulfur)",
"description" : "A bright streak flashes from your pointing finger to a point you choose within range and then blossoms with a low roar into an explosion of flame. Each creature in a 20-foot-radius sphere centered on that point must make a Dexterity saving throw. A target takes 8d6 fire damage on a failed save, or half as much damage on a successful one. The fire spreads around corners. It ignites flammable objects in the area that arent being worn or carried. At Higher Levels. When you cast this spell using a spell slot of 4th level or higher, the damage increases by 1d6 for each slot level above 3rd.",
"duration" : "Instantaneous",
"level" : "3rd",
"range" : "150 feet",
"school" : "Evocation",
"ritual" : false
}
},
"gwendolyn/resources/lookup/monsters.json" : [
{
"name": "Bandit",
"size": "Medium",
"type": "humanoid",
"subtype": "any race",
"alignment": "any non-lawful alignment",
"armor_class": 12,
"hit_points": 11,
"hit_dice": "2d8",
"speed": "30 ft.",
"strength": 11,
"dexterity": 12,
"constitution": 12,
"intelligence": 10,
"wisdom": 10,
"charisma": 10,
"damage_vulnerabilities": "",
"damage_resistances": "",
"damage_immunities": "",
"condition_immunities": "",
"senses": "passive Perception 10",
"languages": "any one language (usually Common)",
"challenge_rating": "1/8",
"actions": [
{
"name": "Scimitar",
"desc": "Melee Weapon Attack: +3 to hit, reach 5 ft., one target. Hit: 4 (1d6 + 1) slashing damage.",
"attack_bonus": 3,
"damage_dice": "1d6",
"damage_bonus": 1
},
{
"name": "Light Crossbow",
"desc": "Ranged Weapon Attack: +3 to hit, range 80 ft./320 ft., one target. Hit: 5 (1d8 + 1) piercing damage.",
"attack_bonus": 3,
"damage_dice": "1d8",
"damage_bonus": 1
}
]
},
"txt": {
"gwendolyn/resources/star_wars/destinyPoints.txt": "",
"gwendolyn/resources/movies.txt": "The Room",
"gwendolyn/resources/names.txt": "Gandalf\n",
"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" : [
"gwendolyn/resources/lookup",
"gwendolyn/resources/games/blackjack_tables",
"gwendolyn/resources/games/connect_four_boards",
"gwendolyn/resources/games/hex_boards",
"gwendolyn/resources/games/hangman_boards",
"gwendolyn/resources/plex",
"gwendolyn/resources/games/old_images"
}
]
},
"txt": {
"gwendolyn/resources/star_wars/destinyPoints.txt": "",
"gwendolyn/resources/movies.txt": "The Room",
"gwendolyn/resources/names.txt": "Gandalf\n",
"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" : [
"gwendolyn/resources/lookup",
"gwendolyn/resources/games/blackjack_tables",
"gwendolyn/resources/games/connect_four_boards",
"gwendolyn/resources/games/hex_boards",
"gwendolyn/resources/games/hangman_boards",
"gwendolyn/resources/plex",
"gwendolyn/resources/games/old_images"
]
}

View File

@@ -1,12 +1,12 @@
"""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"]
"ErrorHandler", "get_params", "log_this", "cap", "make_files",
"replace_multiple", "emoji_to_command"]
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)
replace_multiple, emoji_to_command, long_strings,
sanitize, get_options, get_credentials, encode_id,
decode_id)

View File

@@ -3,15 +3,15 @@ Classes used to handle bot events and errors.
*Classes*
---------
EventHandler
ErrorHandler
EventHandler
ErrorHandler
"""
import traceback # Used to get the traceback of errors
import discord # Used to init discord.Game and discord.Status, as well
# as compare errors to discord errors and as typehints
# as compare errors to discord errors and as typehints
from discord.ext import commands # Used to compare errors with command
# errors
# errors
from interactions import SlashContext, ComponentContext
from gwendolyn_old.utils.util_functions import decode_id
@@ -19,88 +19,88 @@ from gwendolyn_old.exceptions import InvalidInteraction
class EventHandler():
"""
Handles bot events.
"""
Handles bot events.
*Methods*
---------
on_ready()
on_slash_command(ctx: interactions.SlashContext)
on_reaction_add(ctx: interactions.SlashContext)
"""
*Methods*
---------
on_ready()
on_slash_command(ctx: interactions.SlashContext)
on_reaction_add(ctx: interactions.SlashContext)
"""
def __init__(self, bot):
"""Initialize the handler."""
self.bot = bot
def __init__(self, bot):
"""Initialize the handler."""
self.bot = bot
async def on_ready(self):
"""Log and sets status when it logs in."""
await self.bot.database_funcs.imdb_commands()
name = self.bot.user.name
userid = str(self.bot.user.id)
logged_in_message = f"Logged in as {name}, {userid}"
self.bot.log(logged_in_message, level=25)
game = discord.Game("Use /help for commands")
async def on_ready(self):
"""Log and sets status when it logs in."""
await self.bot.database_funcs.imdb_commands()
name = self.bot.user.name
userid = str(self.bot.user.id)
logged_in_message = f"Logged in as {name}, {userid}"
self.bot.log(logged_in_message, level=25)
game = discord.Game("Use /help for commands")
online_status = discord.Status.online
await self.bot.change_presence(activity=game, status=online_status)
online_status = discord.Status.online
await self.bot.change_presence(activity=game, status=online_status)
async def on_slash_command(self, ctx: SlashContext):
"""Log when a slash command is given."""
if ctx.subcommand_name is not None:
subcommand = f" {ctx.subcommand_name} "
else:
subcommand = " "
async def on_slash_command(self, ctx: SlashContext):
"""Log when a slash command is given."""
if ctx.subcommand_name is not None:
subcommand = f" {ctx.subcommand_name} "
else:
subcommand = " "
if ctx.subcommand_group is not None:
sub_command_group = f"{ctx.subcommand_group} "
else:
sub_command_group = ""
if ctx.subcommand_group is not None:
sub_command_group = f"{ctx.subcommand_group} "
else:
sub_command_group = ""
args = " ".join([str(i) for i in ctx.args])
full_command = f"/{ctx.command}{subcommand}{sub_command_group}{args}"
log_message = f"{ctx.author.display_name} ran {full_command}"
self.bot.log(log_message, str(ctx.channel_id), level=25)
args = " ".join([str(i) for i in ctx.args])
full_command = f"/{ctx.command}{subcommand}{sub_command_group}{args}"
log_message = f"{ctx.author.display_name} ran {full_command}"
self.bot.log(log_message, str(ctx.channel_id), level=25)
async def on_component(self, ctx: ComponentContext):
"""Handle component interaction."""
info = decode_id(ctx.custom_id)
self.bot.log(f"Component action with info {info}")
channel = ctx.channel
author = str(ctx.author_id)
async def on_component(self, ctx: ComponentContext):
"""Handle component interaction."""
info = decode_id(ctx.custom_id)
self.bot.log(f"Component action with info {info}")
channel = ctx.channel
author = str(ctx.author_id)
if info[0].lower() == "plex":
if info[1].lower() == "movie":
await self.bot.other.plex.add_movie(
ctx.origin_message,
info[2],
not isinstance(channel, discord.DMChannel)
)
return
if info[0].lower() == "plex":
if info[1].lower() == "movie":
await self.bot.other.plex.add_movie(
ctx.origin_message,
info[2],
not isinstance(channel, discord.DMChannel)
)
return
elif info[1].lower() == "show":
await self.bot.other.plex.add_show(
ctx.origin_message,
info[2],
not isinstance(channel, discord.DMChannel)
)
else:
raise InvalidInteraction(ctx.custom_id, info)
elif info[1].lower() == "show":
await self.bot.other.plex.add_show(
ctx.origin_message,
info[2],
not isinstance(channel, discord.DMChannel)
)
else:
raise InvalidInteraction(ctx.custom_id, info)
elif info[0].lower() == "hangman" and author == info[2]:
if info[1].lower() == "guess":
await self.bot.games.hangman.guess(ctx, *info[3:])
elif info[1].lower() == "end":
await self.bot.games.hangman.stop(ctx, *info[3:])
else:
raise InvalidInteraction(ctx.custom_id, info)
elif info[0].lower() == "connectfour":
connect_four = self.bot.games.connect_four
if info[1].lower() == "place" and author == info[2]:
await connect_four.place_piece(
ctx,
info[3],
int(info[4]),
elif info[0].lower() == "hangman" and author == info[2]:
if info[1].lower() == "guess":
await self.bot.games.hangman.guess(ctx, *info[3:])
elif info[1].lower() == "end":
await self.bot.games.hangman.stop(ctx, *info[3:])
else:
raise InvalidInteraction(ctx.custom_id, info)
elif info[0].lower() == "connectfour":
connect_four = self.bot.games.connect_four
if info[1].lower() == "place" and author == info[2]:
await connect_four.place_piece(
ctx,
info[3],
int(info[4]),
[int(info[5]), int(info[6])],
int(info[7]),
ctx.author_id,

View File

@@ -3,7 +3,7 @@ Contains classes used for utilities.
*Classes*
---------
DatabaseFuncs()
DatabaseFuncs()
"""
import os # Used to test if files exist
import time # Used to test how long it's been since commands were synced
@@ -13,161 +13,161 @@ import discord # Used for type hints
class DatabaseFuncs():
"""
Manages database functions.
"""
Manages database functions.
*Methods*
*Methods*
---------
get_name(user_id: str) -> str
get_id(user_name: str) -> str
delete_game(game_type: str, channel: str)
wipe_games()
connect_four_reaction_test(message: discord.Message,
user: discord.User) -> bool
imdb_commands()
"""
def __init__(self, bot):
"""Initialize the class."""
self.bot = bot
def get_name(self, user_id: str):
"""
Get the name of a user you have the # id of.
*Parameters:
------------
user_id: str
The id of the user you want the name of. The format is
"#" + str(discord.User.id)
*Returns*
---------
get_name(user_id: str) -> str
get_id(user_name: str) -> str
delete_game(game_type: str, channel: str)
wipe_games()
connect_four_reaction_test(message: discord.Message,
user: discord.User) -> bool
imdb_commands()
user_name: str
The name of the user. If the user couldn't be found,
returns the user_id.
"""
user = self.bot.database["users"].find_one({"_id": user_id})
def __init__(self, bot):
"""Initialize the class."""
self.bot = bot
if user_id == f"#{self.bot.user.id}":
return_name = "Gwendolyn"
elif user is not None:
return_name = user["user name"]
else:
self.bot.log(f"Couldn't find user {user_id}")
return_name = user_id
def get_name(self, user_id: str):
"""
Get the name of a user you have the # id of.
return return_name
*Parameters:
------------
user_id: str
The id of the user you want the name of. The format is
"#" + str(discord.User.id)
def get_id(self, user_name: str):
"""
Get the id of a user you have the username of.
*Returns*
---------
user_name: str
The name of the user. If the user couldn't be found,
returns the user_id.
"""
user = self.bot.database["users"].find_one({"_id": user_id})
*Parameters:
------------
user_name: str
The name of the user you want the id of.
if user_id == f"#{self.bot.user.id}":
return_name = "Gwendolyn"
elif user is not None:
return_name = user["user name"]
else:
self.bot.log(f"Couldn't find user {user_id}")
return_name = user_id
*Returns*
---------
user_id: str
The id of the user in the format "#" +
str(discord.User.id). If the user couldn't be found,
returns the user_name.
"""
user_search = {"user name": re.compile(user_name, re.IGNORECASE)}
user = self.bot.database["users"].find_one(user_search)
return return_name
if user is not None:
return_id = user["_id"]
else:
self.bot.log("Couldn't find user "+user_name)
return_id = None
def get_id(self, user_name: str):
"""
Get the id of a user you have the username of.
return return_id
*Parameters:
------------
user_name: str
The name of the user you want the id of.
def delete_game(self, game_type: str, channel: str):
"""
Remove a game from the database.
*Returns*
---------
user_id: str
The id of the user in the format "#" +
str(discord.User.id). If the user couldn't be found,
returns the user_name.
"""
user_search = {"user name": re.compile(user_name, re.IGNORECASE)}
user = self.bot.database["users"].find_one(user_search)
*Parameters*
------------
game_type: 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[game_type].delete_one({"_id": channel})
if user is not None:
return_id = user["_id"]
else:
self.bot.log("Couldn't find user "+user_name)
return_id = None
def wipe_games(self):
"""Delete all running games and pull from git."""
game_types = [
"trivia questions",
"blackjack games",
"connect 4 games"
"hex games",
"wordle games"
]
for game_type in game_types:
self.bot.database[game_type].delete_many({})
return return_id
def connect_four_reaction_test(self, message: discord.Message,
user: discord.User):
"""
Test if the given message is the current connect four game.
def delete_game(self, game_type: str, channel: str):
"""
Remove a game from the database.
Also tests if the given user is the one who's turn it is.
*Parameters*
------------
game_type: 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[game_type].delete_one({"_id": channel})
*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
channel_search = {"_id": str(channel.id)}
game = self.bot.database["connect 4 games"].find_one(channel_search)
def wipe_games(self):
"""Delete all running games and pull from git."""
game_types = [
"trivia questions",
"blackjack games",
"connect 4 games"
"hex games",
"wordle games"
]
for game_type in game_types:
self.bot.database[game_type].delete_many({})
old_images_path = "gwendolyn/resources/games/old_images/"
file_path = old_images_path + f"connect_four{channel.id}"
if os.path.isfile(file_path):
with open(file_path, "r", encoding="utf-8") as file_pointer:
old_image = int(file_pointer.read())
else:
old_image = 0
def connect_four_reaction_test(self, message: discord.Message,
user: discord.User):
"""
Test if the given message is the current connect four game.
if message.id == old_image:
self.bot.log("They reacted to the connect_four game")
turn = game["turn"]
if user == game["players"][turn]:
valid_reaction = True
else:
self.bot.log("It wasn't their turn")
valid_reaction = False
else:
valid_reaction = False
Also tests if the given user is the one who's turn it is.
return valid_reaction
*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
channel_search = {"_id": str(channel.id)}
game = self.bot.database["connect 4 games"].find_one(channel_search)
old_images_path = "gwendolyn/resources/games/old_images/"
file_path = old_images_path + f"connect_four{channel.id}"
if os.path.isfile(file_path):
with open(file_path, "r", encoding="utf-8") as file_pointer:
old_image = int(file_pointer.read())
else:
old_image = 0
if message.id == old_image:
self.bot.log("They reacted to the connect_four game")
turn = game["turn"]
if user == game["players"][turn]:
valid_reaction = True
else:
self.bot.log("It wasn't their turn")
valid_reaction = False
else:
valid_reaction = False
return valid_reaction
async def imdb_commands(self):
"""Sync the slash commands with the discord API."""
collection = self.bot.database["last synced"]
last_synced = collection.find_one()
now = time.time()
if last_synced["last synced"] < now - 86400:
slash_command_list = await self.bot.slash.to_dict()
self.bot.log(f"Updating commands: {slash_command_list}")
await self.bot.slash.sync_all_commands()
id_number = last_synced["_id"]
query_filter = {"_id": id_number}
update = {"$set": {"last synced": now}}
collection.update_one(query_filter, update)
async def imdb_commands(self):
"""Sync the slash commands with the discord API."""
collection = self.bot.database["last synced"]
last_synced = collection.find_one()
now = time.time()
if last_synced["last synced"] < now - 86400:
slash_command_list = await self.bot.slash.to_dict()
self.bot.log(f"Updating commands: {slash_command_list}")
await self.bot.slash.sync_all_commands()
id_number = last_synced["_id"]
query_filter = {"_id": id_number}
update = {"$set": {"last synced": now}}
collection.update_one(query_filter, update)

12
main.py
View File

@@ -4,13 +4,13 @@ from gwendolyn import Gwendolyn
from gwendolyn.utils import make_files
def main():
"""Starts the bot"""
"""Starts the bot"""
make_files()
make_files()
# Creates the Bot
bot = Gwendolyn()
bot.start()
# Creates the Bot
bot = Gwendolyn()
bot.start()
if __name__ == "__main__":
main()
main()