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

feat: allow specifying default scope #8

Merged
merged 3 commits into from
Apr 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 2 additions & 2 deletions deno.jsonc
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@
"lock": false,
"tasks": {
"backport": "rm -rf out && deno run --no-prompt --allow-read=. --allow-write=. https://deno.land/x/deno2node@v1.9.0/src/cli.ts",
"quality:check": "deno lint && deno fmt --check && deno check src/mod.ts",
"quality:fix": "deno lint --fix && deno fmt",
"check": "deno lint && deno fmt --check && deno check src/mod.ts",
"fix": "deno lint --fix && deno fmt",
"test": "deno test --seed=123456 --parallel ./test/",
"coverage": "rm -rf ./test/cov_profile && deno task test --coverage=./test/cov_profile && deno coverage --lcov --output=./coverage.lcov ./test/cov_profile"
}
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

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

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@grammyjs/commands",
"version": "0.5.1",
"version": "0.6.0",
"description": "grammY Commands Plugin",
"main": "out/mod.js",
"scripts": {
Expand Down
56 changes: 52 additions & 4 deletions src/commands.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { Command } from "./command.ts";
import { Command, MaybeArray } from "./command.ts";
import {
Api,
BotCommand,
BotCommandScope,
Composer,
Context,
Middleware,
} from "./deps.deno.ts";
import { CommandOptions } from "./types.ts";

Expand All @@ -17,6 +18,23 @@ type SetMyCommandsParams = {
commands: BotCommand[];
};

const isMiddleware = <C extends Context>(
obj: unknown,
): obj is MaybeArray<Middleware<C>> => {
if (!obj) return false;
if (Array.isArray(obj)) return obj.every(isMiddleware);
const objType = typeof obj;

switch (objType) {
case "function":
return true;
case "object":
return Object.keys(obj).includes("middleware");
}

return false;
};

/**
* Central class that manages all registered commands.
* This is the starting point for the plugin, and this is what you should pass to `bot.use` so your commands get properly registered.
Expand Down Expand Up @@ -68,18 +86,48 @@ export class Commands<C extends Context> {
}

/**
* Registers a new command and returns it.
* @param name Command name
* Registers a new command with a default handler.
* @param name Default command name
* @param description Default command description
* @param handler Default command handler
* @param options Extra options that should apply only to this command
* @returns An instance of the `Command` class
*/
public command(
name: string | RegExp,
description: string,
options: Partial<CommandOptions> = this._commandOptions,
handler: MaybeArray<Middleware<C>>,
options?: Partial<CommandOptions>,
): Command<C>;
/**
* Registers a new command with no handlers.
* @param name Default command name
* @param description Default command description
* @param options Extra options that should apply only to this command
* @returns An instance of the `Command` class
*/
public command(
name: string | RegExp,
description: string,
options?: Partial<CommandOptions>,
): Command<C>;
public command(
name: string | RegExp,
description: string,
handlerOrOptions?: MaybeArray<Middleware<C>> | Partial<CommandOptions>,
_options?: Partial<CommandOptions>,
) {
const handler = isMiddleware(handlerOrOptions)
? handlerOrOptions
: undefined;
const options = handler
? _options ?? this._commandOptions
: handlerOrOptions as Partial<CommandOptions> ??
this._commandOptions;

const command = new Command<C>(name, description, options);
if (handler) command.addToScope({ type: "default" }, handler);

this._commands.push(command);
return command;
}
Expand Down
1 change: 1 addition & 0 deletions src/mod.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export { Command } from "./command.ts";
export * from "./commands.ts";
export * from "./context.ts";
export type { CommandOptions } from "./types.ts";
46 changes: 46 additions & 0 deletions test/commands.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { Commands } from "../src/commands.ts";
import { assertEquals, describe, it } from "./deps.test.ts";

describe("Commands", () => {
describe("command", () => {
it("should create a command with no handlers", () => {
const commands = new Commands();
commands.command("test", "no handler");

assertEquals(commands.toArgs(), []);
});

it("should create a command with a default handler", () => {
const commands = new Commands();
commands.command("test", "default handler", () => {}, {
prefix: undefined,
});

assertEquals(commands.toArgs(), [{
commands: [{ command: "test", description: "default handler" }],
language_code: undefined,
scope: { type: "default" },
}]);
});

it("should support options with no handler", () => {
const commands = new Commands();
commands.command("test", "no handler", { prefix: "test" });
assertEquals(
(commands as any)._commands[0]._options.prefix,
"test",
);
});

it("should support options with default handler", () => {
const commands = new Commands();
commands.command("test", "default handler", () => {}, {
prefix: "test",
});
assertEquals(
(commands as any)._commands[0]._options.prefix,
"test",
);
});
});
});
2 changes: 1 addition & 1 deletion test/context.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
UserFromGetMe,
} from "./deps.test.ts";

describe("the commands function", () => {
describe("commands", () => {
const u = { id: 42, first_name: "bot", is_bot: true } as User;
const c = { id: 100, type: "private" } as Chat;
const m = { text: "a", from: u, chat: c, sender_chat: c } as Message;
Expand Down
11 changes: 7 additions & 4 deletions test/jaroWrinkler.test.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import { distance } from "../src/jaro-winkler.ts";
import { fuzzyMatch, JaroWinklerDistance } from "../src/jaro-winkler.ts";
import { assertEquals, Context, describe, it } from "./deps.test.ts";
import {
distance,
fuzzyMatch,
JaroWinklerDistance,
} from "../src/jaro-winkler.ts";
import { Commands } from "../src/mod.ts";
import { assertEquals, Context, describe, it } from "./deps.test.ts";

describe("The Jaro-Wrinkler Algorithm", () => {
describe("Jaro-Wrinkler Algorithm", () => {
it("should return value 0, because the empty string was given", () => {
assertEquals(distance("", ""), 0);
});
Expand Down
Loading