@grammyjs/commands 1.0.3 → 1.0.4
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-group.js +2 -2
- package/out/command.d.ts +30 -0
- package/out/command.js +59 -23
- package/out/context.d.ts +7 -0
- package/out/context.js +2 -2
- package/out/utils/array.js +3 -3
- package/out/utils/checks.js +7 -5
- package/out/utils/jaro-winkler.js +4 -5
- package/out/utils/set-bot-commands.js +1 -2
- package/package.json +4 -4
package/out/command-group.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.CommandGroup = void 0;
|
|
4
|
+
exports.commandNotFound = commandNotFound;
|
|
4
5
|
const mod_js_1 = require("./mod.js");
|
|
5
6
|
const deps_node_js_1 = require("./deps.node.js");
|
|
6
7
|
const array_js_1 = require("./utils/array.js");
|
|
@@ -249,7 +250,6 @@ function commandNotFound(commands, opts = {}) {
|
|
|
249
250
|
return false;
|
|
250
251
|
};
|
|
251
252
|
}
|
|
252
|
-
exports.commandNotFound = commandNotFound;
|
|
253
253
|
function containsCommands(ctx, commands) {
|
|
254
254
|
let allPrefixes = [
|
|
255
255
|
...new Set((0, array_js_1.ensureArray)(commands).flatMap((cmds) => cmds.prefixes)),
|
package/out/command.d.ts
CHANGED
|
@@ -2,6 +2,25 @@ import { type BotCommand, type BotCommandScope, type BotCommandScopeAllChatAdmin
|
|
|
2
2
|
import type { CommandOptions } from "./types.js";
|
|
3
3
|
import { type MaybeArray } from "./utils/array.js";
|
|
4
4
|
type BotCommandGroupsScope = BotCommandScopeAllGroupChats | BotCommandScopeAllChatAdministrators;
|
|
5
|
+
/**
|
|
6
|
+
* Represents a matched command, the result of the RegExp match, and the rest of the input.
|
|
7
|
+
*/
|
|
8
|
+
export interface CommandMatch {
|
|
9
|
+
/**
|
|
10
|
+
* The matched command.
|
|
11
|
+
*/
|
|
12
|
+
command: string | RegExp;
|
|
13
|
+
/**
|
|
14
|
+
* The rest of the input after the command.
|
|
15
|
+
*/
|
|
16
|
+
rest: string;
|
|
17
|
+
/**
|
|
18
|
+
* The result of the RegExp match.
|
|
19
|
+
*
|
|
20
|
+
* Only defined if the command is a RegExp.
|
|
21
|
+
*/
|
|
22
|
+
match?: RegExpExecArray | null;
|
|
23
|
+
}
|
|
5
24
|
/**
|
|
6
25
|
* Class that represents a single command and allows you to configure it.
|
|
7
26
|
*/
|
|
@@ -117,6 +136,17 @@ export declare class Command<C extends Context = Context> implements MiddlewareO
|
|
|
117
136
|
addToScope(scope: BotCommandGroupsScope, middleware?: MaybeArray<ChatTypeMiddleware<C, "group" | "supergroup">>, options?: Partial<CommandOptions>): this;
|
|
118
137
|
addToScope(scope: BotCommandScopeAllPrivateChats, middleware?: MaybeArray<ChatTypeMiddleware<C, "private">>, options?: Partial<CommandOptions>): this;
|
|
119
138
|
addToScope(scope: BotCommandScope, middleware?: MaybeArray<Middleware<C>>, options?: Partial<CommandOptions>): this;
|
|
139
|
+
/**
|
|
140
|
+
* Finds the matching command in the given context
|
|
141
|
+
*
|
|
142
|
+
* @example
|
|
143
|
+
* ```ts
|
|
144
|
+
* // ctx.msg.text = "/delete_123 something"
|
|
145
|
+
* const match = Command.findMatchingCommand(/delete_(.*)/, { prefix: "/", ignoreCase: true }, ctx)
|
|
146
|
+
* // match is { command: /delete_(.*)/, rest: ["something"], match: ["delete_123"] }
|
|
147
|
+
* ```
|
|
148
|
+
*/
|
|
149
|
+
static findMatchingCommand(command: MaybeArray<string | RegExp>, options: CommandOptions, ctx: Context): CommandMatch | null;
|
|
120
150
|
/**
|
|
121
151
|
* Creates a matcher for the given command that can be used in filtering operations
|
|
122
152
|
*
|
package/out/command.js
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.Command = void 0;
|
|
4
4
|
const deps_node_js_1 = require("./deps.node.js");
|
|
5
|
-
const errors_js_1 = require("./utils/errors.js");
|
|
6
5
|
const array_js_1 = require("./utils/array.js");
|
|
7
6
|
const checks_js_1 = require("./utils/checks.js");
|
|
7
|
+
const errors_js_1 = require("./utils/errors.js");
|
|
8
8
|
const NOCASE_COMMAND_NAME_REGEX = /^[0-9a-z_]+$/i;
|
|
9
9
|
/**
|
|
10
10
|
* Class that represents a single command and allows you to configure it.
|
|
@@ -165,6 +165,58 @@ class Command {
|
|
|
165
165
|
this._scopes.push(scope);
|
|
166
166
|
return this;
|
|
167
167
|
}
|
|
168
|
+
/**
|
|
169
|
+
* Finds the matching command in the given context
|
|
170
|
+
*
|
|
171
|
+
* @example
|
|
172
|
+
* ```ts
|
|
173
|
+
* // ctx.msg.text = "/delete_123 something"
|
|
174
|
+
* const match = Command.findMatchingCommand(/delete_(.*)/, { prefix: "/", ignoreCase: true }, ctx)
|
|
175
|
+
* // match is { command: /delete_(.*)/, rest: ["something"], match: ["delete_123"] }
|
|
176
|
+
* ```
|
|
177
|
+
*/
|
|
178
|
+
static findMatchingCommand(command, options, ctx) {
|
|
179
|
+
var _a;
|
|
180
|
+
const { matchOnlyAtStart, prefix, targetedCommands } = options;
|
|
181
|
+
if (!ctx.has(":text"))
|
|
182
|
+
return null;
|
|
183
|
+
if (matchOnlyAtStart && !ctx.msg.text.startsWith(prefix)) {
|
|
184
|
+
return null;
|
|
185
|
+
}
|
|
186
|
+
const commandNames = (0, array_js_1.ensureArray)(command);
|
|
187
|
+
const escapedPrefix = prefix.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
188
|
+
const commandRegex = new RegExp(`${escapedPrefix}(?<command>[^@ ]+)(?:@(?<username>[^\\s]*))?(?<rest>.*)`, "g");
|
|
189
|
+
const firstCommand = (_a = commandRegex.exec(ctx.msg.text)) === null || _a === void 0 ? void 0 : _a.groups;
|
|
190
|
+
if (!firstCommand)
|
|
191
|
+
return null;
|
|
192
|
+
if (!firstCommand.username && targetedCommands === "required")
|
|
193
|
+
return null;
|
|
194
|
+
if (firstCommand.username && firstCommand.username !== ctx.me.username) {
|
|
195
|
+
return null;
|
|
196
|
+
}
|
|
197
|
+
if (firstCommand.username && targetedCommands === "ignored")
|
|
198
|
+
return null;
|
|
199
|
+
const matchingCommand = commandNames.find((name) => {
|
|
200
|
+
const matches = (0, checks_js_1.matchesPattern)(name instanceof RegExp
|
|
201
|
+
? firstCommand.command + firstCommand.rest
|
|
202
|
+
: firstCommand.command, name, options.ignoreCase);
|
|
203
|
+
return matches;
|
|
204
|
+
});
|
|
205
|
+
if (matchingCommand instanceof RegExp) {
|
|
206
|
+
return {
|
|
207
|
+
command: matchingCommand,
|
|
208
|
+
rest: firstCommand.rest.trim(),
|
|
209
|
+
match: matchingCommand.exec(ctx.msg.text),
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
if (matchingCommand) {
|
|
213
|
+
return {
|
|
214
|
+
command: matchingCommand,
|
|
215
|
+
rest: firstCommand.rest.trim(),
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
return null;
|
|
219
|
+
}
|
|
168
220
|
/**
|
|
169
221
|
* Creates a matcher for the given command that can be used in filtering operations
|
|
170
222
|
*
|
|
@@ -182,30 +234,14 @@ class Command {
|
|
|
182
234
|
* @returns A predicate that matches the given command
|
|
183
235
|
*/
|
|
184
236
|
static hasCommand(command, options) {
|
|
185
|
-
const { matchOnlyAtStart, prefix, targetedCommands } = options;
|
|
186
237
|
return (ctx) => {
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
if (matchOnlyAtStart && !ctx.msg.text.startsWith(prefix)) {
|
|
238
|
+
const matchingCommand = Command.findMatchingCommand(command, options, ctx);
|
|
239
|
+
if (!matchingCommand)
|
|
190
240
|
return false;
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
: ctx.msg.text.split(prefix).map((text) => ({ text }));
|
|
196
|
-
for (const { text } of commands) {
|
|
197
|
-
const [command, username] = text.split("@");
|
|
198
|
-
if (targetedCommands === "ignored" && username)
|
|
199
|
-
continue;
|
|
200
|
-
if (targetedCommands === "required" && !username)
|
|
201
|
-
continue;
|
|
202
|
-
if (username && username !== ctx.me.username)
|
|
203
|
-
continue;
|
|
204
|
-
if (commandNames.some((name) => (0, checks_js_1.matchesPattern)(command.replace(prefix, "").split(" ")[0], name, options.ignoreCase))) {
|
|
205
|
-
return true;
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
return false;
|
|
241
|
+
ctx.match = matchingCommand.rest;
|
|
242
|
+
// TODO: Clean this up. But how to do it without requiring the user to install the commands flavor?
|
|
243
|
+
ctx.commandMatch = matchingCommand;
|
|
244
|
+
return true;
|
|
209
245
|
};
|
|
210
246
|
}
|
|
211
247
|
/**
|
package/out/context.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { CommandGroup } from "./command-group.js";
|
|
2
|
+
import { CommandMatch } from "./command.js";
|
|
2
3
|
import { BotCommandScopeChat, Context, NextFunction } from "./deps.node.js";
|
|
3
4
|
import { SetMyCommandsParams } from "./mod.js";
|
|
4
5
|
import { BotCommandEntity } from "./types.js";
|
|
@@ -42,6 +43,12 @@ export interface CommandsFlavor<C extends Context = Context> extends Context {
|
|
|
42
43
|
* @returns command entities hydrated with the custom prefixes
|
|
43
44
|
*/
|
|
44
45
|
getCommandEntities: (commands: CommandGroup<C> | CommandGroup<C>[]) => BotCommandEntity[];
|
|
46
|
+
/**
|
|
47
|
+
* The matched command and the rest of the input.
|
|
48
|
+
*
|
|
49
|
+
* When matched command is a RegExp, a `match` property exposes the result of the RegExp match.
|
|
50
|
+
*/
|
|
51
|
+
commandMatch: CommandMatch;
|
|
45
52
|
}
|
|
46
53
|
/**
|
|
47
54
|
* Installs the commands flavor into the context.
|
package/out/context.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.MyCommandParams =
|
|
3
|
+
exports.MyCommandParams = void 0;
|
|
4
|
+
exports.commands = commands;
|
|
4
5
|
const array_js_1 = require("./utils/array.js");
|
|
5
6
|
const jaro_winkler_js_1 = require("./utils/jaro-winkler.js");
|
|
6
7
|
const set_bot_commands_js_1 = require("./utils/set-bot-commands.js");
|
|
@@ -70,7 +71,6 @@ function commands() {
|
|
|
70
71
|
return next();
|
|
71
72
|
};
|
|
72
73
|
}
|
|
73
|
-
exports.commands = commands;
|
|
74
74
|
/**
|
|
75
75
|
* Static class for getting and manipulating {@link SetMyCommandsParams}.
|
|
76
76
|
* The main function is {@link from}
|
package/out/utils/array.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.ensureArray = void 0;
|
|
4
|
+
exports.escapeSpecial = escapeSpecial;
|
|
5
|
+
exports.getCommandsRegex = getCommandsRegex;
|
|
4
6
|
const ensureArray = (value) => Array.isArray(value) ? value : [value];
|
|
5
7
|
exports.ensureArray = ensureArray;
|
|
6
8
|
const specialChars = "\\.^$|?*+()[]{}-".split("");
|
|
@@ -8,8 +10,6 @@ const replaceAll = (s, find, replace) => s.replace(new RegExp(`\\${find}`, "g"),
|
|
|
8
10
|
function escapeSpecial(str) {
|
|
9
11
|
return specialChars.reduce((acc, char) => replaceAll(acc, char, `\\${char}`), str);
|
|
10
12
|
}
|
|
11
|
-
exports.escapeSpecial = escapeSpecial;
|
|
12
13
|
function getCommandsRegex(prefix) {
|
|
13
14
|
return new RegExp(`(\?\<\!\\S)(\?<prefix>${escapeSpecial(prefix)})\\S+(\\s|$)`, "g");
|
|
14
15
|
}
|
|
15
|
-
exports.getCommandsRegex = getCommandsRegex;
|
package/out/utils/checks.js
CHANGED
|
@@ -1,15 +1,20 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.isAdmin = isAdmin;
|
|
4
|
+
exports.isMiddleware = isMiddleware;
|
|
5
|
+
exports.isCommandOptions = isCommandOptions;
|
|
6
|
+
exports.matchesPattern = matchesPattern;
|
|
7
|
+
const deps_node_js_1 = require("../deps.node.js");
|
|
4
8
|
function isAdmin(ctx) {
|
|
5
9
|
return ctx
|
|
6
10
|
.getAuthor()
|
|
7
11
|
.then((author) => ["administrator", "creator"].includes(author.status));
|
|
8
12
|
}
|
|
9
|
-
exports.isAdmin = isAdmin;
|
|
10
13
|
function isMiddleware(obj) {
|
|
11
14
|
if (!obj)
|
|
12
15
|
return false;
|
|
16
|
+
if (obj instanceof deps_node_js_1.Composer)
|
|
17
|
+
return true;
|
|
13
18
|
if (Array.isArray(obj))
|
|
14
19
|
return obj.every(isMiddleware);
|
|
15
20
|
const objType = typeof obj;
|
|
@@ -21,7 +26,6 @@ function isMiddleware(obj) {
|
|
|
21
26
|
}
|
|
22
27
|
return false;
|
|
23
28
|
}
|
|
24
|
-
exports.isMiddleware = isMiddleware;
|
|
25
29
|
function isCommandOptions(obj) {
|
|
26
30
|
if (typeof obj !== "object" || !obj)
|
|
27
31
|
return false;
|
|
@@ -37,7 +41,6 @@ function isCommandOptions(obj) {
|
|
|
37
41
|
return true;
|
|
38
42
|
return false;
|
|
39
43
|
}
|
|
40
|
-
exports.isCommandOptions = isCommandOptions;
|
|
41
44
|
function matchesPattern(value, pattern, ignoreCase = false) {
|
|
42
45
|
const transformedValue = ignoreCase ? value.toLowerCase() : value;
|
|
43
46
|
const transformedPattern = pattern instanceof RegExp && ignoreCase && !pattern.flags.includes("i")
|
|
@@ -47,4 +50,3 @@ function matchesPattern(value, pattern, ignoreCase = false) {
|
|
|
47
50
|
? transformedValue === transformedPattern
|
|
48
51
|
: transformedPattern.test(transformedValue);
|
|
49
52
|
}
|
|
50
|
-
exports.matchesPattern = matchesPattern;
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.distance = distance;
|
|
4
|
+
exports.JaroWinklerDistance = JaroWinklerDistance;
|
|
5
|
+
exports.isLanguageCode = isLanguageCode;
|
|
6
|
+
exports.fuzzyMatch = fuzzyMatch;
|
|
4
7
|
const language_codes_js_1 = require("../language-codes.js");
|
|
5
8
|
function distance(s1, s2) {
|
|
6
9
|
if (s1.length === 0 || s2.length === 0) {
|
|
@@ -61,7 +64,6 @@ function distance(s1, s2) {
|
|
|
61
64
|
return (m / s1.length + m / s2.length + (m - t) / m) / 3.0; // HtD: therefore, m - t > 0, and m - t < m
|
|
62
65
|
// HtD: => return value is between 0 and 1
|
|
63
66
|
}
|
|
64
|
-
exports.distance = distance;
|
|
65
67
|
// Computes the Winkler distance between two string -- intrepreted from:
|
|
66
68
|
// http://en.wikipedia.org/wiki/Jaro%E2%80%93Winkler_distance
|
|
67
69
|
// s1 is the first string to compare
|
|
@@ -87,11 +89,9 @@ function JaroWinklerDistance(s1, s2, options) {
|
|
|
87
89
|
return jaro + l * p * (1 - jaro);
|
|
88
90
|
}
|
|
89
91
|
}
|
|
90
|
-
exports.JaroWinklerDistance = JaroWinklerDistance;
|
|
91
92
|
function isLanguageCode(value) {
|
|
92
93
|
return Object.values(language_codes_js_1.LanguageCodes).includes(value);
|
|
93
94
|
}
|
|
94
|
-
exports.isLanguageCode = isLanguageCode;
|
|
95
95
|
function fuzzyMatch(userInput, commands, options) {
|
|
96
96
|
var _a;
|
|
97
97
|
const defaultSimilarityThreshold = 0.82;
|
|
@@ -114,4 +114,3 @@ function fuzzyMatch(userInput, commands, options) {
|
|
|
114
114
|
}, { command: null, similarity: 0 });
|
|
115
115
|
return bestMatch.similarity > similarityThreshold ? bestMatch : null;
|
|
116
116
|
}
|
|
117
|
-
exports.fuzzyMatch = fuzzyMatch;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.setBotCommands =
|
|
3
|
+
exports.setBotCommands = setBotCommands;
|
|
4
4
|
const errors_js_1 = require("./errors.js");
|
|
5
5
|
/**
|
|
6
6
|
* Performs validation and sets the provided commands for the bot.
|
|
@@ -16,4 +16,3 @@ async function setBotCommands(api, commandParams, uncompliantCommands, options)
|
|
|
16
16
|
}
|
|
17
17
|
await Promise.all(commandParams.map((args) => api.raw.setMyCommands(args)));
|
|
18
18
|
}
|
|
19
|
-
exports.setBotCommands = setBotCommands;
|
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@grammyjs/commands",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.4",
|
|
4
4
|
"description": "grammY Commands Plugin",
|
|
5
5
|
"main": "out/mod.js",
|
|
6
6
|
"scripts": {
|
|
7
|
-
"backport": "
|
|
8
|
-
"prepare": "
|
|
7
|
+
"backport": "deno2node tsconfig.json",
|
|
8
|
+
"prepare": "npm run backport"
|
|
9
9
|
},
|
|
10
10
|
"keywords": [
|
|
11
11
|
"grammY",
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"grammy": "^1.17.1"
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {
|
|
30
|
-
"
|
|
30
|
+
"deno2node": "^1.14.0",
|
|
31
31
|
"typescript": "^5.6.3"
|
|
32
32
|
},
|
|
33
33
|
"files": [
|