diff --git a/.gitignore b/.gitignore index 38d611f..aa5010b 100644 --- a/.gitignore +++ b/.gitignore @@ -158,7 +158,7 @@ resources/bedreNetflix/ resources/games/hilo/ resources/games/blackjackTables/ resources/games/oldImages/ -resources/games/4InARowBoards/ +resources/games/connect4Boards/ resources/games/hexBoards/ resources/games/hangmanBoards/ resources/lookup/monsters.json diff --git a/Gwendolyn.py b/Gwendolyn.py index a07cafd..5e72481 100644 --- a/Gwendolyn.py +++ b/Gwendolyn.py @@ -1,35 +1,10 @@ -import discord, os, finnhub, platform, asyncio, traceback +import os, finnhub, platform, asyncio, discord from discord.ext import commands +from discord_slash import SlashCommand from pymongo import MongoClient -from funcs import logThis, makeFiles, Money, Funcs, SwChar, SwDestiny, SwRoll, Games, Generators, BedreNetflix, NerdShit - -commandPrefix = "!" - -if platform.system() == "Windows": - asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy()) - -class Credentials(): - def __init__(self): - with open("credentials.txt","r") as f: - data = f.read().splitlines() - - self.token = data[0][10:].replace(" ","") - self.finnhubKey = data[1][16:].replace(" ","") - self.wordnikKey = data[2][16:].replace(" ","") - self.mongoDBUser = data[3][13:].replace(" ","") - self.mongoDBPassword = data[4][17:].replace(" ","") - self.wolfKey = data[5][19:].replace(" ","") - self.radarrKey = data[6][15:].replace(" ","") - self.sonarrKey = data[7][15:].replace(" ","") - -class Options(): - def __init__(self): - with open("options.txt","r") as f: - data = f.read().splitlines() - - self.prefix = data[0][7:].replace(" ","") - self.testing = (data[1][8:].replace(" ","").lower() == "true") +from funcs import Money, StarWars, Games, Other, LookupFuncs +from utils import Options, Credentials, logThis, makeFiles, databaseFuncs class Gwendolyn(commands.Bot): def __init__(self): @@ -39,70 +14,46 @@ class Gwendolyn(commands.Bot): self.MongoClient = MongoClient(f"mongodb+srv://{self.credentials.mongoDBUser}:{self.credentials.mongoDBPassword}@gwendolyn.qkwfy.mongodb.net/Gwendolyn?retryWrites=true&w=majority") if self.options.testing: - logThis("Testing mode") + self.log("Testing mode") self.database = self.MongoClient["Gwendolyn-Test"] else: self.database = self.MongoClient["Gwendolyn"] - self.swchar = SwChar(self) - self.swroll = SwRoll(self) - self.swdestiny = SwDestiny(self) - - self.generator = Generators() - self.bedreNetflix = BedreNetflix(self) - self.nerdShit = NerdShit(self) - - Games(self) - + self.starWars = StarWars(self) + self.other = Other(self) + self.lookupFuncs = LookupFuncs(self) + self.games = Games(self) self.money = Money(self) - self.funcs = Funcs(self) + self.databaseFuncs = databaseFuncs(self) - super().__init__(command_prefix=commandPrefix, case_insensitive=True) + intents = discord.Intents.default() + intents.members = True -# Creates the required files -makeFiles() + super().__init__(command_prefix=" ", case_insensitive=True, intents = intents) -# Creates the Bot -client = Gwendolyn() + def log(self, messages, channel : str = "", level : int = 10): + logThis(messages, channel, level) -# Logs in -@client.event -async def on_ready(): - logThis("Logged in as "+client.user.name+", "+str(client.user.id)) - game = discord.Game("Some weeb shit") - await client.change_presence(activity=game) -# Logs when user sends a command -@client.event -async def on_command(ctx): - logThis(f"{ctx.message.author.display_name} ran {ctx.message.content}") -# Logs if a command experiences an error -@client.event -async def on_command_error(ctx, error): - if isinstance(error, commands.CommandNotFound): - await ctx.send("That's not a command (error code 001)") - elif isinstance(error,commands.errors.MissingRequiredArgument): - logThis(f"{error}",str(ctx.message.channel.id)) - await ctx.send("Missing command parameters (error code 002). Try using `!help [command]` to find out how to use the command.") - else: - exception = traceback.format_exception(type(error), error, error.__traceback__) - stopAt = "\nThe above exception was the direct cause of the following exception:\n\n" - if stopAt in exception: - index = exception.index(stopAt) - exception = exception[:index] +if __name__ == "__main__": + if platform.system() == "Windows": + asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy()) - exceptionString = "".join(exception) - logThis([f"exception in command !{ctx.command}", f"{exceptionString}"],str(ctx.message.channel.id), 40) - await ctx.send("Something went wrong (error code 000)") + # Creates the required files + makeFiles() -#Loads cogs -for filename in os.listdir("./cogs"): - if filename.endswith(".py"): - client.load_extension(f"cogs.{filename[:-3]}") + # Creates the Bot + bot = Gwendolyn() + bot.slash = SlashCommand(bot, sync_commands=True, sync_on_cog_reload=True, override_type=True) -try: - # Runs the whole shabang - client.run(client.credentials.token) -except: - logThis("Could not log in. Remember to write your bot token in the credentials.txt file") + #Loads cogs + for filename in os.listdir("./cogs"): + if filename.endswith(".py"): + bot.load_extension(f"cogs.{filename[:-3]}") + + try: + # Runs the whole shabang + bot.run(bot.credentials.token) + except: + bot.log("Could not log in. Remember to write your bot token in the credentials.txt file") \ No newline at end of file diff --git a/cogs/EventCog.py b/cogs/EventCog.py new file mode 100644 index 0000000..c220968 --- /dev/null +++ b/cogs/EventCog.py @@ -0,0 +1,40 @@ +import discord, traceback +from discord.ext import commands + +class EventCog(commands.Cog): + def __init__(self, bot): + self.bot = bot + + # Sets the game and logs when the bot logs in + @commands.Cog.listener() + async def on_ready(self): + self.bot.log("Logged in as "+self.bot.user.name+", "+str(self.bot.user.id), level = 20) + game = discord.Game("Use /help for commands") + await self.bot.change_presence(activity=game) + + # Logs when user sends a command + @commands.Cog.listener() + async def on_slash_command(self, ctx): + self.bot.log(f"{ctx.author.display_name} ran /{ctx.name}", str(ctx.channel_id), level = 20) + + # Logs if a command experiences an error + @commands.Cog.listener() + async def on_slash_command_error(self, ctx, error): + if isinstance(error, commands.CommandNotFound): + await ctx.send("That's not a command (error code 001)") + elif isinstance(error,commands.errors.MissingRequiredArgument): + self.bot.log(f"{error}",str(ctx.channel_id)) + await ctx.send("Missing command parameters (error code 002). Try using `!help [command]` to find out how to use the command.") + else: + exception = traceback.format_exception(type(error), error, error.__traceback__) + stopAt = "\nThe above exception was the direct cause of the following exception:\n\n" + if stopAt in exception: + index = exception.index(stopAt) + exception = exception[:index] + + exceptionString = "".join(exception) + self.bot.log([f"exception in /{ctx.name}", f"{exceptionString}"],str(ctx.channel_id), 40) + await ctx.send("Something went wrong (error code 000)") + +def setup(bot): + bot.add_cog(EventCog(bot)) diff --git a/cogs/GameCogs.py b/cogs/GameCogs.py new file mode 100644 index 0000000..ed0ca78 --- /dev/null +++ b/cogs/GameCogs.py @@ -0,0 +1,198 @@ +import discord, asyncio, json +from discord.ext import commands +from discord_slash import cog_ext +from discord_slash import SlashCommandOptionType as scot + +from utils import getParams + +params = getParams() + +class GamesCog(commands.Cog): + def __init__(self,bot): + """Runs game stuff.""" + self.bot = bot + + # Checks user balance + @cog_ext.cog_slash(**params["balance"]) + async def balance(self, ctx): + await ctx.defer() + response = self.bot.money.checkBalance("#"+str(ctx.author.id)) + if response == 1: + new_message = ctx.author.display_name + " has " + str(response) + " GwendoBuck" + else: + new_message = ctx.author.display_name + " has " + str(response) + " GwendoBucks" + await ctx.send(new_message) + + # Gives another user an amount of GwendoBucks + @cog_ext.cog_slash(**params["give"]) + async def give(self, ctx, user, amount): + await ctx.defer() + username = user.display_name + if self.bot.databaseFuncs.getID(username) == None: + async for member in ctx.guild.fetch_members(limit=None): + if member.display_name.lower() == username.lower(): + username = member.display_name + userID = "#" + str(member.id) + self.bot.database["users"].insert_one({"_id":userID,"user name":username,"money":0}) + response = self.bot.money.giveMoney("#"+str(ctx.author.id),username,amount) + await ctx.send(response) + + # Invest GwendoBucks in the stock market + @cog_ext.cog_slash(**params["invest"]) + async def invest(self, ctx, parameters = "check"): + await ctx.defer() + response = self.bot.games.invest.parseInvest(parameters,"#"+str(ctx.author.id)) + if response.startswith("**"): + responses = response.split("\n") + em = discord.Embed(title=responses[0],description="\n".join(responses[1:]),colour=0x00FF00) + await ctx.send(embed=em) + else: + await ctx.send(response) + + # Runs a game of trivia + @cog_ext.cog_slash(**params["trivia"]) + async def trivia(self, ctx, answer = ""): + await ctx.defer() + if answer == "": + question, options, correctAnswer = self.bot.games.trivia.triviaStart(str(ctx.channel_id)) + if options != "": + results = "**"+question+"**\n" + for x, option in enumerate(options): + results += chr(x+97) + ") "+option+"\n" + + await ctx.send(results) + + await asyncio.sleep(60) + + self.bot.games.trivia.triviaCountPoints(str(ctx.channel_id)) + + self.bot.databaseFuncs.deleteGame("trivia questions",str(ctx.channel_id)) + + self.bot.log("Time's up for the trivia question",str(ctx.channel_id)) + await ctx.send("Time's up The answer was \""+chr(correctAnswer)+") "+options[correctAnswer-97]+"\". Anyone who answered that has gotten 1 GwendoBuck") + else: + await ctx.send(question, hidden=True) + + elif answer in ["a","b","c","d"]: + response = self.bot.games.trivia.triviaAnswer("#"+str(ctx.author.id),str(ctx.channel_id),answer) + if response.startswith("Locked in "): + await ctx.send(f"{ctx.author.display_name} answered {answer}") + else: + await ctx.send(response) + else: + self.bot.log("I didn't understand that (error code 1101)",str(ctx.channel_id)) + await ctx.send("I didn't understand that (error code 1101)") + + +class BlackjackCog(commands.Cog): + def __init__(self,bot): + """Runs game stuff.""" + self.bot = bot + + # Starts a game of blackjack + @cog_ext.cog_subcommand(**params["blackjackStart"]) + async def blackjackStart(self, ctx): + await ctx.defer() + await self.bot.games.blackjack.parseBlackjack("", ctx) + + @cog_ext.cog_subcommand(**params["blackjackBet"]) + async def blackjackBet(self, ctx, bet): + await ctx.defer() + await self.bot.games.blackjack.parseBlackjack(f"bet {bet}", ctx) + + @cog_ext.cog_subcommand(**params["blackjackStand"]) + async def blackjackStand(self, ctx, hand = ""): + await ctx.defer() + await self.bot.games.blackjack.parseBlackjack(f"stand {hand}", ctx) + + @cog_ext.cog_subcommand(**params["blackjackHit"]) + async def blackjackHit(self, ctx, hand = ""): + await ctx.defer() + await self.bot.games.blackjack.parseBlackjack(f"hit {hand}", ctx) + + +class ConnectFourCog(commands.Cog): + def __init__(self,bot): + """Runs game stuff.""" + self.bot = bot + # Start a game of connect four against a user + @cog_ext.cog_subcommand(**params["connectFourStartUser"]) + async def connectFourStartUser(self, ctx, user): + await ctx.defer() + await self.bot.games.gameLoops.connectFour(ctx, "start "+user.display_name) + + # Start a game of connect four against gwendolyn + @cog_ext.cog_subcommand(**params["connectFourStartGwendolyn"]) + async def connectFourStartGwendolyn(self, ctx, difficulty = 3): + await ctx.defer() + await self.bot.games.gameLoops.connectFour(ctx, "start "+str(difficulty)) + + # Stop the current game of connect four + @cog_ext.cog_subcommand(**params["connectFourStop"]) + async def connectFourStop(self, ctx): + await self.bot.games.gameLoops.connectFour(ctx, "stop") + + # Place a piece in the current game of connect four + @cog_ext.cog_subcommand(**params["connectFourPlace"]) + async def connectFourPlace(self, ctx, column): + await self.bot.games.gameLoops.connectFour(ctx, "place "+str(column)) + + +class HangmanCog(commands.Cog): + def __init__(self,bot): + """Runs game stuff.""" + self.bot = bot + # Starts a game of Hangman + @cog_ext.cog_subcommand(**params["hangmanStart"]) + async def hangmanStart(self, ctx): + await ctx.defer() + await self.bot.games.gameLoops.runHangman(ctx.channel,"#"+str(ctx.author.id),"start", ctx) + + # Stops a game of Hangman + @cog_ext.cog_subcommand(**params["hangmanStop"]) + async def hangmanStop(self, ctx): + await self.bot.games.gameLoops.runHangman(ctx.channel,"#"+str(ctx.author.id),"stop", ctx) + + +class HexCog(commands.Cog): + def __init__(self,bot): + """Runs game stuff.""" + self.bot = bot + # Start a game of Hex against another user + @cog_ext.cog_subcommand(**params["hexStartUser"]) + async def hexStartUser(self, ctx, user): + await ctx.defer() + await self.bot.games.gameLoops.runHex(ctx, "start "+user.display_name, "#"+str(ctx.author.id)) + + # Start a game of Hex against Gwendolyn + @cog_ext.cog_subcommand(**params["hexStartGwendolyn"]) + async def hexStartGwendolyn(self, ctx, difficulty = 2): + await ctx.defer() + await self.bot.games.gameLoops.runHex(ctx, "start "+str(difficulty), "#"+str(ctx.author.id)) + + # Undo your last hex move + @cog_ext.cog_subcommand(**params["hexUndo"]) + async def hexUndo(self, ctx): + await self.bot.games.gameLoops.runHex(ctx, "undo", "#"+str(ctx.author.id)) + + # Perform a hex swap + @cog_ext.cog_subcommand(**params["hexSwap"]) + async def hexSwap(self, ctx): + await self.bot.games.gameLoops.runHex(ctx, "swap", "#"+str(ctx.author.id)) + + # Surrender the hex game + @cog_ext.cog_subcommand(**params["hexSurrender"]) + async def hexSurrender(self, ctx): + await self.bot.games.gameLoops.runHex(ctx, "surrender", "#"+str(ctx.author.id)) + + # Place a piece in the hex game + @cog_ext.cog_subcommand(**params["hexPlace"]) + async def hexPlace(self, ctx, coordinates): + await self.bot.games.gameLoops.runHex(ctx, "place "+coordinates, "#"+str(ctx.author.id)) + +def setup(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)) \ No newline at end of file diff --git a/cogs/GamesCog.py b/cogs/GamesCog.py deleted file mode 100644 index ef33952..0000000 --- a/cogs/GamesCog.py +++ /dev/null @@ -1,102 +0,0 @@ -import discord, asyncio -from discord.ext import commands - -from funcs import logThis - -class GamesCog(commands.Cog): - - def __init__(self,bot): - """Runs game stuff.""" - self.bot = bot - - # Checks user balance - @commands.command(aliases = ["b"]) - async def balance(self, ctx): - response = self.bot.money.checkBalance("#"+str(ctx.message.author.id)) - if response == 1: - new_message = ctx.message.author.display_name + " has " + str(response) + " GwendoBuck" - else: - new_message = ctx.message.author.display_name + " has " + str(response) + " GwendoBucks" - await ctx.send(new_message) - - # Gives another user an amount of GwendoBucks - @commands.command() - async def give(self, ctx, *, content): - commands = content.split(" ") - amount = int(commands[-1]) - username = " ".join(commands[:-1]) - if self.bot.funcs.getID(username) == None: - async for member in ctx.guild.fetch_members(limit=None): - if member.display_name.lower() == username.lower(): - username = member.display_name - userID = "#" + str(member.id) - self.bot.database["users"].insert_one({"_id":userID,"user name":username,"money":0}) - response = self.bot.money.giveMoney("#"+str(ctx.message.author.id),username,amount) - await ctx.send(response) - - # Invest GwendoBucks in the stock market - @commands.command(aliases=["i"]) - async def invest(self, ctx, *, content = "check"): - response = self.bot.invest.parseInvest(content,"#"+str(ctx.message.author.id)) - if response.startswith("**"): - responses = response.split("\n") - em = discord.Embed(title=responses[0],description="\n".join(responses[1:]),colour=0x00FF00) - await ctx.send(embed=em) - else: - await ctx.send(response) - - # Runs a game of trivia - @commands.command() - async def trivia(self, ctx, *, content = ""): - if content == "": - question, answers, correctAnswer = self.bot.trivia.triviaStart(str(ctx.message.channel.id)) - if answers != "": - results = "**"+question+"**\n" - for x, answer in enumerate(answers): - results += chr(x+97) + ") "+answer+"\n" - - await ctx.send(results) - - await asyncio.sleep(60) - - self.bot.trivia.triviaCountPoints(str(ctx.message.channel.id)) - - self.bot.funcs.deleteGame("trivia questions",str(ctx.message.channel.id)) - - logThis("Time's up for the trivia question",str(ctx.message.channel.id)) - await ctx.send("Time's up The answer was \""+chr(correctAnswer)+") "+answers[correctAnswer-97]+"\". Anyone who answered that has gotten 1 GwendoBuck") - else: - await ctx.send(question) - - elif content in ["a","b","c","d"]: - response = self.bot.trivia.triviaAnswer("#"+str(ctx.message.author.id),str(ctx.message.channel.id),content) - if response.startswith("Locked in "): - await ctx.message.add_reaction("👍") - else: - await ctx.send(response) - else: - logThis("I didn't understand that (error code 1101)",str(ctx.message.channel.id)) - await ctx.send("I didn't understand that (error code 1101)") - - # Runs a game of blackjack - @commands.command(aliases = ["bj"]) - async def blackjack(self, ctx, *, content = ""): - await self.bot.blackjack.parseBlackjack(content,ctx) - - # Runs a game of Connect four - @commands.command(aliases = ["fiar","connect4","connectfour","4iar","4inarow"]) - async def fourinarow(self, ctx, *, content = ""): - await self.bot.gameLoops.fiar(ctx.message.channel,content,"#"+str(ctx.message.author.id)) - - # Runs a game of Hangman - @commands.command(aliases = ["hm"]) - async def hangman(self, ctx, *, content = "start"): - await self.bot.gameLoops.runHangman(ctx.message.channel,"#"+str(ctx.message.author.id),content) - - # Runs a game of Hex - @commands.command(name="hex") - async def hexCommand(self, ctx, *, content = ""): - await self.bot.gameLoops.runHex(ctx.message.channel,content,"#"+str(ctx.message.author.id)) - -def setup(bot): - bot.add_cog(GamesCog(bot)) \ No newline at end of file diff --git a/cogs/LookupCog.py b/cogs/LookupCog.py index 5296db5..aa1366e 100644 --- a/cogs/LookupCog.py +++ b/cogs/LookupCog.py @@ -1,18 +1,21 @@ -import discord +import discord, json from discord.ext import commands +from discord_slash import cog_ext +from discord_slash import SlashCommandOptionType as scot -from funcs import spellFunc, monsterFunc, cap +from utils import getParams, cap + +params = getParams() class LookupCog(commands.Cog): - - def __init__(self,client): + def __init__(self, bot): """Runs lookup commands.""" - self.client = client + self.bot = bot # Looks up a spell - @commands.command() - async def spell(self, ctx, *, content): - spell = spellFunc(cap(content)) + @cog_ext.cog_slash(**params["spell"]) + async def spell(self, ctx, query): + spell = self.bot.lookupFuncs.spellFunc(cap(query)) if len(spell) > 2000: await ctx.send(spell[:2000]) await ctx.send(spell[2000:]) @@ -20,12 +23,12 @@ class LookupCog(commands.Cog): await ctx.send(spell) # Looks up a monster - @commands.command() - async def monster(self, ctx, *, content): - title, text1, text2, text3, text4, text5 = monsterFunc(cap(content)) + @cog_ext.cog_slash(**params["monster"]) + async def monster(self, ctx, query): + title, text1, text2, text3, text4, text5 = self.bot.lookupFuncs.monsterFunc(cap(query)) em1 = discord.Embed(title = title, description = text1, colour=0xDEADBF) - # Sends the received information. Seperates into seperate messages if + # Sends the received information. Separates into separate messages if # there is too much text await ctx.send(embed = em1) if text2 != "": @@ -65,5 +68,5 @@ class LookupCog(commands.Cog): em5_2 = discord.Embed(title = "", description = text5[2048:], colour=0xDEADBF) await ctx.send(embed = em5_2) -def setup(client): - client.add_cog(LookupCog(client)) \ No newline at end of file +def setup(bot): + bot.add_cog(LookupCog(bot)) \ No newline at end of file diff --git a/cogs/MiscCog.py b/cogs/MiscCog.py index 91f560a..7ac34bf 100644 --- a/cogs/MiscCog.py +++ b/cogs/MiscCog.py @@ -1,150 +1,136 @@ -import discord, codecs, string +import discord, codecs, string, json from discord.ext import commands +from discord_slash import cog_ext -from funcs import logThis, helloFunc, roll_dice, imageFunc, movieFunc, cap, findWikiPage +from utils import Options + +with open("resources/slashParameters.json", "r") as f: + params = json.load(f) + +options = Options() + +if options.testing: + for p in params: + params[p]["guild_ids"] = options.guildIds class MiscCog(commands.Cog): - - def __init__(self,client): + def __init__(self, bot): """Runs misc commands.""" - self.client = client - self.client.remove_command("help") - self.generator = client.generator - self.bedreNetflix = client.bedreNetflix - self.nerdShit = client.nerdShit + self.bot = bot + self.bot.remove_command("help") + self.generators = bot.other.generators + self.bedreNetflix = bot.other.bedreNetflix + self.nerdShit = bot.other.nerdShit - @commands.command(name = "help") - async def helpCommand(self, ctx, *, content = ""): - if content == "": + # Sends the bot's latency + @cog_ext.cog_slash(**params["ping"]) + async def ping(self, ctx): + await ctx.send(f"Pong!\nLatency is {round(self.bot.latency * 1000)}ms") + + # Restarts the bot + @cog_ext.cog_slash(**params["stop"]) + async def stop(self, ctx): + if "#"+str(ctx.author.id) in self.bot.options.admins: + await ctx.send("Pulling git repo and restarting...") + + self.bot.databaseFuncs.stopServer() + + self.bot.log("Logging out.") + await self.bot.logout() + else: + self.bot.log(f"{ctx.author.display_name} tried to stop me! (error code 201)",str(ctx.channel_id)) + await ctx.send(f"I don't think I will, {ctx.author.display_name} (error code 201)") + + # Gets help for specific command + @cog_ext.cog_slash(**params["help"]) + async def helpCommand(self, ctx, command = ""): + if command == "": with codecs.open("resources/help/help.txt",encoding="utf-8") as f: text = f.read() em = discord.Embed(title = "Help", description = text,colour = 0x59f442) await ctx.send(embed = em) else: - logThis(f"Looking for help-{content}.txt",str(ctx.message.channel.id)) - with codecs.open(f"resources/help/help-{content}.txt",encoding="utf-8") as f: + self.bot.log(f"Looking for help-{command}.txt",str(ctx.channel_id)) + with codecs.open(f"resources/help/help-{command}.txt",encoding="utf-8") as f: text = f.read() - em = discord.Embed(title = content.capitalize(), description = text,colour = 0x59f442) + em = discord.Embed(title = command.capitalize(), description = text,colour = 0x59f442) await ctx.send(embed = em) - # Sends the bot's latency - @commands.command() - async def ping(self, ctx): - await ctx.send(f"Pong!\nLatency is {round(self.client.latency * 1000)} ms") - - # Logs whatever is written - @commands.command(hidden = True) - async def log(self, ctx, *, content): - logThis(content,str("Logged by "+ctx.message.author.display_name)) - - # Restarts the bot - @commands.command(hidden = True,aliases=["stop"]) - async def restart(self, ctx): - if "#"+str(ctx.message.author.id) in ["#266269899859427329", "#380732645602230272"]: - await ctx.send("Pulling git repo and restarting...") - - self.client.funcs.stopServer() - - logThis("Logging out.") - await self.client.logout() - else: - logThis(f"{ctx.message.author.display_name} tried to stop me! (error code 201)",str(ctx.message.channel.id)) - await ctx.send(f"I don't think I will, {ctx.message.author.display_name} (error code 201)") - - @commands.command(aliases = ["thankyou", "thanku", "thanks"]) + # Lets you thank the bot + @cog_ext.cog_slash(**params["thank"]) async def thank(self, ctx): await ctx.send("You're welcome :blush:") # Sends a friendly message - @commands.command(aliases = ["hi","howdy"]) + @cog_ext.cog_slash(**params["hello"]) async def hello(self, ctx): - await ctx.send(helloFunc(ctx.message.author.display_name)) + await ctx.send(self.bot.other.helloFunc(ctx.author.display_name)) # Rolls dice - @commands.command() - async def roll(self, ctx, *, content = "1d20"): - await ctx.send(roll_dice(ctx.message.author.display_name,content)) - - # Sends an image of the Senkulpa map - @commands.command(name="map") - async def mapCommand(self, ctx): - await ctx.send("https://i.imgur.com/diMXXJs.jpg") + @cog_ext.cog_slash(**params["roll"]) + async def roll(self, ctx, dice = "1d20"): + await ctx.send(self.bot.other.rollDice(ctx.author.display_name, dice)) # Sends a random image - @commands.command(aliases = ["img"]) + @cog_ext.cog_slash(**params["image"]) async def image(self, ctx): - randomImage = imageFunc() - await ctx.send(randomImage) + await ctx.defer() + await ctx.send(self.bot.other.imageFunc()) # Finds a random movie - @commands.command() + @cog_ext.cog_slash(**params["movie"]) async def movie(self,ctx): - async with ctx.typing(): - title, plot, cover, cast = movieFunc() - if title == "error": - await ctx.send("An error occurred. Try again (error code "+plot+")") - else: - try: - 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) - except: - logThis("Error embedding (error code 805)") + await self.bot.other.movieFunc(ctx) # Generates a random name - @commands.command() + @cog_ext.cog_slash(**params["name"]) async def name(self, ctx): - await ctx.send(self.generator.nameGen()) + await ctx.send(self.generators.nameGen()) # Generates a random tavern name - @commands.command() + @cog_ext.cog_slash(**params["tavern"]) async def tavern(self, ctx): - await ctx.send(self.generator.tavernGen()) - - # Sets the game Gwendolyn's playing - @commands.command() - async def game(self, ctx, *, content): - gamePlaying = cap(content) - game = discord.Game(gamePlaying) - await self.client.change_presence(activity=game) + await ctx.send(self.generators.tavernGen()) # Finds a page on the Senkulpa wiki - @commands.command(aliases = ["wikia"]) - async def wiki(self, ctx, *, content): - async with ctx.message.channel.typing(): - command = string.capwords(content) - title, content, thumbnail = findWikiPage(command) - if title != "": - logThis("Sending the embedded message",str(ctx.message.channel.id)) - content += "\n[Læs mere](https://senkulpa.fandom.com/da/wiki/"+title.replace(" ","_")+")" - embed = discord.Embed(title = title, description = content, colour=0xDEADBF) - if thumbnail != "": - embed.set_thumbnail(url=thumbnail) + @cog_ext.cog_slash(**params["wiki"]) + async def wiki(self, ctx, wikiPage): + await ctx.defer() + command = string.capwords(wikiPage) + title, content, thumbnail = self.bot.otherfindWikiPage(command) + if title != "": + self.bot.log("Sending the embedded message",str(ctx.channel_id)) + content += "\n[Læs mere](https://senkulpa.fandom.com/da/wiki/"+title.replace(" ","_")+")" + embed = discord.Embed(title = title, description = content, colour=0xDEADBF) + if thumbnail != "": + embed.set_thumbnail(url=thumbnail) - await ctx.send(embed = embed) - else: - await ctx.send(content) + await ctx.send(embed = embed) + else: + await ctx.send(content) #Searches for movie and adds it to Bedre Netflix - @commands.command(aliases = ["rm","addmovie","am"]) - async def requestmovie(self, ctx, *, content): - await self.bedreNetflix.requestMovie(ctx,content) + @cog_ext.cog_slash(**params["addMovie"]) + async def addMovie(self, ctx, movie): + await ctx.defer() + await self.bedreNetflix.requestMovie(ctx, movie) #Searches for show and adds it to Bedre Netflix - @commands.command(aliases = ["rs","addshow","as","addseries"]) - async def requestshow(self, ctx, *, content): - await self.bedreNetflix.requestShow(ctx,content) + @cog_ext.cog_slash(**params["addShow"]) + async def addShow(self, ctx, show): + await ctx.defer() + await self.bedreNetflix.requestShow(ctx, show) #Returns currently downloading torrents - @commands.command(aliases = ["downloads"]) - async def downloading(self, ctx, *, content = "-d"): - await self.bedreNetflix.downloading(ctx, content) + @cog_ext.cog_slash(**params["downloading"]) + async def downloading(self, ctx, parameters = "-d"): + await ctx.defer() + await self.bedreNetflix.downloading(ctx, parameters) #Looks up on Wolfram Alpha - @commands.command() - async def wolf(self, ctx, *, content): - await self.nerdShit.wolfSearch(ctx,content) + @cog_ext.cog_slash(**params["wolf"]) + async def wolf(self, ctx, query): + await self.nerdShit.wolfSearch(ctx, query) -def setup(client): - client.add_cog(MiscCog(client)) +def setup(bot): + bot.add_cog(MiscCog(bot)) diff --git a/cogs/ReactionCog.py b/cogs/ReactionCog.py index 25dab5c..14b4cc0 100644 --- a/cogs/ReactionCog.py +++ b/cogs/ReactionCog.py @@ -1,28 +1,28 @@ from discord.ext import commands -from funcs import logThis, emojiToCommand +from utils import emojiToCommand class ReactionCog(commands.Cog): - def __init__(self, client): + def __init__(self, bot): """Listens for reactions.""" - self.client = client + self.bot = bot @commands.Cog.listener() - async def on_reaction_add(self, reaction,user): + async def on_reaction_add(self, reaction, user): if user.bot == False: message = reaction.message channel = message.channel - logThis(user.display_name+" reacted to a message",str(channel.id)) + self.bot.log(f"{user.display_name} reacted to a message",str(channel.id)) try: - fourInARowTheirTurn, piece = self.client.funcs.fiarReactionTest(channel,message,"#"+str(user.id)) + connectFourTheirTurn, piece = self.bot.databaseFuncs.connectFourReactionTest(channel,message,"#"+str(user.id)) except: - fourInARowTheirTurn = False + connectFourTheirTurn = False - bedreNetflixMessage, addMovie, imdbIds = self.client.funcs.bedreNetflixReactionTest(channel,message) + bedreNetflixMessage, addMovie, imdbIds = self.bot.databaseFuncs.bedreNetflixReactionTest(channel, message) - if fourInARowTheirTurn: + if connectFourTheirTurn: place = emojiToCommand(reaction.emoji) - await self.client.gameLoops.fiar(channel," place "+str(piece)+" "+str(place),user.id) + await self.bot.games.gameLoops.connectFour(message,"place "+str(piece)+" "+str(place),user.id, str(message.channel.id)) elif bedreNetflixMessage and addMovie: moviePick = emojiToCommand(reaction.emoji) await message.delete() @@ -30,7 +30,7 @@ class ReactionCog(commands.Cog): imdbID = None else: imdbID = imdbIds[moviePick-1] - await self.client.bedreNetflix.addMovie(channel,imdbID) + await self.bot.other.bedreNetflix.addMovie(channel,imdbID) elif bedreNetflixMessage and not addMovie: showPick = emojiToCommand(reaction.emoji) await message.delete() @@ -38,9 +38,9 @@ class ReactionCog(commands.Cog): imdbName = None else: imdbName = imdbIds[showPick-1] - await self.client.bedreNetflix.addShow(channel,imdbName) - elif self.client.funcs.hangmanReactionTest(channel,message) and ord(reaction.emoji) in range(127462,127488): + await self.bot.other.bedreNetflix.addShow(channel,imdbName) + elif self.bot.databaseFuncs.hangmanReactionTest(channel,message) and ord(reaction.emoji) in range(127462,127488): guess = chr(ord(reaction.emoji)-127397) - await self.client.gameLoops.runHangman(channel,"#"+str(user.id),command="guess "+guess) -def setup(client): - client.add_cog(ReactionCog(client)) + await self.bot.games.gameLoops.runHangman(channel,"#"+str(user.id),command="guess "+guess) +def setup(bot): + bot.add_cog(ReactionCog(bot)) diff --git a/cogs/StarWarsCog.py b/cogs/StarWarsCog.py new file mode 100644 index 0000000..850e4f2 --- /dev/null +++ b/cogs/StarWarsCog.py @@ -0,0 +1,67 @@ +import discord, string, json +from discord.ext import commands +from discord_slash import cog_ext + +from utils import Options, cap + +with open("resources/slashParameters.json", "r") as f: + params = json.load(f) + +options = Options() + +if options.testing: + for p in params: + params[p]["guild_ids"] = options.guildIds + +class starWarsCog(commands.Cog): + + def __init__(self, bot): + """Runs star wars commands.""" + self.bot = bot + + # Rolls star wars dice + @cog_ext.cog_slash(**params["starWarsRoll"]) + async def starWarsRoll(self, ctx, dice = ""): + command = cap(dice) + newMessage = self.bot.starWars.roll.parseRoll("#"+str(ctx.author.id),command) + messageList = newMessage.split("\n") + await ctx.send(messageList[0]) + if len(messageList) > 1: + for messageItem in messageList[1:]: + await ctx.channel.send(messageItem) + + # Controls destiny points + @cog_ext.cog_slash(**params["starWarsDestiny"]) + async def starWarsDestiny(self, ctx, parameters = ""): + newMessage = self.bot.starWars.destiny.parseDestiny("#"+str(ctx.author.id),parameters) + messageList = newMessage.split("\n") + await ctx.send(messageList[0]) + if len(messageList) > 1: + for messageItem in messageList[1:]: + await ctx.channel.send(messageItem) + + # Rolls for critical injuries + @cog_ext.cog_slash(**params["starWarsCrit"]) + async def starWarsCrit(self, ctx, severity : int = 0): + newMessage = self.bot.starWars.roll.critRoll(int(severity)) + + messageList = newMessage.split("\n") + await ctx.send(messageList[0]) + if len(messageList) > 1: + for messageItem in messageList[1:]: + await ctx.channel.send(messageItem) + + # Accesses and changes character sheet data with the parseChar function + # from funcs/starWarsFuncs/starWarsCharacter.py + @cog_ext.cog_slash(**params["starWarsCharacter"]) + async def starWarsCharacter(self, ctx, parameters = ""): + command = string.capwords(parameters.replace("+","+ ").replace("-","- ").replace(",",", ")) + title, desc = self.bot.starWars.character.parseChar("#"+str(ctx.author.id),command) + if title != "": + em1 = discord.Embed(title = title, description = desc, colour=0xDEADBF) + await ctx.send(embed = em1) + else: + await ctx.send(desc) + +def setup(bot): + bot.add_cog(starWarsCog(bot)) \ No newline at end of file diff --git a/cogs/SwCog.py b/cogs/SwCog.py deleted file mode 100644 index 4e63fac..0000000 --- a/cogs/SwCog.py +++ /dev/null @@ -1,51 +0,0 @@ -import discord, string -from discord.ext import commands - -from funcs import cap - -class SwCog(commands.Cog): - - def __init__(self,client): - """Runs star wars commands.""" - self.client = client - - # Rolls star wars dice - @commands.command() - async def swroll(self, ctx, *, content = ""): - command = cap(content) - newMessage = self.client.swroll.parseRoll("#"+str(ctx.message.author.id),command) - messageList = newMessage.split("\n") - for messageItem in messageList: - await ctx.send(messageItem) - - # Controls destiny points - @commands.command() - async def swd(self, ctx, *, content): - newMessage = self.client.swdestiny.parseDestiny("#"+str(ctx.message.author.id),content) - messageList = newMessage.split("\n") - for messageItem in messageList: - await ctx.send(messageItem) - - # Rolls for critical injuries - @commands.command() - async def swcrit(self, ctx, arg : int = 0): - newMessage = self.client.swroll.critRoll(int(arg)) - - messageList = newMessage.split("\n") - for messageItem in messageList: - await ctx.send(messageItem) - - # Accesses and changes character sheet data with the parseChar function - # from funcs/swfuncs/swchar.py - @commands.command(aliases=["sw"]) - async def swchar(self, ctx, *, content = ""): - command = string.capwords(content.replace("+","+ ").replace("-","- ").replace(",",", ")) - title, desc = self.client.swchar.parseChar("#"+str(ctx.message.author.id),command) - if title != "": - em1 = discord.Embed(title = title, description = desc, colour=0xDEADBF) - await ctx.send(embed = em1) - else: - await ctx.send(desc) - -def setup(client): - client.add_cog(SwCog(client)) \ No newline at end of file diff --git a/funcs/__init__.py b/funcs/__init__.py index cfc28f7..729f445 100644 --- a/funcs/__init__.py +++ b/funcs/__init__.py @@ -1,17 +1,11 @@ """A collection of all Gwendolyn functions.""" -__all__ = ["Games" ,"helloFunc", "cap", "imageFunc", "logThis", "findWikiPage", "makeFiles", "emojiToCommand", "Money", "spellFunc", "monsterFunc", "Generators", "movieFunc", "roll_dice", "SwChar", "SwDestiny", "SwRoll", "replaceMultiple","Funcs"] - -from .miscFuncs import helloFunc, cap, imageFunc, logThis, findWikiPage, makeFiles, replaceMultiple, emojiToCommand - -from .funcs import Funcs +__all__ = ["Games" , "Money", "LookupFuncs", "StarWars"] from .games import Money, Games -from .lookup import spellFunc, monsterFunc +from .lookup import LookupFuncs -from .other import Generators, movieFunc, BedreNetflix, NerdShit +from .other import Other -from .roll import roll_dice - -from .swfuncs import SwChar, SwDestiny, SwRoll +from .starWarsFuncs import StarWars diff --git a/funcs/funcs.py b/funcs/funcs.py deleted file mode 100644 index a06b187..0000000 --- a/funcs/funcs.py +++ /dev/null @@ -1,85 +0,0 @@ -from .miscFuncs import logThis -import git # Used by stopServer() -import re, json - -class Funcs(): - def __init__(self,bot): - self.bot = bot - - def getName(self,userID): - user = self.bot.database["users"].find_one({"_id":userID}) - - if user != None: - return user["user name"] - elif userID == "Gwendolyn": - return userID - else: - logThis("Couldn't find user "+userID) - return userID - - def getID(self,userName): - user = self.bot.database["users"].find_one({"user name":re.compile(userName, re.IGNORECASE)}) - - if user != None: - return user["_id"] - else: - logThis("Couldn't find user "+userName) - return None - - def deleteGame(self, gameType,channel): - self.bot.database[gameType].delete_one({"_id":channel}) - - def stopServer(self): - self.bot.database["trivia questions"].delete_many({}) - self.bot.database["blackjack games"].delete_many({}) - - if not self.bot.options.testing: - g = git.cmd.Git("") - g.pull() - - def fiarReactionTest(self,channel,message,user): - game = self.bot.database["4 in a row games"].find_one({"_id":str(channel.id)}) - - with open("resources/games/oldImages/fourInARow"+str(channel.id), "r") as f: - oldImage = int(f.read()) - - if message.id == oldImage: - logThis("They reacted to the fourinarow game") - turn = game["turn"] - if user == game["players"][turn]: - return True, turn+1 - else: - logThis("It wasn't their turn") - return False, 0 - else: - return False, 0 - - def hangmanReactionTest(self, channel,message): - try: - with open("resources/games/oldImages/hangman"+str(channel.id), "r") as f: - oldMessages = f.read().splitlines() - except: - return False - gameMessage = False - - for oldMessage in oldMessages: - oldMessageID = int(oldMessage) - if message.id == oldMessageID: - logThis("They reacted to the hangman game") - gameMessage = True - - return gameMessage - - def bedreNetflixReactionTest(self,channel,message): - try: - with open("resources/bedreNetflix/oldMessage"+str(channel.id),"r") as f: - data = json.load(f) - except: - return False, None, None - if data["messageID"] == message.id: - if "imdbIds" in data: - return True, True, data["imdbIds"] - else: - return True, False, data["imdbNames"] - else: - return False, None, None \ No newline at end of file diff --git a/funcs/games/blackjack.py b/funcs/games/blackjack.py index a89cb9e..7fb9c02 100644 --- a/funcs/games/blackjack.py +++ b/funcs/games/blackjack.py @@ -6,7 +6,7 @@ import discord from shutil import copyfile -from funcs import logThis, replaceMultiple +from utils import replaceMultiple from .blackjackDraw import DrawBlackjack class Blackjack(): @@ -16,7 +16,7 @@ class Blackjack(): # Shuffles the blackjack cards def blackjackShuffle(self, decks, channel): - logThis("Shuffling the blackjack deck") + self.bot.log("Shuffling the blackjack deck") with open("resources/games/deckofCards.txt","r") as f: deck = f.read() @@ -27,7 +27,7 @@ class Blackjack(): self.bot.database["blackjack cards"].update_one({"_id":channel},{"$set":{"_id":channel,"cards":allDecks}},upsert=True) # Creates hilo file - logThis("creating hilo doc for "+channel) + self.bot.log("creating hilo doc for "+channel) data = 0 self.bot.database["hilo"].update_one({"_id":channel},{"$set":{"_id":channel,"hilo":data}},upsert=True) @@ -35,7 +35,7 @@ class Blackjack(): # Calculates the value of a blackjack hand def calcHandValue(self, hand : list): - logThis("Calculating hand value") + self.bot.log("Calculating hand value") values = [] values.append(0) @@ -58,13 +58,13 @@ class Blackjack(): if value <= 21: handValue = value - logThis("Calculated "+str(hand)+" to be "+str(handValue)) + self.bot.log("Calculated "+str(hand)+" to be "+str(handValue)) return handValue # Draws a card from the deck def drawCard(self, channel): - logThis("drawing a card") + self.bot.log("drawing a card") drawnCard = self.bot.database["blackjack cards"].find_one({"_id":channel})["cards"][0] self.bot.database["blackjack cards"].update_one({"_id":channel},{"$pop":{"cards":-1}}) @@ -97,7 +97,7 @@ class Blackjack(): # Goes to the next round and calculates some stuff def blackjackContinue(self, channel): - logThis("Continuing blackjack game") + self.bot.log("Continuing blackjack game") game = self.bot.database["blackjack games"].find_one({"_id":channel}) done = False @@ -109,20 +109,20 @@ class Blackjack(): message = "All players are standing. The dealer now shows his cards and draws." if game["all standing"]: - logThis("All are standing") + self.bot.log("All are standing") done = self.dealerDraw(channel) message = "The dealer draws a card." game = self.bot.database["blackjack games"].find_one({"_id":channel}) - logThis("Testing if all are standing") + self.bot.log("Testing if all are standing") for user in game["user hands"]: try: newUser, allStanding, preAllStanding = self.testIfStanding(game["user hands"][user],allStanding,preAllStanding,True) self.bot.database["blackjack games"].update_one({"_id":channel},{"$set":{"user hands."+user:newUser}}) except: - logThis("Error in testing if all are standing (error code 1331)") + self.bot.log("Error in testing if all are standing (error code 1331)") if allStanding: self.bot.database["blackjack games"].update_one({"_id":channel},{"$set":{"all standing":True}}) @@ -130,7 +130,7 @@ class Blackjack(): try: self.draw.drawImage(channel) except: - logThis("Error drawing blackjack table (error code 1340)") + self.bot.log("Error drawing blackjack table (error code 1340)") if allStanding: if done == False: @@ -141,10 +141,10 @@ class Blackjack(): return "", True, done else: if game["round"] == 1: - firstRoundMessage = ". You can also double down with \"!blackjack double\" or split with \"!blackjack split\"" + firstRoundMessage = ". You can also double down with \"/blackjack double\" or split with \"/blackjack split\"" else: firstRoundMessage = "" - return "You have 2 minutes to either hit or stand with \"!blackjack hit\" or \"!blackjack stand\""+firstRoundMessage+". It's assumed you're standing if you don't make a choice.", False, done + return "You have 2 minutes to either hit or stand with \"/blackjack hit\" or \"/blackjack stand\""+firstRoundMessage+". It's assumed you're standing if you don't make a choice.", False, done def testIfStanding(self, hand,allStanding,preAllStanding,topLevel): if hand["hit"] == False: @@ -209,19 +209,19 @@ class Blackjack(): return response + str(roundDone)[0] + str(game["round"]) else: - logThis(user+" is already standing") + self.bot.log(user+" is already standing") return "You can't hit when you're standing" else: - logThis(user+" has already hit this round") + self.bot.log(user+" has already hit this round") return "You've already hit this round" else: - logThis(user+" tried to hit on the 0th round") + self.bot.log(user+" tried to hit on the 0th round") return "You can't hit before you see your cards" else: - logThis(user+" didn't specify a hand") + self.bot.log(user+" didn't specify a hand") return "You need to specify a hand" else: - logThis(user+" tried to hit without being in the game") + self.bot.log(user+" tried to hit without being in the game") return "You have to enter the game before you can hit" @@ -267,27 +267,27 @@ class Blackjack(): roundDone = self.isRoundDone(self.bot.database["blackjack games"].find_one({"_id":channel})) - return "Adding another "+str(bet)+" GwendoBucks to "+self.bot.funcs.getName(user)+"'s bet and drawing another card.",str(roundDone)[0] + str(game["round"]) + return "Adding another "+str(bet)+" GwendoBucks to "+self.bot.databaseFuncs.getName(user)+"'s bet and drawing another card.",str(roundDone)[0] + str(game["round"]) else: - logThis(user+" doesn't have enough GwendoBucks") + self.bot.log(user+" doesn't have enough GwendoBucks") return "You don't have enough GwendoBucks","" else: - logThis(user+" tried to double on round "+str(game["round"])) + self.bot.log(user+" tried to double on round "+str(game["round"])) return "You can only double down on the first round","" else: - logThis(user+" is already standing") + self.bot.log(user+" is already standing") return "You can't double when you're standing","" else: - logThis(user+" has already hit this round") + self.bot.log(user+" has already hit this round") return "You've already hit this round","" else: - logThis(user+" tried to double on the 0th round") + self.bot.log(user+" tried to double on the 0th round") return "You can't double down before you see your cards","" else: - logThis(user+" didn't specify a hand") + self.bot.log(user+" didn't specify a hand") return "You need to specify which hand" else: - logThis(user+" tried to double without being in the game") + self.bot.log(user+" tried to double without being in the game") return "You can't double when you're not in the game","" # When players try to stand @@ -322,19 +322,19 @@ class Blackjack(): return response + str(roundDone)[0] + str(game["round"]) else: - logThis(user+" is already standing") + self.bot.log(user+" is already standing") return "You're already standing" else: - logThis(user+" has already hit this round") + self.bot.log(user+" has already hit this round") return "You've already hit this round" else: - logThis(user+" tried to stand on the first round") + self.bot.log(user+" tried to stand on the first round") return "You can't stand before you see your cards" else: - logThis(user+" didn't specify a hand") + self.bot.log(user+" didn't specify a hand") return "You need to specify which hand" else: - logThis(user+" tried to stand without being in the game") + self.bot.log(user+" tried to stand without being in the game") return "You have to enter the game before you can stand" # When players try to split @@ -355,7 +355,7 @@ class Blackjack(): elif handNumber == 3: hand = game["user hands"][user]["third hand"] else: - logThis(user+" tried to hit without specifying which hand") + self.bot.log(user+" tried to hit without specifying which hand") return "You have to specify the hand you're hitting with." if game["user hands"][user]["split"] == 1: @@ -365,7 +365,7 @@ class Blackjack(): newHand = game["user hands"][user]["fourth hand"] otherHand = 4 else: - logThis(user+" tried to split without specifying which hand") + self.bot.log(user+" tried to split without specifying which hand") return "You have to specify the hand you're splitting.","" if game["user hands"][user]["split"] < 3: @@ -430,34 +430,34 @@ class Blackjack(): roundDone = self.isRoundDone(self.bot.database["blackjack games"].find_one({"_id":channel})) - return "Splitting "+self.bot.funcs.getName(user)+"'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.",str(roundDone)[0] + str(game["round"]) + return "Splitting "+self.bot.databaseFuncs.getName(user)+"'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.",str(roundDone)[0] + str(game["round"]) else: - logThis(user+" doesn't have enough GwendoBucks") + self.bot.log(user+" doesn't have enough GwendoBucks") return "You don't have enough GwendoBucks","" else: - logThis(user+" tried to split 2 different cards") + self.bot.log(user+" tried to split 2 different cards") return "Your cards need to have the same value to split","" else: - logThis(user+" tried to split later than they could") + self.bot.log(user+" tried to split later than they could") return "You can only split on the first round","" else: - logThis(user+" is already standing") + self.bot.log(user+" is already standing") return "You can't split when you're standing","" else: - logThis(user+" has already hit this round") + self.bot.log(user+" has already hit this round") return "You've already hit this round","" else: - logThis(user+" tried to split on the 0th round") + self.bot.log(user+" tried to split on the 0th round") return "You can't split before you see your cards","" else: - logThis(user+" tried to split more than three times") + self.bot.log(user+" tried to split more than three times") return "You can only split 3 times","" # Player enters the game and draws a hand def blackjackPlayerDrawHand(self,channel,user,bet): game = self.bot.database["blackjack games"].find_one({"_id":channel}) - logThis(self.bot.funcs.getName(user)+" is trying to join the game in "+channel) + self.bot.log(self.bot.databaseFuncs.getName(user)+" is trying to join the game in "+channel) if game != None: if user not in game["user hands"]: @@ -481,32 +481,32 @@ class Blackjack(): self.bot.database["blackjack games"].update_one({"_id":channel}, {"$set":{"user hands."+user:newHand}}) - logThis(self.bot.funcs.getName(user)+" entered the game") - return self.bot.funcs.getName(user)+" entered the game" + self.bot.log(f"{self.bot.databaseFuncs.getName(user)} entered the game with a bet of {bet}") + return f"{self.bot.databaseFuncs.getName(user)} entered the game with a bet of {bet}" else: - logThis(user+" doesn't have enough GwendoBucks") + self.bot.log(user+" doesn't have enough GwendoBucks") return "You don't have enough GwendoBucks to place that bet" else: - logThis(user+" tried to bet a negative amount") + self.bot.log(user+" tried to bet a negative amount") return "You can't bet a negative amount" else: - logThis("The table is no longer open for bets") + self.bot.log("The table is no longer open for bets") return "The table is no longer open for bets" else: - logThis("There are already 5 players in the game.") + self.bot.log("There are already 5 players in the game.") return "There's already a maximum of players at the table." else: - logThis(user+" is already in the game") + self.bot.log(user+" is already in the game") return "You've already entered this game" else: - logThis("There is no game going on in "+channel) + self.bot.log("There is no game going on in "+channel) return "There is no game going on in this channel" # Starts a game of blackjack def blackjackStart(self,channel:str): game = self.bot.database["blackjack games"].find_one({"_id":channel}) - logThis("Trying to start a blackjack game in "+channel) + self.bot.log("Trying to start a blackjack game in "+channel) if game == None: @@ -524,7 +524,7 @@ class Blackjack(): return "started" else: - logThis("There is already a blackjack game going on in "+channel) + self.bot.log("There is already a blackjack game going on in "+channel) return "There's already a blackjack game going on. Try again in a few minutes." # Ends the game and calculates winnings @@ -540,26 +540,23 @@ class Blackjack(): try: for user in game["user hands"]: - try: - winnings, netWinnings, reason = self.calcWinnings(game["user hands"][user],dealerValue,True,dealerBlackjack,dealerBusted) - except: - logThis("Error calculating winnings for "+str(user)+" (error code 1312)") + winnings, netWinnings, reason = self.calcWinnings(game["user hands"][user],dealerValue,True,dealerBlackjack,dealerBusted) if winnings < 0: if winnings == -1: - finalWinnings += self.bot.funcs.getName(user)+" lost "+str(-1 * winnings)+" GwendoBuck "+reason+"\n" + finalWinnings += self.bot.databaseFuncs.getName(user)+" lost "+str(-1 * winnings)+" GwendoBuck "+reason+"\n" else: - finalWinnings += self.bot.funcs.getName(user)+" lost "+str(-1 * winnings)+" GwendoBucks "+reason+"\n" + finalWinnings += self.bot.databaseFuncs.getName(user)+" lost "+str(-1 * winnings)+" GwendoBucks "+reason+"\n" else: if winnings == 1: - finalWinnings += self.bot.funcs.getName(user)+" won "+str(winnings)+" GwendoBuck "+reason+"\n" + finalWinnings += self.bot.databaseFuncs.getName(user)+" won "+str(winnings)+" GwendoBuck "+reason+"\n" else: - finalWinnings += self.bot.funcs.getName(user)+" won "+str(winnings)+" GwendoBucks "+reason+"\n" + finalWinnings += self.bot.databaseFuncs.getName(user)+" won "+str(winnings)+" GwendoBucks "+reason+"\n" self.bot.money.addMoney(user,netWinnings) except: - logThis("Error calculating winnings (error code 1311)") + self.bot.log("Error calculating winnings (error code 1311)") self.bot.database["blackjack games"].delete_one({"_id":channel}) @@ -567,7 +564,7 @@ class Blackjack(): def calcWinnings(self,hand, dealerValue, topLevel, dealerBlackjack, dealerBusted): - logThis("Calculating winnings") + self.bot.log("Calculating winnings") reason = "" bet = hand["bet"] winnings = -1 * bet @@ -637,7 +634,7 @@ class Blackjack(): return hand, handNumber except: - logThis("Problem with getHandNumber() (error code 1322)") + self.bot.log("Problem with getHandNumber() (error code 1322)") def isRoundDone(self,game): roundDone = True @@ -662,14 +659,14 @@ class Blackjack(): # Loop of blackjack game rounds async def blackjackLoop(self,channel,gameRound,gameID): - logThis("Loop "+str(gameRound),str(channel.id)) + self.bot.log("Loop "+str(gameRound),str(channel.id)) with open("resources/games/oldImages/blackjack"+str(channel.id), "r") as f: oldImage = await channel.fetch_message(int(f.read())) new_message, allStanding, gamedone = self.blackjackContinue(str(channel.id)) if new_message != "": - logThis(new_message,str(channel.id)) + self.bot.log(new_message,str(channel.id)) await channel.send(new_message) if gamedone == False: await oldImage.delete() @@ -683,7 +680,7 @@ class Blackjack(): else: await asyncio.sleep(120) except: - logThis("Loop "+str(gameRound)+" interrupted (error code 1321)") + self.bot.log("Loop "+str(gameRound)+" interrupted (error code 1321)") game = self.bot.database["blackjack games"].find_one({"_id":str(channel.id)}) @@ -693,27 +690,28 @@ class Blackjack(): if gameRound == realRound and realGameID == gameID: if gamedone == False: - logThis("Loop "+str(gameRound)+" calling self.blackjackLoop()",str(channel.id)) + self.bot.log("Loop "+str(gameRound)+" calling self.blackjackLoop()",str(channel.id)) await self.blackjackLoop(channel,gameRound+1,gameID) else: try: new_message = self.blackjackFinish(str(channel.id)) except: - logThis("Something fucked up (error code 1310)") + self.bot.log("Something fucked up (error code 1310)") await channel.send(new_message) else: - logThis("Ending loop on round "+str(gameRound),str(channel.id)) + self.bot.log("Ending loop on round "+str(gameRound),str(channel.id)) else: - logThis("Ending loop on round "+str(gameRound),str(channel.id)) + self.bot.log("Ending loop on round "+str(gameRound),str(channel.id)) async def parseBlackjack(self,content, ctx): # Blackjack shuffle variables blackjackMinCards = 50 blackjackDecks = 4 - channel = ctx.message.channel.id + channel = ctx.channel_id # Starts the game if content == "": + await ctx.send("Starting a new game of blackjack") cardsLeft = 0 cards = self.bot.database["blackjack cards"].find_one({"_id":str(channel)}) if cards != None: @@ -722,15 +720,15 @@ class Blackjack(): # Shuffles if not enough cards if cardsLeft < blackjackMinCards: self.blackjackShuffle(blackjackDecks,str(channel)) - logThis("Shuffling the blackjack deck...",str(channel)) - await ctx.send("Shuffling the deck...") + self.bot.log("Shuffling the blackjack deck...",str(channel)) + await ctx.channel.send("Shuffling the deck...") new_message = self.blackjackStart(str(channel)) if new_message == "started": - new_message = "Blackjack game started. Use \"!blackjack bet [amount]\" to enter the game within the next 30 seconds." - await ctx.send(new_message) - oldImage = await ctx.send(file = discord.File("resources/games/blackjackTables/blackjackTable"+str(channel)+".png")) + new_message = "Blackjack game started. Use \"/blackjack bet [amount]\" to enter the game within the next 30 seconds." + await ctx.channel.send(new_message) + oldImage = await ctx.channel.send(file = discord.File("resources/games/blackjackTables/blackjackTable"+str(channel)+".png")) with open("resources/games/oldImages/blackjack"+str(channel), "w") as f: f.write(str(oldImage.id)) @@ -743,47 +741,47 @@ class Blackjack(): if len(game["user hands"]) == 0: gamedone = True - await ctx.send("No one entered the game. Ending the game.") + await ctx.channel.send("No one entered the game. Ending the game.") gameID = game["gameID"] # Loop of game rounds if gamedone == False: - logThis("!blackjack calling self.blackjackLoop()",str(channel)) - await self.blackjackLoop(ctx.message.channel,1,gameID) + self.bot.log("/blackjack calling self.blackjackLoop()",str(channel)) + await self.blackjackLoop(ctx.channel,1,gameID) else: new_message = self.blackjackFinish(str(channel)) - await ctx.send(new_message) + await ctx.channel.send(new_message) else: - await ctx.send(new_message) + await ctx.channel.send(new_message) # Entering game and placing bet elif content.startswith("bet"): commands = content.split(" ") amount = int(commands[1]) - response = self.blackjackPlayerDrawHand(str(channel),"#"+str(ctx.message.author.id),amount) + response = self.blackjackPlayerDrawHand(str(channel),"#"+str(ctx.author.id),amount) await ctx.send(response) # Hitting elif content.startswith("hit"): if content == "hit": - response = self.blackjackHit(str(channel),"#"+str(ctx.message.author.id)) + response = self.blackjackHit(str(channel),"#"+str(ctx.author.id)) else: commands = content.split(" ") try: handNumber = int(commands[1]) except: handNumber = 0 - response = self.blackjackHit(str(channel),"#"+str(ctx.message.author.id),handNumber) + response = self.blackjackHit(str(channel),"#"+str(ctx.author.id),handNumber) if response.startswith("accept"): - await ctx.message.add_reaction("👍") + await ctx.send(f"{ctx.author.display_name} hit") #try: if response[6] == "T": gameID = self.bot.database["blackjack games"].find_one({"_id":str(channel)})["gameID"] - logThis("Hit calling self.blackjackLoop()",str(channel)) - await self.blackjackLoop(ctx.message.channel,int(response[7:])+1,gameID) + self.bot.log("Hit calling self.blackjackLoop()",str(channel)) + await self.blackjackLoop(ctx.channel,int(response[7:])+1,gameID) #except: - # logThis("Something fucked up (error code 1320)",str(channel)) + # self.bot.log("Something fucked up (error code 1320)",str(channel)) else: await ctx.send(response) @@ -791,24 +789,24 @@ class Blackjack(): # Standing elif content.startswith("stand"): if content == "hit": - response = self.blackjackStand(str(channel),"#"+str(ctx.message.author.id)) + response = self.blackjackStand(str(channel),"#"+str(ctx.author.id)) else: commands = content.split(" ") try: handNumber = int(commands[1]) except: handNumber = 0 - response = self.blackjackStand(str(channel),"#"+str(ctx.message.author.id),handNumber) + response = self.blackjackStand(str(channel),"#"+str(ctx.author.id),handNumber) if response.startswith("accept"): - await ctx.message.add_reaction("👍") + await ctx.send(f"{ctx.author.display_name} is standing") #try: if response[6] == "T": gameID = self.bot.database["blackjack games"].find_one({"_id":str(channel)})["gameID"] - logThis("Stand calling self.blackjackLoop()",str(channel)) - await self.blackjackLoop(ctx.message.channel,int(response[7:])+1,gameID) + self.bot.log("Stand calling self.blackjackLoop()",str(channel)) + await self.blackjackLoop(ctx.channel,int(response[7:])+1,gameID) #except: - # logThis("Something fucked up (error code 1320)",str(channel)) + # self.bot.log("Something fucked up (error code 1320)",str(channel)) else: await ctx.send(response) @@ -819,17 +817,17 @@ class Blackjack(): handNumber = int(commands[1]) except: handNumber = 0 - response, roundDone = self.blackjackDouble(str(channel),"#"+str(ctx.message.author.id),handNumber) + response, roundDone = self.blackjackDouble(str(channel),"#"+str(ctx.author.id),handNumber) await ctx.send(response) try: if roundDone[0] == "T": gameID = self.bot.database["blackjack games"].find_one({"_id":str(channel)})["gameID"] - logThis("Double calling self.blackjackLoop()",str(channel)) - await self.blackjackLoop(ctx.message.channel,int(roundDone[1:])+1,gameID) + self.bot.log("Double calling self.blackjackLoop()",str(channel)) + await self.blackjackLoop(ctx.channel,int(roundDone[1:])+1,gameID) except: - logThis("Something fucked up (error code 1320)",str(channel)) + self.bot.log("Something fucked up (error code 1320)",str(channel)) # Splitting hand elif content.startswith("split"): @@ -838,17 +836,17 @@ class Blackjack(): handNumber = int(commands[1]) except: handNumber = 0 - response, roundDone = self.blackjackSplit(str(channel),"#"+str(ctx.message.author.id),handNumber) + response, roundDone = self.blackjackSplit(str(channel),"#"+str(ctx.author.id),handNumber) await ctx.send(response) try: if roundDone[0] == "T": gameID = self.bot.database["blackjack games"].find_one({"_id":str(channel)})["gameID"] - logThis("Split calling self.blackjackLoop()",str(channel)) - await self.blackjackLoop(ctx.message.channel,int(roundDone[1:])+1,gameID) + self.bot.log("Split calling self.blackjackLoop()",str(channel)) + await self.blackjackLoop(ctx.channel,int(roundDone[1:])+1,gameID) except: - logThis("Something fucked up (error code 1320)") + self.bot.log("Something fucked up (error code 1320)") # Returning current hi-lo value elif content.startswith("hilo"): @@ -857,12 +855,12 @@ class Blackjack(): hilo = str(data["hilo"]) else: hilo = "0" - await ctx.send(hilo) + await ctx.send(hilo, hidden=True) # Shuffles the blackjack deck elif content.startswith("shuffle"): self.blackjackShuffle(blackjackDecks,str(channel)) - logThis("Shuffling the blackjack deck...",str(channel)) + self.bot.log("Shuffling the blackjack deck...",str(channel)) await ctx.send("Shuffling the deck...") @@ -874,9 +872,9 @@ class Blackjack(): cardsLeft = len(cards["cards"]) decksLeft = round(cardsLeft/52,1) - await ctx.send(str(cardsLeft)+" cards, "+str(decksLeft)+" decks") + await ctx.send(str(cardsLeft)+" cards, "+str(decksLeft)+" decks", hidden=True) else: - logThis("Not a command (error code 1301)") + self.bot.log("Not a command (error code 1301)") await ctx.send("I didn't quite understand that (error code 1301)") diff --git a/funcs/games/blackjackDraw.py b/funcs/games/blackjackDraw.py index 6e9a4c3..23aae9e 100644 --- a/funcs/games/blackjackDraw.py +++ b/funcs/games/blackjackDraw.py @@ -1,5 +1,4 @@ from PIL import Image, ImageDraw, ImageFont -from funcs import logThis border = 100 placement = [0,0] @@ -10,11 +9,11 @@ class DrawBlackjack(): self.bot = bot def drawImage(self,channel): - logThis("Drawing blackjack table",channel) + self.bot.log("Drawing blackjack table",channel) game = self.bot.database["blackjack games"].find_one({"_id":channel}) - fnt = ImageFont.truetype('resources/futura-bold.ttf', 50) - fntSmol = ImageFont.truetype('resources/futura-bold.ttf', 40) + fnt = ImageFont.truetype('resources/fonts/futura-bold.ttf', 50) + fntSmol = ImageFont.truetype('resources/fonts/futura-bold.ttf', 40) borderSmol = int(border/3.5) table = Image.open("resources/games/blackjackTable.png") @@ -31,14 +30,14 @@ class DrawBlackjack(): else: dealerHand = self.drawHand(game["dealer hand"],False,dealerBusted,dealerBlackjack) except: - logThis("Error drawing dealer hand (error code 1341a)") + self.bot.log("Error drawing dealer hand (error code 1341a)") table.paste(dealerHand,(800-borderSmol,20-borderSmol),dealerHand) for x in range(len(hands)): key, value = list(hands.items())[x] - key = self.bot.funcs.getName(key) - #logThis("Drawing "+key+"'s hand") + key = self.bot.databaseFuncs.getName(key) + #self.bot.log("Drawing "+key+"'s hand") userHand = self.drawHand(value["hand"],False,value["busted"],value["blackjack"]) try: if value["split"] == 3: @@ -62,7 +61,7 @@ class DrawBlackjack(): else: table.paste(userHand,(32-borderSmol+(384*placement[x]),680-borderSmol),userHand) except: - logThis("Error drawing player hands (error code 1341b)") + self.bot.log("Error drawing player hands (error code 1341b)") textWidth = fnt.getsize(key)[0] if textWidth < 360: @@ -79,15 +78,15 @@ class DrawBlackjack(): textImage.text((32+(384*placement[x])+117-int(textWidth/2)+2,1020+2),key,fill=(0,0,0), font=fntSmol) textImage.text((32+(384*placement[x])+117-int(textWidth/2),1015),key,fill=(255,255,255), font=fntSmol) - logThis("Saving table image") + self.bot.log("Saving table image") table.save("resources/games/blackjackTables/blackjackTable"+channel+".png") return def drawHand(self, hand, dealer, busted, blackjack): - logThis("Drawing hand "+str(hand)+", "+str(busted)+", "+str(blackjack)) - fnt = ImageFont.truetype('resources/futura-bold.ttf', 200) - fnt2 = ImageFont.truetype('resources/futura-bold.ttf', 120) + self.bot.log("Drawing hand "+str(hand)+", "+str(busted)+", "+str(blackjack)) + fnt = ImageFont.truetype('resources/fonts/futura-bold.ttf', 200) + fnt2 = ImageFont.truetype('resources/fonts/futura-bold.ttf', 120) length = len(hand) background = Image.new("RGBA", ((border*2)+691+(125*(length-1)),(border*2)+1065),(0,0,0,0)) textImage = ImageDraw.Draw(background) @@ -114,7 +113,7 @@ class DrawBlackjack(): w, h = background.size textHeight = 290+border - #logThis("Drawing busted/blackjack") + #self.bot.log("Drawing busted/blackjack") if busted: textWidth = fnt.getsize("BUSTED")[0] textImage.text((int(w/2)-int(textWidth/2)-10,textHeight+20-10),"BUSTED",fill=(0,0,0), font=fnt) @@ -138,5 +137,5 @@ class DrawBlackjack(): textImage.text((int(w/2)-int(textWidth/2)+3,textHeight+3),"BLACKJACK",fill=(255,255,255), font=fnt2) textImage.text((int(w/2)-int(textWidth/2),textHeight),"BLACKJACK",fill=(155,123,0), font=fnt2) - #logThis("Returning resized image") + #self.bot.log("Returning resized image") return background.resize((int(w/3.5),int(h/3.5)),resample=Image.BILINEAR) diff --git a/funcs/games/fourInARow.py b/funcs/games/connectFour.py similarity index 77% rename from funcs/games/fourInARow.py rename to funcs/games/connectFour.py index 23fa96a..d655c62 100644 --- a/funcs/games/fourInARow.py +++ b/funcs/games/connectFour.py @@ -2,8 +2,7 @@ import random import copy import math -from .fourInARowDraw import DrawFourInARow -from funcs import logThis +from .connectFourDraw import drawConnectFour AIScores = { "middle": 3, @@ -20,14 +19,14 @@ rowCount = 6 columnCount = 7 easy = True -class FourInARow(): +class connectFour(): def __init__(self,bot): self.bot = bot - self.draw = DrawFourInARow(bot) + self.draw = drawConnectFour(bot) # Starts the game - def fourInARowStart(self, channel, user, opponent): - game = self.bot.database["4 in a row games"].find_one({"_id":channel}) + def connectFourStart(self, channel, user, opponent): + game = self.bot.database["connect 4 games"].find_one({"_id":channel}) if game == None: @@ -45,7 +44,7 @@ class FourInARow(): return "That difficulty doesn't exist", False, False, False, False except: # Opponent is another player - opponent = self.bot.funcs.getID(opponent) + opponent = self.bot.databaseFuncs.getID(opponent) if opponent != None: difficulty = 5 diffText = "" @@ -62,7 +61,7 @@ class FourInARow(): newGame = {"_id":channel,"board": board,"winner":0,"win direction":"", "win coordinates":[0,0],"players":players,"turn":0,"difficulty":difficulty} - self.bot.database["4 in a row games"].insert_one(newGame) + self.bot.database["connect 4 games"].insert_one(newGame) self.draw.drawImage(channel) @@ -71,13 +70,13 @@ class FourInARow(): if players[0] == "Gwendolyn": gwendoTurn = True - return "Started game against "+self.bot.funcs.getName(opponent)+diffText+". It's "+self.bot.funcs.getName(players[0])+"'s turn", True, False, False, gwendoTurn + return "Started game against "+self.bot.databaseFuncs.getName(opponent)+diffText+". It's "+self.bot.databaseFuncs.getName(players[0])+"'s turn", True, False, False, gwendoTurn else: - return "There's already a 4 in a row game going on in this channel", False, False, False, False + return "There's already a connect 4 game going on in this channel", False, False, False, False # Places a piece at the lowest available point in a specific column def placePiece(self, channel : str,player : int,column : int): - game = self.bot.database["4 in a row games"].find_one({"_id":channel}) + game = self.bot.database["connect 4 games"].find_one({"_id":channel}) if game != None: board = game["board"] @@ -85,21 +84,21 @@ class FourInARow(): board = self.placeOnBoard(board,player,column) if board != None: - self.bot.database["4 in a row games"].update_one({"_id":channel},{"$set":{"board":board}}) + self.bot.database["connect 4 games"].update_one({"_id":channel},{"$set":{"board":board}}) turn = (game["turn"]+1)%2 - self.bot.database["4 in a row games"].update_one({"_id":channel},{"$set":{"turn":turn}}) + self.bot.database["connect 4 games"].update_one({"_id":channel},{"$set":{"turn":turn}}) - logThis("Checking for win") + self.bot.log("Checking for win") won, winDirection, winCoordinates = self.isWon(board) if won != 0: gameWon = True - self.bot.database["4 in a row games"].update_one({"_id":channel},{"$set":{"winner":won}}) - self.bot.database["4 in a row games"].update_one({"_id":channel},{"$set":{"win direction":winDirection}}) - self.bot.database["4 in a row games"].update_one({"_id":channel}, + self.bot.database["connect 4 games"].update_one({"_id":channel},{"$set":{"winner":won}}) + self.bot.database["connect 4 games"].update_one({"_id":channel},{"$set":{"win direction":winDirection}}) + self.bot.database["connect 4 games"].update_one({"_id":channel}, {"$set":{"win coordinates":winCoordinates}}) - message = self.bot.funcs.getName(game["players"][won-1])+" placed a piece in column "+str(column+1)+" and won." + message = self.bot.databaseFuncs.getName(game["players"][won-1])+" placed a piece in column "+str(column+1)+" and won." winAmount = int(game["difficulty"])**2+5 if game["players"][won-1] != "Gwendolyn": message += " Adding "+str(winAmount)+" GwendoBucks to their account." @@ -108,12 +107,12 @@ class FourInARow(): message = "It's a draw!" else: gameWon = False - message = self.bot.funcs.getName(game["players"][player-1])+" placed a piece in column "+str(column+1)+". It's now "+self.bot.funcs.getName(game["players"][turn])+"'s turn." + message = self.bot.databaseFuncs.getName(game["players"][player-1])+" placed a piece in column "+str(column+1)+". It's now "+self.bot.databaseFuncs.getName(game["players"][turn])+"'s turn." gwendoTurn = False if game["players"][turn] == "Gwendolyn": - logThis("It's Gwendolyn's turn") + self.bot.log("It's Gwendolyn's turn") gwendoTurn = True self.draw.drawImage(channel) @@ -139,19 +138,19 @@ class FourInARow(): return board # Parses command - def parseFourInARow(self, command, channel, user): + def parseconnectFour(self, command, channel, user): commands = command.split() if command == "" or command == " ": - return "I didn't get that. Use \"!fourinarow start [opponent]\" to start a game. To play against the computer, use difficulty 1 through 5 as the [opponent].", False, False, False, False + return "I didn't get that. Use \"/connectFour start [opponent]\" to start a game. To play against the computer, use difficulty 1 through 5 as the [opponent].", False, False, False, False elif commands[0] == "start": # Starting a game - if len(commands) == 1: # if the commands is "!fourinarow start", the opponent is Gwendolyn + if len(commands) == 1: # if the commands is "/connectFour start", the opponent is Gwendolyn commands.append("3") - return self.fourInARowStart(channel,user,commands[1]) # commands[1] is the opponent + return self.connectFourStart(channel,user,commands[1]) # commands[1] is the opponent # Stopping the game elif commands[0] == "stop": - game = self.bot.database["4 in a row games"].find_one({"_id":channel}) + game = self.bot.database["connect 4 games"].find_one({"_id":channel}) if user in game["players"]: return "Ending game.", False, False, True, False @@ -160,12 +159,21 @@ class FourInARow(): # Placing manually elif commands[0] == "place": - try: - return self.placePiece(channel,int(commands[1]),int(commands[2])-1) - except: - return "I didn't get that. To place a piece use \"!fourinarow place [player number] [column]\" or press the corresponding message-reaction beneath the board.", False, False, False, False + if len(commands) == 2: + game = self.bot.database["connect 4 games"].find_one({"_id":channel}) + turn = game["turn"] + if user == game["players"][turn]: + piece = turn + 1 + else: + self.bot.log("It wasn't their turn") + return "It's not your turn!", False, False, False, False + column = int(commands[1])-1 + else: + column = int(commands[2])-1 + piece = int(commands[1]) + return self.placePiece(channel, piece, column) else: - return "I didn't get that. Use \"!fourinarow start [opponent]\" to start a game. To play against the computer, use difficulty 1 through 5 as the [opponent].", False, False, False, False + return "I didn't get that. Use \"/connectFour start [opponent]\" to start a game. To play against the computer, use difficulty 1 through 5 as the [opponent].", False, False, False, False # Checks if someone has won the game and returns the winner def isWon(self, board): @@ -226,9 +234,9 @@ class FourInARow(): return won, winDirection, winCoordinates # Plays as the AI - async def fourInARowAI(self, channel): - logThis("Figuring out best move") - game = self.bot.database["4 in a row games"].find_one({"_id":channel}) + async def connectFourAI(self, channel): + self.bot.log("Figuring out best move") + game = self.bot.database["connect 4 games"].find_one({"_id":channel}) board = game["board"] player = game["players"].index("Gwendolyn")+1 @@ -240,7 +248,7 @@ class FourInARow(): testBoard = self.placeOnBoard(testBoard,player,column) if testBoard != None: scores[column] = await self.minimax(testBoard,difficulty,player%2+1,player,-math.inf,math.inf,False) - logThis("Best score for column "+str(column)+" is "+str(scores[column])) + self.bot.log("Best score for column "+str(column)+" is "+str(scores[column])) possibleScores = scores.copy() diff --git a/funcs/games/fourInARowDraw.py b/funcs/games/connectFourDraw.py similarity index 94% rename from funcs/games/fourInARowDraw.py rename to funcs/games/connectFourDraw.py index 58a99da..340bb2f 100644 --- a/funcs/games/fourInARowDraw.py +++ b/funcs/games/connectFourDraw.py @@ -1,16 +1,15 @@ import math from PIL import Image, ImageDraw, ImageFont -from funcs import logThis -class DrawFourInARow(): - def __init__(self,bot): +class drawConnectFour(): + def __init__(self, bot): self.bot = bot # Draws the whole thing def drawImage(self, channel): - logThis("Drawing four in a row board") - game = self.bot.database["4 in a row games"].find_one({"_id":channel}) + self.bot.log("Drawing connect four board") + game = self.bot.database["connect 4 games"].find_one({"_id":channel}) board = game["board"] @@ -34,7 +33,7 @@ class DrawFourInARow(): white = (255,255,255,160) winBarColor = (250,250,250,255) - fnt = ImageFont.truetype('resources/futura-bold.ttf', exampleCircles) + fnt = ImageFont.truetype('resources/fonts/futura-bold.ttf', exampleCircles) boardSize = [w-(2*(border+gridBorder)),h-(2*(border+gridBorder))] placeGridSize = [math.floor(boardSize[0]/7),math.floor(boardSize[1]/6)] @@ -44,12 +43,12 @@ class DrawFourInARow(): if game["players"][0] == "Gwendolyn": player1 = "Gwendolyn" else: - player1 = self.bot.funcs.getName(game["players"][0]) + player1 = self.bot.databaseFuncs.getName(game["players"][0]) if game["players"][1] == "Gwendolyn": player2 = "Gwendolyn" else: - player2 = self.bot.funcs.getName(game["players"][1]) + player2 = self.bot.databaseFuncs.getName(game["players"][1]) background = Image.new("RGB", (w,h+bottomBorder),backgroundColor) @@ -153,4 +152,4 @@ class DrawFourInARow(): d.text((w-border-textWidth,exampleHeight),player2,font=fnt,fill=(0,0,0)) - background.save("resources/games/4InARowBoards/board"+channel+".png") + background.save("resources/games/connect4Boards/board"+channel+".png") diff --git a/funcs/games/gameLoops.py b/funcs/games/gameLoops.py index d70f172..f680558 100644 --- a/funcs/games/gameLoops.py +++ b/funcs/games/gameLoops.py @@ -1,8 +1,6 @@ import asyncio import discord -from funcs import logThis - class GameLoops(): def __init__(self,bot): self.bot = bot @@ -16,43 +14,43 @@ class GameLoops(): for message in messages: oldMessage = await channel.fetch_message(int(message)) - logThis("Deleting old message") + self.bot.log("Deleting old message") await oldMessage.delete() except: oldMessage = "" return oldMessage - # Runs Four in a Row - async def fiar(self, channel,command,user): - try: - response, showImage, deleteImage, gameDone, gwendoTurn = self.bot.fourInARow.parseFourInARow(command,str(channel.id),user) - except: - logThis("Error parsing command (error code 1410)") + # Runs connect four + async def connectFour(self, ctx, command, user = None, channelId = None): + if user is None: + user = "#"+str(ctx.author.id) - await channel.send(response) - logThis(response,str(channel.id)) + if channelId is None: + channelId = str(ctx.channel_id) + + response, showImage, deleteImage, gameDone, gwendoTurn = self.bot.games.connectFour.parseconnectFour(command,channelId, user) + + if hasattr(ctx, "send"): + await ctx.send(response) + else: + await ctx.channel.send(response) + self.bot.log(response, channelId) if showImage: if deleteImage: - try: - oldImage = await self.deleteMessage("fourInARow"+str(channel.id),channel) - except: - logThis("Error deleting message (error code 1401)") - oldImage = await channel.send(file = discord.File("resources/games/4InARowBoards/board"+str(channel.id)+".png")) + oldImage = await self.deleteMessage("connectFour"+channelId,ctx.channel) + oldImage = await ctx.channel.send(file = discord.File("resources/games/connect4Boards/board"+channelId+".png")) if gameDone == False: if gwendoTurn: - try: - response, showImage, deleteImage, gameDone, gwendoTurn = await self.bot.fourInARow.fourInARowAI(str(channel.id)) - except: - logThis("AI error (error code 1420)") - await channel.send(response) - logThis(response,str(channel.id)) + response, showImage, deleteImage, gameDone, gwendoTurn = await self.bot.games.connectFour.connectFourAI(channelId) + await ctx.channel.send(response) + self.bot.log(response,channelId) if showImage: if deleteImage: await oldImage.delete() - oldImage = await channel.send(file = discord.File("resources/games/4InARowBoards/board"+str(channel.id)+".png")) + oldImage = await ctx.channel.send(file = discord.File("resources/games/connect4Boards/board"+channelId+".png")) if gameDone == False: - with open("resources/games/oldImages/fourInARow"+str(channel.id), "w") as f: + with open("resources/games/oldImages/connectFour"+channelId, "w") as f: f.write(str(oldImage.id)) try: reactions = ["1️⃣","2️⃣","3️⃣","4️⃣","5️⃣","6️⃣","7️⃣"] @@ -60,28 +58,28 @@ class GameLoops(): await oldImage.add_reaction(reaction) except: - logThis("Image deleted before I could react to all of them") + self.bot.log("Image deleted before I could react to all of them") else: - with open("resources/games/oldImages/fourInARow"+str(channel.id), "w") as f: + with open("resources/games/oldImages/connectFour"+channelId, "w") as f: f.write(str(oldImage.id)) try: reactions = ["1️⃣","2️⃣","3️⃣","4️⃣","5️⃣","6️⃣","7️⃣"] for reaction in reactions: await oldImage.add_reaction(reaction) except: - logThis("Image deleted before I could react to all of them") + self.bot.log("Image deleted before I could react to all of them") if gameDone: - game = self.bot.database["4 in a row games"].find_one({"_id":str(channel.id)}) + game = self.bot.database["connect 4 games"].find_one({"_id":channelId}) try: - with open("resources/games/oldImages/fourInARow"+str(channel.id), "r") as f: + with open("resources/games/oldImages/connectFour"+channelId, "r") as f: oldImage = await channel.fetch_message(int(f.read())) await oldImage.delete() except: - logThis("The old image was already deleted") + self.bot.log("The old image was already deleted") winner = game["winner"] difficulty = int(game["difficulty"]) @@ -90,16 +88,19 @@ class GameLoops(): if game["players"][winner-1].lower() != "gwendolyn": self.bot.money.addMoney(game["players"][winner-1].lower(),reward) - self.bot.funcs.deleteGame("4 in a row games",str(channel.id)) + self.bot.databaseFuncs.deleteGame("connect 4 games",channelId) - async def runHangman(self,channel,user,command = "start"): + async def runHangman(self,channel,user,command = "start", ctx = None): try: - response, showImage, deleteImage, remainingLetters = self.bot.hangman.parseHangman(str(channel.id),user,command) + response, showImage, deleteImage, remainingLetters = self.bot.games.hangman.parseHangman(str(channel.id),user,command) except: - logThis("Error parsing command (error code 1701)") + self.bot.log("Error parsing command (error code 1701)") if response != "": - await channel.send(response) - logThis(response,str(channel.id)) + if ctx is None: + await channel.send(response) + else: + await ctx.send(response) + self.bot.log(response,str(channel.id)) if showImage: if deleteImage: await self.deleteMessage("hangman"+str(channel.id),channel) @@ -124,47 +125,48 @@ class GameLoops(): emoji = chr(ord(letter)+127397) await message.add_reaction(emoji) except: - logThis("Image deleted before adding all reactions") + self.bot.log("Image deleted before adding all reactions") # Runs Hex - async def runHex(self,channel,command,user): + async def runHex(self,ctx,command,user): + channelId = ctx.channel_id try: - response, showImage, deleteImage, gameDone, gwendoTurn = self.bot.hex.parseHex(command,str(channel.id),user) + response, showImage, deleteImage, gameDone, gwendoTurn = self.bot.games.hex.parseHex(command,str(channelId),user) except: - logThis("Error parsing command (error code 1510)") + self.bot.log("Error parsing command (error code 1510)") - await channel.send(response) + await ctx.send(response) - logThis(response,str(channel.id)) + self.bot.log(response,str(channelId)) if showImage: if deleteImage: try: - oldImage = await self.deleteMessage("hex"+str(channel.id),channel) + oldImage = await self.deleteMessage("hex"+str(channelId),ctx.channel) except: - logThis("Error deleting old image (error code 1501)") - oldImage = await channel.send(file = discord.File("resources/games/hexBoards/board"+str(channel.id)+".png")) + self.bot.log("Error deleting old image (error code 1501)") + oldImage = await ctx.channel.send(file = discord.File("resources/games/hexBoards/board"+str(channelId)+".png")) if gwendoTurn and not gameDone: try: - response, showImage, deleteImage, gameDone, gwendoTurn = self.bot.hex.hexAI(str(channel.id)) + response, showImage, deleteImage, gameDone, gwendoTurn = self.bot.games.hex.hexAI(str(channelId)) except: - response, showImage, deleteImage, gameDone, gwendoTurn = "An AI error occured",False,False,False,False - logThis("AI error (error code 1520)") - await channel.send(response) - logThis(response,str(channel.id)) + response, showImage, deleteImage, gameDone, gwendoTurn = "An AI error ocurred",False,False,False,False + self.bot.log("AI error (error code 1520)") + await ctx.channel.send(response) + self.bot.log(response,str(channelId)) if showImage: if deleteImage: await oldImage.delete() - oldImage = await channel.send(file = discord.File("resources/games/hexBoards/board"+str(channel.id)+".png")) + oldImage = await ctx.channel.send(file = discord.File("resources/games/hexBoards/board"+str(channelId)+".png")) if not gameDone: - with open("resources/games/oldImages/hex"+str(channel.id), "w") as f: + with open("resources/games/oldImages/hex"+str(channelId), "w") as f: f.write(str(oldImage.id)) if gameDone: - game = self.bot.database["hex games"].find_one({"_id":str(channel.id)}) - + game = self.bot.database["hex games"].find_one({"_id":str(channelId)}) + winner = game["winner"] if winner != 0 and game["players"][0] != game["players"][1]: # player1 != player2 winnings = game["difficulty"]*10 self.bot.money.addMoney(game["players"][winner-1].lower(),winnings) - self.bot.funcs.deleteGame("hex games",str(channel.id)) + self.bot.databaseFuncs.deleteGame("hex games",str(channelId)) diff --git a/funcs/games/games.py b/funcs/games/games.py index c17a142..1afee45 100644 --- a/funcs/games/games.py +++ b/funcs/games/games.py @@ -1,7 +1,7 @@ from .invest import Invest from .trivia import Trivia from .blackjack import Blackjack -from .fourInARow import FourInARow +from .connectFour import connectFour from .gameLoops import GameLoops from .hangman import Hangman from .hex import HexGame @@ -10,10 +10,10 @@ class Games(): def __init__(self, bot): self.bot = bot - bot.invest = Invest(bot) - bot.trivia = Trivia(bot) - bot.blackjack = Blackjack(bot) - bot.fourInARow = FourInARow(bot) - bot.gameLoops = GameLoops(bot) - bot.hangman = Hangman(bot) - bot.hex = HexGame(bot) + self.invest = Invest(bot) + self.trivia = Trivia(bot) + self.blackjack = Blackjack(bot) + self.connectFour = connectFour(bot) + self.gameLoops = GameLoops(bot) + self.hangman = Hangman(bot) + self.hex = HexGame(bot) diff --git a/funcs/games/hangman.py b/funcs/games/hangman.py index a116b3e..dcd50df 100644 --- a/funcs/games/hangman.py +++ b/funcs/games/hangman.py @@ -1,7 +1,6 @@ import json, urllib, datetime, string from .hangmanDraw import DrawHangman -from funcs import logThis apiUrl = "https://api.wordnik.com/v4/words.json/randomWords?hasDictionaryDef=true&minCorpusCount=5000&maxCorpusCount=-1&minDictionaryCount=1&maxDictionaryCount=-1&minLength=3&maxLength=11&limit=1&api_key=" @@ -19,7 +18,7 @@ class Hangman(): while "-" in word or "." in word: with urllib.request.urlopen(apiUrl+apiKey) as p: word = list(json.load(p)[0]["word"].upper()) - logThis("Found the word \""+"".join(word)+"\"") + self.bot.log("Found the word \""+"".join(word)+"\"") guessed = [False] * len(word) gameID = datetime.datetime.now().strftime('%Y%m%d%H%M%S') newGame = {"_id":channel,"player" : user,"guessed letters" : [],"word" : word,"game ID" : gameID,"misses" : 0,"guessed" : guessed} @@ -30,8 +29,8 @@ class Hangman(): try: self.draw.drawImage(channel) except: - logThis("Error drawing image (error code 1710)") - return f"{self.bot.funcs.getName(user)} started game of hangman.", True, False, remainingLetters + self.bot.log("Error drawing image (error code 1710)") + return f"{self.bot.databaseFuncs.getName(user)} started game of hangman.", True, False, remainingLetters else: return "There's already a Hangman game going on in the channel", False, False, [] @@ -74,7 +73,7 @@ class Hangman(): try: self.draw.drawImage(channel) except: - logThis("Error drawing image (error code 1710)") + self.bot.log("Error drawing image (error code 1710)") if game["misses"] == 6: self.hangmanStop(channel) @@ -99,7 +98,7 @@ class Hangman(): try: return self.hangmanStart(channel,user) except: - logThis("Error starting game (error code 1730)") + self.bot.log("Error starting game (error code 1730)") elif command == "stop": return self.hangmanStop(channel) elif command.startswith("guess "): @@ -107,6 +106,6 @@ class Hangman(): try: return self.hangmanGuess(channel,user,guess) except: - logThis("Error in guessing (Error Code 1720)") + self.bot.log("Error in guessing (Error Code 1720)") else: return "I didn't understand that", False, False, [] diff --git a/funcs/games/hangmanDraw.py b/funcs/games/hangmanDraw.py index 4019e85..c955fee 100644 --- a/funcs/games/hangmanDraw.py +++ b/funcs/games/hangmanDraw.py @@ -1,7 +1,6 @@ import math, random from PIL import ImageDraw, Image, ImageFont -from funcs import logThis circleDegrees = 360 circleSize = 120 @@ -23,8 +22,8 @@ letterLineDistance = 30 gallowx, gallowy = 360,600 goldenRatio = 1-(1 / ((1 + 5 ** 0.5) / 2)) -fnt = ImageFont.truetype('resources/comic-sans-bold.ttf', letterSize) -smolfnt = ImageFont.truetype('resources/comic-sans-bold.ttf', textSize) +fnt = ImageFont.truetype('resources/fonts/comic-sans-bold.ttf', letterSize) +smolfnt = ImageFont.truetype('resources/fonts/comic-sans-bold.ttf', textSize) backgroundColor = (255,255,255,255) @@ -213,7 +212,7 @@ class DrawHangman(): return background def drawImage(self,channel): - logThis("Drawing hangman image",channel) + self.bot.log("Drawing hangman image", channel) game = self.bot.database["hangman games"].find_one({"_id":channel}) random.seed(game["game ID"]) @@ -222,24 +221,24 @@ class DrawHangman(): try: gallow = self.drawGallows() except: - logThis("Error drawing gallows (error code 1711)") + self.bot.log("Error drawing gallows (error code 1711)") try: man = self.drawMan(game["misses"]) except: - logThis("Error drawing stick figure (error code 1712)") + self.bot.log("Error drawing stick figure (error code 1712)") random.seed(game["game ID"]) try: letterLines = self.drawLetterLines(game["word"],game["guessed"],game["misses"]) except: - logThis("error drawing letter lines (error code 1713)") + self.bot.log("error drawing letter lines (error code 1713)") random.seed(game["game ID"]) try: misses = self.drawMisses(game["guessed letters"],game["word"]) except: - logThis("Error drawing misses (error code 1714)") + self.bot.log("Error drawing misses (error code 1714)") background.paste(gallow,(100,100),gallow) background.paste(man,(300,210),man) diff --git a/funcs/games/hex.py b/funcs/games/hex.py index 4fc819c..3af263f 100644 --- a/funcs/games/hex.py +++ b/funcs/games/hex.py @@ -3,7 +3,6 @@ import copy import math from .hexDraw import DrawHex -from funcs import logThis BOARDWIDTH = 11 ALL_POSITIONS = [(i,j) for i in range(11) for j in range(11)] @@ -23,13 +22,13 @@ class HexGame(): commands = command.lower().split() game = self.bot.database["hex games"].find_one({"_id":channel}) if command == "" or command == " ": - return "I didn't get that. Use \"!hex start [opponent]\" to start a game.", False, False, False, False + return "I didn't get that. Use \"/hex start [opponent]\" to start a game.", False, False, False, False elif commands[0] == "start": # Starting a game - if len(commands) == 1: # if the commands is "!hex start", the opponent is Gwendolyn at difficulty 2 + if len(commands) == 1: # if the commands is "/hex start", the opponent is Gwendolyn at difficulty 2 commands.append("2") - logThis("Starting a hex game with hexStart(). "+str(user)+" challenged "+commands[1]) + self.bot.log("Starting a hex game with hexStart(). "+str(user)+" challenged "+commands[1]) return self.hexStart(channel,user,commands[1]) # commands[1] is the opponent # If using a command with no game, return error @@ -48,7 +47,7 @@ class HexGame(): try: return self.placeHex(channel,commands[1], user) except: - return "I didn't get that. To place a piece use \"!hex place [position]\". A valid position is e.g. \"E2\".", False, False, False, False + return "I didn't get that. To place a piece use \"/hex place [position]\". A valid position is e.g. \"E2\".", False, False, False, False # Undo elif commands[0] == "undo": @@ -60,7 +59,7 @@ class HexGame(): if user in players: opponent = (players.index(user) + 1) % 2 self.bot.database["hex games"].update_one({"_id":channel},{"$set":{"winner":opponent + 1}}) - return "{} surrendered. That means {} won! Adding 30 Gwendobucks to their account.".format(self.bot.funcs.getName(user),self.bot.funcs.getName(players[opponent])), False, False, True, False + return "{} surrendered. That means {} won! Adding 30 Gwendobucks to their account.".format(self.bot.databaseFuncs.getName(user),self.bot.databaseFuncs.getName(players[opponent])), False, False, True, False else: return "You can't surrender when you're not a player.", False, False, False, False @@ -79,7 +78,7 @@ class HexGame(): return "You can only swap as the second player after the very first move.", False, False, False, False else: - return "I didn't get that. Use \"!hex start [opponent]\" to start a game, \"!hex place [position]\" to place a piece, \"!hex undo\" to undo your last move or \"!hex stop\" to stop a current game.", False, False, False, False + return "I didn't get that. Use \"/hex start [opponent]\" to start a game, \"/hex place [position]\" to place a piece, \"/hex undo\" to undo your last move or \"/hex stop\" to stop a current game.", False, False, False, False # Starts the game def hexStart(self, channel, user, opponent): @@ -99,7 +98,7 @@ class HexGame(): int(opponent) return "That difficulty doesn't exist", False, False, False, False except: - opponent = self.bot.funcs.getID(opponent) + opponent = self.bot.databaseFuncs.getID(opponent) if opponent == None: return "I can't find that user", False, False, False, False else: @@ -123,7 +122,7 @@ class HexGame(): gwendoTurn = True if players[0] == "Gwendolyn" else False showImage = True - return "Started Hex game against "+self.bot.funcs.getName(opponent)+ diffText+". It's "+self.bot.funcs.getName(players[0])+"'s turn", showImage, False, False, gwendoTurn + return "Started Hex game against "+self.bot.databaseFuncs.getName(opponent)+ diffText+". It's "+self.bot.databaseFuncs.getName(players[0])+"'s turn", showImage, False, False, gwendoTurn else: return "There's already a hex game going on in this channel", False, False, False, False @@ -143,7 +142,7 @@ class HexGame(): if player == turn: board = game["board"] - logThis("Placing a piece on the board with placeHex()") + self.bot.log("Placing a piece on the board with placeHex()") # Places on board board = self.placeOnHexBoard(board,player,position) @@ -154,17 +153,17 @@ class HexGame(): self.bot.database["hex games"].update_one({"_id":channel},{"$set":{"turn":turn}}) # Checking for a win - logThis("Checking for win") + self.bot.log("Checking for win") winner = self.evaluateBoard(game["board"])[1] if winner == 0: # Continue with the game. gameWon = False - message = self.bot.funcs.getName(game["players"][player-1])+" placed at "+position.upper()+". It's now "+self.bot.funcs.getName(game["players"][turn-1])+"'s turn."# The score is "+str(score) + message = self.bot.databaseFuncs.getName(game["players"][player-1])+" placed at "+position.upper()+". It's now "+self.bot.databaseFuncs.getName(game["players"][turn-1])+"'s turn."# The score is "+str(score) else: # Congratulations! gameWon = True self.bot.database["hex games"].update_one({"_id":channel},{"$set":{"winner":winner}}) - message = self.bot.funcs.getName(game["players"][player-1])+" placed at "+position.upper()+" and won!" + message = self.bot.databaseFuncs.getName(game["players"][player-1])+" placed at "+position.upper()+" and won!" if game["players"][winner-1] != "Gwendolyn": winAmount = game["difficulty"]*10 message += " Adding "+str(winAmount)+" GwendoBucks to their account." @@ -175,7 +174,7 @@ class HexGame(): # Is it now Gwendolyn's turn? gwendoTurn = False if game["players"][turn-1] == "Gwendolyn": - logThis("It's Gwendolyn's turn") + self.bot.log("It's Gwendolyn's turn") gwendoTurn = True # Update the board @@ -188,15 +187,15 @@ class HexGame(): return message, False, False, False, False else: # Move out of turn - message = "It isn't your turn, it is "+self.bot.funcs.getName(game["players"][turn-1])+"'s turn." + message = "It isn't your turn, it is "+self.bot.databaseFuncs.getName(game["players"][turn-1])+"'s turn." return message, False, False, False, False else: - message = "You can't place when you're not in the game. The game's players are: "+self.bot.funcs.getName(game["players"][0])+" and "+self.bot.funcs.getName(game["players"][1])+"." + message = "You can't place when you're not in the game. The game's players are: "+self.bot.databaseFuncs.getName(game["players"][0])+" and "+self.bot.databaseFuncs.getName(game["players"][1])+"." return message, False, False, False, False else: return "There's no game in this channel", False, False, False, False - # Returns a board where the placement has occured + # Returns a board where the placement has ocurred def placeOnHexBoard(self, board,player,position): # Translates the position position = position.lower() @@ -205,17 +204,17 @@ class HexGame(): column = ord(position[0]) - 97 # ord() translates from letter to number row = int(position[1:]) - 1 if column not in range(BOARDWIDTH) or row not in range(BOARDWIDTH): - logThis("Position out of bounds (error code 1533)") + self.bot.log("Position out of bounds (error code 1533)") return "Error. That position is out of bounds." except: - logThis("Invalid position (error code 1531)") + self.bot.log("Invalid position (error code 1531)") return "Error. The position should be a letter followed by a number, e.g. \"e2\"." # Place at the position if board[row][column] == 0: board[row][column] = player return board else: - logThis("Cannot place on existing piece (error code 1532)") + self.bot.log("Cannot place on existing piece (error code 1532)") return "Error. You must place on an empty space." # After your move, you have the option to undo get your turn back #TimeTravel @@ -227,7 +226,7 @@ class HexGame(): turn = game["turn"] # You can only undo after your turn, which is the opponent's turn. if user == game["players"][(turn % 2)]: # If it's not your turn - logThis("Undoing {}'s last move".format(self.bot.funcs.getName(user))) + self.bot.log("Undoing {}'s last move".format(self.bot.databaseFuncs.getName(user))) lastMove = game["gameHistory"].pop() game["board"][lastMove[0]][lastMove[1]] = 0 @@ -252,7 +251,7 @@ class HexGame(): # Plays as the AI def hexAI(self, channel): - logThis("Figuring out best move") + self.bot.log("Figuring out best move") game = self.bot.database["hex games"].find_one({"_id":channel}) board = game["board"] @@ -286,7 +285,7 @@ class HexGame(): if evaluateBoard(testBoard)[0] != current_score: # only think about a move if it improves the score (it's impossible to get worse) # Testing a move and evaluating it judgements[i] = minimaxHex(testBoard,difficulty,-math.inf,math.inf,GwenColor==2) - logThis("Best score for place {} is {}".format((i // BOARDWIDTH,i % BOARDWIDTH),judgements[i])) + self.bot.log("Best score for place {} is {}".format((i // BOARDWIDTH,i % BOARDWIDTH),judgements[i])) bestScore = max(judgements) if (GwenColor == 1) else min(judgements) # this line has an error indices = [i for i, x in enumerate(judgements) if x == bestScore] # which moves got that score? @@ -294,7 +293,7 @@ class HexGame(): chosenMove = (i // BOARDWIDTH , i % BOARDWIDTH) """ placement = "abcdefghijk"[chosenMove[1]]+str(chosenMove[0]+1) - logThis("ChosenMove is {} at {}".format(chosenMove,placement)) + self.bot.log("ChosenMove is {} at {}".format(chosenMove,placement)) return self.placeHex(channel,placement, "Gwendolyn") @@ -323,12 +322,12 @@ class HexGame(): Distance[v] = min(Distance[v], new_dist) # After a hex has been visited, this is noted visited.add(u) - #logThis("Distance from player {}'s start to {} is {}".format(player,u,Distance[u])) + #self.bot.log("Distance from player {}'s start to {} is {}".format(player,u,Distance[u])) if u[player-1] == 10: # if the right coordinate of v is 10, it means we're at the goal scores[player] = Distance[u] # A player's score is the shortest distance to goal. Which equals the number of remaining moves they need to win if unblocked by the opponent. break else: - logThis("For some reason, no path to the goal was found. ") + self.bot.log("For some reason, no path to the goal was found. ") if scores[player] == 0: winner = player break # We don't need to check the other player's score, if player1 won. @@ -344,7 +343,7 @@ class HexGame(): if maximizingPlayer: # red player predicts next move maxEval = -math.inf possiblePlaces = [i for i,v in enumerate(sum(board,[])) if v == 0] - #logThis("Judging a red move at depth {}".format(depth)) + #self.bot.log("Judging a red move at depth {}".format(depth)) for i in possiblePlaces: testBoard = copy.deepcopy(board) testBoard[i // BOARDWIDTH][i % BOARDWIDTH] = 1 # because maximizingPlayer is Red which is number 1 @@ -352,13 +351,13 @@ class HexGame(): maxEval = max(maxEval, evaluation) alpha = max(alpha, evaluation) if beta <= alpha: - #logThis("Just pruned something!") + #self.bot.log("Just pruned something!") break return maxEval else: # blue player predicts next move minEval = math.inf possiblePlaces = [i for i,v in enumerate(sum(board,[])) if v == 0] - #logThis("Judging a blue move at depth {}".format(depth)) + #self.bot.log("Judging a blue move at depth {}".format(depth)) for i in possiblePlaces: testBoard = copy.deepcopy(board) testBoard[i // BOARDWIDTH][i % BOARDWIDTH] = 2 # because minimizingPlayer is Blue which is number 2 @@ -366,7 +365,7 @@ class HexGame(): minEval = min(minEval, evaluation) beta = min(beta, evaluation) if beta <= alpha: - #logThis("Just pruned something!") + #self.bot.log("Just pruned something!") break return minEval diff --git a/funcs/games/hexDraw.py b/funcs/games/hexDraw.py index 0966102..44a064c 100644 --- a/funcs/games/hexDraw.py +++ b/funcs/games/hexDraw.py @@ -1,7 +1,6 @@ import math from PIL import Image, ImageDraw, ImageFont -from funcs import logThis # Defining all the variables CANVAS_WIDTH = 2400 @@ -13,7 +12,7 @@ HEXAGONWIDTH = math.sqrt(3) * SIDELENGTH # the whole width of one hexagon HEXAGONHEIGHT = 1.5 * SIDELENGTH # not really the entire height, but the height difference between two layers FONTSIZE = 45 TEXTCOLOR = (0,0,0) -fnt = ImageFont.truetype('resources/futura-bold.ttf', FONTSIZE) +fnt = ImageFont.truetype('resources/fonts/futura-bold.ttf', FONTSIZE) LINETHICKNESS = 15 HEXTHICKNESS = 6 # This is half the width of the background lining between every hex @@ -29,7 +28,7 @@ COLX_THICKNESS = COLHEXTHICKNESS * math.cos(math.pi/6) COLY_THICKNESS = COLHEXTHICKNESS * math.sin(math.pi/6) # The Name display things: NAMESIZE = 60 -NAME_fnt = ImageFont.truetype('resources/futura-bold.ttf', NAMESIZE) +NAME_fnt = ImageFont.truetype('resources/fonts/futura-bold.ttf', NAMESIZE) X_NAME = {1:175, 2:CANVAS_WIDTH-100} Y_NAME = {1:CANVAS_HEIGHT-150, 2:150} NAMEHEXPADDING = 90 @@ -41,7 +40,7 @@ class DrawHex(): self.bot = bot def drawBoard(self, channel): - logThis("Drawing empty Hex board") + self.bot.log("Drawing empty Hex board") # Creates the empty image im = Image.new('RGB', size=(CANVAS_WIDTH, CANVAS_HEIGHT),color = BACKGROUND_COLOR) @@ -99,7 +98,7 @@ class DrawHex(): game = self.bot.database["hex games"].find_one({"_id":channel}) for p in [1,2]: - playername = self.bot.funcs.getName(game["players"][p-1]) + playername = self.bot.databaseFuncs.getName(game["players"][p-1]) # Draw name x = X_NAME[p] x -= NAME_fnt.getsize(playername)[0] if p==2 else 0 # player2's name is right-aligned @@ -123,7 +122,7 @@ class DrawHex(): def drawHexPlacement(self, channel,player,position): FILEPATH = "resources/games/hexBoards/board"+channel+".png" - logThis("Drawing a newly placed hex. Filepath: "+FILEPATH) + self.bot.log("Drawing a newly placed hex. Filepath: "+FILEPATH) # Translates position # We don't need to error-check, because the position is already checked in placeOnHexBoard() @@ -151,7 +150,7 @@ class DrawHex(): # Save im.save(FILEPATH) except: - logThis("Error drawing new hex on board (error code 1541") + self.bot.log("Error drawing new hex on board (error code 1541") def drawSwap(self, channel): FILEPATH = "resources/games/hexBoards/board"+channel+".png" @@ -163,7 +162,7 @@ class DrawHex(): # Write player names and color for p in [1,2]: - playername = self.bot.funcs.getName(game["players"][p%2]) + playername = self.bot.databaseFuncs.getName(game["players"][p%2]) x = X_NAME[p] x -= NAME_fnt.getsize(playername)[0] if p==2 else 0 # player2's name is right-aligned @@ -183,4 +182,4 @@ class DrawHex(): # Save im.save(FILEPATH) except: - logThis("Error drawing swap (error code 1542)") + self.bot.log("Error drawing swap (error code 1542)") diff --git a/funcs/games/invest.py b/funcs/games/invest.py index f955032..04a80dc 100644 --- a/funcs/games/invest.py +++ b/funcs/games/invest.py @@ -1,5 +1,5 @@ class Invest(): - def __init__(self,bot): + def __init__(self, bot): self.bot = bot def getPrice(self, symbol : str): @@ -13,9 +13,9 @@ class Invest(): userInvestments = self.bot.database["investments"].find_one({"_id":user}) if userInvestments in [None,{}]: - return f"{self.bot.funcs.getName(user)} does not have a stock portfolio." + return f"{self.bot.databaseFuncs.getName(user)} does not have a stock portfolio." else: - portfolio = f"**Stock portfolio for {self.bot.funcs.getName(user)}**" + portfolio = f"**Stock portfolio for {self.bot.databaseFuncs.getName(user)}**" for key, value in list(userInvestments["investments"].items()): purchaseValue = value["purchased for"] @@ -60,7 +60,7 @@ class Invest(): newUser = {"_id":user,"investments":{stock : {"purchased" : buyAmount, "value at purchase" : stockPrice, "purchased for" : buyAmount}}} self.bot.database["investments"].insert_one(newUser) - return f"{self.bot.funcs.getName(user)} bought {buyAmount} GwendoBucks worth of {stock} stock" + return f"{self.bot.databaseFuncs.getName(user)} bought {buyAmount} GwendoBucks worth of {stock} stock" else: return f"{stock} is not traded on the american market." else: @@ -95,7 +95,7 @@ class Invest(): self.bot.database["investments"].update_one({"_id":user}, {"$unset":{"investments."+stock:""}}) - return f"{self.bot.funcs.getName(user)} sold {sellAmount} GwendoBucks worth of {stock} stock" + return f"{self.bot.databaseFuncs.getName(user)} sold {sellAmount} GwendoBucks worth of {stock} stock" else: return f"You don't have enough {stock} stocks to do that" else: @@ -122,7 +122,7 @@ class Invest(): #try: return self.buyStock(user,commands[1],int(commands[2])) #except: - # return "The command must be given as \"!invest buy [stock] [amount of GwendoBucks to purchase with]\"" + # return "The command must be given as \"/invest buy [stock] [amount of GwendoBucks to purchase with]\"" else: return "You must give both a stock name and an amount of gwendobucks you wish to spend." @@ -132,6 +132,6 @@ class Invest(): try: return self.sellStock(user,commands[1],int(commands[2])) except: - return "The command must be given as \"!invest sell [stock] [amount of GwendoBucks to sell stocks for]\"" + return "The command must be given as \"/invest sell [stock] [amount of GwendoBucks to sell stocks for]\"" else: return "You must give both a stock name and an amount of GwendoBucks you wish to sell stocks for." diff --git a/funcs/games/money.py b/funcs/games/money.py index ca5b030..f4d28e3 100644 --- a/funcs/games/money.py +++ b/funcs/games/money.py @@ -1,5 +1,3 @@ -from funcs import logThis - class Money(): def __init__(self, bot): @@ -8,7 +6,7 @@ class Money(): # Returns the account balance for a user def checkBalance(self, user): - logThis("checking "+user+"'s account balance") + self.bot.log("checking "+user+"'s account balance") userData = self.database["users"].find_one({"_id":user}) @@ -18,19 +16,19 @@ class Money(): # Adds money to the account of a user def addMoney(self,user,amount): - logThis("adding "+str(amount)+" to "+user+"'s account") + self.bot.log("adding "+str(amount)+" to "+user+"'s account") userData = self.database["users"].find_one({"_id":user}) if userData != None: self.database["users"].update_one({"_id":user},{"$inc":{"money":amount}}) else: - self.database["users"].insert_one({"_id":user,"user name":self.bot.funcs.getName(user),"money":amount}) + self.database["users"].insert_one({"_id":user,"user name":self.bot.databaseFuncs.getName(user),"money":amount}) # Transfers money from one user to another def giveMoney(self,user,targetUser,amount): userData = self.database["users"].find_one({"_id":user}) - targetUser = self.bot.funcs.getID(targetUser) + targetUser = self.bot.databaseFuncs.getID(targetUser) if amount > 0: if targetUser != None: @@ -38,16 +36,16 @@ class Money(): if userData["money"] >= amount: self.addMoney(user,-1 * amount) self.addMoney(targetUser,amount) - return "Transferred "+str(amount)+" GwendoBucks to "+self.bot.funcs.getName(targetUser) + return "Transferred "+str(amount)+" GwendoBucks to "+self.bot.databaseFuncs.getName(targetUser) else: - logThis("They didn't have enough GwendoBucks (error code 1223b)") + self.bot.log("They didn't have enough GwendoBucks (error code 1223b)") return "You don't have that many GwendoBucks (error code 1223b)" else: - logThis("They didn't have enough GwendoBucks (error code 1223a)") + self.bot.log("They didn't have enough GwendoBucks (error code 1223a)") return "You don't have that many GwendoBucks (error code 1223a)" else: - logThis("They weren't in the system") + self.bot.log("They weren't in the system") return "The target doesn't exist" else: - logThis("They tried to steal") + self.bot.log("They tried to steal") return "Yeah, no. You can't do that" diff --git a/funcs/games/trivia.py b/funcs/games/trivia.py index 8638ad6..3b75cdf 100644 --- a/funcs/games/trivia.py +++ b/funcs/games/trivia.py @@ -2,8 +2,6 @@ import json import urllib import random -from funcs import logThis - class Trivia(): def __init__(self, bot): self.bot = bot @@ -13,13 +11,13 @@ class Trivia(): def triviaStart(self, channel : str): question = self.bot.database["trivia questions"].find_one({"_id":channel}) - logThis("Trying to find a trivia question for "+channel) + self.bot.log("Trying to find a trivia question for "+channel) if question == None: with urllib.request.urlopen("https://opentdb.com/api.php?amount=10&type=multiple") as response: data = json.loads(response.read()) - logThis("Found the question \""+data["results"][0]["question"]+"\"") + self.bot.log("Found the question \""+data["results"][0]["question"]+"\"") answers = data["results"][0]["incorrect_answers"] answers.append(data["results"][0]["correct_answer"]) random.shuffle(answers) @@ -43,7 +41,7 @@ class Trivia(): return question, answers, correctAnswer else: - logThis("There was already a trivia question for that channel (error code 1106)") + self.bot.log("There was already a trivia question for that channel (error code 1106)") return "There's already a trivia question going on. Try again in like, a minute (error code 1106)", "", "" # Lets players answer a trivia question @@ -53,19 +51,19 @@ class Trivia(): if command in ["a","b","c","d"]: if question != None: if user not in question["players"]: - logThis(user+" answered the question in "+channel) + self.bot.log(user+" answered the question in "+channel) self.bot.database["trivia questions"].update_one({"_id":channel},{"$set":{"players."+user : command}}) return "Locked in "+user+"'s answer" else: - logThis(user+" has already answered this question (error code 1105)") + self.bot.log(user+" has already answered this question (error code 1105)") return user+" has already answered this question (error code 1105)" else: - logThis("There's no question right now (error code 1104)") + self.bot.log("There's no question right now (error code 1104)") return "There's no question right now (error code 1104)" else: - logThis("I didn't quite understand that (error code 1103)") + self.bot.log("I didn't quite understand that (error code 1103)") return "I didn't quite understand that (error code 1103)" @@ -73,7 +71,7 @@ class Trivia(): def triviaCountPoints(self, channel : str): question = self.bot.database["trivia questions"].find_one({"_id":channel}) - logThis("Counting points for question in "+channel) + self.bot.log("Counting points for question in "+channel) if question != None: for player, answer in question["players"].items(): @@ -82,6 +80,6 @@ class Trivia(): else: - logThis("Couldn't find the question (error code 1102)") + self.bot.log("Couldn't find the question (error code 1102)") return None diff --git a/funcs/lookup/__init__.py b/funcs/lookup/__init__.py index 7b46bbf..2216bf2 100644 --- a/funcs/lookup/__init__.py +++ b/funcs/lookup/__init__.py @@ -1,5 +1,5 @@ """Gwendolyn functions for looking things up.""" -__all__ = ["spellFunc", "monsterFunc"] +__all__ = ["LookupFuncs"] -from .lookupFuncs import spellFunc, monsterFunc \ No newline at end of file +from .lookupFuncs import LookupFuncs \ No newline at end of file diff --git a/funcs/lookup/lookupFuncs.py b/funcs/lookup/lookupFuncs.py index 27f99ac..3cfe9aa 100644 --- a/funcs/lookup/lookupFuncs.py +++ b/funcs/lookup/lookupFuncs.py @@ -1,136 +1,139 @@ import math -#import discord import json -from funcs import cap, logThis +from utils import cap -# Calculates D&D stat modifier -def modifier(statistic): - mods = math.floor((statistic-10)/2) - if mods >= 0: - mods = "+"+str(mods) - return(str(mods)) -saves = ["strength_save","dexterity_save","constitution_save","intelligence_save","wisdom_save","charisma_save"] -abilities = ["acrobatics","animal_handling","arcana","athletics","deception","history","insight","intimidation","investigation","medicine","nature","perception","performance","persuasion","religion","sleight_of_hand","stealth","survival"] +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"] -# Looks up a monster -def monsterFunc(command): - logThis("Looking up "+command) + # Calculates D&D stat modifier + def modifier(self, statistic): + mods = math.floor((statistic-10)/2) + if mods >= 0: + mods = "+"+str(mods) + return(str(mods)) - # 1-letter monsters don't exist - if len(command) < 2: - logThis("Monster name too short (error code 601)") - return("I don't know that monster... (error code 601)","","","","","") - else: - # Opens "mensters.json" - data = json.load(open('resources/lookup/monsters.json', encoding = "utf8")) - for monster in data: - if "name" in monster and str(command) == monster["name"]: - logThis("Found it!") + # Looks up a monster + def monsterFunc(self, command): + self.bot.log("Looking up "+command) - # Looks at the information about the monster and returns that information - # in seperate variables, allowing Gwendolyn to know where to seperate - # the messages - if monster["subtype"] != "": - typs = (monster["type"]+" ("+monster["subtype"]+")") - else: - typs = monster["type"] - con_mod = math.floor((monster["constitution"]-10)/2) - hit_dice = monster["hit_dice"] + # 1-letter monsters don't exist + if len(command) < 2: + self.bot.log("Monster name too short (error code 601)") + return("I don't know that monster... (error code 601)","","","","","") + else: + # Opens "monsters.json" + data = json.load(open('resources/lookup/monsters.json', encoding = "utf8")) + for monster in data: + if "name" in monster and str(command) == monster["name"]: + self.bot.log("Found it!") - stats = ("**Str:** "+str(monster["strength"])+" ("+modifier(monster["strength"])+")\t**Dex:** "+str(monster["dexterity"])+" ("+modifier(monster["dexterity"])+")\t**Con:** "+str(monster["constitution"])+" ("+modifier(monster["constitution"])+")\n**Int: **"+str(monster["intelligence"])+" ("+modifier(monster["intelligence"])+")\t**Wis: **"+str(monster["wisdom"])+" ("+modifier(monster["wisdom"])+")\t**Cha: **"+str(monster["charisma"])+" ("+modifier(monster["charisma"])+")") + # Looks at the information about the monster and returns that information + # in separate variables, allowing Gwendolyn to know where to separate + # the messages + if monster["subtype"] != "": + typs = (monster["type"]+" ("+monster["subtype"]+")") + else: + typs = monster["type"] + con_mod = math.floor((monster["constitution"]-10)/2) + hit_dice = monster["hit_dice"] - saving_throws = "" - for save in saves: - if save in monster: - if monster[save] >= 0: - saving_throws += " "+cap(save[:3])+" +"+str(monster[save])+"," - else: - saving_throws += " "+cap(save[:3])+" "+str(monster[save])+"," - if saving_throws != "": - saving_throws = "\n**Saving Throws**"+saving_throws[:-1] + stats = ("**Str:** "+str(monster["strength"])+" ("+self.modifier(monster["strength"])+")\t**Dex:** "+str(monster["dexterity"])+" ("+self.modifier(monster["dexterity"])+")\t**Con:** "+str(monster["constitution"])+" ("+self.modifier(monster["constitution"])+")\n**Int: **"+str(monster["intelligence"])+" ("+self.modifier(monster["intelligence"])+")\t**Wis: **"+str(monster["wisdom"])+" ("+self.modifier(monster["wisdom"])+")\t**Cha: **"+str(monster["charisma"])+" ("+self.modifier(monster["charisma"])+")") - skills = "" - for skill in abilities: - if skill in monster: - if monster[skill] >= 0: - skills += " "+cap(skill.replace("_"," "))+" +"+str(monster[skill])+"," - else: - skills += " "+cap(skill.replace("_"," "))+" "+str(monster[skill])+"," - if skills != "": - skills = "\n**Skills**"+skills[:-1] + saving_throws = "" + for save in self.saves: + if save in monster: + if monster[save] >= 0: + saving_throws += " "+cap(save[:3])+" +"+str(monster[save])+"," + else: + saving_throws += " "+cap(save[:3])+" "+str(monster[save])+"," + if saving_throws != "": + saving_throws = "\n**Saving Throws**"+saving_throws[:-1] - vulnerabilities = monster["damage_vulnerabilities"] - if vulnerabilities != "": - vulnerabilities = "\n**Damage Vulnerabilities** "+vulnerabilities + skills = "" + for skill in self.abilities: + if skill in monster: + if monster[skill] >= 0: + skills += " "+cap(skill.replace("_"," "))+" +"+str(monster[skill])+"," + else: + skills += " "+cap(skill.replace("_"," "))+" "+str(monster[skill])+"," + if skills != "": + skills = "\n**Skills**"+skills[:-1] - 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 - spec_ab = "" - if "special_abilities" in monster: - for ability in monster["special_abilities"]: - spec_ab += "\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"] + spec_ab = "" + if "special_abilities" in monster: + for ability in monster["special_abilities"]: + spec_ab += "\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"] - leg_act = "" - if "legendary_actions" in monster: - for action in monster["legendary_actions"]: - leg_act += "\n\n***"+action["name"]+".*** "+action["desc"] + react = "" + if "reactions" in monster: + for reaction in monster["reactions"]: + react += "\n\n***"+reaction["name"]+".*** "+reaction["desc"] - if con_mod < 0: - hit_dice += (" - "+str(con_mod * int(monster["hit_dice"].replace("d"," ").split()[0])*(-1))) - if con_mod > 0: - hit_dice += (" + "+str(con_mod * int(monster["hit_dice"].replace("d"," ").split()[0]))) + leg_act = "" + if "legendary_actions" in monster: + for action in monster["legendary_actions"]: + leg_act += "\n\n***"+action["name"]+".*** "+action["desc"] - new_part = "\n--------------------" + if con_mod < 0: + hit_dice += (" - "+str(con_mod * int(monster["hit_dice"].replace("d"," ").split()[0])*(-1))) + if con_mod > 0: + hit_dice += (" + "+str(con_mod * int(monster["hit_dice"].replace("d"," ").split()[0]))) - monster_type = monster["size"]+" "+typs+", "+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 = monster["size"]+" "+typs+", "+monster["alignment"]+"*" - text1 = (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" - text2 = (spec_ab) - text3 = (act) - text4 = (react) - text5 = (leg_act) + text1 = (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"]) - logThis("Returning monster information") - return(str(command),text1,text2,text3,text4,text5) - logThis("Monster not in database (error code 602)") - return("I don't know that monster... (error code 602)","","","","","") + text2 = (spec_ab) + text3 = (act) + text4 = (react) + text5 = (leg_act) -# Looks up a spell -def spellFunc(command): - logThis("Looking up "+command) + self.bot.log("Returning monster information") + return(str(command),text1,text2,text3,text4,text5) + self.bot.log("Monster not in database (error code 602)") + return("I don't know that monster... (error code 602)","","","","","") - # Opens "spells.json" - data = json.load(open('resources/lookup/spells.json', encoding = "utf8")) - if str(command) in data: - logThis("Returning spell information") - spell_output = ("***"+str(command)+"***\n*"+str(data[str(command)]["level"])+" level "+str(data[str(command)]["school"])+"\nCasting Time: "+str(data[str(command)]["casting_time"])+"\nRange: "+str(data[str(command)]["range"])+"\nComponents: "+str(data[str(command)]["components"])+"\nDuration: "+str(data[str(command)]["duration"])+"*\n \n"+str(data[str(command)]["description"])) - else: - logThis("I don't know that spell (error code 501)") - spell_output = "I don't think that's a spell (error code 501)" - logThis("Successfully ran !spell") - return(spell_output) + # Looks up a spell + def spellFunc(self, command): + self.bot.log("Looking up "+command) + + # Opens "spells.json" + data = json.load(open('resources/lookup/spells.json', encoding = "utf8")) + if str(command) in data: + self.bot.log("Returning spell information") + spell_output = ("***"+str(command)+"***\n*"+str(data[str(command)]["level"])+" level "+str(data[str(command)]["school"])+"\nCasting Time: "+str(data[str(command)]["casting_time"])+"\nRange: "+str(data[str(command)]["range"])+"\nComponents: "+str(data[str(command)]["components"])+"\nDuration: "+str(data[str(command)]["duration"])+"*\n \n"+str(data[str(command)]["description"])) + else: + self.bot.log("I don't know that spell (error code 501)") + spell_output = "I don't think that's a spell (error code 501)" + self.bot.log("Successfully ran /spell") + return(spell_output) diff --git a/funcs/miscFuncs.py b/funcs/miscFuncs.py deleted file mode 100644 index d7d7fae..0000000 --- a/funcs/miscFuncs.py +++ /dev/null @@ -1,222 +0,0 @@ -from typing import Union -import lxml.etree # Used by imageFunc -import datetime # Used by helloFunc -import json # Used by spellFunc -import random # Used by imageFunc -import urllib # Used by imageFunc -import time # Used for logging -import logging # Used for... you know... logging -import wikia # Used by findWikiPage -import os # Used by makeFiles - -logging.basicConfig(filename="gwendolyn.log", level=logging.INFO) - -# Capitalizes all words except some of them -no_caps_list = ["of","the"] -def cap(s): - # Capitalizes a strink like a movie title - word_number = 0 - lst = s.split() - res = '' - for word in lst: - word_number += 1 - if word not in no_caps_list or word_number == 1: - word = word.capitalize() - res += word+" " - res = res[:-1] - return res - -def time_in_range(start, end, x): - # Return true if x is in the range [start, end] - if start <= end: - return start <= x <= end - else: - return start <= x or x <= end - -# Responds with a greeting of a time-appropriate maner -def helloFunc(author): - 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): - return("Good morning, "+str(author)) - elif time_in_range(now.replace(hour=10, minute=0, second=0, microsecond=0),now.replace(hour=13, minute=0, second=0, microsecond=0), now): - return("Good day, "+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): - return("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): - return("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): - return("Good night, "+str(author)) - else: - return("Why hello, "+str(author)) - -# Finds a random picture online -def imageFunc(): - # Picks a type of camera, which decides the naming scheme - try: - cams = ("one","two","three","four") - cam = random.choice(cams) - logThis("Chose cam type "+cam) - if cam == "one": - a = str(random.randint(0 ,9)) - b = str(random.randint(0,9)) - c = str(random.randint(0,9)) - d = str(random.randint(0,9)) - search = ("img_"+a+b+c+d) - elif cam == "two": - a = str(random.randint(2012,2016)) - b = str(random.randint(1,12)).zfill(2) - c = str(random.randint(1,29)).zfill(2) - search = ("IMG_"+a+b+c) - elif cam == "three": - a = str(random.randint(1,500)).zfill(4) - search = ("IMAG_"+a) - elif cam == "four": - a = str(random.randint(0,9)) - b = str(random.randint(0,9)) - c = str(random.randint(0,9)) - d = str(random.randint(0,9)) - search = ("DSC_"+a+b+c+d) - except: - logThis("error picking camera type (error code 702)") - - logThis("Searching for "+search) - - # Searches for the image and reads the resulting web page - try: - 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 = "thumb"]/@href') - - # Picks an image - number = random.randint(1,len(images))-1 - image = images[number] - - logThis("Picked image number "+str(number)) - - # Returns the image - logThis("Successfully returned an image") - except: - image = "Couldn't connect to bing (error code 701)" - logThis("Couldn't connect to bing (error code 701)") - return(image) - -def logThis(messages : Union[str, list], channel = "", level = 20): - localtime = time.asctime(time.localtime(time.time())) - channel = channel.replace("Direct Message with ","") - if type(messages) is str: - messages = [messages] - - for x, msg in enumerate(messages): - if channel == "": - messages[x] = localtime+" - "+msg - else: - messages[x] = localtime+" ("+channel+") - "+msg - - if len(messages) > 1: - messages[0] += " (details in log)" - - if level != 10: - print(messages[0]) - - for logMessage in messages: - logging.log(level, logMessage) - -# Finds a page from the Senkulpa Wikia -def findWikiPage(search : str): - logThis("Trying to find wiki page for "+search) - wikia.set_lang("da") - searchResults = wikia.search("senkulpa",search) - if len(searchResults) > 0: - try: - searchResult = searchResults[0].replace(",","%2C") - logThis("Found page \""+searchResult+"\"") - page = wikia.page("senkulpa",searchResult) - content = page.content.replace(u'\xa0', u' ').split("\n")[0] - - images = page.images - if len(images) > 0: - image = images[len(images)-1]+"/revision/latest?path-prefix=da" - return page.title, content, image - else: - return page.title, content, "" - except: - logThis("Fucked up (error code 1001)") - return "", "Sorry. Fucked that one up (error code 1001)", "" - else: - logThis("Couldn't find the page (error code 1002)") - return "", "Couldn't find page (error code 1002)", "" - -def makeJsonFile(path,content): - # Creates json file if it doesn't exist - try: - f = open(path,"r") - except: - logThis(path.split("/")[-1]+" didn't exist. Making it now.") - with open(path,"w") as f: - json.dump(content,f,indent = 4) - finally: - f.close() - -def makeTxtFile(path,content): - # Creates txt file if it doesn't exist - try: - f = open(path,"r") - except: - logThis(path.split("/")[-1]+" didn't exist. Making it now.") - with open(path,"w") as f: - f.write(content) - finally: - f.close() - -def makeFolder(path): - if os.path.isdir(path) == False: - os.makedirs(path) - logThis("The "+path.split("/")[-1]+" directory didn't exist") - -def makeFiles(): - with open("resources/startingFiles.json") as f: - data = json.load(f) - - for path, content in data["json"].items(): - makeJsonFile(path,content) - - for path, content in data["txt"].items(): - makeTxtFile(path,content) - - for path in data["folder"]: - makeFolder(path) - -# Replaces multiple things with the same thing -def replaceMultiple(mainString, toBeReplaces, newString): - # Iterate over the strings to be replaced - for elem in toBeReplaces : - # Check if string is in the main string - if elem in mainString : - # Replace the string - mainString = mainString.replace(elem, newString) - - return mainString - -def emojiToCommand(emoji): - if emoji == "1️⃣": - return 1 - elif emoji == "2️⃣": - return 2 - elif emoji == "3️⃣": - return 3 - elif emoji == "4️⃣": - return 4 - elif emoji == "5️⃣": - return 5 - elif emoji == "6️⃣": - return 6 - elif emoji == "7️⃣": - return 7 - elif emoji == "🎲": - return "roll" - elif emoji == "❌": - return "none" - elif emoji == "✔️": - return 1 - else: return "" diff --git a/funcs/other/__init__.py b/funcs/other/__init__.py index 3d936c6..8612103 100644 --- a/funcs/other/__init__.py +++ b/funcs/other/__init__.py @@ -1,8 +1,5 @@ """Misc. functions for Gwendolyn.""" -__all__ = ["Generators", "movieFunc","BedreNetflix","NerdShit"] +__all__ = ["Other"] -from .bedreNetflix import BedreNetflix -from .generators import Generators -from .movie import movieFunc -from .nerdShit import NerdShit \ No newline at end of file +from .other import Other \ No newline at end of file diff --git a/funcs/other/bedreNetflix.py b/funcs/other/bedreNetflix.py index ac13937..7c98520 100644 --- a/funcs/other/bedreNetflix.py +++ b/funcs/other/bedreNetflix.py @@ -1,5 +1,4 @@ import requests, imdb, discord, json, math, time, asyncio -from funcs import logThis class BedreNetflix(): def __init__(self,bot): @@ -14,7 +13,7 @@ class BedreNetflix(): #Returns a list of no more than 5 options when user requests a movie async def requestMovie(self, ctx, movieName): - logThis("Searching for "+movieName) + self.bot.log("Searching for "+movieName) movieList = imdb.IMDb().search_movie(movieName) movies = [] for movie in movieList: @@ -41,7 +40,7 @@ class BedreNetflix(): messageText += "Error" imdbIds.append(movie.movieID) - logThis("Returning a list of "+str(len(movies))+" possible movies: "+str(imdbIds)) + self.bot.log("Returning a list of "+str(len(movies))+" possible movies: "+str(imdbIds)) em = discord.Embed(title=messageTitle,description=messageText,colour=0x00FF00) @@ -63,10 +62,10 @@ class BedreNetflix(): #Adds the requested movie to Bedre Netflix async def addMovie(self,channel,imdbId): if imdbId == None: - logThis("Did not find what the user was searching for") + self.bot.log("Did not find what the user was searching for") await channel.send("Try searching for the IMDB id") else: - logThis("Trying to add movie "+str(imdbId)) + self.bot.log("Trying to add movie "+str(imdbId)) apiKey = self.bot.credentials.radarrKey response = requests.get(self.radarrURL+"movie/lookup/imdb?imdbId=tt"+imdbId+"&apiKey="+apiKey) lookupData = response.json() @@ -81,16 +80,16 @@ class BedreNetflix(): if r.status_code == 201: await channel.send(postData["title"]+" successfully added to Bedre Netflix") - logThis("Added "+postData["title"]+" to Bedre Netflix") + self.bot.log("Added "+postData["title"]+" to Bedre Netflix") elif r.status_code == 400: - await channel.send("The movie is already requested for Bedre Netflix") + await channel.send("The movie is already requested for or added to Bedre Netflix") else: await channel.send("Something went wrong") - logThis(str(r.status_code)+" "+r.reason) + self.bot.log(str(r.status_code)+" "+r.reason) #Returns a list of no more than 5 options when user requests a show async def requestShow(self, ctx, showName): - logThis("Searching for "+showName) + self.bot.log("Searching for "+showName) movies = imdb.IMDb().search_movie(showName) #Replace with tvdb shows = [] for movie in movies: @@ -117,7 +116,7 @@ class BedreNetflix(): messageText += "Error" imdbNames.append(show["title"]) - logThis("Returning a list of "+str(len(shows))+" possible shows: "+str(imdbNames)) + self.bot.log("Returning a list of "+str(len(shows))+" possible shows: "+str(imdbNames)) em = discord.Embed(title=messageTitle,description=messageText,colour=0x00FF00) @@ -139,10 +138,10 @@ class BedreNetflix(): #Adds the requested show to Bedre Netflix async def addShow(self,channel,imdbName): if imdbName == None: - logThis("Did not find what the user was searching for") + self.bot.log("Did not find what the user was searching for") await channel.send("Try searching for the IMDB id") else: - logThis("Trying to add show "+str(imdbName)) + self.bot.log("Trying to add show "+str(imdbName)) apiKey = self.bot.credentials.sonarrKey response = requests.get(self.sonarrURL+"series/lookup?term="+imdbName.replace(" ","%20")+"&apiKey="+apiKey) lookupData = response.json()[0] @@ -157,16 +156,16 @@ class BedreNetflix(): if r.status_code == 201: await channel.send(postData["title"]+" successfully added to Bedre Netflix") - logThis("Added a "+postData["title"]+" to Bedre Netflix") + self.bot.log("Added a "+postData["title"]+" to Bedre Netflix") elif r.status_code == 400: - await channel.send("The show is already requested for Bedre Netflix") + await channel.send("The show is already requested for or added to Bedre Netflix") else: await channel.send("Something went wrong") - logThis(str(r.status_code)+" "+r.reason) + self.bot.log(str(r.status_code)+" "+r.reason) #Generates a list of all torrents and returns formatted list and whether all torrents are downloaded async def genDownloadList(self, showDM, showMovies, showShows, episodes): - logThis("Generating torrent list") + self.bot.log("Generating torrent list") titleWidth = 100 message = [] allDownloaded = True @@ -366,10 +365,10 @@ class BedreNetflix(): if messageText.startswith("```"): if allDownloaded: - logThis("All torrents are downloaded") + self.bot.log("All torrents are downloaded") else: messageText = messageText[:-3]+"\nThis message will not update anymore\n```" - logThis("The message updated 20 times") + self.bot.log("The message updated 20 times") await oldMessage.edit(content = messageText) @@ -381,5 +380,5 @@ class BedreNetflix(): else: await ctx.send(messageText) else: - await ctx.send("Invalid or repeated parameters. Use '!help downloading' to see valid parameters.") + await ctx.send("Invalid or repeated parameters. Use '/help downloading' to see valid parameters.") diff --git a/funcs/other/generators.py b/funcs/other/generators.py index 032704c..febe219 100644 --- a/funcs/other/generators.py +++ b/funcs/other/generators.py @@ -1,9 +1,9 @@ -#import numpy as np import random -from funcs import logThis - class Generators(): + 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): @@ -73,7 +73,7 @@ class Generators(): if new_letter == "\n": done = True genName = "".join(chain) - logThis("Generated "+genName) + self.bot.log("Generated "+genName[:-1]) # Returns the name return(genName) @@ -86,7 +86,7 @@ class Generators(): # Picks one of each genTav = random.choice(fp)+" "+random.choice(sp)+random.choice(tp) - logThis("Generated "+genTav) + self.bot.log("Generated "+genTav) # Return the name return(genTav) diff --git a/funcs/other/movie.py b/funcs/other/movie.py deleted file mode 100644 index fc448b0..0000000 --- a/funcs/other/movie.py +++ /dev/null @@ -1,46 +0,0 @@ -import imdb -import random - -from funcs import logThis - -# Picks a random movie and returns information about it -def movieFunc(): - try: - logThis("Creating IMDb object") - ia = imdb.IMDb() - - try: - logThis("Picking a movie") - movs = open("resources/movies.txt", "r") - movlist = movs.read().split("\n") - mov = random.choice(movlist) - movs.close() - except: - logThis("Problem picking the movie (error code 801)") - return("error","804","","") - - try: - logThis("Searching for "+mov) - s_result = ia.search_movie(mov) - except: - logThis("Couldn't find on imdb (error code 802)") - return("error","802","","") - - try: - logThis("Getting the data") - movie = s_result[0] - ia.update(movie) - cast = movie['cast'] - pcast = "" - for x in range(3): - if cast[x]: - pcast += cast[x]['name']+", " - except: - logThis("Couldn't extract data (error code 803)") - return("error","803","","") - - logThis("Successfully ran !movie") - return(movie['title'], movie['plot'][0].split("::")[0], movie['cover url'].replace("150","600").replace("101","404"), pcast[:-2]) - except: - logThis("Something bad happened... (error code 801)") - return("error","801","","") diff --git a/funcs/other/nerdShit.py b/funcs/other/nerdShit.py index a786a0b..e2e64f8 100644 --- a/funcs/other/nerdShit.py +++ b/funcs/other/nerdShit.py @@ -1,81 +1,81 @@ import discord, wolframalpha, requests, os from PIL import Image, ImageDraw, ImageFont -from funcs import logThis class NerdShit(): - def __init__(self,client): + def __init__(self, bot): """Runs misc commands.""" - self.client = client + self.bot = bot async def wolfSearch(self,ctx,content): - fnt = ImageFont.truetype('resources/times-new-roman.ttf', 20) - async with ctx.message.channel.typing(): - logThis("Requesting data") - client = wolframalpha.Client(self.client.credentials.wolfKey) - res = client.query(content) + fnt = ImageFont.truetype('resources/fonts/times-new-roman.ttf', 20) + await ctx.defer() + self.bot.log("Requesting data") + bot = wolframalpha.Client(self.bot.credentials.wolfKey) + res = bot.query(content) - logThis("Processing data") - titles = [] - pods = [] - if int(res.numpods) > 0: - for pod in res.pods: - titles += [pod.title] - for x, sub in enumerate(pod.subpods): - pods += [sub] - if x > 0: - titles += [""] + self.bot.log("Processing data") + titles = [] + pods = [] + if int(res.numpods) > 0: + for pod in res.pods: + titles += [pod.title] + for x, sub in enumerate(pod.subpods): + pods += [sub] + if x > 0: + titles += [""] - podChunks = [pods[x:x+2] for x in range(0, len(pods), 2)] - titleChucks = [titles[x:x+2] for x in range(0, len(titles), 2)] + podChunks = [pods[x:x+2] for x in range(0, len(pods), 2)] + titleChucks = [titles[x:x+2] for x in range(0, len(titles), 2)] + await ctx.send(f"Response for \"{content}\"") - for x, chunk in enumerate(podChunks): - width = 0 - for title in titleChucks[x]: - width = max(width,fnt.getsize(title)[0]) - height = 5 - heights = [] - for count, pod in enumerate(chunk): - heights += [height] - width = max(width,int(list(pod.img)[0]["@width"])) - if titleChucks[x][count] == "": - placeForText = 0 - else: - placeForText = 30 - height += int(list(pod.img)[0]["@height"]) + 10 + placeForText + for x, chunk in enumerate(podChunks): + width = 0 + for title in titleChucks[x]: + width = max(width,fnt.getsize(title)[0]) + height = 5 + heights = [] + for count, pod in enumerate(chunk): + heights += [height] + width = max(width,int(list(pod.img)[0]["@width"])) + if titleChucks[x][count] == "": + placeForText = 0 + else: + placeForText = 30 + height += int(list(pod.img)[0]["@height"]) + 10 + placeForText - width += 10 - height += 5 - wolfImage = Image.new("RGB",(width,height),color=(255,255,255)) + width += 10 + height += 5 + wolfImage = Image.new("RGB",(width,height),color=(255,255,255)) - for count, pod in enumerate(chunk): - response = requests.get(list(pod.img)[0]["@src"]) - file = open("resources/wolfTemp.png", "wb") - file.write(response.content) - file.close() - oldImage = Image.open("resources/wolfTemp.png") - oldSize = oldImage.size - if titleChucks[x][count] == "": - placeForText = 0 - else: - placeForText = 30 - newSize = (width,int(oldSize[1]+10+placeForText)) - newImage = Image.new("RGB",newSize,color=(255,255,255)) - newImage.paste(oldImage, (int((int(oldSize[0]+10)-oldSize[0])/2),int(((newSize[1]-placeForText)-oldSize[1])/2)+placeForText)) - if titleChucks[x][count] != "": - d = ImageDraw.Draw(newImage,"RGB") - d.text((5,7),titleChucks[x][count],font=fnt,fill=(150,150,150)) + for count, pod in enumerate(chunk): + response = requests.get(list(pod.img)[0]["@src"]) + file = open("resources/wolfTemp.png", "wb") + file.write(response.content) + file.close() + oldImage = Image.open("resources/wolfTemp.png") + oldSize = oldImage.size + if titleChucks[x][count] == "": + placeForText = 0 + else: + placeForText = 30 + newSize = (width,int(oldSize[1]+10+placeForText)) + newImage = Image.new("RGB",newSize,color=(255,255,255)) + newImage.paste(oldImage, (int((int(oldSize[0]+10)-oldSize[0])/2),int(((newSize[1]-placeForText)-oldSize[1])/2)+placeForText)) + if titleChucks[x][count] != "": + d = ImageDraw.Draw(newImage,"RGB") + d.text((5,7),titleChucks[x][count],font=fnt,fill=(150,150,150)) - wolfImage.paste(newImage,(0,heights[count])) - newImage.close() - oldImage.close() - count += 1 + wolfImage.paste(newImage,(0,heights[count])) + newImage.close() + oldImage.close() + count += 1 - wolfImage.save("resources/wolf.png") - wolfImage.close() - await ctx.message.channel.send(file = discord.File("resources/wolf.png")) + wolfImage.save("resources/wolf.png") + wolfImage.close() + await ctx.channel.send(file = discord.File("resources/wolf.png")) - os.remove("resources/wolf.png") - os.remove("resources/wolfTemp.png") - else: - logThis("No returned data") - await ctx.message.channel.send("Could not find anything relating to your search") \ No newline at end of file + os.remove("resources/wolf.png") + os.remove("resources/wolfTemp.png") + else: + self.bot.log("No returned data") + await ctx.send("Could not find anything relating to your search") \ No newline at end of file diff --git a/funcs/other/other.py b/funcs/other/other.py new file mode 100644 index 0000000..90bff31 --- /dev/null +++ b/funcs/other/other.py @@ -0,0 +1,151 @@ +import imdb # Used in movieFunc +import random # Used in movieFunc +import discord # Used in movieFunc +import datetime # Used in helloFunc +import urllib # Used in imageFunc +import lxml # Used in imageFunc +import wikia # Used in findWikiPage +import d20 # Used in rollDice +from .bedreNetflix import BedreNetflix +from .nerdShit import NerdShit +from .generators import Generators + +class MyStringifier(d20.MarkdownStringifier): + def _str_expression(self, node): + if node.comment == None: + resultText = "Result" + else: + resultText = node.comment.capitalize() + + return f"**{resultText}**: {self._stringify(node.roll)}\n**Total**: {int(node.total)}" + +class Other(): + def __init__(self, bot): + self.bot = bot + self.bedreNetflix = BedreNetflix(self.bot) + self.nerdShit = NerdShit(self.bot) + self.generators = Generators(self.bot) + + # Picks a random movie and returns information about it + async def movieFunc(self, ctx): + await ctx.defer() + + self.bot.log("Creating IMDb object") + imdbClient = imdb.IMDb() + + self.bot.log("Picking a movie") + with open("resources/movies.txt", "r") as f: + movieList = f.read().split("\n") + movieName = random.choice(movieList) + + self.bot.log(f"Searching for {movieName}") + searchResult = imdbClient.search_movie(movieName) + + self.bot.log("Getting the data") + movie = searchResult[0] + imdbClient.update(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) + + # Responds with a greeting of a time-appropriate maner + def helloFunc(self, author): + def time_in_range(start, end, x): + # Return true if x is in the range [start, end] + if start <= end: + return start <= x <= end + else: + return start <= x or x <= end + 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): + return("Good morning, "+str(author)) + elif time_in_range(now.replace(hour=10, minute=0, second=0, microsecond=0),now.replace(hour=13, minute=0, second=0, microsecond=0), now): + return("Good day, "+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): + return("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): + return("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): + return("Good night, "+str(author)) + else: + return("Hello, "+str(author)) + + # Finds a random picture online + def imageFunc(self): + # 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": + a = str(random.randint(0 ,9)) + b = str(random.randint(0,9)) + c = str(random.randint(0,9)) + d = str(random.randint(0,9)) + search = ("img_"+a+b+c+d) + elif cam == "two": + a = str(random.randint(2012,2016)) + b = str(random.randint(1,12)).zfill(2) + c = str(random.randint(1,29)).zfill(2) + search = ("IMG_"+a+b+c) + elif cam == "three": + a = str(random.randint(1,500)).zfill(4) + search = ("IMAG_"+a) + elif cam == "four": + a = str(random.randint(0,9)) + b = str(random.randint(0,9)) + c = str(random.randint(0,9)) + d = str(random.randint(0,9)) + search = ("DSC_"+a+b+c+d) + + 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 = "thumb"]/@href') + + # Picks an image + number = random.randint(1,len(images))-1 + image = images[number] + + self.bot.log("Picked image number "+str(number)) + + # Returns the image + self.bot.log("Successfully returned an image") + return(image) + + # Finds a page from the Senkulpa Wikia + def findWikiPage(self, search : str): + self.bot.log("Trying to find wiki page for "+search) + wikia.set_lang("da") + searchResults = wikia.search("senkulpa",search) + if len(searchResults) > 0: + searchResult = searchResults[0].replace(",","%2C") + self.bot.log("Found page \""+searchResult+"\"") + page = wikia.page("senkulpa",searchResult) + content = page.content.replace(u'\xa0', u' ').split("\n")[0] + + images = page.images + if len(images) > 0: + image = images[len(images)-1]+"/revision/latest?path-prefix=da" + return page.title, content, image + else: + return page.title, content, "" + else: + self.bot.log("Couldn't find the page (error code 1002)") + return "", "Couldn't find page (error code 1002)", "" + + def rollDice(self, user, rollString): + while len(rollString) > 1 and rollString[0] == " ": + rollString = rollString[1:] + return user+" :game_die:\n"+str(d20.roll(rollString, allow_comments=True,stringifier=MyStringifier())) + diff --git a/funcs/roll/__init__.py b/funcs/roll/__init__.py deleted file mode 100644 index e356957..0000000 --- a/funcs/roll/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -"""Rolling dice.""" - -__all__ = ["roll_dice"] - -from .dice import roll_dice \ No newline at end of file diff --git a/funcs/roll/dice.py b/funcs/roll/dice.py deleted file mode 100644 index 03385d8..0000000 --- a/funcs/roll/dice.py +++ /dev/null @@ -1,20 +0,0 @@ -import d20 - -class MyStringifier(d20.MarkdownStringifier): - - def _str_expression(self, node): - - if node.comment == None: - resultText = "Result" - else: - resultText = node.comment.capitalize() - - return f"**{resultText}**: {self._stringify(node.roll)}\n**Total**: {int(node.total)}" - -def roll_dice(user, rollString): - while len(rollString) > 1 and rollString[0] == " ": - rollString = rollString[1:] - return user+" :game_die:\n"+str(d20.roll(rollString, allow_comments=True,stringifier=MyStringifier())) - - - diff --git a/funcs/starWarsFuncs/__init__.py b/funcs/starWarsFuncs/__init__.py new file mode 100644 index 0000000..041ebad --- /dev/null +++ b/funcs/starWarsFuncs/__init__.py @@ -0,0 +1,5 @@ +"""Functions related to the Star Wars TTRPG.""" + +__all__ = ["StarWars"] + +from .starWars import StarWars \ No newline at end of file diff --git a/funcs/starWarsFuncs/starWars.py b/funcs/starWarsFuncs/starWars.py new file mode 100644 index 0000000..48e6f84 --- /dev/null +++ b/funcs/starWarsFuncs/starWars.py @@ -0,0 +1,10 @@ +from .starWarsChar import StarWarsChar +from .starWarsRoll import StarWarsRoll +from .starWarsDestiny 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) diff --git a/funcs/swfuncs/swchar.py b/funcs/starWarsFuncs/starWarsChar.py similarity index 69% rename from funcs/swfuncs/swchar.py rename to funcs/starWarsFuncs/starWarsChar.py index de8150c..71f56c9 100644 --- a/funcs/swfuncs/swchar.py +++ b/funcs/starWarsFuncs/starWarsChar.py @@ -1,25 +1,23 @@ import json import string -from funcs import logThis - -class SwChar(): +class StarWarsChar(): def __init__(self, bot): self.bot = bot def getCharName(self, user : str): - logThis("Getting name for "+self.bot.funcs.getName(user)+"'s character") - userCharacter = self.bot.database["swcharacters"].find_one({"_id":user}) + self.bot.log("Getting name for "+self.bot.databaseFuncs.getName(user)+"'s character") + userCharacter = self.bot.database["starwars characters"].find_one({"_id":user}) if userCharacter != None: - logThis("Name is "+userCharacter["Name"]) + self.bot.log("Name is "+userCharacter["Name"]) return userCharacter["Name"] else: - logThis("Just using "+self.bot.funcs.getName(user)) - return self.bot.funcs.getName(user) + self.bot.log("Just using "+self.bot.databaseFuncs.getName(user)) + return self.bot.databaseFuncs.getName(user) def setUpDict(self, cmd : dict): - logThis("Setting up a dictionary in a nice way") + self.bot.log("Setting up a dictionary in a nice way") if bool(cmd): keys = list(cmd) values = list(cmd.values()) @@ -38,10 +36,10 @@ class SwChar(): result += "**" + key + "**" + ": " + str(values[x]) + " " else: result += "**" + key + "**" + ": " + str(values[x]) + "\n" - logThis("Returning a dictionary, but well formatted") + self.bot.log("Returning a dictionary, but well formatted") return result else: - logThis("Couldn't find anything") + self.bot.log("Couldn't find anything") return "There doesn't seem to be anything here..." def lookUp(self, data : dict, key : str, cmd : str = ""): @@ -53,87 +51,87 @@ class SwChar(): if cmd == "": break - logThis("Looking up "+key) + self.bot.log("Looking up "+key) if key in data: - logThis(key+" exists") + self.bot.log(key+" exists") if cmd == "": if type(data[key]) is dict and key != "Weapons": return self.setUpDict(data[key]) elif key == "Weapons": - logThis("Does this even get used? I'm too scared to delete it") + self.bot.log("Does this even get used? I'm too scared to delete it") if bool(data[key]): - logThis("Found "+(", ".join(list(data[key])))) + self.bot.log("Found "+(", ".join(list(data[key])))) return ", ".join(list(data[key])) else: - logThis("There is nothing here") + self.bot.log("There is nothing here") return "There doesn't seem to be anything here..." else: if str(data[key]) != "": - logThis("Returning "+str(data[key])) + self.bot.log("Returning "+str(data[key])) return data[key] else: - logThis("There was nothing there") + self.bot.log("There was nothing there") return "There doesn't seem to be anything here" elif cmd[0] == '+': - logThis("Trying to add to "+key) + self.bot.log("Trying to add to "+key) try: cmd = cmd[1:] while cmd[0] == ' ': cmd = cmd[1:] except: - logThis("Yeah, that fucked up") + self.bot.log("Yeah, that fucked up") return "Can't do that" if type(data[key]) is int: try: newValue = data[key] + int(cmd) data[key] = newValue - logThis("Added "+cmd+" to "+key) + self.bot.log("Added "+cmd+" to "+key) return data except: - logThis("Couldn't add "+cmd+" to "+key) + self.bot.log("Couldn't add "+cmd+" to "+key) return "Can't add that" elif type(data[key]) is list: try: data[key].append(cmd) - logThis("Added "+cmd+" to "+key) + self.bot.log("Added "+cmd+" to "+key) return data except: - logThis("Couldn't add "+cmd+" to "+key) + self.bot.log("Couldn't add "+cmd+" to "+key) return "Can't add that" else: - logThis("Yeah, I can't add that to "+key) + self.bot.log("Yeah, I can't add that to "+key) return "Can't add that" elif cmd[0] == '-': - logThis("Trying to remove/subtract from "+key) + self.bot.log("Trying to remove/subtract from "+key) try: cmd = cmd[1:] while cmd[0] == ' ': cmd = cmd[1:] except: - logThis("Yeah, that fucked up") + self.bot.log("Yeah, that fucked up") return "Can't do that" if type(data[key]) is int: try: newValue = data[key] - int(cmd) data[key] = newValue - logThis("Subtracted "+cmd+" from "+key) + self.bot.log("Subtracted "+cmd+" from "+key) return data except: - logThis("Couldn't subtract "+cmd+" from "+key) + self.bot.log("Couldn't subtract "+cmd+" from "+key) return "Can't remove that" elif type(data[key]) is list: try: data[key].remove(cmd) - logThis("Removed "+cmd+" from "+key) + self.bot.log("Removed "+cmd+" from "+key) return data except: - logThis("Couldn't remove "+cmd+" from "+key) + self.bot.log("Couldn't remove "+cmd+" from "+key) return "Can't remove that" else: - logThis("Yeah, I can't remove/subtract that from "+key) + self.bot.log("Yeah, I can't remove/subtract that from "+key) return "Can't remove that" else: while cmd[0] == ' ': @@ -147,7 +145,7 @@ class SwChar(): cmd = cmd[1:] if cmd == "": break - logThis("Looking up "+newKey+" in "+key) + self.bot.log("Looking up "+newKey+" in "+key) lookUpResult = self.lookUp(data[key],newKey,cmd) if type(lookUpResult) is dict: data[key] = lookUpResult @@ -155,21 +153,21 @@ class SwChar(): else: return lookUpResult elif type(data[key]) != list: - logThis("Trying to change "+key+" to "+cmd) + self.bot.log("Trying to change "+key+" to "+cmd) try: cmd = type(data[key])(cmd) data[key] = cmd - logThis("Did that") + self.bot.log("Did that") return data except: - logThis("No. That did not work") + self.bot.log("No. That did not work") return "Wrong data type" else: - logThis("Yeah, that didn't work") + self.bot.log("Yeah, that didn't work") return "Wrong data type" else: - logThis("Couldn't find "+key) - logThis("Testing to see if it's a multi-word key") + self.bot.log("Couldn't find "+key) + self.bot.log("Testing to see if it's a multi-word key") cmd = key + " " + cmd words = cmd.split(" ") search = "" @@ -179,11 +177,11 @@ class SwChar(): search += " " + words[i] i += 1 except: - logThis("It wasn't. "+search+" doesn't exist") + self.bot.log("It wasn't. "+search+" doesn't exist") return search + " doesn't exist" if search[0] == " ": search = search[1:] - logThis("Yeah! Did that! The key was "+search) + self.bot.log("Yeah! Did that! The key was "+search) cmd = cmd[len(search):] if cmd != "": @@ -193,7 +191,7 @@ class SwChar(): break if cmd == "": - logThis("Returning "+search) + self.bot.log("Returning "+search) return self.setUpDict(data[search]) else: newKey = cmd.split(" ")[0] @@ -211,7 +209,7 @@ class SwChar(): return lookUpResult def characterSheet(self,character : dict): - logThis("Setting up a character sheet for "+character["Name"]) + self.bot.log("Setting up a character sheet for "+character["Name"]) divider = "--------------------\n" name = character["Name"] textf = "" @@ -241,7 +239,7 @@ class SwChar(): return name, text1+text2+"\n\n"+text3+divider+text4+"\n"+divider+text5+text6+text7+text8 def charData(self,user : str,cmd : str): - userCharacter = self.bot.database["swcharacters"].find_one({"_id":user}) + userCharacter = self.bot.database["starwars characters"].find_one({"_id":user}) key = string.capwords(cmd.split(" ")[0]) cmd = cmd[len(key):] @@ -253,40 +251,40 @@ class SwChar(): if cmd == "": break - logThis("Looking for "+self.bot.funcs.getName(user)+"'s character") + self.bot.log("Looking for "+self.bot.databaseFuncs.getName(user)+"'s character") if userCharacter != None: - logThis("Foundt it! Looking for "+key+" in the data") + self.bot.log("Found it! Looking for "+key+" in the data") if key in userCharacter: - logThis("Found it!") + self.bot.log("Found it!") if type(userCharacter[key]) is dict: - logThis("It's a dictionary!") + self.bot.log("It's a dictionary!") if cmd == "": - logThis("Retrieving data") + self.bot.log("Retrieving data") if key == "Weapons": if bool(userCharacter[key]): - logThis("Returning a list of weapons") + self.bot.log("Returning a list of weapons") return ", ".join(list(userCharacter[key])) else: - logThis("The character doesn't have any weapons. Which is probably for the best. Like, who just walks around with weapons? (error code 941)") + self.bot.log("The character doesn't have any weapons. Which is probably for the best. Like, who just walks around with weapons? (error code 941)") return "There doesn't seem to be anything there... (error code 941)" else: return self.setUpDict(userCharacter[key]) elif cmd[0] == "+": - logThis("Gonna add something!!!") + self.bot.log("Gonna add something!!!") try: cmd = cmd[1:] while cmd[0] == ' ': cmd = cmd[1:] except: - logThis("Nope. That didn't happen (error code 942)") + self.bot.log("Nope. That didn't happen (error code 942)") return "Can't do that (error code 942)" if (key == "Talents" or key == "Force-powers") and "," in cmd: cmd = cmd.split(",") while cmd[1][0] == " ": cmd[1] = cmd[1][1:] - logThis("Adding "+cmd[0]+" to "+key) - self.bot.database["swcharacters"].update_one({"_id":user}, + self.bot.log("Adding "+cmd[0]+" to "+key) + self.bot.database["starwars characters"].update_one({"_id":user}, {"$set": {key+"."+cmd[0] : cmd[1]}}) return cmd[0]+" added to "+key+" for " + userCharacter["Name"] @@ -294,55 +292,55 @@ class SwChar(): cmd = cmd.split(",") while cmd[1][0] == " ": cmd[1] = cmd[1][1:] - logThis("Adding "+cmd[0]+" to "+key) + self.bot.log("Adding "+cmd[0]+" to "+key) try: - self.bot.database["swcharacters"].update_one({"_id":user}, + self.bot.database["starwars characters"].update_one({"_id":user}, {"$set": {key+"."+cmd[0] : int(cmd[1])}}) except: - logThis("Fucked that up (error code 949)") + self.bot.log("Fucked that up (error code 949)") return "Wrong data type (error code 949)" return cmd[0]+" added to "+key+" for " + userCharacter["Name"] elif key == "Weapons": - with open("resources/starWars/swtemplates.json", "r") as f: + with open("resources/starWars/starwarstemplates.json", "r") as f: templates = json.load(f) newWeapon = templates["Weapon"] - logThis("Adding "+cmd+" to "+key) - self.bot.database["swcharacters"].update_one({"_id":user}, + self.bot.log("Adding "+cmd+" to "+key) + self.bot.database["starwars characters"].update_one({"_id":user}, {"$set": {key+"."+cmd : newWeapon}}) return cmd+" added to weapons for " + userCharacter["Name"] else: - logThis("That's not happening (error code 947d)") + self.bot.log("That's not happening (error code 947d)") return "Can't add that (error code 947d)" elif cmd[0] == "-": - logThis("Gonna subtract/remove something") + self.bot.log("Gonna subtract/remove something") try: cmd = cmd[1:] while cmd[0] == ' ': cmd = cmd[1:] except: - logThis("AAAAAAAAAAAA (error code 948)") + self.bot.log("AAAAAAAAAAAA (error code 948)") return "Can't do that (error code 948)" if key == "Talents" or key == "Force-powers" or key == "Weapons" or key == "Obligations": - logThis("Trying to remove "+cmd+" from "+key) + self.bot.log("Trying to remove "+cmd+" from "+key) if cmd in userCharacter[key]: - self.bot.database["swcharacters"].update_one({"_id":user}, + self.bot.database["starwars characters"].update_one({"_id":user}, {"$unset": {cmd}}) - logThis("I did that") + self.bot.log("I did that") return cmd+" removed from "+key+" from "+userCharacter["Name"] else: - logThis("Welp. I fucked that up (error code 946e)") + self.bot.log("Welp. I fucked that up (error code 946e)") return "Can't remove that (error code 946e)" else: - logThis("Urgh! (error code 946d)") + self.bot.log("Urgh! (error code 946d)") return "Can't remove that (error code 946d)" else: - logThis("Looking up "+cmd+" in "+key) + self.bot.log("Looking up "+cmd+" in "+key) if key == "Talents" or key == "Force-powers": newKey = cmd newcmd = "" @@ -353,106 +351,106 @@ class SwChar(): lookUpResult = self.lookUp(userCharacter[key],newKey,newcmd) if type(lookUpResult) is dict: - self.bot.database["swcharacters"].update_one({"_id":user}, + self.bot.database["starwars characters"].update_one({"_id":user}, {"$set": {key : lookUpResult}}) return "Changed " + userCharacter["Name"] + "'s " + key else: return lookUpResult else: if cmd == "": - logThis("Retrieving data") + self.bot.log("Retrieving data") if type(userCharacter[key]) is list: return key+":\n"+", ".join(userCharacter[key]) else: return userCharacter[key] elif cmd[0] == '+': - logThis("Adding") + self.bot.log("Adding") try: cmd = cmd[1:] while cmd[0] == ' ': cmd = cmd[1:] except: - logThis("Error message (error code 948)") + self.bot.log("Error message (error code 948)") return "Can't do that (error code 948)" if type(userCharacter[key]) is int: try: - logThis("Adding "+cmd+" to "+key) - self.bot.database["swcharacters"].update_one({"_id":user}, + self.bot.log("Adding "+cmd+" to "+key) + self.bot.database["starwars characters"].update_one({"_id":user}, {"$inc": {key : int(cmd)}}) return "Added " + cmd + " to " + userCharacter["Name"] + "'s " + key except: - logThis("BITCH SANDWICH (error code 947c)") + self.bot.log("BITCH SANDWICH (error code 947c)") return "Can't add that (error code 947c)" elif type(userCharacter[key]) is list: try: - logThis("Adding "+cmd+" to "+key) - self.bot.database["swcharacters"].update_one({"_id":user}, + self.bot.log("Adding "+cmd+" to "+key) + self.bot.database["starwars characters"].update_one({"_id":user}, {"$push": {key : cmd}}) return "Added " + cmd + " to " + userCharacter["Name"] + "'s " + key except: - logThis("tstststststs (error code 947b)") + self.bot.log("tstststststs (error code 947b)") return "Can't add that (error code 947b)" else: - logThis("Help (error code 947a)") + self.bot.log("Help (error code 947a)") return "Can't add that (error code 947a)" elif cmd[0] == '-': - logThis("Removing/subtracting") + self.bot.log("Removing/subtracting") try: cmd = cmd[1:] while cmd[0] == ' ': cmd = cmd[1:] except: - logThis("lalalala (error code 948)") + self.bot.log("lalalala (error code 948)") return "Can't do that (error code 948)" if type(userCharacter[key]) is int: try: - logThis("Subtracting "+cmd+" from "+key) - self.bot.database["swcharacters"].update_one({"_id":user}, + self.bot.log("Subtracting "+cmd+" from "+key) + self.bot.database["starwars characters"].update_one({"_id":user}, {"$inc": {key : -int(cmd)}}) return "Subtracted " + cmd + " from " + userCharacter["Name"] + "'s " + key except: - logThis("Tried it. Didn't want to (error code 946c)") + self.bot.log("Tried it. Didn't want to (error code 946c)") return "Can't remove that (error code 946c)" elif type(userCharacter[key]) is list: try: - logThis("removing "+cmd+" from "+key) + self.bot.log("removing "+cmd+" from "+key) try: - self.bot.database["swcharacters"].update_one({"_id":user}, + self.bot.database["starwars characters"].update_one({"_id":user}, {"$pull": {key : cmd}}) except: - logThis("They can only remove stuff that's actually in the list") + self.bot.log("They can only remove stuff that's actually in the list") return "Not in list (error code 944b)" return "Removed " + cmd + " from " + userCharacter["Name"] + "'s " + key except: - logThis("nah (error code 946b)") + self.bot.log("nah (error code 946b)") return "Can't remove that (error code 946b)" else: - logThis("nyope (error code 946a)") + self.bot.log("nyope (error code 946a)") return "Can't remove that (error code 946a)" else: - logThis("Changing "+key+" to "+cmd) + self.bot.log("Changing "+key+" to "+cmd) if type(userCharacter[key]) is int: try: - self.bot.database["swcharacters"].update_one({"_id":user}, + self.bot.database["starwars characters"].update_one({"_id":user}, {"$set": {key : int(cmd)}}) except: - logThis("I don't wanna tho (error code 945b)") + self.bot.log("I don't wanna tho (error code 945b)") return "Can't do that (error code 945b)" elif type(userCharacter[key]) is str: - self.bot.database["swcharacters"].update_one({"_id":user}, + self.bot.database["starwars characters"].update_one({"_id":user}, {"$set": {key : cmd}}) else: - logThis("I don't wanna tho (error code 945a)") + self.bot.log("I don't wanna tho (error code 945a)") return "Can't do that (error code 945a)" return "Changed " + userCharacter["Name"] + "'s " + key +" to " + cmd else: - logThis(key+" isn't in there (error code 944)") + self.bot.log(key+" isn't in there (error code 944)") return "Couldn't find that data. Are you sure you spelled it correctly? (error code 944)" else: - logThis(user+" doesn't have a character (error code 943)") - return "You don't have a character. You can make one with !swchar (error code 943)" + self.bot.log(user+" doesn't have a character (error code 943)") + return "You don't have a character. You can make one with /starwarscharacter (error code 943)" def replaceSpaces(self,cmd : str): withSpaces = ["Specialization Trees","Wound Threshold","Strain Threshold","Defense - Ranged","Defense - Melee","Force Rating","Core Worlds","Outer Rim","Piloting - Planetary","Piloting - Space","Ranged - Heavy","Ranged - Light","Lightsaber Characteristic","Critical Injuries","Force Powers"] @@ -476,7 +474,7 @@ class SwChar(): cmd = self.replaceSpaces(cmd) - userCharacter = self.bot.database["swcharacters"].find_one({"_id":user}) + userCharacter = self.bot.database["starwars characters"].find_one({"_id":user}) if cmd == " ": cmd = "" @@ -492,29 +490,29 @@ class SwChar(): text1, text2 = self.characterSheet(userCharacter) return text1, self.replaceWithSpaces(text2) else: - logThis("Makin' a character for "+self.bot.funcs.getName(user)) - with open("resources/starWars/swtemplates.json", "r") as f: + self.bot.log("Makin' a character for "+self.bot.databaseFuncs.getName(user)) + with open("resources/starWars/starwarstemplates.json", "r") as f: templates = json.load(f) newChar = templates["Character"] newChar["_id"] = user - self.bot.database["swcharacters"].insert_one(newChar) - return "", "Character for " + self.bot.funcs.getName(user) + " created" + self.bot.database["starwars characters"].insert_one(newChar) + return "", "Character for " + self.bot.databaseFuncs.getName(user) + " created" else: if cmd == "Purge": - logThis("Deleting "+self.bot.funcs.getName(user)+"'s character") - self.bot.database["swcharacters"].delete_one({"_id":user}) - return "", "Character for " + self.bot.funcs.getName(user) + " deleted" + self.bot.log("Deleting "+self.bot.databaseFuncs.getName(user)+"'s character") + self.bot.database["starwars characters"].delete_one({"_id":user}) + return "", "Character for " + self.bot.databaseFuncs.getName(user) + " deleted" else: return "", self.replaceWithSpaces(str(self.charData(user,cmd))) def lightsaberChar(self,user : str): - userCharacter = self.bot.database["swcharacters"].find_one({"_id":user}) + userCharacter = self.bot.database["starwars characters"].find_one({"_id":user}) if userCharacter != None: return userCharacter["Lightsaber-characteristic"] def userHasChar(self,user : str): - userCharacter = self.bot.database["swcharacters"].find_one({"_id":user}) + userCharacter = self.bot.database["starwars characters"].find_one({"_id":user}) return userCharacter != None diff --git a/funcs/swfuncs/swdestiny.py b/funcs/starWarsFuncs/starWarsDestiny.py similarity index 69% rename from funcs/swfuncs/swdestiny.py rename to funcs/starWarsFuncs/starWarsDestiny.py index 56a0698..f12ddac 100644 --- a/funcs/swfuncs/swdestiny.py +++ b/funcs/starWarsFuncs/starWarsDestiny.py @@ -1,46 +1,44 @@ -from funcs import logThis - -class SwDestiny(): +class StarWarsDestiny(): def __init__(self, bot): self.bot = bot def destinyNew(self, num : int): - logThis("Creating a new destiny pool with "+str(num)+" players") - roll, diceResults = self.bot.swroll.roll(0,0,0,0,0,0,num) + self.bot.log("Creating a new destiny pool with "+str(num)+" players") + roll, diceResults = self.bot.starwarsroll.roll(0,0,0,0,0,0,num) roll = "".join(sorted(roll)) with open("resources/starWars/destinyPoints.txt","wt") as f: f.write(roll) - return "Rolled for Destiny Points and got:\n"+self.bot.swroll.diceResultToEmoji(diceResults)+"\n"+self.bot.swroll.resultToEmoji(roll) + return "Rolled for Destiny Points and got:\n"+self.bot.starwarsroll.diceResultToEmoji(diceResults)+"\n"+self.bot.starwarsroll.resultToEmoji(roll) def destinyUse(self, user : str): with open("resources/starWars/destinyPoints.txt","rt") as f: points = f.read() if user == "Nikolaj": - logThis("Trying to use a dark side destiny point") + 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("resources/starWars/destinyPoints.txt","wt") as f: f.write(points) - logThis("Did it") - return "Used a dark side destiny point. Destiny pool is now:\n"+self.bot.swroll.resultToEmoji(points) + self.bot.log("Did it") + return "Used a dark side destiny point. Destiny pool is now:\n"+self.bot.starwarsroll.resultToEmoji(points) else: - logThis("There were no dark side destiny points") + self.bot.log("There were no dark side destiny points") return "No dark side destiny points" else: - logThis("Trying to use a light side destiny point") + 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("resources/starWars/destinyPoints.txt","wt") as f: f.write(points) - logThis("Did it") - return "Used a light side destiny point. Destiny pool is now:\n"+self.bot.swroll.resultToEmoji(points) + self.bot.log("Did it") + return "Used a light side destiny point. Destiny pool is now:\n"+self.bot.starwarsroll.resultToEmoji(points) else: - logThis("There were no dark side destiny points") + self.bot.log("There were no dark side destiny points") return "No light side destiny points" def parseDestiny(self, user : str, cmd : str): @@ -52,9 +50,9 @@ class SwDestiny(): if cmd == "": - logThis("Retrieving destiny pool info") + self.bot.log("Retrieving destiny pool info") with open("resources/starWars/destinyPoints.txt","rt") as f: - return self.bot.swroll.resultToEmoji(f.read()) + return self.bot.starwarsroll.resultToEmoji(f.read()) else: commands = cmd.upper().split(" ") if commands[0] == "N": diff --git a/funcs/swfuncs/swroll.py b/funcs/starWarsFuncs/starWarsRoll.py similarity index 88% rename from funcs/swfuncs/swroll.py rename to funcs/starWarsFuncs/starWarsRoll.py index e3d8505..0cd045d 100644 --- a/funcs/swfuncs/swroll.py +++ b/funcs/starWarsFuncs/starWarsRoll.py @@ -3,12 +3,10 @@ import re import string import json -from funcs import logThis - -with open("resources/starWars/swskills.json", "r") as f: +with open("resources/starWars/starwarsskills.json", "r") as f: skillData = json.load(f) -class SwRoll(): +class StarWarsRoll(): def __init__(self, bot): self.bot = bot @@ -55,7 +53,7 @@ class SwRoll(): # Lets dice cancel each other out def simplify(self, result : str): - logThis("Simplifying "+result) + 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') @@ -173,21 +171,21 @@ class SwRoll(): emoji = "" for char in result: if char == 'S': - emoji += "<:success:690971244971163718> " + emoji += "<:success:826026925280854026> " elif char == 'A': - emoji += "<:advantage:690970761611051079> " + emoji += "<:advantage:826026925515604009> " elif char == 'R': - emoji += "<:swtriumph:690971267486187643> " + emoji += "<:triumph:826026925319127070> " elif char == 'F': - emoji += "<:failure:690970957786906664> " + emoji += "<:failure:826026925288980511> " elif char == 'H': - emoji += "<:threat:690971009469382656> " + emoji += "<:threat:826026925280985108> " elif char == 'D': - emoji += "<:despair:690971200163414238> " + emoji += "<:despair:826026925272203294> " elif char == 'L': - emoji += "<:light:691010089905029171>" + emoji += "<:light:826026925059211295>" elif char == 'B': - emoji += "<:dark:691010101901000852>" + emoji += "<:dark:826026925289373717>" return emoji @@ -225,8 +223,8 @@ class SwRoll(): # Rolls for obligation def obligationRoll(self): - logThis("Rolling for obligation") - data = self.bot.database["swcharacters"] + self.bot.log("Rolling for obligation") + data = self.bot.database["starwarscharacters"] table = [] @@ -297,7 +295,7 @@ class SwRoll(): cmd = re.sub(' +',' ',cmd.upper()) + " " if cmd[0] == " ": cmd = cmd[1:] - cmd = self.bot.swchar.replaceSpaces(string.capwords(cmd)) + cmd = self.bot.starwarschar.replaceSpaces(string.capwords(cmd)) commands = cmd.split(" ") if commands[0] == "": rollParameters = [1,0,3,0,0,0,0] @@ -308,39 +306,39 @@ class SwRoll(): try: return self.obligationRoll() except: - logThis("Obligation fucked up (error code 911)") - return "An error occured (error code 911)" + self.bot.log("Obligation fucked up (error code 911)") + return "An error ocurred (error code 911)" elif string.capwords(commands[0]) in skillData: - logThis("Oh look! This guy has skills!") - if self.bot.swchar.userHasChar: - logThis("They have a character. That much we know") - skillLevel = self.bot.swchar.charData(user,"Skills " + string.capwords(commands[0])) + self.bot.log("Oh look! This guy has skills!") + if self.bot.starwarschar.userHasChar: + self.bot.log("They have a character. That much we know") + skillLevel = self.bot.starwarschar.charData(user,"Skills " + string.capwords(commands[0])) if string.capwords(commands[0]) == "Lightsaber": - logThis("The skill is lightsaber") - charLevel = self.bot.swchar.charData(user,"Characteristics " + self.bot.swchar.lightsaberChar(user)) + self.bot.log("The skill is lightsaber") + charLevel = self.bot.starwarschar.charData(user,"Characteristics " + self.bot.starwarschar.lightsaberChar(user)) else: - charLevel = self.bot.swchar.charData(user,"Characteristics " + skillData[string.capwords(commands[0])]) + charLevel = self.bot.starwarschar.charData(user,"Characteristics " + skillData[string.capwords(commands[0])]) abilityDice = abs(charLevel-skillLevel) proficiencyDice = min(skillLevel,charLevel) commands = [str(abilityDice)] + [str(proficiencyDice)] + commands[1:] - logThis("Converted skill to dice") + self.bot.log("Converted skill to dice") else: - logThis("Okay, no they don't i guess (error code 912)") - return "You don't have a user. You can make one with !swchar (error code 912)" + self.bot.log("Okay, no they don't i guess (error code 912)") + return "You don't have a user. You can make one with /starwarscharacter (error code 912)" elif string.capwords(commands[0]) in ["Ranged","Piloting"]: - logThis("They fucked up writing the name of a ranged or piloting skill") + self.bot.log("They fucked up writing the name of a ranged or piloting skill") if string.capwords(commands[0]) == "Ranged": return "Did you mean \"Ranged - Heavy\" or \"Ranged - Light\" (error code 913)" else: return "Did you mean \"Piloting - Planetary\" or \"Piloting - Space\" (error code 913)" try: - logThis("Converting commands to dice") + self.bot.log("Converting commands to dice") for x, command in enumerate(commands): if command != "": command = command.upper() @@ -361,17 +359,17 @@ class SwRoll(): else: rollParameters[x] = int(command) except: - logThis("Someone fucked u-up! (it was them) (error code 914)") + self.bot.log("Someone fucked u-up! (it was them) (error code 914)") return "Invalid input! (error code 914)" - logThis("Rolling "+str(rollParameters)) + self.bot.log("Rolling "+str(rollParameters)) rollResults, diceResults = self.roll(rollParameters[0],rollParameters[1],rollParameters[2],rollParameters[3],rollParameters[4],rollParameters[5],rollParameters[6]) simplified = self.simplify(rollResults) - name = self.bot.swchar.getCharName(user) + name = self.bot.starwarschar.getCharName(user) - logThis("Returns results and simplified results") + self.bot.log("Returns results and simplified results") if simplified == "": return name + " rolls: " + "\n" + self.diceResultToEmoji(diceResults) + "\nEverything cancels out!" diff --git a/funcs/swfuncs/__init__.py b/funcs/swfuncs/__init__.py deleted file mode 100644 index 30e7ee4..0000000 --- a/funcs/swfuncs/__init__.py +++ /dev/null @@ -1,7 +0,0 @@ -"""Functions related to the Star Wars TTRPG.""" - -__all__ = ["SwChar", "SwRoll", "SwDestiny"] - -from .swchar import SwChar -from .swroll import SwRoll -from .swdestiny import SwDestiny \ No newline at end of file diff --git a/project-guidelines.md b/project-guidelines.md index 5442fee..c351765 100644 --- a/project-guidelines.md +++ b/project-guidelines.md @@ -31,16 +31,19 @@ There are no rules for which emoji to use where, but here's some inspiration: # Terminology Comments, strings, variable names, class names, docstrings, as well as all other text in your code, filenames and directory names should use this terminology correctly. +**bot** - The current discord client and instance of the Gwendolyn class. + **cog** - A class that contains an amount of bot commands. **ctx** - The [context](https://discordpy.readthedocs.io/en/latest/ext/commands/api.html#context) of a command. All command and error functions should use `ctx` as the context variable. -**internal** - Functions, classes and methods that are only used by the bot and don't use the Discord API. +**utils** - Functions, classes and methods that are only used by the bot and don't use the Discord API. # Code ## Code Style -+ All the Python code should follow the [PEP 8 guidelines](https://www.python.org/dev/peps/pep-0008/). +All the Python code should follow the [PEP 8 guidelines](https://www.python.org/dev/peps/pep-0008/), with the following differences: ++ Variable and function names must be camelCase, and must fully consist of either full words or common/understandable abbreviations. ### Documentation + Comment lines should not exede 72 characters. @@ -86,7 +89,7 @@ The `Command` methods in cogs should only exist to perform small tasks or call c ## Codebase Management ### Folders + `cogs/` contains the command cogs. -+ `funcs/` contains all functions and classes called on by the rest of the code. ++ `funcs/` contains all functions and classes called on to perform commands. All functions must be accessible through a class, of which the `Gwendolyn` class has an instance as an attribute. + `resources/` contains the images, lookup databases, fonts etc. that the rest of the code uses. ### Important files @@ -94,15 +97,16 @@ The `Command` methods in cogs should only exist to perform small tasks or call c ## Logging Things you should know about the logging: -+ The `logThis()` function can be found in `.funcs/miscFuncs.py. ++ `log()` is a method of the `Gwendolyn` class. + It is used to log to the log-file (`gwendolyn.log`) and print to the command line. + The function can take either a list of strings or a string as its first parameter. If the parameter is a string, it is converted to a list of 1 string. + The first string in the list is printed. All strings in the list are logged to the log-file. + If the list is longer than 1 string, `(details in log)` is added to the printed string. -+ The level parameter is 20 by default, which means the level is `INFO`. 40 corresponds to a level of `ERROR`, and 10 corresponds to a level of `DEBUG`. ++ The level parameter is 20 by default, which means the level is `INFO`. 40 corresponds to a level of `ERROR`, and 10 corresponds to a level of `DEBUG`. Only use these levels when logging. + Logs of level `DEBUG` are not printed. + Logs of level `ERROR` should only be created in the `on_command_error()` or `Command.error()` functions. ### Logging rules -1. There should be at most 3 `INFO` level logs while executing a single command. This includes the log created in the `on_command()` function in `Gwendolyn.py`, so your code for a command can at most make 2 logs of level `INFO`. `DEBUG` level logs should be used for all other logging. +1. Never call the `logThis()` function from `/utils/utilFuncs/`. Always call `bot.log`. +1. The `on_slash_command()` and `on_ready()` events are the only times log should be called at level 20.`DEBUG` level logs should be used for all other logging. 1. Always provide the channel id if available. Although you shouldn't pass the channel id to a function purely to use it in logs. diff --git a/resources/errorCodes.txt b/resources/errorCodes.txt index 68a664a..9234601 100644 --- a/resources/errorCodes.txt +++ b/resources/errorCodes.txt @@ -99,7 +99,7 @@ 1340 - Error in drawing blackjack table 1341 - Error in drawHand() -14 - Four in a row +14 - connect four 1400 - Unspecified error 1401 - Error deleting old image 1410 - Unspecified parsing error diff --git a/resources/comic-sans-bold.ttf b/resources/fonts/comic-sans-bold.ttf similarity index 100% rename from resources/comic-sans-bold.ttf rename to resources/fonts/comic-sans-bold.ttf diff --git a/resources/futura-bold.ttf b/resources/fonts/futura-bold.ttf similarity index 100% rename from resources/futura-bold.ttf rename to resources/fonts/futura-bold.ttf diff --git a/resources/times-new-roman.ttf b/resources/fonts/times-new-roman.ttf similarity index 100% rename from resources/times-new-roman.ttf rename to resources/fonts/times-new-roman.ttf diff --git a/resources/help/help-addmovie.txt b/resources/help/help-addmovie.txt index 5d28180..daa1ac6 100644 --- a/resources/help/help-addmovie.txt +++ b/resources/help/help-addmovie.txt @@ -1 +1 @@ -Du kan søge efter en film ved at skrive `!addmovie [søgning]`. Gwendolyn vil derefter vise dig resultater baseret på din søgning. Du kan derfra reagere på Gwendolyns besked for at downloade en specifik film. \ No newline at end of file +Du kan søge efter en film ved at skrive `/addmovie [søgning]`. Gwendolyn vil derefter vise dig resultater baseret på din søgning. Du kan derfra reagere på Gwendolyns besked for at downloade en specifik film. \ No newline at end of file diff --git a/resources/help/help-addshow.txt b/resources/help/help-addshow.txt index 746f5e9..9d35d5c 100644 --- a/resources/help/help-addshow.txt +++ b/resources/help/help-addshow.txt @@ -1 +1 @@ -Du kan søge efter et show ved at skrive `!addshow [søgning]`. Gwendolyn vil derefter vise dig resultater baseret på din søgning. Du kan derfra reagere på Gwendolyns besked for at downloade et specifikt show. \ No newline at end of file +Du kan søge efter et show ved at skrive `/addshow [søgning]`. Gwendolyn vil derefter vise dig resultater baseret på din søgning. Du kan derfra reagere på Gwendolyns besked for at downloade et specifikt show. \ No newline at end of file diff --git a/resources/help/help-blackjack.txt b/resources/help/help-blackjack.txt index 45f5c43..49464d1 100644 --- a/resources/help/help-blackjack.txt +++ b/resources/help/help-blackjack.txt @@ -1 +1 @@ -Kommandoen `!blackjack` starter et spil blackjack. `!blackjack bet [beløb]` lader dig vædde en mængde af dine GwendoBucks. Du bruger `!blackjack hit`, `!blackjack stand`, `!blackjack split` og `!blackjack double` i løbet af spillet. \ No newline at end of file +Kommandoen `/blackjack` starter et spil blackjack. `/blackjack bet [beløb]` lader dig vædde en mængde af dine GwendoBucks. Du bruger `/blackjack hit`, `/blackjack stand`, `/blackjack split` og `/blackjack double` i løbet af spillet. \ No newline at end of file diff --git a/resources/help/help-connectfour.txt b/resources/help/help-connectfour.txt new file mode 100644 index 0000000..ee48f68 --- /dev/null +++ b/resources/help/help-connectfour.txt @@ -0,0 +1 @@ +Brug `/connectFour start` til at starte et spil imod Gwendolyn. Brug `/connectFour start [modstander]` for at spille imod en anden person. Du kan også bruge `/connectFour start [1-5]`, hvor tallet er sværhedsgraden af Gwendolyn du gerne vil spille imod. \ No newline at end of file diff --git a/resources/help/help-fourinarow.txt b/resources/help/help-fourinarow.txt deleted file mode 100644 index c191230..0000000 --- a/resources/help/help-fourinarow.txt +++ /dev/null @@ -1 +0,0 @@ -Brug `!fourinarow start` til at starte et spil imod Gwendolyn. Brug `!fourinarow start [modstander]` for at spille imod en anden person. Du kan også bruge `!fourinarow start [1-5]`, hvor tallet er sværhedsgraden af Gwendolyn du gerne vil spille imod. \ No newline at end of file diff --git a/resources/help/help-give.txt b/resources/help/help-give.txt index 5fbb27f..8c2803c 100644 --- a/resources/help/help-give.txt +++ b/resources/help/help-give.txt @@ -1 +1 @@ -Du kan give GwendoBucks til andre med `!give [modtager] [antal]`, hvor [modtager] er den der skal modtage GwendoBucks og [antal] er hvor mange GwendoBucks du giver dem. \ No newline at end of file +Du kan give GwendoBucks til andre med `/give [modtager] [antal]`, hvor [modtager] er den der skal modtage GwendoBucks og [antal] er hvor mange GwendoBucks du giver dem. \ No newline at end of file diff --git a/resources/help/help-hangman.txt b/resources/help/help-hangman.txt index eeff703..1d3741e 100644 --- a/resources/help/help-hangman.txt +++ b/resources/help/help-hangman.txt @@ -1 +1 @@ -Brug `!hangman` til at starte et spil hangman. Brug derefter reaktionerne til at gætte bogstaver. Du har 6 gæt. \ No newline at end of file +Brug `/hangman` til at starte et spil hangman. Brug derefter reaktionerne til at gætte bogstaver. Du har 6 gæt. \ No newline at end of file diff --git a/resources/help/help-hello.txt b/resources/help/help-hello.txt index deee19f..6aa55c9 100644 --- a/resources/help/help-hello.txt +++ b/resources/help/help-hello.txt @@ -1 +1 @@ -Hvis du bruger kommandoen `!hello`, sender Gwendolyn en venlig hilsen. \ No newline at end of file +Hvis du bruger kommandoen `/hello`, sender Gwendolyn en venlig hilsen. \ No newline at end of file diff --git a/resources/help/help-hex.txt b/resources/help/help-hex.txt index 99d5b96..9d1e14b 100644 --- a/resources/help/help-hex.txt +++ b/resources/help/help-hex.txt @@ -1 +1 @@ -Brug `!hex start` til at starte et spil imod Gwendolyn. Brug "!hex start [modstander]" for at spille imod en anden person. \ No newline at end of file +Brug `/hex start` til at starte et spil imod Gwendolyn. Brug "/hex start [modstander]" for at spille imod en anden person. \ No newline at end of file diff --git a/resources/help/help-invest.txt b/resources/help/help-invest.txt index b5ceae5..4228ab0 100644 --- a/resources/help/help-invest.txt +++ b/resources/help/help-invest.txt @@ -1,3 +1,3 @@ -`!invest` vil vise dig hvilke aktier du har. `!invest check [symbol]` viser dig en akties nuværende pris, hvor [symbol] er forkortelsen for firmaet. GwendoBucks er lig med 1 amerikans cent. -`!invest buy [symbol] [pris]` lader dig købe aktier. [pris] er mængden af GwendoBucks du bruger på at købe. Du kan købe for færre GwendoBucks end en enkelt akties pris, men ikke for mindre end 100 GwendoBucks. -`!invest buy [symbol] [pris]` lader dig sælge dine aktier. Du kan godt sælge for mindre end 100 GwendoBucks. \ No newline at end of file +`/invest` vil vise dig hvilke aktier du har. `/invest check [symbol]` viser dig en akties nuværende pris, hvor [symbol] er forkortelsen for firmaet. GwendoBucks er lig med 1 amerikans cent. +`/invest buy [symbol] [pris]` lader dig købe aktier. [pris] er mængden af GwendoBucks du bruger på at købe. Du kan købe for færre GwendoBucks end en enkelt akties pris, men ikke for mindre end 100 GwendoBucks. +`/invest buy [symbol] [pris]` lader dig sælge dine aktier. Du kan godt sælge for mindre end 100 GwendoBucks. \ No newline at end of file diff --git a/resources/help/help-map.txt b/resources/help/help-map.txt deleted file mode 100644 index 9bc9cf8..0000000 --- a/resources/help/help-map.txt +++ /dev/null @@ -1 +0,0 @@ -Få et billede af Senkulpa kortet. \ No newline at end of file diff --git a/resources/help/help-monster.txt b/resources/help/help-monster.txt index 4c7a22f..957043d 100644 --- a/resources/help/help-monster.txt +++ b/resources/help/help-monster.txt @@ -1,2 +1,2 @@ -Søg efter et monster i D&D med `!monster [monster]`, hvor [monster] er navnet på det monster du søger efter. +Søg efter et monster i D&D med `/monster [monster]`, hvor [monster] er navnet på det monster du søger efter. Hvis Gwendolyn ikke kan finde det, er det ofte fordi du har skrevet navnet forkert. \ No newline at end of file diff --git a/resources/help/help-spell.txt b/resources/help/help-spell.txt index 16d9eb4..606b9ea 100644 --- a/resources/help/help-spell.txt +++ b/resources/help/help-spell.txt @@ -1,2 +1,2 @@ -Søg efter en spell i D&D med `!spell [spell]`, hvor [spell] er navnet på den spell du søger efter. +Søg efter en spell i D&D med `/spell [spell]`, hvor [spell] er navnet på den spell du søger efter. Hvis Gwendolyn ikke kan finde den, er det ofte fordi du har skrevet navnet forkert. \ No newline at end of file diff --git a/resources/help/help-starwarscharacter.txt b/resources/help/help-starwarscharacter.txt new file mode 100644 index 0000000..794add6 --- /dev/null +++ b/resources/help/help-starwarscharacter.txt @@ -0,0 +1 @@ + Du kan bruge kommandoer som `/starWarsCharacter name Jared` eller `/starWarsCharacter skills astrogation 3` til at ændre din karakters info. Kommandoen `/starWarsCharacter` vil give dig et character sheet for din karakter. \ No newline at end of file diff --git a/resources/help/help-swroll.txt b/resources/help/help-starwarsroll.txt similarity index 86% rename from resources/help/help-swroll.txt rename to resources/help/help-starwarsroll.txt index 51478ac..4876bf2 100644 --- a/resources/help/help-swroll.txt +++ b/resources/help/help-starwarsroll.txt @@ -1 +1 @@ -Lader dig rulle Star Wars terninger. Du kan skrive tal der repræsenterer antallet af hver terning i rækkefølgen: ability, proficiency, difficulty, challenge, boost, setback og force. Du behøver ikke skrive et tal til alle terningerne. Du kan også skrive forbogstavet for terningen du vil rulle før antallet, såsom "!swroll f2", der ruller 2 force terninger. \ No newline at end of file +Lader dig rulle Star Wars terninger. Du kan skrive tal der repræsenterer antallet af hver terning i rækkefølgen: ability, proficiency, difficulty, challenge, boost, setback og force. Du behøver ikke skrive et tal til alle terningerne. Du kan også skrive forbogstavet for terningen du vil rulle før antallet, såsom "/starWarsRoll f2", der ruller 2 force terninger. \ No newline at end of file diff --git a/resources/help/help-swchar.txt b/resources/help/help-swchar.txt deleted file mode 100644 index 70fc0eb..0000000 --- a/resources/help/help-swchar.txt +++ /dev/null @@ -1 +0,0 @@ - Du kan bruge kommandoer som `!swchar name Jared` eller `!swchar skills astrogation 3` til at ændre din karakters info. Kommandoen `!swchar` vil give dig et character sheet for din karakter. \ No newline at end of file diff --git a/resources/help/help-trivia.txt b/resources/help/help-trivia.txt index 305b0ba..a5da454 100644 --- a/resources/help/help-trivia.txt +++ b/resources/help/help-trivia.txt @@ -1,4 +1,4 @@ -Lader dig spille et spil trivia. `!trivia` starter spillet. +Lader dig spille et spil trivia. `/trivia` starter spillet. Hvert spil trivia varer i 1 minut, og der kan kun være et enkelt spil i hver kanal ad gangen. -`!trivia [svar]` lader dig svare på det nuværende spørgsmål, hvor [svar] er a, b, c eller d. +`/trivia [svar]` lader dig svare på det nuværende spørgsmål, hvor [svar] er a, b, c eller d. Hvis du svarer rigtigt får du 1 GwendoBuck. \ No newline at end of file diff --git a/resources/help/help.txt b/resources/help/help.txt index ccbbb01..9501046 100644 --- a/resources/help/help.txt +++ b/resources/help/help.txt @@ -1,49 +1,24 @@ -`!hello` - En venlig hilsen. - -`!roll` - Rul terninger i xdy format. - -`!spell` - Slå en besværgelse op. - -`!monster` - Slå et monster op. - -`!map` - Få et billede af Senkulpa kortet. - -`!image` - Finder et tilfældigt billede fra internettet. - -`!movie` - Giver titlen på en tilfældig film fra Bedre Netflix - -`!name` - Genererer et tilfældigt navn. - -`!tavern` - Genererer en tilfældig tavern. - -`!give` - Lader dig give GwendoBucks til andre. - -`!swchar` - Lader dig lave en Star Wars karakter. - -`!swroll` - Lader dig rulle Star Wars terninger. - -`!balance` - Viser dig hvor mange GwendoBucks du har. - -`!invest` - Lader dig investere dine GwendoBucks i aktiemarkedet. - -`!blackjack` - Lader dig spille et spil blackjack. - -`!trivia` - Lader dig spille et spil trivia, hvor du kan tjene GwendoBucks. - -`!fourinarow` - Lader dig spille et spil fire på stribe. - -`!hex` - Lader dig spille et spil Hex. - -`!hangman` - Lader dig spille et spil hangman. - -`!wolf` - Lader dig slå ting op på Wolfram Alpha. - -`!addmovie` - Lader dig tilføje film til Bedre Netflix. - -`!addshow` - Lader dig tilføje tv shows til Bedre Netflix. - -`!downloading` - Viser dig hvor langt de torrents der er ved at downloade er kommet. - -`!thank` - Lader dig takke Gwendolyn. - -Du kan få ekstra information om kommandoerne med "!help [kommando]". +`/hello` - En venlig hilsen. +`/roll` - Rul terninger i xdy format. +`/spell` - Slå en besværgelse op. +`/monster` - Slå et monster op. +`/image` - Finder et tilfældigt billede fra internettet. +`/movie` - Giver titlen på en tilfældig film fra Bedre Netflix +`/name` - Genererer et tilfældigt navn. +`/tavern` - Genererer en tilfældig tavern. +`/give` - Lader dig give GwendoBucks til andre. +`/starWarsCharacter` - Lader dig lave en Star Wars karakter. +`/starWarsRoll` - Lader dig rulle Star Wars terninger. +`/balance` - Viser dig hvor mange GwendoBucks du har. +`/invest` - Lader dig investere dine GwendoBucks i aktiemarkedet. +`/blackjack` - Lader dig spille et spil blackjack. +`/trivia` - Lader dig spille et spil trivia, hvor du kan tjene GwendoBucks. +`/connectFour` - Lader dig spille et spil fire på stribe. +`/hex` - Lader dig spille et spil Hex. +`/hangman` - Lader dig spille et spil hangman. +`/wolf` - Lader dig slå ting op på Wolfram Alpha. +`/addmovie` - Lader dig tilføje film til Bedre Netflix. +`/addshow` - Lader dig tilføje tv shows til Bedre Netflix. +`/downloading` - Viser dig hvor langt de torrents der er ved at downloade er kommet. +`/thank` - Lader dig takke Gwendolyn. +Du kan få ekstra information om kommandoerne med "/help [kommando]". diff --git a/resources/slashParameters.json b/resources/slashParameters.json new file mode 100644 index 0000000..84dab46 --- /dev/null +++ b/resources/slashParameters.json @@ -0,0 +1,422 @@ +{ + "addMovie" : { + "name" : "addMovie", + "description" : "Request a movie for Bedre Netflix", + "options" : [ + { + "name" : "movie", + "description" : "The movie to request", + "type" : 3, + "required" : "true" + } + ] + }, + "addShow" : { + "name" : "addShow", + "description" : "Request a show for Bedre Netflix", + "options" : [ + { + "name" : "show", + "description" : "The show to request", + "type" : 3, + "required" : "true" + } + ] + }, + "balance" : { + "name" : "balance", + "description" : "See your balance of GwendoBucks" + }, + "blackjackBet" : { + "base" : "blackjack", + "name" : "bet", + "description" : "Enter the current blackjack game with a bet", + "options" : [ + { + "name" : "bet", + "description" : "Your bet", + "type" : 4, + "required" : "true" + } + ] + }, + "blackjackHit" : { + "base" : "blackjack", + "name" : "hit", + "description" : "Hit on your hand in blackjack", + "options" : [ + { + "name" : "hand", + "description" : "The number of the hand to hit if you've split", + "type" : 4, + "required" : "false" + } + ] + }, + "blackjackStand" : { + "base" : "blackjack", + "name" : "stand", + "description" : "Stand on your hand in blackjack", + "options" : [ + { + "name" : "hand", + "description" : "The number of the hand to stand if you've split", + "type" : 4, + "required" : "false" + } + ] + }, + "blackjackStart" : { + "base" : "blackjack", + "name" : "start", + "description" : "Start a game of blackjack" + }, + "connectFourStartGwendolyn" : { + "base" : "connectFour", + "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" + } + ] + }, + "connectFourStartUser" : { + "base" : "connectFour", + "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" + } + ] + }, + "connectFourStop" : { + "base" : "connectFour", + "name" : "stop", + "description" : "Stop the game of connect four" + }, + "connectFourPlace" : { + "base" : "connectFour", + "name" : "place", + "description" : "Place a piece", + "options" : [ + { + "name" : "column", + "description" : "The column to place the piece", + "type" : 4, + "required" : "true" + } + ] + }, + "downloading" : { + "name" : "downloading", + "description" : "See current downloads for Bedre Netflix", + "options" : [ + { + "name" : "parameters", + "description" : "Parameters for the command", + "type" : 3, + "required" : "false" + } + ] + }, + "game" : { + "name" : "game", + "description" : "Set the 'playing' text for Gwendolyn", + "options" : [ + { + "name" : "gameText", + "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" + } + ] + }, + "hangmanStart" : { + "base" : "hangman", + "name" : "start", + "description" : "Start a game of hangman" + }, + "hangmanStop" : { + "base" : "hangman", + "name" : "stop", + "description" : "Stop the current 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" + } + ] + }, + "hexPlace" : { + "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" + } + ] + }, + "hexStartGwendolyn" : { + "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" + } + ] + }, + "hexStartUser" : { + "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" + } + ] + }, + "hexSurrender" : { + "base" : "hex", + "name" : "surrender", + "description" : "Surrender the game of hex" + }, + "hexSwap" : { + "base" : "hex", + "name" : "swap", + "description" : "Perform a hex swap" + }, + "hexUndo" : { + "base" : "hex", + "name" : "undo", + "description" : "Undo your last hex move" + }, + "invest" : { + "name" : "invest", + "description" : "Invest GwendoBucks in the stock market", + "options" : [ + { + "name" : "parameters", + "description" : "The parameters for the command", + "type" : 3, + "required" : "false" + } + ] + }, + "image" : { + "name" : "image", + "description" : "Get a random image from Bing" + }, + "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" + } + ] + }, + "starWarsCharacter" : { + "name" : "starWarsCharacter", + "description" : "Manage your Star Wars character sheet", + "options" : [ + { + "name" : "parameters", + "description" : "The parameters for the command", + "type" : 3, + "required" : "false" + } + ] + }, + "starWarsCrit" : { + "name" : "starWarsCrit", + "description" : "Roll a Star Wars critical injury", + "options" : [ + { + "name" : "severity", + "description" : "The severity of the hit", + "type" : 4, + "required" : "true" + } + ] + }, + "starWarsDestiny" : { + "name" : "starWarsDestiny", + "description" : "Use and see Star Wars Destiny points", + "options" : [ + { + "name" : "parameters", + "description" : "The parameters for the command", + "type" : 3, + "required" : "false" + } + ] + }, + "starWarsRoll" : { + "name" : "starWarsRoll", + "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" : "wikiPage", + "description" : "The page to find", + "type" : 3, + "required" : "true" + } + ] + }, + "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" + } + ] + } +} \ No newline at end of file diff --git a/resources/starWars/swskills.json b/resources/starWars/starwarsskills.json similarity index 100% rename from resources/starWars/swskills.json rename to resources/starWars/starwarsskills.json diff --git a/resources/starWars/swtemplates.json b/resources/starWars/starwarstemplates.json similarity index 100% rename from resources/starWars/swtemplates.json rename to resources/starWars/starwarstemplates.json diff --git a/resources/startingFiles.json b/resources/startingFiles.json index baaa5f4..c6eb89c 100644 --- a/resources/startingFiles.json +++ b/resources/startingFiles.json @@ -60,11 +60,11 @@ "resources/movies.txt": "The Room", "resources/names.txt": "Gandalf", "credentials.txt" : "Bot token: TOKEN\nFinnhub API key: KEY\nWordnik API Key: KEY\nMongoDB user: USERNAME\nMongoDB password: PASSWORD\nWolframAlpha AppID: APPID\nRadarr API key: KEY\nSonarr API key: KEY", - "options.txt" : "Prefix: !\nTesting: True" + "options.txt" : "Testing: True\nTesting guild ids:\nAdmins:" }, "folder" : [ "resources/games/blackjackTables", - "resources/games/4InARowBoards", + "resources/games/connect4Boards", "resources/games/hexBoards", "resources/games/hangmanBoards", "resources/bedreNetflix" diff --git a/utils/__init__.py b/utils/__init__.py new file mode 100644 index 0000000..4598629 --- /dev/null +++ b/utils/__init__.py @@ -0,0 +1,6 @@ +"""A collections of utilities used by Gwendolyn and her functions""" + +__all__ = ["Options", "Credentials", "databaseFuncs", "getParams", "logThis", "cap", "makeFiles", "replaceMultiple", "emojiToCommand"] + +from .helperClasses import Options, Credentials, databaseFuncs +from .utilFunctions import getParams, logThis, cap, makeFiles, replaceMultiple, emojiToCommand \ No newline at end of file diff --git a/utils/helperClasses.py b/utils/helperClasses.py new file mode 100644 index 0000000..74b4cc1 --- /dev/null +++ b/utils/helperClasses.py @@ -0,0 +1,132 @@ +import re, git, os, json + +def sanitize(data : str, options : bool = False): + data = data.splitlines() + dct = {} + for line in data: + if line[0] != "#" and ":" in line: + lineValues = line.split(":") + lineValues[0] = lineValues[0].lower() + lineValues[1] = lineValues[1].replace(" ", "") + if options: + lineValues[1] = lineValues[1].lower() + + if lineValues[0] in ["testing guild ids", "admins"]: + lineValues[1] = lineValues[1].split(",") + if all(i.isnumeric() for i in lineValues[1]): + lineValues[1] = [int(i) for i in lineValues[1]] + + if any(i == lineValues[1] for i in ["true", "false"]): + lineValues[1] = (lineValues[1] == "true") + + dct[lineValues[0]] = lineValues[1] + + return dct + +class Options(): + def __init__(self): + with open("options.txt","r") as f: + data = sanitize(f.read(), True) + + self.testing = data["testing"] + self.guildIds = data["testing guild ids"] + self.admins = data["admins"] + +class Credentials(): + def __init__(self): + with open("credentials.txt","r") as f: + data = sanitize(f.read()) + + self.token = data["bot token"] + self.finnhubKey = data["finnhub api key"] + self.wordnikKey = data["wordnik api key"] + self.mongoDBUser = data["mongodb user"] + self.mongoDBPassword = data["mongodb password"] + self.wolfKey = data["wolframalpha appid"] + self.radarrKey = data["radarr api key"] + self.sonarrKey = data["sonarr api key"] + +class databaseFuncs(): + def __init__(self, bot): + self.bot = bot + + def getName(self, userID): + user = self.bot.database["users"].find_one({"_id":userID}) + + if user != None: + return user["user name"] + elif userID == "Gwendolyn": + return userID + else: + self.bot.log("Couldn't find user "+userID) + return userID + + def getID(self,userName): + user = self.bot.database["users"].find_one({"user name":re.compile(userName, re.IGNORECASE)}) + + if user != None: + return user["_id"] + else: + self.bot.log("Couldn't find user "+userName) + return None + + def deleteGame(self, gameType,channel): + self.bot.database[gameType].delete_one({"_id":channel}) + + def stopServer(self): + self.bot.database["trivia questions"].delete_many({}) + self.bot.database["blackjack games"].delete_many({}) + self.bot.database["connect 4 games"].delete_many({}) + self.bot.database["hangman games"].delete_many({}) + + if not self.bot.options.testing: + g = git.cmd.Git("") + g.pull() + + def connectFourReactionTest(self,channel,message,user): + game = self.bot.database["connect 4 games"].find_one({"_id":str(channel.id)}) + + with open("resources/games/oldImages/connectFour"+str(channel.id), "r") as f: + oldImage = int(f.read()) + + if message.id == oldImage: + self.bot.log("They reacted to the connectFour game") + turn = game["turn"] + if user == game["players"][turn]: + return True, turn+1 + else: + self.bot.log("It wasn't their turn") + return False, 0 + else: + return False, 0 + + def hangmanReactionTest(self, channel,message): + try: + with open("resources/games/oldImages/hangman"+str(channel.id), "r") as f: + oldMessages = f.read().splitlines() + except: + return False + gameMessage = False + + for oldMessage in oldMessages: + oldMessageID = int(oldMessage) + if message.id == oldMessageID: + self.bot.log("They reacted to the hangman game") + gameMessage = True + + return gameMessage + + def bedreNetflixReactionTest(self, channel, message): + if os.path.isfile(f"resources/bedreNetflix/oldMessage{str(channel.id)}"): + with open("resources/bedreNetflix/oldMessage"+str(channel.id),"r") as f: + data = json.load(f) + else: + return False, None, None + + if data["messageID"] == message.id: + if "imdbIds" in data: + return True, True, data["imdbIds"] + else: + return True, False, data["imdbNames"] + else: + return False, None, None diff --git a/utils/utilFunctions.py b/utils/utilFunctions.py new file mode 100644 index 0000000..58a1406 --- /dev/null +++ b/utils/utilFunctions.py @@ -0,0 +1,121 @@ +import json +import time +import logging +import os +from .helperClasses import Options + +logging.basicConfig(filename="gwendolyn.log", level=logging.INFO) + +def getParams(): + with open("resources/slashParameters.json", "r") as f: + params = json.load(f) + + options = Options() + + if options.testing: + for p in params: + params[p]["guild_ids"] = options.guildIds + + return params + +def logThis(messages, channel : str = "", level : int = 20): + localtime = time.asctime(time.localtime(time.time())) + channel = channel.replace("Direct Message with ","") + if type(messages) is str: + messages = [messages] + + for x, msg in enumerate(messages): + if channel == "": + messages[x] = localtime+" - "+msg + else: + messages[x] = localtime+" ("+channel+") - "+msg + + if len(messages) > 1: + messages[0] += " (details in log)" + + if level != 10: + print(messages[0]) + + for logMessage in messages: + logging.log(level, logMessage) + +# Capitalizes all words except some of them +def cap(s): + no_caps_list = ["of","the"] + # Capitalizes a strink like a movie title + word_number = 0 + lst = s.split() + res = '' + for word in lst: + word_number += 1 + if word not in no_caps_list or word_number == 1: + word = word.capitalize() + res += word+" " + res = res[:-1] + return res + +def makeFiles(): + def makeJsonFile(path,content): + # Creates json file if it doesn't exist + if not os.path.isfile(path): + logThis(path.split("/")[-1]+" didn't exist. Making it now.") + with open(path,"w") as f: + json.dump(content,f,indent = 4) + + def makeTxtFile(path,content): + # Creates txt file if it doesn't exist + if not os.path.isfile(path): + logThis(path.split("/")[-1]+" didn't exist. Making it now.") + with open(path,"w") as f: + f.write(content) + + def directory(path): + if not os.path.isdir(path): + os.makedirs(path) + logThis("The "+path.split("/")[-1]+" directory didn't exist") + + with open("resources/startingFiles.json") as f: + data = json.load(f) + + for path, content in data["json"].items(): + makeJsonFile(path,content) + + for path, content in data["txt"].items(): + makeTxtFile(path,content) + + for path in data["folder"]: + directory(path) + +# Replaces multiple things with the same thing +def replaceMultiple(mainString, toBeReplaces, newString): + # Iterate over the strings to be replaced + for elem in toBeReplaces : + # Check if string is in the main string + if elem in mainString : + # Replace the string + mainString = mainString.replace(elem, newString) + + return mainString + +def emojiToCommand(emoji): + if emoji == "1️⃣": + return 1 + elif emoji == "2️⃣": + return 2 + elif emoji == "3️⃣": + return 3 + elif emoji == "4️⃣": + return 4 + elif emoji == "5️⃣": + return 5 + elif emoji == "6️⃣": + return 6 + elif emoji == "7️⃣": + return 7 + elif emoji == "🎲": + return "roll" + elif emoji == "❌": + return "none" + elif emoji == "✔️": + return 1 + else: return ""