birdapi 0.0.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,5 @@
1
+ * text=auto
2
+ *.py text eol=lf
3
+ *.md text eol=lf
4
+ *.toml text eol=lf
5
+ *.json text eol=lf
@@ -0,0 +1,40 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*"
7
+
8
+ jobs:
9
+ build:
10
+ runs-on: ubuntu-latest
11
+ steps:
12
+ - uses: actions/checkout@v4
13
+
14
+ - uses: actions/setup-python@v5
15
+ with:
16
+ python-version: "3.12"
17
+
18
+ - run: pip install build
19
+
20
+ - run: python -m build
21
+
22
+ - uses: actions/upload-artifact@v4
23
+ with:
24
+ name: dist
25
+ path: dist/
26
+
27
+ publish:
28
+ needs: build
29
+ runs-on: ubuntu-latest
30
+ environment: pypi
31
+ permissions:
32
+ id-token: write # required for OIDC trusted publishing
33
+
34
+ steps:
35
+ - uses: actions/download-artifact@v4
36
+ with:
37
+ name: dist
38
+ path: dist/
39
+
40
+ - uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,46 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *.pyo
5
+ .Python
6
+ *.egg-info/
7
+ dist/
8
+ build/
9
+ .eggs/
10
+ *.egg
11
+ wheels/
12
+
13
+ # Virtual environments
14
+ .venv/
15
+ venv/
16
+ env/
17
+ ENV/
18
+
19
+ # Package managers
20
+ node_modules/
21
+ package-lock.json
22
+ uv.lock
23
+
24
+ # Credentials & secrets
25
+ .env
26
+ .env.*
27
+ credentials.json
28
+
29
+ # Query ID cache (auto-refreshed at runtime)
30
+ query-ids-cache.json
31
+
32
+ # IDE
33
+ .idea/
34
+ .vscode/
35
+ *.iml
36
+
37
+ # OS
38
+ .DS_Store
39
+ Thumbs.db
40
+
41
+ # Test & coverage
42
+ .pytest_cache/
43
+ .coverage
44
+ htmlcov/
45
+ .mypy_cache/
46
+ .ruff_cache/
@@ -0,0 +1,106 @@
1
+ # CLAUDE.md
2
+
3
+ This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4
+
5
+ ## What This Repo Is
6
+
7
+ A pure-Python CLI and library for X/Twitter's undocumented GraphQL API, using cookie-based authentication. No browser cookie extraction — credentials are supplied directly via environment variables or CLI flags.
8
+
9
+ **Stability caveat:** X can rotate GraphQL query IDs or change endpoints without notice. The `_query_ids.py` module handles auto-refresh from live x.com bundles.
10
+
11
+ ## Commands
12
+
13
+ ```bash
14
+ # Install (editable) with dev deps
15
+ pip install -e ".[dev]"
16
+
17
+ # Tests
18
+ pytest tests/ # all unit tests (no network)
19
+ pytest tests/test_utils.py::test_X # single test
20
+
21
+ # Lint / format
22
+ ruff check src/ tests/
23
+ ruff format src/ tests/
24
+
25
+ # CLI (requires AUTH_TOKEN + CT0 env vars or --auth-token / --ct0 flags)
26
+ bird --help
27
+ bird whoami
28
+ bird read <tweet-url-or-id>
29
+ bird search "from:steipete" -n 5
30
+ bird tweet "Hello from Python"
31
+ bird query-ids --fresh # force-refresh GraphQL query ID cache
32
+ ```
33
+
34
+ ## Architecture
35
+
36
+ ```
37
+ src/bird/
38
+ __init__.py Public re-exports (TwitterClient, Tweet, User, …)
39
+ client.py TwitterClient — all API methods
40
+ cli.py Click CLI entry point
41
+ _constants.py API URLs, bearer token, fallback query IDs
42
+ _features.py GraphQL feature-flag payloads (per-operation)
43
+ _models.py Dataclasses: Tweet, User, TwitterList, NewsItem, …
44
+ _utils.py Parsing: map_tweet_result, parse_tweets_from_instructions,
45
+ extract_cursor_from_instructions, render_content_state, …
46
+ _query_ids.py Runtime query ID store — scrapes x.com JS bundles,
47
+ caches to ~/.config/bird/query-ids-cache.json (24 h TTL)
48
+ tests/
49
+ test_utils.py Unit tests for _utils.py (no network)
50
+ ```
51
+
52
+ ### Authentication
53
+
54
+ Pass `auth_token` and `ct0` cookies (from an active X/Twitter web session):
55
+
56
+ ```python
57
+ from bird import TwitterClient
58
+
59
+ client = TwitterClient(auth_token="...", ct0="...")
60
+ # or via env vars: AUTH_TOKEN, CT0
61
+ ```
62
+
63
+ Or via CLI: `--auth-token` / `--ct0`, or `AUTH_TOKEN` / `CT0` env vars.
64
+
65
+ ### Client API
66
+
67
+ ```python
68
+ client.tweet(text) # → tweet_id str | None
69
+ client.reply(text, reply_to_id) # → tweet_id str | None
70
+ client.get_tweet(tweet_id) # → Tweet | None
71
+ client.get_replies(tweet_id) # → list[Tweet]
72
+ client.get_thread(tweet_id) # → list[Tweet]
73
+ client.search(query, count) # → (list[Tweet], next_cursor)
74
+ client.get_mentions(username, count) # → (list[Tweet], next_cursor)
75
+ client.get_bookmarks(count) # → (list[Tweet], next_cursor)
76
+ client.get_likes(count) # → (list[Tweet], next_cursor)
77
+ client.get_user_tweets(user_id, count) # → (list[Tweet], next_cursor)
78
+ client.get_home_timeline(count) # → list[Tweet]
79
+ client.get_home_latest_timeline(count) # → list[Tweet]
80
+ client.get_current_user() # → User | None
81
+ client.get_user_id_by_username(handle) # → User | None
82
+ client.get_following(user_id, count) # → (list[User], next_cursor)
83
+ client.get_followers(user_id, count) # → (list[User], next_cursor)
84
+ client.like/unlike/retweet/unretweet/bookmark/unbookmark(tweet_id) # → bool
85
+ client.follow/unfollow(user_id) # → bool
86
+ client.get_owned_lists() # → list[TwitterList]
87
+ client.get_list_timeline(list_id, count) # → (list[Tweet], next_cursor)
88
+ client.get_news(count, ai_only, tabs) # → list[NewsItem]
89
+ client.get_user_about_account(username) # → AboutProfile | None
90
+ client.refresh_query_ids() # → dict (cache info)
91
+ ```
92
+
93
+ ### Query ID caching
94
+
95
+ `_query_ids.QueryIdStore` (singleton: `query_id_store`) scrapes the live x.com
96
+ JS bundles to extract fresh query IDs. Results are cached at
97
+ `~/.config/bird/query-ids-cache.json` for 24 hours. On 404 responses the client
98
+ automatically retries after refreshing. The fallback IDs in `_constants.py` keep
99
+ the client working if the cache is missing.
100
+
101
+ ### Tweet parsing flow
102
+
103
+ `parse_tweets_from_instructions(instructions)` → iterates GraphQL timeline
104
+ instructions → `_collect_tweet_results_from_entry` → `map_tweet_result` →
105
+ `Tweet` dataclass. Rich text (Notes/Articles in Draft.js format) is rendered to
106
+ Markdown by `render_content_state` in `_utils.py`.
birdapi-0.0.1/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 dvermaas
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
birdapi-0.0.1/PKG-INFO ADDED
@@ -0,0 +1,207 @@
1
+ Metadata-Version: 2.4
2
+ Name: birdapi
3
+ Version: 0.0.1
4
+ Summary: CLI and library for X/Twitter GraphQL API (cookie auth, no API key required)
5
+ Project-URL: Homepage, https://github.com/dvermaas/birdapi
6
+ Project-URL: Repository, https://github.com/dvermaas/birdapi
7
+ Project-URL: Issues, https://github.com/dvermaas/birdapi/issues
8
+ Author: dvermaas
9
+ License: MIT
10
+ License-File: LICENSE
11
+ Keywords: api,cli,graphql,twitter,x
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Environment :: Console
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
21
+ Classifier: Topic :: Internet
22
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
23
+ Requires-Python: >=3.10
24
+ Requires-Dist: click>=8.1
25
+ Requires-Dist: httpx>=0.27
26
+ Provides-Extra: dev
27
+ Requires-Dist: mypy>=1.10; extra == 'dev'
28
+ Requires-Dist: pytest-httpx>=0.30; extra == 'dev'
29
+ Requires-Dist: pytest>=8; extra == 'dev'
30
+ Requires-Dist: ruff>=0.4; extra == 'dev'
31
+ Description-Content-Type: text/markdown
32
+
33
+ # bird 🐦
34
+
35
+ A Python CLI and library for X/Twitter's GraphQL API using cookie-based authentication — no API key required.
36
+
37
+ > **Disclaimer:** This uses X/Twitter's undocumented internal GraphQL API. X can change endpoints or rotate query IDs at any time. Expect occasional breakage.
38
+
39
+ ## Installation
40
+
41
+ ```bash
42
+ pip install -e .
43
+ ```
44
+
45
+ Requires Python 3.10+.
46
+
47
+ ## Quick start
48
+
49
+ ### 1. Configure credentials
50
+
51
+ ```bash
52
+ python -m bird.cli configure
53
+ ```
54
+
55
+ You'll be prompted for two cookies from your active X/Twitter session:
56
+
57
+ 1. Open [x.com](https://x.com) and log in
58
+ 2. Open DevTools → Application → Cookies → `https://x.com`
59
+ 3. Copy the values of **`auth_token`** and **`ct0`**
60
+
61
+ Credentials are saved to `~/.config/bird/credentials.json` and used automatically by all commands.
62
+
63
+ ### 2. Run commands
64
+
65
+ ```bash
66
+ python -m bird.cli whoami
67
+ python -m bird.cli search "from:username" -n 10
68
+ python -m bird.cli tweet "Hello from Python"
69
+ ```
70
+
71
+ ## Commands
72
+
73
+ | Command | Description |
74
+ |---|---|
75
+ | `configure` | Save credentials interactively |
76
+ | `whoami` | Show the authenticated account |
77
+ | `check` | Show where credentials are loaded from |
78
+ | `tweet "<text>"` | Post a new tweet |
79
+ | `reply <id-or-url> "<text>"` | Reply to a tweet |
80
+ | `read <id-or-url>` | Fetch a tweet |
81
+ | `thread <id-or-url>` | Show the full conversation thread |
82
+ | `replies <id-or-url>` | List replies to a tweet |
83
+ | `search "<query>"` | Search for tweets |
84
+ | `mentions` | Find tweets mentioning you |
85
+ | `user-tweets @handle` | Get tweets from a user's timeline |
86
+ | `home` | Your "For You" timeline |
87
+ | `home --following` | Your "Following" timeline |
88
+ | `bookmarks` | List your bookmarks |
89
+ | `unbookmark <id-or-url>` | Remove a bookmark |
90
+ | `likes` | List your liked tweets |
91
+ | `following` | Users you follow |
92
+ | `followers` | Users that follow you |
93
+ | `lists` | Your owned lists |
94
+ | `list-timeline <id-or-url>` | Tweets from a list |
95
+ | `news` | News and trending topics from Explore |
96
+ | `about @handle` | "About this account" info |
97
+ | `query-ids` | Inspect or refresh GraphQL query ID cache |
98
+
99
+ ### Common options
100
+
101
+ ```bash
102
+ --json Output raw JSON
103
+ -n / --count N Number of results (default varies per command)
104
+ --cursor STRING Resume pagination from a cursor
105
+ --max-pages N Limit number of pages fetched
106
+ --timeout MS Request timeout in milliseconds
107
+ ```
108
+
109
+ ### Auth options (override saved credentials)
110
+
111
+ ```bash
112
+ --auth-token TOKEN
113
+ --ct0 TOKEN
114
+
115
+ # Or via environment variables
116
+ AUTH_TOKEN=... CT0=... python -m bird.cli whoami
117
+ ```
118
+
119
+ ### Examples
120
+
121
+ ```bash
122
+ # Search and output JSON
123
+ python -m bird.cli search "python asyncio" -n 20 --json
124
+
125
+ # Get someone's recent tweets
126
+ python -m bird.cli user-tweets @gvanrossum -n 50
127
+
128
+ # Fetch a full thread
129
+ python -m bird.cli thread https://x.com/user/status/1234567890123456789
130
+
131
+ # List bookmarks from a specific folder
132
+ python -m bird.cli bookmarks --folder-id 1234567890123456789 -n 50
133
+
134
+ # Fetch AI-curated news
135
+ python -m bird.cli news --ai-only -n 10
136
+
137
+ # Paginate following list
138
+ python -m bird.cli following -n 200 --json
139
+ ```
140
+
141
+ ## Library usage
142
+
143
+ ```python
144
+ from bird import TwitterClient
145
+
146
+ client = TwitterClient(auth_token="...", ct0="...")
147
+
148
+ # Search
149
+ tweets, next_cursor = client.search("from:gvanrossum", count=20)
150
+ for tweet in tweets:
151
+ print(f"@{tweet.author.username}: {tweet.text}")
152
+
153
+ # Post
154
+ tweet_id = client.tweet("Hello from Python!")
155
+
156
+ # Reply
157
+ client.reply("Thanks!", reply_to_tweet_id=tweet_id)
158
+
159
+ # Bookmarks
160
+ tweets, cursor = client.get_bookmarks(count=50)
161
+
162
+ # Engagement
163
+ client.like(tweet_id)
164
+ client.retweet(tweet_id)
165
+ client.bookmark(tweet_id)
166
+
167
+ # News
168
+ items = client.get_news(count=10, ai_only=True)
169
+ ```
170
+
171
+ ### Context manager
172
+
173
+ ```python
174
+ with TwitterClient(auth_token="...", ct0="...") as client:
175
+ user = client.get_current_user()
176
+ print(user.username)
177
+ ```
178
+
179
+ ## Project structure
180
+
181
+ ```
182
+ src/bird/
183
+ client.py TwitterClient — all API methods
184
+ cli.py Click CLI entry point
185
+ _config.py Credential storage (~/.config/bird/credentials.json)
186
+ _constants.py API URLs, bearer token, fallback query IDs
187
+ _features.py GraphQL feature-flag payloads
188
+ _models.py Dataclasses: Tweet, User, TwitterList, NewsItem, …
189
+ _utils.py Response parsing utilities
190
+ _query_ids.py Runtime query ID cache (scraped from x.com bundles)
191
+ tests/
192
+ test_utils.py Unit tests (no network required)
193
+ ```
194
+
195
+ ## Development
196
+
197
+ ```bash
198
+ pip install -e ".[dev]"
199
+ pytest tests/
200
+ ruff check src/ tests/
201
+ ```
202
+
203
+ ## Credential resolution order
204
+
205
+ 1. `--auth-token` / `--ct0` CLI flags
206
+ 2. `AUTH_TOKEN` / `CT0` environment variables
207
+ 3. `~/.config/bird/credentials.json` (written by `bird configure`)
@@ -0,0 +1,175 @@
1
+ # bird 🐦
2
+
3
+ A Python CLI and library for X/Twitter's GraphQL API using cookie-based authentication — no API key required.
4
+
5
+ > **Disclaimer:** This uses X/Twitter's undocumented internal GraphQL API. X can change endpoints or rotate query IDs at any time. Expect occasional breakage.
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ pip install -e .
11
+ ```
12
+
13
+ Requires Python 3.10+.
14
+
15
+ ## Quick start
16
+
17
+ ### 1. Configure credentials
18
+
19
+ ```bash
20
+ python -m bird.cli configure
21
+ ```
22
+
23
+ You'll be prompted for two cookies from your active X/Twitter session:
24
+
25
+ 1. Open [x.com](https://x.com) and log in
26
+ 2. Open DevTools → Application → Cookies → `https://x.com`
27
+ 3. Copy the values of **`auth_token`** and **`ct0`**
28
+
29
+ Credentials are saved to `~/.config/bird/credentials.json` and used automatically by all commands.
30
+
31
+ ### 2. Run commands
32
+
33
+ ```bash
34
+ python -m bird.cli whoami
35
+ python -m bird.cli search "from:username" -n 10
36
+ python -m bird.cli tweet "Hello from Python"
37
+ ```
38
+
39
+ ## Commands
40
+
41
+ | Command | Description |
42
+ |---|---|
43
+ | `configure` | Save credentials interactively |
44
+ | `whoami` | Show the authenticated account |
45
+ | `check` | Show where credentials are loaded from |
46
+ | `tweet "<text>"` | Post a new tweet |
47
+ | `reply <id-or-url> "<text>"` | Reply to a tweet |
48
+ | `read <id-or-url>` | Fetch a tweet |
49
+ | `thread <id-or-url>` | Show the full conversation thread |
50
+ | `replies <id-or-url>` | List replies to a tweet |
51
+ | `search "<query>"` | Search for tweets |
52
+ | `mentions` | Find tweets mentioning you |
53
+ | `user-tweets @handle` | Get tweets from a user's timeline |
54
+ | `home` | Your "For You" timeline |
55
+ | `home --following` | Your "Following" timeline |
56
+ | `bookmarks` | List your bookmarks |
57
+ | `unbookmark <id-or-url>` | Remove a bookmark |
58
+ | `likes` | List your liked tweets |
59
+ | `following` | Users you follow |
60
+ | `followers` | Users that follow you |
61
+ | `lists` | Your owned lists |
62
+ | `list-timeline <id-or-url>` | Tweets from a list |
63
+ | `news` | News and trending topics from Explore |
64
+ | `about @handle` | "About this account" info |
65
+ | `query-ids` | Inspect or refresh GraphQL query ID cache |
66
+
67
+ ### Common options
68
+
69
+ ```bash
70
+ --json Output raw JSON
71
+ -n / --count N Number of results (default varies per command)
72
+ --cursor STRING Resume pagination from a cursor
73
+ --max-pages N Limit number of pages fetched
74
+ --timeout MS Request timeout in milliseconds
75
+ ```
76
+
77
+ ### Auth options (override saved credentials)
78
+
79
+ ```bash
80
+ --auth-token TOKEN
81
+ --ct0 TOKEN
82
+
83
+ # Or via environment variables
84
+ AUTH_TOKEN=... CT0=... python -m bird.cli whoami
85
+ ```
86
+
87
+ ### Examples
88
+
89
+ ```bash
90
+ # Search and output JSON
91
+ python -m bird.cli search "python asyncio" -n 20 --json
92
+
93
+ # Get someone's recent tweets
94
+ python -m bird.cli user-tweets @gvanrossum -n 50
95
+
96
+ # Fetch a full thread
97
+ python -m bird.cli thread https://x.com/user/status/1234567890123456789
98
+
99
+ # List bookmarks from a specific folder
100
+ python -m bird.cli bookmarks --folder-id 1234567890123456789 -n 50
101
+
102
+ # Fetch AI-curated news
103
+ python -m bird.cli news --ai-only -n 10
104
+
105
+ # Paginate following list
106
+ python -m bird.cli following -n 200 --json
107
+ ```
108
+
109
+ ## Library usage
110
+
111
+ ```python
112
+ from bird import TwitterClient
113
+
114
+ client = TwitterClient(auth_token="...", ct0="...")
115
+
116
+ # Search
117
+ tweets, next_cursor = client.search("from:gvanrossum", count=20)
118
+ for tweet in tweets:
119
+ print(f"@{tweet.author.username}: {tweet.text}")
120
+
121
+ # Post
122
+ tweet_id = client.tweet("Hello from Python!")
123
+
124
+ # Reply
125
+ client.reply("Thanks!", reply_to_tweet_id=tweet_id)
126
+
127
+ # Bookmarks
128
+ tweets, cursor = client.get_bookmarks(count=50)
129
+
130
+ # Engagement
131
+ client.like(tweet_id)
132
+ client.retweet(tweet_id)
133
+ client.bookmark(tweet_id)
134
+
135
+ # News
136
+ items = client.get_news(count=10, ai_only=True)
137
+ ```
138
+
139
+ ### Context manager
140
+
141
+ ```python
142
+ with TwitterClient(auth_token="...", ct0="...") as client:
143
+ user = client.get_current_user()
144
+ print(user.username)
145
+ ```
146
+
147
+ ## Project structure
148
+
149
+ ```
150
+ src/bird/
151
+ client.py TwitterClient — all API methods
152
+ cli.py Click CLI entry point
153
+ _config.py Credential storage (~/.config/bird/credentials.json)
154
+ _constants.py API URLs, bearer token, fallback query IDs
155
+ _features.py GraphQL feature-flag payloads
156
+ _models.py Dataclasses: Tweet, User, TwitterList, NewsItem, …
157
+ _utils.py Response parsing utilities
158
+ _query_ids.py Runtime query ID cache (scraped from x.com bundles)
159
+ tests/
160
+ test_utils.py Unit tests (no network required)
161
+ ```
162
+
163
+ ## Development
164
+
165
+ ```bash
166
+ pip install -e ".[dev]"
167
+ pytest tests/
168
+ ruff check src/ tests/
169
+ ```
170
+
171
+ ## Credential resolution order
172
+
173
+ 1. `--auth-token` / `--ct0` CLI flags
174
+ 2. `AUTH_TOKEN` / `CT0` environment variables
175
+ 3. `~/.config/bird/credentials.json` (written by `bird configure`)
@@ -0,0 +1,52 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "birdapi"
7
+ version = "0.0.1"
8
+ description = "CLI and library for X/Twitter GraphQL API (cookie auth, no API key required)"
9
+ readme = "README.md"
10
+ license = { text = "MIT" }
11
+ requires-python = ">=3.10"
12
+ authors = [{ name = "dvermaas" }]
13
+ keywords = ["twitter", "x", "graphql", "cli", "api"]
14
+ classifiers = [
15
+ "Development Status :: 4 - Beta",
16
+ "Environment :: Console",
17
+ "Intended Audience :: Developers",
18
+ "License :: OSI Approved :: MIT License",
19
+ "Programming Language :: Python :: 3",
20
+ "Programming Language :: Python :: 3.10",
21
+ "Programming Language :: Python :: 3.11",
22
+ "Programming Language :: Python :: 3.12",
23
+ "Programming Language :: Python :: 3.13",
24
+ "Topic :: Internet",
25
+ "Topic :: Software Development :: Libraries :: Python Modules",
26
+ ]
27
+ dependencies = [
28
+ "httpx>=0.27",
29
+ "click>=8.1",
30
+ ]
31
+
32
+ [project.urls]
33
+ Homepage = "https://github.com/dvermaas/birdapi"
34
+ Repository = "https://github.com/dvermaas/birdapi"
35
+ Issues = "https://github.com/dvermaas/birdapi/issues"
36
+
37
+ [project.scripts]
38
+ bird = "bird.cli:main"
39
+
40
+ [project.optional-dependencies]
41
+ dev = [
42
+ "pytest>=8",
43
+ "pytest-httpx>=0.30",
44
+ "ruff>=0.4",
45
+ "mypy>=1.10",
46
+ ]
47
+
48
+ [tool.hatch.build.targets.wheel]
49
+ packages = ["src/bird"]
50
+
51
+ [tool.ruff.lint]
52
+ select = ["E", "F", "I", "UP"]
@@ -0,0 +1,16 @@
1
+ """bird — X/Twitter GraphQL client library."""
2
+
3
+ from .client import TwitterClient
4
+ from ._models import AboutProfile, ArticleMetadata, Author, MediaItem, NewsItem, Tweet, TwitterList, User
5
+
6
+ __all__ = [
7
+ "TwitterClient",
8
+ "Tweet",
9
+ "User",
10
+ "Author",
11
+ "MediaItem",
12
+ "ArticleMetadata",
13
+ "TwitterList",
14
+ "AboutProfile",
15
+ "NewsItem",
16
+ ]