Merge pull request #6 from NikolajDanger/convert-to-slash-commands

Convert to slash commands
This commit is contained in:
NikolajDanger
2021-03-31 01:06:08 +02:00
committed by GitHub
72 changed files with 2032 additions and 1515 deletions

2
.gitignore vendored
View File

@@ -158,7 +158,7 @@ resources/bedreNetflix/
resources/games/hilo/ resources/games/hilo/
resources/games/blackjackTables/ resources/games/blackjackTables/
resources/games/oldImages/ resources/games/oldImages/
resources/games/4InARowBoards/ resources/games/connect4Boards/
resources/games/hexBoards/ resources/games/hexBoards/
resources/games/hangmanBoards/ resources/games/hangmanBoards/
resources/lookup/monsters.json resources/lookup/monsters.json

View File

@@ -1,35 +1,10 @@
import discord, os, finnhub, platform, asyncio, traceback import os, finnhub, platform, asyncio, discord
from discord.ext import commands from discord.ext import commands
from discord_slash import SlashCommand
from pymongo import MongoClient from pymongo import MongoClient
from funcs import logThis, makeFiles, Money, Funcs, SwChar, SwDestiny, SwRoll, Games, Generators, BedreNetflix, NerdShit from funcs import Money, StarWars, Games, Other, LookupFuncs
from utils import Options, Credentials, logThis, makeFiles, databaseFuncs
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")
class Gwendolyn(commands.Bot): class Gwendolyn(commands.Bot):
def __init__(self): 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") 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: if self.options.testing:
logThis("Testing mode") self.log("Testing mode")
self.database = self.MongoClient["Gwendolyn-Test"] self.database = self.MongoClient["Gwendolyn-Test"]
else: else:
self.database = self.MongoClient["Gwendolyn"] self.database = self.MongoClient["Gwendolyn"]
self.swchar = SwChar(self) self.starWars = StarWars(self)
self.swroll = SwRoll(self) self.other = Other(self)
self.swdestiny = SwDestiny(self) self.lookupFuncs = LookupFuncs(self)
self.games = Games(self)
self.generator = Generators()
self.bedreNetflix = BedreNetflix(self)
self.nerdShit = NerdShit(self)
Games(self)
self.money = Money(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
super().__init__(command_prefix=" ", case_insensitive=True, intents = intents)
def log(self, messages, channel : str = "", level : int = 10):
logThis(messages, channel, level)
if __name__ == "__main__":
if platform.system() == "Windows":
asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
# Creates the required files # Creates the required files
makeFiles() makeFiles()
# Creates the Bot # Creates the Bot
client = Gwendolyn() bot = Gwendolyn()
bot.slash = SlashCommand(bot, sync_commands=True, sync_on_cog_reload=True, override_type=True)
# 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]
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)")
#Loads cogs #Loads cogs
for filename in os.listdir("./cogs"): for filename in os.listdir("./cogs"):
if filename.endswith(".py"): if filename.endswith(".py"):
client.load_extension(f"cogs.{filename[:-3]}") bot.load_extension(f"cogs.{filename[:-3]}")
try: try:
# Runs the whole shabang # Runs the whole shabang
client.run(client.credentials.token) bot.run(bot.credentials.token)
except: except:
logThis("Could not log in. Remember to write your bot token in the credentials.txt file") bot.log("Could not log in. Remember to write your bot token in the credentials.txt file")

40
cogs/EventCog.py Normal file
View File

@@ -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))

198
cogs/GameCogs.py Normal file
View File

@@ -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))

View File

@@ -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))

View File

@@ -1,18 +1,21 @@
import discord import discord, json
from discord.ext import commands 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): class LookupCog(commands.Cog):
def __init__(self, bot):
def __init__(self,client):
"""Runs lookup commands.""" """Runs lookup commands."""
self.client = client self.bot = bot
# Looks up a spell # Looks up a spell
@commands.command() @cog_ext.cog_slash(**params["spell"])
async def spell(self, ctx, *, content): async def spell(self, ctx, query):
spell = spellFunc(cap(content)) spell = self.bot.lookupFuncs.spellFunc(cap(query))
if len(spell) > 2000: if len(spell) > 2000:
await ctx.send(spell[:2000]) await ctx.send(spell[:2000])
await ctx.send(spell[2000:]) await ctx.send(spell[2000:])
@@ -20,12 +23,12 @@ class LookupCog(commands.Cog):
await ctx.send(spell) await ctx.send(spell)
# Looks up a monster # Looks up a monster
@commands.command() @cog_ext.cog_slash(**params["monster"])
async def monster(self, ctx, *, content): async def monster(self, ctx, query):
title, text1, text2, text3, text4, text5 = monsterFunc(cap(content)) title, text1, text2, text3, text4, text5 = self.bot.lookupFuncs.monsterFunc(cap(query))
em1 = discord.Embed(title = title, description = text1, colour=0xDEADBF) 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 # there is too much text
await ctx.send(embed = em1) await ctx.send(embed = em1)
if text2 != "": if text2 != "":
@@ -65,5 +68,5 @@ class LookupCog(commands.Cog):
em5_2 = discord.Embed(title = "", description = text5[2048:], colour=0xDEADBF) em5_2 = discord.Embed(title = "", description = text5[2048:], colour=0xDEADBF)
await ctx.send(embed = em5_2) await ctx.send(embed = em5_2)
def setup(client): def setup(bot):
client.add_cog(LookupCog(client)) bot.add_cog(LookupCog(bot))

View File

@@ -1,122 +1,105 @@
import discord, codecs, string import discord, codecs, string, json
from discord.ext import commands 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): class MiscCog(commands.Cog):
def __init__(self, bot):
def __init__(self,client):
"""Runs misc commands.""" """Runs misc commands."""
self.client = client self.bot = bot
self.client.remove_command("help") self.bot.remove_command("help")
self.generator = client.generator self.generators = bot.other.generators
self.bedreNetflix = client.bedreNetflix self.bedreNetflix = bot.other.bedreNetflix
self.nerdShit = client.nerdShit self.nerdShit = bot.other.nerdShit
@commands.command(name = "help") # Sends the bot's latency
async def helpCommand(self, ctx, *, content = ""): @cog_ext.cog_slash(**params["ping"])
if content == "": 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: with codecs.open("resources/help/help.txt",encoding="utf-8") as f:
text = f.read() text = f.read()
em = discord.Embed(title = "Help", description = text,colour = 0x59f442) em = discord.Embed(title = "Help", description = text,colour = 0x59f442)
await ctx.send(embed = em) await ctx.send(embed = em)
else: else:
logThis(f"Looking for help-{content}.txt",str(ctx.message.channel.id)) self.bot.log(f"Looking for help-{command}.txt",str(ctx.channel_id))
with codecs.open(f"resources/help/help-{content}.txt",encoding="utf-8") as f: with codecs.open(f"resources/help/help-{command}.txt",encoding="utf-8") as f:
text = f.read() 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) await ctx.send(embed = em)
# Sends the bot's latency # Lets you thank the bot
@commands.command() @cog_ext.cog_slash(**params["thank"])
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"])
async def thank(self, ctx): async def thank(self, ctx):
await ctx.send("You're welcome :blush:") await ctx.send("You're welcome :blush:")
# Sends a friendly message # Sends a friendly message
@commands.command(aliases = ["hi","howdy"]) @cog_ext.cog_slash(**params["hello"])
async def hello(self, ctx): 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 # Rolls dice
@commands.command() @cog_ext.cog_slash(**params["roll"])
async def roll(self, ctx, *, content = "1d20"): async def roll(self, ctx, dice = "1d20"):
await ctx.send(roll_dice(ctx.message.author.display_name,content)) await ctx.send(self.bot.other.rollDice(ctx.author.display_name, dice))
# 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")
# Sends a random image # Sends a random image
@commands.command(aliases = ["img"]) @cog_ext.cog_slash(**params["image"])
async def image(self, ctx): async def image(self, ctx):
randomImage = imageFunc() await ctx.defer()
await ctx.send(randomImage) await ctx.send(self.bot.other.imageFunc())
# Finds a random movie # Finds a random movie
@commands.command() @cog_ext.cog_slash(**params["movie"])
async def movie(self,ctx): async def movie(self,ctx):
async with ctx.typing(): await self.bot.other.movieFunc(ctx)
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)")
# Generates a random name # Generates a random name
@commands.command() @cog_ext.cog_slash(**params["name"])
async def name(self, ctx): async def name(self, ctx):
await ctx.send(self.generator.nameGen()) await ctx.send(self.generators.nameGen())
# Generates a random tavern name # Generates a random tavern name
@commands.command() @cog_ext.cog_slash(**params["tavern"])
async def tavern(self, ctx): async def tavern(self, ctx):
await ctx.send(self.generator.tavernGen()) await ctx.send(self.generators.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)
# Finds a page on the Senkulpa wiki # Finds a page on the Senkulpa wiki
@commands.command(aliases = ["wikia"]) @cog_ext.cog_slash(**params["wiki"])
async def wiki(self, ctx, *, content): async def wiki(self, ctx, wikiPage):
async with ctx.message.channel.typing(): await ctx.defer()
command = string.capwords(content) command = string.capwords(wikiPage)
title, content, thumbnail = findWikiPage(command) title, content, thumbnail = self.bot.otherfindWikiPage(command)
if title != "": if title != "":
logThis("Sending the embedded message",str(ctx.message.channel.id)) self.bot.log("Sending the embedded message",str(ctx.channel_id))
content += "\n[Læs mere](https://senkulpa.fandom.com/da/wiki/"+title.replace(" ","_")+")" content += "\n[Læs mere](https://senkulpa.fandom.com/da/wiki/"+title.replace(" ","_")+")"
embed = discord.Embed(title = title, description = content, colour=0xDEADBF) embed = discord.Embed(title = title, description = content, colour=0xDEADBF)
if thumbnail != "": if thumbnail != "":
@@ -127,24 +110,27 @@ class MiscCog(commands.Cog):
await ctx.send(content) await ctx.send(content)
#Searches for movie and adds it to Bedre Netflix #Searches for movie and adds it to Bedre Netflix
@commands.command(aliases = ["rm","addmovie","am"]) @cog_ext.cog_slash(**params["addMovie"])
async def requestmovie(self, ctx, *, content): async def addMovie(self, ctx, movie):
await self.bedreNetflix.requestMovie(ctx,content) await ctx.defer()
await self.bedreNetflix.requestMovie(ctx, movie)
#Searches for show and adds it to Bedre Netflix #Searches for show and adds it to Bedre Netflix
@commands.command(aliases = ["rs","addshow","as","addseries"]) @cog_ext.cog_slash(**params["addShow"])
async def requestshow(self, ctx, *, content): async def addShow(self, ctx, show):
await self.bedreNetflix.requestShow(ctx,content) await ctx.defer()
await self.bedreNetflix.requestShow(ctx, show)
#Returns currently downloading torrents #Returns currently downloading torrents
@commands.command(aliases = ["downloads"]) @cog_ext.cog_slash(**params["downloading"])
async def downloading(self, ctx, *, content = "-d"): async def downloading(self, ctx, parameters = "-d"):
await self.bedreNetflix.downloading(ctx, content) await ctx.defer()
await self.bedreNetflix.downloading(ctx, parameters)
#Looks up on Wolfram Alpha #Looks up on Wolfram Alpha
@commands.command() @cog_ext.cog_slash(**params["wolf"])
async def wolf(self, ctx, *, content): async def wolf(self, ctx, query):
await self.nerdShit.wolfSearch(ctx,content) await self.nerdShit.wolfSearch(ctx, query)
def setup(client): def setup(bot):
client.add_cog(MiscCog(client)) bot.add_cog(MiscCog(bot))

View File

@@ -1,28 +1,28 @@
from discord.ext import commands from discord.ext import commands
from funcs import logThis, emojiToCommand from utils import emojiToCommand
class ReactionCog(commands.Cog): class ReactionCog(commands.Cog):
def __init__(self, client): def __init__(self, bot):
"""Listens for reactions.""" """Listens for reactions."""
self.client = client self.bot = bot
@commands.Cog.listener() @commands.Cog.listener()
async def on_reaction_add(self, reaction, user): async def on_reaction_add(self, reaction, user):
if user.bot == False: if user.bot == False:
message = reaction.message message = reaction.message
channel = message.channel 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: try:
fourInARowTheirTurn, piece = self.client.funcs.fiarReactionTest(channel,message,"#"+str(user.id)) connectFourTheirTurn, piece = self.bot.databaseFuncs.connectFourReactionTest(channel,message,"#"+str(user.id))
except: 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) 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: elif bedreNetflixMessage and addMovie:
moviePick = emojiToCommand(reaction.emoji) moviePick = emojiToCommand(reaction.emoji)
await message.delete() await message.delete()
@@ -30,7 +30,7 @@ class ReactionCog(commands.Cog):
imdbID = None imdbID = None
else: else:
imdbID = imdbIds[moviePick-1] imdbID = imdbIds[moviePick-1]
await self.client.bedreNetflix.addMovie(channel,imdbID) await self.bot.other.bedreNetflix.addMovie(channel,imdbID)
elif bedreNetflixMessage and not addMovie: elif bedreNetflixMessage and not addMovie:
showPick = emojiToCommand(reaction.emoji) showPick = emojiToCommand(reaction.emoji)
await message.delete() await message.delete()
@@ -38,9 +38,9 @@ class ReactionCog(commands.Cog):
imdbName = None imdbName = None
else: else:
imdbName = imdbIds[showPick-1] imdbName = imdbIds[showPick-1]
await self.client.bedreNetflix.addShow(channel,imdbName) await self.bot.other.bedreNetflix.addShow(channel,imdbName)
elif self.client.funcs.hangmanReactionTest(channel,message) and ord(reaction.emoji) in range(127462,127488): elif self.bot.databaseFuncs.hangmanReactionTest(channel,message) and ord(reaction.emoji) in range(127462,127488):
guess = chr(ord(reaction.emoji)-127397) guess = chr(ord(reaction.emoji)-127397)
await self.client.gameLoops.runHangman(channel,"#"+str(user.id),command="guess "+guess) await self.bot.games.gameLoops.runHangman(channel,"#"+str(user.id),command="guess "+guess)
def setup(client): def setup(bot):
client.add_cog(ReactionCog(client)) bot.add_cog(ReactionCog(bot))

67
cogs/StarWarsCog.py Normal file
View File

@@ -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))

View File

@@ -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))

View File

@@ -1,17 +1,11 @@
"""A collection of all Gwendolyn functions.""" """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"] __all__ = ["Games" , "Money", "LookupFuncs", "StarWars"]
from .miscFuncs import helloFunc, cap, imageFunc, logThis, findWikiPage, makeFiles, replaceMultiple, emojiToCommand
from .funcs import Funcs
from .games import Money, Games 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 .starWarsFuncs import StarWars
from .swfuncs import SwChar, SwDestiny, SwRoll

View File

@@ -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

View File

@@ -6,7 +6,7 @@ import discord
from shutil import copyfile from shutil import copyfile
from funcs import logThis, replaceMultiple from utils import replaceMultiple
from .blackjackDraw import DrawBlackjack from .blackjackDraw import DrawBlackjack
class Blackjack(): class Blackjack():
@@ -16,7 +16,7 @@ class Blackjack():
# Shuffles the blackjack cards # Shuffles the blackjack cards
def blackjackShuffle(self, decks, channel): 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: with open("resources/games/deckofCards.txt","r") as f:
deck = f.read() 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) self.bot.database["blackjack cards"].update_one({"_id":channel},{"$set":{"_id":channel,"cards":allDecks}},upsert=True)
# Creates hilo file # Creates hilo file
logThis("creating hilo doc for "+channel) self.bot.log("creating hilo doc for "+channel)
data = 0 data = 0
self.bot.database["hilo"].update_one({"_id":channel},{"$set":{"_id":channel,"hilo":data}},upsert=True) 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 # Calculates the value of a blackjack hand
def calcHandValue(self, hand : list): def calcHandValue(self, hand : list):
logThis("Calculating hand value") self.bot.log("Calculating hand value")
values = [] values = []
values.append(0) values.append(0)
@@ -58,13 +58,13 @@ class Blackjack():
if value <= 21: if value <= 21:
handValue = value handValue = value
logThis("Calculated "+str(hand)+" to be "+str(handValue)) self.bot.log("Calculated "+str(hand)+" to be "+str(handValue))
return handValue return handValue
# Draws a card from the deck # Draws a card from the deck
def drawCard(self, channel): 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] drawnCard = self.bot.database["blackjack cards"].find_one({"_id":channel})["cards"][0]
self.bot.database["blackjack cards"].update_one({"_id":channel},{"$pop":{"cards":-1}}) 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 # Goes to the next round and calculates some stuff
def blackjackContinue(self, channel): def blackjackContinue(self, channel):
logThis("Continuing blackjack game") self.bot.log("Continuing blackjack game")
game = self.bot.database["blackjack games"].find_one({"_id":channel}) game = self.bot.database["blackjack games"].find_one({"_id":channel})
done = False done = False
@@ -109,20 +109,20 @@ class Blackjack():
message = "All players are standing. The dealer now shows his cards and draws." message = "All players are standing. The dealer now shows his cards and draws."
if game["all standing"]: if game["all standing"]:
logThis("All are standing") self.bot.log("All are standing")
done = self.dealerDraw(channel) done = self.dealerDraw(channel)
message = "The dealer draws a card." message = "The dealer draws a card."
game = self.bot.database["blackjack games"].find_one({"_id":channel}) 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"]: for user in game["user hands"]:
try: try:
newUser, allStanding, preAllStanding = self.testIfStanding(game["user hands"][user],allStanding,preAllStanding,True) 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}}) self.bot.database["blackjack games"].update_one({"_id":channel},{"$set":{"user hands."+user:newUser}})
except: 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: if allStanding:
self.bot.database["blackjack games"].update_one({"_id":channel},{"$set":{"all standing":True}}) self.bot.database["blackjack games"].update_one({"_id":channel},{"$set":{"all standing":True}})
@@ -130,7 +130,7 @@ class Blackjack():
try: try:
self.draw.drawImage(channel) self.draw.drawImage(channel)
except: except:
logThis("Error drawing blackjack table (error code 1340)") self.bot.log("Error drawing blackjack table (error code 1340)")
if allStanding: if allStanding:
if done == False: if done == False:
@@ -141,10 +141,10 @@ class Blackjack():
return "", True, done return "", True, done
else: else:
if game["round"] == 1: 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: else:
firstRoundMessage = "" 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): def testIfStanding(self, hand,allStanding,preAllStanding,topLevel):
if hand["hit"] == False: if hand["hit"] == False:
@@ -209,19 +209,19 @@ class Blackjack():
return response + str(roundDone)[0] + str(game["round"]) return response + str(roundDone)[0] + str(game["round"])
else: else:
logThis(user+" is already standing") self.bot.log(user+" is already standing")
return "You can't hit when you're standing" return "You can't hit when you're standing"
else: else:
logThis(user+" has already hit this round") self.bot.log(user+" has already hit this round")
return "You've already hit this round" return "You've already hit this round"
else: 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" return "You can't hit before you see your cards"
else: else:
logThis(user+" didn't specify a hand") self.bot.log(user+" didn't specify a hand")
return "You need to specify a hand" return "You need to specify a hand"
else: 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" 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})) 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: else:
logThis(user+" doesn't have enough GwendoBucks") self.bot.log(user+" doesn't have enough GwendoBucks")
return "You don't have enough GwendoBucks","" return "You don't have enough GwendoBucks",""
else: 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","" return "You can only double down on the first round",""
else: else:
logThis(user+" is already standing") self.bot.log(user+" is already standing")
return "You can't double when you're standing","" return "You can't double when you're standing",""
else: else:
logThis(user+" has already hit this round") self.bot.log(user+" has already hit this round")
return "You've already hit this round","" return "You've already hit this round",""
else: 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","" return "You can't double down before you see your cards",""
else: else:
logThis(user+" didn't specify a hand") self.bot.log(user+" didn't specify a hand")
return "You need to specify which hand" return "You need to specify which hand"
else: 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","" return "You can't double when you're not in the game",""
# When players try to stand # When players try to stand
@@ -322,19 +322,19 @@ class Blackjack():
return response + str(roundDone)[0] + str(game["round"]) return response + str(roundDone)[0] + str(game["round"])
else: else:
logThis(user+" is already standing") self.bot.log(user+" is already standing")
return "You're already standing" return "You're already standing"
else: else:
logThis(user+" has already hit this round") self.bot.log(user+" has already hit this round")
return "You've already hit this round" return "You've already hit this round"
else: 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" return "You can't stand before you see your cards"
else: else:
logThis(user+" didn't specify a hand") self.bot.log(user+" didn't specify a hand")
return "You need to specify which hand" return "You need to specify which hand"
else: 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" return "You have to enter the game before you can stand"
# When players try to split # When players try to split
@@ -355,7 +355,7 @@ class Blackjack():
elif handNumber == 3: elif handNumber == 3:
hand = game["user hands"][user]["third hand"] hand = game["user hands"][user]["third hand"]
else: 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." return "You have to specify the hand you're hitting with."
if game["user hands"][user]["split"] == 1: if game["user hands"][user]["split"] == 1:
@@ -365,7 +365,7 @@ class Blackjack():
newHand = game["user hands"][user]["fourth hand"] newHand = game["user hands"][user]["fourth hand"]
otherHand = 4 otherHand = 4
else: 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.","" return "You have to specify the hand you're splitting.",""
if game["user hands"][user]["split"] < 3: 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})) 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: else:
logThis(user+" doesn't have enough GwendoBucks") self.bot.log(user+" doesn't have enough GwendoBucks")
return "You don't have enough GwendoBucks","" return "You don't have enough GwendoBucks",""
else: 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","" return "Your cards need to have the same value to split",""
else: 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","" return "You can only split on the first round",""
else: else:
logThis(user+" is already standing") self.bot.log(user+" is already standing")
return "You can't split when you're standing","" return "You can't split when you're standing",""
else: else:
logThis(user+" has already hit this round") self.bot.log(user+" has already hit this round")
return "You've already hit this round","" return "You've already hit this round",""
else: 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","" return "You can't split before you see your cards",""
else: 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","" return "You can only split 3 times",""
# Player enters the game and draws a hand # Player enters the game and draws a hand
def blackjackPlayerDrawHand(self,channel,user,bet): def blackjackPlayerDrawHand(self,channel,user,bet):
game = self.bot.database["blackjack games"].find_one({"_id":channel}) 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 game != None:
if user not in game["user hands"]: if user not in game["user hands"]:
@@ -481,32 +481,32 @@ class Blackjack():
self.bot.database["blackjack games"].update_one({"_id":channel}, self.bot.database["blackjack games"].update_one({"_id":channel},
{"$set":{"user hands."+user:newHand}}) {"$set":{"user hands."+user:newHand}})
logThis(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 self.bot.funcs.getName(user)+" entered the game" return f"{self.bot.databaseFuncs.getName(user)} entered the game with a bet of {bet}"
else: 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" return "You don't have enough GwendoBucks to place that bet"
else: 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" return "You can't bet a negative amount"
else: 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" return "The table is no longer open for bets"
else: 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." return "There's already a maximum of players at the table."
else: else:
logThis(user+" is already in the game") self.bot.log(user+" is already in the game")
return "You've already entered this game" return "You've already entered this game"
else: 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" return "There is no game going on in this channel"
# Starts a game of blackjack # Starts a game of blackjack
def blackjackStart(self,channel:str): def blackjackStart(self,channel:str):
game = self.bot.database["blackjack games"].find_one({"_id":channel}) 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: if game == None:
@@ -524,7 +524,7 @@ class Blackjack():
return "started" return "started"
else: 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." return "There's already a blackjack game going on. Try again in a few minutes."
# Ends the game and calculates winnings # Ends the game and calculates winnings
@@ -540,26 +540,23 @@ class Blackjack():
try: try:
for user in game["user hands"]: for user in game["user hands"]:
try:
winnings, netWinnings, reason = self.calcWinnings(game["user hands"][user],dealerValue,True,dealerBlackjack,dealerBusted) winnings, netWinnings, reason = self.calcWinnings(game["user hands"][user],dealerValue,True,dealerBlackjack,dealerBusted)
except:
logThis("Error calculating winnings for "+str(user)+" (error code 1312)")
if winnings < 0: if winnings < 0:
if winnings == -1: 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: 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: else:
if winnings == 1: 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: 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) self.bot.money.addMoney(user,netWinnings)
except: 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}) self.bot.database["blackjack games"].delete_one({"_id":channel})
@@ -567,7 +564,7 @@ class Blackjack():
def calcWinnings(self,hand, dealerValue, topLevel, dealerBlackjack, dealerBusted): def calcWinnings(self,hand, dealerValue, topLevel, dealerBlackjack, dealerBusted):
logThis("Calculating winnings") self.bot.log("Calculating winnings")
reason = "" reason = ""
bet = hand["bet"] bet = hand["bet"]
winnings = -1 * bet winnings = -1 * bet
@@ -637,7 +634,7 @@ class Blackjack():
return hand, handNumber return hand, handNumber
except: except:
logThis("Problem with getHandNumber() (error code 1322)") self.bot.log("Problem with getHandNumber() (error code 1322)")
def isRoundDone(self,game): def isRoundDone(self,game):
roundDone = True roundDone = True
@@ -662,14 +659,14 @@ class Blackjack():
# Loop of blackjack game rounds # Loop of blackjack game rounds
async def blackjackLoop(self,channel,gameRound,gameID): 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: with open("resources/games/oldImages/blackjack"+str(channel.id), "r") as f:
oldImage = await channel.fetch_message(int(f.read())) oldImage = await channel.fetch_message(int(f.read()))
new_message, allStanding, gamedone = self.blackjackContinue(str(channel.id)) new_message, allStanding, gamedone = self.blackjackContinue(str(channel.id))
if new_message != "": if new_message != "":
logThis(new_message,str(channel.id)) self.bot.log(new_message,str(channel.id))
await channel.send(new_message) await channel.send(new_message)
if gamedone == False: if gamedone == False:
await oldImage.delete() await oldImage.delete()
@@ -683,7 +680,7 @@ class Blackjack():
else: else:
await asyncio.sleep(120) await asyncio.sleep(120)
except: 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)}) 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 gameRound == realRound and realGameID == gameID:
if gamedone == False: 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) await self.blackjackLoop(channel,gameRound+1,gameID)
else: else:
try: try:
new_message = self.blackjackFinish(str(channel.id)) new_message = self.blackjackFinish(str(channel.id))
except: except:
logThis("Something fucked up (error code 1310)") self.bot.log("Something fucked up (error code 1310)")
await channel.send(new_message) await channel.send(new_message)
else: else:
logThis("Ending loop on round "+str(gameRound),str(channel.id)) self.bot.log("Ending loop on round "+str(gameRound),str(channel.id))
else: 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): async def parseBlackjack(self,content, ctx):
# Blackjack shuffle variables # Blackjack shuffle variables
blackjackMinCards = 50 blackjackMinCards = 50
blackjackDecks = 4 blackjackDecks = 4
channel = ctx.message.channel.id channel = ctx.channel_id
# Starts the game # Starts the game
if content == "": if content == "":
await ctx.send("Starting a new game of blackjack")
cardsLeft = 0 cardsLeft = 0
cards = self.bot.database["blackjack cards"].find_one({"_id":str(channel)}) cards = self.bot.database["blackjack cards"].find_one({"_id":str(channel)})
if cards != None: if cards != None:
@@ -722,15 +720,15 @@ class Blackjack():
# Shuffles if not enough cards # Shuffles if not enough cards
if cardsLeft < blackjackMinCards: if cardsLeft < blackjackMinCards:
self.blackjackShuffle(blackjackDecks,str(channel)) 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...") await ctx.channel.send("Shuffling the deck...")
new_message = self.blackjackStart(str(channel)) new_message = self.blackjackStart(str(channel))
if new_message == "started": if new_message == "started":
new_message = "Blackjack game started. Use \"!blackjack bet [amount]\" to enter the game within the next 30 seconds." new_message = "Blackjack game started. Use \"/blackjack bet [amount]\" to enter the game within the next 30 seconds."
await ctx.send(new_message) await ctx.channel.send(new_message)
oldImage = await ctx.send(file = discord.File("resources/games/blackjackTables/blackjackTable"+str(channel)+".png")) 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: with open("resources/games/oldImages/blackjack"+str(channel), "w") as f:
f.write(str(oldImage.id)) f.write(str(oldImage.id))
@@ -743,47 +741,47 @@ class Blackjack():
if len(game["user hands"]) == 0: if len(game["user hands"]) == 0:
gamedone = True 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"] gameID = game["gameID"]
# Loop of game rounds # Loop of game rounds
if gamedone == False: if gamedone == False:
logThis("!blackjack calling self.blackjackLoop()",str(channel)) self.bot.log("/blackjack calling self.blackjackLoop()",str(channel))
await self.blackjackLoop(ctx.message.channel,1,gameID) await self.blackjackLoop(ctx.channel,1,gameID)
else: else:
new_message = self.blackjackFinish(str(channel)) new_message = self.blackjackFinish(str(channel))
await ctx.send(new_message) await ctx.channel.send(new_message)
else: else:
await ctx.send(new_message) await ctx.channel.send(new_message)
# Entering game and placing bet # Entering game and placing bet
elif content.startswith("bet"): elif content.startswith("bet"):
commands = content.split(" ") commands = content.split(" ")
amount = int(commands[1]) 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) await ctx.send(response)
# Hitting # Hitting
elif content.startswith("hit"): elif content.startswith("hit"):
if content == "hit": if content == "hit":
response = self.blackjackHit(str(channel),"#"+str(ctx.message.author.id)) response = self.blackjackHit(str(channel),"#"+str(ctx.author.id))
else: else:
commands = content.split(" ") commands = content.split(" ")
try: try:
handNumber = int(commands[1]) handNumber = int(commands[1])
except: except:
handNumber = 0 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"): if response.startswith("accept"):
await ctx.message.add_reaction("👍") await ctx.send(f"{ctx.author.display_name} hit")
#try: #try:
if response[6] == "T": if response[6] == "T":
gameID = self.bot.database["blackjack games"].find_one({"_id":str(channel)})["gameID"] gameID = self.bot.database["blackjack games"].find_one({"_id":str(channel)})["gameID"]
logThis("Hit calling self.blackjackLoop()",str(channel)) self.bot.log("Hit calling self.blackjackLoop()",str(channel))
await self.blackjackLoop(ctx.message.channel,int(response[7:])+1,gameID) await self.blackjackLoop(ctx.channel,int(response[7:])+1,gameID)
#except: #except:
# logThis("Something fucked up (error code 1320)",str(channel)) # self.bot.log("Something fucked up (error code 1320)",str(channel))
else: else:
await ctx.send(response) await ctx.send(response)
@@ -791,24 +789,24 @@ class Blackjack():
# Standing # Standing
elif content.startswith("stand"): elif content.startswith("stand"):
if content == "hit": if content == "hit":
response = self.blackjackStand(str(channel),"#"+str(ctx.message.author.id)) response = self.blackjackStand(str(channel),"#"+str(ctx.author.id))
else: else:
commands = content.split(" ") commands = content.split(" ")
try: try:
handNumber = int(commands[1]) handNumber = int(commands[1])
except: except:
handNumber = 0 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"): if response.startswith("accept"):
await ctx.message.add_reaction("👍") await ctx.send(f"{ctx.author.display_name} is standing")
#try: #try:
if response[6] == "T": if response[6] == "T":
gameID = self.bot.database["blackjack games"].find_one({"_id":str(channel)})["gameID"] gameID = self.bot.database["blackjack games"].find_one({"_id":str(channel)})["gameID"]
logThis("Stand calling self.blackjackLoop()",str(channel)) self.bot.log("Stand calling self.blackjackLoop()",str(channel))
await self.blackjackLoop(ctx.message.channel,int(response[7:])+1,gameID) await self.blackjackLoop(ctx.channel,int(response[7:])+1,gameID)
#except: #except:
# logThis("Something fucked up (error code 1320)",str(channel)) # self.bot.log("Something fucked up (error code 1320)",str(channel))
else: else:
await ctx.send(response) await ctx.send(response)
@@ -819,17 +817,17 @@ class Blackjack():
handNumber = int(commands[1]) handNumber = int(commands[1])
except: except:
handNumber = 0 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) await ctx.send(response)
try: try:
if roundDone[0] == "T": if roundDone[0] == "T":
gameID = self.bot.database["blackjack games"].find_one({"_id":str(channel)})["gameID"] gameID = self.bot.database["blackjack games"].find_one({"_id":str(channel)})["gameID"]
logThis("Double calling self.blackjackLoop()",str(channel)) self.bot.log("Double calling self.blackjackLoop()",str(channel))
await self.blackjackLoop(ctx.message.channel,int(roundDone[1:])+1,gameID) await self.blackjackLoop(ctx.channel,int(roundDone[1:])+1,gameID)
except: except:
logThis("Something fucked up (error code 1320)",str(channel)) self.bot.log("Something fucked up (error code 1320)",str(channel))
# Splitting hand # Splitting hand
elif content.startswith("split"): elif content.startswith("split"):
@@ -838,17 +836,17 @@ class Blackjack():
handNumber = int(commands[1]) handNumber = int(commands[1])
except: except:
handNumber = 0 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) await ctx.send(response)
try: try:
if roundDone[0] == "T": if roundDone[0] == "T":
gameID = self.bot.database["blackjack games"].find_one({"_id":str(channel)})["gameID"] gameID = self.bot.database["blackjack games"].find_one({"_id":str(channel)})["gameID"]
logThis("Split calling self.blackjackLoop()",str(channel)) self.bot.log("Split calling self.blackjackLoop()",str(channel))
await self.blackjackLoop(ctx.message.channel,int(roundDone[1:])+1,gameID) await self.blackjackLoop(ctx.channel,int(roundDone[1:])+1,gameID)
except: except:
logThis("Something fucked up (error code 1320)") self.bot.log("Something fucked up (error code 1320)")
# Returning current hi-lo value # Returning current hi-lo value
elif content.startswith("hilo"): elif content.startswith("hilo"):
@@ -857,12 +855,12 @@ class Blackjack():
hilo = str(data["hilo"]) hilo = str(data["hilo"])
else: else:
hilo = "0" hilo = "0"
await ctx.send(hilo) await ctx.send(hilo, hidden=True)
# Shuffles the blackjack deck # Shuffles the blackjack deck
elif content.startswith("shuffle"): elif content.startswith("shuffle"):
self.blackjackShuffle(blackjackDecks,str(channel)) 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...") await ctx.send("Shuffling the deck...")
@@ -874,9 +872,9 @@ class Blackjack():
cardsLeft = len(cards["cards"]) cardsLeft = len(cards["cards"])
decksLeft = round(cardsLeft/52,1) 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: 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)") await ctx.send("I didn't quite understand that (error code 1301)")

View File

@@ -1,5 +1,4 @@
from PIL import Image, ImageDraw, ImageFont from PIL import Image, ImageDraw, ImageFont
from funcs import logThis
border = 100 border = 100
placement = [0,0] placement = [0,0]
@@ -10,11 +9,11 @@ class DrawBlackjack():
self.bot = bot self.bot = bot
def drawImage(self,channel): 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}) game = self.bot.database["blackjack games"].find_one({"_id":channel})
fnt = ImageFont.truetype('resources/futura-bold.ttf', 50) fnt = ImageFont.truetype('resources/fonts/futura-bold.ttf', 50)
fntSmol = ImageFont.truetype('resources/futura-bold.ttf', 40) fntSmol = ImageFont.truetype('resources/fonts/futura-bold.ttf', 40)
borderSmol = int(border/3.5) borderSmol = int(border/3.5)
table = Image.open("resources/games/blackjackTable.png") table = Image.open("resources/games/blackjackTable.png")
@@ -31,14 +30,14 @@ class DrawBlackjack():
else: else:
dealerHand = self.drawHand(game["dealer hand"],False,dealerBusted,dealerBlackjack) dealerHand = self.drawHand(game["dealer hand"],False,dealerBusted,dealerBlackjack)
except: 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) table.paste(dealerHand,(800-borderSmol,20-borderSmol),dealerHand)
for x in range(len(hands)): for x in range(len(hands)):
key, value = list(hands.items())[x] key, value = list(hands.items())[x]
key = self.bot.funcs.getName(key) key = self.bot.databaseFuncs.getName(key)
#logThis("Drawing "+key+"'s hand") #self.bot.log("Drawing "+key+"'s hand")
userHand = self.drawHand(value["hand"],False,value["busted"],value["blackjack"]) userHand = self.drawHand(value["hand"],False,value["busted"],value["blackjack"])
try: try:
if value["split"] == 3: if value["split"] == 3:
@@ -62,7 +61,7 @@ class DrawBlackjack():
else: else:
table.paste(userHand,(32-borderSmol+(384*placement[x]),680-borderSmol),userHand) table.paste(userHand,(32-borderSmol+(384*placement[x]),680-borderSmol),userHand)
except: except:
logThis("Error drawing player hands (error code 1341b)") self.bot.log("Error drawing player hands (error code 1341b)")
textWidth = fnt.getsize(key)[0] textWidth = fnt.getsize(key)[0]
if textWidth < 360: 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)+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) 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") table.save("resources/games/blackjackTables/blackjackTable"+channel+".png")
return return
def drawHand(self, hand, dealer, busted, blackjack): def drawHand(self, hand, dealer, busted, blackjack):
logThis("Drawing hand "+str(hand)+", "+str(busted)+", "+str(blackjack)) self.bot.log("Drawing hand "+str(hand)+", "+str(busted)+", "+str(blackjack))
fnt = ImageFont.truetype('resources/futura-bold.ttf', 200) fnt = ImageFont.truetype('resources/fonts/futura-bold.ttf', 200)
fnt2 = ImageFont.truetype('resources/futura-bold.ttf', 120) fnt2 = ImageFont.truetype('resources/fonts/futura-bold.ttf', 120)
length = len(hand) length = len(hand)
background = Image.new("RGBA", ((border*2)+691+(125*(length-1)),(border*2)+1065),(0,0,0,0)) background = Image.new("RGBA", ((border*2)+691+(125*(length-1)),(border*2)+1065),(0,0,0,0))
textImage = ImageDraw.Draw(background) textImage = ImageDraw.Draw(background)
@@ -114,7 +113,7 @@ class DrawBlackjack():
w, h = background.size w, h = background.size
textHeight = 290+border textHeight = 290+border
#logThis("Drawing busted/blackjack") #self.bot.log("Drawing busted/blackjack")
if busted: if busted:
textWidth = fnt.getsize("BUSTED")[0] textWidth = fnt.getsize("BUSTED")[0]
textImage.text((int(w/2)-int(textWidth/2)-10,textHeight+20-10),"BUSTED",fill=(0,0,0), font=fnt) 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)+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) 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) return background.resize((int(w/3.5),int(h/3.5)),resample=Image.BILINEAR)

View File

@@ -2,8 +2,7 @@ import random
import copy import copy
import math import math
from .fourInARowDraw import DrawFourInARow from .connectFourDraw import drawConnectFour
from funcs import logThis
AIScores = { AIScores = {
"middle": 3, "middle": 3,
@@ -20,14 +19,14 @@ rowCount = 6
columnCount = 7 columnCount = 7
easy = True easy = True
class FourInARow(): class connectFour():
def __init__(self,bot): def __init__(self,bot):
self.bot = bot self.bot = bot
self.draw = DrawFourInARow(bot) self.draw = drawConnectFour(bot)
# Starts the game # Starts the game
def fourInARowStart(self, channel, user, opponent): def connectFourStart(self, channel, user, opponent):
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: if game == None:
@@ -45,7 +44,7 @@ class FourInARow():
return "That difficulty doesn't exist", False, False, False, False return "That difficulty doesn't exist", False, False, False, False
except: except:
# Opponent is another player # Opponent is another player
opponent = self.bot.funcs.getID(opponent) opponent = self.bot.databaseFuncs.getID(opponent)
if opponent != None: if opponent != None:
difficulty = 5 difficulty = 5
diffText = "" diffText = ""
@@ -62,7 +61,7 @@ class FourInARow():
newGame = {"_id":channel,"board": board,"winner":0,"win direction":"", newGame = {"_id":channel,"board": board,"winner":0,"win direction":"",
"win coordinates":[0,0],"players":players,"turn":0,"difficulty":difficulty} "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) self.draw.drawImage(channel)
@@ -71,13 +70,13 @@ class FourInARow():
if players[0] == "Gwendolyn": if players[0] == "Gwendolyn":
gwendoTurn = True 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: 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 # Places a piece at the lowest available point in a specific column
def placePiece(self, channel : str,player : int,column : int): 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: if game != None:
board = game["board"] board = game["board"]
@@ -85,21 +84,21 @@ class FourInARow():
board = self.placeOnBoard(board,player,column) board = self.placeOnBoard(board,player,column)
if board != None: 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 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) won, winDirection, winCoordinates = self.isWon(board)
if won != 0: if won != 0:
gameWon = True gameWon = True
self.bot.database["4 in a row games"].update_one({"_id":channel},{"$set":{"winner":won}}) self.bot.database["connect 4 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["connect 4 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":{"win coordinates":winCoordinates}}) {"$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 winAmount = int(game["difficulty"])**2+5
if game["players"][won-1] != "Gwendolyn": if game["players"][won-1] != "Gwendolyn":
message += " Adding "+str(winAmount)+" GwendoBucks to their account." message += " Adding "+str(winAmount)+" GwendoBucks to their account."
@@ -108,12 +107,12 @@ class FourInARow():
message = "It's a draw!" message = "It's a draw!"
else: else:
gameWon = False 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 gwendoTurn = False
if game["players"][turn] == "Gwendolyn": if game["players"][turn] == "Gwendolyn":
logThis("It's Gwendolyn's turn") self.bot.log("It's Gwendolyn's turn")
gwendoTurn = True gwendoTurn = True
self.draw.drawImage(channel) self.draw.drawImage(channel)
@@ -139,19 +138,19 @@ class FourInARow():
return board return board
# Parses command # Parses command
def parseFourInARow(self, command, channel, user): def parseconnectFour(self, command, channel, user):
commands = command.split() commands = command.split()
if command == "" or command == " ": 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": elif commands[0] == "start":
# Starting a game # 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") 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 # Stopping the game
elif commands[0] == "stop": 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"]: if user in game["players"]:
return "Ending game.", False, False, True, False return "Ending game.", False, False, True, False
@@ -160,12 +159,21 @@ class FourInARow():
# Placing manually # Placing manually
elif commands[0] == "place": elif commands[0] == "place":
try: if len(commands) == 2:
return self.placePiece(channel,int(commands[1]),int(commands[2])-1) game = self.bot.database["connect 4 games"].find_one({"_id":channel})
except: turn = game["turn"]
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 user == game["players"][turn]:
piece = turn + 1
else: 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 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 \"/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 # Checks if someone has won the game and returns the winner
def isWon(self, board): def isWon(self, board):
@@ -226,9 +234,9 @@ class FourInARow():
return won, winDirection, winCoordinates return won, winDirection, winCoordinates
# Plays as the AI # Plays as the AI
async def fourInARowAI(self, channel): async def connectFourAI(self, channel):
logThis("Figuring out best move") self.bot.log("Figuring out best move")
game = self.bot.database["4 in a row games"].find_one({"_id":channel}) game = self.bot.database["connect 4 games"].find_one({"_id":channel})
board = game["board"] board = game["board"]
player = game["players"].index("Gwendolyn")+1 player = game["players"].index("Gwendolyn")+1
@@ -240,7 +248,7 @@ class FourInARow():
testBoard = self.placeOnBoard(testBoard,player,column) testBoard = self.placeOnBoard(testBoard,player,column)
if testBoard != None: if testBoard != None:
scores[column] = await self.minimax(testBoard,difficulty,player%2+1,player,-math.inf,math.inf,False) 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() possibleScores = scores.copy()

View File

@@ -1,16 +1,15 @@
import math import math
from PIL import Image, ImageDraw, ImageFont from PIL import Image, ImageDraw, ImageFont
from funcs import logThis
class DrawFourInARow(): class drawConnectFour():
def __init__(self, bot): def __init__(self, bot):
self.bot = bot self.bot = bot
# Draws the whole thing # Draws the whole thing
def drawImage(self, channel): def drawImage(self, channel):
logThis("Drawing four in a row board") self.bot.log("Drawing connect four board")
game = self.bot.database["4 in a row games"].find_one({"_id":channel}) game = self.bot.database["connect 4 games"].find_one({"_id":channel})
board = game["board"] board = game["board"]
@@ -34,7 +33,7 @@ class DrawFourInARow():
white = (255,255,255,160) white = (255,255,255,160)
winBarColor = (250,250,250,255) 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))] boardSize = [w-(2*(border+gridBorder)),h-(2*(border+gridBorder))]
placeGridSize = [math.floor(boardSize[0]/7),math.floor(boardSize[1]/6)] placeGridSize = [math.floor(boardSize[0]/7),math.floor(boardSize[1]/6)]
@@ -44,12 +43,12 @@ class DrawFourInARow():
if game["players"][0] == "Gwendolyn": if game["players"][0] == "Gwendolyn":
player1 = "Gwendolyn" player1 = "Gwendolyn"
else: else:
player1 = self.bot.funcs.getName(game["players"][0]) player1 = self.bot.databaseFuncs.getName(game["players"][0])
if game["players"][1] == "Gwendolyn": if game["players"][1] == "Gwendolyn":
player2 = "Gwendolyn" player2 = "Gwendolyn"
else: 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) 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)) 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")

View File

@@ -1,8 +1,6 @@
import asyncio import asyncio
import discord import discord
from funcs import logThis
class GameLoops(): class GameLoops():
def __init__(self,bot): def __init__(self,bot):
self.bot = bot self.bot = bot
@@ -16,43 +14,43 @@ class GameLoops():
for message in messages: for message in messages:
oldMessage = await channel.fetch_message(int(message)) oldMessage = await channel.fetch_message(int(message))
logThis("Deleting old message") self.bot.log("Deleting old message")
await oldMessage.delete() await oldMessage.delete()
except: except:
oldMessage = "" oldMessage = ""
return oldMessage return oldMessage
# Runs Four in a Row # Runs connect four
async def fiar(self, channel,command,user): async def connectFour(self, ctx, command, user = None, channelId = None):
try: if user is None:
response, showImage, deleteImage, gameDone, gwendoTurn = self.bot.fourInARow.parseFourInARow(command,str(channel.id),user) user = "#"+str(ctx.author.id)
except:
logThis("Error parsing command (error code 1410)")
await channel.send(response) if channelId is None:
logThis(response,str(channel.id)) 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 showImage:
if deleteImage: if deleteImage:
try: oldImage = await self.deleteMessage("connectFour"+channelId,ctx.channel)
oldImage = await self.deleteMessage("fourInARow"+str(channel.id),channel) oldImage = await ctx.channel.send(file = discord.File("resources/games/connect4Boards/board"+channelId+".png"))
except:
logThis("Error deleting message (error code 1401)")
oldImage = await channel.send(file = discord.File("resources/games/4InARowBoards/board"+str(channel.id)+".png"))
if gameDone == False: if gameDone == False:
if gwendoTurn: if gwendoTurn:
try: response, showImage, deleteImage, gameDone, gwendoTurn = await self.bot.games.connectFour.connectFourAI(channelId)
response, showImage, deleteImage, gameDone, gwendoTurn = await self.bot.fourInARow.fourInARowAI(str(channel.id)) await ctx.channel.send(response)
except: self.bot.log(response,channelId)
logThis("AI error (error code 1420)")
await channel.send(response)
logThis(response,str(channel.id))
if showImage: if showImage:
if deleteImage: if deleteImage:
await oldImage.delete() 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: 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)) f.write(str(oldImage.id))
try: try:
reactions = ["1","2","3","4","5","6","7"] reactions = ["1","2","3","4","5","6","7"]
@@ -60,28 +58,28 @@ class GameLoops():
await oldImage.add_reaction(reaction) await oldImage.add_reaction(reaction)
except: 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: 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)) f.write(str(oldImage.id))
try: try:
reactions = ["1","2","3","4","5","6","7"] reactions = ["1","2","3","4","5","6","7"]
for reaction in reactions: for reaction in reactions:
await oldImage.add_reaction(reaction) await oldImage.add_reaction(reaction)
except: 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: 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: 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())) oldImage = await channel.fetch_message(int(f.read()))
await oldImage.delete() await oldImage.delete()
except: except:
logThis("The old image was already deleted") self.bot.log("The old image was already deleted")
winner = game["winner"] winner = game["winner"]
difficulty = int(game["difficulty"]) difficulty = int(game["difficulty"])
@@ -90,16 +88,19 @@ class GameLoops():
if game["players"][winner-1].lower() != "gwendolyn": if game["players"][winner-1].lower() != "gwendolyn":
self.bot.money.addMoney(game["players"][winner-1].lower(),reward) 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: 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: except:
logThis("Error parsing command (error code 1701)") self.bot.log("Error parsing command (error code 1701)")
if response != "": if response != "":
if ctx is None:
await channel.send(response) await channel.send(response)
logThis(response,str(channel.id)) else:
await ctx.send(response)
self.bot.log(response,str(channel.id))
if showImage: if showImage:
if deleteImage: if deleteImage:
await self.deleteMessage("hangman"+str(channel.id),channel) await self.deleteMessage("hangman"+str(channel.id),channel)
@@ -124,47 +125,48 @@ class GameLoops():
emoji = chr(ord(letter)+127397) emoji = chr(ord(letter)+127397)
await message.add_reaction(emoji) await message.add_reaction(emoji)
except: except:
logThis("Image deleted before adding all reactions") self.bot.log("Image deleted before adding all reactions")
# Runs Hex # Runs Hex
async def runHex(self,channel,command,user): async def runHex(self,ctx,command,user):
channelId = ctx.channel_id
try: 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: 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 showImage:
if deleteImage: if deleteImage:
try: try:
oldImage = await self.deleteMessage("hex"+str(channel.id),channel) oldImage = await self.deleteMessage("hex"+str(channelId),ctx.channel)
except: except:
logThis("Error deleting old image (error code 1501)") self.bot.log("Error deleting old image (error code 1501)")
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 gwendoTurn and not gameDone: if gwendoTurn and not gameDone:
try: 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: except:
response, showImage, deleteImage, gameDone, gwendoTurn = "An AI error occured",False,False,False,False response, showImage, deleteImage, gameDone, gwendoTurn = "An AI error ocurred",False,False,False,False
logThis("AI error (error code 1520)") self.bot.log("AI error (error code 1520)")
await channel.send(response) await ctx.channel.send(response)
logThis(response,str(channel.id)) self.bot.log(response,str(channelId))
if showImage: if showImage:
if deleteImage: if deleteImage:
await oldImage.delete() 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: 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)) f.write(str(oldImage.id))
if gameDone: 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"] winner = game["winner"]
if winner != 0 and game["players"][0] != game["players"][1]: # player1 != player2 if winner != 0 and game["players"][0] != game["players"][1]: # player1 != player2
winnings = game["difficulty"]*10 winnings = game["difficulty"]*10
self.bot.money.addMoney(game["players"][winner-1].lower(),winnings) 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))

View File

@@ -1,7 +1,7 @@
from .invest import Invest from .invest import Invest
from .trivia import Trivia from .trivia import Trivia
from .blackjack import Blackjack from .blackjack import Blackjack
from .fourInARow import FourInARow from .connectFour import connectFour
from .gameLoops import GameLoops from .gameLoops import GameLoops
from .hangman import Hangman from .hangman import Hangman
from .hex import HexGame from .hex import HexGame
@@ -10,10 +10,10 @@ class Games():
def __init__(self, bot): def __init__(self, bot):
self.bot = bot self.bot = bot
bot.invest = Invest(bot) self.invest = Invest(bot)
bot.trivia = Trivia(bot) self.trivia = Trivia(bot)
bot.blackjack = Blackjack(bot) self.blackjack = Blackjack(bot)
bot.fourInARow = FourInARow(bot) self.connectFour = connectFour(bot)
bot.gameLoops = GameLoops(bot) self.gameLoops = GameLoops(bot)
bot.hangman = Hangman(bot) self.hangman = Hangman(bot)
bot.hex = HexGame(bot) self.hex = HexGame(bot)

View File

@@ -1,7 +1,6 @@
import json, urllib, datetime, string import json, urllib, datetime, string
from .hangmanDraw import DrawHangman 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=" 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: while "-" in word or "." in word:
with urllib.request.urlopen(apiUrl+apiKey) as p: with urllib.request.urlopen(apiUrl+apiKey) as p:
word = list(json.load(p)[0]["word"].upper()) 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) guessed = [False] * len(word)
gameID = datetime.datetime.now().strftime('%Y%m%d%H%M%S') 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} newGame = {"_id":channel,"player" : user,"guessed letters" : [],"word" : word,"game ID" : gameID,"misses" : 0,"guessed" : guessed}
@@ -30,8 +29,8 @@ class Hangman():
try: try:
self.draw.drawImage(channel) self.draw.drawImage(channel)
except: except:
logThis("Error drawing image (error code 1710)") self.bot.log("Error drawing image (error code 1710)")
return f"{self.bot.funcs.getName(user)} started game of hangman.", True, False, remainingLetters return f"{self.bot.databaseFuncs.getName(user)} started game of hangman.", True, False, remainingLetters
else: else:
return "There's already a Hangman game going on in the channel", False, False, [] return "There's already a Hangman game going on in the channel", False, False, []
@@ -74,7 +73,7 @@ class Hangman():
try: try:
self.draw.drawImage(channel) self.draw.drawImage(channel)
except: except:
logThis("Error drawing image (error code 1710)") self.bot.log("Error drawing image (error code 1710)")
if game["misses"] == 6: if game["misses"] == 6:
self.hangmanStop(channel) self.hangmanStop(channel)
@@ -99,7 +98,7 @@ class Hangman():
try: try:
return self.hangmanStart(channel,user) return self.hangmanStart(channel,user)
except: except:
logThis("Error starting game (error code 1730)") self.bot.log("Error starting game (error code 1730)")
elif command == "stop": elif command == "stop":
return self.hangmanStop(channel) return self.hangmanStop(channel)
elif command.startswith("guess "): elif command.startswith("guess "):
@@ -107,6 +106,6 @@ class Hangman():
try: try:
return self.hangmanGuess(channel,user,guess) return self.hangmanGuess(channel,user,guess)
except: except:
logThis("Error in guessing (Error Code 1720)") self.bot.log("Error in guessing (Error Code 1720)")
else: else:
return "I didn't understand that", False, False, [] return "I didn't understand that", False, False, []

View File

@@ -1,7 +1,6 @@
import math, random import math, random
from PIL import ImageDraw, Image, ImageFont from PIL import ImageDraw, Image, ImageFont
from funcs import logThis
circleDegrees = 360 circleDegrees = 360
circleSize = 120 circleSize = 120
@@ -23,8 +22,8 @@ letterLineDistance = 30
gallowx, gallowy = 360,600 gallowx, gallowy = 360,600
goldenRatio = 1-(1 / ((1 + 5 ** 0.5) / 2)) goldenRatio = 1-(1 / ((1 + 5 ** 0.5) / 2))
fnt = ImageFont.truetype('resources/comic-sans-bold.ttf', letterSize) fnt = ImageFont.truetype('resources/fonts/comic-sans-bold.ttf', letterSize)
smolfnt = ImageFont.truetype('resources/comic-sans-bold.ttf', textSize) smolfnt = ImageFont.truetype('resources/fonts/comic-sans-bold.ttf', textSize)
backgroundColor = (255,255,255,255) backgroundColor = (255,255,255,255)
@@ -213,7 +212,7 @@ class DrawHangman():
return background return background
def drawImage(self,channel): 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}) game = self.bot.database["hangman games"].find_one({"_id":channel})
random.seed(game["game ID"]) random.seed(game["game ID"])
@@ -222,24 +221,24 @@ class DrawHangman():
try: try:
gallow = self.drawGallows() gallow = self.drawGallows()
except: except:
logThis("Error drawing gallows (error code 1711)") self.bot.log("Error drawing gallows (error code 1711)")
try: try:
man = self.drawMan(game["misses"]) man = self.drawMan(game["misses"])
except: except:
logThis("Error drawing stick figure (error code 1712)") self.bot.log("Error drawing stick figure (error code 1712)")
random.seed(game["game ID"]) random.seed(game["game ID"])
try: try:
letterLines = self.drawLetterLines(game["word"],game["guessed"],game["misses"]) letterLines = self.drawLetterLines(game["word"],game["guessed"],game["misses"])
except: except:
logThis("error drawing letter lines (error code 1713)") self.bot.log("error drawing letter lines (error code 1713)")
random.seed(game["game ID"]) random.seed(game["game ID"])
try: try:
misses = self.drawMisses(game["guessed letters"],game["word"]) misses = self.drawMisses(game["guessed letters"],game["word"])
except: 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(gallow,(100,100),gallow)
background.paste(man,(300,210),man) background.paste(man,(300,210),man)

View File

@@ -3,7 +3,6 @@ import copy
import math import math
from .hexDraw import DrawHex from .hexDraw import DrawHex
from funcs import logThis
BOARDWIDTH = 11 BOARDWIDTH = 11
ALL_POSITIONS = [(i,j) for i in range(11) for j in range(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() commands = command.lower().split()
game = self.bot.database["hex games"].find_one({"_id":channel}) game = self.bot.database["hex games"].find_one({"_id":channel})
if command == "" or command == " ": 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": elif commands[0] == "start":
# Starting a game # 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") 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 return self.hexStart(channel,user,commands[1]) # commands[1] is the opponent
# If using a command with no game, return error # If using a command with no game, return error
@@ -48,7 +47,7 @@ class HexGame():
try: try:
return self.placeHex(channel,commands[1], user) return self.placeHex(channel,commands[1], user)
except: 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 # Undo
elif commands[0] == "undo": elif commands[0] == "undo":
@@ -60,7 +59,7 @@ class HexGame():
if user in players: if user in players:
opponent = (players.index(user) + 1) % 2 opponent = (players.index(user) + 1) % 2
self.bot.database["hex games"].update_one({"_id":channel},{"$set":{"winner":opponent + 1}}) 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: else:
return "You can't surrender when you're not a player.", False, False, False, False 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 return "You can only swap as the second player after the very first move.", False, False, False, False
else: 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 # Starts the game
def hexStart(self, channel, user, opponent): def hexStart(self, channel, user, opponent):
@@ -99,7 +98,7 @@ class HexGame():
int(opponent) int(opponent)
return "That difficulty doesn't exist", False, False, False, False return "That difficulty doesn't exist", False, False, False, False
except: except:
opponent = self.bot.funcs.getID(opponent) opponent = self.bot.databaseFuncs.getID(opponent)
if opponent == None: if opponent == None:
return "I can't find that user", False, False, False, False return "I can't find that user", False, False, False, False
else: else:
@@ -123,7 +122,7 @@ class HexGame():
gwendoTurn = True if players[0] == "Gwendolyn" else False gwendoTurn = True if players[0] == "Gwendolyn" else False
showImage = True 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: else:
return "There's already a hex game going on in this channel", False, False, False, False 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: if player == turn:
board = game["board"] 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 # Places on board
board = self.placeOnHexBoard(board,player,position) board = self.placeOnHexBoard(board,player,position)
@@ -154,17 +153,17 @@ class HexGame():
self.bot.database["hex games"].update_one({"_id":channel},{"$set":{"turn":turn}}) self.bot.database["hex games"].update_one({"_id":channel},{"$set":{"turn":turn}})
# Checking for a win # Checking for a win
logThis("Checking for win") self.bot.log("Checking for win")
winner = self.evaluateBoard(game["board"])[1] winner = self.evaluateBoard(game["board"])[1]
if winner == 0: # Continue with the game. if winner == 0: # Continue with the game.
gameWon = False 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! else: # Congratulations!
gameWon = True gameWon = True
self.bot.database["hex games"].update_one({"_id":channel},{"$set":{"winner":winner}}) 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": if game["players"][winner-1] != "Gwendolyn":
winAmount = game["difficulty"]*10 winAmount = game["difficulty"]*10
message += " Adding "+str(winAmount)+" GwendoBucks to their account." message += " Adding "+str(winAmount)+" GwendoBucks to their account."
@@ -175,7 +174,7 @@ class HexGame():
# Is it now Gwendolyn's turn? # Is it now Gwendolyn's turn?
gwendoTurn = False gwendoTurn = False
if game["players"][turn-1] == "Gwendolyn": if game["players"][turn-1] == "Gwendolyn":
logThis("It's Gwendolyn's turn") self.bot.log("It's Gwendolyn's turn")
gwendoTurn = True gwendoTurn = True
# Update the board # Update the board
@@ -188,15 +187,15 @@ class HexGame():
return message, False, False, False, False return message, False, False, False, False
else: else:
# Move out of turn # 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 return message, False, False, False, False
else: 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 return message, False, False, False, False
else: else:
return "There's no game in this channel", False, False, False, False 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): def placeOnHexBoard(self, board,player,position):
# Translates the position # Translates the position
position = position.lower() position = position.lower()
@@ -205,17 +204,17 @@ class HexGame():
column = ord(position[0]) - 97 # ord() translates from letter to number column = ord(position[0]) - 97 # ord() translates from letter to number
row = int(position[1:]) - 1 row = int(position[1:]) - 1
if column not in range(BOARDWIDTH) or row not in range(BOARDWIDTH): 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." return "Error. That position is out of bounds."
except: 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\"." return "Error. The position should be a letter followed by a number, e.g. \"e2\"."
# Place at the position # Place at the position
if board[row][column] == 0: if board[row][column] == 0:
board[row][column] = player board[row][column] = player
return board return board
else: 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." return "Error. You must place on an empty space."
# After your move, you have the option to undo get your turn back #TimeTravel # After your move, you have the option to undo get your turn back #TimeTravel
@@ -227,7 +226,7 @@ class HexGame():
turn = game["turn"] turn = game["turn"]
# You can only undo after your turn, which is the opponent's 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 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() lastMove = game["gameHistory"].pop()
game["board"][lastMove[0]][lastMove[1]] = 0 game["board"][lastMove[0]][lastMove[1]] = 0
@@ -252,7 +251,7 @@ class HexGame():
# Plays as the AI # Plays as the AI
def hexAI(self, channel): 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}) game = self.bot.database["hex games"].find_one({"_id":channel})
board = game["board"] 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) 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 # Testing a move and evaluating it
judgements[i] = minimaxHex(testBoard,difficulty,-math.inf,math.inf,GwenColor==2) 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 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? 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) chosenMove = (i // BOARDWIDTH , i % BOARDWIDTH)
""" """
placement = "abcdefghijk"[chosenMove[1]]+str(chosenMove[0]+1) 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") return self.placeHex(channel,placement, "Gwendolyn")
@@ -323,12 +322,12 @@ class HexGame():
Distance[v] = min(Distance[v], new_dist) Distance[v] = min(Distance[v], new_dist)
# After a hex has been visited, this is noted # After a hex has been visited, this is noted
visited.add(u) 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 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. 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 break
else: 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: if scores[player] == 0:
winner = player winner = player
break # We don't need to check the other player's score, if player1 won. 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 if maximizingPlayer: # red player predicts next move
maxEval = -math.inf maxEval = -math.inf
possiblePlaces = [i for i,v in enumerate(sum(board,[])) if v == 0] 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: for i in possiblePlaces:
testBoard = copy.deepcopy(board) testBoard = copy.deepcopy(board)
testBoard[i // BOARDWIDTH][i % BOARDWIDTH] = 1 # because maximizingPlayer is Red which is number 1 testBoard[i // BOARDWIDTH][i % BOARDWIDTH] = 1 # because maximizingPlayer is Red which is number 1
@@ -352,13 +351,13 @@ class HexGame():
maxEval = max(maxEval, evaluation) maxEval = max(maxEval, evaluation)
alpha = max(alpha, evaluation) alpha = max(alpha, evaluation)
if beta <= alpha: if beta <= alpha:
#logThis("Just pruned something!") #self.bot.log("Just pruned something!")
break break
return maxEval return maxEval
else: # blue player predicts next move else: # blue player predicts next move
minEval = math.inf minEval = math.inf
possiblePlaces = [i for i,v in enumerate(sum(board,[])) if v == 0] 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: for i in possiblePlaces:
testBoard = copy.deepcopy(board) testBoard = copy.deepcopy(board)
testBoard[i // BOARDWIDTH][i % BOARDWIDTH] = 2 # because minimizingPlayer is Blue which is number 2 testBoard[i // BOARDWIDTH][i % BOARDWIDTH] = 2 # because minimizingPlayer is Blue which is number 2
@@ -366,7 +365,7 @@ class HexGame():
minEval = min(minEval, evaluation) minEval = min(minEval, evaluation)
beta = min(beta, evaluation) beta = min(beta, evaluation)
if beta <= alpha: if beta <= alpha:
#logThis("Just pruned something!") #self.bot.log("Just pruned something!")
break break
return minEval return minEval

View File

@@ -1,7 +1,6 @@
import math import math
from PIL import Image, ImageDraw, ImageFont from PIL import Image, ImageDraw, ImageFont
from funcs import logThis
# Defining all the variables # Defining all the variables
CANVAS_WIDTH = 2400 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 HEXAGONHEIGHT = 1.5 * SIDELENGTH # not really the entire height, but the height difference between two layers
FONTSIZE = 45 FONTSIZE = 45
TEXTCOLOR = (0,0,0) TEXTCOLOR = (0,0,0)
fnt = ImageFont.truetype('resources/futura-bold.ttf', FONTSIZE) fnt = ImageFont.truetype('resources/fonts/futura-bold.ttf', FONTSIZE)
LINETHICKNESS = 15 LINETHICKNESS = 15
HEXTHICKNESS = 6 # This is half the width of the background lining between every hex 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) COLY_THICKNESS = COLHEXTHICKNESS * math.sin(math.pi/6)
# The Name display things: # The Name display things:
NAMESIZE = 60 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} X_NAME = {1:175, 2:CANVAS_WIDTH-100}
Y_NAME = {1:CANVAS_HEIGHT-150, 2:150} Y_NAME = {1:CANVAS_HEIGHT-150, 2:150}
NAMEHEXPADDING = 90 NAMEHEXPADDING = 90
@@ -41,7 +40,7 @@ class DrawHex():
self.bot = bot self.bot = bot
def drawBoard(self, channel): def drawBoard(self, channel):
logThis("Drawing empty Hex board") self.bot.log("Drawing empty Hex board")
# Creates the empty image # Creates the empty image
im = Image.new('RGB', size=(CANVAS_WIDTH, CANVAS_HEIGHT),color = BACKGROUND_COLOR) 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}) game = self.bot.database["hex games"].find_one({"_id":channel})
for p in [1,2]: 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 # Draw name
x = X_NAME[p] x = X_NAME[p]
x -= NAME_fnt.getsize(playername)[0] if p==2 else 0 # player2's name is right-aligned 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): def drawHexPlacement(self, channel,player,position):
FILEPATH = "resources/games/hexBoards/board"+channel+".png" 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 # Translates position
# We don't need to error-check, because the position is already checked in placeOnHexBoard() # We don't need to error-check, because the position is already checked in placeOnHexBoard()
@@ -151,7 +150,7 @@ class DrawHex():
# Save # Save
im.save(FILEPATH) im.save(FILEPATH)
except: 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): def drawSwap(self, channel):
FILEPATH = "resources/games/hexBoards/board"+channel+".png" FILEPATH = "resources/games/hexBoards/board"+channel+".png"
@@ -163,7 +162,7 @@ class DrawHex():
# Write player names and color # Write player names and color
for p in [1,2]: 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 = X_NAME[p]
x -= NAME_fnt.getsize(playername)[0] if p==2 else 0 # player2's name is right-aligned x -= NAME_fnt.getsize(playername)[0] if p==2 else 0 # player2's name is right-aligned
@@ -183,4 +182,4 @@ class DrawHex():
# Save # Save
im.save(FILEPATH) im.save(FILEPATH)
except: except:
logThis("Error drawing swap (error code 1542)") self.bot.log("Error drawing swap (error code 1542)")

View File

@@ -13,9 +13,9 @@ class Invest():
userInvestments = self.bot.database["investments"].find_one({"_id":user}) userInvestments = self.bot.database["investments"].find_one({"_id":user})
if userInvestments in [None,{}]: 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: 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()): for key, value in list(userInvestments["investments"].items()):
purchaseValue = value["purchased for"] purchaseValue = value["purchased for"]
@@ -60,7 +60,7 @@ class Invest():
newUser = {"_id":user,"investments":{stock : {"purchased" : buyAmount, "value at purchase" : stockPrice, "purchased for" : buyAmount}}} newUser = {"_id":user,"investments":{stock : {"purchased" : buyAmount, "value at purchase" : stockPrice, "purchased for" : buyAmount}}}
self.bot.database["investments"].insert_one(newUser) 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: else:
return f"{stock} is not traded on the american market." return f"{stock} is not traded on the american market."
else: else:
@@ -95,7 +95,7 @@ class Invest():
self.bot.database["investments"].update_one({"_id":user}, self.bot.database["investments"].update_one({"_id":user},
{"$unset":{"investments."+stock:""}}) {"$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: else:
return f"You don't have enough {stock} stocks to do that" return f"You don't have enough {stock} stocks to do that"
else: else:
@@ -122,7 +122,7 @@ class Invest():
#try: #try:
return self.buyStock(user,commands[1],int(commands[2])) return self.buyStock(user,commands[1],int(commands[2]))
#except: #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: else:
return "You must give both a stock name and an amount of gwendobucks you wish to spend." return "You must give both a stock name and an amount of gwendobucks you wish to spend."
@@ -132,6 +132,6 @@ class Invest():
try: try:
return self.sellStock(user,commands[1],int(commands[2])) return self.sellStock(user,commands[1],int(commands[2]))
except: 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: else:
return "You must give both a stock name and an amount of GwendoBucks you wish to sell stocks for." return "You must give both a stock name and an amount of GwendoBucks you wish to sell stocks for."

View File

@@ -1,5 +1,3 @@
from funcs import logThis
class Money(): class Money():
def __init__(self, bot): def __init__(self, bot):
@@ -8,7 +6,7 @@ class Money():
# Returns the account balance for a user # Returns the account balance for a user
def checkBalance(self, 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}) userData = self.database["users"].find_one({"_id":user})
@@ -18,19 +16,19 @@ class Money():
# Adds money to the account of a user # Adds money to the account of a user
def addMoney(self,user,amount): 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}) userData = self.database["users"].find_one({"_id":user})
if userData != None: if userData != None:
self.database["users"].update_one({"_id":user},{"$inc":{"money":amount}}) self.database["users"].update_one({"_id":user},{"$inc":{"money":amount}})
else: 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 # Transfers money from one user to another
def giveMoney(self,user,targetUser,amount): def giveMoney(self,user,targetUser,amount):
userData = self.database["users"].find_one({"_id":user}) userData = self.database["users"].find_one({"_id":user})
targetUser = self.bot.funcs.getID(targetUser) targetUser = self.bot.databaseFuncs.getID(targetUser)
if amount > 0: if amount > 0:
if targetUser != None: if targetUser != None:
@@ -38,16 +36,16 @@ class Money():
if userData["money"] >= amount: if userData["money"] >= amount:
self.addMoney(user,-1 * amount) self.addMoney(user,-1 * amount)
self.addMoney(targetUser,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: 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)" return "You don't have that many GwendoBucks (error code 1223b)"
else: 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)" return "You don't have that many GwendoBucks (error code 1223a)"
else: else:
logThis("They weren't in the system") self.bot.log("They weren't in the system")
return "The target doesn't exist" return "The target doesn't exist"
else: else:
logThis("They tried to steal") self.bot.log("They tried to steal")
return "Yeah, no. You can't do that" return "Yeah, no. You can't do that"

View File

@@ -2,8 +2,6 @@ import json
import urllib import urllib
import random import random
from funcs import logThis
class Trivia(): class Trivia():
def __init__(self, bot): def __init__(self, bot):
self.bot = bot self.bot = bot
@@ -13,13 +11,13 @@ class Trivia():
def triviaStart(self, channel : str): def triviaStart(self, channel : str):
question = self.bot.database["trivia questions"].find_one({"_id":channel}) 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: if question == None:
with urllib.request.urlopen("https://opentdb.com/api.php?amount=10&type=multiple") as response: with urllib.request.urlopen("https://opentdb.com/api.php?amount=10&type=multiple") as response:
data = json.loads(response.read()) 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 = data["results"][0]["incorrect_answers"]
answers.append(data["results"][0]["correct_answer"]) answers.append(data["results"][0]["correct_answer"])
random.shuffle(answers) random.shuffle(answers)
@@ -43,7 +41,7 @@ class Trivia():
return question, answers, correctAnswer return question, answers, correctAnswer
else: 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)", "", "" return "There's already a trivia question going on. Try again in like, a minute (error code 1106)", "", ""
# Lets players answer a trivia question # Lets players answer a trivia question
@@ -53,19 +51,19 @@ class Trivia():
if command in ["a","b","c","d"]: if command in ["a","b","c","d"]:
if question != None: if question != None:
if user not in question["players"]: 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}}) self.bot.database["trivia questions"].update_one({"_id":channel},{"$set":{"players."+user : command}})
return "Locked in "+user+"'s answer" return "Locked in "+user+"'s answer"
else: 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)" return user+" has already answered this question (error code 1105)"
else: 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)" return "There's no question right now (error code 1104)"
else: 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)" return "I didn't quite understand that (error code 1103)"
@@ -73,7 +71,7 @@ class Trivia():
def triviaCountPoints(self, channel : str): def triviaCountPoints(self, channel : str):
question = self.bot.database["trivia questions"].find_one({"_id":channel}) 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: if question != None:
for player, answer in question["players"].items(): for player, answer in question["players"].items():
@@ -82,6 +80,6 @@ class Trivia():
else: else:
logThis("Couldn't find the question (error code 1102)") self.bot.log("Couldn't find the question (error code 1102)")
return None return None

View File

@@ -1,5 +1,5 @@
"""Gwendolyn functions for looking things up.""" """Gwendolyn functions for looking things up."""
__all__ = ["spellFunc", "monsterFunc"] __all__ = ["LookupFuncs"]
from .lookupFuncs import spellFunc, monsterFunc from .lookupFuncs import LookupFuncs

View File

@@ -1,36 +1,39 @@
import math import math
#import discord
import json import json
from funcs import cap, logThis from utils import cap
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"]
# Calculates D&D stat modifier # Calculates D&D stat modifier
def modifier(statistic): def modifier(self, statistic):
mods = math.floor((statistic-10)/2) mods = math.floor((statistic-10)/2)
if mods >= 0: if mods >= 0:
mods = "+"+str(mods) mods = "+"+str(mods)
return(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"]
# Looks up a monster # Looks up a monster
def monsterFunc(command): def monsterFunc(self, command):
logThis("Looking up "+command) self.bot.log("Looking up "+command)
# 1-letter monsters don't exist # 1-letter monsters don't exist
if len(command) < 2: if len(command) < 2:
logThis("Monster name too short (error code 601)") self.bot.log("Monster name too short (error code 601)")
return("I don't know that monster... (error code 601)","","","","","") return("I don't know that monster... (error code 601)","","","","","")
else: else:
# Opens "mensters.json" # Opens "monsters.json"
data = json.load(open('resources/lookup/monsters.json', encoding = "utf8")) data = json.load(open('resources/lookup/monsters.json', encoding = "utf8"))
for monster in data: for monster in data:
if "name" in monster and str(command) == monster["name"]: if "name" in monster and str(command) == monster["name"]:
logThis("Found it!") self.bot.log("Found it!")
# Looks at the information about the monster and returns that information # Looks at the information about the monster and returns that information
# in seperate variables, allowing Gwendolyn to know where to seperate # in separate variables, allowing Gwendolyn to know where to separate
# the messages # the messages
if monster["subtype"] != "": if monster["subtype"] != "":
typs = (monster["type"]+" ("+monster["subtype"]+")") typs = (monster["type"]+" ("+monster["subtype"]+")")
@@ -39,10 +42,10 @@ def monsterFunc(command):
con_mod = math.floor((monster["constitution"]-10)/2) con_mod = math.floor((monster["constitution"]-10)/2)
hit_dice = monster["hit_dice"] hit_dice = monster["hit_dice"]
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"])+")") 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"])+")")
saving_throws = "" saving_throws = ""
for save in saves: for save in self.saves:
if save in monster: if save in monster:
if monster[save] >= 0: if monster[save] >= 0:
saving_throws += " "+cap(save[:3])+" +"+str(monster[save])+"," saving_throws += " "+cap(save[:3])+" +"+str(monster[save])+","
@@ -52,7 +55,7 @@ def monsterFunc(command):
saving_throws = "\n**Saving Throws**"+saving_throws[:-1] saving_throws = "\n**Saving Throws**"+saving_throws[:-1]
skills = "" skills = ""
for skill in abilities: for skill in self.abilities:
if skill in monster: if skill in monster:
if monster[skill] >= 0: if monster[skill] >= 0:
skills += " "+cap(skill.replace("_"," "))+" +"+str(monster[skill])+"," skills += " "+cap(skill.replace("_"," "))+" +"+str(monster[skill])+","
@@ -115,22 +118,22 @@ def monsterFunc(command):
text4 = (react) text4 = (react)
text5 = (leg_act) text5 = (leg_act)
logThis("Returning monster information") self.bot.log("Returning monster information")
return(str(command),text1,text2,text3,text4,text5) return(str(command),text1,text2,text3,text4,text5)
logThis("Monster not in database (error code 602)") self.bot.log("Monster not in database (error code 602)")
return("I don't know that monster... (error code 602)","","","","","") return("I don't know that monster... (error code 602)","","","","","")
# Looks up a spell # Looks up a spell
def spellFunc(command): def spellFunc(self, command):
logThis("Looking up "+command) self.bot.log("Looking up "+command)
# Opens "spells.json" # Opens "spells.json"
data = json.load(open('resources/lookup/spells.json', encoding = "utf8")) data = json.load(open('resources/lookup/spells.json', encoding = "utf8"))
if str(command) in data: if str(command) in data:
logThis("Returning spell information") 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"])) 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: else:
logThis("I don't know that spell (error code 501)") 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)" spell_output = "I don't think that's a spell (error code 501)"
logThis("Successfully ran !spell") self.bot.log("Successfully ran /spell")
return(spell_output) return(spell_output)

View File

@@ -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 ""

View File

@@ -1,8 +1,5 @@
"""Misc. functions for Gwendolyn.""" """Misc. functions for Gwendolyn."""
__all__ = ["Generators", "movieFunc","BedreNetflix","NerdShit"] __all__ = ["Other"]
from .bedreNetflix import BedreNetflix from .other import Other
from .generators import Generators
from .movie import movieFunc
from .nerdShit import NerdShit

View File

@@ -1,5 +1,4 @@
import requests, imdb, discord, json, math, time, asyncio import requests, imdb, discord, json, math, time, asyncio
from funcs import logThis
class BedreNetflix(): class BedreNetflix():
def __init__(self,bot): def __init__(self,bot):
@@ -14,7 +13,7 @@ class BedreNetflix():
#Returns a list of no more than 5 options when user requests a movie #Returns a list of no more than 5 options when user requests a movie
async def requestMovie(self, ctx, movieName): async def requestMovie(self, ctx, movieName):
logThis("Searching for "+movieName) self.bot.log("Searching for "+movieName)
movieList = imdb.IMDb().search_movie(movieName) movieList = imdb.IMDb().search_movie(movieName)
movies = [] movies = []
for movie in movieList: for movie in movieList:
@@ -41,7 +40,7 @@ class BedreNetflix():
messageText += "Error" messageText += "Error"
imdbIds.append(movie.movieID) 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) em = discord.Embed(title=messageTitle,description=messageText,colour=0x00FF00)
@@ -63,10 +62,10 @@ class BedreNetflix():
#Adds the requested movie to Bedre Netflix #Adds the requested movie to Bedre Netflix
async def addMovie(self,channel,imdbId): async def addMovie(self,channel,imdbId):
if imdbId == None: 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") await channel.send("Try searching for the IMDB id")
else: else:
logThis("Trying to add movie "+str(imdbId)) self.bot.log("Trying to add movie "+str(imdbId))
apiKey = self.bot.credentials.radarrKey apiKey = self.bot.credentials.radarrKey
response = requests.get(self.radarrURL+"movie/lookup/imdb?imdbId=tt"+imdbId+"&apiKey="+apiKey) response = requests.get(self.radarrURL+"movie/lookup/imdb?imdbId=tt"+imdbId+"&apiKey="+apiKey)
lookupData = response.json() lookupData = response.json()
@@ -81,16 +80,16 @@ class BedreNetflix():
if r.status_code == 201: if r.status_code == 201:
await channel.send(postData["title"]+" successfully added to Bedre Netflix") 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: 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: else:
await channel.send("Something went wrong") 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 #Returns a list of no more than 5 options when user requests a show
async def requestShow(self, ctx, showName): 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 movies = imdb.IMDb().search_movie(showName) #Replace with tvdb
shows = [] shows = []
for movie in movies: for movie in movies:
@@ -117,7 +116,7 @@ class BedreNetflix():
messageText += "Error" messageText += "Error"
imdbNames.append(show["title"]) 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) em = discord.Embed(title=messageTitle,description=messageText,colour=0x00FF00)
@@ -139,10 +138,10 @@ class BedreNetflix():
#Adds the requested show to Bedre Netflix #Adds the requested show to Bedre Netflix
async def addShow(self,channel,imdbName): async def addShow(self,channel,imdbName):
if imdbName == None: 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") await channel.send("Try searching for the IMDB id")
else: else:
logThis("Trying to add show "+str(imdbName)) self.bot.log("Trying to add show "+str(imdbName))
apiKey = self.bot.credentials.sonarrKey apiKey = self.bot.credentials.sonarrKey
response = requests.get(self.sonarrURL+"series/lookup?term="+imdbName.replace(" ","%20")+"&apiKey="+apiKey) response = requests.get(self.sonarrURL+"series/lookup?term="+imdbName.replace(" ","%20")+"&apiKey="+apiKey)
lookupData = response.json()[0] lookupData = response.json()[0]
@@ -157,16 +156,16 @@ class BedreNetflix():
if r.status_code == 201: if r.status_code == 201:
await channel.send(postData["title"]+" successfully added to Bedre Netflix") 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: 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: else:
await channel.send("Something went wrong") 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 #Generates a list of all torrents and returns formatted list and whether all torrents are downloaded
async def genDownloadList(self, showDM, showMovies, showShows, episodes): async def genDownloadList(self, showDM, showMovies, showShows, episodes):
logThis("Generating torrent list") self.bot.log("Generating torrent list")
titleWidth = 100 titleWidth = 100
message = [] message = []
allDownloaded = True allDownloaded = True
@@ -366,10 +365,10 @@ class BedreNetflix():
if messageText.startswith("```"): if messageText.startswith("```"):
if allDownloaded: if allDownloaded:
logThis("All torrents are downloaded") self.bot.log("All torrents are downloaded")
else: else:
messageText = messageText[:-3]+"\nThis message will not update anymore\n```" 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) await oldMessage.edit(content = messageText)
@@ -381,5 +380,5 @@ class BedreNetflix():
else: else:
await ctx.send(messageText) await ctx.send(messageText)
else: 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.")

View File

@@ -1,9 +1,9 @@
#import numpy as np
import random import random
from funcs import logThis
class Generators(): class Generators():
def __init__(self, bot):
self.bot = bot
# Returns a list of all letter pairs in the text # Returns a list of all letter pairs in the text
def make_pairs(self, corpus): def make_pairs(self, corpus):
for i in range(len(corpus)-1): for i in range(len(corpus)-1):
@@ -73,7 +73,7 @@ class Generators():
if new_letter == "\n": if new_letter == "\n":
done = True done = True
genName = "".join(chain) genName = "".join(chain)
logThis("Generated "+genName) self.bot.log("Generated "+genName[:-1])
# Returns the name # Returns the name
return(genName) return(genName)
@@ -86,7 +86,7 @@ class Generators():
# Picks one of each # Picks one of each
genTav = random.choice(fp)+" "+random.choice(sp)+random.choice(tp) genTav = random.choice(fp)+" "+random.choice(sp)+random.choice(tp)
logThis("Generated "+genTav) self.bot.log("Generated "+genTav)
# Return the name # Return the name
return(genTav) return(genTav)

View File

@@ -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","","")

View File

@@ -1,20 +1,19 @@
import discord, wolframalpha, requests, os import discord, wolframalpha, requests, os
from PIL import Image, ImageDraw, ImageFont from PIL import Image, ImageDraw, ImageFont
from funcs import logThis
class NerdShit(): class NerdShit():
def __init__(self,client): def __init__(self, bot):
"""Runs misc commands.""" """Runs misc commands."""
self.client = client self.bot = bot
async def wolfSearch(self,ctx,content): async def wolfSearch(self,ctx,content):
fnt = ImageFont.truetype('resources/times-new-roman.ttf', 20) fnt = ImageFont.truetype('resources/fonts/times-new-roman.ttf', 20)
async with ctx.message.channel.typing(): await ctx.defer()
logThis("Requesting data") self.bot.log("Requesting data")
client = wolframalpha.Client(self.client.credentials.wolfKey) bot = wolframalpha.Client(self.bot.credentials.wolfKey)
res = client.query(content) res = bot.query(content)
logThis("Processing data") self.bot.log("Processing data")
titles = [] titles = []
pods = [] pods = []
if int(res.numpods) > 0: if int(res.numpods) > 0:
@@ -27,6 +26,7 @@ class NerdShit():
podChunks = [pods[x:x+2] for x in range(0, len(pods), 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)] 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): for x, chunk in enumerate(podChunks):
width = 0 width = 0
@@ -72,10 +72,10 @@ class NerdShit():
wolfImage.save("resources/wolf.png") wolfImage.save("resources/wolf.png")
wolfImage.close() wolfImage.close()
await ctx.message.channel.send(file = discord.File("resources/wolf.png")) await ctx.channel.send(file = discord.File("resources/wolf.png"))
os.remove("resources/wolf.png") os.remove("resources/wolf.png")
os.remove("resources/wolfTemp.png") os.remove("resources/wolfTemp.png")
else: else:
logThis("No returned data") self.bot.log("No returned data")
await ctx.message.channel.send("Could not find anything relating to your search") await ctx.send("Could not find anything relating to your search")

151
funcs/other/other.py Normal file
View File

@@ -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()))

View File

@@ -1,5 +0,0 @@
"""Rolling dice."""
__all__ = ["roll_dice"]
from .dice import roll_dice

View File

@@ -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()))

View File

@@ -0,0 +1,5 @@
"""Functions related to the Star Wars TTRPG."""
__all__ = ["StarWars"]
from .starWars import StarWars

View File

@@ -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)

View File

@@ -1,25 +1,23 @@
import json import json
import string import string
from funcs import logThis class StarWarsChar():
class SwChar():
def __init__(self, bot): def __init__(self, bot):
self.bot = bot self.bot = bot
def getCharName(self, user : str): def getCharName(self, user : str):
logThis("Getting name for "+self.bot.funcs.getName(user)+"'s character") self.bot.log("Getting name for "+self.bot.databaseFuncs.getName(user)+"'s character")
userCharacter = self.bot.database["swcharacters"].find_one({"_id":user}) userCharacter = self.bot.database["starwars characters"].find_one({"_id":user})
if userCharacter != None: if userCharacter != None:
logThis("Name is "+userCharacter["Name"]) self.bot.log("Name is "+userCharacter["Name"])
return userCharacter["Name"] return userCharacter["Name"]
else: else:
logThis("Just using "+self.bot.funcs.getName(user)) self.bot.log("Just using "+self.bot.databaseFuncs.getName(user))
return self.bot.funcs.getName(user) return self.bot.databaseFuncs.getName(user)
def setUpDict(self, cmd : dict): 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): if bool(cmd):
keys = list(cmd) keys = list(cmd)
values = list(cmd.values()) values = list(cmd.values())
@@ -38,10 +36,10 @@ class SwChar():
result += "**" + key + "**" + ": " + str(values[x]) + " " result += "**" + key + "**" + ": " + str(values[x]) + " "
else: else:
result += "**" + key + "**" + ": " + str(values[x]) + "\n" result += "**" + key + "**" + ": " + str(values[x]) + "\n"
logThis("Returning a dictionary, but well formatted") self.bot.log("Returning a dictionary, but well formatted")
return result return result
else: else:
logThis("Couldn't find anything") self.bot.log("Couldn't find anything")
return "There doesn't seem to be anything here..." return "There doesn't seem to be anything here..."
def lookUp(self, data : dict, key : str, cmd : str = ""): def lookUp(self, data : dict, key : str, cmd : str = ""):
@@ -53,87 +51,87 @@ class SwChar():
if cmd == "": if cmd == "":
break break
logThis("Looking up "+key) self.bot.log("Looking up "+key)
if key in data: if key in data:
logThis(key+" exists") self.bot.log(key+" exists")
if cmd == "": if cmd == "":
if type(data[key]) is dict and key != "Weapons": if type(data[key]) is dict and key != "Weapons":
return self.setUpDict(data[key]) return self.setUpDict(data[key])
elif key == "Weapons": 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]): if bool(data[key]):
logThis("Found "+(", ".join(list(data[key])))) self.bot.log("Found "+(", ".join(list(data[key]))))
return ", ".join(list(data[key])) return ", ".join(list(data[key]))
else: else:
logThis("There is nothing here") self.bot.log("There is nothing here")
return "There doesn't seem to be anything here..." return "There doesn't seem to be anything here..."
else: else:
if str(data[key]) != "": if str(data[key]) != "":
logThis("Returning "+str(data[key])) self.bot.log("Returning "+str(data[key]))
return data[key] return data[key]
else: else:
logThis("There was nothing there") self.bot.log("There was nothing there")
return "There doesn't seem to be anything here" return "There doesn't seem to be anything here"
elif cmd[0] == '+': elif cmd[0] == '+':
logThis("Trying to add to "+key) self.bot.log("Trying to add to "+key)
try: try:
cmd = cmd[1:] cmd = cmd[1:]
while cmd[0] == ' ': while cmd[0] == ' ':
cmd = cmd[1:] cmd = cmd[1:]
except: except:
logThis("Yeah, that fucked up") self.bot.log("Yeah, that fucked up")
return "Can't do that" return "Can't do that"
if type(data[key]) is int: if type(data[key]) is int:
try: try:
newValue = data[key] + int(cmd) newValue = data[key] + int(cmd)
data[key] = newValue data[key] = newValue
logThis("Added "+cmd+" to "+key) self.bot.log("Added "+cmd+" to "+key)
return data return data
except: except:
logThis("Couldn't add "+cmd+" to "+key) self.bot.log("Couldn't add "+cmd+" to "+key)
return "Can't add that" return "Can't add that"
elif type(data[key]) is list: elif type(data[key]) is list:
try: try:
data[key].append(cmd) data[key].append(cmd)
logThis("Added "+cmd+" to "+key) self.bot.log("Added "+cmd+" to "+key)
return data return data
except: except:
logThis("Couldn't add "+cmd+" to "+key) self.bot.log("Couldn't add "+cmd+" to "+key)
return "Can't add that" return "Can't add that"
else: 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" return "Can't add that"
elif cmd[0] == '-': elif cmd[0] == '-':
logThis("Trying to remove/subtract from "+key) self.bot.log("Trying to remove/subtract from "+key)
try: try:
cmd = cmd[1:] cmd = cmd[1:]
while cmd[0] == ' ': while cmd[0] == ' ':
cmd = cmd[1:] cmd = cmd[1:]
except: except:
logThis("Yeah, that fucked up") self.bot.log("Yeah, that fucked up")
return "Can't do that" return "Can't do that"
if type(data[key]) is int: if type(data[key]) is int:
try: try:
newValue = data[key] - int(cmd) newValue = data[key] - int(cmd)
data[key] = newValue data[key] = newValue
logThis("Subtracted "+cmd+" from "+key) self.bot.log("Subtracted "+cmd+" from "+key)
return data return data
except: except:
logThis("Couldn't subtract "+cmd+" from "+key) self.bot.log("Couldn't subtract "+cmd+" from "+key)
return "Can't remove that" return "Can't remove that"
elif type(data[key]) is list: elif type(data[key]) is list:
try: try:
data[key].remove(cmd) data[key].remove(cmd)
logThis("Removed "+cmd+" from "+key) self.bot.log("Removed "+cmd+" from "+key)
return data return data
except: except:
logThis("Couldn't remove "+cmd+" from "+key) self.bot.log("Couldn't remove "+cmd+" from "+key)
return "Can't remove that" return "Can't remove that"
else: 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" return "Can't remove that"
else: else:
while cmd[0] == ' ': while cmd[0] == ' ':
@@ -147,7 +145,7 @@ class SwChar():
cmd = cmd[1:] cmd = cmd[1:]
if cmd == "": if cmd == "":
break break
logThis("Looking up "+newKey+" in "+key) self.bot.log("Looking up "+newKey+" in "+key)
lookUpResult = self.lookUp(data[key],newKey,cmd) lookUpResult = self.lookUp(data[key],newKey,cmd)
if type(lookUpResult) is dict: if type(lookUpResult) is dict:
data[key] = lookUpResult data[key] = lookUpResult
@@ -155,21 +153,21 @@ class SwChar():
else: else:
return lookUpResult return lookUpResult
elif type(data[key]) != list: elif type(data[key]) != list:
logThis("Trying to change "+key+" to "+cmd) self.bot.log("Trying to change "+key+" to "+cmd)
try: try:
cmd = type(data[key])(cmd) cmd = type(data[key])(cmd)
data[key] = cmd data[key] = cmd
logThis("Did that") self.bot.log("Did that")
return data return data
except: except:
logThis("No. That did not work") self.bot.log("No. That did not work")
return "Wrong data type" return "Wrong data type"
else: else:
logThis("Yeah, that didn't work") self.bot.log("Yeah, that didn't work")
return "Wrong data type" return "Wrong data type"
else: else:
logThis("Couldn't find "+key) self.bot.log("Couldn't find "+key)
logThis("Testing to see if it's a multi-word key") self.bot.log("Testing to see if it's a multi-word key")
cmd = key + " " + cmd cmd = key + " " + cmd
words = cmd.split(" ") words = cmd.split(" ")
search = "" search = ""
@@ -179,11 +177,11 @@ class SwChar():
search += " " + words[i] search += " " + words[i]
i += 1 i += 1
except: except:
logThis("It wasn't. "+search+" doesn't exist") self.bot.log("It wasn't. "+search+" doesn't exist")
return search + " doesn't exist" return search + " doesn't exist"
if search[0] == " ": if search[0] == " ":
search = search[1:] 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):] cmd = cmd[len(search):]
if cmd != "": if cmd != "":
@@ -193,7 +191,7 @@ class SwChar():
break break
if cmd == "": if cmd == "":
logThis("Returning "+search) self.bot.log("Returning "+search)
return self.setUpDict(data[search]) return self.setUpDict(data[search])
else: else:
newKey = cmd.split(" ")[0] newKey = cmd.split(" ")[0]
@@ -211,7 +209,7 @@ class SwChar():
return lookUpResult return lookUpResult
def characterSheet(self,character : dict): 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" divider = "--------------------\n"
name = character["Name"] name = character["Name"]
textf = "" textf = ""
@@ -241,7 +239,7 @@ class SwChar():
return name, text1+text2+"\n\n"+text3+divider+text4+"\n"+divider+text5+text6+text7+text8 return name, text1+text2+"\n\n"+text3+divider+text4+"\n"+divider+text5+text6+text7+text8
def charData(self,user : str,cmd : str): 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]) key = string.capwords(cmd.split(" ")[0])
cmd = cmd[len(key):] cmd = cmd[len(key):]
@@ -253,40 +251,40 @@ class SwChar():
if cmd == "": if cmd == "":
break 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: 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: if key in userCharacter:
logThis("Found it!") self.bot.log("Found it!")
if type(userCharacter[key]) is dict: if type(userCharacter[key]) is dict:
logThis("It's a dictionary!") self.bot.log("It's a dictionary!")
if cmd == "": if cmd == "":
logThis("Retrieving data") self.bot.log("Retrieving data")
if key == "Weapons": if key == "Weapons":
if bool(userCharacter[key]): if bool(userCharacter[key]):
logThis("Returning a list of weapons") self.bot.log("Returning a list of weapons")
return ", ".join(list(userCharacter[key])) return ", ".join(list(userCharacter[key]))
else: 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)" return "There doesn't seem to be anything there... (error code 941)"
else: else:
return self.setUpDict(userCharacter[key]) return self.setUpDict(userCharacter[key])
elif cmd[0] == "+": elif cmd[0] == "+":
logThis("Gonna add something!!!") self.bot.log("Gonna add something!!!")
try: try:
cmd = cmd[1:] cmd = cmd[1:]
while cmd[0] == ' ': while cmd[0] == ' ':
cmd = cmd[1:] cmd = cmd[1:]
except: 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)" return "Can't do that (error code 942)"
if (key == "Talents" or key == "Force-powers") and "," in cmd: if (key == "Talents" or key == "Force-powers") and "," in cmd:
cmd = cmd.split(",") cmd = cmd.split(",")
while cmd[1][0] == " ": while cmd[1][0] == " ":
cmd[1] = cmd[1][1:] cmd[1] = cmd[1][1:]
logThis("Adding "+cmd[0]+" to "+key) self.bot.log("Adding "+cmd[0]+" to "+key)
self.bot.database["swcharacters"].update_one({"_id":user}, self.bot.database["starwars characters"].update_one({"_id":user},
{"$set": {key+"."+cmd[0] : cmd[1]}}) {"$set": {key+"."+cmd[0] : cmd[1]}})
return cmd[0]+" added to "+key+" for " + userCharacter["Name"] return cmd[0]+" added to "+key+" for " + userCharacter["Name"]
@@ -294,55 +292,55 @@ class SwChar():
cmd = cmd.split(",") cmd = cmd.split(",")
while cmd[1][0] == " ": while cmd[1][0] == " ":
cmd[1] = cmd[1][1:] cmd[1] = cmd[1][1:]
logThis("Adding "+cmd[0]+" to "+key) self.bot.log("Adding "+cmd[0]+" to "+key)
try: 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])}}) {"$set": {key+"."+cmd[0] : int(cmd[1])}})
except: 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 "Wrong data type (error code 949)"
return cmd[0]+" added to "+key+" for " + userCharacter["Name"] return cmd[0]+" added to "+key+" for " + userCharacter["Name"]
elif key == "Weapons": 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) templates = json.load(f)
newWeapon = templates["Weapon"] newWeapon = templates["Weapon"]
logThis("Adding "+cmd+" to "+key) self.bot.log("Adding "+cmd+" to "+key)
self.bot.database["swcharacters"].update_one({"_id":user}, self.bot.database["starwars characters"].update_one({"_id":user},
{"$set": {key+"."+cmd : newWeapon}}) {"$set": {key+"."+cmd : newWeapon}})
return cmd+" added to weapons for " + userCharacter["Name"] return cmd+" added to weapons for " + userCharacter["Name"]
else: 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)" return "Can't add that (error code 947d)"
elif cmd[0] == "-": elif cmd[0] == "-":
logThis("Gonna subtract/remove something") self.bot.log("Gonna subtract/remove something")
try: try:
cmd = cmd[1:] cmd = cmd[1:]
while cmd[0] == ' ': while cmd[0] == ' ':
cmd = cmd[1:] cmd = cmd[1:]
except: except:
logThis("AAAAAAAAAAAA (error code 948)") self.bot.log("AAAAAAAAAAAA (error code 948)")
return "Can't do that (error code 948)" return "Can't do that (error code 948)"
if key == "Talents" or key == "Force-powers" or key == "Weapons" or key == "Obligations": 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]: if cmd in userCharacter[key]:
self.bot.database["swcharacters"].update_one({"_id":user}, self.bot.database["starwars characters"].update_one({"_id":user},
{"$unset": {cmd}}) {"$unset": {cmd}})
logThis("I did that") self.bot.log("I did that")
return cmd+" removed from "+key+" from "+userCharacter["Name"] return cmd+" removed from "+key+" from "+userCharacter["Name"]
else: 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)" return "Can't remove that (error code 946e)"
else: else:
logThis("Urgh! (error code 946d)") self.bot.log("Urgh! (error code 946d)")
return "Can't remove that (error code 946d)" return "Can't remove that (error code 946d)"
else: else:
logThis("Looking up "+cmd+" in "+key) self.bot.log("Looking up "+cmd+" in "+key)
if key == "Talents" or key == "Force-powers": if key == "Talents" or key == "Force-powers":
newKey = cmd newKey = cmd
newcmd = "" newcmd = ""
@@ -353,106 +351,106 @@ class SwChar():
lookUpResult = self.lookUp(userCharacter[key],newKey,newcmd) lookUpResult = self.lookUp(userCharacter[key],newKey,newcmd)
if type(lookUpResult) is dict: 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}}) {"$set": {key : lookUpResult}})
return "Changed " + userCharacter["Name"] + "'s " + key return "Changed " + userCharacter["Name"] + "'s " + key
else: else:
return lookUpResult return lookUpResult
else: else:
if cmd == "": if cmd == "":
logThis("Retrieving data") self.bot.log("Retrieving data")
if type(userCharacter[key]) is list: if type(userCharacter[key]) is list:
return key+":\n"+", ".join(userCharacter[key]) return key+":\n"+", ".join(userCharacter[key])
else: else:
return userCharacter[key] return userCharacter[key]
elif cmd[0] == '+': elif cmd[0] == '+':
logThis("Adding") self.bot.log("Adding")
try: try:
cmd = cmd[1:] cmd = cmd[1:]
while cmd[0] == ' ': while cmd[0] == ' ':
cmd = cmd[1:] cmd = cmd[1:]
except: except:
logThis("Error message (error code 948)") self.bot.log("Error message (error code 948)")
return "Can't do that (error code 948)" return "Can't do that (error code 948)"
if type(userCharacter[key]) is int: if type(userCharacter[key]) is int:
try: try:
logThis("Adding "+cmd+" to "+key) self.bot.log("Adding "+cmd+" to "+key)
self.bot.database["swcharacters"].update_one({"_id":user}, self.bot.database["starwars characters"].update_one({"_id":user},
{"$inc": {key : int(cmd)}}) {"$inc": {key : int(cmd)}})
return "Added " + cmd + " to " + userCharacter["Name"] + "'s " + key return "Added " + cmd + " to " + userCharacter["Name"] + "'s " + key
except: except:
logThis("BITCH SANDWICH (error code 947c)") self.bot.log("BITCH SANDWICH (error code 947c)")
return "Can't add that (error code 947c)" return "Can't add that (error code 947c)"
elif type(userCharacter[key]) is list: elif type(userCharacter[key]) is list:
try: try:
logThis("Adding "+cmd+" to "+key) self.bot.log("Adding "+cmd+" to "+key)
self.bot.database["swcharacters"].update_one({"_id":user}, self.bot.database["starwars characters"].update_one({"_id":user},
{"$push": {key : cmd}}) {"$push": {key : cmd}})
return "Added " + cmd + " to " + userCharacter["Name"] + "'s " + key return "Added " + cmd + " to " + userCharacter["Name"] + "'s " + key
except: except:
logThis("tstststststs (error code 947b)") self.bot.log("tstststststs (error code 947b)")
return "Can't add that (error code 947b)" return "Can't add that (error code 947b)"
else: else:
logThis("Help (error code 947a)") self.bot.log("Help (error code 947a)")
return "Can't add that (error code 947a)" return "Can't add that (error code 947a)"
elif cmd[0] == '-': elif cmd[0] == '-':
logThis("Removing/subtracting") self.bot.log("Removing/subtracting")
try: try:
cmd = cmd[1:] cmd = cmd[1:]
while cmd[0] == ' ': while cmd[0] == ' ':
cmd = cmd[1:] cmd = cmd[1:]
except: except:
logThis("lalalala (error code 948)") self.bot.log("lalalala (error code 948)")
return "Can't do that (error code 948)" return "Can't do that (error code 948)"
if type(userCharacter[key]) is int: if type(userCharacter[key]) is int:
try: try:
logThis("Subtracting "+cmd+" from "+key) self.bot.log("Subtracting "+cmd+" from "+key)
self.bot.database["swcharacters"].update_one({"_id":user}, self.bot.database["starwars characters"].update_one({"_id":user},
{"$inc": {key : -int(cmd)}}) {"$inc": {key : -int(cmd)}})
return "Subtracted " + cmd + " from " + userCharacter["Name"] + "'s " + key return "Subtracted " + cmd + " from " + userCharacter["Name"] + "'s " + key
except: 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)" return "Can't remove that (error code 946c)"
elif type(userCharacter[key]) is list: elif type(userCharacter[key]) is list:
try: try:
logThis("removing "+cmd+" from "+key) self.bot.log("removing "+cmd+" from "+key)
try: try:
self.bot.database["swcharacters"].update_one({"_id":user}, self.bot.database["starwars characters"].update_one({"_id":user},
{"$pull": {key : cmd}}) {"$pull": {key : cmd}})
except: 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 "Not in list (error code 944b)"
return "Removed " + cmd + " from " + userCharacter["Name"] + "'s " + key return "Removed " + cmd + " from " + userCharacter["Name"] + "'s " + key
except: except:
logThis("nah (error code 946b)") self.bot.log("nah (error code 946b)")
return "Can't remove that (error code 946b)" return "Can't remove that (error code 946b)"
else: else:
logThis("nyope (error code 946a)") self.bot.log("nyope (error code 946a)")
return "Can't remove that (error code 946a)" return "Can't remove that (error code 946a)"
else: else:
logThis("Changing "+key+" to "+cmd) self.bot.log("Changing "+key+" to "+cmd)
if type(userCharacter[key]) is int: if type(userCharacter[key]) is int:
try: try:
self.bot.database["swcharacters"].update_one({"_id":user}, self.bot.database["starwars characters"].update_one({"_id":user},
{"$set": {key : int(cmd)}}) {"$set": {key : int(cmd)}})
except: 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)" return "Can't do that (error code 945b)"
elif type(userCharacter[key]) is str: 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}}) {"$set": {key : cmd}})
else: 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 "Can't do that (error code 945a)"
return "Changed " + userCharacter["Name"] + "'s " + key +" to " + cmd return "Changed " + userCharacter["Name"] + "'s " + key +" to " + cmd
else: 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)" return "Couldn't find that data. Are you sure you spelled it correctly? (error code 944)"
else: else:
logThis(user+" doesn't have a character (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 !swchar (error code 943)" return "You don't have a character. You can make one with /starwarscharacter (error code 943)"
def replaceSpaces(self,cmd : str): 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"] 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) 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 == " ": if cmd == " ":
cmd = "" cmd = ""
@@ -492,29 +490,29 @@ class SwChar():
text1, text2 = self.characterSheet(userCharacter) text1, text2 = self.characterSheet(userCharacter)
return text1, self.replaceWithSpaces(text2) return text1, self.replaceWithSpaces(text2)
else: else:
logThis("Makin' a character for "+self.bot.funcs.getName(user)) self.bot.log("Makin' a character for "+self.bot.databaseFuncs.getName(user))
with open("resources/starWars/swtemplates.json", "r") as f: with open("resources/starWars/starwarstemplates.json", "r") as f:
templates = json.load(f) templates = json.load(f)
newChar = templates["Character"] newChar = templates["Character"]
newChar["_id"] = user newChar["_id"] = user
self.bot.database["swcharacters"].insert_one(newChar) self.bot.database["starwars characters"].insert_one(newChar)
return "", "Character for " + self.bot.funcs.getName(user) + " created" return "", "Character for " + self.bot.databaseFuncs.getName(user) + " created"
else: else:
if cmd == "Purge": if cmd == "Purge":
logThis("Deleting "+self.bot.funcs.getName(user)+"'s character") self.bot.log("Deleting "+self.bot.databaseFuncs.getName(user)+"'s character")
self.bot.database["swcharacters"].delete_one({"_id":user}) self.bot.database["starwars characters"].delete_one({"_id":user})
return "", "Character for " + self.bot.funcs.getName(user) + " deleted" return "", "Character for " + self.bot.databaseFuncs.getName(user) + " deleted"
else: else:
return "", self.replaceWithSpaces(str(self.charData(user,cmd))) return "", self.replaceWithSpaces(str(self.charData(user,cmd)))
def lightsaberChar(self,user : str): 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: if userCharacter != None:
return userCharacter["Lightsaber-characteristic"] return userCharacter["Lightsaber-characteristic"]
def userHasChar(self,user : str): 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 return userCharacter != None

View File

@@ -1,46 +1,44 @@
from funcs import logThis class StarWarsDestiny():
class SwDestiny():
def __init__(self, bot): def __init__(self, bot):
self.bot = bot self.bot = bot
def destinyNew(self, num : int): def destinyNew(self, num : int):
logThis("Creating a new destiny pool with "+str(num)+" players") self.bot.log("Creating a new destiny pool with "+str(num)+" players")
roll, diceResults = self.bot.swroll.roll(0,0,0,0,0,0,num) roll, diceResults = self.bot.starwarsroll.roll(0,0,0,0,0,0,num)
roll = "".join(sorted(roll)) roll = "".join(sorted(roll))
with open("resources/starWars/destinyPoints.txt","wt") as f: with open("resources/starWars/destinyPoints.txt","wt") as f:
f.write(roll) 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): def destinyUse(self, user : str):
with open("resources/starWars/destinyPoints.txt","rt") as f: with open("resources/starWars/destinyPoints.txt","rt") as f:
points = f.read() points = f.read()
if user == "Nikolaj": 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: if 'B' in points:
points = points.replace("B","L",1) points = points.replace("B","L",1)
points = "".join(sorted(points)) points = "".join(sorted(points))
with open("resources/starWars/destinyPoints.txt","wt") as f: with open("resources/starWars/destinyPoints.txt","wt") as f:
f.write(points) f.write(points)
logThis("Did it") self.bot.log("Did it")
return "Used a dark side destiny point. Destiny pool is now:\n"+self.bot.swroll.resultToEmoji(points) return "Used a dark side destiny point. Destiny pool is now:\n"+self.bot.starwarsroll.resultToEmoji(points)
else: 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" return "No dark side destiny points"
else: 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: if 'L' in points:
points = points.replace("L","B",1) points = points.replace("L","B",1)
points = "".join(sorted(points)) points = "".join(sorted(points))
with open("resources/starWars/destinyPoints.txt","wt") as f: with open("resources/starWars/destinyPoints.txt","wt") as f:
f.write(points) f.write(points)
logThis("Did it") self.bot.log("Did it")
return "Used a light side destiny point. Destiny pool is now:\n"+self.bot.swroll.resultToEmoji(points) return "Used a light side destiny point. Destiny pool is now:\n"+self.bot.starwarsroll.resultToEmoji(points)
else: 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" return "No light side destiny points"
def parseDestiny(self, user : str, cmd : str): def parseDestiny(self, user : str, cmd : str):
@@ -52,9 +50,9 @@ class SwDestiny():
if cmd == "": if cmd == "":
logThis("Retrieving destiny pool info") self.bot.log("Retrieving destiny pool info")
with open("resources/starWars/destinyPoints.txt","rt") as f: with open("resources/starWars/destinyPoints.txt","rt") as f:
return self.bot.swroll.resultToEmoji(f.read()) return self.bot.starwarsroll.resultToEmoji(f.read())
else: else:
commands = cmd.upper().split(" ") commands = cmd.upper().split(" ")
if commands[0] == "N": if commands[0] == "N":

View File

@@ -3,12 +3,10 @@ import re
import string import string
import json import json
from funcs import logThis with open("resources/starWars/starwarsskills.json", "r") as f:
with open("resources/starWars/swskills.json", "r") as f:
skillData = json.load(f) skillData = json.load(f)
class SwRoll(): class StarWarsRoll():
def __init__(self, bot): def __init__(self, bot):
self.bot = bot self.bot = bot
@@ -55,7 +53,7 @@ class SwRoll():
# Lets dice cancel each other out # Lets dice cancel each other out
def simplify(self, result : str): def simplify(self, result : str):
logThis("Simplifying "+result) self.bot.log("Simplifying "+result)
simp = "" simp = ""
success = (result.count('S') + result.count('R')) - (result.count('F') + result.count('D')) success = (result.count('S') + result.count('R')) - (result.count('F') + result.count('D'))
advantage = result.count('A') - result.count('H') advantage = result.count('A') - result.count('H')
@@ -173,21 +171,21 @@ class SwRoll():
emoji = "" emoji = ""
for char in result: for char in result:
if char == 'S': if char == 'S':
emoji += "<:success:690971244971163718> " emoji += "<:success:826026925280854026> "
elif char == 'A': elif char == 'A':
emoji += "<:advantage:690970761611051079> " emoji += "<:advantage:826026925515604009> "
elif char == 'R': elif char == 'R':
emoji += "<:swtriumph:690971267486187643> " emoji += "<:triumph:826026925319127070> "
elif char == 'F': elif char == 'F':
emoji += "<:failure:690970957786906664> " emoji += "<:failure:826026925288980511> "
elif char == 'H': elif char == 'H':
emoji += "<:threat:690971009469382656> " emoji += "<:threat:826026925280985108> "
elif char == 'D': elif char == 'D':
emoji += "<:despair:690971200163414238> " emoji += "<:despair:826026925272203294> "
elif char == 'L': elif char == 'L':
emoji += "<:light:691010089905029171>" emoji += "<:light:826026925059211295>"
elif char == 'B': elif char == 'B':
emoji += "<:dark:691010101901000852>" emoji += "<:dark:826026925289373717>"
return emoji return emoji
@@ -225,8 +223,8 @@ class SwRoll():
# Rolls for obligation # Rolls for obligation
def obligationRoll(self): def obligationRoll(self):
logThis("Rolling for obligation") self.bot.log("Rolling for obligation")
data = self.bot.database["swcharacters"] data = self.bot.database["starwarscharacters"]
table = [] table = []
@@ -297,7 +295,7 @@ class SwRoll():
cmd = re.sub(' +',' ',cmd.upper()) + " " cmd = re.sub(' +',' ',cmd.upper()) + " "
if cmd[0] == " ": if cmd[0] == " ":
cmd = cmd[1:] cmd = cmd[1:]
cmd = self.bot.swchar.replaceSpaces(string.capwords(cmd)) cmd = self.bot.starwarschar.replaceSpaces(string.capwords(cmd))
commands = cmd.split(" ") commands = cmd.split(" ")
if commands[0] == "": if commands[0] == "":
rollParameters = [1,0,3,0,0,0,0] rollParameters = [1,0,3,0,0,0,0]
@@ -308,39 +306,39 @@ class SwRoll():
try: try:
return self.obligationRoll() return self.obligationRoll()
except: except:
logThis("Obligation fucked up (error code 911)") self.bot.log("Obligation fucked up (error code 911)")
return "An error occured (error code 911)" return "An error ocurred (error code 911)"
elif string.capwords(commands[0]) in skillData: elif string.capwords(commands[0]) in skillData:
logThis("Oh look! This guy has skills!") self.bot.log("Oh look! This guy has skills!")
if self.bot.swchar.userHasChar: if self.bot.starwarschar.userHasChar:
logThis("They have a character. That much we know") self.bot.log("They have a character. That much we know")
skillLevel = self.bot.swchar.charData(user,"Skills " + string.capwords(commands[0])) skillLevel = self.bot.starwarschar.charData(user,"Skills " + string.capwords(commands[0]))
if string.capwords(commands[0]) == "Lightsaber": if string.capwords(commands[0]) == "Lightsaber":
logThis("The skill is lightsaber") self.bot.log("The skill is lightsaber")
charLevel = self.bot.swchar.charData(user,"Characteristics " + self.bot.swchar.lightsaberChar(user)) charLevel = self.bot.starwarschar.charData(user,"Characteristics " + self.bot.starwarschar.lightsaberChar(user))
else: 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) abilityDice = abs(charLevel-skillLevel)
proficiencyDice = min(skillLevel,charLevel) proficiencyDice = min(skillLevel,charLevel)
commands = [str(abilityDice)] + [str(proficiencyDice)] + commands[1:] commands = [str(abilityDice)] + [str(proficiencyDice)] + commands[1:]
logThis("Converted skill to dice") self.bot.log("Converted skill to dice")
else: else:
logThis("Okay, no they don't i guess (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 !swchar (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"]: 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": if string.capwords(commands[0]) == "Ranged":
return "Did you mean \"Ranged - Heavy\" or \"Ranged - Light\" (error code 913)" return "Did you mean \"Ranged - Heavy\" or \"Ranged - Light\" (error code 913)"
else: else:
return "Did you mean \"Piloting - Planetary\" or \"Piloting - Space\" (error code 913)" return "Did you mean \"Piloting - Planetary\" or \"Piloting - Space\" (error code 913)"
try: try:
logThis("Converting commands to dice") self.bot.log("Converting commands to dice")
for x, command in enumerate(commands): for x, command in enumerate(commands):
if command != "": if command != "":
command = command.upper() command = command.upper()
@@ -361,17 +359,17 @@ class SwRoll():
else: else:
rollParameters[x] = int(command) rollParameters[x] = int(command)
except: 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)" 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]) rollResults, diceResults = self.roll(rollParameters[0],rollParameters[1],rollParameters[2],rollParameters[3],rollParameters[4],rollParameters[5],rollParameters[6])
simplified = self.simplify(rollResults) 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 == "": if simplified == "":
return name + " rolls: " + "\n" + self.diceResultToEmoji(diceResults) + "\nEverything cancels out!" return name + " rolls: " + "\n" + self.diceResultToEmoji(diceResults) + "\nEverything cancels out!"

View File

@@ -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

View File

@@ -31,16 +31,19 @@ There are no rules for which emoji to use where, but here's some inspiration:
# Terminology # 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. 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. **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. **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
## Code Style ## 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 ### Documentation
+ Comment lines should not exede 72 characters. + 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 ## Codebase Management
### Folders ### Folders
+ `cogs/` contains the command cogs. + `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. + `resources/` contains the images, lookup databases, fonts etc. that the rest of the code uses.
### Important files ### Important files
@@ -94,15 +97,16 @@ The `Command` methods in cogs should only exist to perform small tasks or call c
## Logging ## Logging
Things you should know about the 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. + 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 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. + 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. + 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 `DEBUG` are not printed.
+ Logs of level `ERROR` should only be created in the `on_command_error()` or `Command.error()` functions. + Logs of level `ERROR` should only be created in the `on_command_error()` or `Command.error()` functions.
### Logging rules ### 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. 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.

View File

@@ -99,7 +99,7 @@
1340 - Error in drawing blackjack table 1340 - Error in drawing blackjack table
1341 - Error in drawHand() 1341 - Error in drawHand()
14 - Four in a row 14 - connect four
1400 - Unspecified error 1400 - Unspecified error
1401 - Error deleting old image 1401 - Error deleting old image
1410 - Unspecified parsing error 1410 - Unspecified parsing error

View File

@@ -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. 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.

View File

@@ -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. 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.

View File

@@ -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. 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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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. 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.

View File

@@ -1 +1 @@
Brug `!hangman` til at starte et spil hangman. Brug derefter reaktionerne til at gætte bogstaver. Du har 6 gæt. Brug `/hangman` til at starte et spil hangman. Brug derefter reaktionerne til at gætte bogstaver. Du har 6 gæt.

View File

@@ -1 +1 @@
Hvis du bruger kommandoen `!hello`, sender Gwendolyn en venlig hilsen. Hvis du bruger kommandoen `/hello`, sender Gwendolyn en venlig hilsen.

View File

@@ -1 +1 @@
Brug `!hex start` til at starte et spil imod Gwendolyn. Brug "!hex start [modstander]" for at spille imod en anden person. Brug `/hex start` til at starte et spil imod Gwendolyn. Brug "/hex start [modstander]" for at spille imod en anden person.

View File

@@ -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` 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 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. `/invest buy [symbol] [pris]` lader dig sælge dine aktier. Du kan godt sælge for mindre end 100 GwendoBucks.

View File

@@ -1 +0,0 @@
Få et billede af Senkulpa kortet.

View File

@@ -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. Hvis Gwendolyn ikke kan finde det, er det ofte fordi du har skrevet navnet forkert.

View File

@@ -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. Hvis Gwendolyn ikke kan finde den, er det ofte fordi du har skrevet navnet forkert.

View File

@@ -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.

View File

@@ -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. 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.

View File

@@ -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.

View File

@@ -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. 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. Hvis du svarer rigtigt får du 1 GwendoBuck.

View File

@@ -1,49 +1,24 @@
`!hello` - En venlig hilsen. `/hello` - En venlig hilsen.
`/roll` - Rul terninger i xdy format.
`!roll` - Rul terninger i xdy format. `/spell` - Slå en besværgelse op.
`/monster` - Slå et monster op.
`!spell` - Slå en besværgelse op. `/image` - Finder et tilfældigt billede fra internettet.
`/movie` - Giver titlen på en tilfældig film fra Bedre Netflix
`!monster` - Slå et monster op. `/name` - Genererer et tilfældigt navn.
`/tavern` - Genererer en tilfældig tavern.
`!map` - Få et billede af Senkulpa kortet. `/give` - Lader dig give GwendoBucks til andre.
`/starWarsCharacter` - Lader dig lave en Star Wars karakter.
`!image` - Finder et tilfældigt billede fra internettet. `/starWarsRoll` - Lader dig rulle Star Wars terninger.
`/balance` - Viser dig hvor mange GwendoBucks du har.
`!movie` - Giver titlen på en tilfældig film fra Bedre Netflix `/invest` - Lader dig investere dine GwendoBucks i aktiemarkedet.
`/blackjack` - Lader dig spille et spil blackjack.
`!name` - Genererer et tilfældigt navn. `/trivia` - Lader dig spille et spil trivia, hvor du kan tjene GwendoBucks.
`/connectFour` - Lader dig spille et spil fire på stribe.
`!tavern` - Genererer en tilfældig tavern. `/hex` - Lader dig spille et spil Hex.
`/hangman` - Lader dig spille et spil hangman.
`!give` - Lader dig give GwendoBucks til andre. `/wolf` - Lader dig slå ting op på Wolfram Alpha.
`/addmovie` - Lader dig tilføje film til Bedre Netflix.
`!swchar` - Lader dig lave en Star Wars karakter. `/addshow` - Lader dig tilføje tv shows til Bedre Netflix.
`/downloading` - Viser dig hvor langt de torrents der er ved at downloade er kommet.
`!swroll` - Lader dig rulle Star Wars terninger. `/thank` - Lader dig takke Gwendolyn.
Du kan få ekstra information om kommandoerne med "/help [kommando]".
`!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]".

View File

@@ -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"
}
]
}
}

View File

@@ -60,11 +60,11 @@
"resources/movies.txt": "The Room", "resources/movies.txt": "The Room",
"resources/names.txt": "Gandalf", "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", "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" : [ "folder" : [
"resources/games/blackjackTables", "resources/games/blackjackTables",
"resources/games/4InARowBoards", "resources/games/connect4Boards",
"resources/games/hexBoards", "resources/games/hexBoards",
"resources/games/hangmanBoards", "resources/games/hangmanBoards",
"resources/bedreNetflix" "resources/bedreNetflix"

6
utils/__init__.py Normal file
View File

@@ -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

132
utils/helperClasses.py Normal file
View File

@@ -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

121
utils/utilFunctions.py Normal file
View File

@@ -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 ""