balebaazoo 1.0.1 → 1.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.en.md +12 -3
- package/README.md +55 -27
- package/dist/index.cjs +162 -35
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +31 -7
- package/dist/index.d.ts +31 -7
- package/dist/index.js +162 -36
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -593,6 +593,9 @@ interface ApiClientOptions {
|
|
|
593
593
|
maxRetries?: number;
|
|
594
594
|
retryDelayMs?: number;
|
|
595
595
|
}
|
|
596
|
+
interface CallOptions {
|
|
597
|
+
signal?: AbortSignal;
|
|
598
|
+
}
|
|
596
599
|
declare class Api {
|
|
597
600
|
readonly token: string;
|
|
598
601
|
private readonly baseUrl;
|
|
@@ -602,14 +605,14 @@ declare class Api {
|
|
|
602
605
|
constructor(options: ApiClientOptions);
|
|
603
606
|
get fileBaseUrl(): string;
|
|
604
607
|
private methodUrl;
|
|
605
|
-
call<M extends ApiMethod>(method: M, params?: Record<string, unknown
|
|
608
|
+
call<M extends ApiMethod>(method: M, params?: Record<string, unknown>, options?: CallOptions): Promise<ApiMethodResultMap[M]>;
|
|
606
609
|
private invoke;
|
|
607
610
|
downloadFile(filePath: string): Promise<ArrayBuffer>;
|
|
608
611
|
private prepareBody;
|
|
609
612
|
private request;
|
|
610
613
|
private fetchWithRetry;
|
|
611
614
|
getMe(): Promise<User>;
|
|
612
|
-
getUpdates(params?: GetUpdatesParams): Promise<Update[]>;
|
|
615
|
+
getUpdates(params?: GetUpdatesParams, options?: CallOptions): Promise<Update[]>;
|
|
613
616
|
setWebhook(params: SetWebhookParams): Promise<boolean>;
|
|
614
617
|
deleteWebhook(): Promise<boolean>;
|
|
615
618
|
getWebhookInfo(): Promise<WebhookInfo>;
|
|
@@ -674,8 +677,10 @@ declare class Context {
|
|
|
674
677
|
readonly update: Update;
|
|
675
678
|
readonly botInfo?: User;
|
|
676
679
|
callbackQueryAnswered: boolean;
|
|
680
|
+
private _updateTypes?;
|
|
677
681
|
constructor(options: ContextOptions);
|
|
678
682
|
get updateId(): number;
|
|
683
|
+
get updateTypes(): string[];
|
|
679
684
|
get message(): Message | undefined;
|
|
680
685
|
get editedMessage(): Message | undefined;
|
|
681
686
|
get callbackQuery(): CallbackQuery | undefined;
|
|
@@ -768,36 +773,48 @@ interface PollingOptions {
|
|
|
768
773
|
limit?: number;
|
|
769
774
|
timeout?: number;
|
|
770
775
|
allowedUpdates?: string[];
|
|
776
|
+
dropPendingUpdates?: boolean;
|
|
777
|
+
onStart?: (botInfo: User) => void | Promise<void>;
|
|
771
778
|
onError?: (error: unknown) => void;
|
|
772
779
|
signal?: AbortSignal;
|
|
773
780
|
}
|
|
781
|
+
interface WebhookHandlerOptions {
|
|
782
|
+
secretToken?: string;
|
|
783
|
+
maxBodyBytes?: number;
|
|
784
|
+
onError?: (error: unknown) => Response | void;
|
|
785
|
+
}
|
|
774
786
|
declare class PollingRunner {
|
|
775
787
|
private running;
|
|
776
788
|
private abortController?;
|
|
777
789
|
private offset;
|
|
790
|
+
private loopPromise?;
|
|
791
|
+
private backoffAttempt;
|
|
778
792
|
start(bot: PollingBot, options?: PollingOptions): Promise<void>;
|
|
793
|
+
private runLoop;
|
|
794
|
+
setOffset(offset: number): void;
|
|
779
795
|
stop(): Promise<void>;
|
|
780
796
|
}
|
|
781
|
-
declare function createWebhookHandler(bot: PollingBot, getUpdate: (request: Request) => Promise<Update>, options?:
|
|
782
|
-
secretToken?: string;
|
|
783
|
-
maxBodyBytes?: number;
|
|
784
|
-
}): Promise<(request: Request) => Promise<Response>>;
|
|
797
|
+
declare function createWebhookHandler(bot: PollingBot, getUpdate: (request: Request) => Promise<Update>, options?: WebhookHandlerOptions): Promise<(request: Request) => Promise<Response>>;
|
|
785
798
|
declare function webhookFromJson(bot: PollingBot): Promise<(request: Request) => Promise<Response>>;
|
|
786
799
|
|
|
787
800
|
interface BotOptions extends ApiClientOptions {
|
|
788
801
|
botInfo?: User;
|
|
789
802
|
autoAnswerCallback?: boolean;
|
|
790
803
|
}
|
|
804
|
+
|
|
791
805
|
declare class Bot<C extends Context = Context> extends Composer<C> {
|
|
792
806
|
readonly api: Api;
|
|
793
807
|
private botInfo?;
|
|
794
808
|
private readonly polling;
|
|
795
809
|
private readonly autoAnswer;
|
|
810
|
+
private catchHandler?;
|
|
796
811
|
constructor(token: string, options?: Omit<BotOptions, "token">);
|
|
797
812
|
init(): Promise<User>;
|
|
813
|
+
catch(handler: (error: unknown, ctx: C) => void | Promise<void>): this;
|
|
798
814
|
handleUpdate(update: Update): Promise<void>;
|
|
799
815
|
createContext(update: Update): Context;
|
|
800
816
|
start(options?: PollingOptions): Promise<void>;
|
|
817
|
+
launch(options?: PollingOptions): Promise<void>;
|
|
801
818
|
stop(): Promise<void>;
|
|
802
819
|
webhookCallback(): (update: Update) => Promise<void>;
|
|
803
820
|
use(...middleware: MiddlewareLike<C>[]): this;
|
|
@@ -855,6 +872,13 @@ declare class ReplyKeyboard implements ReplyKeyboardMarkup {
|
|
|
855
872
|
declare function removeKeyboard(): ReplyKeyboardRemove;
|
|
856
873
|
|
|
857
874
|
declare function autoAnswerCallback(): Middleware<Context>;
|
|
875
|
+
|
|
858
876
|
declare function errorHandler(onError: (error: unknown, ctx: Context) => Promise<void> | void): Middleware<Context>;
|
|
859
877
|
|
|
860
|
-
|
|
878
|
+
interface GracefulShutdownOptions {
|
|
879
|
+
signals?: NodeJS.Signals[];
|
|
880
|
+
onShutdown?: () => void | Promise<void>;
|
|
881
|
+
}
|
|
882
|
+
declare function setupGracefulShutdown(bot: Bot, options?: GracefulShutdownOptions): void;
|
|
883
|
+
|
|
884
|
+
export { type AddStickerToSetParams, type Animation, type AnswerCallbackQueryParams, type AnswerPreCheckoutQueryParams, Api, type ApiClientOptions, type ApiMethod, type ApiMethodResultMap, type AskReviewParams, type Audio, BaleAPIError, type BaleApiResponse, BaleError, BaleNetworkError, type BanChatMemberParams, Bot, type BotOptions, type CallOptions, type CallbackQuery, type Chat, type ChatAction, type ChatFullInfo, type ChatId, type ChatMember, type ChatMemberAdministrator, type ChatMemberMember, type ChatMemberOwner, type ChatMemberRestricted, type ChatPhoto, Composer, type Contact, Context, type ContextOptions, type CopyMessageParams, type CopyTextButton, type CreateChatInviteLinkParams, type CreateInvoiceLinkParams, type CreateNewStickerSetParams, DEFAULT_API_BASE, type DeleteMessageParams, type Document, type EditMessageCaptionParams, type EditMessageReplyMarkupParams, type EditMessageTextParams, type File, type FilterContext, type FilterQuery, type ForwardMessageParams, type GetChatMemberParams, type GetChatParams, type GetFileParams, type GetUpdatesParams, type GracefulShutdownOptions, InlineKeyboard, type InlineKeyboardButton, type InlineKeyboardMarkup, InputFile, type InputMedia, type InputMediaAnimation, type InputMediaAudio, type InputMediaDocument, type InputMediaPhoto, type InputMediaVideo, type InputSticker, type InquireTransactionParams, type Invoice, type KeyboardButton, type LabeledPrice, type LeaveChatParams, type Location, type Message, type MessageEntity, type MessageId, type Middleware, type MiddlewareLike, type MiddlewareObject, type NextFunction, type PhotoSize, type PinChatMessageParams, type PollingBot, type PollingOptions, PollingRunner, type PreCheckoutQuery, type PromoteChatMemberParams, ReplyKeyboard, type ReplyKeyboardMarkup, type ReplyKeyboardRemove, type ReplyMarkup, type ReplyOptions, type ResponseParameters, type RevokeChatInviteLinkParams, type SendAnimationParams, type SendAudioParams, type SendChatActionParams, type SendContactParams, type SendDocumentParams, type SendInvoiceParams, type SendLocationParams, type SendMediaGroupParams, type SendMediaParams, type SendMessageParams, type SendPhotoParams, type SendVideoParams, type SendVoiceParams, type SetChatDescriptionParams, type SetChatPhotoParams, type SetChatTitleParams, type SetWebhookParams, type Sticker, type StickerSet, type SuccessfulPayment, type Transaction, type UnbanChatMemberParams, type Update, type UploadStickerFileParams, type User, type UserId, type Video, type Voice, type WebAppData, type WebAppInfo, type WebhookHandlerOptions, type WebhookInfo, autoAnswerCallback, bold, createWebhookHandler, errorHandler, extractCommand, isFilePath, isMiddlewareObject, italic, link, matchUpdate, matchesAnyFilter, matchesChatType, matchesFilter, md, normalizeMiddleware, removeKeyboard, runMiddleware, setupGracefulShutdown, spoiler, webhookFromJson };
|
package/dist/index.js
CHANGED
|
@@ -92,6 +92,9 @@ async function isFilePath(source) {
|
|
|
92
92
|
if (source.startsWith("http://") || source.startsWith("https://")) {
|
|
93
93
|
return false;
|
|
94
94
|
}
|
|
95
|
+
if (!looksLikePath(source)) {
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
95
98
|
try {
|
|
96
99
|
const info = await stat(source);
|
|
97
100
|
return info.isFile();
|
|
@@ -99,6 +102,9 @@ async function isFilePath(source) {
|
|
|
99
102
|
return false;
|
|
100
103
|
}
|
|
101
104
|
}
|
|
105
|
+
function looksLikePath(source) {
|
|
106
|
+
return source.startsWith("./") || source.startsWith("../") || source.includes("/") || source.includes("\\");
|
|
107
|
+
}
|
|
102
108
|
|
|
103
109
|
// src/api/client.ts
|
|
104
110
|
var DEFAULT_API_BASE = "https://tapi.bale.ai";
|
|
@@ -121,12 +127,15 @@ var Api = class {
|
|
|
121
127
|
methodUrl(method) {
|
|
122
128
|
return `${this.baseUrl}/bot${this.token}/${method}`;
|
|
123
129
|
}
|
|
124
|
-
async call(method, params) {
|
|
130
|
+
async call(method, params, options) {
|
|
125
131
|
let attempt = 0;
|
|
126
132
|
while (true) {
|
|
127
133
|
try {
|
|
128
|
-
return await this.invoke(method, params);
|
|
134
|
+
return await this.invoke(method, params, options);
|
|
129
135
|
} catch (error) {
|
|
136
|
+
if (options?.signal?.aborted || isAbortError(error)) {
|
|
137
|
+
throw error;
|
|
138
|
+
}
|
|
130
139
|
if (error instanceof BaleAPIError && error.errorCode === 429 && attempt < this.maxRetries) {
|
|
131
140
|
const retryAfter = (error.parameters?.retry_after ?? 1) * 1e3;
|
|
132
141
|
await sleep(retryAfter);
|
|
@@ -137,7 +146,7 @@ var Api = class {
|
|
|
137
146
|
}
|
|
138
147
|
}
|
|
139
148
|
}
|
|
140
|
-
async invoke(method, params) {
|
|
149
|
+
async invoke(method, params, options) {
|
|
141
150
|
const { body } = await this.prepareBody(params ?? {});
|
|
142
151
|
const headers = {};
|
|
143
152
|
if (!(body instanceof FormData)) {
|
|
@@ -147,7 +156,7 @@ var Api = class {
|
|
|
147
156
|
method: "POST",
|
|
148
157
|
headers,
|
|
149
158
|
body: body instanceof FormData ? body : JSON.stringify(body ?? {})
|
|
150
|
-
});
|
|
159
|
+
}, options);
|
|
151
160
|
}
|
|
152
161
|
async downloadFile(filePath) {
|
|
153
162
|
const url = `${this.fileBaseUrl}/${filePath}`;
|
|
@@ -189,8 +198,8 @@ var Api = class {
|
|
|
189
198
|
}
|
|
190
199
|
return { body: formData, isMultipart: true };
|
|
191
200
|
}
|
|
192
|
-
async request(method, init) {
|
|
193
|
-
const response = await this.fetchWithRetry(this.methodUrl(method), init);
|
|
201
|
+
async request(method, init, options) {
|
|
202
|
+
const response = await this.fetchWithRetry(this.methodUrl(method), init, options);
|
|
194
203
|
const payload = await response.json();
|
|
195
204
|
if (!payload.ok) {
|
|
196
205
|
throw new BaleAPIError(
|
|
@@ -201,12 +210,18 @@ var Api = class {
|
|
|
201
210
|
}
|
|
202
211
|
return payload.result;
|
|
203
212
|
}
|
|
204
|
-
async fetchWithRetry(url, init) {
|
|
213
|
+
async fetchWithRetry(url, init, options) {
|
|
205
214
|
let attempt = 0;
|
|
206
215
|
let lastError;
|
|
207
216
|
while (attempt <= this.maxRetries) {
|
|
217
|
+
if (options?.signal?.aborted) {
|
|
218
|
+
throw new DOMException("The operation was aborted", "AbortError");
|
|
219
|
+
}
|
|
208
220
|
try {
|
|
209
|
-
const response = await this.fetchFn(url,
|
|
221
|
+
const response = await this.fetchFn(url, {
|
|
222
|
+
...init,
|
|
223
|
+
signal: options?.signal
|
|
224
|
+
});
|
|
210
225
|
if (response.status === 429) {
|
|
211
226
|
const retryAfter = Number(response.headers.get("retry-after") ?? "1");
|
|
212
227
|
await sleep(retryAfter * 1e3);
|
|
@@ -221,6 +236,9 @@ var Api = class {
|
|
|
221
236
|
return response;
|
|
222
237
|
} catch (error) {
|
|
223
238
|
lastError = error;
|
|
239
|
+
if (isAbortError(error) || options?.signal?.aborted) {
|
|
240
|
+
throw error;
|
|
241
|
+
}
|
|
224
242
|
if (attempt >= this.maxRetries) {
|
|
225
243
|
break;
|
|
226
244
|
}
|
|
@@ -236,8 +254,8 @@ var Api = class {
|
|
|
236
254
|
getMe() {
|
|
237
255
|
return this.call("getMe");
|
|
238
256
|
}
|
|
239
|
-
getUpdates(params) {
|
|
240
|
-
return this.call("getUpdates", asParams(params));
|
|
257
|
+
getUpdates(params, options) {
|
|
258
|
+
return this.call("getUpdates", asParams(params), options);
|
|
241
259
|
}
|
|
242
260
|
setWebhook(params) {
|
|
243
261
|
return this.call("setWebhook", asParams(params));
|
|
@@ -425,6 +443,9 @@ function appendFormValue(formData, key, value) {
|
|
|
425
443
|
function sleep(ms) {
|
|
426
444
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
427
445
|
}
|
|
446
|
+
function isAbortError(error) {
|
|
447
|
+
return error instanceof Error && (error.name === "AbortError" || error.message.includes("aborted"));
|
|
448
|
+
}
|
|
428
449
|
|
|
429
450
|
// src/middleware/types.ts
|
|
430
451
|
function isMiddlewareObject(value) {
|
|
@@ -495,12 +516,10 @@ function extractCommand(text) {
|
|
|
495
516
|
|
|
496
517
|
// src/filters/query.ts
|
|
497
518
|
function matchesFilter(ctx, filter) {
|
|
498
|
-
|
|
499
|
-
return updateMatches.includes(filter);
|
|
519
|
+
return ctx.updateTypes.includes(filter);
|
|
500
520
|
}
|
|
501
521
|
function matchesAnyFilter(ctx, filters) {
|
|
502
|
-
|
|
503
|
-
return filters.some((filter) => updateMatches.includes(filter));
|
|
522
|
+
return filters.some((filter) => ctx.updateTypes.includes(filter));
|
|
504
523
|
}
|
|
505
524
|
function matchesChatType(ctx, chatType) {
|
|
506
525
|
const chat = ctx.chat;
|
|
@@ -613,6 +632,7 @@ var Context = class {
|
|
|
613
632
|
update;
|
|
614
633
|
botInfo;
|
|
615
634
|
callbackQueryAnswered = false;
|
|
635
|
+
_updateTypes;
|
|
616
636
|
constructor(options) {
|
|
617
637
|
this.api = options.api;
|
|
618
638
|
this.update = options.update;
|
|
@@ -621,6 +641,12 @@ var Context = class {
|
|
|
621
641
|
get updateId() {
|
|
622
642
|
return this.update.update_id;
|
|
623
643
|
}
|
|
644
|
+
get updateTypes() {
|
|
645
|
+
if (!this._updateTypes) {
|
|
646
|
+
this._updateTypes = matchUpdate(this.update);
|
|
647
|
+
}
|
|
648
|
+
return this._updateTypes;
|
|
649
|
+
}
|
|
624
650
|
get message() {
|
|
625
651
|
return this.update.message ?? this.update.edited_message;
|
|
626
652
|
}
|
|
@@ -780,21 +806,14 @@ function autoAnswerCallback() {
|
|
|
780
806
|
}
|
|
781
807
|
};
|
|
782
808
|
}
|
|
783
|
-
function errorHandler(onError) {
|
|
784
|
-
return async (ctx, next) => {
|
|
785
|
-
try {
|
|
786
|
-
await next();
|
|
787
|
-
} catch (error) {
|
|
788
|
-
await onError(error, ctx);
|
|
789
|
-
}
|
|
790
|
-
};
|
|
791
|
-
}
|
|
792
809
|
|
|
793
810
|
// src/runner/polling.ts
|
|
794
811
|
var PollingRunner = class {
|
|
795
812
|
running = false;
|
|
796
813
|
abortController;
|
|
797
814
|
offset = 0;
|
|
815
|
+
loopPromise;
|
|
816
|
+
backoffAttempt = 0;
|
|
798
817
|
async start(bot, options = {}) {
|
|
799
818
|
if (this.running) {
|
|
800
819
|
throw new Error("Polling is already running");
|
|
@@ -805,14 +824,22 @@ var PollingRunner = class {
|
|
|
805
824
|
const onError = options.onError ?? ((error) => {
|
|
806
825
|
console.error("[balebaazoo] polling error:", error);
|
|
807
826
|
});
|
|
827
|
+
this.loopPromise = this.runLoop(bot, options, signal, onError);
|
|
828
|
+
await this.loopPromise;
|
|
829
|
+
}
|
|
830
|
+
async runLoop(bot, options, signal, onError) {
|
|
808
831
|
while (this.running && !signal.aborted) {
|
|
809
832
|
try {
|
|
810
|
-
const updates = await bot.api.getUpdates(
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
833
|
+
const updates = await bot.api.getUpdates(
|
|
834
|
+
{
|
|
835
|
+
offset: this.offset,
|
|
836
|
+
limit: options.limit ?? 100,
|
|
837
|
+
timeout: options.timeout ?? 30,
|
|
838
|
+
allowed_updates: options.allowedUpdates
|
|
839
|
+
},
|
|
840
|
+
{ signal }
|
|
841
|
+
);
|
|
842
|
+
this.backoffAttempt = 0;
|
|
816
843
|
for (const update of updates) {
|
|
817
844
|
this.offset = update.update_id + 1;
|
|
818
845
|
try {
|
|
@@ -825,23 +852,49 @@ var PollingRunner = class {
|
|
|
825
852
|
break;
|
|
826
853
|
}
|
|
827
854
|
} catch (error) {
|
|
828
|
-
if (signal.aborted)
|
|
855
|
+
if (signal.aborted || isAbortError2(error)) {
|
|
856
|
+
break;
|
|
857
|
+
}
|
|
858
|
+
if (error instanceof BaleAPIError && error.errorCode === 401) {
|
|
859
|
+
onError(error);
|
|
860
|
+
this.running = false;
|
|
861
|
+
break;
|
|
862
|
+
}
|
|
829
863
|
onError(error);
|
|
830
|
-
await sleep2(
|
|
864
|
+
await sleep2(backoffDelay(this.backoffAttempt));
|
|
865
|
+
this.backoffAttempt++;
|
|
831
866
|
}
|
|
832
867
|
}
|
|
833
868
|
}
|
|
869
|
+
setOffset(offset) {
|
|
870
|
+
this.offset = offset;
|
|
871
|
+
}
|
|
834
872
|
async stop() {
|
|
835
873
|
this.running = false;
|
|
836
874
|
this.abortController?.abort();
|
|
875
|
+
await this.loopPromise;
|
|
837
876
|
}
|
|
838
877
|
};
|
|
878
|
+
function isAbortError2(error) {
|
|
879
|
+
return error instanceof Error && (error.name === "AbortError" || error.message.includes("aborted"));
|
|
880
|
+
}
|
|
881
|
+
function backoffDelay(attempt) {
|
|
882
|
+
const base = 1e3;
|
|
883
|
+
const max = 3e4;
|
|
884
|
+
const exponential = Math.min(base * 2 ** attempt, max);
|
|
885
|
+
const jitter = Math.random() * 0.3 * exponential;
|
|
886
|
+
return Math.floor(exponential + jitter);
|
|
887
|
+
}
|
|
839
888
|
function sleep2(ms) {
|
|
840
889
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
841
890
|
}
|
|
842
891
|
async function createWebhookHandler(bot, getUpdate, options = {}) {
|
|
843
892
|
await bot.init();
|
|
844
893
|
const maxBodyBytes = options.maxBodyBytes ?? 1024 * 1024;
|
|
894
|
+
const onError = options.onError ?? ((error) => {
|
|
895
|
+
console.error("[balebaazoo] webhook error:", error);
|
|
896
|
+
return new Response("Internal Server Error", { status: 500 });
|
|
897
|
+
});
|
|
845
898
|
return async (request) => {
|
|
846
899
|
if (request.method !== "POST") {
|
|
847
900
|
return new Response("Method Not Allowed", { status: 405 });
|
|
@@ -866,8 +919,8 @@ async function createWebhookHandler(bot, getUpdate, options = {}) {
|
|
|
866
919
|
await bot.handleUpdate(update);
|
|
867
920
|
return new Response("OK", { status: 200 });
|
|
868
921
|
} catch (error) {
|
|
869
|
-
|
|
870
|
-
return new Response("Internal Server Error", { status: 500 });
|
|
922
|
+
const response = onError(error);
|
|
923
|
+
return response ?? new Response("Internal Server Error", { status: 500 });
|
|
871
924
|
}
|
|
872
925
|
};
|
|
873
926
|
}
|
|
@@ -883,6 +936,7 @@ var Bot = class extends Composer {
|
|
|
883
936
|
botInfo;
|
|
884
937
|
polling = new PollingRunner();
|
|
885
938
|
autoAnswer;
|
|
939
|
+
catchHandler;
|
|
886
940
|
constructor(token, options = {}) {
|
|
887
941
|
const api = new Api({ token, ...options });
|
|
888
942
|
super();
|
|
@@ -899,9 +953,22 @@ var Bot = class extends Composer {
|
|
|
899
953
|
}
|
|
900
954
|
return this.botInfo;
|
|
901
955
|
}
|
|
956
|
+
catch(handler) {
|
|
957
|
+
this.catchHandler = handler;
|
|
958
|
+
return this;
|
|
959
|
+
}
|
|
902
960
|
async handleUpdate(update) {
|
|
961
|
+
await this.init();
|
|
903
962
|
const ctx = this.createContext(update);
|
|
904
|
-
|
|
963
|
+
try {
|
|
964
|
+
await this.middleware()(ctx, async () => void 0);
|
|
965
|
+
} catch (error) {
|
|
966
|
+
if (this.catchHandler) {
|
|
967
|
+
await this.catchHandler(error, ctx);
|
|
968
|
+
return;
|
|
969
|
+
}
|
|
970
|
+
throw error;
|
|
971
|
+
}
|
|
905
972
|
}
|
|
906
973
|
createContext(update) {
|
|
907
974
|
return new Context({
|
|
@@ -911,9 +978,44 @@ var Bot = class extends Composer {
|
|
|
911
978
|
});
|
|
912
979
|
}
|
|
913
980
|
async start(options = {}) {
|
|
914
|
-
|
|
981
|
+
const onError = options.onError ?? ((error) => {
|
|
982
|
+
console.error("[balebaazoo] polling error:", error);
|
|
983
|
+
});
|
|
984
|
+
try {
|
|
985
|
+
await this.init();
|
|
986
|
+
} catch (error) {
|
|
987
|
+
onError(error);
|
|
988
|
+
return;
|
|
989
|
+
}
|
|
990
|
+
if (options.dropPendingUpdates) {
|
|
991
|
+
try {
|
|
992
|
+
const updates = await this.api.getUpdates({
|
|
993
|
+
offset: -1,
|
|
994
|
+
limit: 1,
|
|
995
|
+
timeout: 0
|
|
996
|
+
});
|
|
997
|
+
if (updates.length > 0) {
|
|
998
|
+
const last = updates[updates.length - 1];
|
|
999
|
+
this.polling.setOffset(last.update_id + 1);
|
|
1000
|
+
}
|
|
1001
|
+
} catch (error) {
|
|
1002
|
+
onError(error);
|
|
1003
|
+
return;
|
|
1004
|
+
}
|
|
1005
|
+
}
|
|
1006
|
+
if (options.onStart) {
|
|
1007
|
+
try {
|
|
1008
|
+
await options.onStart(this.botInfo);
|
|
1009
|
+
} catch (error) {
|
|
1010
|
+
onError(error);
|
|
1011
|
+
return;
|
|
1012
|
+
}
|
|
1013
|
+
}
|
|
915
1014
|
await this.polling.start(this, options);
|
|
916
1015
|
}
|
|
1016
|
+
launch(options) {
|
|
1017
|
+
return this.start(options);
|
|
1018
|
+
}
|
|
917
1019
|
async stop() {
|
|
918
1020
|
await this.polling.stop();
|
|
919
1021
|
}
|
|
@@ -1010,6 +1112,30 @@ function removeKeyboard() {
|
|
|
1010
1112
|
return { remove_keyboard: true };
|
|
1011
1113
|
}
|
|
1012
1114
|
|
|
1013
|
-
|
|
1115
|
+
// src/middleware/error-handler.ts
|
|
1116
|
+
function errorHandler(onError) {
|
|
1117
|
+
return async (ctx, next) => {
|
|
1118
|
+
try {
|
|
1119
|
+
await next();
|
|
1120
|
+
} catch (error) {
|
|
1121
|
+
await onError(error, ctx);
|
|
1122
|
+
}
|
|
1123
|
+
};
|
|
1124
|
+
}
|
|
1125
|
+
|
|
1126
|
+
// src/runner/shutdown.ts
|
|
1127
|
+
function setupGracefulShutdown(bot, options = {}) {
|
|
1128
|
+
const signals = options.signals ?? ["SIGINT", "SIGTERM"];
|
|
1129
|
+
for (const signal of signals) {
|
|
1130
|
+
process.once(signal, () => {
|
|
1131
|
+
void (async () => {
|
|
1132
|
+
await bot.stop();
|
|
1133
|
+
await options.onShutdown?.();
|
|
1134
|
+
})();
|
|
1135
|
+
});
|
|
1136
|
+
}
|
|
1137
|
+
}
|
|
1138
|
+
|
|
1139
|
+
export { Api, BaleAPIError, BaleError, BaleNetworkError, Bot, Composer, Context, DEFAULT_API_BASE, InlineKeyboard, InputFile, PollingRunner, ReplyKeyboard, autoAnswerCallback, bold, createWebhookHandler, errorHandler, extractCommand, isFilePath, isMiddlewareObject, italic, link, matchUpdate, matchesAnyFilter, matchesChatType, matchesFilter, md, normalizeMiddleware, removeKeyboard, runMiddleware, setupGracefulShutdown, spoiler, webhookFromJson };
|
|
1014
1140
|
//# sourceMappingURL=index.js.map
|
|
1015
1141
|
//# sourceMappingURL=index.js.map
|