gramio 0.4.12 → 0.4.13
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/index.cjs +96 -59
- package/dist/index.d.cts +59 -2
- package/dist/index.d.ts +59 -2
- package/dist/index.js +96 -59
- package/dist/{utils-CYIya32k.cjs → utils-C46rnh-r.cjs} +7 -1
- package/dist/{utils-CJfJNxc_.js → utils-En0iVLWH.js} +7 -1
- package/dist/utils.cjs +1 -1
- package/dist/utils.js +1 -1
- package/package.json +4 -4
package/dist/index.cjs
CHANGED
|
@@ -7,7 +7,7 @@ var contexts = require('@gramio/contexts');
|
|
|
7
7
|
var files = require('@gramio/files');
|
|
8
8
|
var format = require('@gramio/format');
|
|
9
9
|
var debug = require('debug');
|
|
10
|
-
var utils = require('./utils-
|
|
10
|
+
var utils = require('./utils-C46rnh-r.cjs');
|
|
11
11
|
var middlewareIo = require('middleware-io');
|
|
12
12
|
var keyboards = require('@gramio/keyboards');
|
|
13
13
|
|
|
@@ -102,6 +102,8 @@ class Plugin {
|
|
|
102
102
|
onResponses: [],
|
|
103
103
|
/** Store plugin onResponseErrors hooks */
|
|
104
104
|
onResponseErrors: [],
|
|
105
|
+
/** Store plugin onApiCalls hooks */
|
|
106
|
+
onApiCalls: [],
|
|
105
107
|
/**
|
|
106
108
|
* Store plugin groups
|
|
107
109
|
*
|
|
@@ -185,6 +187,13 @@ class Plugin {
|
|
|
185
187
|
this._.onResponseErrors.push([methodsOrHandler, void 0]);
|
|
186
188
|
return this;
|
|
187
189
|
}
|
|
190
|
+
onApiCall(methodsOrHandler, handler) {
|
|
191
|
+
if ((typeof methodsOrHandler === "string" || Array.isArray(methodsOrHandler)) && handler)
|
|
192
|
+
this._.onApiCalls.push([handler, methodsOrHandler]);
|
|
193
|
+
else if (typeof methodsOrHandler === "function")
|
|
194
|
+
this._.onApiCalls.push([methodsOrHandler, void 0]);
|
|
195
|
+
return this;
|
|
196
|
+
}
|
|
188
197
|
/**
|
|
189
198
|
* This hook called when the bot is `started`.
|
|
190
199
|
*
|
|
@@ -427,9 +436,6 @@ class Bot {
|
|
|
427
436
|
/** @deprecated use `~.derives` instead @internal. Remap generic */
|
|
428
437
|
__Derives;
|
|
429
438
|
"~" = this._;
|
|
430
|
-
filters = {
|
|
431
|
-
context: (name) => (context) => context.is(name)
|
|
432
|
-
};
|
|
433
439
|
/** Options provided to instance */
|
|
434
440
|
options;
|
|
435
441
|
/** Bot data (filled in when calling bot.init/bot.start) */
|
|
@@ -451,7 +457,13 @@ class Bot {
|
|
|
451
457
|
get: (_target, method) => (
|
|
452
458
|
// @ts-expect-error
|
|
453
459
|
// biome-ignore lint/suspicious/noAssignInExpressions: <explanation>
|
|
454
|
-
_target[method] ??= (args) =>
|
|
460
|
+
_target[method] ??= (args) => {
|
|
461
|
+
const callSite = new Error();
|
|
462
|
+
if (Error.captureStackTrace) {
|
|
463
|
+
Error.captureStackTrace(callSite, _target[method]);
|
|
464
|
+
}
|
|
465
|
+
return this._callApi(method, args, callSite);
|
|
466
|
+
}
|
|
455
467
|
)
|
|
456
468
|
});
|
|
457
469
|
lazyloadPlugins = [];
|
|
@@ -477,7 +489,8 @@ class Bot {
|
|
|
477
489
|
onResponseError: [],
|
|
478
490
|
onError: [],
|
|
479
491
|
onStart: [],
|
|
480
|
-
onStop: []
|
|
492
|
+
onStop: [],
|
|
493
|
+
onApiCall: []
|
|
481
494
|
};
|
|
482
495
|
constructor(tokenOrOptions, optionsRaw) {
|
|
483
496
|
const token = typeof tokenOrOptions === "string" ? tokenOrOptions : tokenOrOptions?.token;
|
|
@@ -500,7 +513,10 @@ class Bot {
|
|
|
500
513
|
new Plugin("@gramio/format").preRequest((context) => {
|
|
501
514
|
if (!context.params) return context;
|
|
502
515
|
const formattable = format.FormattableMap[context.method];
|
|
503
|
-
if (formattable)
|
|
516
|
+
if (formattable)
|
|
517
|
+
context.params = formattable(
|
|
518
|
+
context.params
|
|
519
|
+
);
|
|
504
520
|
return context;
|
|
505
521
|
})
|
|
506
522
|
);
|
|
@@ -517,63 +533,66 @@ class Bot {
|
|
|
517
533
|
await hook(...context);
|
|
518
534
|
}
|
|
519
535
|
}
|
|
520
|
-
async _callApi(method, params = {}) {
|
|
521
|
-
const
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
"preRequest",
|
|
531
|
-
// TODO: fix type error
|
|
532
|
-
// @ts-expect-error
|
|
533
|
-
{
|
|
536
|
+
async _callApi(method, params = {}, callSite) {
|
|
537
|
+
const executeCall = async () => {
|
|
538
|
+
const debug$api$method = debug(`gramio:api:${method}`);
|
|
539
|
+
let url = `${this.options.api.baseURL}${this.options.token}/${this.options.api.useTest ? "test/" : ""}${method}`;
|
|
540
|
+
const reqOptions = {
|
|
541
|
+
method: "POST",
|
|
542
|
+
...this.options.api.fetchOptions,
|
|
543
|
+
headers: new Headers(this.options.api.fetchOptions?.headers)
|
|
544
|
+
};
|
|
545
|
+
const context = await this.runHooks("preRequest", {
|
|
534
546
|
method,
|
|
535
547
|
params
|
|
536
|
-
}
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
548
|
+
});
|
|
549
|
+
params = context.params;
|
|
550
|
+
if (params && files.isMediaUpload(method, params)) {
|
|
551
|
+
if (utils.IS_BUN) {
|
|
552
|
+
const formData = await files.convertJsonToFormData(method, params);
|
|
553
|
+
reqOptions.body = formData;
|
|
554
|
+
} else {
|
|
555
|
+
const [formData, paramsWithoutFiles] = await files.extractFilesToFormData(
|
|
556
|
+
method,
|
|
557
|
+
params
|
|
558
|
+
);
|
|
559
|
+
reqOptions.body = formData;
|
|
560
|
+
const simplifiedParams = utils.simplifyObject(paramsWithoutFiles);
|
|
561
|
+
url += `?${new URLSearchParams(simplifiedParams).toString()}`;
|
|
562
|
+
}
|
|
543
563
|
} else {
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
params
|
|
547
|
-
);
|
|
548
|
-
reqOptions.body = formData;
|
|
549
|
-
const simplifiedParams = utils.simplifyObject(paramsWithoutFiles);
|
|
550
|
-
url += `?${new URLSearchParams(simplifiedParams).toString()}`;
|
|
564
|
+
reqOptions.headers.set("Content-Type", "application/json");
|
|
565
|
+
reqOptions.body = JSON.stringify(params);
|
|
551
566
|
}
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
const err = new utils.TelegramError(data, method, params);
|
|
562
|
-
this.runImmutableHooks("onResponseError", err, this.api);
|
|
563
|
-
if (!params?.suppress) throw err;
|
|
564
|
-
return err;
|
|
565
|
-
}
|
|
566
|
-
this.runImmutableHooks(
|
|
567
|
-
"onResponse",
|
|
568
|
-
// TODO: fix type error
|
|
569
|
-
// @ts-expect-error
|
|
570
|
-
{
|
|
571
|
-
method,
|
|
572
|
-
params,
|
|
573
|
-
response: data.result
|
|
567
|
+
debug$api$method("options: %j", reqOptions);
|
|
568
|
+
const response = await fetch(url, reqOptions);
|
|
569
|
+
const data = await response.json();
|
|
570
|
+
debug$api$method("response: %j", data);
|
|
571
|
+
if (!data.ok) {
|
|
572
|
+
const err = new utils.TelegramError(data, method, params, callSite);
|
|
573
|
+
this.runImmutableHooks("onResponseError", err, this.api);
|
|
574
|
+
if (!params?.suppress) throw err;
|
|
575
|
+
return err;
|
|
574
576
|
}
|
|
575
|
-
|
|
576
|
-
|
|
577
|
+
this.runImmutableHooks(
|
|
578
|
+
"onResponse",
|
|
579
|
+
// TODO: fix type error
|
|
580
|
+
// @ts-expect-error
|
|
581
|
+
{
|
|
582
|
+
method,
|
|
583
|
+
params,
|
|
584
|
+
response: data.result
|
|
585
|
+
}
|
|
586
|
+
);
|
|
587
|
+
return data.result;
|
|
588
|
+
};
|
|
589
|
+
if (!this.hooks.onApiCall.length) return executeCall();
|
|
590
|
+
let fn = executeCall;
|
|
591
|
+
for (const hook of [...this.hooks.onApiCall].reverse()) {
|
|
592
|
+
const prev = fn;
|
|
593
|
+
fn = () => hook({ method, params }, prev);
|
|
594
|
+
}
|
|
595
|
+
return fn();
|
|
577
596
|
}
|
|
578
597
|
async downloadFile(attachment, path) {
|
|
579
598
|
function getFileId(attachment2) {
|
|
@@ -761,6 +780,19 @@ class Bot {
|
|
|
761
780
|
} else this.hooks.onResponseError.push(methodsOrHandler);
|
|
762
781
|
return this;
|
|
763
782
|
}
|
|
783
|
+
onApiCall(methodsOrHandler, handler) {
|
|
784
|
+
if (typeof methodsOrHandler === "string" || Array.isArray(methodsOrHandler)) {
|
|
785
|
+
if (!handler) throw new Error("TODO:");
|
|
786
|
+
const methods = typeof methodsOrHandler === "string" ? [methodsOrHandler] : methodsOrHandler;
|
|
787
|
+
this.hooks.onApiCall.push(async (context, next) => {
|
|
788
|
+
if (methods.includes(context.method)) return handler(context, next);
|
|
789
|
+
return next();
|
|
790
|
+
});
|
|
791
|
+
} else {
|
|
792
|
+
this.hooks.onApiCall.push(methodsOrHandler);
|
|
793
|
+
}
|
|
794
|
+
return this;
|
|
795
|
+
}
|
|
764
796
|
// onExperimental(
|
|
765
797
|
// // filter: Filters,
|
|
766
798
|
// filter: (
|
|
@@ -843,6 +875,11 @@ class Bot {
|
|
|
843
875
|
if (!updateName) this.onResponseError(onResponseError);
|
|
844
876
|
else this.onResponseError(updateName, onResponseError);
|
|
845
877
|
}
|
|
878
|
+
for (const value of plugin._.onApiCalls) {
|
|
879
|
+
const [onApiCall, methods] = value;
|
|
880
|
+
if (!methods) this.onApiCall(onApiCall);
|
|
881
|
+
else this.onApiCall(methods, onApiCall);
|
|
882
|
+
}
|
|
846
883
|
for (const handler of plugin._.groups) {
|
|
847
884
|
this.group(handler);
|
|
848
885
|
}
|
package/dist/index.d.cts
CHANGED
|
@@ -23,7 +23,7 @@ declare class TelegramError<T extends keyof APIMethods> extends Error {
|
|
|
23
23
|
/** Describes why a request was unsuccessful. */
|
|
24
24
|
payload?: TelegramResponseParameters;
|
|
25
25
|
/** Construct new TelegramError */
|
|
26
|
-
constructor(error: TelegramAPIResponseError, method: T, params: MaybeSuppressedParams<T
|
|
26
|
+
constructor(error: TelegramAPIResponseError, method: T, params: MaybeSuppressedParams<T>, callSite?: Error);
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
type MaybeArray<T> = T | T[] | ReadonlyArray<T>;
|
|
@@ -116,6 +116,8 @@ declare class Plugin<Errors extends ErrorDefinitions = {}, Derives extends Deriv
|
|
|
116
116
|
onResponses: [Hooks.OnResponse<any>, MaybeArray<keyof APIMethods> | undefined][];
|
|
117
117
|
/** Store plugin onResponseErrors hooks */
|
|
118
118
|
onResponseErrors: [Hooks.OnResponseError<any>, MaybeArray<keyof APIMethods> | undefined][];
|
|
119
|
+
/** Store plugin onApiCalls hooks */
|
|
120
|
+
onApiCalls: [Hooks.OnApiCall<any>, MaybeArray<keyof APIMethods> | undefined][];
|
|
119
121
|
/**
|
|
120
122
|
* Store plugin groups
|
|
121
123
|
*
|
|
@@ -152,6 +154,8 @@ declare class Plugin<Errors extends ErrorDefinitions = {}, Derives extends Deriv
|
|
|
152
154
|
onResponses: [Hooks.OnResponse<any>, MaybeArray<keyof APIMethods> | undefined][];
|
|
153
155
|
/** Store plugin onResponseErrors hooks */
|
|
154
156
|
onResponseErrors: [Hooks.OnResponseError<any>, MaybeArray<keyof APIMethods> | undefined][];
|
|
157
|
+
/** Store plugin onApiCalls hooks */
|
|
158
|
+
onApiCalls: [Hooks.OnApiCall<any>, MaybeArray<keyof APIMethods> | undefined][];
|
|
155
159
|
/**
|
|
156
160
|
* Store plugin groups
|
|
157
161
|
*
|
|
@@ -256,6 +260,21 @@ declare class Plugin<Errors extends ErrorDefinitions = {}, Derives extends Deriv
|
|
|
256
260
|
* */
|
|
257
261
|
onResponseError<Methods extends keyof APIMethods, Handler extends Hooks.OnResponseError<Methods>>(methods: MaybeArray<Methods>, handler: Handler): this;
|
|
258
262
|
onResponseError(handler: Hooks.OnResponseError): this;
|
|
263
|
+
/**
|
|
264
|
+
* This hook wraps the entire API call, enabling tracing/instrumentation.
|
|
265
|
+
*
|
|
266
|
+
* @example
|
|
267
|
+
* ```typescript
|
|
268
|
+
* const plugin = new Plugin("example").onApiCall(async (context, next) => {
|
|
269
|
+
* console.log(`Calling ${context.method}`);
|
|
270
|
+
* const result = await next();
|
|
271
|
+
* console.log(`${context.method} completed`);
|
|
272
|
+
* return result;
|
|
273
|
+
* });
|
|
274
|
+
* ```
|
|
275
|
+
* */
|
|
276
|
+
onApiCall<Methods extends keyof APIMethods, Handler extends Hooks.OnApiCall<Methods>>(methods: MaybeArray<Methods>, handler: Handler): this;
|
|
277
|
+
onApiCall(handler: Hooks.OnApiCall): this;
|
|
259
278
|
/**
|
|
260
279
|
* This hook called when the bot is `started`.
|
|
261
280
|
*
|
|
@@ -539,6 +558,27 @@ declare namespace Hooks {
|
|
|
539
558
|
* [Documentation](https://gramio.dev/hooks/on-response.html)
|
|
540
559
|
* */
|
|
541
560
|
type OnResponse<Methods extends keyof APIMethods = keyof APIMethods> = (context: AnyTelegramMethodWithReturn<Methods>) => unknown;
|
|
561
|
+
/** Argument type for {@link OnApiCall} */
|
|
562
|
+
type OnApiCallContext<Methods extends keyof APIMethods> = AnyTelegramMethod<Methods>;
|
|
563
|
+
/**
|
|
564
|
+
* Type for `onApiCall` hook (wrap-style)
|
|
565
|
+
*
|
|
566
|
+
* This hook wraps the entire API call execution, enabling span creation
|
|
567
|
+
* around API calls for tracing/instrumentation.
|
|
568
|
+
*
|
|
569
|
+
* @example
|
|
570
|
+
* ```typescript
|
|
571
|
+
* import { Bot } from "gramio";
|
|
572
|
+
*
|
|
573
|
+
* const bot = new Bot(process.env.TOKEN!).onApiCall(async (context, next) => {
|
|
574
|
+
* console.log(`Calling ${context.method}`);
|
|
575
|
+
* const result = await next();
|
|
576
|
+
* console.log(`${context.method} completed`);
|
|
577
|
+
* return result;
|
|
578
|
+
* });
|
|
579
|
+
* ```
|
|
580
|
+
* */
|
|
581
|
+
type OnApiCall<Methods extends keyof APIMethods = keyof APIMethods> = (context: OnApiCallContext<Methods>, next: () => Promise<unknown>) => Promise<unknown>;
|
|
542
582
|
/** Store hooks */
|
|
543
583
|
interface Store<T extends ErrorDefinitions> {
|
|
544
584
|
preRequest: PreRequest[];
|
|
@@ -547,6 +587,7 @@ declare namespace Hooks {
|
|
|
547
587
|
onError: OnError<T>[];
|
|
548
588
|
onStart: OnStart[];
|
|
549
589
|
onStop: OnStop[];
|
|
590
|
+
onApiCall: OnApiCall[];
|
|
550
591
|
}
|
|
551
592
|
}
|
|
552
593
|
/** Error map should be map of string: error */
|
|
@@ -634,7 +675,6 @@ declare class Bot<Errors extends ErrorDefinitions = {}, Derives extends DeriveDe
|
|
|
634
675
|
/** @deprecated @internal. Remap generic */
|
|
635
676
|
derives: Derives;
|
|
636
677
|
};
|
|
637
|
-
private filters;
|
|
638
678
|
/** Options provided to instance */
|
|
639
679
|
readonly options: BotOptions;
|
|
640
680
|
/** Bot data (filled in when calling bot.init/bot.start) */
|
|
@@ -843,6 +883,23 @@ declare class Bot<Errors extends ErrorDefinitions = {}, Derives extends DeriveDe
|
|
|
843
883
|
* */
|
|
844
884
|
onResponseError<Methods extends keyof APIMethods, Handler extends Hooks.OnResponseError<Methods>>(methods: MaybeArray<Methods>, handler: Handler): this;
|
|
845
885
|
onResponseError(handler: Hooks.OnResponseError): this;
|
|
886
|
+
/**
|
|
887
|
+
* This hook wraps the entire API call, enabling tracing/instrumentation.
|
|
888
|
+
*
|
|
889
|
+
* @example
|
|
890
|
+
* ```typescript
|
|
891
|
+
* import { Bot } from "gramio";
|
|
892
|
+
*
|
|
893
|
+
* const bot = new Bot(process.env.TOKEN!).onApiCall(async (context, next) => {
|
|
894
|
+
* console.log(`Calling ${context.method}`);
|
|
895
|
+
* const result = await next();
|
|
896
|
+
* console.log(`${context.method} completed`);
|
|
897
|
+
* return result;
|
|
898
|
+
* });
|
|
899
|
+
* ```
|
|
900
|
+
* */
|
|
901
|
+
onApiCall<Methods extends keyof APIMethods, Handler extends Hooks.OnApiCall<Methods>>(methods: MaybeArray<Methods>, handler: Handler): this;
|
|
902
|
+
onApiCall(handler: Hooks.OnApiCall): this;
|
|
846
903
|
/** Register handler to one or many Updates */
|
|
847
904
|
on<T extends UpdateName>(updateName: MaybeArray<T>, handler: Handler<ContextType<typeof this, T>>): this;
|
|
848
905
|
/** Register handler to any Updates */
|
package/dist/index.d.ts
CHANGED
|
@@ -23,7 +23,7 @@ declare class TelegramError<T extends keyof APIMethods> extends Error {
|
|
|
23
23
|
/** Describes why a request was unsuccessful. */
|
|
24
24
|
payload?: TelegramResponseParameters;
|
|
25
25
|
/** Construct new TelegramError */
|
|
26
|
-
constructor(error: TelegramAPIResponseError, method: T, params: MaybeSuppressedParams<T
|
|
26
|
+
constructor(error: TelegramAPIResponseError, method: T, params: MaybeSuppressedParams<T>, callSite?: Error);
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
type MaybeArray<T> = T | T[] | ReadonlyArray<T>;
|
|
@@ -116,6 +116,8 @@ declare class Plugin<Errors extends ErrorDefinitions = {}, Derives extends Deriv
|
|
|
116
116
|
onResponses: [Hooks.OnResponse<any>, MaybeArray<keyof APIMethods> | undefined][];
|
|
117
117
|
/** Store plugin onResponseErrors hooks */
|
|
118
118
|
onResponseErrors: [Hooks.OnResponseError<any>, MaybeArray<keyof APIMethods> | undefined][];
|
|
119
|
+
/** Store plugin onApiCalls hooks */
|
|
120
|
+
onApiCalls: [Hooks.OnApiCall<any>, MaybeArray<keyof APIMethods> | undefined][];
|
|
119
121
|
/**
|
|
120
122
|
* Store plugin groups
|
|
121
123
|
*
|
|
@@ -152,6 +154,8 @@ declare class Plugin<Errors extends ErrorDefinitions = {}, Derives extends Deriv
|
|
|
152
154
|
onResponses: [Hooks.OnResponse<any>, MaybeArray<keyof APIMethods> | undefined][];
|
|
153
155
|
/** Store plugin onResponseErrors hooks */
|
|
154
156
|
onResponseErrors: [Hooks.OnResponseError<any>, MaybeArray<keyof APIMethods> | undefined][];
|
|
157
|
+
/** Store plugin onApiCalls hooks */
|
|
158
|
+
onApiCalls: [Hooks.OnApiCall<any>, MaybeArray<keyof APIMethods> | undefined][];
|
|
155
159
|
/**
|
|
156
160
|
* Store plugin groups
|
|
157
161
|
*
|
|
@@ -256,6 +260,21 @@ declare class Plugin<Errors extends ErrorDefinitions = {}, Derives extends Deriv
|
|
|
256
260
|
* */
|
|
257
261
|
onResponseError<Methods extends keyof APIMethods, Handler extends Hooks.OnResponseError<Methods>>(methods: MaybeArray<Methods>, handler: Handler): this;
|
|
258
262
|
onResponseError(handler: Hooks.OnResponseError): this;
|
|
263
|
+
/**
|
|
264
|
+
* This hook wraps the entire API call, enabling tracing/instrumentation.
|
|
265
|
+
*
|
|
266
|
+
* @example
|
|
267
|
+
* ```typescript
|
|
268
|
+
* const plugin = new Plugin("example").onApiCall(async (context, next) => {
|
|
269
|
+
* console.log(`Calling ${context.method}`);
|
|
270
|
+
* const result = await next();
|
|
271
|
+
* console.log(`${context.method} completed`);
|
|
272
|
+
* return result;
|
|
273
|
+
* });
|
|
274
|
+
* ```
|
|
275
|
+
* */
|
|
276
|
+
onApiCall<Methods extends keyof APIMethods, Handler extends Hooks.OnApiCall<Methods>>(methods: MaybeArray<Methods>, handler: Handler): this;
|
|
277
|
+
onApiCall(handler: Hooks.OnApiCall): this;
|
|
259
278
|
/**
|
|
260
279
|
* This hook called when the bot is `started`.
|
|
261
280
|
*
|
|
@@ -539,6 +558,27 @@ declare namespace Hooks {
|
|
|
539
558
|
* [Documentation](https://gramio.dev/hooks/on-response.html)
|
|
540
559
|
* */
|
|
541
560
|
type OnResponse<Methods extends keyof APIMethods = keyof APIMethods> = (context: AnyTelegramMethodWithReturn<Methods>) => unknown;
|
|
561
|
+
/** Argument type for {@link OnApiCall} */
|
|
562
|
+
type OnApiCallContext<Methods extends keyof APIMethods> = AnyTelegramMethod<Methods>;
|
|
563
|
+
/**
|
|
564
|
+
* Type for `onApiCall` hook (wrap-style)
|
|
565
|
+
*
|
|
566
|
+
* This hook wraps the entire API call execution, enabling span creation
|
|
567
|
+
* around API calls for tracing/instrumentation.
|
|
568
|
+
*
|
|
569
|
+
* @example
|
|
570
|
+
* ```typescript
|
|
571
|
+
* import { Bot } from "gramio";
|
|
572
|
+
*
|
|
573
|
+
* const bot = new Bot(process.env.TOKEN!).onApiCall(async (context, next) => {
|
|
574
|
+
* console.log(`Calling ${context.method}`);
|
|
575
|
+
* const result = await next();
|
|
576
|
+
* console.log(`${context.method} completed`);
|
|
577
|
+
* return result;
|
|
578
|
+
* });
|
|
579
|
+
* ```
|
|
580
|
+
* */
|
|
581
|
+
type OnApiCall<Methods extends keyof APIMethods = keyof APIMethods> = (context: OnApiCallContext<Methods>, next: () => Promise<unknown>) => Promise<unknown>;
|
|
542
582
|
/** Store hooks */
|
|
543
583
|
interface Store<T extends ErrorDefinitions> {
|
|
544
584
|
preRequest: PreRequest[];
|
|
@@ -547,6 +587,7 @@ declare namespace Hooks {
|
|
|
547
587
|
onError: OnError<T>[];
|
|
548
588
|
onStart: OnStart[];
|
|
549
589
|
onStop: OnStop[];
|
|
590
|
+
onApiCall: OnApiCall[];
|
|
550
591
|
}
|
|
551
592
|
}
|
|
552
593
|
/** Error map should be map of string: error */
|
|
@@ -634,7 +675,6 @@ declare class Bot<Errors extends ErrorDefinitions = {}, Derives extends DeriveDe
|
|
|
634
675
|
/** @deprecated @internal. Remap generic */
|
|
635
676
|
derives: Derives;
|
|
636
677
|
};
|
|
637
|
-
private filters;
|
|
638
678
|
/** Options provided to instance */
|
|
639
679
|
readonly options: BotOptions;
|
|
640
680
|
/** Bot data (filled in when calling bot.init/bot.start) */
|
|
@@ -843,6 +883,23 @@ declare class Bot<Errors extends ErrorDefinitions = {}, Derives extends DeriveDe
|
|
|
843
883
|
* */
|
|
844
884
|
onResponseError<Methods extends keyof APIMethods, Handler extends Hooks.OnResponseError<Methods>>(methods: MaybeArray<Methods>, handler: Handler): this;
|
|
845
885
|
onResponseError(handler: Hooks.OnResponseError): this;
|
|
886
|
+
/**
|
|
887
|
+
* This hook wraps the entire API call, enabling tracing/instrumentation.
|
|
888
|
+
*
|
|
889
|
+
* @example
|
|
890
|
+
* ```typescript
|
|
891
|
+
* import { Bot } from "gramio";
|
|
892
|
+
*
|
|
893
|
+
* const bot = new Bot(process.env.TOKEN!).onApiCall(async (context, next) => {
|
|
894
|
+
* console.log(`Calling ${context.method}`);
|
|
895
|
+
* const result = await next();
|
|
896
|
+
* console.log(`${context.method} completed`);
|
|
897
|
+
* return result;
|
|
898
|
+
* });
|
|
899
|
+
* ```
|
|
900
|
+
* */
|
|
901
|
+
onApiCall<Methods extends keyof APIMethods, Handler extends Hooks.OnApiCall<Methods>>(methods: MaybeArray<Methods>, handler: Handler): this;
|
|
902
|
+
onApiCall(handler: Hooks.OnApiCall): this;
|
|
846
903
|
/** Register handler to one or many Updates */
|
|
847
904
|
on<T extends UpdateName>(updateName: MaybeArray<T>, handler: Handler<ContextType<typeof this, T>>): this;
|
|
848
905
|
/** Register handler to any Updates */
|
package/dist/index.js
CHANGED
|
@@ -9,7 +9,7 @@ export * from '@gramio/files';
|
|
|
9
9
|
import { FormattableMap } from '@gramio/format';
|
|
10
10
|
export * from '@gramio/format';
|
|
11
11
|
import debug from 'debug';
|
|
12
|
-
import { E as ErrorKind, s as sleep, w as withRetries, T as TelegramError, d as debug$updates, I as IS_BUN, a as simplifyObject, t as timeoutWebhook } from './utils-
|
|
12
|
+
import { E as ErrorKind, s as sleep, w as withRetries, T as TelegramError, d as debug$updates, I as IS_BUN, a as simplifyObject, t as timeoutWebhook } from './utils-En0iVLWH.js';
|
|
13
13
|
import { Composer as Composer$1, noopNext } from 'middleware-io';
|
|
14
14
|
export * from '@gramio/keyboards';
|
|
15
15
|
|
|
@@ -104,6 +104,8 @@ class Plugin {
|
|
|
104
104
|
onResponses: [],
|
|
105
105
|
/** Store plugin onResponseErrors hooks */
|
|
106
106
|
onResponseErrors: [],
|
|
107
|
+
/** Store plugin onApiCalls hooks */
|
|
108
|
+
onApiCalls: [],
|
|
107
109
|
/**
|
|
108
110
|
* Store plugin groups
|
|
109
111
|
*
|
|
@@ -187,6 +189,13 @@ class Plugin {
|
|
|
187
189
|
this._.onResponseErrors.push([methodsOrHandler, void 0]);
|
|
188
190
|
return this;
|
|
189
191
|
}
|
|
192
|
+
onApiCall(methodsOrHandler, handler) {
|
|
193
|
+
if ((typeof methodsOrHandler === "string" || Array.isArray(methodsOrHandler)) && handler)
|
|
194
|
+
this._.onApiCalls.push([handler, methodsOrHandler]);
|
|
195
|
+
else if (typeof methodsOrHandler === "function")
|
|
196
|
+
this._.onApiCalls.push([methodsOrHandler, void 0]);
|
|
197
|
+
return this;
|
|
198
|
+
}
|
|
190
199
|
/**
|
|
191
200
|
* This hook called when the bot is `started`.
|
|
192
201
|
*
|
|
@@ -429,9 +438,6 @@ class Bot {
|
|
|
429
438
|
/** @deprecated use `~.derives` instead @internal. Remap generic */
|
|
430
439
|
__Derives;
|
|
431
440
|
"~" = this._;
|
|
432
|
-
filters = {
|
|
433
|
-
context: (name) => (context) => context.is(name)
|
|
434
|
-
};
|
|
435
441
|
/** Options provided to instance */
|
|
436
442
|
options;
|
|
437
443
|
/** Bot data (filled in when calling bot.init/bot.start) */
|
|
@@ -453,7 +459,13 @@ class Bot {
|
|
|
453
459
|
get: (_target, method) => (
|
|
454
460
|
// @ts-expect-error
|
|
455
461
|
// biome-ignore lint/suspicious/noAssignInExpressions: <explanation>
|
|
456
|
-
_target[method] ??= (args) =>
|
|
462
|
+
_target[method] ??= (args) => {
|
|
463
|
+
const callSite = new Error();
|
|
464
|
+
if (Error.captureStackTrace) {
|
|
465
|
+
Error.captureStackTrace(callSite, _target[method]);
|
|
466
|
+
}
|
|
467
|
+
return this._callApi(method, args, callSite);
|
|
468
|
+
}
|
|
457
469
|
)
|
|
458
470
|
});
|
|
459
471
|
lazyloadPlugins = [];
|
|
@@ -479,7 +491,8 @@ class Bot {
|
|
|
479
491
|
onResponseError: [],
|
|
480
492
|
onError: [],
|
|
481
493
|
onStart: [],
|
|
482
|
-
onStop: []
|
|
494
|
+
onStop: [],
|
|
495
|
+
onApiCall: []
|
|
483
496
|
};
|
|
484
497
|
constructor(tokenOrOptions, optionsRaw) {
|
|
485
498
|
const token = typeof tokenOrOptions === "string" ? tokenOrOptions : tokenOrOptions?.token;
|
|
@@ -502,7 +515,10 @@ class Bot {
|
|
|
502
515
|
new Plugin("@gramio/format").preRequest((context) => {
|
|
503
516
|
if (!context.params) return context;
|
|
504
517
|
const formattable = FormattableMap[context.method];
|
|
505
|
-
if (formattable)
|
|
518
|
+
if (formattable)
|
|
519
|
+
context.params = formattable(
|
|
520
|
+
context.params
|
|
521
|
+
);
|
|
506
522
|
return context;
|
|
507
523
|
})
|
|
508
524
|
);
|
|
@@ -519,63 +535,66 @@ class Bot {
|
|
|
519
535
|
await hook(...context);
|
|
520
536
|
}
|
|
521
537
|
}
|
|
522
|
-
async _callApi(method, params = {}) {
|
|
523
|
-
const
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
"preRequest",
|
|
533
|
-
// TODO: fix type error
|
|
534
|
-
// @ts-expect-error
|
|
535
|
-
{
|
|
538
|
+
async _callApi(method, params = {}, callSite) {
|
|
539
|
+
const executeCall = async () => {
|
|
540
|
+
const debug$api$method = debug(`gramio:api:${method}`);
|
|
541
|
+
let url = `${this.options.api.baseURL}${this.options.token}/${this.options.api.useTest ? "test/" : ""}${method}`;
|
|
542
|
+
const reqOptions = {
|
|
543
|
+
method: "POST",
|
|
544
|
+
...this.options.api.fetchOptions,
|
|
545
|
+
headers: new Headers(this.options.api.fetchOptions?.headers)
|
|
546
|
+
};
|
|
547
|
+
const context = await this.runHooks("preRequest", {
|
|
536
548
|
method,
|
|
537
549
|
params
|
|
538
|
-
}
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
550
|
+
});
|
|
551
|
+
params = context.params;
|
|
552
|
+
if (params && isMediaUpload(method, params)) {
|
|
553
|
+
if (IS_BUN) {
|
|
554
|
+
const formData = await convertJsonToFormData(method, params);
|
|
555
|
+
reqOptions.body = formData;
|
|
556
|
+
} else {
|
|
557
|
+
const [formData, paramsWithoutFiles] = await extractFilesToFormData(
|
|
558
|
+
method,
|
|
559
|
+
params
|
|
560
|
+
);
|
|
561
|
+
reqOptions.body = formData;
|
|
562
|
+
const simplifiedParams = simplifyObject(paramsWithoutFiles);
|
|
563
|
+
url += `?${new URLSearchParams(simplifiedParams).toString()}`;
|
|
564
|
+
}
|
|
545
565
|
} else {
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
params
|
|
549
|
-
);
|
|
550
|
-
reqOptions.body = formData;
|
|
551
|
-
const simplifiedParams = simplifyObject(paramsWithoutFiles);
|
|
552
|
-
url += `?${new URLSearchParams(simplifiedParams).toString()}`;
|
|
566
|
+
reqOptions.headers.set("Content-Type", "application/json");
|
|
567
|
+
reqOptions.body = JSON.stringify(params);
|
|
553
568
|
}
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
const err = new TelegramError(data, method, params);
|
|
564
|
-
this.runImmutableHooks("onResponseError", err, this.api);
|
|
565
|
-
if (!params?.suppress) throw err;
|
|
566
|
-
return err;
|
|
567
|
-
}
|
|
568
|
-
this.runImmutableHooks(
|
|
569
|
-
"onResponse",
|
|
570
|
-
// TODO: fix type error
|
|
571
|
-
// @ts-expect-error
|
|
572
|
-
{
|
|
573
|
-
method,
|
|
574
|
-
params,
|
|
575
|
-
response: data.result
|
|
569
|
+
debug$api$method("options: %j", reqOptions);
|
|
570
|
+
const response = await fetch(url, reqOptions);
|
|
571
|
+
const data = await response.json();
|
|
572
|
+
debug$api$method("response: %j", data);
|
|
573
|
+
if (!data.ok) {
|
|
574
|
+
const err = new TelegramError(data, method, params, callSite);
|
|
575
|
+
this.runImmutableHooks("onResponseError", err, this.api);
|
|
576
|
+
if (!params?.suppress) throw err;
|
|
577
|
+
return err;
|
|
576
578
|
}
|
|
577
|
-
|
|
578
|
-
|
|
579
|
+
this.runImmutableHooks(
|
|
580
|
+
"onResponse",
|
|
581
|
+
// TODO: fix type error
|
|
582
|
+
// @ts-expect-error
|
|
583
|
+
{
|
|
584
|
+
method,
|
|
585
|
+
params,
|
|
586
|
+
response: data.result
|
|
587
|
+
}
|
|
588
|
+
);
|
|
589
|
+
return data.result;
|
|
590
|
+
};
|
|
591
|
+
if (!this.hooks.onApiCall.length) return executeCall();
|
|
592
|
+
let fn = executeCall;
|
|
593
|
+
for (const hook of [...this.hooks.onApiCall].reverse()) {
|
|
594
|
+
const prev = fn;
|
|
595
|
+
fn = () => hook({ method, params }, prev);
|
|
596
|
+
}
|
|
597
|
+
return fn();
|
|
579
598
|
}
|
|
580
599
|
async downloadFile(attachment, path) {
|
|
581
600
|
function getFileId(attachment2) {
|
|
@@ -763,6 +782,19 @@ class Bot {
|
|
|
763
782
|
} else this.hooks.onResponseError.push(methodsOrHandler);
|
|
764
783
|
return this;
|
|
765
784
|
}
|
|
785
|
+
onApiCall(methodsOrHandler, handler) {
|
|
786
|
+
if (typeof methodsOrHandler === "string" || Array.isArray(methodsOrHandler)) {
|
|
787
|
+
if (!handler) throw new Error("TODO:");
|
|
788
|
+
const methods = typeof methodsOrHandler === "string" ? [methodsOrHandler] : methodsOrHandler;
|
|
789
|
+
this.hooks.onApiCall.push(async (context, next) => {
|
|
790
|
+
if (methods.includes(context.method)) return handler(context, next);
|
|
791
|
+
return next();
|
|
792
|
+
});
|
|
793
|
+
} else {
|
|
794
|
+
this.hooks.onApiCall.push(methodsOrHandler);
|
|
795
|
+
}
|
|
796
|
+
return this;
|
|
797
|
+
}
|
|
766
798
|
// onExperimental(
|
|
767
799
|
// // filter: Filters,
|
|
768
800
|
// filter: (
|
|
@@ -845,6 +877,11 @@ class Bot {
|
|
|
845
877
|
if (!updateName) this.onResponseError(onResponseError);
|
|
846
878
|
else this.onResponseError(updateName, onResponseError);
|
|
847
879
|
}
|
|
880
|
+
for (const value of plugin._.onApiCalls) {
|
|
881
|
+
const [onApiCall, methods] = value;
|
|
882
|
+
if (!methods) this.onApiCall(onApiCall);
|
|
883
|
+
else this.onApiCall(methods, onApiCall);
|
|
884
|
+
}
|
|
848
885
|
for (const handler of plugin._.groups) {
|
|
849
886
|
this.group(handler);
|
|
850
887
|
}
|
|
@@ -13,13 +13,19 @@ class TelegramError extends Error {
|
|
|
13
13
|
/** Describes why a request was unsuccessful. */
|
|
14
14
|
payload;
|
|
15
15
|
/** Construct new TelegramError */
|
|
16
|
-
constructor(error, method, params) {
|
|
16
|
+
constructor(error, method, params, callSite) {
|
|
17
17
|
super(error.description);
|
|
18
18
|
this.name = method;
|
|
19
19
|
this.method = method;
|
|
20
20
|
this.params = params;
|
|
21
21
|
this.code = error.error_code;
|
|
22
22
|
if (error.parameters) this.payload = error.parameters;
|
|
23
|
+
if (callSite?.stack) {
|
|
24
|
+
const callSiteLines = callSite.stack.split("\n");
|
|
25
|
+
const relevantFrames = callSiteLines.slice(1);
|
|
26
|
+
this.stack = `${this.name}: ${this.message}
|
|
27
|
+
${relevantFrames.join("\n")}`;
|
|
28
|
+
}
|
|
23
29
|
}
|
|
24
30
|
}
|
|
25
31
|
TelegramError.constructor[ErrorKind] = "TELEGRAM";
|
|
@@ -11,13 +11,19 @@ class TelegramError extends Error {
|
|
|
11
11
|
/** Describes why a request was unsuccessful. */
|
|
12
12
|
payload;
|
|
13
13
|
/** Construct new TelegramError */
|
|
14
|
-
constructor(error, method, params) {
|
|
14
|
+
constructor(error, method, params, callSite) {
|
|
15
15
|
super(error.description);
|
|
16
16
|
this.name = method;
|
|
17
17
|
this.method = method;
|
|
18
18
|
this.params = params;
|
|
19
19
|
this.code = error.error_code;
|
|
20
20
|
if (error.parameters) this.payload = error.parameters;
|
|
21
|
+
if (callSite?.stack) {
|
|
22
|
+
const callSiteLines = callSite.stack.split("\n");
|
|
23
|
+
const relevantFrames = callSiteLines.slice(1);
|
|
24
|
+
this.stack = `${this.name}: ${this.message}
|
|
25
|
+
${relevantFrames.join("\n")}`;
|
|
26
|
+
}
|
|
21
27
|
}
|
|
22
28
|
}
|
|
23
29
|
TelegramError.constructor[ErrorKind] = "TELEGRAM";
|
package/dist/utils.cjs
CHANGED
package/dist/utils.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { w as withRetries } from './utils-
|
|
1
|
+
export { w as withRetries } from './utils-En0iVLWH.js';
|
|
2
2
|
import 'debug';
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gramio",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.4.
|
|
4
|
+
"version": "0.4.13",
|
|
5
5
|
"description": "Powerful, extensible and really type-safe Telegram Bot API framework",
|
|
6
6
|
"main": "dist/index.cjs",
|
|
7
7
|
"module": "dist/index.js",
|
|
@@ -56,10 +56,10 @@
|
|
|
56
56
|
"license": "MIT",
|
|
57
57
|
"devDependencies": {
|
|
58
58
|
"@biomejs/biome": "2.3.14",
|
|
59
|
-
"@types/bun": "^1.3.
|
|
59
|
+
"@types/bun": "^1.3.9",
|
|
60
60
|
"@types/debug": "^4.1.12",
|
|
61
61
|
"expect-type": "^1.3.0",
|
|
62
|
-
"pkgroll": "^2.
|
|
62
|
+
"pkgroll": "^2.24.0",
|
|
63
63
|
"typescript": "^5.9.3"
|
|
64
64
|
},
|
|
65
65
|
"dependencies": {
|
|
@@ -68,7 +68,7 @@
|
|
|
68
68
|
"@gramio/files": "^0.3.0",
|
|
69
69
|
"@gramio/format": "^0.3.4",
|
|
70
70
|
"@gramio/keyboards": "^1.3.0",
|
|
71
|
-
"@gramio/types": "^9.
|
|
71
|
+
"@gramio/types": "^9.4.0",
|
|
72
72
|
"debug": "^4.4.3",
|
|
73
73
|
"middleware-io": "^2.8.1"
|
|
74
74
|
},
|