Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: 0.8 release #26

Merged
merged 33 commits into from
Jun 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
3b72180
add to setMyCommands param support for passing an array. Move ensure …
carafelix May 29, 2024
0f1fa7e
add jsdoc examples, deno fmt
carafelix May 29, 2024
afeef9e
explicit type import
carafelix May 29, 2024
8c7b3e6
refactor mergeMyCommandsParams function into a static class
carafelix May 31, 2024
e76d5b3
update tests to use the static class version, hide internals methods,…
carafelix Jun 4, 2024
e5675dc
improve jsdoc, deno fmt
carafelix Jun 4, 2024
ee08b4e
Apply request changes from review:
carafelix Jun 4, 2024
0d61759
underscore public functions that aren't too relevant but are useful e…
carafelix Jun 4, 2024
11bcec5
CHANGE fuzzyMatch return interface, FIX fuzzyMatch from returning a c…
carafelix May 25, 2024
3a2f9e5
encapsulate fuzzyMatch output so it does not brake prior releases
carafelix May 25, 2024
8a87a9b
add tests illustrating the collision problem mentioned in bug: #18
carafelix May 26, 2024
bec70e3
add tests for between-class collisions mentioned in #18
carafelix May 26, 2024
73558bc
lower similarity threshold to allow 3 letter words with 1 letter diff…
carafelix May 28, 2024
660a78d
add test's for proof of concept
carafelix May 28, 2024
f73d083
add ignoreLocalization behavior and tests for it. (ugly code)
carafelix May 28, 2024
21001a4
hide parameter from where it was not use
carafelix May 28, 2024
f9ec95c
add more test's
carafelix May 28, 2024
2b0121f
add getNearestCommand support for multiple command instances, improve…
carafelix May 29, 2024
59e61f1
Apply suggestions from code review
carafelix May 29, 2024
b64a058
improve coverage by testing on null input
carafelix Jun 5, 2024
fc0f06b
export dummy ctx function
carafelix Jun 5, 2024
19caa43
types
carafelix Jun 16, 2024
b33ea6e
refactor toElementals
carafelix Jun 16, 2024
38cff93
- add check for ctx.from.id being ISO639 compatible
carafelix Jun 17, 2024
aec39e7
- add languageCode type to commandElementals. - minor jsdoc.
carafelix Jun 17, 2024
73b1768
when then user is not known, change fallback to all possible languages
carafelix Jun 17, 2024
f19092b
update test's accordingly to change introduced in commit 83e1509
carafelix Jun 18, 2024
1015fe8
add prefilter for regex inside .toArgs
carafelix Jun 18, 2024
9dec11b
- add scope and description to the .toElementals method
carafelix Jun 18, 2024
ed2e836
added a regex test for .toElementals
carafelix Jun 18, 2024
410c662
add jsdoc notes on throw behavior. closes #24
carafelix Jun 18, 2024
b32b122
version bump 0.8.0
carafelix Jun 18, 2024
01d8f02
deno fmt
carafelix Jun 18, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 11 additions & 5 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@grammyjs/commands",
"version": "0.7.0",
"version": "0.8.0",
"description": "grammY Commands Plugin",
"main": "out/mod.js",
"scripts": {
Expand All @@ -16,6 +16,7 @@
"author": "Roz <[email protected]>",
"license": "MIT",
"dependencies": {
"@grammyjs/types": "^3.8.1",
"grammy": "^1.17.1",
"ts-pattern": "^5.0.1"
},
Expand Down
28 changes: 17 additions & 11 deletions src/command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,18 @@ import {
type ChatTypeMiddleware,
Composer,
type Context,
type LanguageCode,
type Middleware,
type MiddlewareObj,
} from "./deps.deno.ts";
import { InvalidScopeError } from "./errors.ts";
import { CommandOptions } from "./types.ts";

export type MaybeArray<T> = T | T[];
import type { CommandOptions } from "./types.ts";
import { ensureArray, type MaybeArray } from "./utils.ts";

type BotCommandGroupsScope =
| BotCommandScopeAllGroupChats
| BotCommandScopeAllChatAdministrators;

const ensureArray = <T>(value: MaybeArray<T>): T[] =>
Array.isArray(value) ? value : [value];

const isAdmin = (ctx: Context) =>
ctx
.getAuthor()
Expand All @@ -36,7 +33,7 @@ export const matchesPattern = (value: string, pattern: string | RegExp) =>
export class Command<C extends Context = Context> implements MiddlewareObj<C> {
private _scopes: BotCommandScope[] = [];
private _languages: Map<
string,
LanguageCode | "default",
{ name: string | RegExp; description: string }
> = new Map();
private _composer: Composer<C> = new Composer<C>();
Expand Down Expand Up @@ -100,6 +97,13 @@ export class Command<C extends Context = Context> implements MiddlewareObj<C> {
return this._languages.get("default")!.description;
}

/**
* Get the prefix for this command
*/
get prefix() {
return this._options.prefix;
}

/**
* Registers the command to a scope to allow it to be handled and used with `setMyCommands`.
* This will automatically apply filtering middlewares for you, so the handler only runs on the specified scope.
Expand Down Expand Up @@ -263,7 +267,7 @@ export class Command<C extends Context = Context> implements MiddlewareObj<C> {
* @param description Localized command description
*/
public localize(
languageCode: string,
languageCode: LanguageCode,
name: string | RegExp,
description: string,
) {
Expand All @@ -279,7 +283,7 @@ export class Command<C extends Context = Context> implements MiddlewareObj<C> {
* @param languageCode Language to get the name for
* @returns Localized command name
*/
public getLocalizedName(languageCode: string) {
public getLocalizedName(languageCode: LanguageCode | "default") {
return this._languages.get(languageCode)?.name ?? this.name;
}

Expand All @@ -288,7 +292,7 @@ export class Command<C extends Context = Context> implements MiddlewareObj<C> {
* @param languageCode Language to get the name for
* @returns Localized command name
*/
public getLocalizedDescription(languageCode: string) {
public getLocalizedDescription(languageCode: LanguageCode | "default") {
return this._languages.get(languageCode)?.description ??
this.description;
}
Expand All @@ -300,7 +304,9 @@ export class Command<C extends Context = Context> implements MiddlewareObj<C> {
* @param languageCode If specified, uses localized versions of the command name and description
* @returns Object representation of this command
*/
public toObject(languageCode = "default"): BotCommand {
public toObject(
languageCode: LanguageCode | "default" = "default",
): BotCommand {
const localizedName = this.getLocalizedName(languageCode);
return {
command: localizedName instanceof RegExp
Expand Down
84 changes: 69 additions & 15 deletions src/commands.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,29 @@
import { Command, MaybeArray } from "./command.ts";
import { Command } from "./command.ts";
import {
Api,
BotCommand,
BotCommandScope,
CommandContext,
Composer,
Context,
type LanguageCode,
Middleware,
} from "./deps.deno.ts";
import { CommandOptions } from "./types.ts";
import type { CommandElementals, CommandOptions } from "./types.ts";
import { type MaybeArray } from "./utils.ts";

/**
* Interface for grouping {@link BotCommand}s that might (or not)
* be related to each other by scope and/or language.
*/
export type SetMyCommandsParams = {
/**
* Scope
* @param language_code two letter abbreviation in ISO_639 standard: https://en.wikipedia.org/wiki/List_of_ISO_639_language_codes
*/
/** If defined: scope on which the commands will take effect */
scope?: BotCommandScope;
language_code?: string;
/** If defined: Language on which the commands will take effect.
* Two letter abbreviation in ISO_639 standard: https://en.wikipedia.org/wiki/List_of_ISO_639_language_codes
*/
language_code?: LanguageCode;
/** Commands that can be each one passed to a SetMyCommands Call */
commands: BotCommand[];
};

Expand Down Expand Up @@ -51,7 +58,7 @@ const isMiddleware = <C extends Context>(
* ```
*/
export class Commands<C extends Context> {
private _languages: Set<string> = new Set();
private _languages: Set<LanguageCode | "default"> = new Set();
private _scopes: Map<string, Array<Command<C>>> = new Map();
private _commands: Command<C>[] = [];
private _composer: Composer<C> = new Composer();
Expand Down Expand Up @@ -150,10 +157,9 @@ export class Commands<C extends Context> {
language_code: language === "default"
? undefined
: language,
commands: commands.map((command) =>
command.toObject(language)
)
.filter((args) => args.command.length > 0),
commands: commands
.filter((command) => typeof command.name === "string")
.map((command) => command.toObject(language)),
});
}
}
Expand Down Expand Up @@ -187,6 +193,11 @@ export class Commands<C extends Context> {
* Registers all commands to be displayed by clients according to their scopes and languages
* Calls `setMyCommands` for each language of each scope of each command.
*
* [!IMPORTANT]
* Calling this method with upperCased command names registered, will throw
* @see https://core.telegram.org/bots/api#botcommand
* @see https://core.telegram.org/method/bots.setBotCommands
*
* @param Instance of `bot` or { api: bot.api }
*/
public async setCommands({ api }: { api: Api }) {
Expand All @@ -196,10 +207,53 @@ export class Commands<C extends Context> {
}

/**
* Alias for {@link toArgs}
* Serialize all register commands into it's name, prefix and language
*
* @param filterLanguage if undefined, it returns all names
* else get only the locales for the given filterLanguage
* fallbacks to "default"
*
* @returns an array of {@link CommandElementals}
*
* Note: mainly used to serialize for {@link FuzzyMatch}
*/
public toJSON() {
return this.toArgs();

public toElementals(
filterLanguage?: LanguageCode | "default",
): CommandElementals[] {
this._populateMetadata();

return Array.from(this._scopes.values())
.flat()
.flatMap(
(command) => {
const elements = [];
for (
const [language, local] of command.languages.entries()
) {
elements.push({
name: local.name instanceof RegExp
? local.name.source
: local.name,
language,
prefix: command.prefix,
scopes: command.scopes,
description: command.getLocalizedDescription(
language,
),
});
}
if (filterLanguage) {
const filtered = elements.filter((command) =>
command.language === filterLanguage
);
const defaulted = elements.filter((command) =>
command.language === "default"
);
return filtered.length ? filtered[0] : defaulted[0];
} else return elements;
},
);
}

/**
Expand Down
Loading
Loading