teledzik 1.0.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/LICENSE +22 -0
- package/README.md +1126 -0
- package/filters.d.ts +1 -0
- package/filters.js +1 -0
- package/format.d.ts +1 -0
- package/format.js +1 -0
- package/future.d.ts +1 -0
- package/future.js +1 -0
- package/lib/button.js +101 -0
- package/lib/cli.mjs +105 -0
- package/lib/composer.js +581 -0
- package/lib/context.js +1300 -0
- package/lib/core/helpers/ai-stream.js +69 -0
- package/lib/core/helpers/args.js +58 -0
- package/lib/core/helpers/check.js +56 -0
- package/lib/core/helpers/compact.js +17 -0
- package/lib/core/helpers/deunionize.js +13 -0
- package/lib/core/helpers/formatting.js +89 -0
- package/lib/core/helpers/input-box.js +87 -0
- package/lib/core/helpers/rich-sanitizer.js +31 -0
- package/lib/core/helpers/smart-queue.js +70 -0
- package/lib/core/helpers/util.js +50 -0
- package/lib/core/network/client.js +318 -0
- package/lib/core/network/error.js +21 -0
- package/lib/core/network/multipart-stream.js +61 -0
- package/lib/core/network/polling.js +86 -0
- package/lib/core/network/webhook.js +54 -0
- package/lib/core/types/rich-message.js +287 -0
- package/lib/core/types/typegram.js +18 -0
- package/lib/filters.js +69 -0
- package/lib/format.js +38 -0
- package/lib/future.js +166 -0
- package/lib/index.js +61 -0
- package/lib/input.js +61 -0
- package/lib/markup.js +111 -0
- package/lib/middleware.js +2 -0
- package/lib/paginated.js +76 -0
- package/lib/reactions.js +81 -0
- package/lib/router.js +45 -0
- package/lib/scenes/base.js +39 -0
- package/lib/scenes/context.js +99 -0
- package/lib/scenes/form-scene.js +23 -0
- package/lib/scenes/index.js +21 -0
- package/lib/scenes/stage.js +49 -0
- package/lib/scenes/wizard/context.js +30 -0
- package/lib/scenes/wizard/index.js +45 -0
- package/lib/scenes.js +17 -0
- package/lib/session.js +163 -0
- package/lib/telegraf.js +274 -0
- package/lib/telegram-types.js +6 -0
- package/lib/telegram.js +1286 -0
- package/lib/types.js +2 -0
- package/lib/utils.js +5 -0
- package/markup.d.ts +1 -0
- package/markup.js +1 -0
- package/package.json +141 -0
- package/scenes.d.ts +1 -0
- package/scenes.js +1 -0
- package/session.d.ts +1 -0
- package/session.js +1 -0
- package/src/button.ts +182 -0
- package/src/composer.ts +1008 -0
- package/src/context.ts +1778 -0
- package/src/core/helpers/ai-stream.ts +96 -0
- package/src/core/helpers/args.ts +63 -0
- package/src/core/helpers/check.ts +71 -0
- package/src/core/helpers/compact.ts +18 -0
- package/src/core/helpers/deunionize.ts +26 -0
- package/src/core/helpers/formatting.ts +119 -0
- package/src/core/helpers/input-box.ts +86 -0
- package/src/core/helpers/rich-sanitizer.ts +36 -0
- package/src/core/helpers/smart-queue.ts +89 -0
- package/src/core/helpers/util.ts +96 -0
- package/src/core/network/client.ts +396 -0
- package/src/core/network/error.ts +29 -0
- package/src/core/network/multipart-stream.ts +45 -0
- package/src/core/network/polling.ts +94 -0
- package/src/core/network/webhook.ts +58 -0
- package/src/core/types/rich-message.ts +375 -0
- package/src/core/types/typegram.ts +44 -0
- package/src/filters.js +69 -0
- package/src/filters.ts +109 -0
- package/src/format.js +38 -0
- package/src/format.ts +110 -0
- package/src/future.js +147 -0
- package/src/future.ts +231 -0
- package/src/index.ts +27 -0
- package/src/input.ts +59 -0
- package/src/markup.js +93 -0
- package/src/markup.ts +142 -0
- package/src/middleware.ts +24 -0
- package/src/paginated.ts +75 -0
- package/src/reactions.ts +118 -0
- package/src/router.ts +55 -0
- package/src/scenes/base.ts +52 -0
- package/src/scenes/context.ts +136 -0
- package/src/scenes/form-scene.ts +34 -0
- package/src/scenes/index.ts +21 -0
- package/src/scenes/stage.ts +71 -0
- package/src/scenes/wizard/context.ts +58 -0
- package/src/scenes/wizard/index.ts +63 -0
- package/src/scenes.js +17 -0
- package/src/scenes.ts +1 -0
- package/src/session.js +175 -0
- package/src/session.ts +204 -0
- package/src/telegraf.ts +385 -0
- package/src/telegram-types.ts +256 -0
- package/src/telegram.ts +1700 -0
- package/src/types.js +2 -0
- package/src/types.ts +2 -0
- package/src/utils.js +5 -0
- package/src/utils.ts +1 -0
- package/types.d.ts +1 -0
- package/types.js +1 -0
- package/typings/button.d.ts +35 -0
- package/typings/button.d.ts.map +1 -0
- package/typings/composer.d.ts +226 -0
- package/typings/composer.d.ts.map +1 -0
- package/typings/context.d.ts +711 -0
- package/typings/context.d.ts.map +1 -0
- package/typings/core/helpers/ai-stream.d.ts +33 -0
- package/typings/core/helpers/args.d.ts +10 -0
- package/typings/core/helpers/args.d.ts.map +1 -0
- package/typings/core/helpers/check.d.ts +55 -0
- package/typings/core/helpers/check.d.ts.map +1 -0
- package/typings/core/helpers/compact.d.ts +3 -0
- package/typings/core/helpers/compact.d.ts.map +1 -0
- package/typings/core/helpers/deunionize.d.ts +17 -0
- package/typings/core/helpers/deunionize.d.ts.map +1 -0
- package/typings/core/helpers/formatting.d.ts +29 -0
- package/typings/core/helpers/formatting.d.ts.map +1 -0
- package/typings/core/helpers/input-box.d.ts +32 -0
- package/typings/core/helpers/rich-sanitizer.d.ts +5 -0
- package/typings/core/helpers/smart-queue.d.ts +18 -0
- package/typings/core/helpers/util.d.ts +26 -0
- package/typings/core/helpers/util.d.ts.map +1 -0
- package/typings/core/network/client.d.ts +54 -0
- package/typings/core/network/client.d.ts.map +1 -0
- package/typings/core/network/error.d.ts +15 -0
- package/typings/core/network/error.d.ts.map +1 -0
- package/typings/core/network/multipart-stream.d.ts +19 -0
- package/typings/core/network/multipart-stream.d.ts.map +1 -0
- package/typings/core/network/polling.d.ts +15 -0
- package/typings/core/network/polling.d.ts.map +1 -0
- package/typings/core/network/webhook.d.ts +6 -0
- package/typings/core/network/webhook.d.ts.map +1 -0
- package/typings/core/types/rich-message.d.ts +143 -0
- package/typings/core/types/rich-message.d.ts.map +1 -0
- package/typings/core/types/typegram.d.ts +36 -0
- package/typings/core/types/typegram.d.ts.map +1 -0
- package/typings/filters.d.ts +17 -0
- package/typings/filters.d.ts.map +1 -0
- package/typings/format.d.ts +21 -0
- package/typings/format.d.ts.map +1 -0
- package/typings/future.d.ts +11 -0
- package/typings/future.d.ts.map +1 -0
- package/typings/index.d.ts +21 -0
- package/typings/index.d.ts.map +1 -0
- package/typings/input.d.ts +58 -0
- package/typings/input.d.ts.map +1 -0
- package/typings/markup.d.ts +26 -0
- package/typings/markup.d.ts.map +1 -0
- package/typings/middleware.d.ts +7 -0
- package/typings/middleware.d.ts.map +1 -0
- package/typings/paginated.d.ts +20 -0
- package/typings/reactions.d.ts +31 -0
- package/typings/reactions.d.ts.map +1 -0
- package/typings/router.d.ts +20 -0
- package/typings/router.d.ts.map +1 -0
- package/typings/scenes/base.d.ts +21 -0
- package/typings/scenes/base.d.ts.map +1 -0
- package/typings/scenes/context.d.ts +35 -0
- package/typings/scenes/context.d.ts.map +1 -0
- package/typings/scenes/form-scene.d.ts +17 -0
- package/typings/scenes/index.d.ts +10 -0
- package/typings/scenes/index.d.ts.map +1 -0
- package/typings/scenes/stage.d.ts +23 -0
- package/typings/scenes/stage.d.ts.map +1 -0
- package/typings/scenes/wizard/context.d.ts +28 -0
- package/typings/scenes/wizard/context.d.ts.map +1 -0
- package/typings/scenes/wizard/index.d.ts +15 -0
- package/typings/scenes/wizard/index.d.ts.map +1 -0
- package/typings/scenes.d.ts +1 -0
- package/typings/scenes.d.ts.map +1 -0
- package/typings/session.d.ts +54 -0
- package/typings/session.d.ts.map +1 -0
- package/typings/telegraf.d.ts +118 -0
- package/typings/telegraf.d.ts.map +1 -0
- package/typings/telegram-types.d.ts +140 -0
- package/typings/telegram-types.d.ts.map +1 -0
- package/typings/telegram.d.ts +697 -0
- package/typings/telegram.d.ts.map +1 -0
- package/typings/types.d.ts +2 -0
- package/typings/types.d.ts.map +1 -0
- package/typings/utils.d.ts +1 -0
- package/typings/utils.d.ts.map +1 -0
- package/utils.d.ts +1 -0
- package/utils.js +1 -0
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AIStreamAdapter = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* AI Live Stream Adapter for Telegram Bots.
|
|
6
|
+
* Throttles live token stream edits to prevent Telegram rate limit bans.
|
|
7
|
+
*/
|
|
8
|
+
class AIStreamAdapter {
|
|
9
|
+
constructor(ctx, options = {}) {
|
|
10
|
+
this.buffer = '';
|
|
11
|
+
this.lastUpdate = 0;
|
|
12
|
+
this.timer = null;
|
|
13
|
+
this.ctx = ctx;
|
|
14
|
+
this.options = options;
|
|
15
|
+
this.minInterval = options.minUpdateIntervalMs ?? 800;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Append new token chunk from LLM stream.
|
|
19
|
+
*/
|
|
20
|
+
async push(chunk) {
|
|
21
|
+
this.buffer += chunk;
|
|
22
|
+
await this.scheduleUpdate();
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Finalize the stream and send the full final content.
|
|
26
|
+
*/
|
|
27
|
+
async end(finalContent) {
|
|
28
|
+
if (this.timer) {
|
|
29
|
+
clearTimeout(this.timer);
|
|
30
|
+
this.timer = null;
|
|
31
|
+
}
|
|
32
|
+
if (finalContent !== undefined) {
|
|
33
|
+
this.buffer = finalContent;
|
|
34
|
+
}
|
|
35
|
+
return this.flush(true);
|
|
36
|
+
}
|
|
37
|
+
async scheduleUpdate() {
|
|
38
|
+
const now = Date.now();
|
|
39
|
+
const elapsed = now - this.lastUpdate;
|
|
40
|
+
if (elapsed >= this.minInterval) {
|
|
41
|
+
await this.flush();
|
|
42
|
+
}
|
|
43
|
+
else if (!this.timer) {
|
|
44
|
+
this.timer = setTimeout(async () => {
|
|
45
|
+
this.timer = null;
|
|
46
|
+
await this.flush();
|
|
47
|
+
}, this.minInterval - elapsed);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
async flush(isFinal = false) {
|
|
51
|
+
if (!this.buffer)
|
|
52
|
+
return;
|
|
53
|
+
this.lastUpdate = Date.now();
|
|
54
|
+
if (this.options.useDraft && this.options.draftId) {
|
|
55
|
+
const richMsg = { html: `<p>${this.buffer}${isFinal ? '' : ' ▍'}</p>` };
|
|
56
|
+
return this.ctx.sendRichMessageDraft(this.options.draftId, richMsg);
|
|
57
|
+
}
|
|
58
|
+
const text = `${this.buffer}${isFinal ? '' : ' ▍'}`;
|
|
59
|
+
if (!this.sentMessageId) {
|
|
60
|
+
const sent = await this.ctx.reply(text, { parse_mode: 'HTML' });
|
|
61
|
+
this.sentMessageId = sent.message_id;
|
|
62
|
+
return sent;
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
return this.ctx.telegram.editMessageText(this.ctx.chat?.id, this.sentMessageId, undefined, text, { parse_mode: 'HTML' });
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
exports.AIStreamAdapter = AIStreamAdapter;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.argsParser = void 0;
|
|
4
|
+
const SINGLE_QUOTE = "'";
|
|
5
|
+
const DOUBLE_QUOTE = '"';
|
|
6
|
+
function argsParser(str, entities = [], entityOffset = 0) {
|
|
7
|
+
const mentions = {};
|
|
8
|
+
for (const entity of entities) // extract all text_mentions into an { offset: length } map
|
|
9
|
+
if (entity.type === 'text_mention' || entity.type === 'text_link')
|
|
10
|
+
mentions[entity.offset - entityOffset] = entity.length;
|
|
11
|
+
const args = [];
|
|
12
|
+
let done = 0;
|
|
13
|
+
let inside = undefined;
|
|
14
|
+
let buf = '';
|
|
15
|
+
function flush(to) {
|
|
16
|
+
if (done !== to)
|
|
17
|
+
args.push(buf + str.slice(done, to)), (inside = undefined);
|
|
18
|
+
buf = '';
|
|
19
|
+
done = to + 1;
|
|
20
|
+
}
|
|
21
|
+
for (let i = 0; i < str.length; i++) {
|
|
22
|
+
const char = str[i];
|
|
23
|
+
// quick lookup length of mention starting at i
|
|
24
|
+
const mention = mentions[i];
|
|
25
|
+
if (mention) {
|
|
26
|
+
// if we're inside a quote, eagerly flush existing state
|
|
27
|
+
flush(i);
|
|
28
|
+
// this also consumes current index, so decrement
|
|
29
|
+
done--;
|
|
30
|
+
// fast forward to end of mention
|
|
31
|
+
i += mention;
|
|
32
|
+
flush(i);
|
|
33
|
+
}
|
|
34
|
+
else if (char === SINGLE_QUOTE || char === DOUBLE_QUOTE)
|
|
35
|
+
if (inside)
|
|
36
|
+
if (inside === char)
|
|
37
|
+
flush(i);
|
|
38
|
+
else
|
|
39
|
+
continue;
|
|
40
|
+
else
|
|
41
|
+
flush(i), (inside = char);
|
|
42
|
+
else if (char === ' ')
|
|
43
|
+
if (inside)
|
|
44
|
+
continue;
|
|
45
|
+
else
|
|
46
|
+
flush(i);
|
|
47
|
+
else if (char === '\n')
|
|
48
|
+
flush(i);
|
|
49
|
+
else if (char === '\\')
|
|
50
|
+
(buf += str.slice(done, i)), (done = ++i); // skip parsing the next char
|
|
51
|
+
else
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
if (done < str.length)
|
|
55
|
+
flush(str.length);
|
|
56
|
+
return args;
|
|
57
|
+
}
|
|
58
|
+
exports.argsParser = argsParser;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.is2D = exports.hasPropType = exports.hasProp = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Checks if a given object has a property with a given name.
|
|
6
|
+
*
|
|
7
|
+
* Example invocation:
|
|
8
|
+
* ```js
|
|
9
|
+
* let obj = { 'foo': 'bar', 'baz': () => {} }
|
|
10
|
+
* hasProp(obj, 'foo') // true
|
|
11
|
+
* hasProp(obj, 'baz') // true
|
|
12
|
+
* hasProp(obj, 'abc') // false
|
|
13
|
+
* ```
|
|
14
|
+
*
|
|
15
|
+
* @param obj An object to test
|
|
16
|
+
* @param prop The name of the property
|
|
17
|
+
*/
|
|
18
|
+
function hasProp(obj, prop) {
|
|
19
|
+
return obj !== undefined && prop in obj;
|
|
20
|
+
}
|
|
21
|
+
exports.hasProp = hasProp;
|
|
22
|
+
/**
|
|
23
|
+
* Checks if a given object has a property with a given name.
|
|
24
|
+
* Furthermore performs a `typeof` check on the property if it exists.
|
|
25
|
+
*
|
|
26
|
+
* Example invocation:
|
|
27
|
+
* ```js
|
|
28
|
+
* let obj = { 'foo': 'bar', 'baz': () => {} }
|
|
29
|
+
* hasPropType(obj, 'foo', 'string') // true
|
|
30
|
+
* hasPropType(obj, 'baz', 'function') // true
|
|
31
|
+
* hasPropType(obj, 'abc', 'number') // false
|
|
32
|
+
* ```
|
|
33
|
+
*
|
|
34
|
+
* @param obj An object to test
|
|
35
|
+
* @param prop The name of the property
|
|
36
|
+
* @param type The type the property is expected to have
|
|
37
|
+
*/
|
|
38
|
+
function hasPropType(obj, prop, type) {
|
|
39
|
+
return hasProp(obj, prop) && type === typeof obj[prop];
|
|
40
|
+
}
|
|
41
|
+
exports.hasPropType = hasPropType;
|
|
42
|
+
/**
|
|
43
|
+
* Checks if the supplied array has two dimensions or not.
|
|
44
|
+
*
|
|
45
|
+
* Example invocations:
|
|
46
|
+
* is2D([]) // false
|
|
47
|
+
* is2D([[]]) // true
|
|
48
|
+
* is2D([[], []]) // true
|
|
49
|
+
* is2D([42]) // false
|
|
50
|
+
*
|
|
51
|
+
* @param arr an array with one or two dimensions
|
|
52
|
+
*/
|
|
53
|
+
function is2D(arr) {
|
|
54
|
+
return Array.isArray(arr[0]);
|
|
55
|
+
}
|
|
56
|
+
exports.is2D = is2D;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.compactOptions = void 0;
|
|
4
|
+
function compactOptions(options) {
|
|
5
|
+
if (!options) {
|
|
6
|
+
return options;
|
|
7
|
+
}
|
|
8
|
+
const compacted = {};
|
|
9
|
+
for (const key in options)
|
|
10
|
+
if (
|
|
11
|
+
// todo(mkr): replace with Object.hasOwn in v5 (Node 16+)
|
|
12
|
+
Object.prototype.hasOwnProperty.call(options, key) &&
|
|
13
|
+
options[key] !== undefined)
|
|
14
|
+
compacted[key] = options[key];
|
|
15
|
+
return compacted;
|
|
16
|
+
}
|
|
17
|
+
exports.compactOptions = compactOptions;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.deunionize = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Expose properties from all union variants.
|
|
6
|
+
* @deprectated
|
|
7
|
+
* @see https://github.com/telegraf/telegraf/issues/1388#issuecomment-791573609
|
|
8
|
+
* @see https://millsp.github.io/ts-toolbelt/modules/union_strict.html
|
|
9
|
+
*/
|
|
10
|
+
function deunionize(t) {
|
|
11
|
+
return t;
|
|
12
|
+
}
|
|
13
|
+
exports.deunionize = deunionize;
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.linkOrMention = exports.createFmt = exports.join = exports.FmtString = void 0;
|
|
4
|
+
const util_1 = require("./util");
|
|
5
|
+
class FmtString {
|
|
6
|
+
constructor(text, entities) {
|
|
7
|
+
this.text = text;
|
|
8
|
+
if (entities) {
|
|
9
|
+
this.entities = entities;
|
|
10
|
+
// force parse_mode to undefined if entities are present
|
|
11
|
+
this.parse_mode = undefined;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
static normalise(content) {
|
|
15
|
+
if (content instanceof FmtString)
|
|
16
|
+
return content;
|
|
17
|
+
return new FmtString(String(content));
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
exports.FmtString = FmtString;
|
|
21
|
+
const isArray = Array.isArray;
|
|
22
|
+
/** Given a base FmtString and something to append to it, mutates the base */
|
|
23
|
+
const _add = (base, next) => {
|
|
24
|
+
const len = base.text.length;
|
|
25
|
+
if (next instanceof FmtString) {
|
|
26
|
+
base.text = `${base.text}${next.text}`;
|
|
27
|
+
// next.entities could be undefined and condition will fail
|
|
28
|
+
for (let i = 0; i < (next.entities?.length || 0); i++) {
|
|
29
|
+
// because of the above condition, next.entities[i] cannot be undefined
|
|
30
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
31
|
+
const entity = next.entities[i];
|
|
32
|
+
// base.entities is ensured by caller
|
|
33
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
34
|
+
base.entities.push({ ...entity, offset: entity.offset + len });
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
else
|
|
38
|
+
base.text = `${base.text}${next}`;
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* Given an `Iterable<FmtString | string | Any>` and a separator, flattens the list into a single FmtString.
|
|
42
|
+
* Analogous to Array#join -> string, but for FmtString
|
|
43
|
+
*/
|
|
44
|
+
const join = (fragments, separator) => {
|
|
45
|
+
const result = new FmtString('');
|
|
46
|
+
// ensure entities array so loop doesn't need to check
|
|
47
|
+
result.entities = [];
|
|
48
|
+
const iter = fragments[Symbol.iterator]();
|
|
49
|
+
let curr = iter.next();
|
|
50
|
+
while (!curr.done) {
|
|
51
|
+
_add(result, curr.value);
|
|
52
|
+
curr = iter.next();
|
|
53
|
+
if (separator && !curr.done)
|
|
54
|
+
_add(result, separator);
|
|
55
|
+
}
|
|
56
|
+
// set parse_mode: undefined if entities are present
|
|
57
|
+
if (result.entities.length)
|
|
58
|
+
result.parse_mode = undefined;
|
|
59
|
+
// remove entities array if not relevant
|
|
60
|
+
else
|
|
61
|
+
delete result.entities;
|
|
62
|
+
return result;
|
|
63
|
+
};
|
|
64
|
+
exports.join = join;
|
|
65
|
+
/** Internal constructor for all fmt helpers */
|
|
66
|
+
function createFmt(kind, opts) {
|
|
67
|
+
return function fmt(parts, ...items) {
|
|
68
|
+
parts = isArray(parts) ? parts : [parts];
|
|
69
|
+
const result = (0, exports.join)((0, util_1.zip)(parts, items));
|
|
70
|
+
if (kind) {
|
|
71
|
+
result.entities ??= [];
|
|
72
|
+
result.entities.unshift({
|
|
73
|
+
type: kind,
|
|
74
|
+
offset: 0,
|
|
75
|
+
length: result.text.length,
|
|
76
|
+
...opts,
|
|
77
|
+
});
|
|
78
|
+
result.parse_mode = undefined;
|
|
79
|
+
}
|
|
80
|
+
return result;
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
exports.createFmt = createFmt;
|
|
84
|
+
const linkOrMention = (content, data) => {
|
|
85
|
+
const { text, entities = [] } = FmtString.normalise(content);
|
|
86
|
+
entities.unshift(Object.assign(data, { offset: 0, length: text.length }));
|
|
87
|
+
return new FmtString(text, entities);
|
|
88
|
+
};
|
|
89
|
+
exports.linkOrMention = linkOrMention;
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.InputBox = void 0;
|
|
27
|
+
const Markup = __importStar(require("../../markup"));
|
|
28
|
+
/**
|
|
29
|
+
* Interactive In-Chat Form Box Card for Telegram Messages.
|
|
30
|
+
* Render boxed form cards with dynamic real-time field updates.
|
|
31
|
+
*/
|
|
32
|
+
class InputBox {
|
|
33
|
+
constructor(id) {
|
|
34
|
+
this.title = '📋 FORM INPUT';
|
|
35
|
+
this.fields = [];
|
|
36
|
+
this.id = id;
|
|
37
|
+
}
|
|
38
|
+
setTitle(title) {
|
|
39
|
+
this.title = title;
|
|
40
|
+
return this;
|
|
41
|
+
}
|
|
42
|
+
addField(key, label, options = {}) {
|
|
43
|
+
this.fields.push({ key, label, ...options });
|
|
44
|
+
return this;
|
|
45
|
+
}
|
|
46
|
+
onComplete(handler) {
|
|
47
|
+
this.completionHandler = handler;
|
|
48
|
+
return this;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Render formatted HTML box card text.
|
|
52
|
+
*/
|
|
53
|
+
renderText(data = {}) {
|
|
54
|
+
const lines = [];
|
|
55
|
+
lines.push(`<b>┌─ ${this.title.toUpperCase()} ─┐</b>`);
|
|
56
|
+
this.fields.forEach((field, idx) => {
|
|
57
|
+
const val = data[field.key] ? `<b>${data[field.key]}</b>` : `<i>[ ${field.placeholder ?? 'Belum diisi'} ]</i>`;
|
|
58
|
+
lines.push(`│ ${idx + 1}. <b>${field.label}</b>: ${val}`);
|
|
59
|
+
});
|
|
60
|
+
const isComplete = this.fields.every((f) => Boolean(data[f.key]));
|
|
61
|
+
lines.push(`<b>└${'─'.repeat(30)}┘</b>`);
|
|
62
|
+
lines.push(isComplete ? '<b>Status:</b> ✅ <i>Lengkap (Siap Dikirim)</i>' : '<b>Status:</b> ⌛ <i>Menunggu Pengisian...</i>');
|
|
63
|
+
return lines.join('\n');
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Render inline keyboard with field edit buttons and submit action.
|
|
67
|
+
*/
|
|
68
|
+
renderKeyboard(data = {}) {
|
|
69
|
+
const buttons = [];
|
|
70
|
+
// Field buttons
|
|
71
|
+
this.fields.forEach((field) => {
|
|
72
|
+
const filled = Boolean(data[field.key]);
|
|
73
|
+
const icon = filled ? '✅' : '✏️';
|
|
74
|
+
buttons.push([Markup.button.callback(`${icon} ${field.label}`, `inputbox:${this.id}:edit:${field.key}`)]);
|
|
75
|
+
});
|
|
76
|
+
// Action row
|
|
77
|
+
const isComplete = this.fields.every((f) => Boolean(data[f.key]));
|
|
78
|
+
if (isComplete) {
|
|
79
|
+
buttons.push([
|
|
80
|
+
Markup.button.callback('🚀 Submit Form', `inputbox:${this.id}:submit`),
|
|
81
|
+
Markup.button.callback('🔄 Reset', `inputbox:${this.id}:reset`),
|
|
82
|
+
]);
|
|
83
|
+
}
|
|
84
|
+
return Markup.inlineKeyboard(buttons);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
exports.InputBox = InputBox;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.sanitizeRichHtml = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Converts Rich HTML strings containing tags like <h1>, <h2>, <p>, <hr>
|
|
6
|
+
* into standard Telegram HTML compatible with parse_mode: 'HTML' (editMessageText/sendMessage).
|
|
7
|
+
*/
|
|
8
|
+
function sanitizeRichHtml(html) {
|
|
9
|
+
if (!html)
|
|
10
|
+
return html;
|
|
11
|
+
let result = html;
|
|
12
|
+
// Convert H1: <h1>Text</h1> -> <b>TEXT</b>
|
|
13
|
+
result = result.replace(/<h1[^>]*>(.*?)<\/h1>/gis, (_, content) => `<b>${content.trim().toUpperCase()}</b>\n\n`);
|
|
14
|
+
// Convert H2..H6: <h2>Text</h2> -> <b>Text</b>
|
|
15
|
+
result = result.replace(/<h[2-6][^>]*>(.*?)<\/h[2-6]>/gis, (_, content) => `<b>${content.trim()}</b>\n\n`);
|
|
16
|
+
// Convert Paragraphs: <p>Text</p> -> Text\n\n
|
|
17
|
+
result = result.replace(/<p[^>]*>(.*?)<\/p>/gis, (_, content) => `${content.trim()}\n\n`);
|
|
18
|
+
// Convert Footer: <footer>Text</footer> -> <i>Text</i>
|
|
19
|
+
result = result.replace(/<footer[^>]*>(.*?)<\/footer>/gis, (_, content) => `<i>${content.trim()}</i>\n`);
|
|
20
|
+
// Convert Horizontal Rules: <hr/> or <hr> -> ──────────
|
|
21
|
+
result = result.replace(/<hr\s*\/?>/gi, '──────────\n');
|
|
22
|
+
// Convert Marks: <mark>Text</mark> -> <b>[Text]</b>
|
|
23
|
+
result = result.replace(/<mark[^>]*>(.*?)<\/mark>/gis, (_, content) => `<b>[${content.trim()}]</b>`);
|
|
24
|
+
// Strip unsupported sub/sup tags but keep text
|
|
25
|
+
result = result.replace(/<sub[^>]*>(.*?)<\/sub>/gis, '$1');
|
|
26
|
+
result = result.replace(/<sup[^>]*>(.*?)<\/sup>/gis, '$1');
|
|
27
|
+
// Trim extra trailing newlines (> 2 consecutive newlines)
|
|
28
|
+
result = result.replace(/\n{3,}/g, '\n\n');
|
|
29
|
+
return result.trim();
|
|
30
|
+
}
|
|
31
|
+
exports.sanitizeRichHtml = sanitizeRichHtml;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SmartQueue = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Smart Queue & Rate-Limit Manager for Telegram Bot API calls.
|
|
6
|
+
* Prevents 429 Too Many Requests by enforcing min delay between calls per target key (e.g. chatId).
|
|
7
|
+
*/
|
|
8
|
+
class SmartQueue {
|
|
9
|
+
constructor(options = {}) {
|
|
10
|
+
this.queues = new Map();
|
|
11
|
+
this.processing = new Set();
|
|
12
|
+
this.minDelayMs = options.minDelayMs ?? 50;
|
|
13
|
+
}
|
|
14
|
+
static getInstance() {
|
|
15
|
+
if (!SmartQueue.instance) {
|
|
16
|
+
SmartQueue.instance = new SmartQueue();
|
|
17
|
+
}
|
|
18
|
+
return SmartQueue.instance;
|
|
19
|
+
}
|
|
20
|
+
enqueue(key, task, options) {
|
|
21
|
+
return new Promise((resolve, reject) => {
|
|
22
|
+
if (!this.queues.has(key)) {
|
|
23
|
+
this.queues.set(key, []);
|
|
24
|
+
}
|
|
25
|
+
this.queues.get(key).push({
|
|
26
|
+
task,
|
|
27
|
+
resolve,
|
|
28
|
+
reject,
|
|
29
|
+
retries: 0,
|
|
30
|
+
});
|
|
31
|
+
this.processQueue(key, options);
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
async processQueue(key, options) {
|
|
35
|
+
if (this.processing.has(key))
|
|
36
|
+
return;
|
|
37
|
+
this.processing.add(key);
|
|
38
|
+
const queue = this.queues.get(key);
|
|
39
|
+
const maxRetries = options?.maxRetries ?? 3;
|
|
40
|
+
const minDelay = options?.minDelayMs ?? this.minDelayMs;
|
|
41
|
+
while (queue && queue.length > 0) {
|
|
42
|
+
const item = queue[0];
|
|
43
|
+
try {
|
|
44
|
+
const result = await item.task();
|
|
45
|
+
queue.shift();
|
|
46
|
+
item.resolve(result);
|
|
47
|
+
}
|
|
48
|
+
catch (err) {
|
|
49
|
+
// Handle Telegram 429 Too Many Requests (retry_after)
|
|
50
|
+
const retryAfter = err?.parameters?.retry_after ?? err?.response?.parameters?.retry_after;
|
|
51
|
+
if (retryAfter && item.retries < maxRetries) {
|
|
52
|
+
item.retries++;
|
|
53
|
+
const waitTime = (retryAfter + 0.5) * 1000;
|
|
54
|
+
await new Promise((res) => setTimeout(res, waitTime));
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
queue.shift();
|
|
58
|
+
item.reject(err);
|
|
59
|
+
}
|
|
60
|
+
if (queue.length > 0) {
|
|
61
|
+
await new Promise((res) => setTimeout(res, minDelay));
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
this.processing.delete(key);
|
|
65
|
+
if (queue && queue.length === 0) {
|
|
66
|
+
this.queues.delete(key);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
exports.SmartQueue = SmartQueue;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.indexed = exports.zip = exports.fmtCaption = exports.env = void 0;
|
|
4
|
+
exports.env = process.env;
|
|
5
|
+
function fmtCaption(extra) {
|
|
6
|
+
if (!extra)
|
|
7
|
+
return;
|
|
8
|
+
const caption = extra.caption;
|
|
9
|
+
if (!caption || typeof caption === 'string')
|
|
10
|
+
return extra;
|
|
11
|
+
const { text, entities } = caption;
|
|
12
|
+
return {
|
|
13
|
+
...extra,
|
|
14
|
+
caption: text,
|
|
15
|
+
...(entities && {
|
|
16
|
+
caption_entities: entities,
|
|
17
|
+
parse_mode: undefined,
|
|
18
|
+
}),
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
exports.fmtCaption = fmtCaption;
|
|
22
|
+
function* zip(xs, ys) {
|
|
23
|
+
const x = xs[Symbol.iterator]();
|
|
24
|
+
const y = ys[Symbol.iterator]();
|
|
25
|
+
let x1 = x.next();
|
|
26
|
+
let y1 = y.next();
|
|
27
|
+
while (!x1.done) {
|
|
28
|
+
yield x1.value;
|
|
29
|
+
if (!y1.done)
|
|
30
|
+
yield y1.value;
|
|
31
|
+
x1 = x.next();
|
|
32
|
+
y1 = y.next();
|
|
33
|
+
}
|
|
34
|
+
while (!y1.done) {
|
|
35
|
+
yield y1.value;
|
|
36
|
+
y1 = y.next();
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
exports.zip = zip;
|
|
40
|
+
function indexed(target, indexer) {
|
|
41
|
+
return new Proxy(target, {
|
|
42
|
+
get: function (target, prop, receiver) {
|
|
43
|
+
if ((typeof prop === 'string' || typeof prop === 'number') &&
|
|
44
|
+
!isNaN(+prop))
|
|
45
|
+
return indexer.call(target, +prop);
|
|
46
|
+
return Reflect.get(target, prop, receiver);
|
|
47
|
+
},
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
exports.indexed = indexed;
|