mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-07 21:01:26 +00:00
feat(telegram): add sticker support with vision caching
Add support for receiving and sending Telegram stickers: Inbound: - Receive static WEBP stickers (skip animated/video) - Process stickers through dedicated vision call for descriptions - Cache vision descriptions to avoid repeated API calls - Graceful error handling for fetch failures Outbound: - Add sticker action to send stickers by fileId - Add sticker-search action to find cached stickers by query - Accept stickerId from shared schema, convert to fileId Cache: - Store sticker metadata (fileId, emoji, setName, description) - Fuzzy search by description, emoji, and set name - Persist to ~/.clawdbot/telegram/sticker-cache.json Config: - Single `channels.telegram.actions.sticker` option enables both send and search actions 🤖 AI-assisted: Built with Claude Code (claude-opus-4-5) Testing: Fully tested - unit tests pass, live tested on dev gateway The contributor understands and has reviewed all code changes. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import {
|
||||
createActionGate,
|
||||
readNumberParam,
|
||||
readStringArrayParam,
|
||||
readStringOrNumberParam,
|
||||
readStringParam,
|
||||
} from "../../../agents/tools/common.js";
|
||||
@@ -45,6 +46,10 @@ export const telegramMessageActions: ChannelMessageActionAdapter = {
|
||||
if (gate("reactions")) actions.add("react");
|
||||
if (gate("deleteMessage")) actions.add("delete");
|
||||
if (gate("editMessage")) actions.add("edit");
|
||||
if (gate("sticker")) {
|
||||
actions.add("sticker");
|
||||
actions.add("sticker-search");
|
||||
}
|
||||
return Array.from(actions);
|
||||
},
|
||||
supportsButtons: ({ cfg }) => {
|
||||
@@ -141,6 +146,41 @@ export const telegramMessageActions: ChannelMessageActionAdapter = {
|
||||
);
|
||||
}
|
||||
|
||||
if (action === "sticker") {
|
||||
const to =
|
||||
readStringParam(params, "to") ?? readStringParam(params, "target", { required: true });
|
||||
// Accept stickerId (array from shared schema) and use first element as fileId
|
||||
const stickerIds = readStringArrayParam(params, "stickerId");
|
||||
const fileId = stickerIds?.[0] ?? readStringParam(params, "fileId", { required: true });
|
||||
const replyToMessageId = readNumberParam(params, "replyTo", { integer: true });
|
||||
const messageThreadId = readNumberParam(params, "threadId", { integer: true });
|
||||
return await handleTelegramAction(
|
||||
{
|
||||
action: "sendSticker",
|
||||
to,
|
||||
fileId,
|
||||
replyToMessageId: replyToMessageId ?? undefined,
|
||||
messageThreadId: messageThreadId ?? undefined,
|
||||
accountId: accountId ?? undefined,
|
||||
},
|
||||
cfg,
|
||||
);
|
||||
}
|
||||
|
||||
if (action === "sticker-search") {
|
||||
const query = readStringParam(params, "query", { required: true });
|
||||
const limit = readNumberParam(params, "limit", { integer: true });
|
||||
return await handleTelegramAction(
|
||||
{
|
||||
action: "searchSticker",
|
||||
query,
|
||||
limit: limit ?? undefined,
|
||||
accountId: accountId ?? undefined,
|
||||
},
|
||||
cfg,
|
||||
);
|
||||
}
|
||||
|
||||
throw new Error(`Action ${action} is not supported for provider ${providerId}.`);
|
||||
},
|
||||
};
|
||||
|
||||
@@ -25,6 +25,7 @@ export const CHANNEL_MESSAGE_ACTION_NAMES = [
|
||||
"thread-reply",
|
||||
"search",
|
||||
"sticker",
|
||||
"sticker-search",
|
||||
"member-info",
|
||||
"role-info",
|
||||
"emoji-list",
|
||||
|
||||
Reference in New Issue
Block a user