@xbibzlibrary/telebibz 0.4.5 → 3.1.1
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 +53 -138
- package/LICENSE +1 -1
- package/NOTICE.md +9 -4
- package/README.id.md +542 -206
- package/README.md +539 -213
- package/examples/01-quickstart.js +13 -0
- package/examples/02-menu-tombol.js +22 -0
- package/examples/03-wizard.js +58 -0
- package/examples/04-broadcast.js +25 -0
- package/examples/05-kirim-file.js +19 -0
- package/examples/06-menu.js +35 -0
- package/examples/07-inline-query.js +18 -0
- package/index.d.ts +106 -0
- package/index.js +44 -0
- package/lib/api.js +154 -0
- package/lib/broadcast.js +35 -0
- package/lib/composer.js +174 -0
- package/lib/context.js +190 -0
- package/lib/errors.js +35 -0
- package/lib/file.js +41 -0
- package/lib/inline-query.js +28 -0
- package/lib/keyboard.js +83 -0
- package/lib/logger.js +38 -0
- package/lib/menus.js +90 -0
- package/lib/net.js +115 -0
- package/lib/ratelimit.js +61 -0
- package/lib/runner.js +45 -0
- package/lib/session.js +36 -0
- package/lib/telebibz.js +193 -0
- package/lib/wizard.js +247 -0
- package/package.json +35 -97
- package/test/all.test.js +439 -0
- package/CODE_OF_CONDUCT.md +0 -37
- package/CONTRIBUTING.md +0 -59
- package/CONTRIBUTION_RULES.md +0 -41
- package/GOVERNANCE.md +0 -47
- package/README.zh-CN.md +0 -306
- package/RELEASE_AUTOMATION.md +0 -78
- package/RELEASE_POLICY.md +0 -32
- package/SECURITY.md +0 -47
- package/SHOWCASE.md +0 -29
- package/SUPPORT.md +0 -30
- package/assets/readme-preview.html +0 -75
- package/assets/telebibz-logo.png +0 -0
- package/assets/telebibz-readme-preview.png +0 -0
- package/bin/telebibz.mjs +0 -3
- package/dist/generated/api.d.ts +0 -13
- package/dist/generated/api.d.ts.map +0 -1
- package/dist/generated/api.js +0 -192
- package/dist/generated/api.js.map +0 -1
- package/dist/src/api/client.d.ts +0 -62
- package/dist/src/api/client.d.ts.map +0 -1
- package/dist/src/api/client.js +0 -104
- package/dist/src/api/client.js.map +0 -1
- package/dist/src/api/errors.d.ts +0 -45
- package/dist/src/api/errors.d.ts.map +0 -1
- package/dist/src/api/errors.js +0 -65
- package/dist/src/api/errors.js.map +0 -1
- package/dist/src/api/index.d.ts +0 -6
- package/dist/src/api/index.d.ts.map +0 -1
- package/dist/src/api/index.js +0 -6
- package/dist/src/api/index.js.map +0 -1
- package/dist/src/api/telegram-types/LICENSE +0 -21
- package/dist/src/api/telegram-types/api.d.ts +0 -22
- package/dist/src/api/telegram-types/checklist.d.ts +0 -72
- package/dist/src/api/telegram-types/inline.d.ts +0 -692
- package/dist/src/api/telegram-types/langs.d.ts +0 -193
- package/dist/src/api/telegram-types/manage.d.ts +0 -1144
- package/dist/src/api/telegram-types/markup.d.ts +0 -268
- package/dist/src/api/telegram-types/message.d.ts +0 -1537
- package/dist/src/api/telegram-types/methods.d.ts +0 -2870
- package/dist/src/api/telegram-types/mod.d.ts +0 -14
- package/dist/src/api/telegram-types/passport.d.ts +0 -163
- package/dist/src/api/telegram-types/payment.d.ts +0 -570
- package/dist/src/api/telegram-types/rich.d.ts +0 -1010
- package/dist/src/api/telegram-types/settings.d.ts +0 -120
- package/dist/src/api/telegram-types/story.d.ts +0 -89
- package/dist/src/api/telegram-types/update.d.ts +0 -84
- package/dist/src/api/telegram.d.ts +0 -7
- package/dist/src/api/telegram.d.ts.map +0 -1
- package/dist/src/api/telegram.js +0 -2
- package/dist/src/api/telegram.js.map +0 -1
- package/dist/src/api/transport.d.ts +0 -68
- package/dist/src/api/transport.d.ts.map +0 -1
- package/dist/src/api/transport.js +0 -264
- package/dist/src/api/transport.js.map +0 -1
- package/dist/src/api/types.d.ts +0 -466
- package/dist/src/api/types.d.ts.map +0 -1
- package/dist/src/api/types.js +0 -2
- package/dist/src/api/types.js.map +0 -1
- package/dist/src/branding/terminal.d.ts +0 -77
- package/dist/src/branding/terminal.d.ts.map +0 -1
- package/dist/src/branding/terminal.js +0 -328
- package/dist/src/branding/terminal.js.map +0 -1
- package/dist/src/broadcast/broadcast.d.ts +0 -50
- package/dist/src/broadcast/broadcast.d.ts.map +0 -1
- package/dist/src/broadcast/broadcast.js +0 -56
- package/dist/src/broadcast/broadcast.js.map +0 -1
- package/dist/src/cache/cache.d.ts +0 -34
- package/dist/src/cache/cache.d.ts.map +0 -1
- package/dist/src/cache/cache.js +0 -41
- package/dist/src/cache/cache.js.map +0 -1
- package/dist/src/cli.d.ts +0 -2
- package/dist/src/cli.d.ts.map +0 -1
- package/dist/src/cli.js +0 -84
- package/dist/src/cli.js.map +0 -1
- package/dist/src/context/context.d.ts +0 -124
- package/dist/src/context/context.d.ts.map +0 -1
- package/dist/src/context/context.js +0 -302
- package/dist/src/context/context.js.map +0 -1
- package/dist/src/core/bot.d.ts +0 -204
- package/dist/src/core/bot.d.ts.map +0 -1
- package/dist/src/core/bot.js +0 -506
- package/dist/src/core/bot.js.map +0 -1
- package/dist/src/core/events.d.ts +0 -75
- package/dist/src/core/events.d.ts.map +0 -1
- package/dist/src/core/events.js +0 -35
- package/dist/src/core/events.js.map +0 -1
- package/dist/src/core/webhook-reply.d.ts +0 -34
- package/dist/src/core/webhook-reply.d.ts.map +0 -1
- package/dist/src/core/webhook-reply.js +0 -37
- package/dist/src/core/webhook-reply.js.map +0 -1
- package/dist/src/index.d.ts +0 -24
- package/dist/src/index.d.ts.map +0 -1
- package/dist/src/index.js +0 -24
- package/dist/src/index.js.map +0 -1
- package/dist/src/keyboard/index.d.ts +0 -46
- package/dist/src/keyboard/index.d.ts.map +0 -1
- package/dist/src/keyboard/index.js +0 -55
- package/dist/src/keyboard/index.js.map +0 -1
- package/dist/src/middleware/compose.d.ts +0 -5
- package/dist/src/middleware/compose.d.ts.map +0 -1
- package/dist/src/middleware/compose.js +0 -17
- package/dist/src/middleware/compose.js.map +0 -1
- package/dist/src/observability/logger.d.ts +0 -78
- package/dist/src/observability/logger.d.ts.map +0 -1
- package/dist/src/observability/logger.js +0 -285
- package/dist/src/observability/logger.js.map +0 -1
- package/dist/src/plugins/plugin.d.ts +0 -38
- package/dist/src/plugins/plugin.d.ts.map +0 -1
- package/dist/src/plugins/plugin.js +0 -59
- package/dist/src/plugins/plugin.js.map +0 -1
- package/dist/src/queue/queue.d.ts +0 -77
- package/dist/src/queue/queue.d.ts.map +0 -1
- package/dist/src/queue/queue.js +0 -213
- package/dist/src/queue/queue.js.map +0 -1
- package/dist/src/router/router.d.ts +0 -61
- package/dist/src/router/router.d.ts.map +0 -1
- package/dist/src/router/router.js +0 -183
- package/dist/src/router/router.js.map +0 -1
- package/dist/src/state/conversation.d.ts +0 -56
- package/dist/src/state/conversation.d.ts.map +0 -1
- package/dist/src/state/conversation.js +0 -133
- package/dist/src/state/conversation.js.map +0 -1
- package/dist/src/state/forms.d.ts +0 -34
- package/dist/src/state/forms.d.ts.map +0 -1
- package/dist/src/state/forms.js +0 -44
- package/dist/src/state/forms.js.map +0 -1
- package/dist/src/state/menu.d.ts +0 -78
- package/dist/src/state/menu.d.ts.map +0 -1
- package/dist/src/state/menu.js +0 -127
- package/dist/src/state/menu.js.map +0 -1
- package/dist/src/storage/storage.d.ts +0 -146
- package/dist/src/storage/storage.d.ts.map +0 -1
- package/dist/src/storage/storage.js +0 -195
- package/dist/src/storage/storage.js.map +0 -1
- package/dist/src/telegram-features.d.ts +0 -33
- package/dist/src/telegram-features.d.ts.map +0 -1
- package/dist/src/telegram-features.js +0 -71
- package/dist/src/telegram-features.js.map +0 -1
- package/dist/src/testing.d.ts +0 -24
- package/dist/src/testing.d.ts.map +0 -1
- package/dist/src/testing.js +0 -38
- package/dist/src/testing.js.map +0 -1
- package/dist/src/utils/concurrency.d.ts +0 -25
- package/dist/src/utils/concurrency.d.ts.map +0 -1
- package/dist/src/utils/concurrency.js +0 -52
- package/dist/src/utils/concurrency.js.map +0 -1
- package/dist/src/utils/files.d.ts +0 -45
- package/dist/src/utils/files.d.ts.map +0 -1
- package/dist/src/utils/files.js +0 -53
- package/dist/src/utils/files.js.map +0 -1
- package/dist/src/utils/text.d.ts +0 -39
- package/dist/src/utils/text.d.ts.map +0 -1
- package/dist/src/utils/text.js +0 -56
- package/dist/src/utils/text.js.map +0 -1
- package/dist/src/webhook/handler.d.ts +0 -19
- package/dist/src/webhook/handler.d.ts.map +0 -1
- package/dist/src/webhook/handler.js +0 -141
- package/dist/src/webhook/handler.js.map +0 -1
- package/dist-cjs/generated/api.js +0 -194
- package/dist-cjs/package.json +0 -3
- package/dist-cjs/src/api/client.js +0 -107
- package/dist-cjs/src/api/errors.js +0 -74
- package/dist-cjs/src/api/index.js +0 -21
- package/dist-cjs/src/api/telegram-types/LICENSE +0 -21
- package/dist-cjs/src/api/telegram-types/api.d.ts +0 -22
- package/dist-cjs/src/api/telegram-types/checklist.d.ts +0 -72
- package/dist-cjs/src/api/telegram-types/inline.d.ts +0 -692
- package/dist-cjs/src/api/telegram-types/langs.d.ts +0 -193
- package/dist-cjs/src/api/telegram-types/manage.d.ts +0 -1144
- package/dist-cjs/src/api/telegram-types/markup.d.ts +0 -268
- package/dist-cjs/src/api/telegram-types/message.d.ts +0 -1537
- package/dist-cjs/src/api/telegram-types/methods.d.ts +0 -2870
- package/dist-cjs/src/api/telegram-types/mod.d.ts +0 -14
- package/dist-cjs/src/api/telegram-types/passport.d.ts +0 -163
- package/dist-cjs/src/api/telegram-types/payment.d.ts +0 -570
- package/dist-cjs/src/api/telegram-types/rich.d.ts +0 -1010
- package/dist-cjs/src/api/telegram-types/settings.d.ts +0 -120
- package/dist-cjs/src/api/telegram-types/story.d.ts +0 -89
- package/dist-cjs/src/api/telegram-types/update.d.ts +0 -84
- package/dist-cjs/src/api/telegram.js +0 -2
- package/dist-cjs/src/api/transport.js +0 -267
- package/dist-cjs/src/api/types.js +0 -2
- package/dist-cjs/src/branding/terminal.js +0 -338
- package/dist-cjs/src/broadcast/broadcast.js +0 -58
- package/dist-cjs/src/cache/cache.js +0 -45
- package/dist-cjs/src/cli.js +0 -86
- package/dist-cjs/src/context/context.js +0 -305
- package/dist-cjs/src/core/bot.js +0 -510
- package/dist-cjs/src/core/events.js +0 -38
- package/dist-cjs/src/core/webhook-reply.js +0 -42
- package/dist-cjs/src/index.js +0 -47
- package/dist-cjs/src/keyboard/index.js +0 -61
- package/dist-cjs/src/middleware/compose.js +0 -20
- package/dist-cjs/src/observability/logger.js +0 -293
- package/dist-cjs/src/plugins/plugin.js +0 -63
- package/dist-cjs/src/queue/queue.js +0 -219
- package/dist-cjs/src/router/router.js +0 -186
- package/dist-cjs/src/state/conversation.js +0 -139
- package/dist-cjs/src/state/forms.js +0 -47
- package/dist-cjs/src/state/menu.js +0 -133
- package/dist-cjs/src/storage/storage.js +0 -202
- package/dist-cjs/src/telegram-features.js +0 -76
- package/dist-cjs/src/testing.js +0 -45
- package/dist-cjs/src/utils/concurrency.js +0 -57
- package/dist-cjs/src/utils/files.js +0 -58
- package/dist-cjs/src/utils/text.js +0 -63
- package/dist-cjs/src/webhook/handler.js +0 -144
- package/docs/API.id.md +0 -1935
- package/docs/API.md +0 -1969
- package/docs/API.zh-CN.md +0 -1929
- package/docs/COOKBOOK.id.md +0 -321
- package/docs/COOKBOOK.md +0 -321
- package/docs/COOKBOOK.zh-CN.md +0 -321
- package/docs/ERRORS.id.md +0 -194
- package/docs/ERRORS.md +0 -194
- package/docs/ERRORS.zh-CN.md +0 -194
- package/docs/FILES.id.md +0 -243
- package/docs/FILES.md +0 -243
- package/docs/FILES.zh-CN.md +0 -243
- package/docs/GETTING_STARTED.id.md +0 -89
- package/docs/GETTING_STARTED.md +0 -89
- package/docs/GETTING_STARTED.zh-CN.md +0 -89
- package/docs/GITHUB_PACKAGES.id.md +0 -82
- package/docs/GITHUB_PACKAGES.md +0 -82
- package/docs/GITHUB_PACKAGES.zh-CN.md +0 -82
- package/docs/MIGRATION_TELEGRAF.id.md +0 -147
- package/docs/MIGRATION_TELEGRAF.md +0 -154
- package/docs/MIGRATION_TELEGRAF.zh-CN.md +0 -147
- package/docs/README.md +0 -67
- package/docs/STORAGE.id.md +0 -105
- package/docs/STORAGE.md +0 -105
- package/docs/STORAGE.zh-CN.md +0 -105
- package/docs/TESTING.id.md +0 -203
- package/docs/TESTING.md +0 -203
- package/docs/TESTING.zh-CN.md +0 -203
- package/docs/WEBHOOK.id.md +0 -212
- package/docs/WEBHOOK.md +0 -215
- package/docs/WEBHOOK.zh-CN.md +0 -212
- package/examples/README.md +0 -37
- package/examples/files.ts +0 -35
- package/examples/minimal.ts +0 -12
- package/examples/tsconfig.json +0 -9
- package/examples/webhook.ts +0 -42
- package/examples/wizard-registration.ts +0 -42
package/lib/wizard.js
ADDED
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
// lib/wizard.js — percakapan tanya-jawab berurutan (form) berbasis sesi.
|
|
2
|
+
// v3.1: + TOMBOL pilihan (reply keyboard / inline keyboard), mode tampilan
|
|
3
|
+
// 'send' | 'edit' | 'delete', cleanup pesan & hapus keyboard otomatis.
|
|
4
|
+
'use strict';
|
|
5
|
+
|
|
6
|
+
const KEY = '__telebibz_wizard';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Definisi wizard:
|
|
10
|
+
* {
|
|
11
|
+
* mode: 'send' | 'edit' | 'delete', // ops, default 'send' (per-step bisa override)
|
|
12
|
+
* cleanup: true, // ops: hapus pesan tanya terakhir saat selesai
|
|
13
|
+
* removeKeyboard: true, // ops: singkirkan reply keyboard saat selesai
|
|
14
|
+
* steps: [
|
|
15
|
+
* { key:'nama', ask:'Siapa namamu?' },
|
|
16
|
+
* { key:'jk', ask:'Jenis kelamin?', buttons: ['Laki-laki', 'Perempuan'] },
|
|
17
|
+
* { key:'setuju', ask:'Setuju?', inline: true,
|
|
18
|
+
* buttons: [[{ text:'✅ Ya', value:'ya' }, { text:'❌ Tidak', value:'tdk' }]] },
|
|
19
|
+
* { key:'umur', ask:'Umur berapa?', parse: Number, mode: 'edit', onlyButtons: false,
|
|
20
|
+
* validate: (n) => (n>0 && n<120) ? null : 'Umur tidak masuk akal, ulangi:' },
|
|
21
|
+
* ],
|
|
22
|
+
* done: async (answers, ctx) => {},
|
|
23
|
+
* cancelWords: ['batal', '/batal', 'cancel'], // ops, default ada
|
|
24
|
+
* onCancel: (ctx) => ctx.reply('Dibatalkan.'), // ops
|
|
25
|
+
* }
|
|
26
|
+
*
|
|
27
|
+
* Format `buttons`:
|
|
28
|
+
* ['A', 'B'] → label polos, nilai = label
|
|
29
|
+
* [{ text:'A', value:'a' }] → label + nilai berbeda (flat, disusun 2 per baris)
|
|
30
|
+
* [['A','B'], ['C']] → baris eksplisit (reply maupun inline)
|
|
31
|
+
* `inline: true` → tombol callback (klik = nilai langsung, tanpa mengetik)
|
|
32
|
+
* `onlyButtons: true` → tolak ketikan bebas, wajib pilih tombol
|
|
33
|
+
*/
|
|
34
|
+
const wizards = new Map();
|
|
35
|
+
|
|
36
|
+
function define(id, def) {
|
|
37
|
+
if (!def || !Array.isArray(def.steps) || !def.steps.length || typeof def.done !== 'function') {
|
|
38
|
+
throw new Error(`wizard "${id}" butuh steps[] dan done(answers, ctx)`);
|
|
39
|
+
}
|
|
40
|
+
const cancelWords = new Set((def.cancelWords || ['batal', '/batal', 'cancel']).map((s) => String(s).toLowerCase()));
|
|
41
|
+
wizards.set(id, { ...def, cancelWords });
|
|
42
|
+
return id;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function get(id) { return wizards.get(id); }
|
|
46
|
+
|
|
47
|
+
/* ---------- normalisasi tombol ---------- */
|
|
48
|
+
function normalizeButtons(input) {
|
|
49
|
+
if (!Array.isArray(input) || !input.length) return null;
|
|
50
|
+
const norm = (b) => (b && typeof b === 'object' && b.text !== undefined
|
|
51
|
+
? { text: String(b.text), value: b.value !== undefined ? b.value : String(b.text) }
|
|
52
|
+
: { text: String(b), value: String(b) });
|
|
53
|
+
if (Array.isArray(input[0])) return input.map((r) => (Array.isArray(r) ? r : [r]).map(norm));
|
|
54
|
+
// daftar flat → susun rapi maksimal 2 tombol per baris
|
|
55
|
+
const flat = input.map(norm);
|
|
56
|
+
const rows = [];
|
|
57
|
+
for (let i = 0; i < flat.length; i += 2) rows.push(flat.slice(i, i + 2));
|
|
58
|
+
return rows;
|
|
59
|
+
}
|
|
60
|
+
const flatten = (rows) => rows.reduce((a, r) => a.concat(r), []);
|
|
61
|
+
|
|
62
|
+
/** Susun reply_markup untuk langkah ke-`idx` (jika ada tombolnya). */
|
|
63
|
+
function stepExtra(def, st, idx) {
|
|
64
|
+
const step = def.steps[idx];
|
|
65
|
+
const extra = { ...(step.opts || {}) };
|
|
66
|
+
const rows = normalizeButtons(step.buttons);
|
|
67
|
+
if (!rows) return extra;
|
|
68
|
+
if (step.inline) {
|
|
69
|
+
let n = 0;
|
|
70
|
+
extra.reply_markup = {
|
|
71
|
+
inline_keyboard: rows.map((r) => r.map((b) => ({
|
|
72
|
+
text: b.text,
|
|
73
|
+
callback_data: `wiz:${st.cb}:${idx}:${n++}`,
|
|
74
|
+
}))),
|
|
75
|
+
};
|
|
76
|
+
} else {
|
|
77
|
+
st.rk = true; // pernah memakai reply keyboard → perlu dibersihkan saat selesai
|
|
78
|
+
extra.reply_markup = {
|
|
79
|
+
keyboard: rows.map((r) => r.map((b) => ({ text: b.text }))),
|
|
80
|
+
resize_keyboard: true,
|
|
81
|
+
...(step.oneTime ? { one_time_keyboard: true } : {}),
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
return extra;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/** Tampilkan pertanyaan langkah `idx` sesuai mode ('send' | 'edit' | 'delete'). */
|
|
88
|
+
async function tampil(ctx, st, def, idx, text) {
|
|
89
|
+
const step = def.steps[idx];
|
|
90
|
+
const mode = step.mode || def.mode || 'send';
|
|
91
|
+
const extra = stepExtra(def, st, idx);
|
|
92
|
+
|
|
93
|
+
if (mode === 'edit' && st.msgId) {
|
|
94
|
+
try {
|
|
95
|
+
await ctx.api.editMessageText(st.chatId, st.msgId, text, extra);
|
|
96
|
+
return;
|
|
97
|
+
} catch (e) {
|
|
98
|
+
if (/not modified/i.test((e && (e.description || e.message)) || '')) return;
|
|
99
|
+
// pesan tak ditemukan (sudah dihapus) → jatuh ke kirim baru
|
|
100
|
+
}
|
|
101
|
+
} else if (mode === 'delete' && st.msgId) {
|
|
102
|
+
try { await ctx.api.deleteMessage(st.chatId, st.msgId); } catch { /* sudah hilang */ }
|
|
103
|
+
st.msgId = undefined;
|
|
104
|
+
}
|
|
105
|
+
const sent = await ctx.reply(text, extra);
|
|
106
|
+
if (sent && sent.message_id) { st.chatId = ctx.chatId; st.msgId = sent.message_id; }
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/** Bersihkan jejak wizard: hapus pesan tanya (cleanup) + singkirkan reply keyboard. */
|
|
110
|
+
async function bersih(ctx, st, def) {
|
|
111
|
+
if (!def) return;
|
|
112
|
+
const cleanupOn = def.cleanup !== undefined ? !!def.cleanup : (def.mode === 'delete');
|
|
113
|
+
if (cleanupOn && st.msgId) {
|
|
114
|
+
try { await ctx.api.deleteMessage(st.chatId, st.msgId); } catch { /* sudah hilang */ }
|
|
115
|
+
}
|
|
116
|
+
if (st.rk && def.removeKeyboard !== false) {
|
|
117
|
+
try {
|
|
118
|
+
await ctx.api.sendMessage(st.chatId, '\u200b', { reply_markup: { remove_keyboard: true } });
|
|
119
|
+
} catch { /* chat tak terjangkau */ }
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/** Mulai wizard dari handler mana pun (command/action/dll). */
|
|
124
|
+
async function start(ctx, id) {
|
|
125
|
+
const def = wizards.get(id);
|
|
126
|
+
if (!def) throw new Error(`wizard "${id}" belum didefinisikan`);
|
|
127
|
+
if (!ctx.session) throw new Error('telebibz: session belum aktif (lib internal)');
|
|
128
|
+
const st = { id, i: 0, ans: {}, cb: Math.random().toString(36).slice(2, 8) };
|
|
129
|
+
ctx.session[KEY] = st;
|
|
130
|
+
const s0 = def.steps[0];
|
|
131
|
+
const text = typeof s0.ask === 'function' ? await s0.ask(ctx) : s0.ask;
|
|
132
|
+
return tampil(ctx, st, def, 0, text);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/** Proses satu jawaban (teks ketikan ATAU nilai tombol) untuk langkah aktif. */
|
|
136
|
+
async function jawab(ctx, st, def, input) {
|
|
137
|
+
const step = def.steps[st.i];
|
|
138
|
+
let value = input;
|
|
139
|
+
if (step.parse) value = await step.parse(input, ctx);
|
|
140
|
+
if (step.validate) {
|
|
141
|
+
const errMsg = await step.validate(value, ctx);
|
|
142
|
+
if (errMsg) {
|
|
143
|
+
const mode = step.mode || def.mode || 'send';
|
|
144
|
+
if (mode === 'send') return ctx.reply(errMsg);
|
|
145
|
+
return tampil(ctx, st, def, st.i, errMsg); // edit/delete: ubah pesan yang sama
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
st.ans[step.key] = value;
|
|
149
|
+
st.i += 1;
|
|
150
|
+
|
|
151
|
+
if (st.i >= def.steps.length) {
|
|
152
|
+
await bersih(ctx, st, def);
|
|
153
|
+
delete ctx.session[KEY];
|
|
154
|
+
return def.done(st.ans, ctx);
|
|
155
|
+
}
|
|
156
|
+
const ns = def.steps[st.i];
|
|
157
|
+
return tampil(ctx, st, def, st.i, typeof ns.ask === 'function' ? await ns.ask(ctx) : ns.ask);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/** Batalkan wizard yang sedang berjalan secara programatis. */
|
|
161
|
+
async function cancel(ctx) {
|
|
162
|
+
const st = ctx.session && ctx.session[KEY];
|
|
163
|
+
if (!st) return false;
|
|
164
|
+
const def = wizards.get(st.id);
|
|
165
|
+
await bersih(ctx, st, def);
|
|
166
|
+
delete ctx.session[KEY];
|
|
167
|
+
if (def && def.onCancel) { await def.onCancel(ctx); return true; }
|
|
168
|
+
await ctx.reply('✖️ Sesi dibatalkan.');
|
|
169
|
+
return true;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/** Edit pesan-tanya wizard yang sedang tampil (fallback: kirim baru). */
|
|
173
|
+
async function editAsk(ctx, text, extra = {}) {
|
|
174
|
+
const st = ctx.session && ctx.session[KEY];
|
|
175
|
+
if (!st || !st.msgId) return ctx.reply(text, extra);
|
|
176
|
+
try { await ctx.api.editMessageText(st.chatId, st.msgId, text, extra); }
|
|
177
|
+
catch {
|
|
178
|
+
const sent = await ctx.reply(text, extra);
|
|
179
|
+
if (sent && sent.message_id) { st.chatId = ctx.chatId; st.msgId = sent.message_id; }
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/** Hapus pesan-tanya wizard yang sedang tampil. */
|
|
184
|
+
async function deleteAsk(ctx) {
|
|
185
|
+
const st = ctx.session && ctx.session[KEY];
|
|
186
|
+
if (!st || !st.msgId) return false;
|
|
187
|
+
try { await ctx.api.deleteMessage(st.chatId, st.msgId); } catch { /* sudah hilang */ }
|
|
188
|
+
st.msgId = undefined;
|
|
189
|
+
return true;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/** Middleware global: memproses jawaban wizard yang sedang berjalan. */
|
|
193
|
+
function middleware() {
|
|
194
|
+
return async (ctx, next) => {
|
|
195
|
+
const st = ctx.session && ctx.session[KEY];
|
|
196
|
+
if (!st) return next();
|
|
197
|
+
const def = wizards.get(st.id);
|
|
198
|
+
if (!def) { delete ctx.session[KEY]; return next(); }
|
|
199
|
+
|
|
200
|
+
/* ---- klik tombol inline (callback_query) ---- */
|
|
201
|
+
const q = ctx.callback_query;
|
|
202
|
+
if (q && typeof q.data === 'string') {
|
|
203
|
+
const m = /^wiz:([a-z0-9]+):(\d+):(\d+)$/i.exec(q.data);
|
|
204
|
+
if (m) {
|
|
205
|
+
const stale = (pesan) => ctx.answerCallbackQuery({ text: pesan, show_alert: true }).catch(() => {});
|
|
206
|
+
if (m[1] !== st.cb || Number(m[2]) !== st.i) return stale('⌛ Tombol usang — formulir sudah berpindah/berakhir.');
|
|
207
|
+
const rows = normalizeButtons(def.steps[st.i].buttons);
|
|
208
|
+
const tombol = rows && flatten(rows)[Number(m[3])];
|
|
209
|
+
if (!tombol) return stale('⌛ Tombol usang — formulir sudah berpindah/berakhir.');
|
|
210
|
+
await ctx.answerCallbackQuery().catch(() => {});
|
|
211
|
+
return jawab(ctx, st, def, tombol.value);
|
|
212
|
+
}
|
|
213
|
+
// callback lain saat wizard aktif → diamkan, wizard menunggu (konsisten non-teks)
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/* ---- jawaban teks ---- */
|
|
217
|
+
const text = ctx.message && typeof ctx.message.text === 'string' ? ctx.message.text.trim() : null;
|
|
218
|
+
if (text === null) return; // pesan non-teks (foto/stiker) — diamkan, wizard menunggu
|
|
219
|
+
|
|
220
|
+
if (def.cancelWords.has(text.toLowerCase())) {
|
|
221
|
+
await bersih(ctx, st, def);
|
|
222
|
+
delete ctx.session[KEY];
|
|
223
|
+
if (def.onCancel) return def.onCancel(ctx);
|
|
224
|
+
return ctx.reply('✖️ Sesi dibatalkan.');
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
const step = def.steps[st.i];
|
|
228
|
+
let input = text;
|
|
229
|
+
const rows = normalizeButtons(step.buttons);
|
|
230
|
+
if (rows) {
|
|
231
|
+
const hit = flatten(rows).find((b) => b.text.toLowerCase() === text.toLowerCase());
|
|
232
|
+
if (hit) input = hit.value; // tekan tombol reply → pakai nilainya
|
|
233
|
+
else if (step.onlyButtons) {
|
|
234
|
+
const pesan = step.onlyButtons === true
|
|
235
|
+
? '✋ Pilih salah satu tombol yang tersedia ya:'
|
|
236
|
+
: step.onlyButtons;
|
|
237
|
+
return tampil(ctx, st, def, st.i, pesan);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
return jawab(ctx, st, def, input);
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/** True kalau user ini sedang di tengah wizard. */
|
|
245
|
+
function active(ctx) { return Boolean(ctx.session && ctx.session[KEY]); }
|
|
246
|
+
|
|
247
|
+
module.exports = { define, get, start, middleware, active, cancel, editAsk, deleteAsk, KEY };
|
package/package.json
CHANGED
|
@@ -1,114 +1,52 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xbibzlibrary/telebibz",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "Telegram
|
|
5
|
-
"
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
"telegram-bot-api",
|
|
9
|
-
"telegram-bot-framework",
|
|
10
|
-
"nodejs",
|
|
11
|
-
"typescript",
|
|
12
|
-
"telegram-webhook",
|
|
13
|
-
"long-polling",
|
|
14
|
-
"conversation-wizard",
|
|
15
|
-
"inline-keyboard",
|
|
16
|
-
"telegram-mini-app",
|
|
17
|
-
"bot-framework"
|
|
18
|
-
],
|
|
19
|
-
"type": "module",
|
|
20
|
-
"private": false,
|
|
21
|
-
"publishConfig": {
|
|
22
|
-
"access": "public",
|
|
23
|
-
"provenance": false
|
|
24
|
-
},
|
|
3
|
+
"version": "3.1.1",
|
|
4
|
+
"description": "Library Telegram Indonesia production-grade — set fitur penuh setara grammY: proxy-api segala metode, transformer, menus, inline query, media group, throttler & auto-retry, wizard + tombol + edit/delete, session swappable, webhook, polling tahan-409. //—Xbibz Official—//",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"types": "index.d.ts",
|
|
7
|
+
"type": "commonjs",
|
|
25
8
|
"license": "MIT",
|
|
9
|
+
"author": "Xbibz Official",
|
|
26
10
|
"repository": {
|
|
27
11
|
"type": "git",
|
|
28
12
|
"url": "https://github.com/XbibzOfficial777/telebibz.git"
|
|
29
13
|
},
|
|
30
14
|
"homepage": "https://github.com/XbibzOfficial777/telebibz#readme",
|
|
31
|
-
"
|
|
32
|
-
"
|
|
33
|
-
|
|
15
|
+
"keywords": [
|
|
16
|
+
"telegram",
|
|
17
|
+
"telegram-bot",
|
|
18
|
+
"bot",
|
|
19
|
+
"grammy",
|
|
20
|
+
"telegram-api",
|
|
21
|
+
"inline-keyboard",
|
|
22
|
+
"wizard",
|
|
23
|
+
"broadcast",
|
|
24
|
+
"indonesia",
|
|
25
|
+
"nodejs",
|
|
26
|
+
"zero-dependency",
|
|
27
|
+
"tanpa-dependency"
|
|
28
|
+
],
|
|
34
29
|
"engines": {
|
|
35
|
-
"node": ">=
|
|
30
|
+
"node": ">=18"
|
|
36
31
|
},
|
|
37
|
-
"
|
|
38
|
-
"
|
|
39
|
-
"
|
|
40
|
-
"
|
|
41
|
-
"
|
|
42
|
-
"lint": "tsc -p tsconfig.json --noEmit && eslint scripts/*.mjs bin/*.mjs --no-error-on-unmatched-pattern",
|
|
43
|
-
"test": "vitest run",
|
|
44
|
-
"test:watch": "vitest",
|
|
45
|
-
"test:integration": "vitest run tests/integration/**/*.test.ts",
|
|
46
|
-
"test:e2e": "vitest run tests/e2e",
|
|
47
|
-
"test:types": "tsc -p tests/tsconfig.json --noEmit",
|
|
48
|
-
"test:examples": "tsc -p examples/tsconfig.json --noEmit",
|
|
49
|
-
"benchmark": "tsx tests/benchmark.ts",
|
|
50
|
-
"package:check": "npm run build && npm pack --dry-run",
|
|
51
|
-
"security": "npm audit --audit-level=high --package-lock-only",
|
|
52
|
-
"release:check": "node scripts/release-check.mjs",
|
|
53
|
-
"doctor": "tsx src/cli.ts doctor",
|
|
54
|
-
"start": "tsx src/cli.ts start",
|
|
55
|
-
"dev": "tsx examples/minimal.ts",
|
|
56
|
-
"prepack": "npm run build",
|
|
57
|
-
"prepublishOnly": "npm run typecheck && npm run test:types && npm run test:examples && npm run lint && npm test && npm run build && npm run security && npm run release:check"
|
|
58
|
-
},
|
|
59
|
-
"bin": {
|
|
60
|
-
"telebibz": "./bin/telebibz.mjs"
|
|
32
|
+
"dependencies": {
|
|
33
|
+
"axios": "^1.20.0",
|
|
34
|
+
"mime-types": "^3.0.2",
|
|
35
|
+
"https-proxy-agent": "^9.1.0",
|
|
36
|
+
"debug": "^4.4.3"
|
|
61
37
|
},
|
|
62
|
-
"
|
|
63
|
-
"
|
|
64
|
-
"types": "./dist/src/index.d.ts",
|
|
65
|
-
"import": "./dist/src/index.js",
|
|
66
|
-
"require": "./dist-cjs/src/index.js"
|
|
67
|
-
},
|
|
68
|
-
"./api": {
|
|
69
|
-
"types": "./dist/src/api/index.d.ts",
|
|
70
|
-
"import": "./dist/src/api/index.js",
|
|
71
|
-
"require": "./dist-cjs/src/api/index.js"
|
|
72
|
-
},
|
|
73
|
-
"./keyboard": {
|
|
74
|
-
"types": "./dist/src/keyboard/index.d.ts",
|
|
75
|
-
"import": "./dist/src/keyboard/index.js",
|
|
76
|
-
"require": "./dist-cjs/src/keyboard/index.js"
|
|
77
|
-
},
|
|
78
|
-
"./testing": {
|
|
79
|
-
"types": "./dist/src/testing.d.ts",
|
|
80
|
-
"import": "./dist/src/testing.js",
|
|
81
|
-
"require": "./dist-cjs/src/testing.js"
|
|
82
|
-
}
|
|
38
|
+
"scripts": {
|
|
39
|
+
"test": "node test/all.test.js"
|
|
83
40
|
},
|
|
84
41
|
"files": [
|
|
85
|
-
"
|
|
86
|
-
"
|
|
87
|
-
"
|
|
42
|
+
"index.js",
|
|
43
|
+
"index.d.ts",
|
|
44
|
+
"lib/",
|
|
45
|
+
"examples/",
|
|
46
|
+
"test/",
|
|
88
47
|
"README.md",
|
|
89
|
-
"README.id.md",
|
|
90
|
-
"README.zh-CN.md",
|
|
91
48
|
"LICENSE",
|
|
92
|
-
"CHANGELOG.md",
|
|
93
|
-
"SECURITY.md",
|
|
94
|
-
"CODE_OF_CONDUCT.md",
|
|
95
|
-
"CONTRIBUTING.md",
|
|
96
|
-
"CONTRIBUTION_RULES.md",
|
|
97
|
-
"GOVERNANCE.md",
|
|
98
|
-
"SUPPORT.md",
|
|
99
49
|
"NOTICE.md",
|
|
100
|
-
"
|
|
101
|
-
|
|
102
|
-
"SHOWCASE.md",
|
|
103
|
-
"assets",
|
|
104
|
-
"docs",
|
|
105
|
-
"examples"
|
|
106
|
-
],
|
|
107
|
-
"devDependencies": {
|
|
108
|
-
"@types/node": "^22.10.0",
|
|
109
|
-
"eslint": "^9.17.0",
|
|
110
|
-
"tsx": "^4.19.2",
|
|
111
|
-
"typescript": "^5.7.2",
|
|
112
|
-
"vitest": "^4.1.11"
|
|
113
|
-
}
|
|
50
|
+
"CHANGELOG.md"
|
|
51
|
+
]
|
|
114
52
|
}
|