@elizaos/plugin-x 2.0.0-beta.1
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 +536 -0
- package/auto-enable.ts +30 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +12756 -0
- package/dist/index.js.map +1 -0
- package/package.json +394 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Shaw Walters and elizaOS Contributors
|
|
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,536 @@
|
|
|
1
|
+
# Eliza Twitter/X Client
|
|
2
|
+
|
|
3
|
+
This package provides Twitter/X integration for the Eliza AI agent using the official Twitter API v2.
|
|
4
|
+
|
|
5
|
+
## π¨ TL;DR - Quick Setup
|
|
6
|
+
|
|
7
|
+
**Just want your bot to post tweets? Here's the fastest path:**
|
|
8
|
+
|
|
9
|
+
1. **Get Twitter Developer account** β https://developer.twitter.com
|
|
10
|
+
2. **Create an app** β Enable "Read and write" permissions
|
|
11
|
+
3. Choose your auth mode:
|
|
12
|
+
- **Option A (default, legacy): OAuth 1.0a env vars**
|
|
13
|
+
- API Key & Secret (from "Consumer Keys")
|
|
14
|
+
- Access Token & Secret (from "Authentication Tokens")
|
|
15
|
+
|
|
16
|
+
- **Option B (recommended): βlogin + approveβ OAuth 2.0 (PKCE)**
|
|
17
|
+
- Client ID (from "OAuth 2.0 Client ID")
|
|
18
|
+
- Redirect URI (loopback recommended)
|
|
19
|
+
|
|
20
|
+
4. **Add to `.env`:**
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
# Option A: legacy OAuth 1.0a (default)
|
|
24
|
+
TWITTER_AUTH_MODE=env
|
|
25
|
+
TWITTER_API_KEY=xxx
|
|
26
|
+
TWITTER_API_SECRET_KEY=xxx
|
|
27
|
+
TWITTER_ACCESS_TOKEN=xxx
|
|
28
|
+
TWITTER_ACCESS_TOKEN_SECRET=xxx
|
|
29
|
+
|
|
30
|
+
# Option B: OAuth 2.0 PKCE (interactive login + approve, no client secret)
|
|
31
|
+
# TWITTER_AUTH_MODE=oauth
|
|
32
|
+
# TWITTER_CLIENT_ID=xxx
|
|
33
|
+
# TWITTER_REDIRECT_URI=http://127.0.0.1:8080/callback
|
|
34
|
+
|
|
35
|
+
TWITTER_ENABLE_POST=true
|
|
36
|
+
TWITTER_POST_IMMEDIATELY=true
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
5. **Run:** `bun start`
|
|
40
|
+
|
|
41
|
+
Tip: if you use **OAuth 2.0 PKCE**, the plugin will print an authorization URL on first run and store tokens for you (no manual token pasting).
|
|
42
|
+
|
|
43
|
+
## Features
|
|
44
|
+
|
|
45
|
+
- β
**Autonomous tweet posting** with configurable intervals
|
|
46
|
+
- β
**Timeline monitoring** and interaction
|
|
47
|
+
- β
**Mention and reply handling**
|
|
48
|
+
- β
**Search functionality**
|
|
49
|
+
- β
**Direct message support**
|
|
50
|
+
- β
**Advanced timeline algorithms** with weighted scoring
|
|
51
|
+
- β
**Comprehensive caching system**
|
|
52
|
+
- β
**Built-in rate limiting and retry mechanisms**
|
|
53
|
+
- β
**Discovery service** for autonomous content discovery and growth
|
|
54
|
+
|
|
55
|
+
## Prerequisites
|
|
56
|
+
|
|
57
|
+
- Twitter Developer Account with API v2 access
|
|
58
|
+
- Either Twitter OAuth 1.0a credentials (legacy env vars) or OAuth 2.0 Client ID (PKCE)
|
|
59
|
+
- Node.js and bun installed
|
|
60
|
+
|
|
61
|
+
## π Quick Start
|
|
62
|
+
|
|
63
|
+
### Step 1: Get Twitter Developer Access
|
|
64
|
+
|
|
65
|
+
1. Apply for a developer account at https://developer.twitter.com
|
|
66
|
+
2. Create a new app in the [Developer Portal](https://developer.twitter.com/en/portal/projects-and-apps)
|
|
67
|
+
3. Ensure your app has API v2 access
|
|
68
|
+
|
|
69
|
+
### Step 2: Configure App Permissions for Posting
|
|
70
|
+
|
|
71
|
+
**β οΈ CRITICAL: Default apps can only READ. You must enable WRITE permissions to post tweets!**
|
|
72
|
+
|
|
73
|
+
1. In your app settings, go to **"User authentication settings"**
|
|
74
|
+
2. Configure exactly as shown:
|
|
75
|
+
|
|
76
|
+
**App permissions**: `Read and write` β
|
|
77
|
+
|
|
78
|
+
**Type of App**: `Web App, Automated App or Bot`
|
|
79
|
+
|
|
80
|
+
**Required URLs** (copy these exactly):
|
|
81
|
+
|
|
82
|
+
```
|
|
83
|
+
Callback URI: http://localhost:3000/callback
|
|
84
|
+
Website URL: https://github.com/elizaos/eliza
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
**Optional fields**:
|
|
88
|
+
|
|
89
|
+
```
|
|
90
|
+
Organization name: ElizaOS
|
|
91
|
+
Organization URL: https://github.com/elizaos/eliza
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
3. Click **Save**
|
|
95
|
+
|
|
96
|
+
### Step 3: Get the RIGHT Credentials (OAuth 1.0a)
|
|
97
|
+
|
|
98
|
+
You can use either legacy **OAuth 1.0a** env vars (default) or **OAuth 2.0 PKCE** (βlogin + approveβ).
|
|
99
|
+
|
|
100
|
+
In your app's **"Keys and tokens"** page, you'll see several sections. Here's what to use:
|
|
101
|
+
|
|
102
|
+
```
|
|
103
|
+
β
USE THESE when TWITTER_AUTH_MODE=env (OAuth 1.0a):
|
|
104
|
+
βββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
105
|
+
β Consumer Keys β
|
|
106
|
+
β ββ API Key: xxx...xxx β TWITTER_API_KEY β
|
|
107
|
+
β ββ API Key Secret: xxx...xxx β TWITTER_API_SECRET_KEY β
|
|
108
|
+
β β
|
|
109
|
+
β Authentication Tokens β
|
|
110
|
+
β ββ Access Token: xxx...xxx β TWITTER_ACCESS_TOKEN β
|
|
111
|
+
β ββ Access Token Secret: xxx β TWITTER_ACCESS_TOKEN_SECRET β
|
|
112
|
+
βββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
113
|
+
|
|
114
|
+
β
USE THESE when TWITTER_AUTH_MODE=oauth (OAuth 2.0 PKCE):
|
|
115
|
+
βββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
116
|
+
β OAuth 2.0 Client ID and Client Secret β
|
|
117
|
+
β ββ Client ID: xxx...xxx β TWITTER_CLIENT_ID β
|
|
118
|
+
β ββ Client Secret: xxx...xxx β NOT USED (do not put in env) β
|
|
119
|
+
β β
|
|
120
|
+
β Bearer Token β NOT USED β
|
|
121
|
+
βββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
**After enabling write permissions, you MUST:**
|
|
125
|
+
|
|
126
|
+
1. Click **"Regenerate"** on Access Token & Secret
|
|
127
|
+
2. Copy the NEW tokens (old ones won't have write access)
|
|
128
|
+
3. Look for "Created with Read and Write permissions" β
|
|
129
|
+
|
|
130
|
+
### Step 4: Configure Environment Variables
|
|
131
|
+
|
|
132
|
+
Create or edit `.env` file in your project root:
|
|
133
|
+
|
|
134
|
+
```bash
|
|
135
|
+
# Auth mode (default: env)
|
|
136
|
+
# - env: legacy OAuth 1.0a keys/tokens
|
|
137
|
+
# - oauth: βlogin + approveβ OAuth 2.0 PKCE (no client secret in plugin)
|
|
138
|
+
TWITTER_AUTH_MODE=env
|
|
139
|
+
TWITTER_DEFAULT_ACCOUNT_ID=default
|
|
140
|
+
|
|
141
|
+
# REQUIRED: OAuth 1.0a Credentials (from "Consumer Keys" section)
|
|
142
|
+
TWITTER_API_KEY=your_api_key_here # From "API Key"
|
|
143
|
+
TWITTER_API_SECRET_KEY=your_api_key_secret_here # From "API Key Secret"
|
|
144
|
+
|
|
145
|
+
# REQUIRED: OAuth 1.0a Tokens (from "Authentication Tokens" section)
|
|
146
|
+
TWITTER_ACCESS_TOKEN=your_access_token_here # Must have "Read and Write"
|
|
147
|
+
TWITTER_ACCESS_TOKEN_SECRET=your_token_secret_here # Regenerate after permission change
|
|
148
|
+
|
|
149
|
+
# ---- OR ----
|
|
150
|
+
# OAuth 2.0 PKCE (βlogin + approveβ) configuration:
|
|
151
|
+
# TWITTER_AUTH_MODE=oauth
|
|
152
|
+
# TWITTER_CLIENT_ID=your_oauth2_client_id_here
|
|
153
|
+
# TWITTER_REDIRECT_URI=http://127.0.0.1:8080/callback
|
|
154
|
+
# Optional:
|
|
155
|
+
# TWITTER_SCOPES="tweet.read tweet.write users.read offline.access"
|
|
156
|
+
|
|
157
|
+
# Basic Configuration
|
|
158
|
+
TWITTER_DRY_RUN=false # Set to true to test without posting
|
|
159
|
+
TWITTER_ENABLE_POST=true # Enable autonomous tweet posting
|
|
160
|
+
|
|
161
|
+
# Optional: Posting Configuration
|
|
162
|
+
TWITTER_POST_IMMEDIATELY=true # Post on startup (great for testing)
|
|
163
|
+
TWITTER_POST_INTERVAL=120 # Minutes between posts (default: 120)
|
|
164
|
+
# For more natural timing, use MIN/MAX intervals:
|
|
165
|
+
TWITTER_POST_INTERVAL_MIN=90 # Minimum minutes between posts
|
|
166
|
+
TWITTER_POST_INTERVAL_MAX=150 # Maximum minutes between posts
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
When using **TWITTER_AUTH_MODE=oauth**, the plugin will:
|
|
170
|
+
|
|
171
|
+
- Print an authorization URL on first run
|
|
172
|
+
- Capture the callback via a local loopback server **or** ask you to paste the redirected URL
|
|
173
|
+
- Persist tokens per `accountId` via Eliza runtime cache if available, otherwise a local token file under `~/.eliza/twitter/accounts/<accountId>/oauth2.tokens.json`
|
|
174
|
+
|
|
175
|
+
For multi-account pilots, route connector targets with `accountId`. The plugin defaults to `TWITTER_DEFAULT_ACCOUNT_ID` when no target/content account is provided. You can also provide account-scoped credentials through `TWITTER_ACCOUNTS` JSON until the shared connector account store is available.
|
|
176
|
+
|
|
177
|
+
### Step 5: Run Your Bot
|
|
178
|
+
|
|
179
|
+
```typescript
|
|
180
|
+
// Your character should include the twitter plugin
|
|
181
|
+
const character = {
|
|
182
|
+
// ... other config
|
|
183
|
+
plugins: [
|
|
184
|
+
// Required for content generation
|
|
185
|
+
"@elizaos/plugin-x", // X (Twitter) functionality
|
|
186
|
+
],
|
|
187
|
+
postExamples: [
|
|
188
|
+
// Examples for tweet generation
|
|
189
|
+
"Just discovered an amazing pattern in the data...",
|
|
190
|
+
"The future of AI is collaborative intelligence",
|
|
191
|
+
// ... more examples
|
|
192
|
+
],
|
|
193
|
+
};
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
Then start your bot:
|
|
197
|
+
|
|
198
|
+
```bash
|
|
199
|
+
bun run start
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
## π Complete Configuration Reference
|
|
203
|
+
|
|
204
|
+
```bash
|
|
205
|
+
# Required Twitter API v2 Credentials (OAuth 1.0a)
|
|
206
|
+
TWITTER_API_KEY= # Consumer API Key
|
|
207
|
+
TWITTER_API_SECRET_KEY= # Consumer API Secret
|
|
208
|
+
TWITTER_ACCESS_TOKEN= # Access Token (with write permissions)
|
|
209
|
+
TWITTER_ACCESS_TOKEN_SECRET= # Access Token Secret
|
|
210
|
+
|
|
211
|
+
# Core Configuration
|
|
212
|
+
TWITTER_DRY_RUN=false # Set to true for testing without posting
|
|
213
|
+
TWITTER_TARGET_USERS= # Comma-separated usernames to target (use "*" for all)
|
|
214
|
+
TWITTER_RETRY_LIMIT=5 # Maximum retry attempts for failed operations
|
|
215
|
+
|
|
216
|
+
# Feature Toggles
|
|
217
|
+
TWITTER_ENABLE_POST=false # Enable autonomous tweet posting
|
|
218
|
+
TWITTER_ENABLE_REPLIES=true # Enable mention and reply handling
|
|
219
|
+
TWITTER_ENABLE_ACTIONS=false # Enable timeline actions (likes, retweets, quotes)
|
|
220
|
+
TWITTER_ENABLE_DISCOVERY= # Enable discovery service (defaults to true if ACTIONS enabled)
|
|
221
|
+
|
|
222
|
+
# Timing Configuration (all in minutes)
|
|
223
|
+
# For natural behavior, set MIN/MAX intervals - the agent will randomly choose between them
|
|
224
|
+
# If MIN/MAX not set, falls back to the fixed interval values
|
|
225
|
+
|
|
226
|
+
# Post intervals
|
|
227
|
+
TWITTER_POST_INTERVAL=120 # Fixed interval between posts (default: 120, used if MIN/MAX not set)
|
|
228
|
+
TWITTER_POST_INTERVAL_MIN=90 # Minimum minutes between posts (default: 90)
|
|
229
|
+
TWITTER_POST_INTERVAL_MAX=150 # Maximum minutes between posts (default: 150)
|
|
230
|
+
|
|
231
|
+
# Engagement intervals
|
|
232
|
+
TWITTER_ENGAGEMENT_INTERVAL=30 # Fixed interval for interactions (default: 30, used if MIN/MAX not set)
|
|
233
|
+
TWITTER_ENGAGEMENT_INTERVAL_MIN=20 # Minimum minutes between engagements (default: 20)
|
|
234
|
+
TWITTER_ENGAGEMENT_INTERVAL_MAX=40 # Maximum minutes between engagements (default: 40)
|
|
235
|
+
|
|
236
|
+
# Discovery intervals
|
|
237
|
+
TWITTER_DISCOVERY_INTERVAL_MIN=15 # Minimum minutes between discovery cycles (default: 15)
|
|
238
|
+
TWITTER_DISCOVERY_INTERVAL_MAX=30 # Maximum minutes between discovery cycles (default: 30)
|
|
239
|
+
|
|
240
|
+
# Engagement Limits
|
|
241
|
+
TWITTER_MAX_ENGAGEMENTS_PER_RUN=5 # Maximum interactions per engagement cycle (default: 5)
|
|
242
|
+
TWITTER_MAX_TWEET_LENGTH=280 # Maximum tweet length
|
|
243
|
+
|
|
244
|
+
# Discovery Service Settings
|
|
245
|
+
TWITTER_MIN_FOLLOWER_COUNT=100 # Minimum followers for accounts to follow
|
|
246
|
+
TWITTER_MAX_FOLLOWS_PER_CYCLE=5 # Maximum accounts to follow per discovery cycle
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
## π Discovery Service
|
|
250
|
+
|
|
251
|
+
The Twitter Discovery Service enables autonomous content discovery and engagement, helping your agent build a following and interact with relevant content on Twitter.
|
|
252
|
+
|
|
253
|
+
### Overview
|
|
254
|
+
|
|
255
|
+
The discovery service autonomously:
|
|
256
|
+
|
|
257
|
+
- Searches for content related to your agent's topics
|
|
258
|
+
- Identifies high-quality accounts to follow
|
|
259
|
+
- Engages with relevant tweets through likes, replies, and quotes
|
|
260
|
+
- Builds up your agent's timeline by following interesting accounts
|
|
261
|
+
|
|
262
|
+
### Configuration
|
|
263
|
+
|
|
264
|
+
```bash
|
|
265
|
+
# Enable discovery service (defaults to true if TWITTER_ENABLE_ACTIONS=true)
|
|
266
|
+
TWITTER_ENABLE_DISCOVERY=true
|
|
267
|
+
|
|
268
|
+
# Discovery interval in minutes (default: 30)
|
|
269
|
+
TWITTER_DISCOVERY_INTERVAL=30
|
|
270
|
+
|
|
271
|
+
# Minimum follower count for accounts to follow (default: 100)
|
|
272
|
+
TWITTER_MIN_FOLLOWER_COUNT=100
|
|
273
|
+
|
|
274
|
+
# Maximum accounts to follow per cycle (default: 5)
|
|
275
|
+
TWITTER_MAX_FOLLOWS_PER_CYCLE=5
|
|
276
|
+
|
|
277
|
+
# Maximum engagements per cycle (default: 10)
|
|
278
|
+
TWITTER_MAX_ENGAGEMENTS_PER_RUN=10
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
### How It Works
|
|
282
|
+
|
|
283
|
+
1. **Content Discovery**: Searches for tweets containing your agent's topics
|
|
284
|
+
2. **Account Scoring**: Scores accounts based on quality (follower count) and relevance
|
|
285
|
+
3. **Tweet Scoring**: Scores tweets for engagement based on relevance:
|
|
286
|
+
- Like: score > 0.6
|
|
287
|
+
- Reply: score > 0.8
|
|
288
|
+
- Quote: score > 0.85
|
|
289
|
+
4. **Memory System**: Tracks engaged tweets and followed accounts to avoid duplicates
|
|
290
|
+
|
|
291
|
+
### Character Configuration
|
|
292
|
+
|
|
293
|
+
The discovery service uses your agent's character configuration:
|
|
294
|
+
|
|
295
|
+
```json
|
|
296
|
+
{
|
|
297
|
+
"name": "YourAgent",
|
|
298
|
+
"topics": [
|
|
299
|
+
"artificial intelligence",
|
|
300
|
+
"machine learning",
|
|
301
|
+
"web3",
|
|
302
|
+
"blockchain"
|
|
303
|
+
],
|
|
304
|
+
"bio": "AI researcher interested in decentralized systems"
|
|
305
|
+
}
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
If topics aren't specified, the service extracts them from the bio.
|
|
309
|
+
|
|
310
|
+
## π― Common Use Cases
|
|
311
|
+
|
|
312
|
+
### Just Want to Post Tweets?
|
|
313
|
+
|
|
314
|
+
```bash
|
|
315
|
+
# Minimal setup for posting only
|
|
316
|
+
TWITTER_API_KEY=xxx
|
|
317
|
+
TWITTER_API_SECRET_KEY=xxx
|
|
318
|
+
TWITTER_ACCESS_TOKEN=xxx # Must have write permissions!
|
|
319
|
+
TWITTER_ACCESS_TOKEN_SECRET=xxx
|
|
320
|
+
|
|
321
|
+
TWITTER_ENABLE_POST=true
|
|
322
|
+
TWITTER_POST_IMMEDIATELY=true # Great for testing
|
|
323
|
+
TWITTER_ENABLE_REPLIES=false # Disable interactions
|
|
324
|
+
TWITTER_ENABLE_ACTIONS=false # Disable timeline actions
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
### Want Full Interaction Bot?
|
|
328
|
+
|
|
329
|
+
```bash
|
|
330
|
+
# Full interaction setup
|
|
331
|
+
TWITTER_API_KEY=xxx
|
|
332
|
+
TWITTER_API_SECRET_KEY=xxx
|
|
333
|
+
TWITTER_ACCESS_TOKEN=xxx
|
|
334
|
+
TWITTER_ACCESS_TOKEN_SECRET=xxx
|
|
335
|
+
|
|
336
|
+
TWITTER_ENABLE_POST=true
|
|
337
|
+
TWITTER_ENABLE_REPLIES=true
|
|
338
|
+
TWITTER_ENABLE_ACTIONS=true # Enables likes, retweets, quotes
|
|
339
|
+
TWITTER_ENABLE_DISCOVERY=true # Enables growth features
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
### Testing Without Posting?
|
|
343
|
+
|
|
344
|
+
```bash
|
|
345
|
+
# Dry run mode
|
|
346
|
+
TWITTER_DRY_RUN=true # Simulates all actions
|
|
347
|
+
TWITTER_ENABLE_POST=true
|
|
348
|
+
TWITTER_POST_IMMEDIATELY=true
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
## π¨ Troubleshooting
|
|
352
|
+
|
|
353
|
+
### 403 Errors When Engaging with Tweets
|
|
354
|
+
|
|
355
|
+
If you see errors like "Failed to create tweet: Request failed with code 403", this usually means:
|
|
356
|
+
|
|
357
|
+
1. **Missing Write Permissions**: Make sure your Twitter app has "Read and write" permissions
|
|
358
|
+
- Go to your app settings in the Twitter Developer Portal
|
|
359
|
+
- Check that App permissions shows "Read and write" β
|
|
360
|
+
- If not, change it and regenerate your Access Token & Secret
|
|
361
|
+
|
|
362
|
+
2. **Protected Accounts**: The bot may be trying to engage with protected/private accounts
|
|
363
|
+
- The plugin now automatically skips these with a warning
|
|
364
|
+
|
|
365
|
+
3. **Self-Engagement**: Trying to reply to or quote your own tweets
|
|
366
|
+
- Twitter API doesn't allow this and returns 403
|
|
367
|
+
|
|
368
|
+
4. **Account Restrictions**: Your account may have restrictions
|
|
369
|
+
- Check if your account is in good standing
|
|
370
|
+
- Ensure you're not violating Twitter's automation rules
|
|
371
|
+
|
|
372
|
+
The plugin will now:
|
|
373
|
+
|
|
374
|
+
- Automatically detect and skip 403 errors with a warning
|
|
375
|
+
- Continue processing other tweets
|
|
376
|
+
- Mark failed tweets as "skip" to avoid retrying
|
|
377
|
+
|
|
378
|
+
### Other Common Issues
|
|
379
|
+
|
|
380
|
+
### "403 Forbidden" When Posting
|
|
381
|
+
|
|
382
|
+
This is the #1 issue! Your app has read-only permissions.
|
|
383
|
+
|
|
384
|
+
**Solution:**
|
|
385
|
+
|
|
386
|
+
1. Go to app settings β "User authentication settings"
|
|
387
|
+
2. Change to "Read and write"
|
|
388
|
+
3. Save settings
|
|
389
|
+
4. **CRITICAL**: Regenerate your Access Token & Secret
|
|
390
|
+
5. Update `.env` with NEW tokens
|
|
391
|
+
6. Restart your bot
|
|
392
|
+
|
|
393
|
+
**How to verify:** In "Keys and tokens", your Access Token should show "Created with Read and Write permissions"
|
|
394
|
+
|
|
395
|
+
### "Could not authenticate you"
|
|
396
|
+
|
|
397
|
+
This usually means your credentials donβt match your selected auth mode.
|
|
398
|
+
|
|
399
|
+
**Solution:**
|
|
400
|
+
|
|
401
|
+
- If `TWITTER_AUTH_MODE=env`:
|
|
402
|
+
- Use credentials from "Consumer Keys" section (API Key/Secret)
|
|
403
|
+
- Use credentials from "Authentication Tokens" section (Access Token/Secret)
|
|
404
|
+
- Do not use OAuth 2.0 Client ID/Client Secret/Bearer Token for this mode
|
|
405
|
+
- If `TWITTER_AUTH_MODE=oauth`:
|
|
406
|
+
- Use OAuth 2.0 **Client ID** (`TWITTER_CLIENT_ID`)
|
|
407
|
+
- Set a loopback redirect URI (`TWITTER_REDIRECT_URI`, e.g. `http://127.0.0.1:8080/callback`)
|
|
408
|
+
- Do not set/ship a client secret (PKCE flow)
|
|
409
|
+
|
|
410
|
+
### Bot Not Posting Automatically
|
|
411
|
+
|
|
412
|
+
**Checklist:**
|
|
413
|
+
|
|
414
|
+
- β
Is `TWITTER_ENABLE_POST=true`?
|
|
415
|
+
- β
Does your character have `postExamples`?
|
|
416
|
+
- β
Check logs for "Twitter posting is ENABLED"
|
|
417
|
+
- β
Try `TWITTER_POST_IMMEDIATELY=true` for testing
|
|
418
|
+
|
|
419
|
+
### Timeline Not Loading
|
|
420
|
+
|
|
421
|
+
**Common causes:**
|
|
422
|
+
|
|
423
|
+
- Rate limiting (check Twitter Developer Portal)
|
|
424
|
+
- Invalid credentials
|
|
425
|
+
- Account restrictions
|
|
426
|
+
|
|
427
|
+
### "Invalid or expired token"
|
|
428
|
+
|
|
429
|
+
Your tokens may have been revoked or regenerated.
|
|
430
|
+
|
|
431
|
+
**Solution:**
|
|
432
|
+
|
|
433
|
+
1. Go to Twitter Developer Portal
|
|
434
|
+
2. Regenerate all tokens
|
|
435
|
+
3. Update `.env`
|
|
436
|
+
4. Restart bot
|
|
437
|
+
|
|
438
|
+
## π Advanced Features
|
|
439
|
+
|
|
440
|
+
### Timeline Processing
|
|
441
|
+
|
|
442
|
+
The plugin supports two main approaches:
|
|
443
|
+
|
|
444
|
+
- **Timeline Actions**: Process home timeline for likes, retweets, and quotes
|
|
445
|
+
- **Targeted Interactions**: Reply to mentions and specific users
|
|
446
|
+
|
|
447
|
+
### Target User Configuration
|
|
448
|
+
|
|
449
|
+
```bash
|
|
450
|
+
# Interact with everyone (default)
|
|
451
|
+
TWITTER_TARGET_USERS=
|
|
452
|
+
|
|
453
|
+
# Interact with specific users only
|
|
454
|
+
TWITTER_TARGET_USERS=user1,user2,user3
|
|
455
|
+
|
|
456
|
+
# Interact with everyone (explicit)
|
|
457
|
+
TWITTER_TARGET_USERS=*
|
|
458
|
+
```
|
|
459
|
+
|
|
460
|
+
### Natural Posting Intervals
|
|
461
|
+
|
|
462
|
+
The plugin adds variance to all intervals for more human-like behavior:
|
|
463
|
+
|
|
464
|
+
- Post intervals vary by Β±20% by default
|
|
465
|
+
- Discovery intervals vary by Β±10 minutes
|
|
466
|
+
- Engagement intervals vary based on activity
|
|
467
|
+
|
|
468
|
+
### Request Queue & Rate Limiting
|
|
469
|
+
|
|
470
|
+
The plugin includes sophisticated rate limiting:
|
|
471
|
+
|
|
472
|
+
- Automatic retry with exponential backoff
|
|
473
|
+
- Request queue to prevent API abuse
|
|
474
|
+
- Configurable retry limits
|
|
475
|
+
- Built-in caching to reduce API calls
|
|
476
|
+
|
|
477
|
+
## π§ͺ Development & Testing
|
|
478
|
+
|
|
479
|
+
```bash
|
|
480
|
+
# Run tests
|
|
481
|
+
bun test
|
|
482
|
+
|
|
483
|
+
# Run with debug logging
|
|
484
|
+
DEBUG=eliza:* bun start
|
|
485
|
+
|
|
486
|
+
# Test without posting
|
|
487
|
+
TWITTER_DRY_RUN=true bun start
|
|
488
|
+
```
|
|
489
|
+
|
|
490
|
+
### Testing Checklist
|
|
491
|
+
|
|
492
|
+
1. **Test Auth**: Check logs for successful Twitter login
|
|
493
|
+
2. **Test Posting**: Set `TWITTER_POST_IMMEDIATELY=true`
|
|
494
|
+
3. **Test Dry Run**: Use `TWITTER_DRY_RUN=true` first
|
|
495
|
+
4. **Monitor Logs**: Look for "Twitter posting is ENABLED"
|
|
496
|
+
|
|
497
|
+
## π Security Best Practices
|
|
498
|
+
|
|
499
|
+
- Store credentials in `.env` file (never commit!)
|
|
500
|
+
- Use `.env.local` for local development
|
|
501
|
+
- Regularly rotate API keys
|
|
502
|
+
- Monitor API usage in Developer Portal
|
|
503
|
+
- Enable only necessary permissions
|
|
504
|
+
- Review [Twitter's automation rules](https://help.twitter.com/en/rules-and-policies/twitter-automation)
|
|
505
|
+
|
|
506
|
+
## π API Usage & Limits
|
|
507
|
+
|
|
508
|
+
This plugin uses Twitter API v2 endpoints efficiently:
|
|
509
|
+
|
|
510
|
+
- **Home Timeline**: Cached and refreshed periodically
|
|
511
|
+
- **Tweet Creation**: Rate limited automatically
|
|
512
|
+
- **User Lookups**: Cached to reduce calls
|
|
513
|
+
- **Search**: Configurable intervals
|
|
514
|
+
|
|
515
|
+
Monitor your usage at: https://developer.twitter.com/en/portal/dashboard
|
|
516
|
+
|
|
517
|
+
## π Additional Resources
|
|
518
|
+
|
|
519
|
+
- [Twitter API v2 Documentation](https://developer.twitter.com/en/docs/twitter-api)
|
|
520
|
+
- [Twitter OAuth 1.0a Guide](https://developer.twitter.com/en/docs/authentication/oauth-1-0a)
|
|
521
|
+
- [Twitter OAuth 2.0 (Authorization Code with PKCE)](https://developer.twitter.com/en/docs/authentication/oauth-2-0/authorization-code)
|
|
522
|
+
- [Rate Limits Reference](https://developer.twitter.com/en/docs/twitter-api/rate-limits)
|
|
523
|
+
- [ElizaOS Documentation](https://github.com/elizaos/eliza)
|
|
524
|
+
|
|
525
|
+
## π€ Contributing
|
|
526
|
+
|
|
527
|
+
Contributions are welcome! Please:
|
|
528
|
+
|
|
529
|
+
1. Check existing issues first
|
|
530
|
+
2. Follow the code style
|
|
531
|
+
3. Add tests for new features
|
|
532
|
+
4. Update documentation
|
|
533
|
+
|
|
534
|
+
## π License
|
|
535
|
+
|
|
536
|
+
This plugin is part of the ElizaOS project. See the main repository for license information.
|
package/auto-enable.ts
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
// Auto-enable check for @elizaos/plugin-x.
|
|
2
|
+
//
|
|
3
|
+
// Plugin manifest entry-point β referenced by package.json's
|
|
4
|
+
// `elizaos.plugin.autoEnableModule`. Keep this module light: env reads only,
|
|
5
|
+
// no service init, no transitive imports of the full plugin runtime. The
|
|
6
|
+
// auto-enable engine loads dozens of these per boot.
|
|
7
|
+
import type { PluginAutoEnableContext } from "@elizaos/core";
|
|
8
|
+
|
|
9
|
+
/** Enable when an `x` (or legacy `twitter`) connector block is present and not explicitly disabled. */
|
|
10
|
+
export function shouldEnable(ctx: PluginAutoEnableContext): boolean {
|
|
11
|
+
const connectors = ctx.config?.connectors as
|
|
12
|
+
| Record<string, unknown>
|
|
13
|
+
| undefined;
|
|
14
|
+
if (!connectors) return false;
|
|
15
|
+
|
|
16
|
+
// Either `connectors.x` or the legacy `connectors.twitter` enables the plugin.
|
|
17
|
+
for (const key of ["x", "twitter"] as const) {
|
|
18
|
+
const c = connectors[key];
|
|
19
|
+
if (!c || typeof c !== "object") continue;
|
|
20
|
+
const config = c as Record<string, unknown>;
|
|
21
|
+
if (config.enabled === false) continue;
|
|
22
|
+
// The full per-connector field check (apiKey/apiSecret/accessToken) lives
|
|
23
|
+
// in the central engine's isConnectorConfigured. We delegate to a simple
|
|
24
|
+
// "block present + not explicitly disabled" check here; the central
|
|
25
|
+
// engine's stricter check remains as a fallback during migration.
|
|
26
|
+
return true;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return false;
|
|
30
|
+
}
|