wolverine-ai 6.6.2 → 7.0.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/package.json +1 -1
- package/src/claw/claw-runner.js +5 -0
- package/src/core/runner.js +17 -0
- package/src/security/code-guard.js +569 -0
- package/src/security/self-improve.js +289 -0
- package/wolverine-claw/config/settings.json +1 -1
- package/wolverine-claw/skills/browser/README.md +17 -0
- package/wolverine-claw/skills/browser/SKILL.md +11 -0
- package/wolverine-claw/skills/browser/_meta.json +6 -0
- package/wolverine-claw/skills/browser/index.js +41 -0
- package/wolverine-claw/skills/discord/SKILL.md +369 -0
- package/wolverine-claw/skills/discord/_meta.json +6 -0
- package/wolverine-claw/skills/telegram/SKILL.md +43 -0
- package/wolverine-claw/skills/telegram/_meta.json +6 -0
- package/wolverine-claw/skills/telegram/references/telegram-bot-api.md +63 -0
- package/wolverine-claw/skills/telegram/references/telegram-commands-playbook.md +26 -0
- package/wolverine-claw/skills/telegram/references/telegram-request-templates.md +42 -0
- package/wolverine-claw/skills/telegram/references/telegram-update-routing.md +23 -0
- package/wolverine-claw/skills/twitter-post/SKILL.md +98 -0
- package/wolverine-claw/skills/twitter-post/_meta.json +6 -0
- package/wolverine-claw/skills/twitter-post/scripts/tweet.js +198 -0
|
@@ -0,0 +1,369 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: discord
|
|
3
|
+
description: Use when you need to control Discord from Clawdbot via the discord tool: send messages, react, post or upload stickers, upload emojis, run polls, manage threads/pins/search, fetch permissions or member/role/channel info, or handle moderation actions in Discord DMs or channels.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Discord Actions
|
|
7
|
+
|
|
8
|
+
## Overview
|
|
9
|
+
|
|
10
|
+
Use `discord` to manage messages, reactions, threads, polls, and moderation. You can disable groups via `discord.actions.*` (defaults to enabled, except roles/moderation). The tool uses the bot token configured for Clawdbot.
|
|
11
|
+
|
|
12
|
+
## Inputs to collect
|
|
13
|
+
|
|
14
|
+
- For reactions: `channelId`, `messageId`, and an `emoji`.
|
|
15
|
+
- For stickers/polls/sendMessage: a `to` target (`channel:<id>` or `user:<id>`). Optional `content` text.
|
|
16
|
+
- Polls also need a `question` plus 2–10 `answers`.
|
|
17
|
+
- For media: `mediaUrl` with `file:///path` for local files or `https://...` for remote.
|
|
18
|
+
- For emoji uploads: `guildId`, `name`, `mediaUrl`, optional `roleIds` (limit 256KB, PNG/JPG/GIF).
|
|
19
|
+
- For sticker uploads: `guildId`, `name`, `description`, `tags`, `mediaUrl` (limit 512KB, PNG/APNG/Lottie JSON).
|
|
20
|
+
|
|
21
|
+
Message context lines include `discord message id` and `channel` fields you can reuse directly.
|
|
22
|
+
|
|
23
|
+
**Note:** `sendMessage` uses `to: "channel:<id>"` format, not `channelId`. Other actions like `react`, `readMessages`, `editMessage` use `channelId` directly.
|
|
24
|
+
|
|
25
|
+
## Actions
|
|
26
|
+
|
|
27
|
+
### React to a message
|
|
28
|
+
|
|
29
|
+
```json
|
|
30
|
+
{
|
|
31
|
+
"action": "react",
|
|
32
|
+
"channelId": "123",
|
|
33
|
+
"messageId": "456",
|
|
34
|
+
"emoji": "✅"
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### List reactions + users
|
|
39
|
+
|
|
40
|
+
```json
|
|
41
|
+
{
|
|
42
|
+
"action": "reactions",
|
|
43
|
+
"channelId": "123",
|
|
44
|
+
"messageId": "456",
|
|
45
|
+
"limit": 100
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### Send a sticker
|
|
50
|
+
|
|
51
|
+
```json
|
|
52
|
+
{
|
|
53
|
+
"action": "sticker",
|
|
54
|
+
"to": "channel:123",
|
|
55
|
+
"stickerIds": ["9876543210"],
|
|
56
|
+
"content": "Nice work!"
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
- Up to 3 sticker IDs per message.
|
|
61
|
+
- `to` can be `user:<id>` for DMs.
|
|
62
|
+
|
|
63
|
+
### Upload a custom emoji
|
|
64
|
+
|
|
65
|
+
```json
|
|
66
|
+
{
|
|
67
|
+
"action": "emojiUpload",
|
|
68
|
+
"guildId": "999",
|
|
69
|
+
"name": "party_blob",
|
|
70
|
+
"mediaUrl": "file:///tmp/party.png",
|
|
71
|
+
"roleIds": ["222"]
|
|
72
|
+
}
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
- Emoji images must be PNG/JPG/GIF and <= 256KB.
|
|
76
|
+
- `roleIds` is optional; omit to make the emoji available to everyone.
|
|
77
|
+
|
|
78
|
+
### Upload a sticker
|
|
79
|
+
|
|
80
|
+
```json
|
|
81
|
+
{
|
|
82
|
+
"action": "stickerUpload",
|
|
83
|
+
"guildId": "999",
|
|
84
|
+
"name": "clawdbot_wave",
|
|
85
|
+
"description": "Clawdbot waving hello",
|
|
86
|
+
"tags": "👋",
|
|
87
|
+
"mediaUrl": "file:///tmp/wave.png"
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
- Stickers require `name`, `description`, and `tags`.
|
|
92
|
+
- Uploads must be PNG/APNG/Lottie JSON and <= 512KB.
|
|
93
|
+
|
|
94
|
+
### Create a poll
|
|
95
|
+
|
|
96
|
+
```json
|
|
97
|
+
{
|
|
98
|
+
"action": "poll",
|
|
99
|
+
"to": "channel:123",
|
|
100
|
+
"question": "Lunch?",
|
|
101
|
+
"answers": ["Pizza", "Sushi", "Salad"],
|
|
102
|
+
"allowMultiselect": false,
|
|
103
|
+
"durationHours": 24,
|
|
104
|
+
"content": "Vote now"
|
|
105
|
+
}
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
- `durationHours` defaults to 24; max 32 days (768 hours).
|
|
109
|
+
|
|
110
|
+
### Check bot permissions for a channel
|
|
111
|
+
|
|
112
|
+
```json
|
|
113
|
+
{
|
|
114
|
+
"action": "permissions",
|
|
115
|
+
"channelId": "123"
|
|
116
|
+
}
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
## Ideas to try
|
|
120
|
+
|
|
121
|
+
- React with ✅/⚠️ to mark status updates.
|
|
122
|
+
- Post a quick poll for release decisions or meeting times.
|
|
123
|
+
- Send celebratory stickers after successful deploys.
|
|
124
|
+
- Upload new emojis/stickers for release moments.
|
|
125
|
+
- Run weekly “priority check” polls in team channels.
|
|
126
|
+
- DM stickers as acknowledgements when a user’s request is completed.
|
|
127
|
+
|
|
128
|
+
## Action gating
|
|
129
|
+
|
|
130
|
+
Use `discord.actions.*` to disable action groups:
|
|
131
|
+
- `reactions` (react + reactions list + emojiList)
|
|
132
|
+
- `stickers`, `polls`, `permissions`, `messages`, `threads`, `pins`, `search`
|
|
133
|
+
- `emojiUploads`, `stickerUploads`
|
|
134
|
+
- `memberInfo`, `roleInfo`, `channelInfo`, `voiceStatus`, `events`
|
|
135
|
+
- `roles` (role add/remove, default `false`)
|
|
136
|
+
- `moderation` (timeout/kick/ban, default `false`)
|
|
137
|
+
### Read recent messages
|
|
138
|
+
|
|
139
|
+
```json
|
|
140
|
+
{
|
|
141
|
+
"action": "readMessages",
|
|
142
|
+
"channelId": "123",
|
|
143
|
+
"limit": 20
|
|
144
|
+
}
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### Send/edit/delete a message
|
|
148
|
+
|
|
149
|
+
```json
|
|
150
|
+
{
|
|
151
|
+
"action": "sendMessage",
|
|
152
|
+
"to": "channel:123",
|
|
153
|
+
"content": "Hello from Clawdbot"
|
|
154
|
+
}
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
**With media attachment:**
|
|
158
|
+
|
|
159
|
+
```json
|
|
160
|
+
{
|
|
161
|
+
"action": "sendMessage",
|
|
162
|
+
"to": "channel:123",
|
|
163
|
+
"content": "Check out this audio!",
|
|
164
|
+
"mediaUrl": "file:///tmp/audio.mp3"
|
|
165
|
+
}
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
- `to` uses format `channel:<id>` or `user:<id>` for DMs (not `channelId`!)
|
|
169
|
+
- `mediaUrl` supports local files (`file:///path/to/file`) and remote URLs (`https://...`)
|
|
170
|
+
- Optional `replyTo` with a message ID to reply to a specific message
|
|
171
|
+
|
|
172
|
+
```json
|
|
173
|
+
{
|
|
174
|
+
"action": "editMessage",
|
|
175
|
+
"channelId": "123",
|
|
176
|
+
"messageId": "456",
|
|
177
|
+
"content": "Fixed typo"
|
|
178
|
+
}
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
```json
|
|
182
|
+
{
|
|
183
|
+
"action": "deleteMessage",
|
|
184
|
+
"channelId": "123",
|
|
185
|
+
"messageId": "456"
|
|
186
|
+
}
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
### Threads
|
|
190
|
+
|
|
191
|
+
```json
|
|
192
|
+
{
|
|
193
|
+
"action": "threadCreate",
|
|
194
|
+
"channelId": "123",
|
|
195
|
+
"name": "Bug triage",
|
|
196
|
+
"messageId": "456"
|
|
197
|
+
}
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
```json
|
|
201
|
+
{
|
|
202
|
+
"action": "threadList",
|
|
203
|
+
"guildId": "999"
|
|
204
|
+
}
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
```json
|
|
208
|
+
{
|
|
209
|
+
"action": "threadReply",
|
|
210
|
+
"channelId": "777",
|
|
211
|
+
"content": "Replying in thread"
|
|
212
|
+
}
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
### Pins
|
|
216
|
+
|
|
217
|
+
```json
|
|
218
|
+
{
|
|
219
|
+
"action": "pinMessage",
|
|
220
|
+
"channelId": "123",
|
|
221
|
+
"messageId": "456"
|
|
222
|
+
}
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
```json
|
|
226
|
+
{
|
|
227
|
+
"action": "listPins",
|
|
228
|
+
"channelId": "123"
|
|
229
|
+
}
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
### Search messages
|
|
233
|
+
|
|
234
|
+
```json
|
|
235
|
+
{
|
|
236
|
+
"action": "searchMessages",
|
|
237
|
+
"guildId": "999",
|
|
238
|
+
"content": "release notes",
|
|
239
|
+
"channelIds": ["123", "456"],
|
|
240
|
+
"limit": 10
|
|
241
|
+
}
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
### Member + role info
|
|
245
|
+
|
|
246
|
+
```json
|
|
247
|
+
{
|
|
248
|
+
"action": "memberInfo",
|
|
249
|
+
"guildId": "999",
|
|
250
|
+
"userId": "111"
|
|
251
|
+
}
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
```json
|
|
255
|
+
{
|
|
256
|
+
"action": "roleInfo",
|
|
257
|
+
"guildId": "999"
|
|
258
|
+
}
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
### List available custom emojis
|
|
262
|
+
|
|
263
|
+
```json
|
|
264
|
+
{
|
|
265
|
+
"action": "emojiList",
|
|
266
|
+
"guildId": "999"
|
|
267
|
+
}
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
### Role changes (disabled by default)
|
|
271
|
+
|
|
272
|
+
```json
|
|
273
|
+
{
|
|
274
|
+
"action": "roleAdd",
|
|
275
|
+
"guildId": "999",
|
|
276
|
+
"userId": "111",
|
|
277
|
+
"roleId": "222"
|
|
278
|
+
}
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
### Channel info
|
|
282
|
+
|
|
283
|
+
```json
|
|
284
|
+
{
|
|
285
|
+
"action": "channelInfo",
|
|
286
|
+
"channelId": "123"
|
|
287
|
+
}
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
```json
|
|
291
|
+
{
|
|
292
|
+
"action": "channelList",
|
|
293
|
+
"guildId": "999"
|
|
294
|
+
}
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
### Voice status
|
|
298
|
+
|
|
299
|
+
```json
|
|
300
|
+
{
|
|
301
|
+
"action": "voiceStatus",
|
|
302
|
+
"guildId": "999",
|
|
303
|
+
"userId": "111"
|
|
304
|
+
}
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
### Scheduled events
|
|
308
|
+
|
|
309
|
+
```json
|
|
310
|
+
{
|
|
311
|
+
"action": "eventList",
|
|
312
|
+
"guildId": "999"
|
|
313
|
+
}
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
### Moderation (disabled by default)
|
|
317
|
+
|
|
318
|
+
```json
|
|
319
|
+
{
|
|
320
|
+
"action": "timeout",
|
|
321
|
+
"guildId": "999",
|
|
322
|
+
"userId": "111",
|
|
323
|
+
"durationMinutes": 10
|
|
324
|
+
}
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
## Discord Writing Style Guide
|
|
328
|
+
|
|
329
|
+
**Keep it conversational!** Discord is a chat platform, not documentation.
|
|
330
|
+
|
|
331
|
+
### Do
|
|
332
|
+
- Short, punchy messages (1-3 sentences ideal)
|
|
333
|
+
- Multiple quick replies > one wall of text
|
|
334
|
+
- Use emoji for tone/emphasis 🦞
|
|
335
|
+
- Lowercase casual style is fine
|
|
336
|
+
- Break up info into digestible chunks
|
|
337
|
+
- Match the energy of the conversation
|
|
338
|
+
|
|
339
|
+
### Don't
|
|
340
|
+
- No markdown tables (Discord renders them as ugly raw `| text |`)
|
|
341
|
+
- No `## Headers` for casual chat (use **bold** or CAPS for emphasis)
|
|
342
|
+
- Avoid multi-paragraph essays
|
|
343
|
+
- Don't over-explain simple things
|
|
344
|
+
- Skip the "I'd be happy to help!" fluff
|
|
345
|
+
|
|
346
|
+
### Formatting that works
|
|
347
|
+
- **bold** for emphasis
|
|
348
|
+
- `code` for technical terms
|
|
349
|
+
- Lists for multiple items
|
|
350
|
+
- > quotes for referencing
|
|
351
|
+
- Wrap multiple links in `<>` to suppress embeds
|
|
352
|
+
|
|
353
|
+
### Example transformations
|
|
354
|
+
|
|
355
|
+
❌ Bad:
|
|
356
|
+
```
|
|
357
|
+
I'd be happy to help with that! Here's a comprehensive overview of the versioning strategies available:
|
|
358
|
+
|
|
359
|
+
## Semantic Versioning
|
|
360
|
+
Semver uses MAJOR.MINOR.PATCH format where...
|
|
361
|
+
|
|
362
|
+
## Calendar Versioning
|
|
363
|
+
CalVer uses date-based versions like...
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
✅ Good:
|
|
367
|
+
```
|
|
368
|
+
versioning options: semver (1.2.3), calver (2026.01.04), or yolo (`latest` forever). what fits your release cadence?
|
|
369
|
+
```
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: telegram
|
|
3
|
+
description: OpenClaw skill for designing Telegram Bot API workflows and command-driven conversations using direct HTTPS requests (no SDKs).
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Telegram Bot Skill (Advanced)
|
|
7
|
+
|
|
8
|
+
## Purpose
|
|
9
|
+
Provide a clean, production-oriented guide for building Telegram bot workflows via the Bot API, focusing on command UX, update handling, and safe operations using plain HTTPS.
|
|
10
|
+
|
|
11
|
+
## Best fit
|
|
12
|
+
- You want a command-first bot that behaves professionally.
|
|
13
|
+
- You need a reliable update flow (webhook or polling).
|
|
14
|
+
- You prefer direct HTTP calls instead of libraries.
|
|
15
|
+
|
|
16
|
+
## Not a fit
|
|
17
|
+
- You require a full SDK or framework integration.
|
|
18
|
+
- You need complex media uploads and streaming in-process.
|
|
19
|
+
|
|
20
|
+
## Quick orientation
|
|
21
|
+
- Read `references/telegram-bot-api.md` for endpoints, update types, and request patterns.
|
|
22
|
+
- Read `references/telegram-commands-playbook.md` for command UX and messaging style.
|
|
23
|
+
- Read `references/telegram-update-routing.md` for update normalization and routing rules.
|
|
24
|
+
- Read `references/telegram-request-templates.md` for HTTP payload templates.
|
|
25
|
+
- Keep this SKILL.md short and use references for details.
|
|
26
|
+
|
|
27
|
+
## Required inputs
|
|
28
|
+
- Bot token and base API URL.
|
|
29
|
+
- Update strategy: webhook or long polling.
|
|
30
|
+
- Command list and conversation tone.
|
|
31
|
+
- Allowed update types and rate-limit posture.
|
|
32
|
+
|
|
33
|
+
## Expected output
|
|
34
|
+
- A clear command design, update flow plan, and operational checklist.
|
|
35
|
+
|
|
36
|
+
## Operational notes
|
|
37
|
+
- Prefer strict command routing: `/start`, `/help`, `/settings`, `/status`.
|
|
38
|
+
- Always validate incoming update payloads and chat context.
|
|
39
|
+
- Handle 429s with backoff and avoid message bursts.
|
|
40
|
+
|
|
41
|
+
## Security notes
|
|
42
|
+
- Never log tokens.
|
|
43
|
+
- Use webhooks with a secret token header when possible.
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# Telegram Bot API Field Notes
|
|
2
|
+
|
|
3
|
+
## 1) Base URL and request style
|
|
4
|
+
- Base format: `https://api.telegram.org/bot<token>/<method>`
|
|
5
|
+
- Use GET or POST with JSON or form-encoded payloads.
|
|
6
|
+
- File uploads use `multipart/form-data` and `attach://` references.
|
|
7
|
+
|
|
8
|
+
## 2) Updates and delivery models
|
|
9
|
+
### Long polling
|
|
10
|
+
- `getUpdates` delivers updates with an `offset` cursor and `timeout`.
|
|
11
|
+
|
|
12
|
+
### Webhook
|
|
13
|
+
- `setWebhook` switches the bot to webhook mode.
|
|
14
|
+
- Webhook URLs must be HTTPS. Check the official docs for port restrictions.
|
|
15
|
+
|
|
16
|
+
### Update types (examples)
|
|
17
|
+
- `message`, `edited_message`, `channel_post`, `edited_channel_post`
|
|
18
|
+
- `inline_query`, `chosen_inline_result`, `callback_query`
|
|
19
|
+
- `shipping_query`, `pre_checkout_query`, `poll`, `poll_answer`
|
|
20
|
+
|
|
21
|
+
Use `allowed_updates` to limit which updates you receive.
|
|
22
|
+
|
|
23
|
+
## 3) High-traffic-safe patterns
|
|
24
|
+
- Use `allowed_updates` to reduce noise.
|
|
25
|
+
- Keep handlers idempotent (Telegram may retry).
|
|
26
|
+
- Return quickly from webhooks; process heavy work async.
|
|
27
|
+
|
|
28
|
+
## 4) Common methods (non-exhaustive)
|
|
29
|
+
- `getMe`, `getUpdates`, `setWebhook`
|
|
30
|
+
- `sendMessage`, `editMessageText`, `deleteMessage`
|
|
31
|
+
- `sendPhoto`, `sendDocument`, `sendChatAction`
|
|
32
|
+
- `answerCallbackQuery`, `answerInlineQuery`
|
|
33
|
+
|
|
34
|
+
## 5) Common fields (non-exhaustive)
|
|
35
|
+
### sendMessage
|
|
36
|
+
- `chat_id`, `text`, `parse_mode`
|
|
37
|
+
- `entities`, `disable_web_page_preview`
|
|
38
|
+
- `reply_markup` (inline keyboard, reply keyboard)
|
|
39
|
+
|
|
40
|
+
### reply_markup (inline keyboard)
|
|
41
|
+
- `inline_keyboard`: array of button rows
|
|
42
|
+
- Buttons can contain `text` + `callback_data` or `url`
|
|
43
|
+
|
|
44
|
+
### callback_query
|
|
45
|
+
- `id`, `from`, `message`, `data`
|
|
46
|
+
|
|
47
|
+
### sendChatAction
|
|
48
|
+
- `action`: `typing`, `upload_photo`, `upload_document`, `upload_video`, `choose_sticker`
|
|
49
|
+
|
|
50
|
+
## 6) Command UX checklist
|
|
51
|
+
- `/start`: greet, explain features, and show main commands.
|
|
52
|
+
- `/help`: include short examples and support contact.
|
|
53
|
+
- `/settings`: show toggles with inline keyboards.
|
|
54
|
+
- `/status`: show recent job results or queue size.
|
|
55
|
+
|
|
56
|
+
## 7) Error handling
|
|
57
|
+
- `429`: back off and retry.
|
|
58
|
+
- `400`: validate chat_id, message length, and formatting.
|
|
59
|
+
- `403`: bot blocked or chat not accessible.
|
|
60
|
+
|
|
61
|
+
## 8) Reference links
|
|
62
|
+
- https://core.telegram.org/bots/api
|
|
63
|
+
- https://core.telegram.org/bots/faq
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Telegram Command Playbook
|
|
2
|
+
|
|
3
|
+
## Command set (professional baseline)
|
|
4
|
+
- `/start`: greet, set expectations, and show main actions.
|
|
5
|
+
- `/help`: short help + examples.
|
|
6
|
+
- `/status`: show last job result, queue length, or uptime.
|
|
7
|
+
- `/settings`: show toggles via inline keyboard.
|
|
8
|
+
- `/about`: short bot description and support contact.
|
|
9
|
+
|
|
10
|
+
## Command UX patterns
|
|
11
|
+
- Acknowledge fast, then do heavy work asynchronously.
|
|
12
|
+
- Prefer short replies with a single call-to-action.
|
|
13
|
+
- Always include “what next?” in `/start` and `/help`.
|
|
14
|
+
|
|
15
|
+
## Inline keyboard patterns
|
|
16
|
+
- Use stable callback_data names (e.g., `settings:notifications:on`).
|
|
17
|
+
- Keep callbacks idempotent.
|
|
18
|
+
|
|
19
|
+
## Message style guidelines
|
|
20
|
+
- Use MarkdownV2 or HTML consistently; avoid mixing.
|
|
21
|
+
- If using MarkdownV2, escape reserved characters.
|
|
22
|
+
- Keep single message length under safe limits; split when needed.
|
|
23
|
+
|
|
24
|
+
## Examples (short)
|
|
25
|
+
- `/start` reply: “Hi! I can publish posts and send alerts. Try /help.”
|
|
26
|
+
- `/status` reply: “Queue: 2 jobs. Last run: success 2m ago.”
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Telegram Request Templates (HTTP)
|
|
2
|
+
|
|
3
|
+
## sendMessage
|
|
4
|
+
POST `/sendMessage`
|
|
5
|
+
```json
|
|
6
|
+
{
|
|
7
|
+
"chat_id": 123456789,
|
|
8
|
+
"text": "Hello",
|
|
9
|
+
"parse_mode": "HTML",
|
|
10
|
+
"disable_web_page_preview": true
|
|
11
|
+
}
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## editMessageText
|
|
15
|
+
POST `/editMessageText`
|
|
16
|
+
```json
|
|
17
|
+
{
|
|
18
|
+
"chat_id": 123456789,
|
|
19
|
+
"message_id": 42,
|
|
20
|
+
"text": "Updated",
|
|
21
|
+
"parse_mode": "HTML"
|
|
22
|
+
}
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## answerCallbackQuery
|
|
26
|
+
POST `/answerCallbackQuery`
|
|
27
|
+
```json
|
|
28
|
+
{
|
|
29
|
+
"callback_query_id": "1234567890",
|
|
30
|
+
"text": "Saved"
|
|
31
|
+
}
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## setWebhook
|
|
35
|
+
POST `/setWebhook`
|
|
36
|
+
```json
|
|
37
|
+
{
|
|
38
|
+
"url": "https://example.com/telegram/webhook",
|
|
39
|
+
"secret_token": "your-secret",
|
|
40
|
+
"allowed_updates": ["message","callback_query"]
|
|
41
|
+
}
|
|
42
|
+
```
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Telegram Update Routing
|
|
2
|
+
|
|
3
|
+
## Update normalization
|
|
4
|
+
- Normalize inbound updates to a single envelope:
|
|
5
|
+
- `update_id`, `chat_id`, `user_id`, `message_id`, `text`, `callback_data`, `type`
|
|
6
|
+
- This makes routing logic consistent across message types.
|
|
7
|
+
|
|
8
|
+
## Routing rules
|
|
9
|
+
- If `callback_query` exists, handle callbacks first.
|
|
10
|
+
- Else if `message.text` starts with `/`, treat as command.
|
|
11
|
+
- Else fall back to default handler (help or menu).
|
|
12
|
+
|
|
13
|
+
## Safe defaults
|
|
14
|
+
- Unknown command: reply with `/help` guidance.
|
|
15
|
+
- Unknown callback: answerCallbackQuery with a short notice.
|
|
16
|
+
|
|
17
|
+
## Idempotency
|
|
18
|
+
- Keep a cache of processed `update_id` in case of retries.
|
|
19
|
+
- Ensure handlers can be safely re-run.
|
|
20
|
+
|
|
21
|
+
## Error handling
|
|
22
|
+
- On 429: backoff and retry with jitter.
|
|
23
|
+
- On 400: validate payload length and parse mode.
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: twitter-post
|
|
3
|
+
description: Post tweets to Twitter/X via the official API v2 (OAuth 1.0a). Use when the user asks to tweet, post to Twitter/X, send a thread, reply to a tweet, or quote tweet. Supports single tweets, threads, replies, and quote tweets with automatic character weight validation.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Twitter Post
|
|
7
|
+
|
|
8
|
+
Post tweets via the official Twitter/X API v2 using OAuth 1.0a authentication.
|
|
9
|
+
|
|
10
|
+
## Prerequisites
|
|
11
|
+
|
|
12
|
+
Four environment variables must be set. Obtain them from [developer.x.com](https://developer.x.com):
|
|
13
|
+
|
|
14
|
+
```
|
|
15
|
+
TWITTER_CONSUMER_KEY=<API Key>
|
|
16
|
+
TWITTER_CONSUMER_SECRET=<API Key Secret>
|
|
17
|
+
TWITTER_ACCESS_TOKEN=<Access Token>
|
|
18
|
+
TWITTER_ACCESS_TOKEN_SECRET=<Access Token Secret>
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Optional:
|
|
22
|
+
- `HTTPS_PROXY` — HTTP proxy URL (e.g. `http://127.0.0.1:7897`) for regions that need it
|
|
23
|
+
- `TWITTER_DRY_RUN=1` — validate and print without posting
|
|
24
|
+
|
|
25
|
+
## Setup
|
|
26
|
+
|
|
27
|
+
Store credentials as env vars. Recommended: add to the OpenClaw instance config or export in shell profile. **Never hardcode keys in SKILL.md or scripts.**
|
|
28
|
+
|
|
29
|
+
If the user hasn't set up OAuth yet, guide them:
|
|
30
|
+
|
|
31
|
+
1. Go to [developer.x.com](https://developer.x.com) → Dashboard → Create App
|
|
32
|
+
2. Set **App permissions** to **Read and Write**
|
|
33
|
+
3. Go to **Keys and tokens** tab
|
|
34
|
+
4. Copy API Key, API Key Secret
|
|
35
|
+
5. Generate Access Token and Access Token Secret (ensure Read+Write scope)
|
|
36
|
+
6. If the portal only shows Read, use PIN-based OAuth flow:
|
|
37
|
+
- Call `POST /oauth/request_token` with `oauth_callback=oob`
|
|
38
|
+
- User opens `https://api.twitter.com/oauth/authorize?oauth_token=<token>`
|
|
39
|
+
- User provides the PIN code
|
|
40
|
+
- Call `POST /oauth/access_token` with the PIN as `oauth_verifier`
|
|
41
|
+
|
|
42
|
+
## Usage
|
|
43
|
+
|
|
44
|
+
All commands via `exec`. Script path: `scripts/tweet.js` (relative to this skill directory).
|
|
45
|
+
|
|
46
|
+
### Single tweet
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
node scripts/tweet.js "Your tweet content here"
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### Reply to a tweet
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
node scripts/tweet.js --reply-to 1234567890 "Reply text"
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Quote tweet
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
node scripts/tweet.js --quote 1234567890 "Your commentary"
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Thread (multiple tweets)
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
node scripts/tweet.js --thread "First tweet" "Second tweet" "Third tweet"
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### Output
|
|
71
|
+
|
|
72
|
+
JSON to stdout:
|
|
73
|
+
|
|
74
|
+
```json
|
|
75
|
+
{"ok":true,"id":"123456789","url":"https://x.com/i/status/123456789","remaining":"99","limit":"100"}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
On error: `{"ok":false,"error":"..."}`
|
|
79
|
+
|
|
80
|
+
## Character Limits
|
|
81
|
+
|
|
82
|
+
- Max 280 weighted characters per tweet
|
|
83
|
+
- CJK characters (Chinese/Japanese/Korean) count as **2** each
|
|
84
|
+
- URLs count as **23** each regardless of length
|
|
85
|
+
- Script auto-validates before posting; rejects if over limit
|
|
86
|
+
|
|
87
|
+
## Rate Limits
|
|
88
|
+
|
|
89
|
+
- **100 tweets / 15 min** per user (OAuth 1.0a)
|
|
90
|
+
- **3,000 tweets / month** on Basic plan ($200/mo)
|
|
91
|
+
- Check `remaining` field in output to monitor quota
|
|
92
|
+
|
|
93
|
+
## Tips
|
|
94
|
+
|
|
95
|
+
- For content from Notion/database: fetch the text first, then pipe to `tweet.js`
|
|
96
|
+
- For cron-based auto-posting: use `exec` with env vars set, parse JSON output to confirm success
|
|
97
|
+
- Thread mode posts sequentially; each tweet auto-replies to the previous one
|
|
98
|
+
- Combine `--thread` with `--reply-to` to attach a thread under an existing tweet
|