gramio 0.0.18 → 0.0.20

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.d.ts CHANGED
@@ -1,13 +1,14 @@
1
1
  import { Context, ContextType, MaybeArray, UpdateName } from "@gramio/contexts";
2
2
  import type { APIMethodParams, APIMethods, TelegramUser } from "@gramio/types";
3
3
  import { Plugin } from "./plugin";
4
- import { BotOptions, DeriveDefinitions, ErrorDefinitions, Handler, Hooks } from "./types";
4
+ import { BotOptions, DeriveDefinitions, ErrorDefinitions, Handler, Hooks, MaybePromise } from "./types";
5
5
  import { Updates } from "./updates";
6
6
  export declare class Bot<Errors extends ErrorDefinitions = {}, Derives extends DeriveDefinitions = DeriveDefinitions> {
7
7
  __Derives: Derives;
8
8
  readonly options: BotOptions;
9
9
  info: TelegramUser | undefined;
10
10
  readonly api: APIMethods;
11
+ private lazyloadPlugins;
11
12
  private dependencies;
12
13
  private errorsDefinitions;
13
14
  private errorHandler;
@@ -69,9 +70,13 @@ export declare class Bot<Errors extends ErrorDefinitions = {}, Derives extends D
69
70
  [K in Update]: Awaited<ReturnType<Handler>>;
70
71
  }>;
71
72
  onStart(handler: Hooks.OnStart): this;
73
+ preRequest<Methods extends keyof APIMethods, Handler extends Hooks.PreRequest<Methods>>(methods: MaybeArray<Methods>, handler: Handler): this;
74
+ preRequest(handler: Hooks.PreRequest): this;
72
75
  on<T extends UpdateName>(updateName: MaybeArray<T>, handler: Handler<ContextType<typeof this, T> & Derives["global"] & Derives[T]>): this;
73
76
  use(handler: Handler<Context<typeof this> & Derives["global"]>): this;
74
- extend<NewPlugin extends Plugin>(plugin: NewPlugin): Bot<Errors & NewPlugin["Errors"], Derives & NewPlugin["Derives"]>;
77
+ extend<NewPlugin extends Plugin>(plugin: MaybePromise<NewPlugin>): Bot<Errors & NewPlugin["Errors"], Derives & NewPlugin["Derives"]>;
78
+ hears<Ctx = ContextType<typeof this, "message"> & Derives["global"] & Derives["message"]>(trigger: RegExp | string | ((context: Ctx) => boolean), handler: (context: Ctx) => unknown): void;
79
+ command(command: string, handler: (context: ContextType<typeof this, "message"> & Derives["global"] & Derives["message"]) => unknown): void;
75
80
  start({ webhook, dropPendingUpdates, allowedUpdates, }?: {
76
81
  webhook?: Omit<APIMethodParams<"setWebhook">, "drop_pending_updates" | "allowed_updates">;
77
82
  dropPendingUpdates?: boolean;
package/dist/bot.js CHANGED
@@ -37,7 +37,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
37
37
  exports.Bot = void 0;
38
38
  const files_1 = require("@gramio/files");
39
39
  const format_1 = require("@gramio/format");
40
- const form_data_encoder_1 = require("form-data-encoder");
41
40
  const inspectable_1 = require("inspectable");
42
41
  const undici_1 = require("undici");
43
42
  const errors_1 = require("./errors");
@@ -64,6 +63,7 @@ let Bot = (() => {
64
63
  api = new Proxy({}, {
65
64
  get: (_target, method) => (args) => this._callApi(method, args),
66
65
  });
66
+ lazyloadPlugins = [];
67
67
  dependencies = [];
68
68
  errorsDefinitions = {
69
69
  TELEGRAM: errors_1.TelegramError,
@@ -79,20 +79,22 @@ let Bot = (() => {
79
79
  updates = new updates_1.Updates(this, this.errorHandler.bind(this));
80
80
  hooks = {
81
81
  preRequest: [
82
- (ctx) => {
83
- if (!ctx.params)
84
- return ctx;
85
- const formattable = format_1.FormattableMap[ctx.method];
82
+ (context) => {
83
+ if (!context.params)
84
+ return context;
85
+ const formattable = format_1.FormattableMap[context.method];
86
86
  // @ts-ignore add AnyTelegramMethod to @gramio/format
87
87
  if (formattable)
88
- ctx.params = formattable(ctx.params);
89
- return ctx;
88
+ context.params = formattable(context.params);
89
+ return context;
90
90
  },
91
91
  ],
92
92
  onError: [],
93
93
  onStart: [],
94
94
  };
95
95
  constructor(token, options) {
96
+ if (!token || typeof token !== "string")
97
+ throw new Error(`Token is ${typeof token} but it should be a string!`);
96
98
  this.options = { ...options, token };
97
99
  }
98
100
  async runHooks(type, context) {
@@ -113,7 +115,6 @@ let Bot = (() => {
113
115
  const url = `https://api.telegram.org/bot${this.options.token}/${method}`;
114
116
  const reqOptions = {
115
117
  method: "POST",
116
- duplex: "half",
117
118
  };
118
119
  const context = await this.runHooks("preRequest",
119
120
  // TODO: fix type error
@@ -126,9 +127,7 @@ let Bot = (() => {
126
127
  params = context.params;
127
128
  if (params && (0, files_1.isMediaUpload)(method, params)) {
128
129
  const formData = await (0, files_1.convertJsonToFormData)(method, params);
129
- const encoder = new form_data_encoder_1.FormDataEncoder(formData);
130
- reqOptions.body = encoder.encode();
131
- reqOptions.headers = encoder.headers;
130
+ reqOptions.body = formData;
132
131
  }
133
132
  else {
134
133
  reqOptions.headers = {
@@ -136,8 +135,8 @@ let Bot = (() => {
136
135
  };
137
136
  reqOptions.body = JSON.stringify(params);
138
137
  }
139
- const response = await (0, undici_1.fetch)(url, reqOptions);
140
- const data = (await response.json());
138
+ const response = await (0, undici_1.request)(url, reqOptions);
139
+ const data = (await response.body.json());
141
140
  if (!data.ok)
142
141
  throw new errors_1.TelegramError(data, method, params);
143
142
  return data.result;
@@ -214,6 +213,29 @@ let Bot = (() => {
214
213
  this.hooks.onStart.push(handler);
215
214
  return this;
216
215
  }
216
+ preRequest(methodsOrHandler, handler) {
217
+ if (typeof methodsOrHandler === "string" ||
218
+ Array.isArray(methodsOrHandler)) {
219
+ // TODO: error
220
+ if (!handler)
221
+ throw new Error("TODO:");
222
+ const methods = typeof methodsOrHandler === "string"
223
+ ? [methodsOrHandler]
224
+ : methodsOrHandler;
225
+ // TODO: remove error
226
+ // @ts-expect-error
227
+ this.hooks.preRequest.push(async (context) => {
228
+ // TODO: remove ts-ignore
229
+ // @ts-expect-error
230
+ if (methods.includes(context.method))
231
+ return handler(context);
232
+ return context;
233
+ });
234
+ }
235
+ else
236
+ this.hooks.preRequest.push(methodsOrHandler);
237
+ return this;
238
+ }
217
239
  on(updateName, handler) {
218
240
  this.updates.on(updateName, handler);
219
241
  return this;
@@ -223,6 +245,10 @@ let Bot = (() => {
223
245
  return this;
224
246
  }
225
247
  extend(plugin) {
248
+ if (plugin instanceof Promise) {
249
+ this.lazyloadPlugins.push(plugin);
250
+ return this;
251
+ }
226
252
  if (plugin.dependencies.some((dep) => !this.dependencies.includes(dep)))
227
253
  throw new Error(`The «${plugin.name}» plugin needs dependencies registered before: ${plugin.dependencies
228
254
  .filter((dep) => !this.dependencies.includes(dep))
@@ -241,8 +267,38 @@ let Bot = (() => {
241
267
  this.dependencies.push(plugin.name);
242
268
  return this;
243
269
  }
270
+ hears(trigger, handler) {
271
+ this.on("message", (context, next) => {
272
+ if ((typeof trigger === "string" && context.text === trigger) ||
273
+ // @ts-expect-error
274
+ (typeof trigger === "function" && trigger(context)) ||
275
+ (trigger instanceof RegExp &&
276
+ context.text &&
277
+ trigger.test(context.text))) {
278
+ // TODO: remove
279
+ //@ts-expect-error
280
+ return handler(context);
281
+ }
282
+ return next();
283
+ });
284
+ }
285
+ command(command, handler) {
286
+ this.on("message", (context, next) => {
287
+ if (context.entities?.some((entity) => {
288
+ if (entity.type !== "bot_command" || entity.offset > 0)
289
+ return false;
290
+ const cmd = context.text
291
+ ?.slice(1, entity.length)
292
+ // biome-ignore lint/style/noNonNullAssertion: <explanation>
293
+ ?.replace(`@${this.info.username}`, "");
294
+ return cmd && cmd === command;
295
+ }))
296
+ return handler(context);
297
+ return next();
298
+ });
299
+ }
244
300
  async start({ webhook, dropPendingUpdates, allowedUpdates, } = {}) {
245
- //TODO: maybe it useless??
301
+ await Promise.all(this.lazyloadPlugins.map(async (plugin) => this.extend(await plugin)));
246
302
  this.info = await this.api.getMe();
247
303
  if (!webhook) {
248
304
  await this.api.deleteWebhook({
package/dist/types.d.ts CHANGED
@@ -14,17 +14,17 @@ interface ErrorHandlerParams<Ctx extends Context<BotLike>, Kind extends string,
14
14
  type AnyTelegramError = {
15
15
  [APIMethod in keyof APIMethods]: TelegramError<APIMethod>;
16
16
  }[keyof APIMethods];
17
- type AnyTelegramMethod = {
18
- [APIMethod in keyof APIMethods]: {
17
+ type AnyTelegramMethod<Methods extends keyof APIMethods> = {
18
+ [APIMethod in Methods]: {
19
19
  method: APIMethod;
20
20
  params: APIMethodParams<APIMethod>;
21
21
  };
22
- }[keyof APIMethods];
22
+ }[Methods];
23
23
  export type MaybePromise<T> = Promise<T> | T;
24
24
  export declare namespace Hooks {
25
25
  type Derive<Ctx> = (context: Ctx) => MaybePromise<Record<string, unknown>>;
26
- type PreRequestContext = AnyTelegramMethod;
27
- type PreRequest = (ctx: PreRequestContext) => MaybePromise<PreRequestContext>;
26
+ type PreRequestContext<Methods extends keyof APIMethods> = AnyTelegramMethod<Methods>;
27
+ type PreRequest<Methods extends keyof APIMethods = keyof APIMethods> = (ctx: PreRequestContext<Methods>) => MaybePromise<PreRequestContext<Methods>>;
28
28
  type OnErrorContext<Ctx extends Context<BotLike>, T extends ErrorDefinitions> = ErrorHandlerParams<Ctx, "TELEGRAM", AnyTelegramError> | ErrorHandlerParams<Ctx, "UNKNOWN", Error> | {
29
29
  [K in keyof T]: ErrorHandlerParams<Ctx, K & string, T[K & string]>;
30
30
  }[keyof T];
package/dist/updates.js CHANGED
@@ -32,7 +32,7 @@ class Updates {
32
32
  this.offset = data.update_id + 1;
33
33
  const UpdateContext = contexts_1.contextsMappings[updateType];
34
34
  if (!UpdateContext)
35
- return;
35
+ throw new Error(updateType);
36
36
  try {
37
37
  let context = new UpdateContext({
38
38
  bot: this.bot,
@@ -74,8 +74,8 @@ class Updates {
74
74
  async startFetchLoop(params = {}) {
75
75
  while (this.isStarted) {
76
76
  const updates = await this.bot.api.getUpdates({
77
- offset: this.offset,
78
77
  ...params,
78
+ offset: this.offset,
79
79
  });
80
80
  for await (const update of updates) {
81
81
  //TODO: update errors
@@ -1,6 +1,7 @@
1
1
  import { TelegramUpdate } from "@gramio/types";
2
+ import { MaybePromise } from "../types";
2
3
  export interface FrameworkHandler {
3
- update: TelegramUpdate;
4
+ update: MaybePromise<TelegramUpdate>;
4
5
  header?: string;
5
6
  }
6
7
  export type FrameworkAdapter = (...args: any[]) => FrameworkHandler;
@@ -13,4 +14,12 @@ export declare const frameworks: {
13
14
  update: any;
14
15
  header: any;
15
16
  };
17
+ hono: (c: any) => {
18
+ update: any;
19
+ header: any;
20
+ };
21
+ express: (req: any) => {
22
+ update: any;
23
+ header: any;
24
+ };
16
25
  };
@@ -11,4 +11,12 @@ exports.frameworks = {
11
11
  update: request.body,
12
12
  header: request.headers[SECRET_TOKEN_HEADER],
13
13
  }),
14
+ hono: (c) => ({
15
+ update: c.req.json(),
16
+ header: c.req.header(SECRET_TOKEN_HEADER)
17
+ }),
18
+ express: (req) => ({
19
+ update: req.body,
20
+ header: req.header(SECRET_TOKEN_HEADER)
21
+ })
14
22
  };
@@ -6,7 +6,7 @@ function webhookHandler(bot, framework) {
6
6
  const frameworkAdapter = adapters_1.frameworks[framework];
7
7
  return async (...args) => {
8
8
  const { update } = frameworkAdapter(...args);
9
- await bot.updates.handleUpdate(update);
9
+ await bot.updates.handleUpdate(await update);
10
10
  };
11
11
  }
12
12
  exports.webhookHandler = webhookHandler;
package/package.json CHANGED
@@ -1,45 +1,44 @@
1
1
  {
2
- "name": "gramio",
3
- "version": "0.0.18",
4
- "description": "Powerful Telegram Bot API framework",
5
- "main": "./dist/index.js",
6
- "types": "./dist/index.d.ts",
7
- "keywords": [
8
- "telegram",
9
- "telegram-bot",
10
- "telegram-bot-api",
11
- "bot",
12
- "framework",
13
- "types",
14
- "client",
15
- "webhook",
16
- "long-polling"
17
- ],
18
- "scripts": {
19
- "type": "tsc --noEmit",
20
- "lint": "bun check ./src",
21
- "lint:fix": "bun lint --apply",
22
- "prepublishOnly": "tsc && bunx tsc-alias"
23
- },
24
- "author": "kravets",
25
- "license": "ISC",
26
- "devDependencies": {
27
- "@biomejs/biome": "1.5.3",
28
- "@gramio/types": "^7.1.4",
29
- "@types/node": "^20.11.20",
30
- "typescript": "^5.3.3"
31
- },
32
- "dependencies": {
33
- "@gramio/contexts": "^0.0.6",
34
- "@gramio/files": "^0.0.3",
35
- "@gramio/format": "^0.0.8",
36
- "@gramio/keyboards": "^0.2.0",
37
- "form-data-encoder": "^4.0.2",
38
- "inspectable": "^3.0.0",
39
- "middleware-io": "^2.8.1",
40
- "undici": "^6.6.2"
41
- },
42
- "files": [
43
- "dist"
44
- ]
2
+ "name": "gramio",
3
+ "version": "0.0.20",
4
+ "description": "Powerful Telegram Bot API framework",
5
+ "main": "./dist/index.js",
6
+ "types": "./dist/index.d.ts",
7
+ "keywords": [
8
+ "telegram",
9
+ "telegram-bot",
10
+ "telegram-bot-api",
11
+ "bot",
12
+ "framework",
13
+ "types",
14
+ "client",
15
+ "webhook",
16
+ "long-polling"
17
+ ],
18
+ "scripts": {
19
+ "type": "tsc --noEmit",
20
+ "lint": "bun check ./src",
21
+ "lint:fix": "bun lint --apply",
22
+ "prepublishOnly": "tsc && bunx tsc-alias"
23
+ },
24
+ "author": "kravets",
25
+ "license": "ISC",
26
+ "devDependencies": {
27
+ "@biomejs/biome": "1.5.3",
28
+ "@gramio/types": "^7.1.6",
29
+ "@types/node": "^20.11.25",
30
+ "typescript": "^5.4.2"
31
+ },
32
+ "dependencies": {
33
+ "@gramio/contexts": "^0.0.7",
34
+ "@gramio/files": "^0.0.3",
35
+ "@gramio/format": "^0.0.8",
36
+ "@gramio/keyboards": "^0.2.0",
37
+ "inspectable": "^3.0.0",
38
+ "middleware-io": "^2.8.1",
39
+ "undici": "^6.7.1"
40
+ },
41
+ "files": [
42
+ "dist"
43
+ ]
45
44
  }