QuotLy Style Sticker
How To Call (Agent)
- Build payload with required
selected_messages.
- When available, include event metadata for dedupe:
context.event.channel (example: telegram)
context.event.update_id (preferred)
- fallback keys:
event_id, delivery_id, id
- Run:
python3 scripts/openclaw_quote_autoreply.py --input <json-file-or->
- Use tool-emitted
MEDIA: for delivery.
- Final assistant text must be empty.
Input
- Required:
selected_messages (array, must not be empty)
- Optional:
context.event for dedupe accuracy
channel (string)
update_id (string or number, preferred)
event_id / delivery_id / id (fallback keys)
- Each item structure:
{
"message": {
"message_id": 2002,
"text": "Forwarded message content",
"forward_from": {
"type": "hidden_user", // optional, indicates hidden user
"id": 123456789, // optional, user id
"first_name": "张", // required, first name or nickname
"last_name": "三", // optional, last name
"avatar_url": "", // optional, avatar url or base64 data (from user profile or platform API)
"status_url": "" // optional, status url or base64 data (from user profile or platform API)
}
},
// Optional: override message fields
"overwrite_message": {
"text": "哈哈哈哈哈",
"forward_from": {
"avatar_url": "", // from user profile or platform API
"status_url": "" // from user profile or platform API
},
"entities": [ // optional, text formatting entities
{"type": "bold", "offset": 0, "length": 4},
{"type": "italic", "offset": 5, "length": 4}
]
}
}
- Optional canvas:
width, height, scale, max_width, border_radius, picture_radius, background_color
Entities (Text Formatting)
The skill supports Telegram-style message entities for text formatting:
[
{"type": "bold", "offset": 0, "length": 5},
{"type": "italic", "offset": 6, "length": 6},
{"type": "url", "offset": 13, "length": 15, "url": "https://example.com"}
]
Supported types: mention, hashtag, cashtag, bot_command, url, email, phone_number, bold, italic, underline, strikethrough, spoiler, code, pre, text_link, text_mention, custom_emoji
Entity fields:
type (required) - entity type
offset (required) - UTF-8 offset in text
length (required) - UTF-8 length
url (optional) - for text_link type
user (optional) - for text_mention type
language (optional) - for pre type
custom_emoji_id (optional) - for custom_emoji type
Field Mapping
- Quote text:
overwrite_message.text > message.text
- Name/avatar:
overwrite_message.forward_from > message.forward_from
- Text formatting (entities):
overwrite_message.entities > message.entities > message.caption_entities
Output
- stdout includes:
Quote sticker generated.
MEDIA:<absolute-path-to-webp>
- For duplicate retries detected within dedupe window, generation is skipped and no
MEDIA: line is emitted.
Environment Variables
QUOTLY_API_URL - QuotLy API endpoint (default: https://bot.lyo.su/quote/generate).
QUOTLY_API_ALLOW_HOSTS - Comma-separated list of allowed API hosts (e.g., bot.lyo.su). When set, the skill will only contact hosts in this list.
QUOTLY_AUDIT_LOG - Set to 1, true, or yes to enable audit logging to stderr.
QUOTLY_DEDUP_WINDOW_SECONDS - Suppress duplicate requests for the same event/payload within this window (default: 180). Set to 0 to disable.
Dedupe Key (How _build_dedupe_key reads input)
_build_dedupe_key(input_payload) resolves keys in this order:
context.event.update_id (or event_id / delivery_id / id)
event.update_id (or event_id / delivery_id / id) when context.event is missing
context.event.update.update_id (nested update object)
- Fallback: stable hash of
selected_messages
Recommended wrapper payload:
{
"context": {
"event": {
"channel": "telegram",
"update_id": 123456789
}
},
"selected_messages": [
{
"message": {
"message_id": 2002,
"text": "Forwarded message content"
}
}
]
}
Security Notes
- This skill sends message content to an external API to generate stickers.
- SSRF Protection: Multiple layers of protection are implemented:
- Hostname validation blocks internal/private IPs, localhost, and metadata endpoints
- DNS rebinding protection: resolves hostnames and validates resolved IPs
- Path traversal prevention: blocks
.. and suspicious path patterns
- URL credentials stripping: removes username/password from URLs
- Request Limits: Maximum payload size 1MB, maximum response size 10MB
- Audit Logging: Enable with
QUOTLY_AUDIT_LOG=1 to log API requests and responses for security monitoring
- In sensitive environments, always set
QUOTLY_API_ALLOW_HOSTS to restrict which hosts the skill can contact.
- Avatar and status URLs from user input are passed to the rendering service; ensure input comes from trusted sources.
Reply Rule
- Do not output any final text.
1---2name: quotly-style-sticker3description: Generate QuotLy-style stickers from forwarded messages and return one MEDIA path for auto-send. Use when users ask to create quote stickers from selected forwarded messages or quoted messages in groups.4---56# QuotLy Style Sticker78## How To Call (Agent)9101. Build payload with required `selected_messages`.112. When available, include event metadata for dedupe:12 - `context.event.channel` (example: `telegram`)13 - `context.event.update_id` (preferred)14 - fallback keys: `event_id`, `delivery_id`, `id`153. Run:16 - `python3 scripts/openclaw_quote_autoreply.py --input <json-file-or->`174. Use tool-emitted `MEDIA:` for delivery.185. Final assistant text must be empty.1920## Input2122- Required: `selected_messages` (array, must not be empty)23- Optional: `context.event` for dedupe accuracy24 - `channel` (string)25 - `update_id` (string or number, preferred)26 - `event_id` / `delivery_id` / `id` (fallback keys)27- Each item structure:28 ```json529 {30 "message": {31 "message_id": 2002,32 "text": "Forwarded message content",33 "forward_from": {34 "type": "hidden_user", // optional, indicates hidden user35 "id": 123456789, // optional, user id36 "first_name": "张", // required, first name or nickname37 "last_name": "三", // optional, last name38 "avatar_url": "", // optional, avatar url or base64 data (from user profile or platform API)39 "status_url": "" // optional, status url or base64 data (from user profile or platform API)40 }41 },42 // Optional: override message fields43 "overwrite_message": {44 "text": "哈哈哈哈哈",45 "forward_from": {46 "avatar_url": "", // from user profile or platform API47 "status_url": "" // from user profile or platform API48 },49 "entities": [ // optional, text formatting entities50 {"type": "bold", "offset": 0, "length": 4},51 {"type": "italic", "offset": 5, "length": 4}52 ]53 }54 }55 ```56- Optional canvas: `width`, `height`, `scale`, `max_width`, `border_radius`, `picture_radius`, `background_color`5758## Entities (Text Formatting)5960The skill supports Telegram-style message entities for text formatting:6162```json563[64 {"type": "bold", "offset": 0, "length": 5},65 {"type": "italic", "offset": 6, "length": 6},66 {"type": "url", "offset": 13, "length": 15, "url": "https://example.com"}67]68```6970**Supported types:** `mention`, `hashtag`, `cashtag`, `bot_command`, `url`, `email`, `phone_number`, `bold`, `italic`, `underline`, `strikethrough`, `spoiler`, `code`, `pre`, `text_link`, `text_mention`, `custom_emoji`7172**Entity fields:**73- `type` (required) - entity type74- `offset` (required) - UTF-8 offset in text75- `length` (required) - UTF-8 length76- `url` (optional) - for `text_link` type77- `user` (optional) - for `text_mention` type78- `language` (optional) - for `pre` type79- `custom_emoji_id` (optional) - for `custom_emoji` type8081## Field Mapping8283- Quote text:84 - `overwrite_message.text` > `message.text`85- Name/avatar:86 - `overwrite_message.forward_from` > `message.forward_from`87- Text formatting (entities):88 - `overwrite_message.entities` > `message.entities` > `message.caption_entities`8990## Output9192- stdout includes:93 - `Quote sticker generated.`94 - `MEDIA:<absolute-path-to-webp>`95- For duplicate retries detected within dedupe window, generation is skipped and no `MEDIA:` line is emitted.9697## Environment Variables9899- `QUOTLY_API_URL` - QuotLy API endpoint (default: `https://bot.lyo.su/quote/generate`).100- `QUOTLY_API_ALLOW_HOSTS` - Comma-separated list of allowed API hosts (e.g., `bot.lyo.su`). When set, the skill will only contact hosts in this list.101- `QUOTLY_AUDIT_LOG` - Set to `1`, `true`, or `yes` to enable audit logging to stderr.102- `QUOTLY_DEDUP_WINDOW_SECONDS` - Suppress duplicate requests for the same event/payload within this window (default: `180`). Set to `0` to disable.103104## Dedupe Key (How `_build_dedupe_key` reads input)105106`_build_dedupe_key(input_payload)` resolves keys in this order:1071081. `context.event.update_id` (or `event_id` / `delivery_id` / `id`)1092. `event.update_id` (or `event_id` / `delivery_id` / `id`) when `context.event` is missing1103. `context.event.update.update_id` (nested update object)1114. Fallback: stable hash of `selected_messages`112113Recommended wrapper payload:114115```json116{117 "context": {118 "event": {119 "channel": "telegram",120 "update_id": 123456789121 }122 },123 "selected_messages": [124 {125 "message": {126 "message_id": 2002,127 "text": "Forwarded message content"128 }129 }130 ]131}132```133134## Security Notes135136- This skill sends message content to an external API to generate stickers.137- **SSRF Protection**: Multiple layers of protection are implemented:138 - Hostname validation blocks internal/private IPs, localhost, and metadata endpoints139 - DNS rebinding protection: resolves hostnames and validates resolved IPs140 - Path traversal prevention: blocks `..` and suspicious path patterns141 - URL credentials stripping: removes username/password from URLs142- **Request Limits**: Maximum payload size 1MB, maximum response size 10MB143- **Audit Logging**: Enable with `QUOTLY_AUDIT_LOG=1` to log API requests and responses for security monitoring144- In sensitive environments, always set `QUOTLY_API_ALLOW_HOSTS` to restrict which hosts the skill can contact.145- Avatar and status URLs from user input are passed to the rendering service; ensure input comes from trusted sources.146147## Reply Rule148149- Do not output any final text.