@xbibzlibrary/telebibz 3.1.1 → 3.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/LICENSE +1 -1
  3. package/NOTICE.md +15 -8
  4. package/README.id.md +85 -16
  5. package/README.md +84 -16
  6. package/examples/08-rich-message.js +34 -0
  7. package/index.d.ts +300 -96
  8. package/index.js +8 -2
  9. package/lib/api.js +20 -6
  10. package/lib/composer.js +14 -3
  11. package/lib/context.js +85 -25
  12. package/lib/file.js +8 -1
  13. package/lib/inline-query.js +6 -1
  14. package/lib/logger.js +44 -14
  15. package/lib/ratelimit.js +16 -3
  16. package/lib/rich.js +170 -0
  17. package/lib/runner.js +14 -5
  18. package/lib/session.js +12 -4
  19. package/lib/telebibz.js +40 -24
  20. package/lib/telegram-methods.js +192 -0
  21. package/package.json +14 -10
  22. package/test/audit.test.js +320 -0
  23. package/test/types.test.ts +40 -0
  24. package/types/telegram-bot-api/LICENSE +21 -0
  25. package/types/telegram-bot-api/api.d.ts +22 -0
  26. package/types/telegram-bot-api/checklist.d.ts +72 -0
  27. package/types/telegram-bot-api/inline.d.ts +692 -0
  28. package/types/telegram-bot-api/langs.d.ts +193 -0
  29. package/types/telegram-bot-api/manage.d.ts +1153 -0
  30. package/types/telegram-bot-api/markup.d.ts +278 -0
  31. package/types/telegram-bot-api/message.d.ts +1557 -0
  32. package/types/telegram-bot-api/methods.d.ts +2860 -0
  33. package/types/telegram-bot-api/mod.d.ts +14 -0
  34. package/types/telegram-bot-api/passport.d.ts +163 -0
  35. package/types/telegram-bot-api/payment.d.ts +576 -0
  36. package/types/telegram-bot-api/rich.d.ts +1198 -0
  37. package/types/telegram-bot-api/settings.d.ts +120 -0
  38. package/types/telegram-bot-api/story.d.ts +89 -0
  39. package/types/telegram-bot-api/update.d.ts +86 -0
package/index.d.ts CHANGED
@@ -1,106 +1,310 @@
1
- // index.d.ts — tipe ringkas untuk autocompletion editor (autocorrect).
2
- // v3: tipe longgar (JS-first) — parity grammY.
3
- type Context = any; type Bot = any;
1
+ // Public TypeScript surface for @xbibzlibrary/telebibz.
2
+ import type { ApiMethods, Opts } from './types/telegram-bot-api/methods.js';
3
+ import type { InputRichBlock, InputRichMessage, InputRichMessageMedia } from './types/telegram-bot-api/rich.js';
4
+ export * as TelegramTypes from './types/telegram-bot-api/mod.js';
5
+ export type * from './types/telegram-bot-api/rich.js';
4
6
 
5
- declare module '@xbibzlibrary/telebibz' {
6
- type Color = 'danger' | 'success' | 'primary';
7
- type Handler = (ctx: Context) => unknown;
7
+ export type TelegramFileInput = string | File;
8
+ export type TelegramMethodName = keyof ApiMethods<TelegramFileInput>;
9
+ export type TelegramApiMethods = ApiMethods<TelegramFileInput>;
10
+ export type TelegramApiPayloads = Opts<TelegramFileInput>;
11
+ export type TelegramMethodArguments<M extends TelegramMethodName> = Parameters<ApiMethods<TelegramFileInput>[M]>;
12
+ export type TelegramMethodPayload<M extends TelegramMethodName> = Opts<TelegramFileInput>[M];
13
+ export type TelegramMethodResult<M extends TelegramMethodName> = ReturnType<ApiMethods<TelegramFileInput>[M]>;
14
+ export const TELEGRAM_API_METHODS: readonly TelegramMethodName[];
8
15
 
9
- type WizardMode = 'send' | 'edit' | 'delete';
10
- type WizardButton = string | { text: string; value?: unknown };
11
- interface WizardStep {
12
- key: string;
13
- ask: string | ((ctx: Context) => string | Promise<string>);
14
- parse?: (text: string, ctx: Context) => unknown | Promise<unknown>;
15
- validate?: (value: unknown, ctx: Context) => string | null | Promise<string | null>;
16
- opts?: Record<string, unknown>;
17
- /** Tombol pilihan: ['A','B'] | [{text,value}] | baris eksplisit [['A'],['B','C']]. */
18
- buttons?: Array<WizardButton | WizardButton[]>;
19
- /** true → tombol inline (callback), default reply keyboard. */
20
- inline?: boolean;
21
- /** true/string → tolak ketikan bebas, wajib pilih tombol. */
22
- onlyButtons?: boolean | string;
23
- /** Override mode tampilan per langkah. */
24
- mode?: WizardMode;
25
- /** Reply keyboard sekali pakai. */
26
- oneTime?: boolean;
27
- }
28
- interface WizardDef {
29
- steps: WizardStep[];
30
- done: (answers: Record<string, unknown>, ctx: Context) => unknown;
31
- cancelWords?: string[];
32
- onCancel?: (ctx: Context) => unknown;
33
- /** 'send' (default) | 'edit' satu pesan | 'delete' tanya-hapus per langkah. */
34
- mode?: WizardMode;
35
- /** Hapus pesan tanya terakhir saat wizard selesai (default: true bila mode 'delete'). */
36
- cleanup?: boolean;
37
- /** Singkirkan reply keyboard saat selesai (default: true bila tombol reply pernah dipakai). */
38
- removeKeyboard?: boolean;
39
- }
16
+ export interface ApiClient {
17
+ readonly token: string;
18
+ config: { use(transformer: (prev: (method: string, payload?: any) => Promise<any>, method: string, payload?: any) => any): ApiClient['config'] };
19
+ callApi<M extends TelegramMethodName>(method: M, ...args: TelegramMethodArguments<M>): Promise<TelegramMethodResult<M>>;
20
+ raw<M extends TelegramMethodName>(method: M, ...args: TelegramMethodArguments<M>): Promise<TelegramMethodResult<M>>;
21
+ sendRichMessage(payload: TelegramMethodPayload<'sendRichMessage'>): Promise<TelegramMethodResult<'sendRichMessage'>>;
22
+ sendLivePhoto(payload: TelegramMethodPayload<'sendLivePhoto'>): Promise<TelegramMethodResult<'sendLivePhoto'>>;
23
+ sendMessageDraft(payload: TelegramMethodPayload<'sendMessageDraft'>): Promise<TelegramMethodResult<'sendMessageDraft'>>;
24
+ sendRichMessageDraft(payload: TelegramMethodPayload<'sendRichMessageDraft'>): Promise<TelegramMethodResult<'sendRichMessageDraft'>>;
25
+ answerGuestQuery(payload: TelegramMethodPayload<'answerGuestQuery'>): Promise<TelegramMethodResult<'answerGuestQuery'>>;
26
+ editEphemeralMessageText(payload: TelegramMethodPayload<'editEphemeralMessageText'>): Promise<TelegramMethodResult<'editEphemeralMessageText'>>;
27
+ editEphemeralMessageMedia(payload: TelegramMethodPayload<'editEphemeralMessageMedia'>): Promise<TelegramMethodResult<'editEphemeralMessageMedia'>>;
28
+ editEphemeralMessageCaption(payload: TelegramMethodPayload<'editEphemeralMessageCaption'>): Promise<TelegramMethodResult<'editEphemeralMessageCaption'>>;
29
+ editEphemeralMessageReplyMarkup(payload: TelegramMethodPayload<'editEphemeralMessageReplyMarkup'>): Promise<TelegramMethodResult<'editEphemeralMessageReplyMarkup'>>;
30
+ deleteEphemeralMessage(payload: TelegramMethodPayload<'deleteEphemeralMessage'>): Promise<TelegramMethodResult<'deleteEphemeralMessage'>>;
31
+ [method: string]: any;
32
+ }
40
33
 
41
- interface TeleBibzOpts {
42
- allowedUpdates?: string[];
43
- onError?: (err: unknown, ctx?: Context) => unknown;
44
- silent?: boolean;
45
- dropPending?: boolean;
46
- session?: { initial?: () => unknown; getKey?: (ctx: Context) => string | undefined; storage?: unknown };
47
- transport?: (method: string, payload?: object) => Promise<unknown>;
48
- }
34
+ export type Handler = (ctx: Context, next?: () => Promise<unknown>) => unknown;
35
+ export type WizardMode = 'send' | 'edit' | 'delete';
36
+ export type WizardButton = string | { text: string; value?: unknown };
37
+ export type Color = 'danger' | 'success' | 'primary';
49
38
 
50
- class TeleBibz {
51
- constructor(token: string, opts?: TeleBibzOpts);
52
- api: any;
53
- botInfo: any;
54
- use(...mw: any[]): this;
55
- cmd(names: string | string[], ...mw: Handler[]): this;
56
- hears(match: string | RegExp, ...mw: Handler[]): this;
57
- action(trigs: string | RegExp | string[], ...mw: Handler[]): this;
58
- on(filter: string | string[], ...mw: Handler[]): this;
59
- start(replies: string | Handler): this;
60
- wizard(id: string, def: WizardDef, bindCommand?: boolean): this;
61
- wizardStart(ctx: Context, id: string): Promise<unknown>;
62
- wizardActive(ctx: Context): boolean;
63
- wizardCancel(ctx: Context): Promise<boolean>;
64
- wizardEdit(ctx: Context, text: string, extra?: object): Promise<unknown>;
65
- wizardDelete(ctx: Context): Promise<boolean>;
66
- broadcast(ids: Array<number | string>, pesan: any, opts?: { delay?: number }): Promise<{ terkirim: number; gagal: number; errors: Array<{ chatId: any; pesan: string }> }>;
67
- launch(opts?: Record<string, unknown>): Promise<this>;
68
- handleUpdate(update: any): Promise<void>;
69
- webhook(...args: any[]): any;
70
- stop(): Promise<void>;
71
- }
39
+ export interface WizardStep {
40
+ key: string;
41
+ ask: string | ((ctx: Context) => string | Promise<string>);
42
+ parse?: (text: unknown, ctx: Context) => unknown | Promise<unknown>;
43
+ validate?: (value: unknown, ctx: Context) => string | null | Promise<string | null>;
44
+ opts?: Record<string, unknown>;
45
+ buttons?: Array<WizardButton | WizardButton[]>;
46
+ inline?: boolean;
47
+ onlyButtons?: boolean | string;
48
+ mode?: WizardMode;
49
+ oneTime?: boolean;
50
+ }
51
+ export interface WizardDef {
52
+ steps: WizardStep[];
53
+ done: (answers: Record<string, unknown>, ctx: Context) => unknown;
54
+ cancelWords?: string[];
55
+ onCancel?: (ctx: Context) => unknown;
56
+ mode?: WizardMode;
57
+ cleanup?: boolean;
58
+ removeKeyboard?: boolean;
59
+ }
60
+ export interface SessionOptions {
61
+ initial?: () => Record<string, unknown>;
62
+ getKey?: (ctx: Context) => string | undefined;
63
+ storage?: {
64
+ read(key: string): unknown | Promise<unknown>;
65
+ write(key: string, value: Record<string, unknown>): unknown | Promise<unknown>;
66
+ delete(key: string): unknown | Promise<unknown>;
67
+ } | Map<string, Record<string, unknown>>;
68
+ }
69
+ export interface TeleBibzOptions {
70
+ allowedUpdates?: string[];
71
+ onError?: (err: unknown, ctx?: Context) => unknown;
72
+ silent?: boolean;
73
+ dropPending?: boolean;
74
+ session?: SessionOptions;
75
+ transport?: (method: string, payload?: Record<string, unknown>) => Promise<unknown>;
76
+ apiRoot?: string;
77
+ proxy?: string;
78
+ timeoutMs?: number;
79
+ headers?: Record<string, string>;
80
+ }
72
81
 
73
- function btn(text: string, callbackData: string | number, style?: Color, iconId?: string): any;
74
- function url(text: string, link: string, style?: Color, iconId?: string): any;
75
- function webApp(text: string, link: string, iconId?: string): any;
76
- function copy(text: string, value: string, iconId?: string): any;
77
- function kb(rows: any[][]): { reply_markup: { inline_keyboard: any[][] } };
78
- namespace kb {
79
- function markup(rows: any[][]): { inline_keyboard: any[][] };
80
- function confirm(yesData: string, noData: string, labelYes?: string, labelNo?: string): any;
81
- }
82
+ export class Context {
83
+ constructor(update: any, api: any, me?: any);
84
+ update: any;
85
+ api: ApiClient;
86
+ me?: any;
87
+ msg?: any;
88
+ chat?: any;
89
+ from?: any;
90
+ chatId?: number | string;
91
+ msgId?: number;
92
+ guestQueryId?: string;
93
+ session: Record<string, any>;
94
+ match?: string;
95
+ reply(text: string, extra?: object): Promise<any>;
96
+ replyWithRichMessage(content: InputRichMessage<TelegramFileInput>, extra?: object): Promise<any>;
97
+ replyWithLivePhoto(livePhoto: TelegramFileInput, photo: TelegramFileInput, extra?: object): Promise<any>;
98
+ replyEphemeral(text: string, receiverUserId: number, extra?: object): Promise<any>;
99
+ sendMessageDraft(draftId: number, text: string, extra?: object): Promise<any>;
100
+ sendRichMessageDraft(draftId: number, content: TelegramMethodPayload<'sendRichMessageDraft'>['rich_message'], extra?: object): Promise<any>;
101
+ replyWithHTML(text: string, extra?: object): Promise<any>;
102
+ replyWithMarkdown(text: string, extra?: object): Promise<any>;
103
+ replyWithPhoto(photo: any, extra?: object): Promise<any>;
104
+ replyWithVideo(video: any, extra?: object): Promise<any>;
105
+ replyWithAudio(audio: any, extra?: object): Promise<any>;
106
+ replyWithDocument(document: any, extra?: object): Promise<any>;
107
+ replyWithAnimation(animation: any, extra?: object): Promise<any>;
108
+ replyWithVoice(voice: any, extra?: object): Promise<any>;
109
+ replyWithVideoNote(videoNote: any, extra?: object): Promise<any>;
110
+ replyWithSticker(sticker: any, extra?: object): Promise<any>;
111
+ replyWithMediaGroup(media: any[], extra?: object): Promise<any>;
112
+ replyWithLocation(latitude: number, longitude: number, extra?: object): Promise<any>;
113
+ replyWithVenue(latitude: number, longitude: number, title: string, address: string, extra?: object): Promise<any>;
114
+ replyWithContact(phone: string, firstName: string, extra?: object): Promise<any>;
115
+ replyWithPoll(question: string, options: any[], extra?: object): Promise<any>;
116
+ replyWithDice(emoji?: string, extra?: object): Promise<any>;
117
+ replyWithInvoice(title: string, description: string, payload: string, currency: string, prices: any[], extra?: object): Promise<any>;
118
+ replyWithChatAction(action?: string, extra?: object): Promise<any>;
119
+ forwardMessage(to: number | string, from?: number | string, messageId?: number, extra?: object): Promise<any>;
120
+ copyMessage(to: number | string, from?: number | string, messageId?: number, extra?: object): Promise<any>;
121
+ editMessageText(text: string, extra?: object): Promise<any>;
122
+ editRichMessage(content: InputRichMessage<TelegramFileInput>, extra?: object): Promise<any>;
123
+ editEphemeralMessageText(receiverUserId: number, ephemeralMessageId: number, text: string, extra?: object): Promise<any>;
124
+ editEphemeralRichMessage(receiverUserId: number, ephemeralMessageId: number, content: InputRichMessage<TelegramFileInput>, extra?: object): Promise<any>;
125
+ editEphemeralMessageMedia(receiverUserId: number, ephemeralMessageId: number, media: any, extra?: object): Promise<any>;
126
+ editEphemeralMessageCaption(receiverUserId: number, ephemeralMessageId: number, extra?: object): Promise<any>;
127
+ editEphemeralMessageReplyMarkup(receiverUserId: number, ephemeralMessageId: number, extra?: object): Promise<any>;
128
+ deleteEphemeralMessage(receiverUserId: number, ephemeralMessageId: number): Promise<any>;
129
+ editMessageCaption(extra?: object): Promise<any>;
130
+ editMessageMedia(media: any, extra?: object): Promise<any>;
131
+ editMessageReplyMarkup(extra?: object): Promise<any>;
132
+ deleteMessage(chatId?: number | string, messageId?: number): Promise<any>;
133
+ deleteMessages(ids: number[]): Promise<any>;
134
+ react(emoji?: string, extra?: object): Promise<any>;
135
+ answerCallbackQuery(extra?: object | string): Promise<any>;
136
+ answerInlineQuery(results: any[], extra?: object): Promise<any>;
137
+ answerGuestQuery(result: any): Promise<any>;
138
+ getFile(): Promise<any>;
139
+ downloadFile(dest: string): Promise<string>;
140
+ [key: string]: any;
141
+ }
82
142
 
83
- const wizard: {
84
- define: (id: string, def: WizardDef) => string;
85
- start: (ctx: Context, id: string) => Promise<unknown>;
86
- active: (ctx: Context) => boolean;
87
- cancel: (ctx: Context) => Promise<boolean>;
88
- editAsk: (ctx: Context, text: string, extra?: object) => Promise<unknown>;
89
- deleteAsk: (ctx: Context) => Promise<boolean>;
90
- KEY: string;
91
- };
143
+ export class Composer {
144
+ use(...middleware: any[]): this;
145
+ on(filter: string | string[], ...middleware: Handler[]): this;
146
+ hears(match: string | RegExp, ...middleware: Handler[]): this;
147
+ command(names: string | string[], ...middleware: Handler[]): this;
148
+ callbackQuery(triggers: string | RegExp | Array<string | RegExp>, ...middleware: Handler[]): this;
149
+ filter(predicate: (ctx: Context) => unknown, ...middleware: Handler[]): Composer;
150
+ drop(predicate: (ctx: Context) => unknown, ...middleware: Handler[]): Composer;
151
+ branch(predicate: (ctx: Context) => unknown, yes: any, no: any): this;
152
+ route(router: string | ((ctx: Context) => unknown), routes: Record<string, any>): this;
153
+ lazy(factory: (ctx: Context) => any): this;
154
+ fork(...middleware: Handler[]): this;
155
+ errorBoundary(handler: (err: BotError, next: () => Promise<unknown>) => unknown, ...middleware: Handler[]): Composer;
156
+ middleware(): Handler;
157
+ run(ctx: Context, next?: () => Promise<unknown>): Promise<unknown>;
158
+ }
159
+ export class BotError extends Error { error: unknown; ctx: Context; }
92
160
 
93
- function humanize(err: unknown): { pesan: string; saran: string | null; method?: string; code?: number };
94
- const log: { info: Function; ok: Function; warn: Function; error: Function; banner: Function };
95
- const say: { html: (text: string, extra?: object) => object };
161
+ export class TeleBibz {
162
+ constructor(token: string, opts?: TeleBibzOptions);
163
+ api: ApiClient;
164
+ botInfo?: any;
165
+ use(...middleware: Handler[]): this;
166
+ cmd(names: string | string[], ...middleware: Handler[]): this;
167
+ hears(match: string | RegExp, ...middleware: Handler[]): this;
168
+ action(triggers: string | RegExp | Array<string | RegExp>, ...middleware: Handler[]): this;
169
+ on(filter: string | string[], ...middleware: Handler[]): this;
170
+ start(replies: string | Handler): this;
171
+ wizard(id: string, def: WizardDef, bindCommand?: boolean): this;
172
+ wizardStart(ctx: Context, id: string): Promise<unknown>;
173
+ wizardActive(ctx: Context): boolean;
174
+ wizardCancel(ctx: Context): Promise<boolean>;
175
+ wizardEdit(ctx: Context, text: string, extra?: object): Promise<unknown>;
176
+ wizardDelete(ctx: Context): Promise<boolean>;
177
+ broadcast(ids: Array<number | string>, message: any, opts?: { delay?: number }): Promise<{ terkirim: number; gagal: number; errors: Array<{ chatId: any; pesan: string }> }>;
178
+ init(): Promise<any>;
179
+ launch(opts?: Record<string, unknown>): Promise<this>;
180
+ handleUpdate(update: any): Promise<void>;
181
+ webhook(opts?: { secretToken?: string; maxBodyBytes?: number }): (req: any, res: any) => Promise<void>;
182
+ stop(): void;
183
+ readonly runPromise?: Promise<void>;
184
+ }
185
+ export { TeleBibz as Bot };
96
186
 
97
- class File { constructor(src: any, filename?: string, type?: string); src: any; filename: string; data(): Promise<Buffer>; }
98
- const InputFile: typeof File;
99
- const InlineKeyboard: any;
100
- const Keyboard: any;
101
- class ApiError extends Error { description: string; error_code?: number; method?: string; payload?: any; }
102
- const Composer: any; const BotError: any; const session: any; const Api: any;
187
+ export function session(opts?: SessionOptions): Handler;
188
+ export function btn(text: string, callbackData: string | number, style?: Color, iconId?: string): any;
189
+ export function url(text: string, link: string, style?: Color, iconId?: string): any;
190
+ export function webApp(text: string, link: string, iconId?: string): any;
191
+ export function copy(text: string, value: string, iconId?: string): any;
192
+ export function kb(rows: any[][]): { reply_markup: { inline_keyboard: any[][] } };
193
+ export namespace kb {
194
+ function markup(rows: any[][]): { inline_keyboard: any[][] };
195
+ function confirm(yesData: string, noData: string, labelYes?: string, labelNo?: string): any;
196
+ }
197
+ export class InlineKeyboard {
198
+ constructor(rows?: any[][]);
199
+ text(text: string, data: string, style?: Color, iconId?: string): this;
200
+ url(text: string, link: string, style?: Color, iconId?: string): this;
201
+ webApp(text: string, link: string, iconId?: string): this;
202
+ copy(text: string, value: string, iconId?: string): this;
203
+ row(): this;
204
+ build(): { reply_markup: { inline_keyboard: any[][] } };
205
+ }
206
+ export class Keyboard {
207
+ text(text: string): this;
208
+ requestContact(text: string): this;
209
+ requestLocation(text: string): this;
210
+ row(): this;
211
+ resized(value?: boolean): this;
212
+ oneTime(value?: boolean): this;
213
+ build(): any;
214
+ }
215
+
216
+ export class Menu extends Composer {
217
+ constructor(id: string);
218
+ text(label: string, handler?: Handler): this;
219
+ url(label: string, link: string, opts?: object): this;
220
+ webApp(label: string, link: string): this;
221
+ submenu(label: string, targetId: string): this;
222
+ back(label?: string, parentId?: string): this;
223
+ row(): this;
224
+ render(ctx: Context): Promise<any>;
225
+ }
226
+ export class MenuContainer extends Composer {
227
+ create(id: string): Menu;
228
+ get(id: string): Menu | undefined;
103
229
  }
104
230
 
105
- import { Menu as _M } from './lib/menus';
106
- export {};
231
+ export class File {
232
+ constructor(src: any, filename?: string, type?: string);
233
+ src: any;
234
+ filename: string;
235
+ type?: string;
236
+ data(): Promise<Uint8Array>;
237
+ }
238
+ export class InputFile extends File {}
239
+ export const InputMediaBuilder: {
240
+ photo(media: any, extra?: object): any;
241
+ video(media: any, extra?: object): any;
242
+ livePhoto(media: any, photo: any, extra?: object): any;
243
+ document(media: any, extra?: object): any;
244
+ audio(media: any, extra?: object): any;
245
+ animation(media: any, extra?: object): any;
246
+ };
247
+ export const InputPaidMediaBuilder: {
248
+ photo(media: any, extra?: object): any;
249
+ video(media: any, extra?: object): any;
250
+ livePhoto(media: any, photo: any, extra?: object): any;
251
+ };
252
+ export class RichMessageBuilder {
253
+ html(value: string): this;
254
+ markdown(value: string): this;
255
+ blocks(value?: InputRichBlock<TelegramFileInput>[]): this;
256
+ add(...blocks: InputRichBlock<TelegramFileInput>[]): this;
257
+ media(items: InputRichMessageMedia<TelegramFileInput>[]): this;
258
+ rtl(value?: boolean): this;
259
+ skipEntityDetection(value?: boolean): this;
260
+ build(): InputRichMessage<TelegramFileInput>;
261
+ buildDraft(): TelegramMethodPayload<'sendRichMessageDraft'>['rich_message'];
262
+ }
263
+ export const rich: {
264
+ html(html: string, options?: Partial<InputRichMessage<TelegramFileInput>>): InputRichMessage<TelegramFileInput>;
265
+ markdown(markdown: string, options?: Partial<InputRichMessage<TelegramFileInput>>): InputRichMessage<TelegramFileInput>;
266
+ blocks(blocks: InputRichBlock<TelegramFileInput>[], options?: Partial<InputRichMessage<TelegramFileInput>>): InputRichMessage<TelegramFileInput>;
267
+ draftHtml(html: string, options?: Partial<InputRichMessage<TelegramFileInput>>): TelegramMethodPayload<'sendRichMessageDraft'>['rich_message'];
268
+ draftMarkdown(markdown: string, options?: Partial<InputRichMessage<TelegramFileInput>>): TelegramMethodPayload<'sendRichMessageDraft'>['rich_message'];
269
+ draftBlocks(blocks: InputRichBlock<TelegramFileInput>[], options?: Partial<InputRichMessage<TelegramFileInput>>): TelegramMethodPayload<'sendRichMessageDraft'>['rich_message'];
270
+ block(type: string, props?: Record<string, unknown>): InputRichBlock<TelegramFileInput>;
271
+ [builder: string]: (...args: any[]) => any;
272
+ };
273
+ export function inputRichMessage(content: Partial<InputRichMessage<TelegramFileInput>>, options?: Partial<InputRichMessage<TelegramFileInput>>): InputRichMessage<TelegramFileInput>;
274
+
275
+ export function makeApi(token: string, transport?: TeleBibzOptions['transport'], transportOpts?: TeleBibzOptions): ApiClient;
276
+ export function createTransport(token: string, opts?: { apiRoot?: string; proxy?: string; timeoutMs?: number; headers?: Record<string, string> }): TeleBibzOptions['transport'];
277
+ export class ApiError extends Error {
278
+ description: string;
279
+ error_code?: number;
280
+ method?: string;
281
+ payload?: any;
282
+ parameters: Record<string, any>;
283
+ }
284
+ export function autoRetry(opts?: { maxRetry?: number; baseDelayMs?: number }): Function;
285
+ export function throttler(opts?: { perSecond?: number }): Function;
286
+ export function limiter(opts?: { windowMs?: number; limit?: number; onExceeded?: Handler }): Handler;
287
+ export function broadcast(api: any, ids: Array<number | string>, message: any, opts?: { delay?: number }): Promise<any>;
288
+ export function matchInlineQuery(trigger: string | RegExp): (ctx: Context) => boolean;
289
+ export const iq: Record<string, (...args: any[]) => any>;
290
+ export function humanize(error: unknown): { pesan: string; saran: string | null; method?: string; code?: number | string };
291
+ export const wizard: {
292
+ define(id: string, def: WizardDef): string;
293
+ get(id: string): WizardDef | undefined;
294
+ start(ctx: Context, id: string): Promise<unknown>;
295
+ active(ctx: Context): boolean;
296
+ cancel(ctx: Context): Promise<boolean>;
297
+ editAsk(ctx: Context, text: string, extra?: object): Promise<unknown>;
298
+ deleteAsk(ctx: Context): Promise<boolean>;
299
+ middleware(): Handler;
300
+ KEY: string;
301
+ };
302
+ export const log: {
303
+ info(...args: any[]): void;
304
+ ok(...args: any[]): void;
305
+ warn(...args: any[]): void;
306
+ error(...args: any[]): void;
307
+ paint(code: string, text: unknown): string;
308
+ banner(title: string, rows?: string[], developer?: string): void;
309
+ };
310
+ export const say: { html(text: string, extra?: object): object };
package/index.js CHANGED
@@ -4,7 +4,9 @@
4
4
 
5
5
  const { TeleBibz } = require('./lib/telebibz');
6
6
  const { ApiError, createTransport } = require('./lib/net');
7
- const { File, InputFile, InputMediaBuilder } = require('./lib/file');
7
+ const { File, InputFile, InputMediaBuilder, InputPaidMediaBuilder } = require('./lib/file');
8
+ const { rich, RichMessageBuilder, inputRichMessage } = require('./lib/rich');
9
+ const { TELEGRAM_API_METHODS } = require('./lib/telegram-methods');
8
10
  const { btn, url, webApp, copy, kb, InlineKeyboard, Keyboard } = require('./lib/keyboard');
9
11
  const wizard = require('./lib/wizard');
10
12
  const { humanize } = require('./lib/errors');
@@ -32,7 +34,11 @@ module.exports = {
32
34
  // percakapan
33
35
  wizard,
34
36
  // file & media
35
- File, InputFile, InputMediaBuilder,
37
+ File, InputFile, InputMediaBuilder, InputPaidMediaBuilder,
38
+ // Rich Messages (Bot API 10.3)
39
+ rich, RichMessageBuilder, inputRichMessage,
40
+ // complete raw Bot API method registry (185 methods)
41
+ TELEGRAM_API_METHODS,
36
42
  // api & transport
37
43
  makeApi, createTransport, ApiError,
38
44
  // anti-spam & keandalan
package/lib/api.js CHANGED
@@ -11,10 +11,12 @@ class ApiConfig {
11
11
  }
12
12
 
13
13
  class ApiBase {
14
- constructor(token, transport) {
14
+ constructor(token, transport, transportOpts = {}) {
15
15
  this.token = token;
16
+ this.transportOpts = transportOpts;
17
+ this.apiRoot = (transportOpts.apiRoot || 'https://api.telegram.org').replace(/\/$/, '');
16
18
  this.config = new ApiConfig();
17
- this._base = transport || createTransport(token, {});
19
+ this._base = transport || createTransport(token, transportOpts);
18
20
  this.raw = (method, payload = {}) => this.callApi(method, payload);
19
21
  }
20
22
 
@@ -34,6 +36,18 @@ class ApiBase {
34
36
 
35
37
  /* ---- pesan ---- */
36
38
  sendMessage(chat_id, text, extra = {}) { return this.callApi('sendMessage', { chat_id, text, ...extra }); }
39
+
40
+ // Bot API 10.x rich content, streaming drafts, guest queries and ephemeral messages.
41
+ sendRichMessage(payload) { return this.callApi('sendRichMessage', payload); }
42
+ sendLivePhoto(payload) { return this.callApi('sendLivePhoto', payload); }
43
+ sendMessageDraft(payload) { return this.callApi('sendMessageDraft', payload); }
44
+ sendRichMessageDraft(payload) { return this.callApi('sendRichMessageDraft', payload); }
45
+ answerGuestQuery(payload) { return this.callApi('answerGuestQuery', payload); }
46
+ editEphemeralMessageText(payload) { return this.callApi('editEphemeralMessageText', payload); }
47
+ editEphemeralMessageMedia(payload) { return this.callApi('editEphemeralMessageMedia', payload); }
48
+ editEphemeralMessageCaption(payload) { return this.callApi('editEphemeralMessageCaption', payload); }
49
+ editEphemeralMessageReplyMarkup(payload) { return this.callApi('editEphemeralMessageReplyMarkup', payload); }
50
+ deleteEphemeralMessage(payload) { return this.callApi('deleteEphemeralMessage', payload); }
37
51
  forwardMessage(chat_id, from_chat_id, message_id, extra = {}) { return this.callApi('forwardMessage', { chat_id, from_chat_id, message_id, ...extra }); }
38
52
  forwardMessages(chat_id, from_chat_id, message_ids, extra = {}) { return this.callApi('forwardMessages', { chat_id, from_chat_id, message_ids, ...extra }); }
39
53
  copyMessage(chat_id, from_chat_id, message_id, extra = {}) { return this.callApi('copyMessage', { chat_id, from_chat_id, message_id, ...extra }); }
@@ -71,7 +85,7 @@ class ApiBase {
71
85
  const f = await this.getFile(file_id);
72
86
  const axios = require('axios');
73
87
  const fs = require('fs');
74
- const url = `https://api.telegram.org/file/bot${this.token}/${f.file_path}`;
88
+ const url = `${this.apiRoot}/file/bot${this.token}/${f.file_path}`;
75
89
  const res = await axios.get(url, { responseType: 'stream', ...axiosOpts });
76
90
  const out = fs.createWriteStream(dest);
77
91
  await new Promise((ok, no) => { res.data.pipe(out); out.on('finish', ok); out.on('error', no); res.data.on('error', no); });
@@ -136,13 +150,13 @@ class ApiBase {
136
150
  * Implementasi: kalau nama ada di ApiBase, pakai definisi resminya; kalau
137
151
  * tidak, fallback jadi satu-argumen-payload.
138
152
  */
139
- function makeApi(token, transport) {
140
- const base = new ApiBase(token, transport);
153
+ function makeApi(token, transport, transportOpts = {}) {
154
+ const base = new ApiBase(token, transport, transportOpts);
141
155
  return new Proxy(base, {
142
156
  get(target, prop, recv) {
143
157
  const v = Reflect.get(target, prop, recv);
144
158
  if (v !== undefined) return typeof v === 'function' ? v.bind(target) : v;
145
- if (typeof prop === 'string' && /^[a-z][a-zA-Z0-9]*$/.test(prop)) {
159
+ if (typeof prop === 'string' && !['then', 'catch', 'finally'].includes(prop) && /^[a-z][a-zA-Z0-9]*$/.test(prop)) {
146
160
  return (payload = {}) => target.callApi(prop, payload);
147
161
  }
148
162
  return undefined;
package/lib/composer.js CHANGED
@@ -8,6 +8,7 @@ const UPDATE_FIELDS = {
8
8
  message: (u) => u.message, edited_message: (u) => u.edited_message,
9
9
  channel_post: (u) => u.channel_post, edited_channel_post: (u) => u.edited_channel_post,
10
10
  business_message: (u) => u.business_message, edited_business_message: (u) => u.edited_business_message,
11
+ deleted_business_messages: (u) => u.deleted_business_messages, guest_message: (u) => u.guest_message,
11
12
  callback_query: (u) => u.callback_query, inline_query: (u) => u.inline_query,
12
13
  chat_join_request: (u) => u.chat_join_request, chat_member: (u) => u.chat_member,
13
14
  my_chat_member: (u) => u.my_chat_member, message_reaction: (u) => u.message_reaction,
@@ -15,6 +16,8 @@ const UPDATE_FIELDS = {
15
16
  business_connection: (u) => u.business_connection, poll: (u) => u.poll, poll_answer: (u) => u.poll_answer,
16
17
  chosen_inline_result: (u) => u.chosen_inline_result, shipping_query: (u) => u.shipping_query,
17
18
  pre_checkout_query: (u) => u.pre_checkout_query, purchased_paid_media: (u) => u.purchased_paid_media,
19
+ chat_boost: (u) => u.chat_boost, removed_chat_boost: (u) => u.removed_chat_boost,
20
+ stopped_message_generation: (u) => u.stopped_message_generation,
18
21
  };
19
22
  const MSG_PROPS = {
20
23
  text: (m) => typeof m.text === 'string', caption: (m) => typeof m.caption === 'string',
@@ -28,7 +31,6 @@ const MSG_PROPS = {
28
31
  via_bot: (m) => !!m.via_bot, reply_to_message: (m) => !!m.reply_to_message, entities: (m) => Array.isArray(m.entities),
29
32
  media: (m) => Array.isArray(m.photo) || !!m.video || !!m.document || !!m.audio,
30
33
  data: () => false, // khusus callback_query ditangani di bawah
31
- successful_payment: (m) => !!m.successful_payment,
32
34
  };
33
35
 
34
36
  /** filter 'message:photo', ':text', 'callback_query': → fungsi (ctx) => boolean */
@@ -69,7 +71,12 @@ class Composer {
69
71
  on(filter, ...mw) { [].concat(filter).forEach((f) => this.stack.push({ match: compileFilter(f), fns: mw })); return this; }
70
72
  hears(re, ...mw) {
71
73
  [].concat(re).forEach((r) => this.stack.push({
72
- match: (ctx) => { const m = msgOf(ctx.update); const t = m && (m.text || m.caption || ''); return !!t && r.test(t); },
74
+ match: (ctx) => {
75
+ const m = msgOf(ctx.update); const t = m && (m.text || m.caption || '');
76
+ if (!t) return false;
77
+ if (r instanceof RegExp) r.lastIndex = 0;
78
+ return r.test(t);
79
+ },
73
80
  fns: mw,
74
81
  }));
75
82
  return this;
@@ -97,7 +104,11 @@ class Composer {
97
104
  match: (ctx) => {
98
105
  const q = ctx.callback_query || ctx.update.callback_query;
99
106
  if (!q || typeof q.data !== 'string') return false;
100
- return list.some((t) => t instanceof RegExp ? t.test(q.data) : String(t) === q.data);
107
+ return list.some((t) => {
108
+ if (!(t instanceof RegExp)) return String(t) === q.data;
109
+ t.lastIndex = 0;
110
+ return t.test(q.data);
111
+ });
101
112
  },
102
113
  fns: mw,
103
114
  });