stitchkit 0.100.1 → 0.100.3
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/CHANGELOG.md +99 -0
- package/README.md +2 -1
- package/dist/application/process-lifecycle-transitions.d.ts +13 -2
- package/dist/application/process-lifecycle-transitions.d.ts.map +1 -1
- package/dist/application/process-lifecycle.d.ts +2 -1
- package/dist/application/process-lifecycle.d.ts.map +1 -1
- package/dist/entrypoints/agent-runtime/browser.js +119 -119
- package/dist/entrypoints/agent-runtime/coding-tools.js +15 -20
- package/dist/entrypoints/agent-runtime/harness.js +55 -63
- package/dist/entrypoints/agent-runtime/openrouter.js +6 -6
- package/dist/entrypoints/agent-runtime/sandbox.js +20 -25
- package/dist/entrypoints/agent-runtime/sqlite/bun.js +11 -13
- package/dist/entrypoints/agent-runtime/sqlite/node.js +11 -13
- package/dist/entrypoints/agent-runtime/testing.js +32 -34
- package/dist/entrypoints/agent-runtime.js +395 -402
- package/dist/entrypoints/application/diagnostic-journal.js +26 -27
- package/dist/entrypoints/application/directory-inbox.js +16 -17
- package/dist/entrypoints/application/grammy.js +13 -13
- package/dist/entrypoints/application/opentelemetry.js +13 -13
- package/dist/entrypoints/application/schemas.js +24 -24
- package/dist/entrypoints/application.d.ts +1 -1
- package/dist/entrypoints/application.d.ts.map +1 -1
- package/dist/entrypoints/application.js +218 -214
- package/dist/entrypoints/bin/upgrade-cli.js +2 -2
- package/dist/entrypoints/cli.js +81 -84
- package/dist/entrypoints/contract.js +54 -57
- package/dist/entrypoints/declaration.js +22 -22
- package/dist/entrypoints/files.js +18 -21
- package/dist/entrypoints/geo.js +7 -8
- package/dist/entrypoints/google.js +2 -2
- package/dist/entrypoints/index.js +150 -154
- package/dist/entrypoints/live.js +45 -47
- package/dist/entrypoints/node.js +68 -74
- package/dist/entrypoints/oauth.js +6 -6
- package/dist/entrypoints/observability.d.ts +1 -0
- package/dist/entrypoints/observability.d.ts.map +1 -1
- package/dist/entrypoints/observability.js +115 -87
- package/dist/entrypoints/primitives.js +35 -35
- package/dist/entrypoints/react/keyboard.d.ts +4 -0
- package/dist/entrypoints/react/keyboard.d.ts.map +1 -0
- package/dist/entrypoints/react/keyboard.js +397 -0
- package/dist/entrypoints/react.js +10 -10
- package/dist/entrypoints/release.js +7 -7
- package/dist/entrypoints/remote.js +15 -17
- package/dist/entrypoints/server.js +198 -200
- package/dist/entrypoints/telegram/html.d.ts +5 -0
- package/dist/entrypoints/telegram/html.d.ts.map +1 -0
- package/dist/entrypoints/telegram/html.js +26 -0
- package/dist/entrypoints/telegram/screens.d.ts +14 -0
- package/dist/entrypoints/telegram/screens.d.ts.map +1 -0
- package/dist/entrypoints/telegram/screens.js +2028 -0
- package/dist/entrypoints/telegram.d.ts +5 -1
- package/dist/entrypoints/telegram.d.ts.map +1 -1
- package/dist/entrypoints/telegram.js +548 -156
- package/dist/entrypoints/testing.js +75 -79
- package/dist/entrypoints/tools/connections.js +30 -32
- package/dist/entrypoints/tools/contract.js +18 -20
- package/dist/entrypoints/tools/invoker.js +12 -17
- package/dist/entrypoints/tools.js +223 -229
- package/dist/entrypoints/tracking/server.js +6 -6
- package/dist/entrypoints/tracking.js +40 -42
- package/dist/entrypoints/voice.js +3 -3
- package/dist/{index-eaysmdtq.js → index-0ndk4555.js} +56 -56
- package/dist/{index-2bxbyab0.js → index-1bx1xv1k.js} +1 -1
- package/dist/{index-p5r7qpdd.js → index-1eeqpadm.js} +4 -4
- package/dist/{index-hadmp193.js → index-3ct7hhq6.js} +210 -210
- package/dist/{index-e01r054k.js → index-45tdvqa3.js} +26 -26
- package/dist/{index-dce5wxcq.js → index-4s0fep5q.js} +8 -8
- package/dist/index-50ejfz75.js +9 -0
- package/dist/{index-m9zn6cpq.js → index-5107q189.js} +12 -12
- package/dist/{index-sbdmyz75.js → index-5cc6r990.js} +3 -3
- package/dist/index-6k1svmjh.js +141 -0
- package/dist/{index-c6bxbsnc.js → index-7kxw1awn.js} +2 -2
- package/dist/{index-0r0fbk7z.js → index-7z9ym7t8.js} +28 -28
- package/dist/{index-p7hgdyhb.js → index-814xpr6d.js} +2 -2
- package/dist/{index-gtj3zc53.js → index-8kzct1d6.js} +99 -99
- package/dist/{index-1zbbzgfh.js → index-9pw0a51a.js} +4 -4
- package/dist/{index-79z7m7dt.js → index-a9pd417t.js} +35 -35
- package/dist/{index-ham5sz8m.js → index-aaj97r4y.js} +45 -45
- package/dist/{index-s812ycat.js → index-aan6hqb9.js} +3 -3
- package/dist/{index-10x2hbx0.js → index-adhgd4pe.js} +44 -44
- package/dist/{index-2gxzjvyr.js → index-afjvjyck.js} +23 -23
- package/dist/{index-qmy6zq75.js → index-ahvsksw5.js} +16 -16
- package/dist/{index-hr4tzbwq.js → index-ap3gqe56.js} +3 -3
- package/dist/{index-znfs20ss.js → index-b2bz0kdm.js} +16 -16
- package/dist/{index-r066jx76.js → index-c6aagrbd.js} +148 -120
- package/dist/{index-k30h66yd.js → index-ck71tbcf.js} +9 -9
- package/dist/{index-eqqvgdb3.js → index-ct75c3at.js} +2 -2
- package/dist/{index-gw8bmyaj.js → index-djjhhgjk.js} +41 -41
- package/dist/{index-8qt2m66q.js → index-dvwj1f43.js} +43 -43
- package/dist/{index-fhwqwxe0.js → index-ej331hah.js} +1 -1
- package/dist/{index-9t3dffv2.js → index-ewbaywk5.js} +5 -5
- package/dist/{index-7p1f0vp2.js → index-fyphpknh.js} +25 -25
- package/dist/{index-83bdg97s.js → index-g149e9pk.js} +1 -1
- package/dist/{index-ngfhvfpd.js → index-g6a3na27.js} +4 -4
- package/dist/{index-qwhynv6x.js → index-h124epcf.js} +20 -20
- package/dist/{index-h6eeys1v.js → index-h97tqqp1.js} +9 -9
- package/dist/{index-zcgf3gqf.js → index-hby4qhax.js} +10 -10
- package/dist/{index-5jrd0yng.js → index-j8aw2c0e.js} +4 -4
- package/dist/{index-d8m8zpd8.js → index-jzczzcsb.js} +14 -14
- package/dist/index-kqnd6a85.js +26 -0
- package/dist/{index-35mh5bhj.js → index-kw1ws0cs.js} +12 -12
- package/dist/{index-yw4fzmdz.js → index-kzz6rq0w.js} +28 -17
- package/dist/{index-4gcnakhx.js → index-m38ej7e5.js} +2 -2
- package/dist/{index-ndddxtyx.js → index-m79yr938.js} +19 -19
- package/dist/{index-5p2m7we1.js → index-m9fndta6.js} +11 -11
- package/dist/index-mnkk1ffz.js +150 -0
- package/dist/index-n15jny5b.js +4 -0
- package/dist/{index-2vtcmrj9.js → index-n53mswt3.js} +20 -20
- package/dist/{index-bt14acb5.js → index-n5yqxd3d.js} +21 -21
- package/dist/{index-bm5rx7n6.js → index-n9tyz8z3.js} +12 -12
- package/dist/index-nmaqxdx7.js +463 -0
- package/dist/{index-mqv3b5rh.js → index-nx6eazt0.js} +30 -30
- package/dist/{index-3z73fh2c.js → index-q0th8q0z.js} +9 -9
- package/dist/{index-v260df89.js → index-qjeggp8w.js} +20 -20
- package/dist/{index-zfrhfn82.js → index-r1z0rd9c.js} +20 -20
- package/dist/{index-wqgjfstn.js → index-r5c4fedv.js} +3 -3
- package/dist/{index-cyktc4bp.js → index-r5hsgkz5.js} +118 -118
- package/dist/{index-0b1ess5e.js → index-r7a7r7ha.js} +1 -1
- package/dist/{index-1j8pm5t0.js → index-rfkh44ss.js} +15 -15
- package/dist/index-rz3z13e9.js +47 -0
- package/dist/{index-k6gpggb9.js → index-s80awwsw.js} +35 -35
- package/dist/{index-vqr7f7v8.js → index-ssmd41kh.js} +124 -124
- package/dist/{index-ensd0r74.js → index-v14qqmys.js} +41 -41
- package/dist/{index-paz6sgdp.js → index-v4a2fjtk.js} +36 -36
- package/dist/{index-d9pk3td4.js → index-w0eqdhyd.js} +14 -14
- package/dist/{index-5qn1kx34.js → index-w575evhq.js} +29 -29
- package/dist/{index-3gye9wzb.js → index-w5s3xftz.js} +26 -26
- package/dist/{index-tm88avnj.js → index-wykebpn9.js} +3 -3
- package/dist/{index-sh3s86na.js → index-xkhk5d6g.js} +17 -17
- package/dist/{index-6k1937bx.js → index-xqhede6x.js} +4 -4
- package/dist/{index-f4fx2tza.js → index-zs4ms3th.js} +181 -181
- package/dist/{index-k5hsfc3j.js → index-zsvzhjtk.js} +1 -1
- package/dist/observability/bounded-logger.d.ts +2 -0
- package/dist/observability/bounded-logger.d.ts.map +1 -1
- package/dist/observability/sanitize.d.ts +6 -0
- package/dist/observability/sanitize.d.ts.map +1 -1
- package/dist/observability/secret-values.d.ts +25 -0
- package/dist/observability/secret-values.d.ts.map +1 -0
- package/dist/react/keyboard/hooks.d.ts +71 -0
- package/dist/react/keyboard/hooks.d.ts.map +1 -0
- package/dist/react/keyboard/layers.d.ts +98 -0
- package/dist/react/keyboard/layers.d.ts.map +1 -0
- package/dist/react/keyboard/zone.d.ts +139 -0
- package/dist/react/keyboard/zone.d.ts.map +1 -0
- package/dist/telegram/crypto.d.ts +16 -0
- package/dist/telegram/crypto.d.ts.map +1 -0
- package/dist/telegram/html/check.d.ts +26 -0
- package/dist/telegram/html/check.d.ts.map +1 -0
- package/dist/telegram/html/nodes.d.ts +70 -0
- package/dist/telegram/html/nodes.d.ts.map +1 -0
- package/dist/telegram/html/parse.d.ts +35 -0
- package/dist/telegram/html/parse.d.ts.map +1 -0
- package/dist/telegram/html/render.d.ts +39 -0
- package/dist/telegram/html/render.d.ts.map +1 -0
- package/dist/telegram/init-data.d.ts.map +1 -1
- package/dist/telegram/operator-channel.d.ts +36 -3
- package/dist/telegram/operator-channel.d.ts.map +1 -1
- package/dist/telegram/screens/callback-codec.d.ts +34 -0
- package/dist/telegram/screens/callback-codec.d.ts.map +1 -0
- package/dist/telegram/screens/dispatch.d.ts +22 -0
- package/dist/telegram/screens/dispatch.d.ts.map +1 -0
- package/dist/telegram/screens/display.d.ts +70 -0
- package/dist/telegram/screens/display.d.ts.map +1 -0
- package/dist/telegram/screens/execute.d.ts +57 -0
- package/dist/telegram/screens/execute.d.ts.map +1 -0
- package/dist/telegram/screens/html.d.ts +36 -0
- package/dist/telegram/screens/html.d.ts.map +1 -0
- package/dist/telegram/screens/outcome.d.ts +74 -0
- package/dist/telegram/screens/outcome.d.ts.map +1 -0
- package/dist/telegram/screens/path.d.ts +29 -0
- package/dist/telegram/screens/path.d.ts.map +1 -0
- package/dist/telegram/screens/reconcile.d.ts +67 -0
- package/dist/telegram/screens/reconcile.d.ts.map +1 -0
- package/dist/telegram/screens/registry.d.ts +23 -0
- package/dist/telegram/screens/registry.d.ts.map +1 -0
- package/dist/telegram/screens/render.d.ts +70 -0
- package/dist/telegram/screens/render.d.ts.map +1 -0
- package/dist/telegram/screens/runtime.d.ts +133 -0
- package/dist/telegram/screens/runtime.d.ts.map +1 -0
- package/dist/telegram/screens/screen-types.d.ts +130 -0
- package/dist/telegram/screens/screen-types.d.ts.map +1 -0
- package/dist/telegram/screens/screen.d.ts +138 -0
- package/dist/telegram/screens/screen.d.ts.map +1 -0
- package/dist/telegram/screens/state.d.ts +115 -0
- package/dist/telegram/screens/state.d.ts.map +1 -0
- package/dist/telegram/screens/telegram-screens.d.ts +18 -0
- package/dist/telegram/screens/telegram-screens.d.ts.map +1 -0
- package/dist/telegram/screens/test-chat-telegram.d.ts +47 -0
- package/dist/telegram/screens/test-chat-telegram.d.ts.map +1 -0
- package/dist/telegram/screens/test-chat.d.ts +66 -0
- package/dist/telegram/screens/test-chat.d.ts.map +1 -0
- package/dist/telegram/screens/view.d.ts +89 -0
- package/dist/telegram/screens/view.d.ts.map +1 -0
- package/dist/telegram/send-failure.d.ts +19 -0
- package/dist/telegram/send-failure.d.ts.map +1 -1
- package/dist/telegram/update-intake.d.ts +78 -0
- package/dist/telegram/update-intake.d.ts.map +1 -0
- package/dist/telegram/update-store-sqlite.d.ts +26 -0
- package/dist/telegram/update-store-sqlite.d.ts.map +1 -0
- package/dist/telegram/update-store.d.ts +67 -0
- package/dist/telegram/update-store.d.ts.map +1 -0
- package/dist/telegram/webhook.d.ts +105 -0
- package/dist/telegram/webhook.d.ts.map +1 -0
- package/dist/tools/cli/args-fields.d.ts +8 -0
- package/dist/tools/cli/args-fields.d.ts.map +1 -1
- package/dist/tools/cli/args-route.d.ts.map +1 -1
- package/dist/tools/cli/args.d.ts.map +1 -1
- package/dist/tools/cli/help.d.ts.map +1 -1
- package/llms/application.2.txt +26 -1
- package/llms/application.txt +18 -27
- package/llms/cli.txt +8 -2
- package/llms/observability.txt +2 -1
- package/llms/react-keyboard.txt +193 -0
- package/llms/stitchkit.txt +7 -1
- package/llms/telegram-html.txt +35 -0
- package/llms/telegram-screens.txt +365 -0
- package/llms/telegram.txt +160 -4
- package/llms-full.txt +755 -11
- package/llms.txt +11 -6
- package/package.json +17 -2
- package/dist/index-2k4yrqkc.js +0 -9
- package/dist/index-crykmqkr.js +0 -26
- package/dist/index-y64k3s0h.js +0 -150
- package/dist/index-y91ry9h2.js +0 -4
- /package/dist/{index-hffjpmq9.js → index-9jfdm5tg.js} +0 -0
- /package/dist/{index-zjjyynm3.js → index-d4pa2bgs.js} +0 -0
- /package/dist/{index-rxfy4cq7.js → index-dwfv9a85.js} +0 -0
- /package/dist/{index-5jm36zv1.js → index-gfk7nrht.js} +0 -0
- /package/dist/{index-b9aefrqd.js → index-n1dqr7gf.js} +0 -0
- /package/dist/{index-q3pyb9n0.js → index-sykb5ag7.js} +0 -0
- /package/dist/{index-48ffdxgk.js → index-xhzq2qvj.js} +0 -0
- /package/dist/{index-kzfs85xp.js → index-zsarb5xp.js} +0 -0
|
@@ -27,9 +27,11 @@ export interface TelegramOperatorDrop<TTopic extends string> {
|
|
|
27
27
|
/**
|
|
28
28
|
* `overflow` — the queue was full and this was the oldest; `refused` —
|
|
29
29
|
* Telegram said no in a way repeating will not fix; `attempts` — it kept
|
|
30
|
-
* failing; `closed` — the channel closed before it was sent
|
|
30
|
+
* failing; `closed` — the channel closed before it was sent; `repeated`
|
|
31
|
+
* — the same message was sent within the dedupe window; `over-budget` —
|
|
32
|
+
* the window's budget was spent.
|
|
31
33
|
*/
|
|
32
|
-
readonly reason: 'overflow' | 'refused' | 'attempts' | 'closed';
|
|
34
|
+
readonly reason: 'overflow' | 'refused' | 'attempts' | 'closed' | 'repeated' | 'over-budget';
|
|
33
35
|
readonly failure?: TelegramSendFailure;
|
|
34
36
|
}
|
|
35
37
|
export interface TelegramOperatorChannelConfig<TTopic extends string> {
|
|
@@ -54,6 +56,33 @@ export interface TelegramOperatorChannelConfig<TTopic extends string> {
|
|
|
54
56
|
* API file carries `<root>/<token>/…` in its path.
|
|
55
57
|
*/
|
|
56
58
|
readonly sensitivePatterns?: readonly RegExp[];
|
|
59
|
+
/** Exact secret values to mask as well — `secretValuesFromEnv(process.env)`. */
|
|
60
|
+
readonly sensitiveValues?: readonly string[];
|
|
61
|
+
/**
|
|
62
|
+
* Hold back repeats and storms. The same message — by `fingerprint` — is
|
|
63
|
+
* sent once per window; the next one sent says how many were held back.
|
|
64
|
+
* Past `maxPerWindow` messages in a window the rest are counted, and the
|
|
65
|
+
* count rides on the first message sent after.
|
|
66
|
+
*/
|
|
67
|
+
readonly dedupe?: TelegramOperatorDedupe<TTopic>;
|
|
68
|
+
}
|
|
69
|
+
export interface TelegramOperatorDedupe<TTopic extends string> {
|
|
70
|
+
/** Default 600 000 — ten minutes. */
|
|
71
|
+
readonly windowMs?: number;
|
|
72
|
+
/** Messages sent per window, whatever their fingerprint. Default 20. */
|
|
73
|
+
readonly maxPerWindow?: number;
|
|
74
|
+
/**
|
|
75
|
+
* What makes two messages the same. Default: the topic and the text with
|
|
76
|
+
* numbers, UUIDs and long identifiers blanked — they differ between two
|
|
77
|
+
* occurrences of one failure without making it another.
|
|
78
|
+
*/
|
|
79
|
+
readonly fingerprint?: (text: string, topic: TTopic | undefined) => string;
|
|
80
|
+
/** The line added to a message after `count` of its repeats were held back. */
|
|
81
|
+
readonly repeatedLine?: (count: number) => string;
|
|
82
|
+
/** The line added to the first message after `count` were held back by the budget. */
|
|
83
|
+
readonly overBudgetLine?: (count: number) => string;
|
|
84
|
+
/** Default `Date.now`. */
|
|
85
|
+
readonly now?: () => number;
|
|
57
86
|
}
|
|
58
87
|
export interface TelegramOperatorChannel<TTopic extends string> {
|
|
59
88
|
/** Queue one message. Returns at once and never throws. */
|
|
@@ -73,6 +102,10 @@ export interface TelegramOperatorSenderConfig {
|
|
|
73
102
|
readonly parseMode?: 'HTML' | 'MarkdownV2';
|
|
74
103
|
readonly fetch?: typeof fetch;
|
|
75
104
|
}
|
|
76
|
-
/**
|
|
105
|
+
/**
|
|
106
|
+
* The standard `send`: `sendMessage` through the Bot API, no bot library. With
|
|
107
|
+
* `parseMode: 'HTML'` the text is repaired and cut by what it shows, so a cut
|
|
108
|
+
* never leaves a tag open.
|
|
109
|
+
*/
|
|
77
110
|
export declare function telegramOperatorSender(config: TelegramOperatorSenderConfig): TelegramOperatorChannelConfig<string>['send'];
|
|
78
111
|
//# sourceMappingURL=operator-channel.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"operator-channel.d.ts","sourceRoot":"","sources":["../../src/telegram/operator-channel.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;
|
|
1
|
+
{"version":3,"file":"operator-channel.d.ts","sourceRoot":"","sources":["../../src/telegram/operator-channel.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/** Telegram's limit for `callback_data`, in UTF-8 bytes. */
|
|
2
|
+
export declare const CALLBACK_DATA_LIMIT = 64;
|
|
3
|
+
/** A value a param or an action's input may carry through a button. */
|
|
4
|
+
export type ActionValue = string | number | boolean | null;
|
|
5
|
+
export interface CallbackAddress {
|
|
6
|
+
readonly screen: string;
|
|
7
|
+
readonly action?: string;
|
|
8
|
+
readonly params: readonly ActionValue[];
|
|
9
|
+
readonly input?: Readonly<Record<string, ActionValue | undefined>>;
|
|
10
|
+
/** Opens the screen below instead of changing the message it is on. */
|
|
11
|
+
readonly detached?: boolean;
|
|
12
|
+
}
|
|
13
|
+
export type ParsedCallback = {
|
|
14
|
+
readonly kind: 'token';
|
|
15
|
+
readonly token: string;
|
|
16
|
+
} | {
|
|
17
|
+
readonly kind: 'address';
|
|
18
|
+
readonly screen: string;
|
|
19
|
+
readonly action: string | undefined;
|
|
20
|
+
readonly detached: boolean;
|
|
21
|
+
/** Still encoded: the screen decides which are params and which input. */
|
|
22
|
+
readonly segments: readonly string[];
|
|
23
|
+
};
|
|
24
|
+
export declare function utf8Length(text: string): number;
|
|
25
|
+
/** A screen id, action name or token: safe inside the grammar without escaping. */
|
|
26
|
+
export declare function assertCallbackName(kind: string, name: string): void;
|
|
27
|
+
export declare function encodeCallback(address: CallbackAddress): string;
|
|
28
|
+
export declare function encodeToken(token: string): string;
|
|
29
|
+
export declare function parseCallback(body: string): ParsedCallback | null;
|
|
30
|
+
/** Positional path params; `null` when any is malformed. */
|
|
31
|
+
export declare function decodeParams(segments: readonly string[]): ActionValue[] | null;
|
|
32
|
+
/** Named input entries; `null` when any is malformed, unsafe or repeated. */
|
|
33
|
+
export declare function decodeInput(segments: readonly string[]): Record<string, ActionValue> | null;
|
|
34
|
+
//# sourceMappingURL=callback-codec.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"callback-codec.d.ts","sourceRoot":"","sources":["../../../src/telegram/screens/callback-codec.ts"],"names":[],"mappings":"AA2BA,4DAA4D;AAC5D,eAAO,MAAM,mBAAmB,KAAK,CAAC;AAEtC,uEAAuE;AACvE,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,CAAC;AAO3D,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,SAAS,WAAW,EAAE,CAAC;IACxC,QAAQ,CAAC,KAAK,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,WAAW,GAAG,SAAS,CAAC,CAAC,CAAC;IACnE,uEAAuE;IACvE,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED,MAAM,MAAM,cAAc,GACtB;IAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAClD;IACE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,0EAA0E;IAC1E,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;CACtC,CAAC;AAEN,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE/C;AAED,mFAAmF;AACnF,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAMnE;AA0DD,wBAAgB,cAAc,CAAC,OAAO,EAAE,eAAe,GAAG,MAAM,CAkB/D;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEjD;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI,CAYjE;AAED,4DAA4D;AAC5D,wBAAgB,YAAY,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,GAAG,WAAW,EAAE,GAAG,IAAI,CAQ9E;AAED,6EAA6E;AAC7E,wBAAgB,WAAW,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,GAAG,IAAI,CAY3F"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The three ways a chat reaches a screen: a press, a message, an open.
|
|
3
|
+
*
|
|
4
|
+
* A press is trusted only as far as Telegram vouches for it. Telegram sends
|
|
5
|
+
* the pressed message along with its keyboard, and a `callback_data` that is
|
|
6
|
+
* not on that keyboard was not pressed — it was sent (MTProto lets a client
|
|
7
|
+
* send any bytes) — so it never reaches a handler. What remains is still user
|
|
8
|
+
* input: params go through the screen's schema and every load above it before
|
|
9
|
+
* an action runs.
|
|
10
|
+
*/
|
|
11
|
+
import type { Context } from 'grammy';
|
|
12
|
+
import type { Message } from 'grammy/types';
|
|
13
|
+
import { type ScreenOrigin } from './display.js';
|
|
14
|
+
import type { ScreensRuntime } from './runtime.js';
|
|
15
|
+
import type { ScreenInputKind } from './screen-types.js';
|
|
16
|
+
/** The input kind of a message, for `.on(...)`; animations also carry `document`. */
|
|
17
|
+
export declare function inputKindOf(message: Message): ScreenInputKind | undefined;
|
|
18
|
+
export declare function dispatchPress<C extends Context>(runtime: ScreensRuntime<C>, ctx: C): Promise<void>;
|
|
19
|
+
/** Whether the message was taken as input; `false` hands it to the next handler. */
|
|
20
|
+
export declare function dispatchInput<C extends Context>(runtime: ScreensRuntime<C>, ctx: C, message: Message): Promise<boolean>;
|
|
21
|
+
export declare function openScreen<C extends Context>(runtime: ScreensRuntime<C>, ctx: C, origin: ScreenOrigin<C>, previous: 'keep' | 'delete'): Promise<void>;
|
|
22
|
+
//# sourceMappingURL=dispatch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dispatch.d.ts","sourceRoot":"","sources":["../../../src/telegram/screens/dispatch.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,KAAK,EAA4B,OAAO,EAAE,MAAM,cAAc,CAAC;AAGtE,OAAO,EAEL,KAAK,YAAY,EAKlB,MAAM,WAAW,CAAC;AAMnB,OAAO,KAAK,EAAqB,cAAc,EAAiB,MAAM,WAAW,CAAC;AAClF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AA2BtD,qFAAqF;AACrF,wBAAgB,WAAW,CAAC,OAAO,EAAE,OAAO,GAAG,eAAe,GAAG,SAAS,CAczE;AAwKD,wBAAsB,aAAa,CAAC,CAAC,SAAS,OAAO,EACnD,OAAO,EAAE,cAAc,CAAC,CAAC,CAAC,EAC1B,GAAG,EAAE,CAAC,GACL,OAAO,CAAC,IAAI,CAAC,CAgFf;AAED,oFAAoF;AACpF,wBAAsB,aAAa,CAAC,CAAC,SAAS,OAAO,EACnD,OAAO,EAAE,cAAc,CAAC,CAAC,CAAC,EAC1B,GAAG,EAAE,CAAC,EACN,OAAO,EAAE,OAAO,GACf,OAAO,CAAC,OAAO,CAAC,CAmFlB;AAED,wBAAsB,UAAU,CAAC,CAAC,SAAS,OAAO,EAChD,OAAO,EAAE,cAAc,CAAC,CAAC,CAAC,EAC1B,GAAG,EAAE,CAAC,EACN,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,EACvB,QAAQ,EAAE,MAAM,GAAG,QAAQ,GAC1B,OAAO,CAAC,IAAI,CAAC,CA8Bf"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* From an outcome to the chat: which screen, then what the chat shows.
|
|
3
|
+
*
|
|
4
|
+
* `settleNavigation` follows an outcome to the screen it names — resolving it,
|
|
5
|
+
* and following again when that screen's load answers with an outcome of its
|
|
6
|
+
* own — collecting the toast and notices met on the way. `displayScreen`
|
|
7
|
+
* renders the settled screen, reconciles it with what the chat shows, carries
|
|
8
|
+
* the plan out and writes the chat's record — also when Telegram refused a
|
|
9
|
+
* call halfway, so the record never claims less or more than the chat shows.
|
|
10
|
+
*/
|
|
11
|
+
import type { Context } from 'grammy';
|
|
12
|
+
import type { ActionValue } from './callback-codec.js';
|
|
13
|
+
import { type ScreenApi } from './execute.js';
|
|
14
|
+
import type { TelegramText } from './html.js';
|
|
15
|
+
import type { ScreenNotice, ScreenOutcome, ScreenToast } from './outcome.js';
|
|
16
|
+
import { type ShownMessage } from './reconcile.js';
|
|
17
|
+
import type { RegisteredScreen } from './registry.js';
|
|
18
|
+
import type { ScreensRuntime, ScreenTrigger } from './runtime.js';
|
|
19
|
+
import type { ResolvedScreen } from './screen-types.js';
|
|
20
|
+
import { type ScreenChatState } from './state.js';
|
|
21
|
+
/** Where a chat is, as far as navigation is concerned. */
|
|
22
|
+
export interface ScreenOrigin<C extends Context> {
|
|
23
|
+
readonly entry: RegisteredScreen<C>;
|
|
24
|
+
/** As a button or the record carries them; the screen's schema parses them on resolution. */
|
|
25
|
+
readonly params: Readonly<Record<string, ActionValue>>;
|
|
26
|
+
}
|
|
27
|
+
export interface SettledNavigation<C extends Context> {
|
|
28
|
+
/** Absent when the outcome leads nowhere — a stay with no screen to stay on. */
|
|
29
|
+
readonly target: {
|
|
30
|
+
readonly entry: RegisteredScreen<C>;
|
|
31
|
+
readonly resolved: ResolvedScreen;
|
|
32
|
+
} | undefined;
|
|
33
|
+
readonly toast: ScreenToast | undefined;
|
|
34
|
+
readonly notices: readonly ScreenNotice[];
|
|
35
|
+
}
|
|
36
|
+
export declare function settleNavigation<C extends Context>(runtime: ScreensRuntime<C>, ctx: C, origin: ScreenOrigin<C> | undefined, outcome: ScreenOutcome): Promise<SettledNavigation<C>>;
|
|
37
|
+
/** What the new view is reconciled against. */
|
|
38
|
+
export type DisplayBase =
|
|
39
|
+
/** What the chat's record says it shows. */
|
|
40
|
+
{
|
|
41
|
+
readonly mode: 'state';
|
|
42
|
+
}
|
|
43
|
+
/** A message pressed outside that view. */
|
|
44
|
+
| {
|
|
45
|
+
readonly mode: 'foreign';
|
|
46
|
+
readonly message: ShownMessage;
|
|
47
|
+
}
|
|
48
|
+
/** Nothing: the view is sent below and the old one left as it is. */
|
|
49
|
+
| {
|
|
50
|
+
readonly mode: 'new';
|
|
51
|
+
}
|
|
52
|
+
/** The old view is deleted and the new one sent below. */
|
|
53
|
+
| {
|
|
54
|
+
readonly mode: 'fresh';
|
|
55
|
+
};
|
|
56
|
+
export interface DisplayRequest<C extends Context> {
|
|
57
|
+
readonly ctx: C;
|
|
58
|
+
readonly chat: string;
|
|
59
|
+
readonly chatId: number;
|
|
60
|
+
readonly state: ScreenChatState;
|
|
61
|
+
readonly settled: SettledNavigation<C>;
|
|
62
|
+
readonly base: DisplayBase;
|
|
63
|
+
readonly trigger: ScreenTrigger;
|
|
64
|
+
readonly started: number;
|
|
65
|
+
}
|
|
66
|
+
export declare function sendText(api: ScreenApi, chatId: number, content: TelegramText): Promise<number>;
|
|
67
|
+
/** Delete the chat's remarks whose time has come, and write the record. */
|
|
68
|
+
export declare function sweepDue<C extends Context>(runtime: ScreensRuntime<C>, api: ScreenApi, chat: string, chatId: number): Promise<ScreenChatState>;
|
|
69
|
+
export declare function displayScreen<C extends Context>(runtime: ScreensRuntime<C>, request: DisplayRequest<C>): Promise<void>;
|
|
70
|
+
//# sourceMappingURL=display.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"display.d.ts","sourceRoot":"","sources":["../../../src/telegram/screens/display.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Carrying out a view plan through the Bot API.
|
|
3
|
+
*
|
|
4
|
+
* The plan is what should work; this is what to do when Telegram disagrees.
|
|
5
|
+
* Three refusals are expected in a live chat and none of them is a failure of
|
|
6
|
+
* the screen:
|
|
7
|
+
*
|
|
8
|
+
* - **"message is not modified"** — the edit asked for what is already there
|
|
9
|
+
* (content the record never saw, an adopted message). It is success.
|
|
10
|
+
* - **the message is gone or cannot be edited** — deleted by the user, or not
|
|
11
|
+
* ours. That message and every one after it are sent anew, because a new
|
|
12
|
+
* message lands at the bottom and the order must hold.
|
|
13
|
+
* - **a deletion refused** — Telegram lets a bot delete only messages younger
|
|
14
|
+
* than 48 hours, and a network can drop the call. The view is already right
|
|
15
|
+
* without it; the message loses its buttons instead (an edit has no age
|
|
16
|
+
* limit), so no stale menu stays live, and its id is reported.
|
|
17
|
+
*
|
|
18
|
+
* Anything else — a rate limit, a payload Telegram cannot parse, a network
|
|
19
|
+
* failure — stops the plan. What was already done is not undone: the
|
|
20
|
+
* {@link PlanInterrupted} error carries the messages the chat now shows, with
|
|
21
|
+
* the ones whose content is uncertain marked unknown, so the chat's record is
|
|
22
|
+
* written true and the next render repairs the rest.
|
|
23
|
+
*/
|
|
24
|
+
import type { Api } from 'grammy';
|
|
25
|
+
import type { ShownMessage, ViewPlan } from './reconcile.js';
|
|
26
|
+
import type { OutgoingMessage } from './render.js';
|
|
27
|
+
/** The Bot API methods screens call — `ctx.api` provides them. */
|
|
28
|
+
export type ScreenApi = Pick<Api, 'sendMessage' | 'sendRichMessage' | 'sendPhoto' | 'sendVideo' | 'sendAnimation' | 'sendDocument' | 'sendAudio' | 'editMessageText' | 'editMessageCaption' | 'editMessageMedia' | 'editMessageReplyMarkup' | 'deleteMessage' | 'answerCallbackQuery'>;
|
|
29
|
+
export type ChatId = number;
|
|
30
|
+
export interface ExecutionReport {
|
|
31
|
+
readonly sent: number;
|
|
32
|
+
readonly edited: number;
|
|
33
|
+
readonly kept: number;
|
|
34
|
+
readonly deleted: number;
|
|
35
|
+
/** Messages Telegram would not delete; they stay, without buttons. */
|
|
36
|
+
readonly undeleted: readonly number[];
|
|
37
|
+
}
|
|
38
|
+
export interface ExecutedView {
|
|
39
|
+
readonly shown: readonly ShownMessage[];
|
|
40
|
+
readonly report: ExecutionReport;
|
|
41
|
+
}
|
|
42
|
+
/** A plan stopped by a refusal the chat cannot absorb; `shown` is what the chat shows now. */
|
|
43
|
+
export declare class PlanInterrupted extends Error {
|
|
44
|
+
readonly shown: readonly ShownMessage[];
|
|
45
|
+
readonly cause: unknown;
|
|
46
|
+
constructor(shown: readonly ShownMessage[], cause: unknown);
|
|
47
|
+
}
|
|
48
|
+
export declare function sendOutgoing(api: ScreenApi, chatId: ChatId, message: OutgoingMessage): Promise<number>;
|
|
49
|
+
/**
|
|
50
|
+
* Delete messages; a message Telegram will not delete loses its buttons
|
|
51
|
+
* instead. Returns the ids that stayed. Never throws: by the time anything is
|
|
52
|
+
* deleted the new view is in the chat, and failing on this last, optional step
|
|
53
|
+
* would leave the chat's record behind the chat.
|
|
54
|
+
*/
|
|
55
|
+
export declare function deleteMessages(api: ScreenApi, chatId: ChatId, ids: readonly number[]): Promise<number[]>;
|
|
56
|
+
export declare function executePlan(api: ScreenApi, chatId: ChatId, plan: ViewPlan): Promise<ExecutedView>;
|
|
57
|
+
//# sourceMappingURL=execute.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"execute.d.ts","sourceRoot":"","sources":["../../../src/telegram/screens/execute.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,QAAQ,CAAC;AAGlC,OAAO,KAAK,EAAY,YAAY,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACpE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAEhD,kEAAkE;AAClE,MAAM,MAAM,SAAS,GAAG,IAAI,CAC1B,GAAG,EACD,aAAa,GACb,iBAAiB,GACjB,WAAW,GACX,WAAW,GACX,eAAe,GACf,cAAc,GACd,WAAW,GACX,iBAAiB,GACjB,oBAAoB,GACpB,kBAAkB,GAClB,wBAAwB,GACxB,eAAe,GACf,qBAAqB,CACxB,CAAC;AAEF,MAAM,MAAM,MAAM,GAAG,MAAM,CAAC;AAE5B,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,sEAAsE;IACtE,QAAQ,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;CACvC;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,KAAK,EAAE,SAAS,YAAY,EAAE,CAAC;IACxC,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAC;CAClC;AAED,8FAA8F;AAC9F,qBAAa,eAAgB,SAAQ,KAAK;IAEtC,QAAQ,CAAC,KAAK,EAAE,SAAS,YAAY,EAAE;aACrB,KAAK,EAAE,OAAO;IAFlC,YACW,KAAK,EAAE,SAAS,YAAY,EAAE,EACrB,KAAK,EAAE,OAAO,EAMjC;CACF;AAgBD,wBAAsB,YAAY,CAChC,GAAG,EAAE,SAAS,EACd,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,eAAe,GACvB,OAAO,CAAC,MAAM,CAAC,CA2BjB;AAyCD;;;;;GAKG;AACH,wBAAsB,cAAc,CAClC,GAAG,EAAE,SAAS,EACd,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,SAAS,MAAM,EAAE,GACrB,OAAO,CAAC,MAAM,EAAE,CAAC,CAanB;AAyBD,wBAAsB,WAAW,CAC/B,GAAG,EAAE,SAAS,EACd,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,QAAQ,GACb,OAAO,CAAC,YAAY,CAAC,CAgDvB"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Telegram HTML that cannot be assembled by accident.
|
|
3
|
+
*
|
|
4
|
+
* A screen interpolates values it did not write — a bot's username, an
|
|
5
|
+
* owner's title, a count — into markup it did. With plain strings every one of
|
|
6
|
+
* those is a place where a `<` in somebody's name breaks the message Telegram
|
|
7
|
+
* is asked to parse, or quietly changes what it shows. So markup is a type:
|
|
8
|
+
* the `html` tag escapes every interpolated string and inserts only another
|
|
9
|
+
* `TelegramHtml` as markup, and text the application already holds as Telegram
|
|
10
|
+
* HTML — an owner's stored greeting — enters through `html.raw`, the one place
|
|
11
|
+
* that says "trusted" out loud.
|
|
12
|
+
*/
|
|
13
|
+
/** Only `html`, `html.raw` and `html.join` make markup; this key stays in the module. */
|
|
14
|
+
declare const MINT: unique symbol;
|
|
15
|
+
/** Telegram HTML, parsed by Telegram with `parse_mode: 'HTML'`. Made by `html`. */
|
|
16
|
+
export declare class TelegramHtml {
|
|
17
|
+
#private;
|
|
18
|
+
constructor(mint: typeof MINT, markup: string);
|
|
19
|
+
/** The markup as Telegram receives it. */
|
|
20
|
+
toString(): string;
|
|
21
|
+
}
|
|
22
|
+
/** What a screen may put where text goes: plain text, or markup. */
|
|
23
|
+
export type TelegramText = string | TelegramHtml;
|
|
24
|
+
/** A value `html` accepts between its literal parts. */
|
|
25
|
+
export type HtmlValue = string | number | bigint | TelegramHtml | false | null | undefined;
|
|
26
|
+
export interface HtmlTag {
|
|
27
|
+
/** Markup with every interpolated value escaped; a nested `html` stays markup. */
|
|
28
|
+
(literals: TemplateStringsArray, ...values: readonly HtmlValue[]): TelegramHtml;
|
|
29
|
+
/** Markup the application already holds, trusted as it is. */
|
|
30
|
+
raw(markup: string): TelegramHtml;
|
|
31
|
+
/** Several fragments as one, separated by `separator` (escaped unless it is markup). */
|
|
32
|
+
join(parts: readonly HtmlValue[], separator?: string | TelegramHtml): TelegramHtml;
|
|
33
|
+
}
|
|
34
|
+
export declare const html: HtmlTag;
|
|
35
|
+
export {};
|
|
36
|
+
//# sourceMappingURL=html.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"html.d.ts","sourceRoot":"","sources":["../../../src/telegram/screens/html.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,yFAAyF;AACzF,QAAA,MAAM,IAAI,EAAE,OAAO,MAA+B,CAAC;AAEnD,mFAAmF;AACnF,qBAAa,YAAY;;IAGvB,YAAY,IAAI,EAAE,OAAO,IAAI,EAAE,MAAM,EAAE,MAAM,EAO5C;IAED,0CAA0C;IAC1C,QAAQ,IAAI,MAAM,CAEjB;CACF;AAED,oEAAoE;AACpE,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,YAAY,CAAC;AAEjD,wDAAwD;AACxD,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,YAAY,GAAG,KAAK,GAAG,IAAI,GAAG,SAAS,CAAC;AAQ3F,MAAM,WAAW,OAAO;IACtB,kFAAkF;IAClF,CAAC,QAAQ,EAAE,oBAAoB,EAAE,GAAG,MAAM,EAAE,SAAS,SAAS,EAAE,GAAG,YAAY,CAAC;IAChF,8DAA8D;IAC9D,GAAG,CAAC,MAAM,EAAE,MAAM,GAAG,YAAY,CAAC;IAClC,wFAAwF;IACxF,IAAI,CAAC,KAAK,EAAE,SAAS,SAAS,EAAE,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,YAAY,GAAG,YAAY,CAAC;CACpF;AAUD,eAAO,MAAM,IAAI,EAAE,OAUjB,CAAC"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What a load, an action or an input answers with.
|
|
3
|
+
*
|
|
4
|
+
* One value, built by chaining, read once by the runtime: where the chat goes
|
|
5
|
+
* next and what it hears on the way. `void` from a handler is `stay()` — show
|
|
6
|
+
* this screen again with fresh data — so a handler that only changes data
|
|
7
|
+
* returns nothing and the screen follows.
|
|
8
|
+
*
|
|
9
|
+
* - `toast` answers the press itself: the small notification Telegram shows
|
|
10
|
+
* over the chat. One per press; the last one wins.
|
|
11
|
+
* - `notice` without a lifetime is a receipt that stays in the chat: it is
|
|
12
|
+
* posted and the screen moves below it, so the conversation reads in order.
|
|
13
|
+
* - `notice` with `expiresInMs` is a remark below the screen that removes
|
|
14
|
+
* itself; the screen stays where it is.
|
|
15
|
+
*/
|
|
16
|
+
import type { ActionValue } from './callback-codec.js';
|
|
17
|
+
import type { TelegramText } from './html.js';
|
|
18
|
+
import type { AnyTelegramScreen, ScreenLinkArgs } from './screen-types.js';
|
|
19
|
+
export type ScreenNavigation = {
|
|
20
|
+
readonly type: 'stay';
|
|
21
|
+
} | {
|
|
22
|
+
readonly type: 'back';
|
|
23
|
+
} | {
|
|
24
|
+
readonly type: 'go';
|
|
25
|
+
readonly screen: AnyTelegramScreen;
|
|
26
|
+
readonly params: Readonly<Record<string, ActionValue>>;
|
|
27
|
+
};
|
|
28
|
+
export interface ScreenToast {
|
|
29
|
+
readonly text: string;
|
|
30
|
+
/** Show it as an alert the user must dismiss, not a passing notification. */
|
|
31
|
+
readonly alert: boolean;
|
|
32
|
+
}
|
|
33
|
+
export interface ScreenNotice {
|
|
34
|
+
readonly content: TelegramText;
|
|
35
|
+
/** Removed after this many milliseconds; absent, it stays. */
|
|
36
|
+
readonly expiresInMs?: number;
|
|
37
|
+
}
|
|
38
|
+
export interface NoticeOptions {
|
|
39
|
+
/** Removed after this many milliseconds, at most 2³¹ − 1 (a timer's limit); absent, it stays. */
|
|
40
|
+
readonly expiresInMs?: number;
|
|
41
|
+
}
|
|
42
|
+
export declare class ScreenOutcome {
|
|
43
|
+
#private;
|
|
44
|
+
readonly navigation: ScreenNavigation;
|
|
45
|
+
/** An outcome, told apart from data by its private brand rather than its shape. */
|
|
46
|
+
static is(value: unknown): value is ScreenOutcome;
|
|
47
|
+
readonly toastSpec: ScreenToast | undefined;
|
|
48
|
+
readonly notices: readonly ScreenNotice[];
|
|
49
|
+
constructor(navigation?: ScreenNavigation, toast?: ScreenToast | undefined, notices?: readonly ScreenNotice[]);
|
|
50
|
+
/** Show the current screen again, with fresh data. */
|
|
51
|
+
stay(): ScreenOutcome;
|
|
52
|
+
/** Show another screen. */
|
|
53
|
+
go<TScreen extends AnyTelegramScreen>(screen: TScreen, ...params: ScreenLinkArgs<TScreen>): ScreenOutcome;
|
|
54
|
+
/** Show the parent screen. */
|
|
55
|
+
back(): ScreenOutcome;
|
|
56
|
+
/** Answer the press with a notification (or an alert). */
|
|
57
|
+
toast(text: string, options?: {
|
|
58
|
+
readonly alert?: boolean;
|
|
59
|
+
}): ScreenOutcome;
|
|
60
|
+
/** Post a message: a receipt that stays, or a remark that expires. */
|
|
61
|
+
notice(content: TelegramText, options?: NoticeOptions): ScreenOutcome;
|
|
62
|
+
}
|
|
63
|
+
/** The builders every handler context carries; each starts a fresh outcome. */
|
|
64
|
+
export interface ScreenOutcomeBuilders {
|
|
65
|
+
stay(): ScreenOutcome;
|
|
66
|
+
go<TScreen extends AnyTelegramScreen>(screen: TScreen, ...params: ScreenLinkArgs<TScreen>): ScreenOutcome;
|
|
67
|
+
back(): ScreenOutcome;
|
|
68
|
+
toast(text: string, options?: {
|
|
69
|
+
readonly alert?: boolean;
|
|
70
|
+
}): ScreenOutcome;
|
|
71
|
+
notice(content: TelegramText, options?: NoticeOptions): ScreenOutcome;
|
|
72
|
+
}
|
|
73
|
+
export declare function outcomeBuilders(): ScreenOutcomeBuilders;
|
|
74
|
+
//# sourceMappingURL=outcome.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"outcome.d.ts","sourceRoot":"","sources":["../../../src/telegram/screens/outcome.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAC3C,OAAO,KAAK,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAExE,MAAM,MAAM,gBAAgB,GACxB;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACzB;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACzB;IACE,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;IACpB,QAAQ,CAAC,MAAM,EAAE,iBAAiB,CAAC;IACnC,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC;CACxD,CAAC;AAEN,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,6EAA6E;IAC7E,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,OAAO,EAAE,YAAY,CAAC;IAC/B,8DAA8D;IAC9D,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;CAC/B;AAED,MAAM,WAAW,aAAa;IAC5B,iGAAiG;IACjG,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;CAC/B;AAOD,qBAAa,aAAa;;IAGxB,QAAQ,CAAC,UAAU,EAAE,gBAAgB,CAAC;IAEtC,mFAAmF;IACnF,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,aAAa,CAEhD;IACD,QAAQ,CAAC,SAAS,EAAE,WAAW,GAAG,SAAS,CAAC;IAC5C,QAAQ,CAAC,OAAO,EAAE,SAAS,YAAY,EAAE,CAAC;IAE1C,YACE,UAAU,GAAE,gBAAmC,EAC/C,KAAK,GAAE,WAAW,GAAG,SAAqB,EAC1C,OAAO,GAAE,SAAS,YAAY,EAAO,EAKtC;IAED,sDAAsD;IACtD,IAAI,IAAI,aAAa,CAEpB;IAED,2BAA2B;IAC3B,EAAE,CAAC,OAAO,SAAS,iBAAiB,EAClC,MAAM,EAAE,OAAO,EACf,GAAG,MAAM,EAAE,cAAc,CAAC,OAAO,CAAC,GACjC,aAAa,CAOf;IAED,8BAA8B;IAC9B,IAAI,IAAI,aAAa,CAEpB;IAED,0DAA0D;IAC1D,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE;QAAE,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAA;KAAO,GAAG,aAAa,CAa7E;IAED,sEAAsE;IACtE,MAAM,CAAC,OAAO,EAAE,YAAY,EAAE,OAAO,GAAE,aAAkB,GAAG,aAAa,CAaxE;CACF;AAED,+EAA+E;AAC/E,MAAM,WAAW,qBAAqB;IACpC,IAAI,IAAI,aAAa,CAAC;IACtB,EAAE,CAAC,OAAO,SAAS,iBAAiB,EAClC,MAAM,EAAE,OAAO,EACf,GAAG,MAAM,EAAE,cAAc,CAAC,OAAO,CAAC,GACjC,aAAa,CAAC;IACjB,IAAI,IAAI,aAAa,CAAC;IACtB,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,aAAa,CAAC;IAC3E,MAAM,CAAC,OAAO,EAAE,YAAY,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,aAAa,CAAC;CACvE;AAED,wBAAgB,eAAe,IAAI,qBAAqB,CASvD"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A screen's address: a path whose `:name` segments are its params.
|
|
3
|
+
*
|
|
4
|
+
* The path is the whole navigation model. A screen's parent is the nearest
|
|
5
|
+
* declared screen whose path is a prefix of its own, segment by segment, so
|
|
6
|
+
* "back" is a fact about the tree rather than a history someone has to keep —
|
|
7
|
+
* nothing to lose on a restart, nothing to corrupt when a press arrives from an
|
|
8
|
+
* older message.
|
|
9
|
+
*/
|
|
10
|
+
import { type PathParams } from '../../internal/route-pattern.js';
|
|
11
|
+
/** The params a screen path names, as strings (`/bot/:botId` → `{ botId: string }`). */
|
|
12
|
+
export type ScreenPathParams<TPath extends string> = PathParams<TPath>;
|
|
13
|
+
export interface ScreenPath {
|
|
14
|
+
readonly path: string;
|
|
15
|
+
readonly segments: readonly string[];
|
|
16
|
+
/** Param names in path order — the order a button carries them in. */
|
|
17
|
+
readonly params: readonly string[];
|
|
18
|
+
}
|
|
19
|
+
export declare function parseScreenPath(path: string): ScreenPath;
|
|
20
|
+
/** `parent` is a strict prefix of `child`, segment by segment. */
|
|
21
|
+
export declare function isAncestorPath(parent: ScreenPath, child: ScreenPath): boolean;
|
|
22
|
+
/**
|
|
23
|
+
* A short id derived from the path: stable across releases while the path is,
|
|
24
|
+
* and short enough to leave a button room for its params.
|
|
25
|
+
*/
|
|
26
|
+
export declare function derivedScreenId(path: string): string;
|
|
27
|
+
/** The concrete chat-facing path, for logs and transitions. */
|
|
28
|
+
export declare function formatScreenPath(path: ScreenPath, params: Readonly<Record<string, string>>): string;
|
|
29
|
+
//# sourceMappingURL=path.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"path.d.ts","sourceRoot":"","sources":["../../../src/telegram/screens/path.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,KAAK,UAAU,EAAqB,MAAM,8BAA8B,CAAC;AAGlF,wFAAwF;AACxF,MAAM,MAAM,gBAAgB,CAAC,KAAK,SAAS,MAAM,IAAI,UAAU,CAAC,KAAK,CAAC,CAAC;AAEvE,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,sEAAsE;IACtE,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;CACpC;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,CAgBxD;AAED,kEAAkE;AAClE,wBAAgB,cAAc,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,GAAG,OAAO,CAG7E;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEpD;AAED,+DAA+D;AAC/D,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,UAAU,EAChB,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GACvC,MAAM,CAMR"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* From what the chat shows to what it should show, in the fewest Bot API calls
|
|
3
|
+
* that keep the chat in order.
|
|
4
|
+
*
|
|
5
|
+
* Telegram orders messages by when they were sent, and a sent message cannot
|
|
6
|
+
* move. So a message is kept (and edited in place) only while the new view's
|
|
7
|
+
* order allows it: walking the new view top to bottom, a message whose key the
|
|
8
|
+
* chat already shows — below the last one kept, and editable into the new
|
|
9
|
+
* shape — is kept. The first message that cannot be kept is sent, and so is
|
|
10
|
+
* every message after it, because anything sent lands at the bottom; whatever
|
|
11
|
+
* the chat showed and was not kept is deleted.
|
|
12
|
+
*
|
|
13
|
+
* Editable means what the Bot API can do in place: text into text and rich
|
|
14
|
+
* into rich (`editMessageText`), text or rich into media and media into media
|
|
15
|
+
* of any kind (`editMessageMedia`). Media into text or rich, and text into rich
|
|
16
|
+
* or back, is a new message.
|
|
17
|
+
*
|
|
18
|
+
* The plan is data. Carrying it out — and recovering when Telegram refuses an
|
|
19
|
+
* edit it allowed a moment ago — is `execute`'s.
|
|
20
|
+
*/
|
|
21
|
+
import type { MessageFingerprint, OutgoingMessage, RenderedKind } from './render.js';
|
|
22
|
+
/** A message the chat shows, as the chat's state remembers it. */
|
|
23
|
+
export interface ShownMessage {
|
|
24
|
+
readonly key: string;
|
|
25
|
+
readonly id: number;
|
|
26
|
+
readonly kind: RenderedKind;
|
|
27
|
+
/** `null` for a message whose content is not known — one adopted from a press. */
|
|
28
|
+
readonly fingerprint: MessageFingerprint | null;
|
|
29
|
+
}
|
|
30
|
+
export interface EditParts {
|
|
31
|
+
readonly content: boolean;
|
|
32
|
+
readonly media: boolean;
|
|
33
|
+
readonly markup: boolean;
|
|
34
|
+
}
|
|
35
|
+
export type PlanStep = {
|
|
36
|
+
readonly op: 'keep';
|
|
37
|
+
readonly id: number;
|
|
38
|
+
readonly from: ShownMessage;
|
|
39
|
+
readonly message: OutgoingMessage;
|
|
40
|
+
} | {
|
|
41
|
+
readonly op: 'edit';
|
|
42
|
+
readonly id: number;
|
|
43
|
+
readonly from: ShownMessage;
|
|
44
|
+
readonly message: OutgoingMessage;
|
|
45
|
+
readonly parts: EditParts;
|
|
46
|
+
} | {
|
|
47
|
+
readonly op: 'send';
|
|
48
|
+
readonly message: OutgoingMessage;
|
|
49
|
+
};
|
|
50
|
+
export interface ViewPlan {
|
|
51
|
+
/** The new view, top to bottom: each message kept, edited or sent. */
|
|
52
|
+
readonly steps: readonly PlanStep[];
|
|
53
|
+
/** Messages the chat showed that the new view does not keep. */
|
|
54
|
+
readonly deletions: readonly number[];
|
|
55
|
+
}
|
|
56
|
+
export declare function isEditable(from: RenderedKind, to: RenderedKind): boolean;
|
|
57
|
+
export interface PlanOptions {
|
|
58
|
+
/**
|
|
59
|
+
* The message a press came from, when it is not part of the view the chat
|
|
60
|
+
* state knows. It becomes the first message of the new view if it can.
|
|
61
|
+
*/
|
|
62
|
+
readonly adopt?: ShownMessage;
|
|
63
|
+
/** Send the whole view anew below everything, deleting what was shown. */
|
|
64
|
+
readonly fresh?: boolean;
|
|
65
|
+
}
|
|
66
|
+
export declare function planView(shown: readonly ShownMessage[], next: readonly OutgoingMessage[], options?: PlanOptions): ViewPlan;
|
|
67
|
+
//# sourceMappingURL=reconcile.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reconcile.d.ts","sourceRoot":"","sources":["../../../src/telegram/screens/reconcile.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,OAAO,KAAK,EAAE,kBAAkB,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAElF,kEAAkE;AAClE,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAC5B,kFAAkF;IAClF,QAAQ,CAAC,WAAW,EAAE,kBAAkB,GAAG,IAAI,CAAC;CACjD;AAED,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,MAAM,QAAQ,GAChB;IACE,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,eAAe,CAAC;CACnC,GACD;IACE,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,eAAe,CAAC;IAClC,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC;CAC3B,GACD;IAAE,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,eAAe,CAAA;CAAE,CAAC;AAE/D,MAAM,WAAW,QAAQ;IACvB,sEAAsE;IACtE,QAAQ,CAAC,KAAK,EAAE,SAAS,QAAQ,EAAE,CAAC;IACpC,gEAAgE;IAChE,QAAQ,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;CACvC;AAID,wBAAgB,UAAU,CAAC,IAAI,EAAE,YAAY,EAAE,EAAE,EAAE,YAAY,GAAG,OAAO,CAExE;AAgBD,MAAM,WAAW,WAAW;IAC1B;;;OAGG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,YAAY,CAAC;IAC9B,0EAA0E;IAC1E,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,wBAAgB,QAAQ,CACtB,KAAK,EAAE,SAAS,YAAY,EAAE,EAC9B,IAAI,EAAE,SAAS,eAAe,EAAE,EAChC,OAAO,GAAE,WAAgB,GACxB,QAAQ,CAiCV"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The screens a bot declared, by id and by object, with the tree between them.
|
|
3
|
+
*
|
|
4
|
+
* Checked once, when the bot is composed: two screens with one path or one id
|
|
5
|
+
* would make a button mean two things, and a screen whose id collides with
|
|
6
|
+
* another's derived id would do so silently on the next release.
|
|
7
|
+
*/
|
|
8
|
+
import type { Context } from 'grammy';
|
|
9
|
+
import type { ButtonResolver } from './render.js';
|
|
10
|
+
import type { AnyTelegramScreen, ScreenActions, ScreenDefinition, ScreenParams, TelegramScreen } from './screen-types.js';
|
|
11
|
+
export type DeclaredScreen<C extends Context> = TelegramScreen<C, ScreenParams, unknown, ScreenActions>;
|
|
12
|
+
export interface RegisteredScreen<C extends Context> {
|
|
13
|
+
readonly screen: DeclaredScreen<C>;
|
|
14
|
+
readonly definition: ScreenDefinition<C>;
|
|
15
|
+
readonly parent: RegisteredScreen<C> | undefined;
|
|
16
|
+
}
|
|
17
|
+
export interface ScreenRegistry<C extends Context> {
|
|
18
|
+
byId(id: string): RegisteredScreen<C> | undefined;
|
|
19
|
+
entryOf(screen: AnyTelegramScreen): RegisteredScreen<C>;
|
|
20
|
+
resolverFor(entry: RegisteredScreen<C>): ButtonResolver;
|
|
21
|
+
}
|
|
22
|
+
export declare function createScreenRegistry<C extends Context>(screens: readonly DeclaredScreen<C>[]): ScreenRegistry<C>;
|
|
23
|
+
//# sourceMappingURL=registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../../src/telegram/screens/registry.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAEtC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAC/C,OAAO,KAAK,EACV,iBAAiB,EACjB,aAAa,EACb,gBAAgB,EAChB,YAAY,EACZ,cAAc,EACf,MAAM,gBAAgB,CAAC;AAExB,MAAM,MAAM,cAAc,CAAC,CAAC,SAAS,OAAO,IAAI,cAAc,CAC5D,CAAC,EACD,YAAY,EACZ,OAAO,EACP,aAAa,CACd,CAAC;AAEF,MAAM,WAAW,gBAAgB,CAAC,CAAC,SAAS,OAAO;IACjD,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC,CAAC,CAAC;IACnC,QAAQ,CAAC,UAAU,EAAE,gBAAgB,CAAC,CAAC,CAAC,CAAC;IACzC,QAAQ,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC;CAClD;AAED,MAAM,WAAW,cAAc,CAAC,CAAC,SAAS,OAAO;IAC/C,IAAI,CAAC,EAAE,EAAE,MAAM,GAAG,gBAAgB,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC;IAClD,OAAO,CAAC,MAAM,EAAE,iBAAiB,GAAG,gBAAgB,CAAC,CAAC,CAAC,CAAC;IACxD,WAAW,CAAC,KAAK,EAAE,gBAAgB,CAAC,CAAC,CAAC,GAAG,cAAc,CAAC;CACzD;AAED,wBAAgB,oBAAoB,CAAC,CAAC,SAAS,OAAO,EACpD,OAAO,EAAE,SAAS,cAAc,CAAC,CAAC,CAAC,EAAE,GACpC,cAAc,CAAC,CAAC,CAAC,CAkFnB"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A view as Telegram will receive it: payloads, `callback_data` and the
|
|
3
|
+
* fingerprints the next render is compared against.
|
|
4
|
+
*
|
|
5
|
+
* Buttons are resolved here, against the registered screens: a link becomes
|
|
6
|
+
* its target's id and params, `back` the parent of the screen being shown, an
|
|
7
|
+
* action the screen's own id, params and input. An address longer than
|
|
8
|
+
* Telegram's 64 bytes is kept in the chat's state under a short token and the
|
|
9
|
+
* button carries the token — so a long param never makes a screen unrenderable.
|
|
10
|
+
*/
|
|
11
|
+
import type { InlineKeyboardButton, InlineKeyboardMarkup, InputRichMessageWithoutUpload } from 'grammy/types';
|
|
12
|
+
import { type TelegramText } from './html.js';
|
|
13
|
+
import type { AnyTelegramScreen, ScreenParams } from './screen-types.js';
|
|
14
|
+
import { ScreenButton, type ScreenMediaKind, type ScreenViewResult } from './view.js';
|
|
15
|
+
export type RenderedKind = 'text' | 'rich' | ScreenMediaKind;
|
|
16
|
+
/** The parts of a message that are edited separately, as digests. */
|
|
17
|
+
export interface MessageFingerprint {
|
|
18
|
+
readonly content: string;
|
|
19
|
+
readonly media: string;
|
|
20
|
+
readonly markup: string;
|
|
21
|
+
}
|
|
22
|
+
export interface OutgoingMessage {
|
|
23
|
+
readonly key: string;
|
|
24
|
+
readonly kind: RenderedKind;
|
|
25
|
+
/**
|
|
26
|
+
* Telegram HTML: the text of a text message, the caption of a media one.
|
|
27
|
+
* Always sent with `parse_mode: 'HTML'`, plain strings escaped — so no
|
|
28
|
+
* `parse_mode` default an application sets elsewhere can reinterpret it.
|
|
29
|
+
*/
|
|
30
|
+
readonly html: string | undefined;
|
|
31
|
+
readonly rich: InputRichMessageWithoutUpload | undefined;
|
|
32
|
+
readonly linkPreview: boolean | undefined;
|
|
33
|
+
readonly media: string | undefined;
|
|
34
|
+
readonly markup: InlineKeyboardMarkup | undefined;
|
|
35
|
+
readonly fingerprint: MessageFingerprint;
|
|
36
|
+
}
|
|
37
|
+
/** Where a screen button leads, resolved against the registered screens. */
|
|
38
|
+
export interface ButtonResolver {
|
|
39
|
+
/** The id and param order of a registered screen; throws for one not registered. */
|
|
40
|
+
addressOf(screen: AnyTelegramScreen): {
|
|
41
|
+
readonly id: string;
|
|
42
|
+
readonly params: readonly string[];
|
|
43
|
+
};
|
|
44
|
+
/** The parent of the screen being rendered, or `undefined` at the root. */
|
|
45
|
+
readonly parent: {
|
|
46
|
+
readonly id: string;
|
|
47
|
+
readonly params: readonly string[];
|
|
48
|
+
} | undefined;
|
|
49
|
+
readonly path: string;
|
|
50
|
+
}
|
|
51
|
+
export interface RenderContext {
|
|
52
|
+
readonly prefix: string;
|
|
53
|
+
readonly resolver: ButtonResolver;
|
|
54
|
+
readonly params: ScreenParams;
|
|
55
|
+
}
|
|
56
|
+
export interface RenderedView {
|
|
57
|
+
readonly messages: readonly OutgoingMessage[];
|
|
58
|
+
/** Addresses too long for a button, by token. */
|
|
59
|
+
readonly tokens: Readonly<Record<string, string>>;
|
|
60
|
+
}
|
|
61
|
+
/** Text as Telegram HTML: markup as it is, a plain string escaped. */
|
|
62
|
+
export declare function htmlOf(text: TelegramText): string;
|
|
63
|
+
export declare function renderView(view: ScreenViewResult, context: RenderContext): RenderedView;
|
|
64
|
+
/**
|
|
65
|
+
* A link for a message the screens do not own — a notification. It carries
|
|
66
|
+
* its whole address, because no view record will hold a token for it, and it
|
|
67
|
+
* opens its screen below rather than changing the message it sits on.
|
|
68
|
+
*/
|
|
69
|
+
export declare function renderDetachedButton(button: ScreenButton, prefix: string, addressOf: ButtonResolver['addressOf']): InlineKeyboardButton.CallbackButton;
|
|
70
|
+
//# sourceMappingURL=render.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../../src/telegram/screens/render.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,KAAK,EACV,oBAAoB,EACpB,oBAAoB,EACpB,6BAA6B,EAC9B,MAAM,cAAc,CAAC;AAUtB,OAAO,EAAgB,KAAK,YAAY,EAAE,MAAM,QAAQ,CAAC;AACzD,OAAO,KAAK,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAEtE,OAAO,EAIL,YAAY,EACZ,KAAK,eAAe,EACpB,KAAK,gBAAgB,EAEtB,MAAM,QAAQ,CAAC;AAEhB,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,MAAM,GAAG,eAAe,CAAC;AAE7D,qEAAqE;AACrE,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAC5B;;;;OAIG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,QAAQ,CAAC,IAAI,EAAE,6BAA6B,GAAG,SAAS,CAAC;IACzD,QAAQ,CAAC,WAAW,EAAE,OAAO,GAAG,SAAS,CAAC;IAC1C,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,QAAQ,CAAC,MAAM,EAAE,oBAAoB,GAAG,SAAS,CAAC;IAClD,QAAQ,CAAC,WAAW,EAAE,kBAAkB,CAAC;CAC1C;AAED,4EAA4E;AAC5E,MAAM,WAAW,cAAc;IAC7B,oFAAoF;IACpF,SAAS,CAAC,MAAM,EAAE,iBAAiB,GAAG;QACpC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;QACpB,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;KACpC,CAAC;IACF,2EAA2E;IAC3E,QAAQ,CAAC,MAAM,EAAE;QAAE,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAA;KAAE,GAAG,SAAS,CAAC;IACzF,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAC;IAClC,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC;CAC/B;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,QAAQ,EAAE,SAAS,eAAe,EAAE,CAAC;IAC9C,iDAAiD;IACjD,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CACnD;AAED,sEAAsE;AACtE,wBAAgB,MAAM,CAAC,IAAI,EAAE,YAAY,GAAG,MAAM,CAEjD;AAoKD,wBAAgB,UAAU,CAAC,IAAI,EAAE,gBAAgB,EAAE,OAAO,EAAE,aAAa,GAAG,YAAY,CA8BvF;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,cAAc,CAAC,WAAW,CAAC,GACrC,oBAAoB,CAAC,cAAc,CAmBrC"}
|