diff --git a/wordlinator/app/__init__.py b/wordlinator/app/__init__.py index 9dbd2eb..43b89fe 100644 --- a/wordlinator/app/__init__.py +++ b/wordlinator/app/__init__.py @@ -1,3 +1,4 @@ +import argparse import asyncio import datetime @@ -7,12 +8,12 @@ import rich.table import wordlinator.sheets import wordlinator.twitter -WORDLE_DAY_ONE = datetime.date(2021, 6, 20) -WORDLE_TODAY_NUMBER = (datetime.date.today() - WORDLE_DAY_ONE).days +WORDLE_DAY_ZERO = datetime.date(2021, 6, 19) +WORDLE_TODAY_NUMBER = (datetime.date.today() - WORDLE_DAY_ZERO).days async def get_scores(wordle_day=WORDLE_TODAY_NUMBER): - users = wordlinator.sheets.get_wordlegolf_users() + users = wordlinator.sheets.SheetsClient().get_users() twitter_client = wordlinator.twitter.TwitterClient() @@ -26,8 +27,7 @@ async def get_scores(wordle_day=WORDLE_TODAY_NUMBER): return scores -async def main(): - wordle_day = WORDLE_TODAY_NUMBER # - 1 +async def main(wordle_day=None): scores = await get_scores(wordle_day) table = rich.table.Table( @@ -44,11 +44,11 @@ async def main(): if raw_score < 4: color = "green" elif raw_score == 4: - color = "white" + color = "orange3" elif raw_score > 6: color = "red" else: - color = "blue" + color = "yellow" score_args = [raw_score, score.score, score.score_name] args += [f"[{color}]{arg}" for arg in score_args] @@ -58,8 +58,25 @@ async def main(): rich.print(table) +def _get_day(): + parser = argparse.ArgumentParser("wordlinator") + days = parser.add_mutually_exclusive_group() + days.add_argument( + "--days-ago", type=int, help="The number of days back to pull a score report." + ) + days.add_argument( + "--wordle-day", type=int, help="The wordle day number for the score report." + ) + args = parser.parse_args() + wordle_day = args.wordle_day or WORDLE_TODAY_NUMBER + if args.days_ago: + wordle_day = WORDLE_TODAY_NUMBER - args.days_ago + return wordle_day + + def sync_main(): - asyncio.run(main()) + wordle_day = _get_day() + asyncio.run(main(wordle_day=wordle_day)) if __name__ == "__main__": diff --git a/wordlinator/sheets/__init__.py b/wordlinator/sheets/__init__.py index 9ab9942..244c086 100644 --- a/wordlinator/sheets/__init__.py +++ b/wordlinator/sheets/__init__.py @@ -4,34 +4,33 @@ import googleapiclient.discovery import rich import rich.table -WORDLEGOLF_SPREADSHEET_ID = "1POoklzvD643pvdMAleFxrecN50IMv2NdQBs9h43Hw8E" -WORDLEGOLF_RANGE_NAME = "Round 1!A2:A100" +SPREADSHEET_ID = "1POoklzvD643pvdMAleFxrecN50IMv2NdQBs9h43Hw8E" +SHEET_NAME = "Round 1" +USER_RANGE = "A2:A1000" -def _get_sheets_client(): - return googleapiclient.discovery.build( - "sheets", "v4", developerKey=os.getenv("SHEET_API_KEY") - ) +class SheetsClient: + def __init__( + self, sheet_id=SPREADSHEET_ID, sheet_name=SHEET_NAME, user_range=USER_RANGE + ): + creds = {"developerKey": os.getenv("SHEET_API_KEY")} + self.client = googleapiclient.discovery.build("sheets", "v4", **creds) + self.sheet_id = sheet_id + self.sheet_name = sheet_name + self.user_range = user_range + def _get_sheet_values(self, range): + sheets = self.client.spreadsheets() + result = sheets.values().get(spreadsheetId=self.sheet_id, range=range).execute() + return result.get("values", []) -def _get_sheet_values(client, range): - sheet = client.spreadsheets() - result = ( - sheet.values() - .get(spreadsheetId=WORDLEGOLF_SPREADSHEET_ID, range=range) - .execute() - ) - return result.get("values", []) - - -def get_wordlegolf_users(): - client = _get_sheets_client() - res = _get_sheet_values(client, WORDLEGOLF_RANGE_NAME) - return [row[0] for row in res] + def get_users(self): + rows = self._get_sheet_values(f"{self.sheet_name}!{self.user_range}") + return list(filter(None, [row[0] for row in rows])) def main(): - users = get_wordlegolf_users() + users = SheetsClient().get_users() table = rich.table.Table("Username", title="WordleGolf Players") for user in users: table.add_row(user) diff --git a/wordlinator/twitter/__init__.py b/wordlinator/twitter/__init__.py index 9748950..05d461c 100644 --- a/wordlinator/twitter/__init__.py +++ b/wordlinator/twitter/__init__.py @@ -5,15 +5,28 @@ import enum import os import re +import authlib.integrations.httpx_client import dateutil.parser import httpx import rich BASE_URL = "https://api.twitter.com/2" -WORDLE_RE = re.compile(r"Wordle (?P\d+) (?P[X\d])/6") +WORDLE_RE = re.compile(r"Wordle(\w+)? (?P\d+) (?P[X\d])/6") TOKEN = os.getenv("TWITTER_TOKEN") +def _get_oauth_creds(): + creds = { + "client_id": os.getenv("TWITTER_API_KEY"), + "client_secret": os.getenv("TWITTER_API_KEY_SECRET"), + "token": os.getenv("TWITTER_USER_TOKEN"), + "token_secret": os.getenv("TWITTER_USER_TOKEN_SECRET"), + } + if not all(creds.values()): + return None + return creds + + @dataclasses.dataclass class TwitterUser: name: str @@ -76,8 +89,13 @@ class TwitterClient(httpx.AsyncClient): SEARCH_PATH = "tweets/search/recent" def __init__(self, **kwargs): + oauth_creds = _get_oauth_creds() + if oauth_creds: + auth = authlib.integrations.httpx_client.OAuth1Auth(**oauth_creds) + kwargs["auth"] = auth super().__init__(base_url=BASE_URL, **kwargs) - self.headers["Authorization"] = f"Bearer {TOKEN}" + if not oauth_creds: + self.headers["Authorization"] = f"Bearer {TOKEN}" async def search_tweets(self, search_str): return await self.get( @@ -102,7 +120,7 @@ class TwitterClient(httpx.AsyncClient): async def get_user_wordles(self, username): return self._build_wordle_tweets( - await self.search_tweets(f"from:{username} wordle") + await self.search_tweets(f"from:{username} (wordle OR #WordleGolf)") ) async def get_wordlegolf_tweets(self):