mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-08 10:11:24 +00:00
feat(telegram): support inline button styles (#18241)
Merged via /review-pr -> /prepare-pr -> /merge-pr.
Prepared head SHA: 239cb3552e
Co-authored-by: obviyus <22031114+obviyus@users.noreply.github.com>
Co-authored-by: obviyus <22031114+obviyus@users.noreply.github.com>
Reviewed-by: @obviyus
This commit is contained in:
@@ -4,6 +4,7 @@ import type { RuntimeEnv } from "../runtime.js";
|
||||
import type { TelegramMessageContext } from "./bot-message-context.js";
|
||||
import type { TelegramBotOptions } from "./bot.js";
|
||||
import type { TelegramStreamMode } from "./bot/types.js";
|
||||
import type { TelegramInlineButtons } from "./button-types.js";
|
||||
import { resolveAgentDir } from "../agents/agent-scope.js";
|
||||
import {
|
||||
findModelInCatalog,
|
||||
@@ -300,9 +301,7 @@ export const dispatchTelegramMessage = async ({
|
||||
const finalText = payload.text;
|
||||
const currentPreviewText = streamMode === "block" ? draftText : lastPartialText;
|
||||
const previewButtons = (
|
||||
payload.channelData?.telegram as
|
||||
| { buttons?: Array<Array<{ text: string; callback_data: string }>> }
|
||||
| undefined
|
||||
payload.channelData?.telegram as { buttons?: TelegramInlineButtons } | undefined
|
||||
)?.buttons;
|
||||
let draftStoppedForPreviewEdit = false;
|
||||
// Skip preview edit for error payloads to avoid overwriting previous content
|
||||
|
||||
@@ -3,6 +3,7 @@ import type { ReplyPayload } from "../../auto-reply/types.js";
|
||||
import type { ReplyToMode } from "../../config/config.js";
|
||||
import type { MarkdownTableMode } from "../../config/types.base.js";
|
||||
import type { RuntimeEnv } from "../../runtime.js";
|
||||
import type { TelegramInlineButtons } from "../button-types.js";
|
||||
import type { StickerMetadata, TelegramContext } from "./types.js";
|
||||
import { chunkMarkdownTextWithMode, type ChunkMode } from "../../auto-reply/chunk.js";
|
||||
import { danger, logVerbose } from "../../globals.js";
|
||||
@@ -108,7 +109,7 @@ export async function deliverReplies(params: {
|
||||
? [reply.mediaUrl]
|
||||
: [];
|
||||
const telegramData = reply.channelData?.telegram as
|
||||
| { buttons?: Array<Array<{ text: string; callback_data: string }>> }
|
||||
| { buttons?: TelegramInlineButtons }
|
||||
| undefined;
|
||||
const replyMarkup = buildInlineKeyboard(telegramData?.buttons);
|
||||
if (mediaList.length === 0) {
|
||||
|
||||
9
src/telegram/button-types.ts
Normal file
9
src/telegram/button-types.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
export type TelegramButtonStyle = "danger" | "success" | "primary";
|
||||
|
||||
export type TelegramInlineButton = {
|
||||
text: string;
|
||||
callback_data: string;
|
||||
style?: TelegramButtonStyle;
|
||||
};
|
||||
|
||||
export type TelegramInlineButtons = TelegramInlineButton[][];
|
||||
@@ -76,6 +76,29 @@ describe("buildInlineKeyboard", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("passes through button style", () => {
|
||||
const result = buildInlineKeyboard([
|
||||
[
|
||||
{
|
||||
text: "Option A",
|
||||
callback_data: "cmd:a",
|
||||
style: "primary",
|
||||
},
|
||||
],
|
||||
]);
|
||||
expect(result).toEqual({
|
||||
inline_keyboard: [
|
||||
[
|
||||
{
|
||||
text: "Option A",
|
||||
callback_data: "cmd:a",
|
||||
style: "primary",
|
||||
},
|
||||
],
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
it("filters invalid buttons and empty rows", () => {
|
||||
const result = buildInlineKeyboard([
|
||||
[
|
||||
|
||||
@@ -6,6 +6,7 @@ import type {
|
||||
} from "@grammyjs/types";
|
||||
import { type ApiClientOptions, Bot, HttpError, InputFile } from "grammy";
|
||||
import type { RetryConfig } from "../infra/retry.js";
|
||||
import type { TelegramInlineButtons } from "./button-types.js";
|
||||
import { loadConfig } from "../config/config.js";
|
||||
import { resolveMarkdownTableMode } from "../config/markdown-tables.js";
|
||||
import { logVerbose } from "../globals.js";
|
||||
@@ -55,7 +56,7 @@ type TelegramSendOpts = {
|
||||
/** Forum topic thread ID (for forum supergroups) */
|
||||
messageThreadId?: number;
|
||||
/** Inline keyboard buttons (reply markup). */
|
||||
buttons?: Array<Array<{ text: string; callback_data: string }>>;
|
||||
buttons?: TelegramInlineButtons;
|
||||
};
|
||||
|
||||
type TelegramSendResult = {
|
||||
@@ -404,6 +405,7 @@ export function buildInlineKeyboard(
|
||||
(button): InlineKeyboardButton => ({
|
||||
text: button.text,
|
||||
callback_data: button.callback_data,
|
||||
...(button.style ? { style: button.style } : {}),
|
||||
}),
|
||||
),
|
||||
)
|
||||
@@ -778,7 +780,7 @@ type TelegramEditOpts = {
|
||||
/** Controls whether link previews are shown in the edited message. */
|
||||
linkPreview?: boolean;
|
||||
/** Inline keyboard buttons (reply markup). Pass empty array to remove buttons. */
|
||||
buttons?: Array<Array<{ text: string; callback_data: string }>>;
|
||||
buttons?: TelegramInlineButtons;
|
||||
/** Optional config injection to avoid global loadConfig() (improves testability). */
|
||||
cfg?: ReturnType<typeof loadConfig>;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user