gramio 0.0.35 → 0.0.37

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.md CHANGED
@@ -36,7 +36,7 @@ and GramIO customize your project the way you want it!
36
36
  ```typescript
37
37
  import { Bot } from "gramio";
38
38
 
39
- const bot = new Bot()
39
+ const bot = new Bot(process.env.TOKEN as string)
40
40
  .command("start", (context) => context.send("Hello!"))
41
41
  .onStart(({ info }) => console.log(`✨ Bot ${info.username} was started!`));
42
42
 
package/dist/bot.d.ts CHANGED
@@ -44,8 +44,12 @@ export declare class Bot<Errors extends ErrorDefinitions = {}, Derives extends D
44
44
  /** This instance handle updates */
45
45
  updates: Updates;
46
46
  private hooks;
47
- /** Create new Bot instance */
48
- constructor(token: string, options?: Omit<BotOptions, "token">);
47
+ constructor(token: string, options?: Omit<BotOptions, "token" | "api"> & {
48
+ api?: Partial<BotOptions["api"]>;
49
+ });
50
+ constructor(options: Omit<BotOptions, "api"> & {
51
+ api?: Partial<BotOptions["api"]>;
52
+ });
49
53
  private runHooks;
50
54
  private runImmutableHooks;
51
55
  private _callApi;
package/dist/bot.js CHANGED
@@ -81,7 +81,7 @@ let Bot = (() => {
81
81
  /** @internal. Remap generic */
82
82
  __Derives;
83
83
  /** Options provided to instance */
84
- options = {};
84
+ options;
85
85
  /** Bot data (filled in when calling bot.init/bot.start) */
86
86
  info;
87
87
  /**
@@ -106,6 +106,8 @@ let Bot = (() => {
106
106
  TELEGRAM: errors_1.TelegramError,
107
107
  };
108
108
  errorHandler(context, error) {
109
+ if (!this.hooks.onError.length)
110
+ throw error;
109
111
  return this.runImmutableHooks("onError", {
110
112
  context,
111
113
  //@ts-expect-error ErrorKind exists if user register error-class with .error("kind", SomeError);
@@ -123,11 +125,17 @@ let Bot = (() => {
123
125
  onStart: [],
124
126
  onStop: [],
125
127
  };
126
- /** Create new Bot instance */
127
- constructor(token, options) {
128
+ constructor(tokenOrOptions, options) {
129
+ const token = typeof tokenOrOptions === "string"
130
+ ? tokenOrOptions
131
+ : tokenOrOptions?.token;
128
132
  if (!token || typeof token !== "string")
129
133
  throw new Error(`Token is ${typeof token} but it should be a string!`);
130
- this.options = { ...options, token };
134
+ this.options = {
135
+ ...(typeof tokenOrOptions === "object" ? tokenOrOptions : options),
136
+ token,
137
+ api: { ...options?.api, baseURL: "https://api.telegram.org/bot" },
138
+ };
131
139
  if (!(options?.plugins &&
132
140
  "format" in options.plugins &&
133
141
  !options.plugins.format))
@@ -156,7 +164,7 @@ let Bot = (() => {
156
164
  }
157
165
  }
158
166
  async _callApi(method, params = {}) {
159
- const url = `https://api.telegram.org/bot${this.options.token}/${method}`;
167
+ const url = `${this.options.api.baseURL}${this.options.token}/${method}`;
160
168
  const reqOptions = {
161
169
  method: "POST",
162
170
  };
@@ -212,7 +220,7 @@ let Bot = (() => {
212
220
  }
213
221
  const fileId = typeof attachment === "string" ? attachment : getFileId(attachment);
214
222
  const file = await this.api.getFile({ file_id: fileId });
215
- const url = `https://api.telegram.org/file/bot${this.options.token}/${file.file_path}`;
223
+ const url = `${this.options.api.baseURL.replace("/bot", "/file/bot")}${this.options.token}/${file.file_path}`;
216
224
  const res = await (0, undici_1.request)(url);
217
225
  const buffer = await res.body.arrayBuffer();
218
226
  if (path) {
@@ -539,8 +547,9 @@ let Bot = (() => {
539
547
  return next();
540
548
  if (trigger instanceof RegExp && !trigger.test(context.data))
541
549
  return next();
542
- // @ts-expect-error
543
- context.queryData = trigger.unpack(context.data);
550
+ if (trigger instanceof callback_data_1.CallbackData)
551
+ // @ts-expect-error
552
+ context.queryData = trigger.unpack(context.data);
544
553
  //@ts-expect-error
545
554
  return handler(context);
546
555
  });
package/dist/composer.js CHANGED
@@ -11,9 +11,7 @@ class Composer {
11
11
  constructor(onError) {
12
12
  this.onError =
13
13
  onError ||
14
- ((context, error) => {
15
- // @ts-expect-error
16
- error.context = context;
14
+ ((_, error) => {
17
15
  throw error;
18
16
  });
19
17
  this.recompose();
package/dist/plugin.d.ts CHANGED
@@ -138,7 +138,7 @@ export declare class Plugin<Errors extends ErrorDefinitions = {}, Derives extend
138
138
  preRequest<Methods extends keyof APIMethods, Handler extends Hooks.PreRequest<Methods>>(methods: MaybeArray<Methods>, handler: Handler): this;
139
139
  preRequest(handler: Hooks.PreRequest): this;
140
140
  /**
141
- * This hook called when API return sucesfull response
141
+ * This hook called when API return successful response
142
142
  *
143
143
  * [Documentation](https://gramio.dev/hooks/on-response.html)
144
144
  * */
package/dist/types.d.ts CHANGED
@@ -6,10 +6,26 @@ import type { TelegramError } from "./errors";
6
6
  import type { Plugin } from "./plugin";
7
7
  /** Bot options that you can provide to {@link Bot} constructor */
8
8
  export interface BotOptions {
9
- token?: string;
9
+ /** Bot token */
10
+ token: string;
11
+ /** List of plugins enabled by default */
10
12
  plugins?: {
13
+ /** Pass `false` to disable plugin. @default true */
11
14
  format?: boolean;
12
15
  };
16
+ /** Options to configure how to send requests to the Telegram Bot API */
17
+ api: {
18
+ /** URL which will be used to send requests to. @default "https://api.telegram.org/bot" */
19
+ baseURL: string;
20
+ /**
21
+ * Should we send requests to `test` data center?
22
+ * The test environment is completely separate from the main environment, so you will need to create a new user account and a new bot with `@BotFather`.
23
+ *
24
+ * [Documentation](https://core.telegram.org/bots/webapps#using-bots-in-the-test-environment)
25
+ * @default false
26
+ * */
27
+ useTest?: boolean;
28
+ };
13
29
  }
14
30
  /**
15
31
  * Handler is a function with context and next function arguments
package/dist/updates.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { type Context } from "@gramio/contexts";
2
2
  import type { APIMethodParams, TelegramUpdate } from "@gramio/types";
3
- import { type CaughtMiddlewareHandler } from "middleware-io";
3
+ import type { CaughtMiddlewareHandler } from "middleware-io";
4
4
  import { Composer } from "./composer";
5
5
  import type { AnyBot } from "./types";
6
6
  export declare class Updates {
@@ -3,7 +3,8 @@ import { Response } from "undici";
3
3
  import type { MaybePromise } from "../types";
4
4
  export interface FrameworkHandler {
5
5
  update: MaybePromise<TelegramUpdate>;
6
- header?: string;
6
+ header: string;
7
+ unauthorized: () => unknown;
7
8
  response?: () => unknown;
8
9
  }
9
10
  export type FrameworkAdapter = (...args: any[]) => FrameworkHandler;
@@ -11,30 +12,43 @@ export declare const frameworks: {
11
12
  elysia: ({ body, headers }: any) => {
12
13
  update: any;
13
14
  header: any;
15
+ unauthorized: () => Response;
14
16
  };
15
- fastify: (request: any) => {
17
+ fastify: (request: any, reply: any) => {
16
18
  update: any;
17
19
  header: any;
20
+ unauthorized: () => any;
18
21
  };
19
22
  hono: (c: any) => {
20
23
  update: any;
21
24
  header: any;
25
+ unauthorized: () => any;
22
26
  };
23
- express: (req: any) => {
27
+ express: (req: any, res: any) => {
24
28
  update: any;
25
29
  header: any;
30
+ unauthorized: () => any;
26
31
  };
27
32
  koa: (ctx: any) => {
28
33
  update: any;
29
34
  header: any;
35
+ unauthorized: () => void;
30
36
  };
31
- http: (req: any) => {
37
+ http: (req: any, res: any) => {
32
38
  update: Promise<TelegramUpdate>;
33
39
  header: any;
40
+ unauthorized: () => any;
34
41
  };
35
- stdHTTP: (req: any) => {
42
+ "std/http": (req: any) => {
36
43
  update: any;
37
44
  header: any;
38
45
  response: () => Response;
46
+ unauthorized: () => Response;
47
+ };
48
+ "Bun.serve": (req: any) => {
49
+ update: any;
50
+ header: any;
51
+ response: () => Response;
52
+ unauthorized: () => Response;
39
53
  };
40
54
  };
@@ -3,28 +3,37 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.frameworks = void 0;
4
4
  const undici_1 = require("undici");
5
5
  const SECRET_TOKEN_HEADER = "X-Telegram-Bot-Api-Secret-Token";
6
+ const WRONG_TOKEN_ERROR = "secret token is invalid";
6
7
  exports.frameworks = {
7
8
  elysia: ({ body, headers }) => ({
8
9
  update: body,
9
10
  header: headers[SECRET_TOKEN_HEADER],
11
+ unauthorized: () => new undici_1.Response(WRONG_TOKEN_ERROR, { status: 401 }),
10
12
  }),
11
- fastify: (request) => ({
13
+ fastify: (request, reply) => ({
12
14
  update: request.body,
13
15
  header: request.headers[SECRET_TOKEN_HEADER],
16
+ unauthorized: () => reply.code(401).send(WRONG_TOKEN_ERROR),
14
17
  }),
15
18
  hono: (c) => ({
16
19
  update: c.req.json(),
17
20
  header: c.req.header(SECRET_TOKEN_HEADER),
21
+ unauthorized: () => c.text(WRONG_TOKEN_ERROR, 401),
18
22
  }),
19
- express: (req) => ({
23
+ express: (req, res) => ({
20
24
  update: req.body,
21
25
  header: req.header(SECRET_TOKEN_HEADER),
26
+ unauthorized: () => res.status(401).send(WRONG_TOKEN_ERROR),
22
27
  }),
23
28
  koa: (ctx) => ({
24
29
  update: ctx.request.body,
25
30
  header: ctx.get(SECRET_TOKEN_HEADER),
31
+ unauthorized: () => {
32
+ ctx.status === 401;
33
+ ctx.body = WRONG_TOKEN_ERROR;
34
+ },
26
35
  }),
27
- http: (req) => ({
36
+ http: (req, res) => ({
28
37
  update: new Promise((resolve) => {
29
38
  let body = "";
30
39
  req.on("data", (chunk) => {
@@ -33,10 +42,18 @@ exports.frameworks = {
33
42
  req.on("end", () => resolve(JSON.parse(body)));
34
43
  }),
35
44
  header: req.headers[SECRET_TOKEN_HEADER.toLowerCase()],
45
+ unauthorized: () => res.writeHead(401).end(WRONG_TOKEN_ERROR),
36
46
  }),
37
- stdHTTP: (req) => ({
47
+ "std/http": (req) => ({
38
48
  update: req.json(),
39
49
  header: req.headers.get(SECRET_TOKEN_HEADER),
40
- response: () => new undici_1.Response(null, { status: 200 }),
50
+ response: () => new undici_1.Response("ok!"),
51
+ unauthorized: () => new undici_1.Response(WRONG_TOKEN_ERROR, { status: 401 }),
52
+ }),
53
+ "Bun.serve": (req) => ({
54
+ update: req.json(),
55
+ header: req.headers.get(SECRET_TOKEN_HEADER),
56
+ response: () => new undici_1.Response("ok!"),
57
+ unauthorized: () => new undici_1.Response(WRONG_TOKEN_ERROR, { status: 401 }),
41
58
  }),
42
59
  };
@@ -30,35 +30,48 @@ export type WebhookHandlers = keyof typeof frameworks;
30
30
  * });
31
31
  * ```
32
32
  */
33
- export declare function webhookHandler<Framework extends keyof typeof frameworks>(bot: Bot, framework: Framework): ReturnType<{
33
+ export declare function webhookHandler<Framework extends keyof typeof frameworks>(bot: Bot, framework: Framework, secretToken?: string): ReturnType<{
34
34
  elysia: ({ body, headers }: any) => {
35
35
  update: any;
36
36
  header: any;
37
+ unauthorized: () => import("undici").Response;
37
38
  };
38
- fastify: (request: any) => {
39
+ fastify: (request: any, reply: any) => {
39
40
  update: any;
40
41
  header: any;
42
+ unauthorized: () => any;
41
43
  };
42
44
  hono: (c: any) => {
43
45
  update: any;
44
46
  header: any;
47
+ unauthorized: () => any;
45
48
  };
46
- express: (req: any) => {
49
+ express: (req: any, res: any) => {
47
50
  update: any;
48
51
  header: any;
52
+ unauthorized: () => any;
49
53
  };
50
54
  koa: (ctx: any) => {
51
55
  update: any;
52
56
  header: any;
57
+ unauthorized: () => void;
53
58
  };
54
- http: (req: any) => {
59
+ http: (req: any, res: any) => {
55
60
  update: Promise<import("@gramio/types").TelegramUpdate>;
56
61
  header: any;
62
+ unauthorized: () => any;
57
63
  };
58
- stdHTTP: (req: any) => {
64
+ "std/http": (req: any) => {
59
65
  update: any;
60
66
  header: any;
61
67
  response: () => import("undici").Response;
68
+ unauthorized: () => import("undici").Response;
69
+ };
70
+ "Bun.serve": (req: any) => {
71
+ update: any;
72
+ header: any;
73
+ response: () => import("undici").Response;
74
+ unauthorized: () => import("undici").Response;
62
75
  };
63
76
  }[Framework]> extends {
64
77
  response: () => any;
@@ -30,11 +30,15 @@ const adapters_1 = require("./adapters");
30
30
  * });
31
31
  * ```
32
32
  */
33
- function webhookHandler(bot, framework) {
33
+ function webhookHandler(bot, framework, secretToken) {
34
34
  const frameworkAdapter = adapters_1.frameworks[framework];
35
35
  return (async (...args) => {
36
36
  // @ts-expect-error
37
- const { update, response } = frameworkAdapter(...args);
37
+ const { update, response, header, unauthorized } = frameworkAdapter(
38
+ // @ts-expect-error
39
+ ...args);
40
+ if (secretToken && header !== secretToken)
41
+ return unauthorized();
38
42
  await bot.updates.handleUpdate(await update);
39
43
  if (response)
40
44
  return response();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gramio",
3
- "version": "0.0.35",
3
+ "version": "0.0.37",
4
4
  "description": "Powerful Telegram Bot API framework",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -27,19 +27,19 @@
27
27
  "license": "ISC",
28
28
  "devDependencies": {
29
29
  "@biomejs/biome": "1.7.3",
30
- "@types/node": "^20.12.9",
30
+ "@types/node": "^20.12.12",
31
31
  "typescript": "^5.4.5"
32
32
  },
33
33
  "dependencies": {
34
34
  "@gramio/callback-data": "^0.0.3",
35
35
  "@gramio/contexts": "^0.0.15",
36
36
  "@gramio/files": "^0.0.8",
37
- "@gramio/format": "^0.1.0",
38
- "@gramio/keyboards": "^0.3.1",
37
+ "@gramio/format": "^0.1.2",
38
+ "@gramio/keyboards": "^0.3.2",
39
39
  "@gramio/types": "^7.3.4",
40
40
  "inspectable": "^3.0.1",
41
41
  "middleware-io": "^2.8.1",
42
- "undici": "^6.16.1"
42
+ "undici": "^6.17.0"
43
43
  },
44
44
  "files": [
45
45
  "dist"