diff --git a/README.md b/README.md index 38f8737..c626061 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,18 @@ # WORDLE! + The ability to play Wordle with your friends in Discord! Simply type in /wordle 'word' and the bot will display a board for you to play the game with! ![image](https://github.com/JaredIsaacs/worlde-bot/assets/45950689/99eb2724-4ed3-4a4f-ac34-a88c57697b26) - ## Features + - Automatically construct the board behind the scenes. - Checks with the [Wordle API](https://github.com/petergeorgas/Wordle-API) for correct answers. - Can Play with multiple friends at once. ## Todo + - Implement a single player mode. - Make the word generate after each successful playthrough. - Keep track of player stats. diff --git a/app.py b/app.py index 103a95e..315e95f 100644 --- a/app.py +++ b/app.py @@ -31,6 +31,7 @@ async def setup_hook(self) -> None: @client.event async def on_ready(): wordle_db.init_db() + print(wordle_db.get_word()) print(f'App running. Logged on as {client.user.id}!') @@ -44,8 +45,9 @@ async def on_guild_join(guild: discord.guild.Guild): @client.tree.command() async def wordle(interaction: discord.Interaction, word: str): guild_id = interaction.guild_id + secret_word = wordle_db.get_word() - if wordle_db.check_exists(guild_id): + if wordle_db.check_guild_exists(guild_id): accuracy_board, letter_board = wordle_db.get_wordle_progress(guild_id) board = wordleboard.WordleBoard(accuracy_board=accuracy_board, letter_board=letter_board) else: @@ -55,8 +57,9 @@ async def wordle(interaction: discord.Interaction, word: str): await interaction.response.send_message(f'Sorry, {interaction.user.mention}. But the wordle of the day has already been completed.\nTo see the board, type /board.') return + try: - board.process_word(word) + board.process_word(word, secret_word) board_file = convert_to_image(board) embed = create_embed(interaction) @@ -101,5 +104,6 @@ def convert_to_image(board): for line in open_file: WORD_LIST.add(line.strip()) + handler = logging.FileHandler(filename='logs/debug.log', encoding='utf-8', mode='w') client.run(os.getenv('BOT_TOKEN'), log_handler=handler, log_level=logging.DEBUG) \ No newline at end of file diff --git a/globals.py b/globals.py index 384beda..f0258ab 100644 --- a/globals.py +++ b/globals.py @@ -17,8 +17,6 @@ 2 : CORRECT_CHAR } -WORDLE_URL = 'https://wordle-api.vercel.app/api/wordle' - DB_PATH = 'db/wordle.db' WORD_LIST = set() \ No newline at end of file diff --git a/wordleboard.py b/wordleboard.py index 079e0b1..9112e03 100644 --- a/wordleboard.py +++ b/wordleboard.py @@ -1,6 +1,5 @@ from globals import * from PIL import Image, ImageDraw, ImageFont -from wordlerequest import get_wordle_info class WordleBoard(): @@ -33,49 +32,52 @@ def __init__(self, accuracy_board: list = None, letter_board: list = None): self.letter_board = letter_board - def process_word(self, word: str): - assert len(word) == 5, f'{word} is not 5 characters long!' #Check if word is correct length - assert word.lower() in WORD_LIST, f'{word} is not in the word list!' #Check if word is in the word list. Can maybe combine this with previous check. + def process_word(self, guess: str, word: str): + assert len(guess) == 5, f'{guess} is not 5 characters long!' #Check if guess is correct length + assert guess.lower() in WORD_LIST, f'{guess} is not in the guess list!' #Check if guess is in the guess list. Can maybe combine this with previous check. self.correct_chars = 0 - word = word.upper() - wordle_info = get_wordle_info(word) + guess = guess.upper() + unmatched = {} letter_row = next(row for row in self.letter_board if None in row) - for i, char in enumerate(word): + for i, char in enumerate(guess): letter_row[i] = char accuracy_row = next(row for row in self.accuracy_board if None in row) - if wordle_info['was_correct']: - for i, char in enumerate(word): + for i in range(len(word)): + if word[i] == guess[i]: accuracy_row[i] = 2 - self.isWinner = True - else: - i = 0 - accuracy = 0 - - while len(wordle_info['character_info']) != 0: - character_scoring = wordle_info['character_info'].pop(0)['scoring'] - - if character_scoring['in_word'] and character_scoring['correct_idx']: - accuracy = 2 - self.correct_chars += 1 - elif character_scoring['in_word'] and not character_scoring['correct_idx']: - accuracy = 1 + self.correct_chars += 1 + else: + unmatched[word[i]] = unmatched.get(word[i], 0) + 1 + + for i in range(len(guess)): + if guess[i] != word[i]: + if unmatched.get(guess[i], 0) > 0: + accuracy_row[i] = 1 + unmatched[guess[i]] -= 1 else: - accuracy = 0 + accuracy_row[i] = 0 + + + if self.check_for_win(accuracy_row): + self.isWinner = True - accuracy_row[i] = accuracy - i += 1 - if self.check_for_loss(): self.isWinner = False def check_for_loss(self): if None not in self.accuracy_board[5] and self.isWinner != True: + return True + + + def check_for_win(self, row): + for i in range(len(row)): + if row[i] != 2: + return False return True - def create_wordle_square(self, char: str, x: int, y: int) -> Image: diff --git a/wordledb.py b/wordledb.py index e0d2d88..6f3d4b9 100644 --- a/wordledb.py +++ b/wordledb.py @@ -1,4 +1,4 @@ -import sqlite3, datetime, pickle +import sqlite3, datetime, pickle, random from os import path, makedirs from globals import * @@ -19,10 +19,13 @@ def init_db(self) -> None: self.cur.execute('''CREATE TABLE IF NOT EXISTS wordle (date TEXT NOT NULL, guild_id INTEGER NOT NULL, completed TEXT, won TEXT, accuracy_board BINARY NOT NULL, letter_board BINARY NOT NULL)''') + + self.cur.execute('''CREATE TABLE IF NOT EXISTS wordle_word (date TEXT NOT NULL, word TEXT NOT NULL)''') + self.conn.commit() - def check_exists(self, guild_id: int) -> bool: + def check_guild_exists(self, guild_id: int) -> bool: today = datetime.date.today() guild = self.cur.execute('''SELECT * FROM wordle WHERE guild_id = ? AND date = ?''', (guild_id, today)) @@ -63,7 +66,7 @@ def update_wordle_progress(self, guild_id: int, accuracy_board: list, letter_boa p_accuracy = pickle.dumps(accuracy_board, protocol=pickle.HIGHEST_PROTOCOL) p_letter = pickle.dumps(letter_board, protocol=pickle.HIGHEST_PROTOCOL) - if self.check_exists(guild_id): + if self.check_guild_exists(guild_id): self.cur.execute('''UPDATE wordle SET completed = ?, won = ?, accuracy_board = ?, letter_board = ? WHERE guild_id = ? AND date = ?''', (completed, won, p_accuracy, p_letter, guild_id, today)) @@ -83,11 +86,43 @@ def get_wordle_progress(self, guild_id: int): accuracy_board = pickle.loads(boards[0]) letter_board = pickle.loads(boards[1]) - return accuracy_board, letter_board - + return accuracy_board, letter_board + + def update_word(self) -> str: + today = datetime.date.today() + word = random.choice(list(WORD_LIST)) + + self.cur.execute('''INSERT INTO wordle_word (date, word) values (?, ?)''', (today, word)) + self.conn.commit() + + return word + + + def check_word_exists(self): + today = datetime.date.today() + + guild = self.cur.execute('''SELECT * FROM wordle_word + WHERE date = ?''', (today,)) + + if guild.fetchone(): + return True + return False + + + def get_word(self) -> str: + today = datetime.date.today() + + if self.check_word_exists(): + word = self.cur.execute("SELECT word FROM wordle_word WHERE date = ?", (today,)).fetchone()[0] + else: + word = self.update_word() + + return word.upper() + + def get_all_wordles(self): # For Debug purposes self.cur.execute('SELECT date, guild_id, completed, won FROM wordle') for e in self.cur: - print(e) \ No newline at end of file + print(e) diff --git a/wordlerequest.py b/wordlerequest.py deleted file mode 100644 index add5a2d..0000000 --- a/wordlerequest.py +++ /dev/null @@ -1,9 +0,0 @@ -from globals import * -import requests - -def get_wordle_info(word: str): - body = { - "guess": word - } - - return requests.post(url=WORDLE_URL, data=body).json()