@grammyjs/commands 0.0.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) [year] [fullname]
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,178 @@
1
+ ## grammY Commands Plugin
2
+
3
+ This plugin provides a convenient way to define and manage commands for your grammY bot. It simplifies the process of
4
+ setting up commands with scopes and localization.
5
+
6
+ ## Installation
7
+
8
+ On NPM, this plugin is available as `@grammyjs/commands`, and on Deno it's available at
9
+ [deno.land/x/grammy_commands](https://deno.land/x/grammy_commands).
10
+
11
+ You can install it for Node.js with this command:
12
+
13
+ ```sh
14
+ npm i @grammyjs/commands
15
+ ```
16
+
17
+ ## Core Concepts
18
+
19
+ ### The `Commands` class
20
+
21
+ The `Commands` class is the foundation of this plugin. It allows you to create commands by specifying their names and
22
+ descriptions, along with additional attributes such as scopes and localization.
23
+
24
+ ### The `ctx.setMyCommands` method
25
+
26
+ The `ctx.setMyCommands` method, provided by the plugin, offers a convenient way to dynamically set the available
27
+ commands for the current chat. By invoking this method and passing an instance of the `Commands` class, you can override
28
+ the default command scopes and make all commands accessible within the current chat. This feature is particularly useful
29
+ when you need to customize the command set for specific chat contexts, ignoring the predefined scopes, which allows for
30
+ a more tailored and context-aware usage of bot commands.
31
+
32
+ ## Usage
33
+
34
+ ### Managing Commands For Multiple Scopes
35
+
36
+ To manage commands for multiple scopes at once, create an instance of the `Commands` class, add your commands to it, and
37
+ then call the `setFor` method of the class instance. Check out this example:
38
+
39
+ ```typescript
40
+ import { Bot } from "https://deno.land/x/grammy/mod.ts";
41
+ import { Commands } from "https://deno.land/x/grammy_commands/mod.ts";
42
+
43
+ const bot = new Bot("<your_bot_token>");
44
+ const cmds = new Commands();
45
+
46
+ // Define your commands...
47
+
48
+ await cmds.setFor(bot);
49
+ ```
50
+
51
+ ### Managing Commands For The Current Chat
52
+
53
+ To set the commands for the current chat, you can use the `ctx.setMyCommands` method of the `Context` object. For that,
54
+ you will need to install the `CommandsFlavor` to your context, and create an instance of the `Commands` class, to which
55
+ you add your commands to and then pass to `ctx.setMyCommands`. This will override the predefined scopes and make all
56
+ commands available to the current chat. Here's an example:
57
+
58
+ > Please note that this only works in updates which have a `chat` object. If `ctx.chat` is not defined, an error will be
59
+ > thrown ar runtime.
60
+
61
+ ```typescript
62
+ import { Bot, Context } from "https://deno.land/x/grammy/mod.ts";
63
+ import { Commands, CommandsFlavor } from "https://deno.land/x/grammy_commands/mod.ts";
64
+
65
+ type MyContext = CommandsFlavor<Context>;
66
+ const bot = new Bot<MyContext>("<your_bot_token>");
67
+
68
+ bot.on(":text", async (ctx: Context) => {
69
+ const cmds = new Commands();
70
+
71
+ // Define your commands...
72
+
73
+ await ctx.setMyCommands(cmds);
74
+ });
75
+ ```
76
+
77
+ ### Defining Commands
78
+
79
+ To define a command, use the `command` method of the `CommandsPlugin` instance. The `command` method takes two
80
+ arguments: the command name and the command description. Here's an example:
81
+
82
+ ```typescript
83
+ commands.command("help", "Sends help");
84
+ ```
85
+
86
+ ### Setting handlers
87
+
88
+ The underlying class returned by the `.command()` method extends the grammY `Composer` class. That means you can use
89
+ `.use`, `.filter`, `.branch`, `.chatType` and every other `Composer` method you already know and love. Alternatively,
90
+ you can pass your middleware as a third parameter to the `.command()` method. You can also use the `onChatType` method
91
+ of the `Command` class to define middleware specific to that chat type. Here are some examples:
92
+
93
+ #### Example 1
94
+
95
+ ```typescript
96
+ commands.command("start", "Starts the bot", (ctx) => {
97
+ ctx.reply(`Hello, ${ctx.chat?.first_name ?? "there"}!`);
98
+ });
99
+ ```
100
+
101
+ #### Example 2
102
+
103
+ ```typescript
104
+ commands.command("start", "Starts the bot")
105
+ .onChatType("private", (ctx) => ctx.reply(`Hello ${ctx.chat.first_name}!`))
106
+ .onChatType(["group", "supergroup", "channel"], (ctx) => ctx.reply(`Hello members of ${ctx.chat.title}!`))
107
+ .addToScope("default");
108
+ ```
109
+
110
+ ### Localization
111
+
112
+ You can localize command names and descriptions using the `localize` method. The `localize` method takes the language
113
+ code, the localized command name, and the localized command description. Here's an example:
114
+
115
+ ```typescript
116
+ commands.command("help", "Sends help")
117
+ .localize("de-DE", "hilfe", "Sendet Hilfe");
118
+ ```
119
+
120
+ ### Scopes
121
+
122
+ Scopes determine the availability of each command, enabling you to control whether a command can be accessed in all
123
+ group chats, private chats, or limited to chat administrators. Commands can be assigned to different scopes using the
124
+ `addToScope` method. Here's an example:
125
+
126
+ ```typescript
127
+ commands.command("help", "Sends help")
128
+ .addToScope("default")
129
+ .addToScope("all_group_chats")
130
+ .addToScope("all_private_chats")
131
+ .addToScope("all_chat_administrators")
132
+ .addToScope("chat_administrators", "@grammyjs")
133
+ .addToScope("chat", "@SpecificUserChat");
134
+ ```
135
+
136
+ ### Setting Commands for Current Chat
137
+
138
+ To set the commands for the current chat, you can use the `setMyCommands` method of the `Context` object. This will
139
+ override the defined scopes and make all commands available to the current chat. Here's an example:
140
+
141
+ ```typescript
142
+ bot.on(":text", async (ctx) => {
143
+ await ctx.setMyCommands(commands);
144
+ });
145
+ ```
146
+
147
+ This will set all commands defined in the `commands` instance for the current chat.
148
+
149
+ ## Examples
150
+
151
+ ### Example 1: Help Command
152
+
153
+ This example shows how to define a basic help command:
154
+
155
+ ```typescript
156
+ commands.command("help", "Sends help")
157
+ .localize("de-DE", "hilfe", "Sendet Hilfe")
158
+ .addToScope("default")
159
+ .addToScope("all_group_chats")
160
+ .addToScope("all_private_chats")
161
+ .addToScope("all_chat_administrators")
162
+ .addToScope("chat_administrators", "@grammyjs")
163
+ .addToScope("chat", "@LWJerri");
164
+ ```
165
+
166
+ ### Example 2: Stats Command
167
+
168
+ This example shows how to define a stats command for group chats:
169
+
170
+ ```typescript
171
+ commands.command("stats", "Sends group stats")
172
+ .addToScope("all_group_chats")
173
+ .addToScope("all_chat_administrators")
174
+ .addToScope("chat_administrators", "@grammyjs")
175
+ .addToScope("chat", "@LWJerri");
176
+ ```
177
+
178
+ Feel free to add more commands and customize them according to your bot's needs.
@@ -0,0 +1,22 @@
1
+ import { BotCommand, BotCommandScope, Chat, ChatTypeContext, CommandMiddleware, Composer, Context, Middleware } from "./deps.node.js";
2
+ export type MaybeArray<T> = T | T[];
3
+ export declare class Command<C extends Context = Context> extends Composer<C> {
4
+ #private;
5
+ constructor(name: string, description: string, ...middleware: Array<Middleware<C>>);
6
+ get languages(): Map<string, {
7
+ name: string;
8
+ description: string;
9
+ }>;
10
+ get scopes(): BotCommandScope[];
11
+ get name(): string;
12
+ get description(): string;
13
+ addToScope(type: "default" | "all_private_chats" | "all_group_chats" | "all_chat_administrators"): this;
14
+ addToScope(type: "chat", chatId: string | number): this;
15
+ addToScope(type: "chat_member", chatId: string | number, userId: number): this;
16
+ addToScope(type: "chat_administrators", chatId: string | number): this;
17
+ localize(languageCode: string, name: string, description: string): this;
18
+ getLocalizedName(languageCode: string): string;
19
+ getLocalizedDescription(languageCode: string): string;
20
+ onChatType<T extends Chat["type"]>(chatType: MaybeArray<T>, ...middleware: Array<CommandMiddleware<ChatTypeContext<C, T>>>): this;
21
+ toObject(languageCode?: string): BotCommand;
22
+ }
package/out/command.js ADDED
@@ -0,0 +1,69 @@
1
+ "use strict";
2
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
3
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
4
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
5
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
6
+ };
7
+ var _Command_scopes, _Command_languages;
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.Command = void 0;
10
+ const deps_node_js_1 = require("./deps.node.js");
11
+ class Command extends deps_node_js_1.Composer {
12
+ constructor(name, description, ...middleware) {
13
+ super();
14
+ _Command_scopes.set(this, []);
15
+ _Command_languages.set(this, new Map());
16
+ if (!name.match(/[a-z0-9_]{1,32}/)) {
17
+ throw new Error(`${name} is not a valid command name`);
18
+ }
19
+ __classPrivateFieldGet(this, _Command_languages, "f").set("default", { name, description });
20
+ this.command(name, ...middleware);
21
+ }
22
+ get languages() {
23
+ return __classPrivateFieldGet(this, _Command_languages, "f");
24
+ }
25
+ get scopes() {
26
+ return __classPrivateFieldGet(this, _Command_scopes, "f");
27
+ }
28
+ get name() {
29
+ return __classPrivateFieldGet(this, _Command_languages, "f").get("default").name;
30
+ }
31
+ get description() {
32
+ return __classPrivateFieldGet(this, _Command_languages, "f").get("default").description;
33
+ }
34
+ addToScope(type, chatId, userId) {
35
+ const scope = (0, deps_node_js_1.match)({ type, chatId, userId })
36
+ .with({ type: "default" }, { type: "all_chat_administrators" }, { type: "all_group_chats" }, { type: "all_private_chats" }, ({ type }) => ({ type }))
37
+ .with({ type: deps_node_js_1.P.union("chat", "chat_administrators"), chatId: deps_node_js_1.P.not(deps_node_js_1.P.nullish) }, ({ type, chatId }) => ({ type, chat_id: chatId }))
38
+ .with({ type: "chat_member", chatId: deps_node_js_1.P.not(deps_node_js_1.P.nullish), userId: deps_node_js_1.P.not(deps_node_js_1.P.nullish) }, ({ type, chatId, userId }) => ({ type, chat_id: chatId, user_id: userId }))
39
+ .otherwise(() => null);
40
+ if (scope)
41
+ __classPrivateFieldGet(this, _Command_scopes, "f").push(scope);
42
+ return this;
43
+ }
44
+ localize(languageCode, name, description) {
45
+ __classPrivateFieldGet(this, _Command_languages, "f").set(languageCode, { name, description });
46
+ return this;
47
+ }
48
+ getLocalizedName(languageCode) {
49
+ var _a, _b;
50
+ return (_b = (_a = __classPrivateFieldGet(this, _Command_languages, "f").get(languageCode)) === null || _a === void 0 ? void 0 : _a.name) !== null && _b !== void 0 ? _b : this.name;
51
+ }
52
+ getLocalizedDescription(languageCode) {
53
+ var _a, _b;
54
+ return (_b = (_a = __classPrivateFieldGet(this, _Command_languages, "f").get(languageCode)) === null || _a === void 0 ? void 0 : _a.description) !== null && _b !== void 0 ? _b : this.description;
55
+ }
56
+ onChatType(chatType, ...middleware) {
57
+ const names = Array.from(__classPrivateFieldGet(this, _Command_languages, "f").values()).map(({ name }) => name);
58
+ this.chatType(chatType).command(names, ...middleware);
59
+ return this;
60
+ }
61
+ toObject(languageCode = "default") {
62
+ return {
63
+ command: this.getLocalizedName(languageCode),
64
+ description: this.getLocalizedDescription(languageCode),
65
+ };
66
+ }
67
+ }
68
+ exports.Command = Command;
69
+ _Command_scopes = new WeakMap(), _Command_languages = new WeakMap();
@@ -0,0 +1,13 @@
1
+ import { Context, NextFunction } from "./deps.node.js";
2
+ import { Commands } from "./plugin.js";
3
+ export type CommandsFlavor<C extends Context = Context> = C & {
4
+ /**
5
+ * Sets the provided commands for the current chat.
6
+ * Cannot be called on updates that don't have a `chat` property.
7
+ *
8
+ * @param commands List of available commands
9
+ * @returns Promise with the result of the operations
10
+ */
11
+ setMyCommands: (commands: Commands<C>) => Promise<true[]>;
12
+ };
13
+ export declare function commands<C extends Context>(): (ctx: CommandsFlavor<C>, next: NextFunction) => Promise<void>;
package/out/context.js ADDED
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.commands = void 0;
4
+ function commands() {
5
+ return (ctx, next) => {
6
+ ctx.setMyCommands = (commands) => {
7
+ if (!ctx.chat)
8
+ throw new Error("cannot call `ctx.setMyCommands` on an update with no `chat` property");
9
+ return Promise.all(commands
10
+ .toSingleScopeArgs({ type: "chat", chat_id: ctx.chat.id })
11
+ .map((args) => ctx.api.raw.setMyCommands(args)));
12
+ };
13
+ return next();
14
+ };
15
+ }
16
+ exports.commands = commands;
@@ -0,0 +1,3 @@
1
+ export { Bot, type ChatTypeContext, type CommandMiddleware, Composer, Context, type Middleware, type NextFunction, } from "grammy";
2
+ export type { BotCommand, BotCommandScope, Chat } from "grammy/types";
3
+ export { match, P } from "ts-pattern";
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.P = exports.match = exports.Context = exports.Composer = exports.Bot = void 0;
4
+ // TODO: Replace with official deno module, once it arrives (https://github.com/gvergnaud/ts-pattern/pull/108)
5
+ var grammy_1 = require("grammy");
6
+ Object.defineProperty(exports, "Bot", { enumerable: true, get: function () { return grammy_1.Bot; } });
7
+ Object.defineProperty(exports, "Composer", { enumerable: true, get: function () { return grammy_1.Composer; } });
8
+ Object.defineProperty(exports, "Context", { enumerable: true, get: function () { return grammy_1.Context; } });
9
+ var ts_pattern_1 = require("ts-pattern");
10
+ Object.defineProperty(exports, "match", { enumerable: true, get: function () { return ts_pattern_1.match; } });
11
+ Object.defineProperty(exports, "P", { enumerable: true, get: function () { return ts_pattern_1.P; } });
package/out/mod.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ export * from "./context.js";
2
+ export * from "./plugin.js";
package/out/mod.js ADDED
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./context.js"), exports);
18
+ __exportStar(require("./plugin.js"), exports);
@@ -0,0 +1,18 @@
1
+ import { Command } from "./command.js";
2
+ import { Bot, BotCommand, BotCommandScope, Context, Middleware } from "./deps.node.js";
3
+ type SetMyCommandsParams = {
4
+ scope?: BotCommandScope;
5
+ language_code?: string;
6
+ commands: BotCommand[];
7
+ };
8
+ export declare class Commands<C extends Context> {
9
+ #private;
10
+ constructor(commands?: Command<C>[]);
11
+ command(name: string, description: string, ...middleware: Array<Middleware<C>>): Command<C>;
12
+ toArgs(): SetMyCommandsParams[];
13
+ toSingleScopeArgs(scope: BotCommandScope): SetMyCommandsParams[];
14
+ setFor<C extends Context>(bot: Bot<C>): Promise<true[]>;
15
+ toJSON(): SetMyCommandsParams[];
16
+ toString(): string;
17
+ }
18
+ export {};
package/out/plugin.js ADDED
@@ -0,0 +1,88 @@
1
+ "use strict";
2
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
3
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
4
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
5
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
6
+ };
7
+ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
8
+ if (kind === "m") throw new TypeError("Private method is not writable");
9
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
10
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
11
+ return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
12
+ };
13
+ var _Commands_instances, _Commands_languages, _Commands_scopes, _Commands_commands, _Commands_addCommandToScope, _Commands_populate;
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.Commands = void 0;
16
+ const command_js_1 = require("./command.js");
17
+ const deps_node_js_1 = require("./deps.node.js");
18
+ class Commands {
19
+ constructor(commands = []) {
20
+ _Commands_instances.add(this);
21
+ _Commands_languages.set(this, new Set());
22
+ _Commands_scopes.set(this, new Map());
23
+ _Commands_commands.set(this, []);
24
+ commands.forEach((command) => __classPrivateFieldGet(this, _Commands_commands, "f").push(command));
25
+ }
26
+ command(name, description, ...middleware) {
27
+ const command = new command_js_1.Command(name, description, ...middleware);
28
+ __classPrivateFieldGet(this, _Commands_commands, "f").push(command);
29
+ return command;
30
+ }
31
+ toArgs() {
32
+ __classPrivateFieldGet(this, _Commands_instances, "m", _Commands_populate).call(this);
33
+ const params = [];
34
+ for (const [scope, commands] of __classPrivateFieldGet(this, _Commands_scopes, "f").entries()) {
35
+ for (const language of __classPrivateFieldGet(this, _Commands_languages, "f")) {
36
+ params.push({
37
+ scope: JSON.parse(scope),
38
+ language_code: language === "default" ? undefined : language,
39
+ commands: commands.map((command) => command.toObject(language)),
40
+ });
41
+ }
42
+ }
43
+ return params.filter((params) => params.commands.length > 0);
44
+ }
45
+ toSingleScopeArgs(scope) {
46
+ __classPrivateFieldGet(this, _Commands_instances, "m", _Commands_populate).call(this);
47
+ const params = [];
48
+ for (const language of __classPrivateFieldGet(this, _Commands_languages, "f")) {
49
+ params.push({
50
+ scope,
51
+ language_code: (0, deps_node_js_1.match)(language).with("default", () => undefined).otherwise((value) => value),
52
+ commands: __classPrivateFieldGet(this, _Commands_commands, "f")
53
+ .filter((command) => command.scopes.length)
54
+ .map((command) => command.toObject(language)),
55
+ });
56
+ }
57
+ return params;
58
+ }
59
+ setFor(bot) {
60
+ const argsArray = this.toArgs();
61
+ const promises = argsArray.map((args) => bot.api.raw.setMyCommands(args));
62
+ return Promise.all(promises);
63
+ }
64
+ toJSON() {
65
+ return this.toArgs();
66
+ }
67
+ toString() {
68
+ return JSON.stringify(this);
69
+ }
70
+ [(_Commands_languages = new WeakMap(), _Commands_scopes = new WeakMap(), _Commands_commands = new WeakMap(), _Commands_instances = new WeakSet(), _Commands_addCommandToScope = function _Commands_addCommandToScope(scope, command) {
71
+ var _a;
72
+ const commands = (_a = __classPrivateFieldGet(this, _Commands_scopes, "f").get(JSON.stringify(scope))) !== null && _a !== void 0 ? _a : [];
73
+ __classPrivateFieldGet(this, _Commands_scopes, "f").set(JSON.stringify(scope), commands.concat([command]));
74
+ }, _Commands_populate = function _Commands_populate() {
75
+ __classPrivateFieldSet(this, _Commands_languages, new Set(), "f");
76
+ __classPrivateFieldSet(this, _Commands_scopes, new Map(), "f");
77
+ __classPrivateFieldGet(this, _Commands_commands, "f").forEach((command) => {
78
+ command.scopes.forEach((scope) => __classPrivateFieldGet(this, _Commands_instances, "m", _Commands_addCommandToScope).call(this, scope, command));
79
+ Array.from(command.languages.keys()).forEach((language) => __classPrivateFieldGet(this, _Commands_languages, "f").add(language));
80
+ });
81
+ }, Symbol.for("Deno.customInspect"))]() {
82
+ return this.toString();
83
+ }
84
+ [Symbol.for("nodejs.util.inspect.custom")]() {
85
+ return this.toString();
86
+ }
87
+ }
88
+ exports.Commands = Commands;
package/package.json ADDED
@@ -0,0 +1,25 @@
1
+ {
2
+ "name": "@grammyjs/commands",
3
+ "version": "0.0.1",
4
+ "description": "grammY Commands Plugin",
5
+ "main": "out/mod.js",
6
+ "scripts": {
7
+ "prepare": "deno task backport"
8
+ },
9
+ "keywords": [
10
+ "grammY",
11
+ "telegram",
12
+ "bot",
13
+ "commands"
14
+ ],
15
+ "author": "Roz <roz@rjmunhoz.me>",
16
+ "license": "MIT",
17
+ "dependencies": {
18
+ "grammy": "^1.17.1",
19
+ "ts-pattern": "^5.0.1"
20
+ },
21
+ "devDependencies": {
22
+ "typescript": "^5.1.6"
23
+ },
24
+ "files": ["out"]
25
+ }