Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 24 additions & 11 deletions plugins/ton-bridge/README.md
Original file line number Diff line number Diff line change
@@ -1,22 +1,23 @@
# TON Bridge

Share the TON Bridge Mini App link with a beautiful inline button in Telegram chats.
Share the TON Bridge Mini App link with an inline button in Telegram chats.
Works in DMs, groups, and channels.

TON Bridge works with support from TONBANKCARD.

## Features

- Inline button for TON Bridge Mini App access
- Customizable button text and emoji
- Sends a message with a URL inline button directly to the current chat
- Button text controllable per tool call (the LLM can omit or include emoji)
- Customizable default button text via config
- Custom message support
- Easy integration with AI agents

## Tools

| Tool | Description | Category |
|------|-------------|----------|
| `ton_bridge_open` | Send a message with a TON Bridge Mini App link | action |
| `ton_bridge_about` | Send info about TON Bridge with a link to the Mini App | data-bearing |
| `ton_bridge_open` | Send a message with a TON Bridge Mini App button | action |
| `ton_bridge_about` | Send info about TON Bridge with a Mini App button | data-bearing |
| `ton_bridge_custom_message` | Send a custom message alongside a TON Bridge button | action |

## Installation
Expand All @@ -32,19 +33,27 @@ cp -r plugins/ton-bridge ~/.teleton/plugins/
# ~/.teleton/config.yaml
plugins:
ton_bridge:
buttonText: "TON Bridge No1" # Button text (default: "TON Bridge No1")
buttonEmoji: "🌉" # Emoji on button (default: "🌉")
startParam: "" # Optional start parameter
buttonText: "TON Bridge No1" # Default button label (default: "TON Bridge No1")
startParam: "" # Optional start parameter appended to the Mini App URL
```

> **Note:** Emoji on the button is controlled by the agent at call time via the `buttonText` parameter, not by config. This allows the agent to send buttons with or without emoji as requested by the user.

## Usage Examples

### Open TON Bridge
```
Open TON Bridge
```

Will send a message with a button linking to https://t.me/TONBridge_robot?startapp
Sends a message with a button linking to `https://t.me/TONBridge_robot?startapp`.

### Open TON Bridge without emoji on button
```
Open TON Bridge, no emoji on the button
```

The agent will call `ton_bridge_open` with `buttonText: "TON Bridge No1"` (no emoji).

### Get Info About TON Bridge
```
Expand All @@ -63,16 +72,20 @@ Send "Transfer your assets via TON Bridge" with a TON Bridge button
| Param | Type | Required | Default | Description |
|-------|------|----------|---------|-------------|
| `message` | string | No | — | Optional message text to show with the button |
| `buttonText` | string | No | config default | Button label. Do not include emoji unless user requested it. |

### `ton_bridge_about`

No parameters required.
| Param | Type | Required | Default | Description |
|-------|------|----------|---------|-------------|
| `buttonText` | string | No | config default | Button label. Do not include emoji unless user requested it. |

### `ton_bridge_custom_message`

| Param | Type | Required | Default | Description |
|-------|------|----------|---------|-------------|
| `customMessage` | string | Yes | — | Custom message text to display with the button |
| `buttonText` | string | No | config default | Button label. Do not include emoji unless user requested it. |

---

Expand Down
107 changes: 75 additions & 32 deletions plugins/ton-bridge/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@
* TON Bridge plugin
*
* Provides LLM-callable tools to share the TON Bridge Mini App link.
* Pattern B (SDK) — uses sdk.pluginConfig, sdk.log
* Pattern B (SDK) — uses sdk.pluginConfig, sdk.log, sdk.telegram.sendMessage
*
* Actively sends messages with URL inline buttons so the button renders
* correctly in DMs, groups, and channels.
*/

// ─── Manifest (inline) ────────────────────────────────────────────────────────
Expand All @@ -16,7 +19,6 @@ export const manifest = {
description: "Share TON Bridge Mini App link with a button. Opens https://t.me/TONBridge_robot?startapp",
defaultConfig: {
buttonText: "TON Bridge No1",
buttonEmoji: "🌉",
startParam: "",
},
};
Expand All @@ -25,14 +27,10 @@ export const manifest = {

const MINI_APP_URL = "https://t.me/TONBridge_robot?startapp";

function buildReplyMarkup(buttonText, buttonEmoji, startParam) {
const label = buttonEmoji ? `${buttonEmoji} ${buttonText}` : buttonText;
const url = startParam
function buildUrl(startParam) {
return startParam
? `${MINI_APP_URL}=${encodeURIComponent(startParam)}`
: MINI_APP_URL;
return {
inline_keyboard: [[{ text: label, url }]],
};
}

// ─── Tools ────────────────────────────────────────────────────────────────────
Expand All @@ -42,7 +40,7 @@ export const tools = (sdk) => [
{
name: "ton_bridge_open",
description:
"Send a message with a TON Bridge Mini App link. Use when the user asks to open or access TON Bridge.",
"Send a message with a TON Bridge Mini App button. Use when the user asks to open or access TON Bridge. Sends the message directly to the current chat.",
category: "action",
parameters: {
type: "object",
Expand All @@ -53,30 +51,45 @@ export const tools = (sdk) => [
minLength: 1,
maxLength: 500,
},
buttonText: {
type: "string",
description: "Button label text. Omit to use the configured default. Do NOT include emoji here unless the user explicitly requested one.",
minLength: 1,
maxLength: 64,
},
},
},
execute: async (params, context) => {
try {
const buttonText = sdk.pluginConfig?.buttonText ?? "TON Bridge No1";
const buttonEmoji = sdk.pluginConfig?.buttonEmoji ?? "🌉";
const buttonText = params.buttonText ?? sdk.pluginConfig?.buttonText ?? "TON Bridge No1";
const startParam = sdk.pluginConfig?.startParam ?? "";
const url = buildUrl(startParam);

const content =
const text =
params.message ??
"🌉 **TON Bridge** — The #1 Bridge in the TON Catalog\n\nClick the button below to open TON Bridge Mini App.";
"TON Bridge — The #1 Bridge in the TON Catalog\n\nClick the button below to open TON Bridge Mini App.";

sdk.log?.info(
`ton_bridge_open called by ${context?.senderId ?? "unknown"}`
);

const messageId = await sdk.telegram.sendMessage(
context.chatId,
text,
{
inlineKeyboard: [[{ text: buttonText, url }]],
}
);

return {
success: true,
data: {
content,
reply_markup: buildReplyMarkup(buttonText, buttonEmoji, startParam),
},
data: { message_id: messageId, chat_id: context.chatId },
};
} catch (err) {
if (err.name === "PluginSDKError") {
sdk.log?.error(`ton_bridge_open failed: ${err.code}: ${err.message}`);
return { success: false, error: `${err.code}: ${String(err.message).slice(0, 500)}` };
}
sdk.log?.error("ton_bridge_open failed:", err.message);
return { success: false, error: String(err.message || err).slice(0, 500) };
}
Expand All @@ -87,31 +100,46 @@ export const tools = (sdk) => [
{
name: "ton_bridge_about",
description:
"Send an info message about TON Bridge with a link to the Mini App. Use when the user asks about TON Bridge or wants more information.",
"Send an info message about TON Bridge with a Mini App button. Use when the user asks about TON Bridge or wants more information.",
category: "data-bearing",
parameters: {
type: "object",
properties: {},
properties: {
buttonText: {
type: "string",
description: "Button label text. Omit to use the configured default. Do NOT include emoji here unless the user explicitly requested one.",
minLength: 1,
maxLength: 64,
},
},
},
execute: async (params, context) => {
try {
const buttonText = sdk.pluginConfig?.buttonText ?? "TON Bridge No1";
const buttonEmoji = sdk.pluginConfig?.buttonEmoji ?? "🌉";
const buttonText = params.buttonText ?? sdk.pluginConfig?.buttonText ?? "TON Bridge No1";
const startParam = sdk.pluginConfig?.startParam ?? "";
const url = buildUrl(startParam);

sdk.log?.info(
`ton_bridge_about called by ${context?.senderId ?? "unknown"}`
);

const messageId = await sdk.telegram.sendMessage(
context.chatId,
"About TON Bridge\n\nTON Bridge is the #1 bridge in the TON Catalog. Transfer assets across chains seamlessly via the official Mini App.",
{
inlineKeyboard: [[{ text: buttonText, url }]],
}
);

return {
success: true,
data: {
content:
"ℹ️ **About TON Bridge**\n\nTON Bridge is the #1 bridge in the TON Catalog. Transfer assets across chains seamlessly via the official Mini App.",
reply_markup: buildReplyMarkup(buttonText, buttonEmoji, startParam),
},
data: { message_id: messageId, chat_id: context.chatId },
};
} catch (err) {
if (err.name === "PluginSDKError") {
sdk.log?.error(`ton_bridge_about failed: ${err.code}: ${err.message}`);
return { success: false, error: `${err.code}: ${String(err.message).slice(0, 500)}` };
}
sdk.log?.error("ton_bridge_about failed:", err.message);
return { success: false, error: String(err.message || err).slice(0, 500) };
}
Expand All @@ -133,27 +161,42 @@ export const tools = (sdk) => [
minLength: 1,
maxLength: 500,
},
buttonText: {
type: "string",
description: "Button label text. Omit to use the configured default. Do NOT include emoji here unless the user explicitly requested one.",
minLength: 1,
maxLength: 64,
},
},
required: ["customMessage"],
},
execute: async (params, context) => {
try {
const buttonText = sdk.pluginConfig?.buttonText ?? "TON Bridge No1";
const buttonEmoji = sdk.pluginConfig?.buttonEmoji ?? "🌉";
const buttonText = params.buttonText ?? sdk.pluginConfig?.buttonText ?? "TON Bridge No1";
const startParam = sdk.pluginConfig?.startParam ?? "";
const url = buildUrl(startParam);

sdk.log?.info(
`ton_bridge_custom_message called by ${context?.senderId ?? "unknown"}`
);

const messageId = await sdk.telegram.sendMessage(
context.chatId,
params.customMessage,
{
inlineKeyboard: [[{ text: buttonText, url }]],
}
);

return {
success: true,
data: {
content: params.customMessage,
reply_markup: buildReplyMarkup(buttonText, buttonEmoji, startParam),
},
data: { message_id: messageId, chat_id: context.chatId },
};
} catch (err) {
if (err.name === "PluginSDKError") {
sdk.log?.error(`ton_bridge_custom_message failed: ${err.code}: ${err.message}`);
return { success: false, error: `${err.code}: ${String(err.message).slice(0, 500)}` };
}
sdk.log?.error("ton_bridge_custom_message failed:", err.message);
return { success: false, error: String(err.message || err).slice(0, 500) };
}
Expand Down
1 change: 0 additions & 1 deletion plugins/ton-bridge/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
],
"defaultConfig": {
"buttonText": "TON Bridge No1",
"buttonEmoji": "🌉",
"startParam": ""
},
"permissions": [],
Expand Down
Loading