@coffer-org/plugin-telegram 1.3.1 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/runtime/bot.d.ts +1 -0
- package/dist/runtime/bot.js +145 -44
- package/dist/runtime/chain-store.d.ts +28 -0
- package/dist/runtime/chain-store.js +46 -0
- package/dist/runtime/index.js +14 -1
- package/dist/schema.js +46 -15
- package/package.json +5 -5
package/dist/runtime/bot.d.ts
CHANGED
package/dist/runtime/bot.js
CHANGED
|
@@ -1,16 +1,44 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
|
-
import { TelegramClient, Api } from '
|
|
4
|
-
import { LogLevel } from '
|
|
5
|
-
import { StringSession } from '
|
|
6
|
-
import { NewMessage } from '
|
|
7
|
-
import { handleIncoming } from '@coffer-org/plugin-orchestrator/runtime';
|
|
3
|
+
import { TelegramClient, Api } from 'teleproto';
|
|
4
|
+
import { LogLevel } from 'teleproto/extensions/Logger.js';
|
|
5
|
+
import { StringSession } from 'teleproto/sessions/index.js';
|
|
6
|
+
import { NewMessage } from 'teleproto/events/index.js';
|
|
7
|
+
import { handleIncoming, loadGatePolicy } from '@coffer-org/plugin-orchestrator/runtime';
|
|
8
|
+
import { recordUser, recordAssistant, buildChain } from "./chain-store.js";
|
|
8
9
|
import { loadBotConfig, hasCredentials } from "./config.js";
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
import { getLogger } from '@coffer-org/sdk/logger';
|
|
11
|
+
const log = getLogger('telegram');
|
|
12
|
+
const FALLBACK_REPLY_WINDOW_MS = 1_800_000;
|
|
13
|
+
const lastByChat = new Map();
|
|
14
|
+
async function replyWindowMs() {
|
|
15
|
+
try {
|
|
16
|
+
return (await loadGatePolicy()).replyWindow * 1000;
|
|
17
|
+
}
|
|
18
|
+
catch (err) {
|
|
19
|
+
log.warn(`gate policy load: ${err instanceof Error ? err.message : String(err)} — using default reply window`);
|
|
20
|
+
return FALLBACK_REPLY_WINDOW_MS;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
export function stripHtml(s) {
|
|
24
|
+
return s
|
|
25
|
+
.replace(/<[^>]*>/g, '')
|
|
26
|
+
.replace(/</g, '<')
|
|
27
|
+
.replace(/>/g, '>')
|
|
28
|
+
.replace(/"/g, '"')
|
|
29
|
+
.replace(/'/g, "'")
|
|
30
|
+
.replace(/&/g, '&');
|
|
31
|
+
}
|
|
32
|
+
const TELEGRAM_FORMAT = [
|
|
33
|
+
'CRITICAL OUTPUT FORMAT — Telegram HTML ONLY. Format the reply strictly with Telegram\'s HTML subset (<b>, <i>, <code>, <a>, …) and NOTHING else. NEVER use Markdown — no *bold*, _italic_, **bold**, `code`, ```blocks```, # headings, - bullets, or | tables. Markdown does not render here; it shows up as literal characters and breaks the message. When in doubt, use an HTML tag or plain text.',
|
|
34
|
+
'Inline styling (tags may nest): <b>bold</b>, <i>italic</i>, <u>underline</u>, <s>strike</s>, <code>inline code</code>, <spoiler>spoiler</spoiler>. Links: <a href="https://…">text</a> (also <a href="tg://user?id=123">mention</a>).',
|
|
35
|
+
'Blocks: <pre>code block</pre> or, for syntax highlight, <pre><code class="language-python">…</code></pre>. Quotes: <blockquote>quote</blockquote>, or <blockquote expandable>long collapsible quote</blockquote>. Bullet lists: start plain lines with "• ".',
|
|
36
|
+
'Only those tags are parsed. NOT supported here (do not use): <tg-spoiler>, <span>, <ins>, <strike>, <tg-time> — use <spoiler>, <u>, <s> instead. Avoid <tg-emoji> (needs a custom-emoji id + Premium); use ordinary emoji.',
|
|
37
|
+
'DO NOT use markdown (*, _, #, ```), tables, or images. Escape literal <, >, and & in prose as <, >, and & so they are not read as tags.',
|
|
38
|
+
'Render any TABLE as a <pre> block with space-aligned columns — real tables are unsupported.',
|
|
39
|
+
'Beyond the tags, use Unicode symbols and emoji to structure and enrich replies — they render everywhere: bullets (•, ▪, –), separators (─────), arrows (→), status marks (✅ ⚠️ ❌ ⏳), and topic emoji (📅 💰 🏥 🛒 🌱 …). They make messages scannable and friendly.',
|
|
40
|
+
'Keep replies short and skimmable (messages cap at 4096 chars): prefer short paragraphs and "• " bullet lists over long prose.',
|
|
41
|
+
].join('\n');
|
|
14
42
|
function loadSessionString(file) {
|
|
15
43
|
try {
|
|
16
44
|
return fs.readFileSync(file, 'utf-8');
|
|
@@ -49,36 +77,62 @@ export async function startBot(opts = {}) {
|
|
|
49
77
|
const me = (await tg.getMe());
|
|
50
78
|
const meId = me?.id?.toString();
|
|
51
79
|
log.info(`connected as @${me?.username || me?.firstName || meId}`);
|
|
52
|
-
async function
|
|
80
|
+
async function sendHtml(peer, text, replyTo) {
|
|
53
81
|
try {
|
|
54
|
-
return await tg.sendMessage(peer, { message: text, parseMode: '
|
|
82
|
+
return await tg.sendMessage(peer, { message: text, parseMode: 'html', replyTo });
|
|
55
83
|
}
|
|
56
84
|
catch {
|
|
57
85
|
try {
|
|
58
|
-
return await tg.sendMessage(peer, { message: text });
|
|
86
|
+
return await tg.sendMessage(peer, { message: stripHtml(text), replyTo });
|
|
59
87
|
}
|
|
60
88
|
catch {
|
|
61
89
|
return undefined;
|
|
62
90
|
}
|
|
63
91
|
}
|
|
64
92
|
}
|
|
65
|
-
async function
|
|
93
|
+
async function editHtml(peer, msgId, text) {
|
|
66
94
|
try {
|
|
67
|
-
await tg.editMessage(peer, { message: msgId, text, parseMode: '
|
|
95
|
+
await tg.editMessage(peer, { message: msgId, text, parseMode: 'html' });
|
|
68
96
|
}
|
|
69
97
|
catch {
|
|
70
98
|
try {
|
|
71
|
-
await tg.editMessage(peer, { message: msgId, text });
|
|
99
|
+
await tg.editMessage(peer, { message: msgId, text: stripHtml(text) });
|
|
72
100
|
}
|
|
73
101
|
catch {
|
|
74
102
|
}
|
|
75
103
|
}
|
|
76
104
|
}
|
|
77
105
|
function startTypingPeer(peer) {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
106
|
+
let logged = false;
|
|
107
|
+
let stopped = false;
|
|
108
|
+
let timer;
|
|
109
|
+
const warn = (err) => {
|
|
110
|
+
if (logged)
|
|
111
|
+
return;
|
|
112
|
+
logged = true;
|
|
113
|
+
log.warn(`typing indicator: ${err instanceof Error ? err.message : String(err)}`);
|
|
114
|
+
};
|
|
115
|
+
void (async () => {
|
|
116
|
+
let input;
|
|
117
|
+
try {
|
|
118
|
+
input = await tg.getInputEntity(peer);
|
|
119
|
+
}
|
|
120
|
+
catch (err) {
|
|
121
|
+
warn(err);
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
if (stopped)
|
|
125
|
+
return;
|
|
126
|
+
const ping = () => tg
|
|
127
|
+
.invoke(new Api.messages.SetTyping({ peer: input, action: new Api.SendMessageTypingAction() }))
|
|
128
|
+
.catch(warn);
|
|
129
|
+
void ping();
|
|
130
|
+
timer = setInterval(() => void ping(), 5000);
|
|
131
|
+
})();
|
|
132
|
+
return () => {
|
|
133
|
+
stopped = true;
|
|
134
|
+
clearInterval(timer);
|
|
135
|
+
};
|
|
82
136
|
}
|
|
83
137
|
tg.addEventHandler(async (event) => {
|
|
84
138
|
try {
|
|
@@ -103,31 +157,78 @@ export async function startBot(opts = {}) {
|
|
|
103
157
|
catch {
|
|
104
158
|
}
|
|
105
159
|
log.info(`msg [${chatLabel}]: ${text.slice(0, 80)}`);
|
|
106
|
-
const
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
id
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
160
|
+
const stopTyping = startTypingPeer(peer);
|
|
161
|
+
try {
|
|
162
|
+
const chatId = String(event.chatId ?? '?');
|
|
163
|
+
const userId = message.senderId?.toString() ?? '?';
|
|
164
|
+
const incomingMsgId = String(message.id);
|
|
165
|
+
const replyTo = message.replyTo?.replyToMsgId ?? null;
|
|
166
|
+
let replyToId = replyTo != null ? String(replyTo) : null;
|
|
167
|
+
const nowMs = Date.now();
|
|
168
|
+
if (!replyToId) {
|
|
169
|
+
const prev = lastByChat.get(chatId);
|
|
170
|
+
if (prev && nowMs - prev.ts < (await replyWindowMs()))
|
|
171
|
+
replyToId = prev.msgId;
|
|
172
|
+
}
|
|
173
|
+
lastByChat.set(chatId, { msgId: incomingMsgId, ts: nowMs });
|
|
174
|
+
let displayName;
|
|
175
|
+
try {
|
|
176
|
+
const s = (await message.getSender());
|
|
177
|
+
displayName = s?.firstName || s?.username || undefined;
|
|
178
|
+
}
|
|
179
|
+
catch {
|
|
180
|
+
}
|
|
181
|
+
await recordUser({ chatId, msgId: incomingMsgId, sender: displayName, text, ts: message.date ?? 0, replyToId });
|
|
182
|
+
const fetch = async (id) => {
|
|
183
|
+
try {
|
|
184
|
+
const arr = (await tg.getMessages(peer, { ids: [Number(id)] }));
|
|
185
|
+
const m = arr?.[0];
|
|
186
|
+
if (!m)
|
|
187
|
+
return null;
|
|
188
|
+
return {
|
|
189
|
+
text: m.message ?? '',
|
|
190
|
+
senderId: m.senderId?.toString() ?? '',
|
|
191
|
+
replyToId: m.replyTo?.replyToMsgId?.toString() ?? null,
|
|
192
|
+
date: m.date ?? 0,
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
catch {
|
|
115
196
|
return null;
|
|
116
|
-
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
197
|
+
}
|
|
198
|
+
};
|
|
199
|
+
const messages = await buildChain(incomingMsgId, { chatId, fetch, botId: meId ?? '' });
|
|
200
|
+
const connector = {
|
|
201
|
+
id: 'telegram',
|
|
202
|
+
capabilities: { streaming: true, typing: true, maxMessageLength: 4096 },
|
|
203
|
+
async sendMessage(_chatId, msgText) {
|
|
204
|
+
const sent = await sendHtml(peer, msgText, Number(incomingMsgId));
|
|
205
|
+
if (!sent)
|
|
206
|
+
return null;
|
|
207
|
+
return { msgId: String(sent.id) };
|
|
208
|
+
},
|
|
209
|
+
async editMessage(_chatId, editId, msgText) {
|
|
210
|
+
await editHtml(peer, Number(editId), msgText);
|
|
211
|
+
},
|
|
212
|
+
startTyping(_chatId) {
|
|
213
|
+
return () => { };
|
|
214
|
+
},
|
|
215
|
+
async recordAssistant(m) {
|
|
216
|
+
await recordAssistant({ ...m, chatId, now: Math.floor(Date.now() / 1000) });
|
|
217
|
+
if (m.botMsgId)
|
|
218
|
+
lastByChat.set(chatId, { msgId: m.botMsgId, ts: Date.now() });
|
|
219
|
+
},
|
|
220
|
+
};
|
|
221
|
+
await handleIncoming(connector, {
|
|
222
|
+
connectorId: 'telegram',
|
|
223
|
+
chatId,
|
|
224
|
+
channelSystem: TELEGRAM_FORMAT,
|
|
225
|
+
sender: { id: userId, displayName },
|
|
226
|
+
messages,
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
finally {
|
|
230
|
+
stopTyping();
|
|
231
|
+
}
|
|
131
232
|
}
|
|
132
233
|
catch (err) {
|
|
133
234
|
log.error(`message handling: ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { ConvMessage } from '@coffer-org/plugin-orchestrator/runtime';
|
|
2
|
+
export type FetchMsg = (msgId: string) => Promise<{
|
|
3
|
+
text: string;
|
|
4
|
+
senderId: string;
|
|
5
|
+
replyToId: string | null;
|
|
6
|
+
date: number;
|
|
7
|
+
} | null>;
|
|
8
|
+
export declare function recordUser(m: {
|
|
9
|
+
chatId: string;
|
|
10
|
+
msgId: string;
|
|
11
|
+
sender?: string | null;
|
|
12
|
+
text: string;
|
|
13
|
+
ts: number;
|
|
14
|
+
replyToId: string | null;
|
|
15
|
+
}): Promise<void>;
|
|
16
|
+
export declare function recordAssistant(m: {
|
|
17
|
+
chatId: string;
|
|
18
|
+
parentMsgId: string | null;
|
|
19
|
+
botMsgId: string | null;
|
|
20
|
+
text: string;
|
|
21
|
+
now: number;
|
|
22
|
+
}): Promise<void>;
|
|
23
|
+
export declare function buildChain(headMsgId: string, opts: {
|
|
24
|
+
chatId: string;
|
|
25
|
+
fetch: FetchMsg;
|
|
26
|
+
botId: string;
|
|
27
|
+
maxDepth?: number;
|
|
28
|
+
}): Promise<ConvMessage[]>;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { getThreadMessage, putThreadMessage } from '@coffer-org/server/thread-store';
|
|
2
|
+
import { getLogger } from '@coffer-org/sdk/logger';
|
|
3
|
+
const log = getLogger('telegram');
|
|
4
|
+
const CONNECTOR = 'telegram';
|
|
5
|
+
const DEFAULT_MAX_DEPTH = 30;
|
|
6
|
+
export async function recordUser(m) {
|
|
7
|
+
await putThreadMessage({ connector: CONNECTOR, chatId: m.chatId, msgId: m.msgId, role: 'user', sender: m.sender ?? null, text: m.text, ts: m.ts, replyToId: m.replyToId });
|
|
8
|
+
}
|
|
9
|
+
export async function recordAssistant(m) {
|
|
10
|
+
if (m.botMsgId == null)
|
|
11
|
+
return;
|
|
12
|
+
await putThreadMessage({
|
|
13
|
+
connector: CONNECTOR,
|
|
14
|
+
chatId: m.chatId,
|
|
15
|
+
msgId: m.botMsgId,
|
|
16
|
+
role: 'assistant',
|
|
17
|
+
text: m.text,
|
|
18
|
+
ts: m.now,
|
|
19
|
+
replyToId: m.parentMsgId,
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
export async function buildChain(headMsgId, opts) {
|
|
23
|
+
const max = opts.maxDepth ?? DEFAULT_MAX_DEPTH;
|
|
24
|
+
const acc = [];
|
|
25
|
+
let cur = headMsgId;
|
|
26
|
+
const seen = new Set();
|
|
27
|
+
while (cur && acc.length < max && !seen.has(cur)) {
|
|
28
|
+
seen.add(cur);
|
|
29
|
+
let stored = await getThreadMessage(CONNECTOR, opts.chatId, cur);
|
|
30
|
+
if (!stored) {
|
|
31
|
+
const fetched = await opts.fetch(cur);
|
|
32
|
+
if (!fetched)
|
|
33
|
+
break;
|
|
34
|
+
const role = fetched.senderId === opts.botId ? 'assistant' : 'user';
|
|
35
|
+
await putThreadMessage({ connector: CONNECTOR, chatId: opts.chatId, msgId: cur, role, sender: null, text: fetched.text, ts: fetched.date, replyToId: fetched.replyToId });
|
|
36
|
+
stored = { msgId: cur, role, sender: null, text: fetched.text, ts: fetched.date, replyToId: fetched.replyToId };
|
|
37
|
+
}
|
|
38
|
+
acc.push({ role: stored.role, content: stored.text, sender: stored.sender, msgId: stored.msgId, ts: stored.ts });
|
|
39
|
+
cur = stored.replyToId;
|
|
40
|
+
}
|
|
41
|
+
if (acc.length >= max)
|
|
42
|
+
log.info(`chain capped at ${max} for ${headMsgId}`);
|
|
43
|
+
while (acc.length && acc.at(-1)?.role !== 'user')
|
|
44
|
+
acc.pop();
|
|
45
|
+
return acc.reverse();
|
|
46
|
+
}
|
package/dist/runtime/index.js
CHANGED
|
@@ -1,13 +1,26 @@
|
|
|
1
1
|
import { getPluginSettings } from '@coffer-org/server/plugin-runtime';
|
|
2
|
+
import { pruneThreadMessages } from '@coffer-org/server/thread-store';
|
|
2
3
|
import { startBot, stopBot } from "./bot.js";
|
|
4
|
+
import { getLogger } from '@coffer-org/sdk/logger';
|
|
5
|
+
const log = getLogger('telegram');
|
|
6
|
+
const THREAD_TTL_MS = Number(process.env['TELEGRAM_THREAD_TTL_MS'] ?? 7 * 86_400_000);
|
|
3
7
|
export { startBot, stopBot };
|
|
4
8
|
export { loadBotConfig, hasCredentials } from "./config.js";
|
|
5
9
|
export const serverHooks = {
|
|
6
10
|
init: async () => {
|
|
7
11
|
const dbSettings = await getPluginSettings('telegram');
|
|
8
|
-
void startBot({ dbSettings }).catch((e) =>
|
|
12
|
+
void startBot({ dbSettings }).catch((e) => log.warn(`failed to start: ${e.message}`));
|
|
9
13
|
},
|
|
10
14
|
teardown: async () => {
|
|
11
15
|
await stopBot();
|
|
12
16
|
},
|
|
17
|
+
backgroundTasks: [
|
|
18
|
+
{
|
|
19
|
+
name: 'telegram-thread-prune',
|
|
20
|
+
intervalMs: 86_400_000,
|
|
21
|
+
run: async () => {
|
|
22
|
+
await pruneThreadMessages('telegram', Math.floor((Date.now() - THREAD_TTL_MS) / 1000));
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
],
|
|
13
26
|
};
|
package/dist/schema.js
CHANGED
|
@@ -154,7 +154,10 @@ function assignProp(target, prop, value) {
|
|
|
154
154
|
}
|
|
155
155
|
function mergeDefs(...defs) {
|
|
156
156
|
const mergedDescriptors = {};
|
|
157
|
-
for (const def of defs)
|
|
157
|
+
for (const def of defs) {
|
|
158
|
+
const descriptors = Object.getOwnPropertyDescriptors(def);
|
|
159
|
+
Object.assign(mergedDescriptors, descriptors);
|
|
160
|
+
}
|
|
158
161
|
return Object.defineProperties({}, mergedDescriptors);
|
|
159
162
|
}
|
|
160
163
|
function esc(str) {
|
|
@@ -476,7 +479,7 @@ var _parse = (_Err) => (schema, value, _ctx, _params) => {
|
|
|
476
479
|
}, ctx);
|
|
477
480
|
if (result instanceof Promise) throw new $ZodAsyncError();
|
|
478
481
|
if (result.issues.length) {
|
|
479
|
-
const e = new (_params?.Err ?? _Err)(result.issues.map((iss) => finalizeIssue(iss, ctx, config())));
|
|
482
|
+
const e = new ((_params?.Err) ?? _Err)(result.issues.map((iss) => finalizeIssue(iss, ctx, config())));
|
|
480
483
|
captureStackTrace(e, _params?.callee);
|
|
481
484
|
throw e;
|
|
482
485
|
}
|
|
@@ -493,7 +496,7 @@ var _parseAsync = (_Err) => async (schema, value, _ctx, params) => {
|
|
|
493
496
|
}, ctx);
|
|
494
497
|
if (result instanceof Promise) result = await result;
|
|
495
498
|
if (result.issues.length) {
|
|
496
|
-
const e = new (params?.Err ?? _Err)(result.issues.map((iss) => finalizeIssue(iss, ctx, config())));
|
|
499
|
+
const e = new ((params?.Err) ?? _Err)(result.issues.map((iss) => finalizeIssue(iss, ctx, config())));
|
|
497
500
|
captureStackTrace(e, params?.callee);
|
|
498
501
|
throw e;
|
|
499
502
|
}
|
|
@@ -1589,13 +1592,13 @@ var $ZodObject = /*@__PURE__*/ $constructor("$ZodObject", (inst, def) => {
|
|
|
1589
1592
|
}
|
|
1590
1593
|
return propValues;
|
|
1591
1594
|
});
|
|
1592
|
-
const isObject$
|
|
1595
|
+
const isObject$2 = isObject;
|
|
1593
1596
|
const catchall = def.catchall;
|
|
1594
1597
|
let value;
|
|
1595
1598
|
inst._zod.parse = (payload, ctx) => {
|
|
1596
1599
|
value ?? (value = _normalized.value);
|
|
1597
1600
|
const input = payload.value;
|
|
1598
|
-
if (!isObject$
|
|
1601
|
+
if (!isObject$2(input)) {
|
|
1599
1602
|
payload.issues.push({
|
|
1600
1603
|
expected: "object",
|
|
1601
1604
|
code: "invalid_type",
|
|
@@ -1718,7 +1721,7 @@ var $ZodObjectJIT = /*@__PURE__*/ $constructor("$ZodObjectJIT", (inst, def) => {
|
|
|
1718
1721
|
return (payload, ctx) => fn(shape, payload, ctx);
|
|
1719
1722
|
};
|
|
1720
1723
|
let fastpass;
|
|
1721
|
-
const isObject$
|
|
1724
|
+
const isObject$1 = isObject;
|
|
1722
1725
|
const jit = !globalConfig.jitless;
|
|
1723
1726
|
const fastEnabled = jit && allowsEval.value;
|
|
1724
1727
|
const catchall = def.catchall;
|
|
@@ -1726,7 +1729,7 @@ var $ZodObjectJIT = /*@__PURE__*/ $constructor("$ZodObjectJIT", (inst, def) => {
|
|
|
1726
1729
|
inst._zod.parse = (payload, ctx) => {
|
|
1727
1730
|
value ?? (value = _normalized.value);
|
|
1728
1731
|
const input = payload.value;
|
|
1729
|
-
if (!isObject$
|
|
1732
|
+
if (!isObject$1(input)) {
|
|
1730
1733
|
payload.issues.push({
|
|
1731
1734
|
expected: "object",
|
|
1732
1735
|
code: "invalid_type",
|
|
@@ -1945,7 +1948,7 @@ var $ZodOptional = /*@__PURE__*/ $constructor("$ZodOptional", (inst, def) => {
|
|
|
1945
1948
|
inst._zod.optin = "optional";
|
|
1946
1949
|
inst._zod.optout = "optional";
|
|
1947
1950
|
defineLazy(inst._zod, "values", () => {
|
|
1948
|
-
return def.innerType._zod.values ? new Set([...def.innerType._zod.values, void 0]) : void 0;
|
|
1951
|
+
return def.innerType._zod.values ? /* @__PURE__ */ new Set([...def.innerType._zod.values, void 0]) : void 0;
|
|
1949
1952
|
});
|
|
1950
1953
|
defineLazy(inst._zod, "pattern", () => {
|
|
1951
1954
|
const pattern = def.innerType._zod.pattern;
|
|
@@ -1979,7 +1982,7 @@ var $ZodNullable = /*@__PURE__*/ $constructor("$ZodNullable", (inst, def) => {
|
|
|
1979
1982
|
return pattern ? new RegExp(`^(${cleanRegex(pattern.source)}|null)$`) : void 0;
|
|
1980
1983
|
});
|
|
1981
1984
|
defineLazy(inst._zod, "values", () => {
|
|
1982
|
-
return def.innerType._zod.values ? new Set([...def.innerType._zod.values, null]) : void 0;
|
|
1985
|
+
return def.innerType._zod.values ? /* @__PURE__ */ new Set([...def.innerType._zod.values, null]) : void 0;
|
|
1983
1986
|
});
|
|
1984
1987
|
inst._zod.parse = (payload, ctx) => {
|
|
1985
1988
|
if (payload.value === null) return payload;
|
|
@@ -4587,7 +4590,7 @@ function password(raw) {
|
|
|
4587
4590
|
* Internal API-token list — keyValue-shaped collection (name + write-only
|
|
4588
4591
|
* token + timestamps), custom renderer (`kind:'internalApiToken'`, own
|
|
4589
4592
|
* create/revoke UI — same trick as url()/perWeekday()). "Internal" = not a
|
|
4590
|
-
* general-purpose field type for plugin
|
|
4593
|
+
* general-purpose field type for plugin shelves, only for the core account
|
|
4591
4594
|
* settings page. `token` is `kind:'password'` so maskSecrets/preserveTree
|
|
4592
4595
|
* already mask/preserve it for free.
|
|
4593
4596
|
*/
|
|
@@ -4686,7 +4689,7 @@ var TEL_RE = /^\+?[\d\s()-]{4,}$/;
|
|
|
4686
4689
|
/** Loose URL: будь-який scheme:// АБО host-з-крапкою (+опц. порт/шлях). Без пробілів. */
|
|
4687
4690
|
var LINK_RE = /^([a-z][a-z0-9+.-]*:\/\/\S+|[\w-]+(\.[\w-]+)+(:\d+)?(\/\S*)?)$/i;
|
|
4688
4691
|
/** CSS named colors (CSS Color Module L4) — для f.colorname. */
|
|
4689
|
-
var CSS_COLOR_NAMES = new Set([
|
|
4692
|
+
var CSS_COLOR_NAMES = /* @__PURE__ */ new Set([
|
|
4690
4693
|
"aliceblue",
|
|
4691
4694
|
"antiquewhite",
|
|
4692
4695
|
"aqua",
|
|
@@ -5147,7 +5150,7 @@ var require_data = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
5147
5150
|
},
|
|
5148
5151
|
cs: {
|
|
5149
5152
|
name: "Czech",
|
|
5150
|
-
nativeName: "
|
|
5153
|
+
nativeName: "čeština"
|
|
5151
5154
|
},
|
|
5152
5155
|
cu: {
|
|
5153
5156
|
name: "Old Church Slavonic",
|
|
@@ -5611,7 +5614,7 @@ var require_data = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
5611
5614
|
},
|
|
5612
5615
|
sk: {
|
|
5613
5616
|
name: "Slovak",
|
|
5614
|
-
nativeName: "
|
|
5617
|
+
nativeName: "slovenčtina"
|
|
5615
5618
|
},
|
|
5616
5619
|
sl: {
|
|
5617
5620
|
name: "Slovenian",
|
|
@@ -5989,6 +5992,34 @@ function wrapKey(opts, meta) {
|
|
|
5989
5992
|
noEditControl: true
|
|
5990
5993
|
}
|
|
5991
5994
|
};
|
|
5995
|
+
if (opts.emphasis) m = {
|
|
5996
|
+
...m,
|
|
5997
|
+
hints: {
|
|
5998
|
+
...m.hints,
|
|
5999
|
+
emphasis: opts.emphasis
|
|
6000
|
+
}
|
|
6001
|
+
};
|
|
6002
|
+
if (opts.noLabel) m = {
|
|
6003
|
+
...m,
|
|
6004
|
+
hints: {
|
|
6005
|
+
...m.hints,
|
|
6006
|
+
noLabel: true
|
|
6007
|
+
}
|
|
6008
|
+
};
|
|
6009
|
+
if (opts.role) m = {
|
|
6010
|
+
...m,
|
|
6011
|
+
hints: {
|
|
6012
|
+
...m.hints,
|
|
6013
|
+
role: opts.role
|
|
6014
|
+
}
|
|
6015
|
+
};
|
|
6016
|
+
if (opts.pinned) m = {
|
|
6017
|
+
...m,
|
|
6018
|
+
hints: {
|
|
6019
|
+
...m.hints,
|
|
6020
|
+
pinned: true
|
|
6021
|
+
}
|
|
6022
|
+
};
|
|
5992
6023
|
if (opts.default !== void 0) m = {
|
|
5993
6024
|
...m,
|
|
5994
6025
|
default: opts.default
|
|
@@ -6352,8 +6383,8 @@ function relation(raw) {
|
|
|
6352
6383
|
displayKey: o.displayKey ?? "name"
|
|
6353
6384
|
},
|
|
6354
6385
|
relation: {
|
|
6355
|
-
|
|
6356
|
-
type: raw.options.
|
|
6386
|
+
library: raw.options.library,
|
|
6387
|
+
type: raw.options.shelf
|
|
6357
6388
|
},
|
|
6358
6389
|
...multi && { json: true },
|
|
6359
6390
|
zod: optionalize(s, required)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@coffer-org/plugin-telegram",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": ">=24"
|
|
@@ -25,11 +25,11 @@
|
|
|
25
25
|
"test": "node --import tsx --test \"src/runtime/*.test.ts\""
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@coffer-org/plugin-orchestrator": "^1.
|
|
29
|
-
"@coffer-org/sdk": "^1.
|
|
30
|
-
"@coffer-org/server": "^1.
|
|
28
|
+
"@coffer-org/plugin-orchestrator": "^1.4.0",
|
|
29
|
+
"@coffer-org/sdk": "^1.5.0",
|
|
30
|
+
"@coffer-org/server": "^1.8.0",
|
|
31
31
|
"input": "^1.0.1",
|
|
32
|
-
"
|
|
32
|
+
"teleproto": "^1.228.1"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {},
|
|
35
35
|
"coffer": {
|