diff --git a/b2.py b/b2.py index dad0a36..15bece8 100644 --- a/b2.py +++ b/b2.py @@ -54,3 +54,14 @@ class Client: 'X-Bz-Content-Sha1': hashlib.sha1(data).hexdigest() } self.post(upload['uploadUrl'], headers=headers, data=data) + + def list_objects(self, bucket_id, prefix=""): + r = self.post( + f'{self.api_url}/b2api/v2/b2_list_file_names', + json={ + 'bucketId': bucket_id, + 'prefix': prefix, + 'maxFileCount': 1000 # I imagine wordle will get old before this becomes a problem + } + ) + return r.json()['files'] diff --git a/bot.py b/bot.py index ee04839..70ce61a 100644 --- a/bot.py +++ b/bot.py @@ -79,6 +79,42 @@ def slack_request(method, **kwargs): return resp +class State: + def __init__(self, driver): + self.driver = driver + self.b2_client = b2.Client(os.environ['B2_KEY_ID'], os.environ['B2_APP_KEY']) + self.bucket_id = os.environ['B2_BUCKET_ID'] + + def restore(self): + # use yesterday's state if available + # if not, use the latest previous + files = b2.list_objects(self.bucket_id, 'wordle/') + data = None + for i in range(1, 1001): + filename = files[-i] + if filename < f'state_{datetime.date().today()}.json': + data = self.b2_client.get_object('cupboard', filename) + break + + if data: + self.driver.execute_script( + "window.localStorage.setItem('statistics', arguments[1]);", + data.decode('utf-8') + ) + print('Restored state: ' filename) + + def save(self): + state = self.driver.execute_script("return window.localStorage.getItem('statistics')") + if state: + filename = f'state_{datetime.date().today()}.json' + self.b2_client.put_object( + self.bucket_id, + 'wordle_state.json', + state.encode('utf-8') + ) + print('Saved state: ' filename) + + class Solver: def __init__(self): print('Launching web browser') @@ -89,7 +125,6 @@ class Solver: self.body = self.driver.find_element(By.TAG_NAME, 'body') self.body.click() self.words = pathlib.Path('dictionary.txt').read_text().splitlines() - self.b2_client = b2.Client(os.environ['B2_KEY_ID'], os.environ['B2_APP_KEY']) def setup_driver(self): options = ChromeOptions() @@ -98,22 +133,6 @@ class Solver: options.add_argument('--remote-debugging-port=9222') return webdriver.Chrome(options=options) - def restore_state(self): - data = self.b2_client.get_object('cupboard', 'wordle_state.json') - if data: - self.driver.execute_script( - "window.localStorage.setItem('statistics', arguments[1]);", - data.decode('utf-8') - ) - - def save_state(self): - state = driver.execute_script("return window.localStorage.getItem('statistics')") - self.b2_client.put_object( - os.environ['B2_BUCKET_ID'], - 'wordle_state.json', - state.encode('utf-8') - ) - def input_word(self, word): for char in word: self.body.send_keys(char) @@ -155,12 +174,6 @@ class Solver: history.append(row_hist) return history - def capture_board(self): - board = self.driver.execute_script("return document.querySelector('game-app').shadowRoot.querySelector('#board')") - filename = f'wordlebot_{datetime.datetime.now().strftime("%Y-%m-%d")}.png' - board.screenshot(filename) - return filename - def solve(self): print('Attempting to solve') for i in range(6): @@ -182,28 +195,51 @@ class Solver: self.words = [w for w in self.words if filter_word(w, conditions)] return None + def capture_board(self): + board = self.driver.execute_script("return document.querySelector('game-app').shadowRoot.querySelector('#board')") + filename = f'result_{datetime.date.today()}.png' + board.screenshot(filename) + return filename + + def capture_stats(self): + btn = self.driver.execute_script("return document.querySelector('game-app').shadowRoot.querySelector('game-icon[icon=statistics]')") + btn.click() + time.sleep(0.5) + stats = self.driver.execute_script("return document.querySelector('game-app').shadowRoot.querySelector('game-stats')") + filename = f'stats_{datetime.date.today()}.png' + stats.screenshot(filename) + return filename + if __name__ == '__main__': solver = Solver() try: - if result := solver.solve(): - filename = solver.capture_board() + solver.state.restore() + result = solver.solve() + solver.state.save() + board_img = solver.capture_board() + stats_img = solve.capture_state() finally: solver.driver.close() if result: print(f'Success!') - wordle_num = (datetime.date.today() - datetime.date(2022, 1, 17)).days + 212 - lines = [f"Wordle {wordle_num}: {result['iterations']}/6"] - lines = lines + [''.join(row) for row in result['history']] - - channel = os.environ['SLACK_CHANNEL'] - msg = slack_request('chat.postMessage', json={'channel': channel, 'text': '\n'.join(lines)}) - slack_request( - 'files.upload', - params={'thread_ts': msg['ts'], 'channels': channel}, - files={'file': (filename, open(filename, 'rb').read())}, - ) - - else: + else print('Failed to find the word.') + + wordle_num = (datetime.date.today() - datetime.date(2022, 1, 17)).days + 212 + lines = [f"Wordle {wordle_num}: {result['iterations']}/6"] + lines = lines + [''.join(row) for row in result['history']] + + channel = os.environ['SLACK_CHANNEL'] + msg = slack_request('chat.postMessage', json={'channel': channel, 'text': '\n'.join(lines)}) + slack_request( + 'files.upload', + params={'thread_ts': msg['ts'], 'channels': channel}, + files={'file': (board_img, open(board_img, 'rb').read())}, + ) + slack_request( + 'files.upload', + params={'thread_ts': msg['ts'], 'channels': channel}, + files={'file': (stats_img, open(stats_img, 'rb').read())}, + )