gramio 0.0.50 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/bot.js DELETED
@@ -1,824 +0,0 @@
1
- "use strict";
2
- var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
3
- function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
4
- var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
5
- var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
6
- var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
7
- var _, done = false;
8
- for (var i = decorators.length - 1; i >= 0; i--) {
9
- var context = {};
10
- for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
11
- for (var p in contextIn.access) context.access[p] = contextIn.access[p];
12
- context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
13
- var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
14
- if (kind === "accessor") {
15
- if (result === void 0) continue;
16
- if (result === null || typeof result !== "object") throw new TypeError("Object expected");
17
- if (_ = accept(result.get)) descriptor.get = _;
18
- if (_ = accept(result.set)) descriptor.set = _;
19
- if (_ = accept(result.init)) initializers.unshift(_);
20
- }
21
- else if (_ = accept(result)) {
22
- if (kind === "field") initializers.unshift(_);
23
- else descriptor[key] = _;
24
- }
25
- }
26
- if (target) Object.defineProperty(target, contextIn.name, descriptor);
27
- done = true;
28
- };
29
- var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
30
- var useValue = arguments.length > 2;
31
- for (var i = 0; i < initializers.length; i++) {
32
- value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
33
- }
34
- return useValue ? value : void 0;
35
- };
36
- var __importDefault = (this && this.__importDefault) || function (mod) {
37
- return (mod && mod.__esModule) ? mod : { "default": mod };
38
- };
39
- Object.defineProperty(exports, "__esModule", { value: true });
40
- exports.Bot = void 0;
41
- const promises_1 = __importDefault(require("node:fs/promises"));
42
- const node_stream_1 = require("node:stream");
43
- const callback_data_1 = require("@gramio/callback-data");
44
- const contexts_1 = require("@gramio/contexts");
45
- const files_1 = require("@gramio/files");
46
- const format_1 = require("@gramio/format");
47
- const debug_1 = __importDefault(require("debug"));
48
- const inspectable_1 = require("inspectable");
49
- const errors_1 = require("./errors");
50
- const plugin_1 = require("./plugin");
51
- const updates_1 = require("./updates");
52
- const $debugger = (0, debug_1.default)("gramio");
53
- const debug$api = $debugger.extend("api");
54
- /** Bot instance
55
- *
56
- * @example
57
- * ```ts
58
- * import { Bot } from "gramio";
59
- *
60
- * const bot = new Bot("") // put you token here
61
- * .command("start", (context) => context.send("Hi!"))
62
- * .onStart(console.log);
63
- *
64
- * bot.start();
65
- * ```
66
- */
67
- let Bot = (() => {
68
- let _classDecorators = [(0, inspectable_1.Inspectable)({
69
- serialize: () => ({}),
70
- })];
71
- let _classDescriptor;
72
- let _classExtraInitializers = [];
73
- let _classThis;
74
- var Bot = class {
75
- static { _classThis = this; }
76
- static {
77
- const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0;
78
- __esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
79
- Bot = _classThis = _classDescriptor.value;
80
- if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
81
- __runInitializers(_classThis, _classExtraInitializers);
82
- }
83
- _ = {
84
- /** @internal. Remap generic */
85
- derives: {},
86
- };
87
- /** @internal. Remap generic */
88
- __Derives;
89
- filters = {
90
- context: (name) => (context) => context.is(name),
91
- };
92
- /** Options provided to instance */
93
- options;
94
- /** Bot data (filled in when calling bot.init/bot.start) */
95
- info;
96
- /**
97
- * Send API Request to Telegram Bot API
98
- *
99
- * @example
100
- * ```ts
101
- * const response = await bot.api.sendMessage({
102
- * chat_id: "@gramio_forum",
103
- * text: "some text",
104
- * });
105
- * ```
106
- *
107
- * [Documentation](https://gramio.dev/bot-api.html)
108
- */
109
- api = new Proxy({}, {
110
- get: (_target, method) =>
111
- // @ts-expect-error
112
- // biome-ignore lint/suspicious/noAssignInExpressions: <explanation>
113
- (_target[method] ??= (args) => this._callApi(method, args)),
114
- });
115
- lazyloadPlugins = [];
116
- dependencies = [];
117
- errorsDefinitions = {
118
- TELEGRAM: errors_1.TelegramError,
119
- };
120
- errorHandler(context, error) {
121
- if (!this.hooks.onError.length)
122
- throw error;
123
- return this.runImmutableHooks("onError", {
124
- context,
125
- //@ts-expect-error ErrorKind exists if user register error-class with .error("kind", SomeError);
126
- kind: error.constructor[errors_1.ErrorKind] ?? "UNKNOWN",
127
- error: error,
128
- });
129
- }
130
- /** This instance handle updates */
131
- updates = new updates_1.Updates(this, this.errorHandler.bind(this));
132
- hooks = {
133
- preRequest: [],
134
- onResponse: [],
135
- onResponseError: [],
136
- onError: [],
137
- onStart: [],
138
- onStop: [],
139
- };
140
- constructor(tokenOrOptions, options) {
141
- const token = typeof tokenOrOptions === "string"
142
- ? tokenOrOptions
143
- : tokenOrOptions?.token;
144
- if (!token || typeof token !== "string")
145
- throw new Error(`Token is ${typeof token} but it should be a string!`);
146
- this.options = {
147
- ...(typeof tokenOrOptions === "object" ? tokenOrOptions : options),
148
- token,
149
- api: {
150
- baseURL: "https://api.telegram.org/bot",
151
- retryGetUpdatesWait: 1000,
152
- ...options?.api,
153
- },
154
- };
155
- if (!(options?.plugins &&
156
- "format" in options.plugins &&
157
- !options.plugins.format))
158
- this.extend(new plugin_1.Plugin("@gramio/format").preRequest((context) => {
159
- if (!context.params)
160
- return context;
161
- // @ts-ignore
162
- const formattable = format_1.FormattableMap[context.method];
163
- // @ts-ignore add AnyTelegramMethod to @gramio/format
164
- if (formattable)
165
- context.params = formattable(context.params);
166
- return context;
167
- }));
168
- }
169
- async runHooks(type, context) {
170
- let data = context;
171
- for await (const hook of this.hooks[type]) {
172
- data = await hook(data);
173
- }
174
- return data;
175
- }
176
- async runImmutableHooks(type, ...context) {
177
- for await (const hook of this.hooks[type]) {
178
- //TODO: solve that later
179
- //@ts-expect-error
180
- await hook(...context);
181
- }
182
- }
183
- async _callApi(method, params = {}) {
184
- const debug$api$method = debug$api.extend(method);
185
- const url = `${this.options.api.baseURL}${this.options.token}/${method}`;
186
- // Omit<
187
- // NonNullable<Parameters<typeof fetch>[1]>,
188
- // "headers"
189
- // > & {
190
- // headers: Headers;
191
- // }
192
- // idk why it cause https://github.com/gramiojs/gramio/actions/runs/10388006206/job/28762703484
193
- // also in logs types differs
194
- const reqOptions = {
195
- method: "POST",
196
- ...this.options.api.fetchOptions,
197
- // @ts-ignore types node/bun and global missmatch
198
- headers: new Headers(this.options.api.fetchOptions?.headers),
199
- };
200
- const context = await this.runHooks("preRequest",
201
- // TODO: fix type error
202
- // @ts-expect-error
203
- {
204
- method,
205
- params,
206
- });
207
- // biome-ignore lint/style/noParameterAssign: mutate params
208
- params = context.params;
209
- // @ts-ignore
210
- if (params && (0, files_1.isMediaUpload)(method, params)) {
211
- // @ts-ignore
212
- const formData = await (0, files_1.convertJsonToFormData)(method, params);
213
- reqOptions.body = formData;
214
- }
215
- else {
216
- reqOptions.headers.set("Content-Type", "application/json");
217
- reqOptions.body = JSON.stringify(params);
218
- }
219
- debug$api$method("options: %j", reqOptions);
220
- const response = await fetch(url, reqOptions);
221
- const data = (await response.json());
222
- debug$api$method("response: %j", data);
223
- if (!data.ok) {
224
- const err = new errors_1.TelegramError(data, method, params);
225
- // @ts-expect-error
226
- this.runImmutableHooks("onResponseError", err, this.api);
227
- if (!params?.suppress)
228
- throw err;
229
- return err;
230
- }
231
- this.runImmutableHooks("onResponse",
232
- // TODO: fix type error
233
- // @ts-expect-error
234
- {
235
- method,
236
- params,
237
- response: data.result,
238
- });
239
- return data.result;
240
- }
241
- async downloadFile(attachment, path) {
242
- function getFileId(attachment) {
243
- if (attachment instanceof contexts_1.PhotoAttachment) {
244
- return attachment.bigSize.fileId;
245
- }
246
- if ("fileId" in attachment && typeof attachment.fileId === "string")
247
- return attachment.fileId;
248
- if ("file_id" in attachment)
249
- return attachment.file_id;
250
- throw new Error("Invalid attachment");
251
- }
252
- const fileId = typeof attachment === "string" ? attachment : getFileId(attachment);
253
- const file = await this.api.getFile({ file_id: fileId });
254
- const url = `${this.options.api.baseURL.replace("/bot", "/file/bot")}${this.options.token}/${file.file_path}`;
255
- const res = await fetch(url);
256
- if (path) {
257
- if (!res.body)
258
- throw new Error("Response without body (should be never throw)");
259
- // @ts-ignore denoo
260
- await promises_1.default.writeFile(path, node_stream_1.Readable.fromWeb(res.body));
261
- return path;
262
- }
263
- const buffer = await res.arrayBuffer();
264
- return buffer;
265
- }
266
- /**
267
- * Register custom class-error for type-safe catch in `onError` hook
268
- *
269
- * @example
270
- * ```ts
271
- * export class NoRights extends Error {
272
- * needRole: "admin" | "moderator";
273
- *
274
- * constructor(role: "admin" | "moderator") {
275
- * super();
276
- * this.needRole = role;
277
- * }
278
- * }
279
- *
280
- * const bot = new Bot(process.env.TOKEN!)
281
- * .error("NO_RIGHTS", NoRights)
282
- * .onError(({ context, kind, error }) => {
283
- * if (context.is("message") && kind === "NO_RIGHTS")
284
- * return context.send(
285
- * format`You don't have enough rights! You need to have an «${bold(
286
- * error.needRole
287
- * )}» role.`
288
- * );
289
- * });
290
- *
291
- * bot.updates.on("message", (context) => {
292
- * if (context.text === "bun") throw new NoRights("admin");
293
- * });
294
- * ```
295
- */
296
- error(kind, error) {
297
- //@ts-expect-error Set ErrorKind
298
- error[errors_1.ErrorKind] = kind;
299
- this.errorsDefinitions[kind] = error;
300
- return this;
301
- }
302
- onError(updateNameOrHandler, handler) {
303
- if (typeof updateNameOrHandler === "function") {
304
- this.hooks.onError.push(updateNameOrHandler);
305
- return this;
306
- }
307
- if (handler) {
308
- this.hooks.onError.push(async (errContext) => {
309
- if (errContext.context.is(updateNameOrHandler))
310
- // TODO: Sorry... fix later
311
- //@ts-expect-error
312
- await handler(errContext);
313
- });
314
- }
315
- return this;
316
- }
317
- derive(updateNameOrHandler, handler) {
318
- this.updates.composer.derive(updateNameOrHandler, handler);
319
- return this;
320
- }
321
- decorate(nameOrRecordValue, value) {
322
- for (const contextName of Object.keys(contexts_1.contextsMappings)) {
323
- if (typeof nameOrRecordValue === "string")
324
- // @ts-expect-error
325
- Object.defineProperty(contexts_1.contextsMappings[contextName].prototype, name, {
326
- value,
327
- });
328
- else
329
- Object.defineProperties(
330
- // @ts-expect-error
331
- contexts_1.contextsMappings[contextName].prototype, Object.keys(nameOrRecordValue).reduce((acc, key) => {
332
- acc[key] = { value: nameOrRecordValue[key] };
333
- return acc;
334
- }, {}));
335
- }
336
- return this;
337
- }
338
- /**
339
- * This hook called when the bot is `started`.
340
- *
341
- * @example
342
- * ```typescript
343
- * import { Bot } from "gramio";
344
- *
345
- * const bot = new Bot(process.env.TOKEN!).onStart(
346
- * ({ plugins, info, updatesFrom }) => {
347
- * console.log(`plugin list - ${plugins.join(", ")}`);
348
- * console.log(`bot username is @${info.username}`);
349
- * console.log(`updates from ${updatesFrom}`);
350
- * }
351
- * );
352
- *
353
- * bot.start();
354
- * ```
355
- *
356
- * [Documentation](https://gramio.dev/hooks/on-start.html)
357
- * */
358
- onStart(handler) {
359
- this.hooks.onStart.push(handler);
360
- return this;
361
- }
362
- /**
363
- * This hook called when the bot stops.
364
- *
365
- * @example
366
- * ```typescript
367
- * import { Bot } from "gramio";
368
- *
369
- * const bot = new Bot(process.env.TOKEN!).onStop(
370
- * ({ plugins, info, updatesFrom }) => {
371
- * console.log(`plugin list - ${plugins.join(", ")}`);
372
- * console.log(`bot username is @${info.username}`);
373
- * }
374
- * );
375
- *
376
- * bot.start();
377
- * bot.stop();
378
- * ```
379
- *
380
- * [Documentation](https://gramio.dev/hooks/on-stop.html)
381
- * */
382
- onStop(handler) {
383
- this.hooks.onStop.push(handler);
384
- return this;
385
- }
386
- preRequest(methodsOrHandler, handler) {
387
- if (typeof methodsOrHandler === "string" ||
388
- Array.isArray(methodsOrHandler)) {
389
- // TODO: error
390
- if (!handler)
391
- throw new Error("TODO:");
392
- const methods = typeof methodsOrHandler === "string"
393
- ? [methodsOrHandler]
394
- : methodsOrHandler;
395
- // TODO: remove error
396
- // @ts-expect-error
397
- this.hooks.preRequest.push(async (context) => {
398
- // TODO: remove ts-ignore
399
- // @ts-expect-error
400
- if (methods.includes(context.method))
401
- return handler(context);
402
- return context;
403
- });
404
- }
405
- else
406
- this.hooks.preRequest.push(methodsOrHandler);
407
- return this;
408
- }
409
- onResponse(methodsOrHandler, handler) {
410
- if (typeof methodsOrHandler === "string" ||
411
- Array.isArray(methodsOrHandler)) {
412
- // TODO: error
413
- if (!handler)
414
- throw new Error("TODO:");
415
- const methods = typeof methodsOrHandler === "string"
416
- ? [methodsOrHandler]
417
- : methodsOrHandler;
418
- this.hooks.onResponse.push(async (context) => {
419
- // TODO: remove ts-ignore
420
- // @ts-expect-error
421
- if (methods.includes(context.method))
422
- return handler(context);
423
- return context;
424
- });
425
- }
426
- else
427
- this.hooks.onResponse.push(methodsOrHandler);
428
- return this;
429
- }
430
- onResponseError(methodsOrHandler, handler) {
431
- if (typeof methodsOrHandler === "string" ||
432
- Array.isArray(methodsOrHandler)) {
433
- // TODO: error
434
- if (!handler)
435
- throw new Error("TODO:");
436
- const methods = typeof methodsOrHandler === "string"
437
- ? [methodsOrHandler]
438
- : methodsOrHandler;
439
- this.hooks.onResponseError.push(async (context) => {
440
- // TODO: remove ts-ignore
441
- // @ts-expect-error
442
- if (methods.includes(context.method))
443
- return handler(context);
444
- return context;
445
- });
446
- }
447
- else
448
- this.hooks.onResponseError.push(methodsOrHandler);
449
- return this;
450
- }
451
- // onExperimental(
452
- // // filter: Filters,
453
- // filter: (
454
- // f: Filters<
455
- // Context<typeof this> & Derives["global"],
456
- // [{ equal: { prop: number }; addition: { some: () => 2 } }]
457
- // >,
458
- // ) => Filters,
459
- // handler: Handler<Context<typeof this> & Derives["global"]>,
460
- // ) {}
461
- /** Register handler to one or many Updates */
462
- on(updateName, handler) {
463
- this.updates.composer.on(updateName, handler);
464
- return this;
465
- }
466
- /** Register handler to any Updates */
467
- use(handler) {
468
- this.updates.composer.use(handler);
469
- return this;
470
- }
471
- /**
472
- * Extend {@link Plugin} logic and types
473
- *
474
- * @example
475
- * ```ts
476
- * import { Plugin, Bot } from "gramio";
477
- *
478
- * export class PluginError extends Error {
479
- * wow: "type" | "safe" = "type";
480
- * }
481
- *
482
- * const plugin = new Plugin("gramio-example")
483
- * .error("PLUGIN", PluginError)
484
- * .derive(() => {
485
- * return {
486
- * some: ["derived", "props"] as const,
487
- * };
488
- * });
489
- *
490
- * const bot = new Bot(process.env.TOKEN!)
491
- * .extend(plugin)
492
- * .onError(({ context, kind, error }) => {
493
- * if (context.is("message") && kind === "PLUGIN") {
494
- * console.log(error.wow);
495
- * }
496
- * })
497
- * .use((context) => {
498
- * console.log(context.some);
499
- * });
500
- * ```
501
- */
502
- extend(plugin) {
503
- if (plugin instanceof Promise) {
504
- this.lazyloadPlugins.push(plugin);
505
- return this;
506
- }
507
- if (plugin._.dependencies.some((dep) => !this.dependencies.includes(dep)))
508
- throw new Error(`The «${plugin._.name}» plugin needs dependencies registered before: ${plugin._.dependencies
509
- .filter((dep) => !this.dependencies.includes(dep))
510
- .join(", ")}`);
511
- if (plugin._.composer.length) {
512
- this.use(plugin._.composer.composed);
513
- }
514
- this.decorate(plugin._.decorators);
515
- for (const [key, value] of Object.entries(plugin._.errorsDefinitions)) {
516
- if (this.errorsDefinitions[key])
517
- this.errorsDefinitions[key] = value;
518
- }
519
- for (const value of plugin._.preRequests) {
520
- const [preRequest, updateName] = value;
521
- if (!updateName)
522
- this.preRequest(preRequest);
523
- else
524
- this.preRequest(updateName, preRequest);
525
- }
526
- for (const value of plugin._.onResponses) {
527
- const [onResponse, updateName] = value;
528
- if (!updateName)
529
- this.onResponse(onResponse);
530
- else
531
- this.onResponse(updateName, onResponse);
532
- }
533
- for (const value of plugin._.onResponseErrors) {
534
- const [onResponseError, updateName] = value;
535
- if (!updateName)
536
- this.onResponseError(onResponseError);
537
- else
538
- this.onResponseError(updateName, onResponseError);
539
- }
540
- for (const handler of plugin._.groups) {
541
- this.group(handler);
542
- }
543
- this.dependencies.push(plugin._.name);
544
- return this;
545
- }
546
- /**
547
- * Register handler to reaction (`message_reaction` update)
548
- *
549
- * @example
550
- * ```ts
551
- * new Bot().reaction("👍", async (context) => {
552
- * await context.reply(`Thank you!`);
553
- * });
554
- * ```
555
- * */
556
- reaction(trigger, handler) {
557
- const reactions = Array.isArray(trigger) ? trigger : [trigger];
558
- return this.on("message_reaction", (context, next) => {
559
- const newReactions = [];
560
- for (const reaction of context.newReactions) {
561
- if (reaction.type !== "emoji")
562
- continue;
563
- const foundIndex = context.oldReactions.findIndex((oldReaction) => oldReaction.type === "emoji" &&
564
- oldReaction.emoji === reaction.emoji);
565
- if (foundIndex === -1) {
566
- newReactions.push(reaction);
567
- }
568
- else {
569
- // TODO: REFACTOR
570
- context.oldReactions.splice(foundIndex, 1);
571
- }
572
- }
573
- if (!newReactions.some((x) => x.type === "emoji" && reactions.includes(x.emoji)))
574
- return next();
575
- return handler(context);
576
- });
577
- }
578
- /**
579
- * Register handler to `callback_query` event
580
- *
581
- * @example
582
- * ```ts
583
- * const someData = new CallbackData("example").number("id");
584
- *
585
- * new Bot()
586
- * .command("start", (context) =>
587
- * context.send("some", {
588
- * reply_markup: new InlineKeyboard().text(
589
- * "example",
590
- * someData.pack({
591
- * id: 1,
592
- * })
593
- * ),
594
- * })
595
- * )
596
- * .callbackQuery(someData, (context) => {
597
- * context.queryData; // is type-safe
598
- * });
599
- * ```
600
- */
601
- callbackQuery(trigger, handler) {
602
- return this.on("callback_query", (context, next) => {
603
- if (!context.data)
604
- return next();
605
- if (typeof trigger === "string" && context.data !== trigger)
606
- return next();
607
- if (trigger instanceof callback_data_1.CallbackData &&
608
- !trigger.regexp().test(context.data))
609
- return next();
610
- if (trigger instanceof RegExp && !trigger.test(context.data))
611
- return next();
612
- if (trigger instanceof callback_data_1.CallbackData)
613
- // @ts-expect-error
614
- context.queryData = trigger.unpack(context.data);
615
- //@ts-expect-error
616
- return handler(context);
617
- });
618
- }
619
- /** Register handler to `chosen_inline_result` update */
620
- chosenInlineResult(trigger, handler) {
621
- return this.on("chosen_inline_result", (context, next) => {
622
- if ((typeof trigger === "string" && context.query === trigger) ||
623
- // @ts-expect-error
624
- (typeof trigger === "function" && trigger(context)) ||
625
- (trigger instanceof RegExp && trigger.test(context.query))) {
626
- //@ts-expect-error
627
- context.args =
628
- trigger instanceof RegExp ? context.query?.match(trigger) : null;
629
- // TODO: remove
630
- //@ts-expect-error
631
- return handler(context);
632
- }
633
- return next();
634
- });
635
- }
636
- /**
637
- * Register handler to `inline_query` update
638
- *
639
- * @example
640
- * ```ts
641
- * new Bot().inlineQuery(
642
- * /regular expression with (.*)/i,
643
- * async (context) => {
644
- * if (context.args) {
645
- * await context.answer(
646
- * [
647
- * InlineQueryResult.article(
648
- * "id-1",
649
- * context.args[1],
650
- * InputMessageContent.text("some"),
651
- * {
652
- * reply_markup: new InlineKeyboard().text(
653
- * "some",
654
- * "callback-data"
655
- * ),
656
- * }
657
- * ),
658
- * ],
659
- * {
660
- * cache_time: 0,
661
- * }
662
- * );
663
- * }
664
- * },
665
- * {
666
- * onResult: (context) => context.editText("Message edited!"),
667
- * }
668
- * );
669
- * ```
670
- * */
671
- inlineQuery(trigger, handler, options = {}) {
672
- // @ts-expect-error fix later...
673
- if (options.onResult)
674
- this.chosenInlineResult(trigger, options.onResult);
675
- return this.on("inline_query", (context, next) => {
676
- if ((typeof trigger === "string" && context.query === trigger) ||
677
- // @ts-expect-error
678
- (typeof trigger === "function" && trigger(context)) ||
679
- (trigger instanceof RegExp && trigger.test(context.query))) {
680
- //@ts-expect-error
681
- context.args =
682
- trigger instanceof RegExp ? context.query?.match(trigger) : null;
683
- // TODO: remove
684
- //@ts-expect-error
685
- return handler(context);
686
- }
687
- return next();
688
- });
689
- }
690
- /**
691
- * Register handler to `message` and `business_message` event
692
- *
693
- * new Bot().hears(/regular expression with (.*)/i, async (context) => {
694
- * if (context.args) await context.send(`Params ${context.args[1]}`);
695
- * });
696
- */
697
- hears(trigger, handler) {
698
- return this.on("message", (context, next) => {
699
- const text = context.text ?? context.caption;
700
- if ((typeof trigger === "string" && text === trigger) ||
701
- // @ts-expect-error
702
- (typeof trigger === "function" && trigger(context)) ||
703
- (trigger instanceof RegExp && text && trigger.test(text))) {
704
- //@ts-expect-error
705
- context.args = trigger instanceof RegExp ? text?.match(trigger) : null;
706
- // TODO: remove
707
- //@ts-expect-error
708
- return handler(context);
709
- }
710
- return next();
711
- });
712
- }
713
- /**
714
- * Register handler to `message` and `business_message` event when entities contains a command
715
- *
716
- * new Bot().command("start", async (context) => {
717
- * return context.send(`You message is /start ${context.args}`);
718
- * });
719
- */
720
- command(command, handler, options) {
721
- if (command.startsWith("/"))
722
- throw new Error("Do not use / in command name");
723
- return this.on(["message", "business_message"], (context, next) => {
724
- // TODO: change to find
725
- if (context.entities?.some((entity) => {
726
- if (entity.type !== "bot_command" || entity.offset > 0)
727
- return false;
728
- const cmd = context.text
729
- ?.slice(1, entity.length)
730
- // biome-ignore lint/style/noNonNullAssertion: <explanation>
731
- ?.replace(`@${this.info.username}`, "");
732
- // @ts-expect-error
733
- context.args = context.text?.slice(entity.length).trim() || null;
734
- return cmd === command;
735
- }))
736
- // @ts-expect-error
737
- return handler(context);
738
- return next();
739
- });
740
- }
741
- /** Currently not isolated!!! */
742
- group(grouped) {
743
- return grouped(this);
744
- }
745
- /**
746
- * Init bot. Call it manually only if you doesn't use {@link Bot.start}
747
- */
748
- async init() {
749
- await Promise.all(this.lazyloadPlugins.map(async (plugin) => this.extend(await plugin)));
750
- const info = await this.api.getMe({
751
- suppress: true,
752
- });
753
- if (info instanceof errors_1.TelegramError) {
754
- if (info.code === 404)
755
- info.message = "The bot token is incorrect. Check it in BotFather.";
756
- throw info;
757
- }
758
- this.info = info;
759
- }
760
- /**
761
- * Start receive updates via long-polling or webhook
762
- *
763
- * @example
764
- * ```ts
765
- * import { Bot } from "gramio";
766
- *
767
- * const bot = new Bot("") // put you token here
768
- * .command("start", (context) => context.send("Hi!"))
769
- * .onStart(console.log);
770
- *
771
- * bot.start();
772
- * ```
773
- */
774
- async start({ webhook, dropPendingUpdates, allowedUpdates, } = {}) {
775
- await this.init();
776
- if (!webhook) {
777
- await this.api.deleteWebhook({
778
- drop_pending_updates: dropPendingUpdates,
779
- });
780
- await this.updates.startPolling({
781
- allowed_updates: allowedUpdates,
782
- });
783
- this.runImmutableHooks("onStart", {
784
- plugins: this.dependencies,
785
- // biome-ignore lint/style/noNonNullAssertion: bot.init() guarantees this.info
786
- info: this.info,
787
- updatesFrom: "long-polling",
788
- });
789
- return this.info;
790
- }
791
- if (this.updates.isStarted)
792
- this.updates.stopPolling();
793
- await this.api.setWebhook({
794
- ...webhook,
795
- drop_pending_updates: dropPendingUpdates,
796
- allowed_updates: allowedUpdates,
797
- });
798
- this.runImmutableHooks("onStart", {
799
- plugins: this.dependencies,
800
- // biome-ignore lint/style/noNonNullAssertion: bot.init() guarantees this.info
801
- info: this.info,
802
- updatesFrom: "webhook",
803
- });
804
- return this.info;
805
- }
806
- /**
807
- * Stops receiving events via long-polling or webhook
808
- * Currently does not implement graceful shutdown
809
- * */
810
- async stop() {
811
- if (this.updates.isStarted)
812
- this.updates.stopPolling();
813
- else
814
- await this.api.deleteWebhook();
815
- await this.runImmutableHooks("onStop", {
816
- plugins: this.dependencies,
817
- // biome-ignore lint/style/noNonNullAssertion: bot.init() guarantees this.info
818
- info: this.info,
819
- });
820
- }
821
- };
822
- return Bot = _classThis;
823
- })();
824
- exports.Bot = Bot;