@xbibzlibrary/telebibz 0.1.8 → 0.1.10
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/README.id.md +3 -12
- package/README.md +8 -8
- package/README.zh-CN.md +2 -11
- package/assets/readme-preview.html +2 -2
- package/dist/src/branding/terminal.js +1 -1
- package/dist/src/branding/terminal.js.map +1 -1
- package/dist/src/core/bot.d.ts +1 -4
- package/dist/src/core/bot.d.ts.map +1 -1
- package/dist/src/core/bot.js +3 -18
- package/dist/src/core/bot.js.map +1 -1
- package/dist/src/index.d.ts +0 -2
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +0 -2
- package/dist/src/index.js.map +1 -1
- package/dist/src/observability/logger.d.ts +6 -0
- package/dist/src/observability/logger.d.ts.map +1 -1
- package/dist/src/observability/logger.js +56 -11
- package/dist/src/observability/logger.js.map +1 -1
- package/dist/src/testing.d.ts.map +1 -1
- package/dist/src/testing.js +1 -9
- package/dist/src/testing.js.map +1 -1
- package/dist-cjs/src/branding/terminal.js +1 -1
- package/dist-cjs/src/core/bot.js +3 -18
- package/dist-cjs/src/index.js +0 -2
- package/dist-cjs/src/observability/logger.js +56 -11
- package/dist-cjs/src/testing.js +1 -9
- package/docs/API.id.md +7 -95
- package/docs/API.md +13 -87
- package/docs/API.zh-CN.md +7 -95
- package/package.json +1 -2
- package/APPROVAL_FEATURE.md +0 -73
- package/dist/src/approval/approval.d.ts +0 -66
- package/dist/src/approval/approval.d.ts.map +0 -1
- package/dist/src/approval/approval.js +0 -105
- package/dist/src/approval/approval.js.map +0 -1
- package/dist/src/branding/branding.d.ts +0 -17
- package/dist/src/branding/branding.d.ts.map +0 -1
- package/dist/src/branding/branding.js +0 -35
- package/dist/src/branding/branding.js.map +0 -1
- package/dist-cjs/src/approval/approval.js +0 -110
- package/dist-cjs/src/branding/branding.js +0 -39
package/dist-cjs/src/core/bot.js
CHANGED
|
@@ -9,7 +9,6 @@ const router_js_1 = require("../router/router.js");
|
|
|
9
9
|
const events_js_1 = require("./events.js");
|
|
10
10
|
const storage_js_1 = require("../storage/storage.js");
|
|
11
11
|
const plugin_js_1 = require("../plugins/plugin.js");
|
|
12
|
-
const approval_js_1 = require("../approval/approval.js");
|
|
13
12
|
const logger_js_1 = require("../observability/logger.js");
|
|
14
13
|
const terminal_js_1 = require("../branding/terminal.js");
|
|
15
14
|
class Bot {
|
|
@@ -19,7 +18,6 @@ class Bot {
|
|
|
19
18
|
plugins;
|
|
20
19
|
session;
|
|
21
20
|
services;
|
|
22
|
-
approval;
|
|
23
21
|
token;
|
|
24
22
|
logger;
|
|
25
23
|
middlewares = [];
|
|
@@ -48,7 +46,6 @@ class Bot {
|
|
|
48
46
|
},
|
|
49
47
|
});
|
|
50
48
|
this.plugins = new plugin_js_1.PluginManager(this);
|
|
51
|
-
this.approval = new approval_js_1.ApprovalGate(this.api, config.approval);
|
|
52
49
|
this.pollingOptions = {
|
|
53
50
|
timeout: config.polling?.timeout ?? 30,
|
|
54
51
|
limit: config.polling?.limit ?? 100,
|
|
@@ -71,22 +68,15 @@ class Bot {
|
|
|
71
68
|
if (this.statusValue === "initialized" || this.statusValue === "running")
|
|
72
69
|
return this;
|
|
73
70
|
this.logger.info("bot.initializing");
|
|
74
|
-
const animation = (0, terminal_js_1.startTerminalAnimation)("Connecting to Telegram and
|
|
71
|
+
const animation = (0, terminal_js_1.startTerminalAnimation)("Connecting to Telegram and initializing bot");
|
|
75
72
|
try {
|
|
76
73
|
this.me = await this.api.methods.getMe();
|
|
77
|
-
const approval = await this.approval.check({ bot: this.me });
|
|
78
|
-
if (!approval.allowed) {
|
|
79
|
-
this.statusValue = "awaiting-approval";
|
|
80
|
-
this.logger.warn("approval.pending", { botId: this.me.id, status: approval.status });
|
|
81
|
-
animation.stop("Approval request sent; waiting for developer decision");
|
|
82
|
-
return this;
|
|
83
|
-
}
|
|
84
74
|
this.statusValue = "initialized";
|
|
85
75
|
this.logger.info("bot.initialized", { botId: this.me.id, username: this.me.username });
|
|
86
76
|
await this.events.emit("bot:initialized", { bot: this });
|
|
87
77
|
await this.plugins.setup();
|
|
88
78
|
await this.plugins.start();
|
|
89
|
-
animation.stop("
|
|
79
|
+
animation.stop("Bot initialized; ready to start");
|
|
90
80
|
return this;
|
|
91
81
|
}
|
|
92
82
|
catch (error) {
|
|
@@ -99,8 +89,6 @@ class Bot {
|
|
|
99
89
|
if (options.mode !== "polling")
|
|
100
90
|
throw new Error("Use createWebhookHandler() for webhook mode.");
|
|
101
91
|
await this.init();
|
|
102
|
-
if (this.statusValue === "awaiting-approval")
|
|
103
|
-
return;
|
|
104
92
|
if (this.statusValue === "running")
|
|
105
93
|
return;
|
|
106
94
|
this.statusValue = "starting";
|
|
@@ -150,11 +138,8 @@ class Bot {
|
|
|
150
138
|
const session = await this.session.get(key) ?? {};
|
|
151
139
|
if (!this.me)
|
|
152
140
|
await this.init();
|
|
153
|
-
if (
|
|
154
|
-
if (update.callback_query)
|
|
155
|
-
await this.approval.handleCallback(update.callback_query);
|
|
141
|
+
if (!this.me)
|
|
156
142
|
return;
|
|
157
|
-
}
|
|
158
143
|
const ctx = new context_js_1.Context({ update, api: this.api, session, services: this.services });
|
|
159
144
|
await this.events.emit("update", { update });
|
|
160
145
|
if (message) {
|
package/dist-cjs/src/index.js
CHANGED
|
@@ -31,9 +31,7 @@ __exportStar(require("./utils/text.js"), exports);
|
|
|
31
31
|
__exportStar(require("./state/conversation.js"), exports);
|
|
32
32
|
__exportStar(require("./state/forms.js"), exports);
|
|
33
33
|
__exportStar(require("./state/menu.js"), exports);
|
|
34
|
-
__exportStar(require("./approval/approval.js"), exports);
|
|
35
34
|
__exportStar(require("./telegram-features.js"), exports);
|
|
36
|
-
__exportStar(require("./branding/branding.js"), exports);
|
|
37
35
|
var terminal_js_1 = require("./branding/terminal.js");
|
|
38
36
|
Object.defineProperty(exports, "buildTerminalBranding", { enumerable: true, get: function () { return terminal_js_1.buildTerminalBranding; } });
|
|
39
37
|
Object.defineProperty(exports, "printTerminalBranding", { enumerable: true, get: function () { return terminal_js_1.printTerminalBranding; } });
|
|
@@ -6,13 +6,30 @@ exports.summarizeUpdate = summarizeUpdate;
|
|
|
6
6
|
exports.createLogger = createLogger;
|
|
7
7
|
const priorities = { silent: 99, error: 0, warn: 1, info: 2, debug: 3, trace: 4 };
|
|
8
8
|
const defaultRedactKeys = ["token", "secret", "password", "authorization", "cookie", "private_key", "api_key", "npm_token", "bot_token"];
|
|
9
|
+
const ANSI = {
|
|
10
|
+
reset: "\u001b[0m",
|
|
11
|
+
dim: "\u001b[2m",
|
|
12
|
+
red: "\u001b[31m",
|
|
13
|
+
yellow: "\u001b[33m",
|
|
14
|
+
green: "\u001b[32m",
|
|
15
|
+
cyan: "\u001b[36m",
|
|
16
|
+
blue: "\u001b[34m",
|
|
17
|
+
magenta: "\u001b[35m",
|
|
18
|
+
};
|
|
9
19
|
function isObject(value) { return typeof value === "object" && value !== null; }
|
|
10
20
|
function shouldRedact(key, keys) { const normalized = key.toLowerCase().replace(/[-_]/g, ""); return keys.some((candidate) => normalized.includes(candidate.toLowerCase().replace(/[-_]/g, ""))); }
|
|
21
|
+
function redactString(value) {
|
|
22
|
+
return value
|
|
23
|
+
.replace(/\b\d{6,12}:[A-Za-z0-9_-]{20,}\b/g, "[REDACTED_TELEGRAM_TOKEN]")
|
|
24
|
+
.replace(/\bnpm_[A-Za-z0-9]{20,}\b/g, "[REDACTED_NPM_TOKEN]");
|
|
25
|
+
}
|
|
11
26
|
function safeValue(value, keys, seen = new WeakSet()) {
|
|
27
|
+
if (typeof value === "string")
|
|
28
|
+
return redactString(value);
|
|
12
29
|
if (typeof value === "bigint")
|
|
13
30
|
return `${value}n`;
|
|
14
31
|
if (value instanceof Error)
|
|
15
|
-
return { name: value.name, message: value.message, stack: value.stack };
|
|
32
|
+
return safeValue({ name: value.name, message: value.message, stack: value.stack }, keys, seen);
|
|
16
33
|
if (Array.isArray(value)) {
|
|
17
34
|
if (seen.has(value))
|
|
18
35
|
return "[Circular]";
|
|
@@ -74,29 +91,57 @@ function summarizeUpdate(update, includeContent = false) {
|
|
|
74
91
|
}
|
|
75
92
|
return summary;
|
|
76
93
|
}
|
|
77
|
-
function
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
94
|
+
function levelColor(level) {
|
|
95
|
+
if (level === "error")
|
|
96
|
+
return ANSI.red;
|
|
97
|
+
if (level === "warn")
|
|
98
|
+
return ANSI.yellow;
|
|
99
|
+
if (level === "debug")
|
|
100
|
+
return ANSI.blue;
|
|
101
|
+
if (level === "trace")
|
|
102
|
+
return ANSI.magenta;
|
|
103
|
+
return ANSI.green;
|
|
104
|
+
}
|
|
105
|
+
function formatEntry(entry, color, format) {
|
|
106
|
+
if (format === "json") {
|
|
107
|
+
const line = JSON.stringify(entry);
|
|
108
|
+
return color ? `${ANSI.dim}${line}${ANSI.reset}` : line;
|
|
109
|
+
}
|
|
110
|
+
const time = entry.timestamp.slice(11, 23);
|
|
111
|
+
const label = entry.level.toUpperCase().padEnd(5, " ");
|
|
112
|
+
const context = entry.context && Object.keys(entry.context).length ? ` ${JSON.stringify(entry.context)}` : "";
|
|
113
|
+
const line = `${time} ${label} ${entry.event}${context}`;
|
|
114
|
+
return color ? `${levelColor(entry.level)}${line}${ANSI.reset}` : line;
|
|
115
|
+
}
|
|
116
|
+
function createDefaultSink(options, redactKeys) {
|
|
117
|
+
const stream = options.stream ?? process.stdout;
|
|
118
|
+
const color = options.color ?? Boolean(stream.isTTY && !process.env.NO_COLOR);
|
|
119
|
+
const format = options.format ?? "pretty";
|
|
120
|
+
return (entry) => {
|
|
121
|
+
const safeEntry = redact(entry, redactKeys);
|
|
122
|
+
const line = formatEntry(safeEntry, color, format);
|
|
123
|
+
stream.write(`${line}\n`);
|
|
124
|
+
};
|
|
85
125
|
}
|
|
86
126
|
class Logger {
|
|
87
127
|
level;
|
|
128
|
+
format;
|
|
129
|
+
color;
|
|
88
130
|
includeUpdateContent;
|
|
89
131
|
sink;
|
|
90
132
|
redactKeys;
|
|
91
133
|
baseContext;
|
|
92
134
|
constructor(options = {}) {
|
|
93
135
|
this.level = options.level ?? "info";
|
|
136
|
+
this.format = options.format ?? "pretty";
|
|
137
|
+
const stream = options.stream ?? process.stdout;
|
|
138
|
+
this.color = options.color ?? Boolean(stream.isTTY && !process.env.NO_COLOR);
|
|
94
139
|
this.includeUpdateContent = options.includeUpdateContent ?? false;
|
|
95
|
-
this.sink = options.sink ?? defaultSink;
|
|
96
140
|
this.redactKeys = options.redactKeys ?? defaultRedactKeys;
|
|
141
|
+
this.sink = options.sink ?? createDefaultSink({ color: this.color, format: this.format, stream }, this.redactKeys);
|
|
97
142
|
this.baseContext = options.context ?? {};
|
|
98
143
|
}
|
|
99
|
-
child(context) { return new Logger({ level: this.level, sink: this.sink, includeUpdateContent: this.includeUpdateContent, redactKeys: this.redactKeys, context: { ...this.baseContext, ...context } }); }
|
|
144
|
+
child(context) { return new Logger({ level: this.level, format: this.format, color: this.color, sink: this.sink, includeUpdateContent: this.includeUpdateContent, redactKeys: this.redactKeys, context: { ...this.baseContext, ...context } }); }
|
|
100
145
|
trace(event, context) { this.write("trace", event, context); }
|
|
101
146
|
debug(event, context) { this.write("debug", event, context); }
|
|
102
147
|
info(event, context) { this.write("info", event, context); }
|
package/dist-cjs/src/testing.js
CHANGED
|
@@ -34,14 +34,6 @@ function createMockCallbackUpdate(overrides = {}) {
|
|
|
34
34
|
function createTestBot() {
|
|
35
35
|
const transport = new MockTransport();
|
|
36
36
|
transport.respond("getMe", { ok: true, result: { id: 99, is_bot: true, first_name: "TestBot", username: "test_bot" } });
|
|
37
|
-
|
|
38
|
-
async get(key) {
|
|
39
|
-
if (key !== "telebibz:approval:99")
|
|
40
|
-
return undefined;
|
|
41
|
-
return { key, botId: 99, status: "approved", nonce: "test-approved", requestedAt: Date.now() };
|
|
42
|
-
},
|
|
43
|
-
async set() { },
|
|
44
|
-
};
|
|
45
|
-
return { bot: new bot_js_1.Bot({ token: "123456:TEST_TOKEN", transport, approval: { store: approvalStore } }), transport };
|
|
37
|
+
return { bot: new bot_js_1.Bot({ token: "123456:TEST_TOKEN", transport }), transport };
|
|
46
38
|
}
|
|
47
39
|
function createMockContext(bot, update = createMockUpdate()) { return new context_js_1.Context({ update, api: bot.api, session: {}, services: {} }); }
|
package/docs/API.id.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
Dokumen ini adalah referensi API untuk `@xbibzlibrary/telebibz@0.1.4`. Seluruh signature dan perilaku yang dijelaskan di sini dipetakan dari source TypeScript yang diekspor package. Jika suatu tipe Telegram belum memiliki pemetaan parameter/result khusus, package tetap menyediakan akses runtime melalui API dinamis, tetapi tipe parameternya masih generik.
|
|
8
8
|
|
|
9
|
-
> **Status implementasi.** Dokumentasi ini menjelaskan kemampuan yang tersedia pada rilis saat ini. `JsonFileStorage`, storage Redis/SQL/Mongo berbasis driver, session/conversation berbasis Storage, cron lima field lengkap, `MenuController`,
|
|
9
|
+
> **Status implementasi.** Dokumentasi ini menjelaskan kemampuan yang tersedia pada rilis saat ini. `JsonFileStorage`, storage Redis/SQL/Mongo berbasis driver, session/conversation berbasis Storage, cron lima field lengkap, `MenuController`, terminal status output branded, structured logging dengan redaction, validasi Web App, `PaymentsClient`, dan declaration `TelegramTypes` sudah tersedia. Core method map tetap khusus untuk inferensi request/result tertentu, sedangkan `api.raw()` tersedia untuk method Telegram berikutnya.
|
|
10
10
|
|
|
11
11
|
## Instalasi dan import
|
|
12
12
|
|
|
@@ -51,7 +51,6 @@ Subpath exports yang tersedia adalah sebagai berikut.
|
|
|
51
51
|
type BotStatus =
|
|
52
52
|
| "created"
|
|
53
53
|
| "initialized"
|
|
54
|
-
| "awaiting-approval"
|
|
55
54
|
| "starting"
|
|
56
55
|
| "running"
|
|
57
56
|
| "stopping"
|
|
@@ -74,7 +73,6 @@ type BotStatus =
|
|
|
74
73
|
| `polling.allowedUpdates` | `string[]` | `[]` | Filter update Telegram. |
|
|
75
74
|
| `polling.retryDelayMs` | `number` | `500` | Delay awal ketika polling gagal. |
|
|
76
75
|
| `polling.maxRetryDelayMs` | `number` | `30000` | Batas maksimum delay reconnect. |
|
|
77
|
-
| `approval` | `ApprovalOptions` | `{}` | Hanya label, cooldown, dan storage; target developer dikunci internal. |
|
|
78
76
|
|
|
79
77
|
### Konstruktor `Bot`
|
|
80
78
|
|
|
@@ -84,7 +82,7 @@ new Bot<S extends object = Record<string, unknown>>(
|
|
|
84
82
|
): Bot<S>
|
|
85
83
|
```
|
|
86
84
|
|
|
87
|
-
Jika argumen berupa string, string tersebut dianggap sebagai token. Konstruktor membuat `ApiClient`, router, event bus, plugin manager, session storage, dan
|
|
85
|
+
Jika argumen berupa string, string tersebut dianggap sebagai token. Konstruktor membuat `ApiClient`, router, event bus, plugin manager, session storage, dan structured runtime logging yang selalu aktif. Konstruktor langsung memancarkan event `bot:created` secara asinkron.
|
|
88
86
|
|
|
89
87
|
Konstruktor melempar `Error` jika token kosong atau tidak sesuai pola token Telegram.
|
|
90
88
|
|
|
@@ -98,7 +96,6 @@ Konstruktor melempar `Error` jika token kosong atau tidak sesuai pola token Tele
|
|
|
98
96
|
| `plugins` | `PluginManager<Context<S>>` | Manajer lifecycle plugin. |
|
|
99
97
|
| `session` | `Storage<string, S>` | Session bot; dapat memakai adapter persistent. |
|
|
100
98
|
| `services` | `Record<string, unknown>` | Salinan service yang diberikan saat konstruktor. |
|
|
101
|
-
| `approval` | `ApprovalGate \| undefined` | Approval gate jika `approval` dikonfigurasi. |
|
|
102
99
|
| `token` | `string` | Token bot yang dipakai client. |
|
|
103
100
|
| `status` | `BotStatus` | Status lifecycle terkini. |
|
|
104
101
|
| `botInfo` | `User \| undefined` | Hasil `getMe()` terakhir yang tersimpan. |
|
|
@@ -157,9 +154,7 @@ Mendaftarkan plugin. Nama plugin harus unik.
|
|
|
157
154
|
init(): Promise<this>
|
|
158
155
|
```
|
|
159
156
|
|
|
160
|
-
Memanggil `getMe()`, menyimpan informasi bot,
|
|
161
|
-
|
|
162
|
-
Jika approval belum diberikan, method mengubah status menjadi `"awaiting-approval"`, mengirim notifikasi ke pemilik melalui `ApprovalGate`, dan mengembalikan bot tanpa mengaktifkan status `initialized`. Panggilan berikutnya tetap dapat dipakai setelah pemilik memberikan persetujuan.
|
|
157
|
+
Memanggil `getMe()`, menyimpan informasi bot, menginisialisasi plugin, dan mengembalikan bot yang siap untuk polling atau pemrosesan update manual.
|
|
163
158
|
|
|
164
159
|
`init()` idempoten ketika status sudah `initialized` atau `running`.
|
|
165
160
|
|
|
@@ -258,8 +253,6 @@ handleUpdate(update: Update): Promise<void>
|
|
|
258
253
|
|
|
259
254
|
Memproses satu update secara manual. Method menentukan kunci session dari `chat.id` dan `from.id`, membuat `Context`, memancarkan event `update` dan `message`, menjalankan middleware lalu router, dan menyimpan session setelah pipeline selesai.
|
|
260
255
|
|
|
261
|
-
Jika approval aktif dan bot belum diizinkan, update biasa dihentikan. Callback approval tetap diteruskan ke `ApprovalGate.handleCallback()`.
|
|
262
|
-
|
|
263
256
|
Error pipeline mengubah status bot menjadi `error`, memancarkan `bot:error`, lalu dilempar kembali.
|
|
264
257
|
|
|
265
258
|
### Contoh bot minimal
|
|
@@ -1268,89 +1261,9 @@ new Menu(id: string): Menu
|
|
|
1268
1261
|
|
|
1269
1262
|
---
|
|
1270
1263
|
|
|
1271
|
-
## 12.
|
|
1272
|
-
|
|
1273
|
-
Gerbang persetujuan selalu mengirim notifikasi branded kepada developer library ketika bot pertama kali memakai telebibz. Target chat dan pengambil keputusan dikunci secara internal; keduanya bukan bagian dari konfigurasi publik dan tidak dicetak pada notifikasi. Pesan menyertakan bot ID/username serta tombol `Izinkan` dan `Tidak Diizinkan`.
|
|
1274
|
-
|
|
1275
|
-
### `ApprovalOptions`
|
|
1276
|
-
|
|
1277
|
-
| Properti | Tipe | Default | Deskripsi |
|
|
1278
|
-
|---|---|---:|---|
|
|
1279
|
-
| `ownerLabel` | `string` | `Dev Gantenggg` | Hanya label tampilan; tidak dapat mengubah target developer. |
|
|
1280
|
-
| `notificationCooldownMs` | `number` | `600000` | Cooldown notifikasi pending. |
|
|
1281
|
-
| `store` | `ApprovalStore` | `MemoryApprovalStore` | Penyimpanan approval custom. |
|
|
1282
|
-
|
|
1283
|
-
### Tipe persetujuan
|
|
1284
|
-
|
|
1285
|
-
```ts
|
|
1286
|
-
type ApprovalStatus = "pending" | "approved" | "denied";
|
|
1287
|
-
|
|
1288
|
-
interface ApprovalRecord {
|
|
1289
|
-
key: string;
|
|
1290
|
-
botId: number;
|
|
1291
|
-
botUsername?: string;
|
|
1292
|
-
status: ApprovalStatus;
|
|
1293
|
-
nonce: string;
|
|
1294
|
-
requestedAt: number;
|
|
1295
|
-
decidedAt?: number;
|
|
1296
|
-
decidedBy?: number;
|
|
1297
|
-
notificationMessageId?: number;
|
|
1298
|
-
}
|
|
1299
|
-
|
|
1300
|
-
interface ApprovalIdentity {
|
|
1301
|
-
bot: User;
|
|
1302
|
-
}
|
|
1303
|
-
|
|
1304
|
-
interface ApprovalCheck {
|
|
1305
|
-
allowed: boolean;
|
|
1306
|
-
status: ApprovalStatus;
|
|
1307
|
-
record?: ApprovalRecord;
|
|
1308
|
-
}
|
|
1309
|
-
```
|
|
1310
|
-
|
|
1311
|
-
### `ApprovalStore`
|
|
1312
|
-
|
|
1313
|
-
```ts
|
|
1314
|
-
interface ApprovalStore {
|
|
1315
|
-
get(key: string): Promise<ApprovalRecord | undefined>;
|
|
1316
|
-
set(key: string, record: ApprovalRecord): Promise<void>;
|
|
1317
|
-
delete?(key: string): Promise<boolean>;
|
|
1318
|
-
}
|
|
1319
|
-
```
|
|
1264
|
+
## 12. Logging Terminal
|
|
1320
1265
|
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
```ts
|
|
1324
|
-
new MemoryApprovalStore(): MemoryApprovalStore
|
|
1325
|
-
```
|
|
1326
|
-
|
|
1327
|
-
Penyimpanan in-memory yang mengembalikan salinan record saat `get` dan `set`.
|
|
1328
|
-
|
|
1329
|
-
### `ApprovalGate`
|
|
1330
|
-
|
|
1331
|
-
```ts
|
|
1332
|
-
new ApprovalGate(api: ApiClient, options: ApprovalOptions): ApprovalGate
|
|
1333
|
-
```
|
|
1334
|
-
|
|
1335
|
-
| Method | Signature | Deskripsi |
|
|
1336
|
-
|---|---|---|
|
|
1337
|
-
| `check` | `check(identity): Promise<ApprovalCheck>` | Mengembalikan approved jika record berstatus approved; mengirim request baru jika belum ada atau cooldown habis. |
|
|
1338
|
-
| `handleCallback` | `handleCallback(callback): Promise<{ handled: boolean; status?: ApprovalStatus }>` | Memvalidasi nonce dan owner, lalu melakukan approve/deny. Callback yang tidak valid atau bukan approval dikembalikan sebagai `handled: false`. |
|
|
1339
|
-
| `isAllowed` | `isAllowed(botId): Promise<boolean>` | True hanya jika record approval developer tetap berstatus approved. |
|
|
1340
|
-
| `revoke` | `revoke(botId): Promise<boolean>` | Menghapus record jika store mendukung delete. |
|
|
1341
|
-
|
|
1342
|
-
Callback hanya dapat diputuskan oleh identitas developer internal; owner ID dari caller tidak digunakan oleh API produksi. Nonce acak 16 karakter heksadesimal mencegah callback lama digunakan kembali. ID developer tidak dicetak pada terminal atau notifikasi Telegram. Callback kadaluarsa menghasilkan alert kedaluwarsa.
|
|
1343
|
-
|
|
1344
|
-
```ts
|
|
1345
|
-
const bot = new Bot({
|
|
1346
|
-
token: process.env.TELEGRAM_BOT_TOKEN!,
|
|
1347
|
-
approval: { ownerLabel: "Dev Gantenggg" },
|
|
1348
|
-
});
|
|
1349
|
-
|
|
1350
|
-
// Target approval dikunci internal; object ini tidak dapat mengubahnya.
|
|
1351
|
-
```
|
|
1352
|
-
|
|
1353
|
-
---
|
|
1266
|
+
This package starts directly after Telegram API connectivity is established. The terminal prints a boxed telebibz attribution, an animated startup status when attached to a TTY, and structured colorful logs for lifecycle, API, polling, webhook, and update events. Set logger format to `json` for machine ingestion.
|
|
1354
1267
|
|
|
1355
1268
|
## 13. Utilitas Teks
|
|
1356
1269
|
|
|
@@ -1750,7 +1663,6 @@ Semua adapter mengimplementasikan kontrak `Storage<K, V>` yang sama. Package int
|
|
|
1750
1663
|
| `RedisStorage<V>` | `new RedisStorage(client, prefix?)` | Storage Redis melalui `RedisLikeClient`, termasuk TTL dan namespace. |
|
|
1751
1664
|
| `SqlStorage<V>` | `new SqlStorage(driver)` | Storage SQL melalui `SqlStorageDriver` milik aplikasi. |
|
|
1752
1665
|
| `MongoStorage<V>` | `new MongoStorage(collection)` | Storage Mongo melalui `MongoStorageCollection` milik aplikasi. |
|
|
1753
|
-
| `StorageApprovalStore` | `new StorageApprovalStore(storage)` | Record approval persistent dari `Storage<string, ApprovalRecord>` apa pun. |
|
|
1754
1666
|
|
|
1755
1667
|
`BotOptions.session` menerima `Storage<string, S>`, sehingga session dapat memakai adapter apa pun. `ConversationManager` menerima abstraction yang sama dan menyediakan `getAsync()`, `cancelAsync()`, serta `clearExpiredAsync()` untuk state conversation durable.
|
|
1756
1668
|
|
|
@@ -1773,7 +1685,7 @@ const bot = new Bot({ token: process.env.TELEGRAM_BOT_TOKEN!, session });
|
|
|
1773
1685
|
|
|
1774
1686
|
### Namespace deklarasi Telegram lengkap
|
|
1775
1687
|
|
|
1776
|
-
Package memvendorkan declaration Telegram berlisensi MIT dan mengeksposnya sebagai type-only export melalui `TelegramTypes`, serta alias seperti `TelegramUser`, `TelegramMessage`, `TelegramUpdate`, dan `TelegramApiMethods`.
|
|
1688
|
+
Package memvendorkan declaration Telegram berlisensi MIT dan mengeksposnya sebagai type-only export melalui `TelegramTypes`, serta alias seperti `TelegramUser`, `TelegramMessage`, `TelegramUpdate`, dan `TelegramApiMethods`. CLI memakai kotak Unicode berwarna dengan attribution `Library Bot Telegram By @xbibzofficial`. `Logger` menghasilkan output terminal atau JSON terstruktur dengan level, redaction, ringkasan update, dan opt-in untuk isi pesan user/callback. Declaration ini mencakup surface object, union, enum, dan method tanpa runtime dependency tambahan. Map method inti telebibz tetap khusus untuk method yang memiliki pemetaan parameter/result langsung.
|
|
1777
1689
|
|
|
1778
1690
|
---
|
|
1779
1691
|
|
|
@@ -1783,7 +1695,7 @@ Perpustakaan menargetkan Node.js `>=20`, menggunakan ESM sebagai module utama, s
|
|
|
1783
1695
|
|
|
1784
1696
|
Daftar method yang dihasilkan API dan peta method API bukanlah hal yang sama. `TelegramMethodName` mencakup 184 nama runtime, tetapi `TelegramMethodMap` hanya memiliki parameter/hasil yang bertipe khusus untuk subset yang tercantum pada bagian API client. Untuk method lain, gunakan `api.raw()` atau tambahkan deklarasi tipe di sisi aplikasi.
|
|
1785
1697
|
|
|
1786
|
-
State
|
|
1698
|
+
State session dan primitive in-memory lainnya hilang saat proses dimulai ulang kecuali aplikasi menyediakan adapter persistent. `BotOptions.session` menerima kontrak generic `Storage<string, S>`.
|
|
1787
1699
|
|
|
1788
1700
|
---
|
|
1789
1701
|
|
package/docs/API.md
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
This document is the API reference for `@xbibzlibrary/telebibz@0.1.4`. All signatures and behaviors described here are mapped from the package's exported TypeScript source. If a Telegram type does not have a specific parameter/result mapping, the package still provides runtime access via a dynamic API, but the parameter types remain generic.
|
|
7
7
|
|
|
8
|
-
> **Implementation status.** This documentation describes the capabilities available in the current release. `JsonFileStorage`, driver-based Redis/SQL/Mongo storage, storage-backed sessions/conversations, full five-field cron, `MenuController`,
|
|
8
|
+
> **Implementation status.** This documentation describes the capabilities available in the current release. `JsonFileStorage`, driver-based Redis/SQL/Mongo storage, storage-backed sessions/conversations, full five-field cron, `MenuController`, terminal branding, structured redacted logging, Web App validation, PaymentsClient, and vendored `TelegramTypes` declarations are included. The core method map remains specialized for selected request/result inference, while `api.raw()` remains available for future Telegram methods.
|
|
9
9
|
|
|
10
10
|
## Installation and import
|
|
11
11
|
|
|
@@ -50,7 +50,6 @@ The available subpath exports are as follows.
|
|
|
50
50
|
type BotStatus =
|
|
51
51
|
| "created"
|
|
52
52
|
| "initialized"
|
|
53
|
-
| "awaiting-approval"
|
|
54
53
|
| "starting"
|
|
55
54
|
| "running"
|
|
56
55
|
| "stopping"
|
|
@@ -73,7 +72,6 @@ type BotStatus =
|
|
|
73
72
|
| `polling.allowedUpdates` | `string[]` | `[]` | Telegram update filters. |
|
|
74
73
|
| `polling.retryDelayMs` | `number` | `500` | Initial delay when polling fails. |
|
|
75
74
|
| `polling.maxRetryDelayMs` | `number` | `30000` | Maximum reconnect delay. |
|
|
76
|
-
| `approval` | `ApprovalOptions` | `{}` | Optional label, cooldown, and approval storage only; the developer approval target is fixed internally. |
|
|
77
75
|
|
|
78
76
|
### Constructor `Bot`
|
|
79
77
|
|
|
@@ -83,7 +81,7 @@ new Bot<S extends object = Record<string, unknown>>(
|
|
|
83
81
|
): Bot<S>
|
|
84
82
|
```
|
|
85
83
|
|
|
86
|
-
If the argument is a string, it is treated as the token. The constructor creates `ApiClient`, router, event bus, plugin manager, session storage, and
|
|
84
|
+
If the argument is a string, it is treated as the token. The constructor creates `ApiClient`, router, event bus, plugin manager, session storage, and structured runtime logging. The constructor emits the `bot:created` event asynchronously.
|
|
87
85
|
|
|
88
86
|
The constructor throws `Error` if the token is empty or does not match the Telegram token pattern.
|
|
89
87
|
|
|
@@ -97,7 +95,6 @@ The constructor throws `Error` if the token is empty or does not match the Teleg
|
|
|
97
95
|
| `plugins` | `PluginManager<Context<S>>` | Plugin lifecycle manager. |
|
|
98
96
|
| `session` | `Storage<string, S>` | Bot session; any persistent adapter may be used. |
|
|
99
97
|
| `services` | `Record<string, unknown>` | A copy of services provided to the constructor. |
|
|
100
|
-
| `approval` | `ApprovalGate \| undefined` | Approval gate if `approval` is configured. |
|
|
101
98
|
| `token` | `string` | Bot token used by the client. |
|
|
102
99
|
| `status` | `BotStatus` | Current lifecycle status. |
|
|
103
100
|
| `botInfo` | `User \| undefined` | Last stored result of `getMe()`. |
|
|
@@ -156,9 +153,7 @@ Registers a plugin. Plugin names must be unique.
|
|
|
156
153
|
init(): Promise<this>
|
|
157
154
|
```
|
|
158
155
|
|
|
159
|
-
Calls `getMe()`, stores the bot information,
|
|
160
|
-
|
|
161
|
-
If approval has not been granted, the method sets the status to `"awaiting-approval"`, notifies the owner via the `ApprovalGate`, and returns the bot without marking it as `initialized`. Subsequent calls can be used after the owner grants approval.
|
|
156
|
+
Calls `getMe()`, stores the bot information, initializes plugins, and returns an initialized bot ready for polling or manual update handling.
|
|
162
157
|
|
|
163
158
|
`init()` is idempotent when the status is already `initialized` or `running`.
|
|
164
159
|
|
|
@@ -257,8 +252,6 @@ handleUpdate(update: Update): Promise<void>
|
|
|
257
252
|
|
|
258
253
|
Processes a single update manually. The method determines the session key from `chat.id` and `from.id`, creates a `Context`, emits `update` and `message` events, runs middleware then the router, and saves the session after the pipeline completes.
|
|
259
254
|
|
|
260
|
-
If approval is active and the bot has not been approved, normal updates are stopped. Approval callbacks are still forwarded to `ApprovalGate.handleCallback()`.
|
|
261
|
-
|
|
262
255
|
Pipeline errors set the bot status to `error`, emit `bot:error`, and then rethrow the error.
|
|
263
256
|
|
|
264
257
|
### Minimal bot example
|
|
@@ -1267,86 +1260,20 @@ new Menu(id: string): Menu
|
|
|
1267
1260
|
|
|
1268
1261
|
---
|
|
1269
1262
|
|
|
1270
|
-
## 12.
|
|
1271
|
-
|
|
1272
|
-
The always-on approval gate sends the branded notification to the library developer when a bot uses telebibz for the first time. The target chat and authorized decision-maker are fixed internally and are not part of the public configuration or notification output. The message includes the bot ID/username and provides `Izinkan` and `Tidak Diizinkan` buttons.
|
|
1273
|
-
|
|
1274
|
-
### `ApprovalOptions`
|
|
1275
|
-
|
|
1276
|
-
| Property | Type | Default | Description |
|
|
1277
|
-
|---|---|---:|---|
|
|
1278
|
-
| `ownerLabel` | `string` | `Dev Gantenggg` | Display label only; it cannot change the target developer. |
|
|
1279
|
-
| `notificationCooldownMs` | `number` | `600000` | Pending notification cooldown. |
|
|
1280
|
-
| `store` | `ApprovalStore` | `MemoryApprovalStore` | Custom approval storage. |
|
|
1263
|
+
## 12. Terminal Logging
|
|
1281
1264
|
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
```ts
|
|
1285
|
-
type ApprovalStatus = "pending" | "approved" | "denied";
|
|
1286
|
-
|
|
1287
|
-
interface ApprovalRecord {
|
|
1288
|
-
key: string;
|
|
1289
|
-
botId: number;
|
|
1290
|
-
botUsername?: string;
|
|
1291
|
-
status: ApprovalStatus;
|
|
1292
|
-
nonce: string;
|
|
1293
|
-
requestedAt: number;
|
|
1294
|
-
decidedAt?: number;
|
|
1295
|
-
decidedBy?: number;
|
|
1296
|
-
notificationMessageId?: number;
|
|
1297
|
-
}
|
|
1298
|
-
|
|
1299
|
-
interface ApprovalIdentity {
|
|
1300
|
-
bot: User;
|
|
1301
|
-
}
|
|
1302
|
-
|
|
1303
|
-
interface ApprovalCheck {
|
|
1304
|
-
allowed: boolean;
|
|
1305
|
-
status: ApprovalStatus;
|
|
1306
|
-
record?: ApprovalRecord;
|
|
1307
|
-
}
|
|
1308
|
-
```
|
|
1309
|
-
|
|
1310
|
-
### `ApprovalStore`
|
|
1311
|
-
|
|
1312
|
-
```ts
|
|
1313
|
-
interface ApprovalStore {
|
|
1314
|
-
get(key: string): Promise<ApprovalRecord | undefined>;
|
|
1315
|
-
set(key: string, record: ApprovalRecord): Promise<void>;
|
|
1316
|
-
delete?(key: string): Promise<boolean>;
|
|
1317
|
-
}
|
|
1318
|
-
```
|
|
1319
|
-
|
|
1320
|
-
### `MemoryApprovalStore`
|
|
1321
|
-
|
|
1322
|
-
```ts
|
|
1323
|
-
new MemoryApprovalStore(): MemoryApprovalStore
|
|
1324
|
-
```
|
|
1325
|
-
|
|
1326
|
-
In-memory storage that returns a copy of the record on `get` and `set`.
|
|
1327
|
-
|
|
1328
|
-
### `ApprovalGate`
|
|
1329
|
-
|
|
1330
|
-
```ts
|
|
1331
|
-
new ApprovalGate(api: ApiClient, options: ApprovalOptions): ApprovalGate
|
|
1332
|
-
```
|
|
1333
|
-
|
|
1334
|
-
| Method | Signature | Description |
|
|
1335
|
-
|---|---|---|
|
|
1336
|
-
| `check` | `check(identity): Promise<ApprovalCheck>` | Returns approved if the record status is approved; sends a new request if none exists or the cooldown has expired. |
|
|
1337
|
-
| `handleCallback` | `handleCallback(callback): Promise<{ handled: boolean; status?: ApprovalStatus }>` | Validates the nonce and owner, then performs approve/deny. Invalid callbacks or non-approval callbacks are returned as `handled: false`. |
|
|
1338
|
-
| `isAllowed` | `isAllowed(botId): Promise<boolean>` | True only if the fixed developer approval record is approved. |
|
|
1339
|
-
| `revoke` | `revoke(botId): Promise<boolean>` | Deletes the record if the store supports delete. |
|
|
1340
|
-
|
|
1341
|
-
Callbacks can only be decided by the fixed internal developer identity; caller-supplied owner IDs are ignored by the production API. A random 16-character hexadecimal nonce prevents old callbacks from being reused. The developer ID is not included in terminal or Telegram notification output. Expired callbacks produce an expiration alert.
|
|
1265
|
+
The CLI prints a colored Unicode attribution box and an animated startup status when attached to a TTY. The default logger emits compact, readable terminal lines with colored levels and structured context. Use `format: "json"` for machine ingestion, `includeUpdateContent: true` when message text or callback data is explicitly required, and a custom `sink` for application monitoring.
|
|
1342
1266
|
|
|
1343
1267
|
```ts
|
|
1344
1268
|
const bot = new Bot({
|
|
1345
1269
|
token: process.env.TELEGRAM_BOT_TOKEN!,
|
|
1346
|
-
|
|
1270
|
+
logger: {
|
|
1271
|
+
level: "debug",
|
|
1272
|
+
format: "pretty",
|
|
1273
|
+
color: true,
|
|
1274
|
+
includeUpdateContent: false,
|
|
1275
|
+
},
|
|
1347
1276
|
});
|
|
1348
|
-
|
|
1349
|
-
// The approval target is fixed internally; it cannot be changed through this object.
|
|
1350
1277
|
```
|
|
1351
1278
|
|
|
1352
1279
|
---
|
|
@@ -1750,7 +1677,6 @@ All storage adapters implement the same `Storage<K, V>` contract. The core packa
|
|
|
1750
1677
|
| `RedisStorage<V>` | `new RedisStorage(client, prefix?)` | Redis-backed storage through `RedisLikeClient`, including TTL and namespace operations. |
|
|
1751
1678
|
| `SqlStorage<V>` | `new SqlStorage(driver)` | SQL-backed storage through an application-owned `SqlStorageDriver`. |
|
|
1752
1679
|
| `MongoStorage<V>` | `new MongoStorage(collection)` | Mongo collection-backed storage through an application-owned `MongoStorageCollection`. |
|
|
1753
|
-
| `StorageApprovalStore` | `new StorageApprovalStore(storage)` | Persistent owner-approval records backed by any `Storage<string, ApprovalRecord>`. |
|
|
1754
1680
|
|
|
1755
1681
|
`BotOptions.session` accepts `Storage<string, S>`, so sessions can use any adapter. `ConversationManager` accepts the same storage abstraction and exposes `getAsync()`, `cancelAsync()`, and `clearExpiredAsync()` for durable conversation state.
|
|
1756
1682
|
|
|
@@ -1773,7 +1699,7 @@ const bot = new Bot({ token: process.env.TELEGRAM_BOT_TOKEN!, session });
|
|
|
1773
1699
|
|
|
1774
1700
|
### Complete Telegram declaration namespace
|
|
1775
1701
|
|
|
1776
|
-
The package vendors MIT-licensed Telegram declarations and exposes them as type-only exports through `TelegramTypes`, plus aliases such as `TelegramUser`, `TelegramMessage`, `TelegramUpdate`, and `TelegramApiMethods`.
|
|
1702
|
+
The package vendors MIT-licensed Telegram declarations and exposes them as type-only exports through `TelegramTypes`, plus aliases such as `TelegramUser`, `TelegramMessage`, `TelegramUpdate`, and `TelegramApiMethods`. The CLI uses a colored Unicode box with the attribution `Library Bot Telegram By @xbibzofficial`. `Logger` emits structured terminal or JSON entries with configurable levels, redaction, update summaries, and opt-in user message/callback content. These declarations cover the complete object, union, enum, and method declaration surface without adding a runtime dependency. Core telebibz method maps remain specialized for the methods with direct request/result mappings.
|
|
1777
1703
|
|
|
1778
1704
|
---
|
|
1779
1705
|
## 19. Compatibility and limitations to be aware of
|
|
@@ -1782,7 +1708,7 @@ The library targets Node.js `>=20`, uses ESM as the primary module, and also pro
|
|
|
1782
1708
|
|
|
1783
1709
|
The list of generated API methods and the API method map are not the same. `TelegramMethodName` includes 184 runtime names, but `TelegramMethodMap` only has specially-typed parameters/results for the subset listed in the API client section. For other methods, use `api.raw()` or add a type declaration on the application side.
|
|
1784
1710
|
|
|
1785
|
-
|
|
1711
|
+
Session state and other in-memory primitives are lost when the process restarts unless the application provides a persistent adapter. `BotOptions.session` accepts the generic `Storage<string, S>` contract.
|
|
1786
1712
|
|
|
1787
1713
|
---
|
|
1788
1714
|
|