On the last few PRs I have noticed two problems: 1. `ruff format` fails even though it seems OK on our local machines (sometimes, not always) 2. Nate's and Sam's machines kept flip-flopping a specific piece of formatting back and forth, indicating a subtle difference of config hiding somewhere 3. This was reproducible by running `ruff format` in the terminal, followed by `make check`. The former would edit files, and then `make check` would edit them back! This PR addresses both issues, and further standardizes our editor & linter configs to be super stable. Specifically: 1. The main fix for the above, the pre-commit hook was pinned to a super old version of ruff. This resulted in subtle differences in behavior between our machines, and on CI. 2. Moved ruff settings from `pyproject.toml` to `.ruff.toml` pyproject files in subdirectories (e.g. `toolkits/**`) were overriding the main pyproject file and erasing the custom ruff config we set at the root. This meant that our ruff config was applied to `arcade` but not to any of the other packages. By moving the config to `.ruff.toml` at the root, all projects will inherit the same ruff linting & formatting config. 4. Un-ignored the `.vscode/` directory so that we can share vscode/cursor workspace settings. This is valuable for standardizing settings like the default formatter (ruff) and default test framework (pytest). However, it's important that going forward we _only_ commit things here that should apply across all of our machines. 5. To avoid any conflict between prettier and ruff, prettier now explicitly ignores *.py files 6. Finally, `ruff format` and `make check` agree. A number of files are newly auto-formatted.
58 lines
1.8 KiB
Python
58 lines
1.8 KiB
Python
import json
|
|
|
|
from requests import Response
|
|
|
|
|
|
def get_tweet_url(tweet_id: str) -> str:
|
|
"""Get the URL of a tweet given its ID."""
|
|
return f"https://x.com/x/status/{tweet_id}"
|
|
|
|
|
|
def parse_search_recent_tweets_response(response: Response) -> str:
|
|
"""
|
|
Parses response from the X API search recent tweets endpoint.
|
|
Returns a JSON string with the tweets data.
|
|
|
|
Example parsed response:
|
|
"tweets": [
|
|
{
|
|
"author_id": "558248927",
|
|
"id": "1838272933141319832",
|
|
"edit_history_tweet_ids": [
|
|
"1838272933141319832"
|
|
],
|
|
"text": "PR pending on @LangChainAI, will be integrated there soon! https://t.co/DPWd4lccQo",
|
|
"tweet_url": "https://x.com/x/status/1838272933141319832",
|
|
"author_username": "tomas_hk",
|
|
"author_name": "Tomas Hernando Kofman"
|
|
},
|
|
]
|
|
"""
|
|
if response.status_code != 200:
|
|
return json.dumps({"tweets": []})
|
|
|
|
tweets_data = json.loads(response.text)
|
|
|
|
if not sanity_check_tweets_data(tweets_data):
|
|
return json.dumps({"tweets": []})
|
|
|
|
for tweet in tweets_data["data"]:
|
|
tweet["tweet_url"] = get_tweet_url(tweet["id"])
|
|
|
|
for tweet_data, user_data in zip(tweets_data["data"], tweets_data["includes"]["users"]):
|
|
tweet_data["author_username"] = user_data["username"]
|
|
tweet_data["author_name"] = user_data["name"]
|
|
|
|
return json.dumps({"tweets": tweets_data["data"]})
|
|
|
|
|
|
def sanity_check_tweets_data(tweets_data: dict) -> bool:
|
|
"""
|
|
Sanity check the tweets data.
|
|
Returns True if the tweets data is valid and contains tweets, False otherwise.
|
|
"""
|
|
if not tweets_data.get("data", []):
|
|
return False
|
|
if not tweets_data.get("includes", {}).get("users", []):
|
|
return False
|
|
return True
|