@cm-growth-hacking/twitter-client 0.2.0
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.
- package/LICENSE +21 -0
- package/README.md +360 -0
- package/bin/twitter.js +1129 -0
- package/dist/cli/output.d.ts +22 -0
- package/dist/cli/output.d.ts.map +1 -0
- package/dist/cli/output.js +71 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +196 -0
- package/dist/client/TwitterClient.d.ts +47 -0
- package/dist/client/TwitterClient.d.ts.map +1 -0
- package/dist/client/TwitterClient.js +472 -0
- package/dist/client/auth.d.ts +21 -0
- package/dist/client/auth.d.ts.map +1 -0
- package/dist/client/auth.js +42 -0
- package/dist/client/graphql.d.ts +49 -0
- package/dist/client/graphql.d.ts.map +1 -0
- package/dist/client/graphql.js +191 -0
- package/dist/client/parsers.d.ts +14 -0
- package/dist/client/parsers.d.ts.map +1 -0
- package/dist/client/parsers.js +147 -0
- package/dist/client/query-ids.d.ts +22 -0
- package/dist/client/query-ids.d.ts.map +1 -0
- package/dist/client/query-ids.js +157 -0
- package/dist/client/rest.d.ts +10 -0
- package/dist/client/rest.d.ts.map +1 -0
- package/dist/client/rest.js +41 -0
- package/dist/client/types.d.ts +80 -0
- package/dist/client/types.d.ts.map +1 -0
- package/dist/client/types.js +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1 -0
- package/package.json +58 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Thaddeus
|
|
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.
|
package/README.md
ADDED
|
@@ -0,0 +1,360 @@
|
|
|
1
|
+
# @thaddeus/twitter-client
|
|
2
|
+
|
|
3
|
+
Lightweight Twitter/X GraphQL client and CLI tool.
|
|
4
|
+
|
|
5
|
+
## Quick Start
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
# Install
|
|
9
|
+
bun install
|
|
10
|
+
|
|
11
|
+
# Set credentials (get from browser DevTools → Application → Cookies)
|
|
12
|
+
export TWITTER_AUTH_TOKEN="your_auth_token"
|
|
13
|
+
export TWITTER_CT0="your_ct0_token"
|
|
14
|
+
|
|
15
|
+
# Search tweets
|
|
16
|
+
bun run src/cli.ts search "bitcoin"
|
|
17
|
+
|
|
18
|
+
# Post tweet
|
|
19
|
+
bun run src/cli.ts tweet "Hello World!"
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Features
|
|
23
|
+
|
|
24
|
+
- 🚀 Zero dependencies (except for CLI colors)
|
|
25
|
+
- 📝 Full TypeScript support
|
|
26
|
+
- 🔐 Cookie-based authentication
|
|
27
|
+
- 🎯 GraphQL API integration
|
|
28
|
+
- 💻 CLI tool included
|
|
29
|
+
- ⚡ Bun-optimized
|
|
30
|
+
|
|
31
|
+
## Installation
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
npm install @thaddeus/twitter-client
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Both `npm` and `bun` work for installation.
|
|
38
|
+
|
|
39
|
+
Or globally for the CLI:
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
npm install -g @thaddeus/twitter-client
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Authentication
|
|
46
|
+
|
|
47
|
+
This client uses Twitter's cookie-based authentication (same as the web app). You'll need two values from your browser:
|
|
48
|
+
|
|
49
|
+
1. **auth_token** - From cookie `auth_token`
|
|
50
|
+
2. **ct0** - From cookie `ct0`
|
|
51
|
+
|
|
52
|
+
### Getting Credentials
|
|
53
|
+
|
|
54
|
+
1. Open Twitter/X in your browser
|
|
55
|
+
2. Open Developer Tools (F12)
|
|
56
|
+
3. Go to Application > Storage > Cookies
|
|
57
|
+
4. Copy the values for `auth_token` and `ct0`
|
|
58
|
+
|
|
59
|
+
### Setting Up Environment
|
|
60
|
+
|
|
61
|
+
Create a `.env` file:
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
TWITTER_AUTH_TOKEN=your_auth_token_here
|
|
65
|
+
TWITTER_CT0=your_ct0_here
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Known Limitations
|
|
69
|
+
|
|
70
|
+
- **Tweet Posting Error 226**: New or low-activity accounts may get "looks automated" error. Try posting from web interface first to warm up the account.
|
|
71
|
+
- **Rate Limiting**: Not yet implemented - Twitter may temporarily block rapid requests.
|
|
72
|
+
- **Query ID Rotation**: Query IDs rotate frequently (daily/weekly). Use `twitter update-query-ids --fresh` if commands fail.
|
|
73
|
+
|
|
74
|
+
## Query ID Management
|
|
75
|
+
|
|
76
|
+
Twitter rotates GraphQL query IDs frequently. This client handles this automatically:
|
|
77
|
+
|
|
78
|
+
**Auto-Refresh (Recommended):**
|
|
79
|
+
- On 404 errors, the client automatically refreshes query IDs and retries
|
|
80
|
+
- No manual intervention needed
|
|
81
|
+
- Cache updated to `~/.config/twitter-client/query-ids.json` (24h TTL)
|
|
82
|
+
|
|
83
|
+
**Manual Refresh:**
|
|
84
|
+
```bash
|
|
85
|
+
twitter update-query-ids # Update if cache is stale
|
|
86
|
+
twitter update-query-ids --fresh # Force refresh regardless of cache age
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
**How It Works:**
|
|
90
|
+
1. Client fetches Twitter's web client JavaScript bundle
|
|
91
|
+
2. Extracts current query IDs using regex patterns
|
|
92
|
+
3. Caches IDs locally with 24-hour TTL
|
|
93
|
+
4. Falls back to baked-in IDs if scraping fails
|
|
94
|
+
|
|
95
|
+
**Troubleshooting:**
|
|
96
|
+
- If commands fail with "persisted query not found": Run `twitter update-query-ids --fresh`
|
|
97
|
+
- Check cache freshness: `cat ~/.config/twitter-client/query-ids.json`
|
|
98
|
+
- Clear cache: `rm ~/.config/twitter-client/query-ids.json`
|
|
99
|
+
|
|
100
|
+
## Commands
|
|
101
|
+
|
|
102
|
+
### whoami
|
|
103
|
+
|
|
104
|
+
Shows your authenticated Twitter account information.
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
twitter whoami
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Example output:
|
|
111
|
+
```
|
|
112
|
+
Logged in as: @username (Display Name)
|
|
113
|
+
User ID: 1234567890
|
|
114
|
+
Followers: 1,234
|
|
115
|
+
Following: 567
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
**Note:** The `whoami` command uses Twitter's GraphQL API. If you encounter authentication errors, verify your environment variables are set correctly:
|
|
119
|
+
```bash
|
|
120
|
+
echo $TWITTER_AUTH_TOKEN
|
|
121
|
+
echo $TWITTER_CT0
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
## CLI Usage
|
|
125
|
+
|
|
126
|
+
Once installed globally, the `twitter` command is available:
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
# Show current user info
|
|
130
|
+
twitter whoami
|
|
131
|
+
|
|
132
|
+
# Search for tweets
|
|
133
|
+
twitter search "typescript"
|
|
134
|
+
|
|
135
|
+
# Post a tweet
|
|
136
|
+
twitter tweet "Hello, world!"
|
|
137
|
+
|
|
138
|
+
# Get a tweet by ID or URL
|
|
139
|
+
twitter get 1234567890
|
|
140
|
+
twitter get https://x.com/user/status/1234567890
|
|
141
|
+
|
|
142
|
+
# Get tweets from a user
|
|
143
|
+
twitter user username
|
|
144
|
+
|
|
145
|
+
# Get news timeline
|
|
146
|
+
twitter news
|
|
147
|
+
|
|
148
|
+
# Get mentions
|
|
149
|
+
twitter mentions
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
## Library Usage
|
|
153
|
+
|
|
154
|
+
```typescript
|
|
155
|
+
import { TwitterClient } from '@thaddeus/twitter-client';
|
|
156
|
+
|
|
157
|
+
const client = new TwitterClient({
|
|
158
|
+
authToken: process.env.TWITTER_AUTH_TOKEN!,
|
|
159
|
+
ct0: process.env.TWITTER_CT0!,
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
// Get current user info
|
|
163
|
+
const result = await client.whoami();
|
|
164
|
+
if (result.success) {
|
|
165
|
+
console.log(`@${result.user.username}`);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// Search for tweets
|
|
169
|
+
const searchResult = await client.search('typescript');
|
|
170
|
+
if (searchResult.success) {
|
|
171
|
+
searchResult.tweets.forEach(tweet => {
|
|
172
|
+
console.log(`@${tweet.author.username}: ${tweet.text}`);
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// Post a tweet
|
|
177
|
+
const postResult = await client.tweet('Hello from the API!');
|
|
178
|
+
if (postResult.success) {
|
|
179
|
+
console.log(`Tweet ID: ${postResult.tweetId}`);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// Get a tweet
|
|
183
|
+
const tweetResult = await client.getTweet('1234567890');
|
|
184
|
+
if (tweetResult.success) {
|
|
185
|
+
console.log(tweetResult.tweet.text);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// Get user's tweets
|
|
189
|
+
const userResult = await client.getUserTweets('username');
|
|
190
|
+
if (userResult.success) {
|
|
191
|
+
userResult.tweets.forEach(tweet => {
|
|
192
|
+
console.log(tweet.text);
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// Reply to a tweet
|
|
197
|
+
const replyResult = await client.reply('1234567890', 'This is a reply');
|
|
198
|
+
|
|
199
|
+
// Like a tweet
|
|
200
|
+
const likeResult = await client.likeTweet('1234567890');
|
|
201
|
+
|
|
202
|
+
// Unlike a tweet
|
|
203
|
+
const unlikeResult = await client.unlikeTweet('1234567890');
|
|
204
|
+
|
|
205
|
+
// Get news timeline
|
|
206
|
+
const newsResult = await client.getNews();
|
|
207
|
+
if (newsResult.success) {
|
|
208
|
+
newsResult.items.forEach(item => {
|
|
209
|
+
console.log(item.headline);
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// Get mentions
|
|
214
|
+
const mentionsResult = await client.getMentions();
|
|
215
|
+
if (mentionsResult.success) {
|
|
216
|
+
mentionsResult.tweets.forEach(tweet => {
|
|
217
|
+
console.log(`@${tweet.author.username}: ${tweet.text}`);
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
## API Reference
|
|
223
|
+
|
|
224
|
+
### TwitterClient
|
|
225
|
+
|
|
226
|
+
#### Constructor
|
|
227
|
+
|
|
228
|
+
```typescript
|
|
229
|
+
new TwitterClient(options: {
|
|
230
|
+
authToken: string;
|
|
231
|
+
ct0: string;
|
|
232
|
+
timeout?: number;
|
|
233
|
+
})
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
#### Methods
|
|
237
|
+
|
|
238
|
+
##### `whoami(): Promise<UserResult>`
|
|
239
|
+
Verify authentication and get current user info.
|
|
240
|
+
|
|
241
|
+
##### `search(query: string, count?: number): Promise<SearchResult>`
|
|
242
|
+
Search for tweets. Count must be between 1-200 (default: 20).
|
|
243
|
+
|
|
244
|
+
##### `tweet(text: string): Promise<PostResult>`
|
|
245
|
+
Post a new tweet.
|
|
246
|
+
|
|
247
|
+
##### `getTweet(tweetIdOrUrl: string): Promise<TweetResult>`
|
|
248
|
+
Get a single tweet by ID or URL.
|
|
249
|
+
|
|
250
|
+
##### `getUserTweets(username: string, count?: number): Promise<TweetsResult>`
|
|
251
|
+
Get recent tweets from a user.
|
|
252
|
+
|
|
253
|
+
##### `reply(tweetId: string, text: string): Promise<PostResult>`
|
|
254
|
+
Reply to a tweet.
|
|
255
|
+
|
|
256
|
+
##### `likeTweet(tweetId: string): Promise<PostResult>`
|
|
257
|
+
Like a tweet.
|
|
258
|
+
|
|
259
|
+
##### `unlikeTweet(tweetId: string): Promise<PostResult>`
|
|
260
|
+
Unlike a tweet.
|
|
261
|
+
|
|
262
|
+
##### `getNews(count?: number): Promise<NewsResult>`
|
|
263
|
+
Get news timeline (For You timeline). Count must be between 1-200 (default: 20).
|
|
264
|
+
|
|
265
|
+
##### `getMentions(count?: number): Promise<TweetsResult>`
|
|
266
|
+
Get mentions timeline. Count must be between 1-200 (default: 20).
|
|
267
|
+
|
|
268
|
+
### Types
|
|
269
|
+
|
|
270
|
+
#### `Tweet`
|
|
271
|
+
```typescript
|
|
272
|
+
interface Tweet {
|
|
273
|
+
id: string;
|
|
274
|
+
text: string;
|
|
275
|
+
author: User;
|
|
276
|
+
createdAt: string;
|
|
277
|
+
likeCount: number;
|
|
278
|
+
retweetCount: number;
|
|
279
|
+
replyCount: number;
|
|
280
|
+
quoteCount: number;
|
|
281
|
+
viewCount: number;
|
|
282
|
+
bookmarkCount: number;
|
|
283
|
+
media?: MediaItem[];
|
|
284
|
+
isQuote?: boolean;
|
|
285
|
+
quotedTweet?: Tweet;
|
|
286
|
+
isRetweet?: boolean;
|
|
287
|
+
retweetedTweet?: Tweet;
|
|
288
|
+
inReplyTo?: string;
|
|
289
|
+
conversationId?: string;
|
|
290
|
+
}
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
#### `User`
|
|
294
|
+
```typescript
|
|
295
|
+
interface User {
|
|
296
|
+
id: string;
|
|
297
|
+
username: string;
|
|
298
|
+
name: string;
|
|
299
|
+
description?: string;
|
|
300
|
+
followersCount?: number;
|
|
301
|
+
followingCount?: number;
|
|
302
|
+
isBlueVerified?: boolean;
|
|
303
|
+
profileImageUrl?: string;
|
|
304
|
+
createdAt?: string;
|
|
305
|
+
}
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
#### `Result<T>`
|
|
309
|
+
All methods return a Result object:
|
|
310
|
+
```typescript
|
|
311
|
+
interface Result<T> {
|
|
312
|
+
success: true;
|
|
313
|
+
data: T;
|
|
314
|
+
} | {
|
|
315
|
+
success: false;
|
|
316
|
+
error: string;
|
|
317
|
+
code: ErrorCode;
|
|
318
|
+
}
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
## Error Codes
|
|
322
|
+
|
|
323
|
+
- `AUTH_FAILED` - Authentication credentials are invalid or expired
|
|
324
|
+
- `NETWORK_ERROR` - Network request failed
|
|
325
|
+
- `RATE_LIMITED` - Rate limit exceeded
|
|
326
|
+
- `INVALID_INPUT` - Invalid input parameters
|
|
327
|
+
- `NOT_FOUND` - Resource not found
|
|
328
|
+
- `SERVER_ERROR` - Twitter server error
|
|
329
|
+
- `UNKNOWN_ERROR` - Unknown error occurred
|
|
330
|
+
|
|
331
|
+
## Development
|
|
332
|
+
|
|
333
|
+
```bash
|
|
334
|
+
# Install dependencies
|
|
335
|
+
bun install
|
|
336
|
+
|
|
337
|
+
# Run tests
|
|
338
|
+
bun test
|
|
339
|
+
|
|
340
|
+
# Run tests with live API calls
|
|
341
|
+
TWITTER_LIVE=1 bun test tests/live/
|
|
342
|
+
|
|
343
|
+
# Build
|
|
344
|
+
bun run build
|
|
345
|
+
|
|
346
|
+
# Run CLI directly
|
|
347
|
+
bun run dev
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
## License
|
|
351
|
+
|
|
352
|
+
MIT
|
|
353
|
+
|
|
354
|
+
## Contributing
|
|
355
|
+
|
|
356
|
+
Contributions are welcome! Please open an issue or submit a pull request.
|
|
357
|
+
|
|
358
|
+
## Disclaimer
|
|
359
|
+
|
|
360
|
+
This project is not affiliated with Twitter/X. Use at your own risk and make sure to comply with Twitter's Terms of Service.
|