@grammyjs/commands 0.5.0 → 0.6.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/out/command.d.ts CHANGED
@@ -1,49 +1,125 @@
1
1
  import { type BotCommand, type BotCommandScope, type BotCommandScopeAllChatAdministrators, type BotCommandScopeAllGroupChats, type BotCommandScopeAllPrivateChats, type ChatTypeMiddleware, type Context, type Middleware, type MiddlewareObj } from "./deps.node.js";
2
+ import { CommandOptions } from "./types.js";
2
3
  export type MaybeArray<T> = T | T[];
3
- export type CommandOptions = {
4
- /**
5
- * The prefix used to identify a command.
6
- * Defaults to `/`.
7
- */
8
- prefix: string;
9
- /**
10
- * Whether the command should only be matched at the start of the message.
11
- * Defaults to `true`.
12
- */
13
- matchOnlyAtStart: boolean;
14
- /**
15
- * Whether to ignore or only care about commands ending with the bot's username.
16
- * Defaults to `"optional"`.
17
- *
18
- * - `"ignored"`: only non-targeted commands are matched
19
- * - `"optional"`: both targeted and non-targeted commands are matched
20
- * - `"ignored"`: only targeted commands are matched
21
- */
22
- targetedCommands: "ignored" | "optional" | "required";
23
- };
24
4
  type BotCommandGroupsScope = BotCommandScopeAllGroupChats | BotCommandScopeAllChatAdministrators;
25
5
  export declare const matchesPattern: (value: string, pattern: string | RegExp) => boolean;
6
+ /**
7
+ * Class that represents a single command and allows you to configure it.
8
+ */
26
9
  export declare class Command<C extends Context = Context> implements MiddlewareObj<C> {
27
10
  private _scopes;
28
11
  private _languages;
29
12
  private _composer;
30
13
  private _options;
14
+ /**
15
+ * Constructor for the `Command` class.
16
+ * Do not call this directly. Instead, use the `command` method from the `Commands` class
17
+ *
18
+ * @param name Default command name
19
+ * @param description Default command description
20
+ * @param options Options object that shuold apply to this command only
21
+ * @access package
22
+ */
31
23
  constructor(name: string | RegExp, description: string, options?: Partial<CommandOptions>);
24
+ /**
25
+ * Get registered scopes for this command
26
+ */
32
27
  get scopes(): BotCommandScope[];
28
+ /**
29
+ * Get registered languages for this command
30
+ */
33
31
  get languages(): Map<string, {
34
32
  name: string | RegExp;
35
33
  description: string;
36
34
  }>;
35
+ /**
36
+ * Get registered names for this command
37
+ */
37
38
  get names(): (string | RegExp)[];
39
+ /**
40
+ * Get the default name for this command
41
+ */
38
42
  get name(): string | RegExp;
43
+ /**
44
+ * Get the default description for this command
45
+ */
39
46
  get description(): string;
47
+ /**
48
+ * Registers the command to a scope to allow it to be handled and used with `setMyCommands`.
49
+ * This will automatically apply filtering middlewares for you, so the handler only runs on the specified scope.
50
+ *
51
+ * @example
52
+ * ```ts
53
+ * const myCommands = new Commands();
54
+ * myCommands.command("start", "Initializes bot configuration")
55
+ * .addToScope(
56
+ * { type: "all_private_chats" },
57
+ * (ctx) => ctx.reply(`Hello, ${ctx.chat.first_name}!`),
58
+ * )
59
+ * .addToScope(
60
+ * { type: "all_group_chats" },
61
+ * (ctx) => ctx.reply(`Hello, members of ${ctx.chat.title}!`),
62
+ * );
63
+ * ```
64
+ *
65
+ * @param scope Which scope this command should be available on
66
+ * @param middleware The handler for this command on the specified scope
67
+ * @param options Additional options that should apply only to this scope
68
+ */
40
69
  addToScope(scope: BotCommandGroupsScope, middleware: MaybeArray<ChatTypeMiddleware<C, "group" | "supergroup">>, options?: Partial<CommandOptions>): this;
41
70
  addToScope(scope: BotCommandScopeAllPrivateChats, middleware: MaybeArray<ChatTypeMiddleware<C, "private">>, options?: Partial<CommandOptions>): this;
42
71
  addToScope(scope: BotCommandScope, middleware: MaybeArray<Middleware<C>>, options?: Partial<CommandOptions>): this;
72
+ /**
73
+ * Creates a matcher for the given command that can be used in filtering operations
74
+ *
75
+ * @example
76
+ * ```ts
77
+ * bot
78
+ * .filter(
79
+ * Command.hasCommand(/\/delete_(.*)/),
80
+ * (ctx) => ctx.reply(`Deleting ${ctx.message?.text?.split("_")[1]}`)
81
+ * )
82
+ * ```
83
+ *
84
+ * @param command Command name or RegEx
85
+ * @param options Options that should apply to the matching algorithm
86
+ * @returns A predicate that matches the given command
87
+ */
43
88
  static hasCommand(command: MaybeArray<string | RegExp>, options: CommandOptions): (ctx: Context) => boolean;
89
+ /**
90
+ * Adds a new translation for the command
91
+ *
92
+ * @example
93
+ * ```ts
94
+ * myCommands
95
+ * .command("start", "Starts the bot configuration")
96
+ * .localize("pt", "iniciar", "Inicia a configuração do bot")
97
+ * ```
98
+ *
99
+ * @param languageCode Language this translation applies to
100
+ * @param name Localized command name
101
+ * @param description Localized command description
102
+ */
44
103
  localize(languageCode: string, name: string | RegExp, description: string): this;
104
+ /**
105
+ * Gets the localized command name of an existing translation
106
+ * @param languageCode Language to get the name for
107
+ * @returns Localized command name
108
+ */
45
109
  getLocalizedName(languageCode: string): string | RegExp;
110
+ /**
111
+ * Gets the localized command name of an existing translation
112
+ * @param languageCode Language to get the name for
113
+ * @returns Localized command name
114
+ */
46
115
  getLocalizedDescription(languageCode: string): string;
116
+ /**
117
+ * Converts command to an object representation.
118
+ * Useful for JSON serialization.
119
+ *
120
+ * @param languageCode If specified, uses localized versions of the command name and description
121
+ * @returns Object representation of this command
122
+ */
47
123
  toObject(languageCode?: string): BotCommand;
48
124
  middleware(): import("grammy").MiddlewareFn<C>;
49
125
  }
package/out/command.js CHANGED
@@ -4,10 +4,24 @@ exports.Command = exports.matchesPattern = void 0;
4
4
  const deps_node_js_1 = require("./deps.node.js");
5
5
  const errors_js_1 = require("./errors.js");
6
6
  const ensureArray = (value) => Array.isArray(value) ? value : [value];
7
- const isAdmin = (ctx) => ctx.getAuthor().then((author) => ["administrator", "creator"].includes(author.status));
7
+ const isAdmin = (ctx) => ctx
8
+ .getAuthor()
9
+ .then((author) => ["administrator", "creator"].includes(author.status));
8
10
  const matchesPattern = (value, pattern) => typeof pattern === "string" ? value === pattern : pattern.test(value);
9
11
  exports.matchesPattern = matchesPattern;
12
+ /**
13
+ * Class that represents a single command and allows you to configure it.
14
+ */
10
15
  class Command {
16
+ /**
17
+ * Constructor for the `Command` class.
18
+ * Do not call this directly. Instead, use the `command` method from the `Commands` class
19
+ *
20
+ * @param name Default command name
21
+ * @param description Default command description
22
+ * @param options Options object that shuold apply to this command only
23
+ * @access package
24
+ */
11
25
  constructor(name, description, options = {}) {
12
26
  this._scopes = [];
13
27
  this._languages = new Map();
@@ -22,18 +36,33 @@ class Command {
22
36
  this._options.prefix = "/";
23
37
  this._languages.set("default", { name: name, description });
24
38
  }
39
+ /**
40
+ * Get registered scopes for this command
41
+ */
25
42
  get scopes() {
26
43
  return this._scopes;
27
44
  }
45
+ /**
46
+ * Get registered languages for this command
47
+ */
28
48
  get languages() {
29
49
  return this._languages;
30
50
  }
51
+ /**
52
+ * Get registered names for this command
53
+ */
31
54
  get names() {
32
55
  return Array.from(this._languages.values()).map(({ name }) => name);
33
56
  }
57
+ /**
58
+ * Get the default name for this command
59
+ */
34
60
  get name() {
35
61
  return this._languages.get("default").name;
36
62
  }
63
+ /**
64
+ * Get the default description for this command
65
+ */
37
66
  get description() {
38
67
  return this._languages.get("default").description;
39
68
  }
@@ -89,6 +118,22 @@ class Command {
89
118
  this._scopes.push(scope);
90
119
  return this;
91
120
  }
121
+ /**
122
+ * Creates a matcher for the given command that can be used in filtering operations
123
+ *
124
+ * @example
125
+ * ```ts
126
+ * bot
127
+ * .filter(
128
+ * Command.hasCommand(/\/delete_(.*)/),
129
+ * (ctx) => ctx.reply(`Deleting ${ctx.message?.text?.split("_")[1]}`)
130
+ * )
131
+ * ```
132
+ *
133
+ * @param command Command name or RegEx
134
+ * @param options Options that should apply to the matching algorithm
135
+ * @returns A predicate that matches the given command
136
+ */
92
137
  static hasCommand(command, options) {
93
138
  const { matchOnlyAtStart, prefix, targetedCommands } = options;
94
139
  return (ctx) => {
@@ -109,12 +154,27 @@ class Command {
109
154
  continue;
110
155
  if (username && username !== ctx.me.username)
111
156
  continue;
112
- if (commandNames.some((name) => (0, exports.matchesPattern)(command.replace(prefix, ""), name)))
157
+ if (commandNames.some((name) => (0, exports.matchesPattern)(command.replace(prefix, ""), name))) {
113
158
  return true;
159
+ }
114
160
  }
115
161
  return false;
116
162
  };
117
163
  }
164
+ /**
165
+ * Adds a new translation for the command
166
+ *
167
+ * @example
168
+ * ```ts
169
+ * myCommands
170
+ * .command("start", "Starts the bot configuration")
171
+ * .localize("pt", "iniciar", "Inicia a configuração do bot")
172
+ * ```
173
+ *
174
+ * @param languageCode Language this translation applies to
175
+ * @param name Localized command name
176
+ * @param description Localized command description
177
+ */
118
178
  localize(languageCode, name, description) {
119
179
  this._languages.set(languageCode, {
120
180
  name: new RegExp(name),
@@ -122,14 +182,31 @@ class Command {
122
182
  });
123
183
  return this;
124
184
  }
185
+ /**
186
+ * Gets the localized command name of an existing translation
187
+ * @param languageCode Language to get the name for
188
+ * @returns Localized command name
189
+ */
125
190
  getLocalizedName(languageCode) {
126
191
  var _a, _b;
127
192
  return (_b = (_a = this._languages.get(languageCode)) === null || _a === void 0 ? void 0 : _a.name) !== null && _b !== void 0 ? _b : this.name;
128
193
  }
194
+ /**
195
+ * Gets the localized command name of an existing translation
196
+ * @param languageCode Language to get the name for
197
+ * @returns Localized command name
198
+ */
129
199
  getLocalizedDescription(languageCode) {
130
200
  var _a, _b;
131
201
  return (_b = (_a = this._languages.get(languageCode)) === null || _a === void 0 ? void 0 : _a.description) !== null && _b !== void 0 ? _b : this.description;
132
202
  }
203
+ /**
204
+ * Converts command to an object representation.
205
+ * Useful for JSON serialization.
206
+ *
207
+ * @param languageCode If specified, uses localized versions of the command name and description
208
+ * @returns Object representation of this command
209
+ */
133
210
  toObject(languageCode = "default") {
134
211
  const localizedName = this.getLocalizedName(languageCode);
135
212
  return {
package/out/commands.d.ts CHANGED
@@ -1,10 +1,27 @@
1
- import { Command, CommandOptions } from "./command.js";
2
- import { Api, BotCommand, BotCommandScope, Context } from "./deps.node.js";
1
+ import { Command, MaybeArray } from "./command.js";
2
+ import { Api, BotCommand, BotCommandScope, Context, Middleware } from "./deps.node.js";
3
+ import { CommandOptions } from "./types.js";
3
4
  type SetMyCommandsParams = {
5
+ /**
6
+ * Scope
7
+ */
4
8
  scope?: BotCommandScope;
5
9
  language_code?: string;
6
10
  commands: BotCommand[];
7
11
  };
12
+ /**
13
+ * Central class that manages all registered commands.
14
+ * This is the starting point for the plugin, and this is what you should pass to `bot.use` so your commands get properly registered.
15
+ *
16
+ * @example
17
+ * ```typescript
18
+ * const myCommands = new Commands()
19
+ * commands.command("start", "start the bot configuration", (ctx) => ctx.reply("Hello there!"))
20
+ *
21
+ * // Registers the commands with the bot instance.
22
+ * bot.use(myCommands)
23
+ * ```
24
+ */
8
25
  export declare class Commands<C extends Context> {
9
26
  private _languages;
10
27
  private _scopes;
@@ -15,13 +32,52 @@ export declare class Commands<C extends Context> {
15
32
  private _addCommandToScope;
16
33
  private _populateComposer;
17
34
  private _populateMetadata;
35
+ /**
36
+ * Registers a new command with a default handler.
37
+ * @param name Default command name
38
+ * @param description Default command description
39
+ * @param handler Default command handler
40
+ * @param options Extra options that should apply only to this command
41
+ * @returns An instance of the `Command` class
42
+ */
43
+ command(name: string | RegExp, description: string, handler: MaybeArray<Middleware<C>>, options?: Partial<CommandOptions>): Command<C>;
44
+ /**
45
+ * Registers a new command with no handlers.
46
+ * @param name Default command name
47
+ * @param description Default command description
48
+ * @param options Extra options that should apply only to this command
49
+ * @returns An instance of the `Command` class
50
+ */
18
51
  command(name: string | RegExp, description: string, options?: Partial<CommandOptions>): Command<C>;
52
+ /**
53
+ * Serializes the commands into multiple objects that can each be passed to a `setMyCommands` call.
54
+ *
55
+ * @returns One item for each combination of command + scope + language
56
+ */
19
57
  toArgs(): SetMyCommandsParams[];
58
+ /**
59
+ * Serializes the commands of a single scope into objects that can each be passed to a `setMyCommands` call.
60
+ *
61
+ * @param scope Selected scope to be serialized
62
+ * @returns One item per command per language
63
+ */
20
64
  toSingleScopeArgs(scope: BotCommandScope): SetMyCommandsParams[];
65
+ /**
66
+ * Registers all commands to be displayed by clients according to their scopes and languages
67
+ * Calls `setMyCommands` for each language of each scope of each command.
68
+ *
69
+ * @param Instance of `bot` or { api: bot.api }
70
+ */
21
71
  setCommands({ api }: {
22
72
  api: Api;
23
73
  }): Promise<void>;
74
+ /**
75
+ * Alias for {@link toArgs}
76
+ */
24
77
  toJSON(): SetMyCommandsParams[];
78
+ /**
79
+ * @returns A JSON serialized version of all the currently registered commands
80
+ */
25
81
  toString(): string;
26
82
  middleware(): import("grammy").MiddlewareFn<C>;
27
83
  }
package/out/commands.js CHANGED
@@ -3,6 +3,33 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Commands = void 0;
4
4
  const command_js_1 = require("./command.js");
5
5
  const deps_node_js_1 = require("./deps.node.js");
6
+ const isMiddleware = (obj) => {
7
+ if (!obj)
8
+ return false;
9
+ if (Array.isArray(obj))
10
+ return obj.every(isMiddleware);
11
+ const objType = typeof obj;
12
+ switch (objType) {
13
+ case "function":
14
+ return true;
15
+ case "object":
16
+ return Object.keys(obj).includes("middleware");
17
+ }
18
+ return false;
19
+ };
20
+ /**
21
+ * Central class that manages all registered commands.
22
+ * This is the starting point for the plugin, and this is what you should pass to `bot.use` so your commands get properly registered.
23
+ *
24
+ * @example
25
+ * ```typescript
26
+ * const myCommands = new Commands()
27
+ * commands.command("start", "start the bot configuration", (ctx) => ctx.reply("Hello there!"))
28
+ *
29
+ * // Registers the commands with the bot instance.
30
+ * bot.use(myCommands)
31
+ * ```
32
+ */
6
33
  class Commands {
7
34
  constructor(options = {}) {
8
35
  this._languages = new Set();
@@ -34,11 +61,25 @@ class Commands {
34
61
  }
35
62
  });
36
63
  }
37
- command(name, description, options = this._commandOptions) {
64
+ command(name, description, handlerOrOptions, _options) {
65
+ var _a;
66
+ const handler = isMiddleware(handlerOrOptions)
67
+ ? handlerOrOptions
68
+ : undefined;
69
+ const options = handler
70
+ ? _options !== null && _options !== void 0 ? _options : this._commandOptions
71
+ : (_a = handlerOrOptions) !== null && _a !== void 0 ? _a : this._commandOptions;
38
72
  const command = new command_js_1.Command(name, description, options);
73
+ if (handler)
74
+ command.addToScope({ type: "default" }, handler);
39
75
  this._commands.push(command);
40
76
  return command;
41
77
  }
78
+ /**
79
+ * Serializes the commands into multiple objects that can each be passed to a `setMyCommands` call.
80
+ *
81
+ * @returns One item for each combination of command + scope + language
82
+ */
42
83
  toArgs() {
43
84
  this._populateMetadata();
44
85
  const params = [];
@@ -56,6 +97,12 @@ class Commands {
56
97
  }
57
98
  return params.filter((params) => params.commands.length > 0);
58
99
  }
100
+ /**
101
+ * Serializes the commands of a single scope into objects that can each be passed to a `setMyCommands` call.
102
+ *
103
+ * @param scope Selected scope to be serialized
104
+ * @returns One item per command per language
105
+ */
59
106
  toSingleScopeArgs(scope) {
60
107
  this._populateMetadata();
61
108
  const params = [];
@@ -70,12 +117,24 @@ class Commands {
70
117
  }
71
118
  return params;
72
119
  }
120
+ /**
121
+ * Registers all commands to be displayed by clients according to their scopes and languages
122
+ * Calls `setMyCommands` for each language of each scope of each command.
123
+ *
124
+ * @param Instance of `bot` or { api: bot.api }
125
+ */
73
126
  async setCommands({ api }) {
74
127
  await Promise.all(this.toArgs().map((args) => api.raw.setMyCommands(args)));
75
128
  }
129
+ /**
130
+ * Alias for {@link toArgs}
131
+ */
76
132
  toJSON() {
77
133
  return this.toArgs();
78
134
  }
135
+ /**
136
+ * @returns A JSON serialized version of all the currently registered commands
137
+ */
79
138
  toString() {
80
139
  return JSON.stringify(this);
81
140
  }
@@ -83,9 +142,19 @@ class Commands {
83
142
  this._populateComposer();
84
143
  return this._composer.middleware();
85
144
  }
145
+ /**
146
+ * Replaces the `toString` method on node.js
147
+ *
148
+ * @see toString
149
+ */
86
150
  [Symbol.for("Deno.customInspect")]() {
87
151
  return this.toString();
88
152
  }
153
+ /**
154
+ * Replaces the `toString` method on Deno
155
+ *
156
+ * @see toString
157
+ */
89
158
  [Symbol.for("nodejs.util.inspect.custom")]() {
90
159
  return this.toString();
91
160
  }
package/out/mod.d.ts CHANGED
@@ -1,2 +1,4 @@
1
+ export { Command } from "./command.js";
1
2
  export * from "./commands.js";
2
3
  export * from "./context.js";
4
+ export type { CommandOptions } from "./types.js";
package/out/mod.js CHANGED
@@ -14,5 +14,8 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.Command = void 0;
18
+ var command_js_1 = require("./command.js");
19
+ Object.defineProperty(exports, "Command", { enumerable: true, get: function () { return command_js_1.Command; } });
17
20
  __exportStar(require("./commands.js"), exports);
18
21
  __exportStar(require("./context.js"), exports);
package/out/types.d.ts ADDED
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Supported command options
3
+ */
4
+ export interface CommandOptions {
5
+ /**
6
+ * The prefix used to identify a command.
7
+ * Defaults to `/`.
8
+ */
9
+ prefix: string;
10
+ /**
11
+ * Whether the command should only be matched at the start of the message.
12
+ * Defaults to `true`.
13
+ */
14
+ matchOnlyAtStart: boolean;
15
+ /**
16
+ * Whether to ignore or only care about commands ending with the bot's username.
17
+ * Defaults to `"optional"`.
18
+ *
19
+ * - `"ignored"`: only non-targeted commands are matched
20
+ * - `"optional"`: both targeted and non-targeted commands are matched
21
+ * - `"required"`: only targeted commands are matched
22
+ */
23
+ targetedCommands: "ignored" | "optional" | "required";
24
+ }
package/out/types.js ADDED
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@grammyjs/commands",
3
- "version": "0.5.0",
3
+ "version": "0.6.0",
4
4
  "description": "grammY Commands Plugin",
5
5
  "main": "out/mod.js",
6
6
  "scripts": {