QuotLy Style Sticker
Human Guide
OpenClaw usage:
- Enable
quotly-style-sticker in OpenClaw.
- Forward one or multiple Telegram messages to OpenClaw.
- Trigger with a prompt such as
Use $quotly-style-sticker to generate a quote sticker.
- OpenClaw sends back the generated sticker automatically.
Local usage:
python scripts/openclaw_quote_autoreply.py --input <openclaw-input.json>
echo '<json>' | python scripts/openclaw_quote_autoreply.py --input -
python scripts/openclaw_quote_autoreply.py --input scripts/input.sample.json
Output contract:
Quote sticker generated.
MEDIA:<absolute-path-to-webp>
Each request writes a unique temp file path.
If messages has multiple entries, all entries are rendered into one sticker.
Skills Config (Human)
Configure env vars in openclaw.json via skills.entries.<skill>.env:
{
"skills": {
"entries": {
"quotly-style-sticker": {
"env": {
"QUOTLY_DISABLE_TELEGRAM_AVATAR_LOOKUP": "true",
"QUOTLY_DISABLE_REMOTE_AVATAR_URL": "true",
"QUOTLY_AVATAR_ALLOW_HOSTS": "cdn.telegram.org,images.example.com",
"QUOTLY_MAX_AVATAR_BYTES": "1048576",
"TG_BOT_TOKEN": "<optional for Telegram avatar lookup>"
}
}
}
}
}
Sandbox note:
skills.entries.<skill>.env applies to host runs.
- For sandboxed runs, provide env vars in sandbox docker env config.
Agent Contract
Entry command:
python scripts/openclaw_quote_autoreply.py --input <json-file-or->
Input Model
{
"messages": [
{
"message": {
"text": "...",
"forward": {
"sender": { "id": 1, "name": "User A" },
"text": "Forward text A"
}
}
},
{
"message": {
"text": "...",
"forward": {
"sender": { "id": 2, "name": "User B" },
"text": "Forward text B"
}
}
}
],
"context": { "event": { "channel": "telegram", "rawPayload": {} } }
}
Single-message fallback is supported when messages is absent:
context.message
- or root-level message-like fields (
text, sender, forward, ...)
Override fields:
- Global fallback:
quote_text, original_text, source_id, source_name, source_status_emoji, source_status_emoji_id, source_avatar_url
- Per-message override: same keys inside each message item
Resolution rules:
- Source identity: per-item
source_* > global source_* > message.forward.* > rawPayload > message.sender.
- Quote text: per-item
quote_text > global quote_text > message text > forwarded text > per-item/global original_text.
- Name fields sent to renderer:
first_name/last_name; status uses emoji_status when status id is available.
Output Model
- Must print one
MEDIA: line with absolute path to generated .webp.
- Non-fatal avatar issues should continue without avatar.
Avatar -> Renderer Path (Security)
How avatar is passed to lyo:
- If message already has avatar URL, script sanitizes it and may pass sanitized HTTPS URL.
- If avatar is missing and Telegram lookup is enabled, script calls Telegram API, downloads avatar bytes, and sends
data:image/...;base64,... inline data URL. Telegram lookup is disabled by default.
- Script never sends
https://api.telegram.org/file/bot<token>/... to renderer.
Avatar safety rules before sending to renderer:
- Reject non-HTTPS remote URLs.
- Reject URLs with embedded credentials.
- Reject internal/private/loopback hosts.
- Reject URLs with sensitive query keys (
token, sig, auth, x-amz, x-goog, etc).
- Enforce max avatar size for inline data URLs (
QUOTLY_MAX_AVATAR_BYTES).
Runtime & Network
Required env vars:
Optional env vars:
TG_BOT_TOKEN or TELEGRAM_BOT_TOKEN (Telegram avatar lookup only)
QUOTLY_DISABLE_TELEGRAM_AVATAR_LOOKUP (default true)
QUOTLY_DISABLE_REMOTE_AVATAR_URL (default true)
QUOTLY_AVATAR_ALLOW_HOSTS (default empty)
QUOTLY_MAX_AVATAR_BYTES (default 1048576)
External endpoint:
- default renderer:
https://bot.lyo.su/quote/generate
- fallback renderer URL:
https://bot.lyo.su/quote/generate.webp
- override:
--api <your-endpoint>
1---2name: quotly-style-sticker3description: Generate QuotLy-style stickers from OpenClaw context and return MEDIA for auto-send. Use for single or multi-message quote cards (multiple forwarded messages merged into one sticker).4---56# QuotLy Style Sticker78## Human Guide910OpenClaw usage:11121. Enable `quotly-style-sticker` in OpenClaw.132. Forward one or multiple Telegram messages to OpenClaw.143. Trigger with a prompt such as `Use $quotly-style-sticker to generate a quote sticker`.154. OpenClaw sends back the generated sticker automatically.1617Local usage:1819- `python scripts/openclaw_quote_autoreply.py --input <openclaw-input.json>`20- `echo '<json>' | python scripts/openclaw_quote_autoreply.py --input -`21- `python scripts/openclaw_quote_autoreply.py --input scripts/input.sample.json`2223Output contract:2425- `Quote sticker generated.`26- `MEDIA:<absolute-path-to-webp>`2728Each request writes a unique temp file path.29If `messages` has multiple entries, all entries are rendered into one sticker.3031## Skills Config (Human)3233Configure env vars in `openclaw.json` via `skills.entries.<skill>.env`:3435```json36{37 "skills": {38 "entries": {39 "quotly-style-sticker": {40 "env": {41 "QUOTLY_DISABLE_TELEGRAM_AVATAR_LOOKUP": "true",42 "QUOTLY_DISABLE_REMOTE_AVATAR_URL": "true",43 "QUOTLY_AVATAR_ALLOW_HOSTS": "cdn.telegram.org,images.example.com",44 "QUOTLY_MAX_AVATAR_BYTES": "1048576",45 "TG_BOT_TOKEN": "<optional for Telegram avatar lookup>"46 }47 }48 }49 }50}51```5253Sandbox note:5455- `skills.entries.<skill>.env` applies to host runs.56- For sandboxed runs, provide env vars in sandbox docker env config.5758## Agent Contract5960Entry command:6162- `python scripts/openclaw_quote_autoreply.py --input <json-file-or->`6364### Input Model6566```json67{68 "messages": [69 {70 "message": {71 "text": "...",72 "forward": {73 "sender": { "id": 1, "name": "User A" },74 "text": "Forward text A"75 }76 }77 },78 {79 "message": {80 "text": "...",81 "forward": {82 "sender": { "id": 2, "name": "User B" },83 "text": "Forward text B"84 }85 }86 }87 ],88 "context": { "event": { "channel": "telegram", "rawPayload": {} } }89}90```9192Single-message fallback is supported when `messages` is absent:9394- `context.message`95- or root-level message-like fields (`text`, `sender`, `forward`, ...)9697Override fields:9899- Global fallback: `quote_text`, `original_text`, `source_id`, `source_name`, `source_status_emoji`, `source_status_emoji_id`, `source_avatar_url`100- Per-message override: same keys inside each message item101102Resolution rules:1031041. Source identity: per-item `source_*` > global `source_*` > `message.forward.*` > `rawPayload` > `message.sender`.1052. Quote text: per-item `quote_text` > global `quote_text` > message text > forwarded text > per-item/global `original_text`.1063. Name fields sent to renderer: `first_name`/`last_name`; status uses `emoji_status` when status id is available.107108### Output Model109110- Must print one `MEDIA:` line with absolute path to generated `.webp`.111- Non-fatal avatar issues should continue without avatar.112113## Avatar -> Renderer Path (Security)114115How avatar is passed to lyo:1161171. If message already has avatar URL, script sanitizes it and may pass sanitized HTTPS URL.1182. If avatar is missing and Telegram lookup is enabled, script calls Telegram API, downloads avatar bytes, and sends `data:image/...;base64,...` inline data URL. Telegram lookup is disabled by default.1193. Script never sends `https://api.telegram.org/file/bot<token>/...` to renderer.120121Avatar safety rules before sending to renderer:122123- Reject non-HTTPS remote URLs.124- Reject URLs with embedded credentials.125- Reject internal/private/loopback hosts.126- Reject URLs with sensitive query keys (`token`, `sig`, `auth`, `x-amz`, `x-goog`, etc).127- Enforce max avatar size for inline data URLs (`QUOTLY_MAX_AVATAR_BYTES`).128129## Runtime & Network130131Required env vars:132133- none134135Optional env vars:136137- `TG_BOT_TOKEN` or `TELEGRAM_BOT_TOKEN` (Telegram avatar lookup only)138- `QUOTLY_DISABLE_TELEGRAM_AVATAR_LOOKUP` (default `true`)139- `QUOTLY_DISABLE_REMOTE_AVATAR_URL` (default `true`)140- `QUOTLY_AVATAR_ALLOW_HOSTS` (default empty)141- `QUOTLY_MAX_AVATAR_BYTES` (default `1048576`)142143External endpoint:144145- default renderer: `https://bot.lyo.su/quote/generate`146- fallback renderer URL: `https://bot.lyo.su/quote/generate.webp`147- override: `--api <your-endpoint>`