@pikokr/command.ts 3.0.6 β†’ 3.0.8-dev.3955b1f

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.
Files changed (37) hide show
  1. package/.all-contributorsrc +33 -0
  2. package/LICENSE +21 -0
  3. package/README.md +5 -3
  4. package/dist/builtinModules/BuiltinCommandConverters.d.ts +3 -1
  5. package/dist/builtinModules/BuiltinCommandConverters.js +40 -3
  6. package/dist/builtinModules/BuiltinSlashCommandConverters.d.ts +2 -1
  7. package/dist/builtinModules/BuiltinSlashCommandConverters.js +9 -0
  8. package/dist/builtinModules/CommandHandler.js +3 -0
  9. package/dist/command/decorator.js +27 -3
  10. package/dist/error/ModuleError.d.ts +2 -1
  11. package/dist/error/ModuleError.js +2 -1
  12. package/dist/error/checks/DMOnlyCommand.d.ts +3 -0
  13. package/dist/error/checks/DMOnlyCommand.js +9 -0
  14. package/dist/error/checks/GuildOnlyCommand.d.ts +3 -0
  15. package/dist/error/checks/GuildOnlyCommand.js +9 -0
  16. package/dist/error/checks/OwnerOnlyCommand.d.ts +3 -0
  17. package/dist/error/checks/OwnerOnlyCommand.js +9 -0
  18. package/dist/error/checks/index.d.ts +3 -0
  19. package/dist/error/checks/index.js +15 -0
  20. package/dist/error/index.d.ts +1 -0
  21. package/dist/error/index.js +1 -0
  22. package/dist/structures/CommandClient.d.ts +2 -1
  23. package/dist/structures/CommandClient.js +1 -0
  24. package/dist/structures/Registry.js +11 -2
  25. package/package.json +2 -2
  26. package/src/builtinModules/BuiltinCommandConverters.ts +31 -3
  27. package/src/builtinModules/BuiltinSlashCommandConverters.ts +6 -1
  28. package/src/builtinModules/CommandHandler.ts +4 -0
  29. package/src/command/decorator.ts +25 -7
  30. package/src/error/ModuleError.ts +1 -1
  31. package/src/error/checks/DMOnlyCommand.ts +5 -0
  32. package/src/error/checks/GuildOnlyCommand.ts +5 -0
  33. package/src/error/checks/OwnerOnlyCommand.ts +5 -0
  34. package/src/error/checks/index.ts +3 -0
  35. package/src/error/index.ts +1 -0
  36. package/src/structures/CommandClient.ts +3 -1
  37. package/src/structures/Registry.ts +11 -2
@@ -0,0 +1,33 @@
1
+ {
2
+ "files": [
3
+ "README.md"
4
+ ],
5
+ "imageSize": 100,
6
+ "contributorsPerLine": 7,
7
+ "contributorsSortAlphabetically": false,
8
+ "badgeTemplate": "[![All Contributors](https://img.shields.io/badge/all_contributors-<%= contributors.length %>-orange.svg?style=flat-square)](#contributors)",
9
+ "contributorTemplate": "<a href=\"<%= contributor.profile %>\"><img src=\"<%= contributor.avatar_url %>\" width=\"<%= options.imageSize %>px;\" alt=\"\"/><br /><sub><b><%= contributor.name %></b></sub></a>",
10
+ "types": {
11
+ "custom": {
12
+ "symbol": "πŸ”­",
13
+ "description": "A custom contribution type.",
14
+ "link": "[<%= symbol %>](<%= url %> \"<%= description %>\"),"
15
+ }
16
+ },
17
+ "skipCi": true,
18
+ "contributors": [
19
+ {
20
+ "login": "pikokr",
21
+ "name": "파링",
22
+ "avatar_url": "https://avatars.githubusercontent.com/u/68010770?v=4",
23
+ "profile": "https://pikokr.dev",
24
+ "contributions": [
25
+ "code"
26
+ ]
27
+ }
28
+ ],
29
+ "projectName": "command.ts",
30
+ "projectOwner": "pikokr",
31
+ "repoType": "github",
32
+ "repoHost": "https://github.com"
33
+ }
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2021 파링
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 CHANGED
@@ -1,7 +1,9 @@
1
1
  # Command.TS
2
2
 
3
- Command framework for discord.js
3
+ [![.github/workflows/publish.yml](https://github.com/pikokr/command.ts/actions/workflows/publish.yml/badge.svg)](https://github.com/pikokr/command.ts/actions/workflows/publish.yml)
4
+
5
+ ![cts](https://user-images.githubusercontent.com/68010770/145200458-b14c5e4e-6927-4516-8d48-c68a384d2a20.png)
4
6
 
5
- [Discord](https://discord.gg/EEhcPzsGHV) [κ°€μ΄λ“œ](https://pikokr.notion.site/a60262db37724fd38e4b7fc83be7e52d)
7
+ Command framework for discord.js
6
8
 
7
- [V2 λ¬Έμ„œ](https://command-ts-docs-ezojnktwv-pikokr.vercel.app/)
9
+ [Discord](https://discord.gg/EEhcPzsGHV) / [λ¬Έμ„œ](https://v3.cts.pikokr.dev) / [V2 λ¬Έμ„œ](https://command-ts-docs-ezojnktwv-pikokr.vercel.app/)
@@ -1,5 +1,5 @@
1
1
  import { BuiltInModule } from './BuiltInModule';
2
- import { Client, GuildMember, Message, User } from 'discord.js';
2
+ import { Client, GuildMember, Message, User, Role } from 'discord.js';
3
3
  import { CommandClient } from '../structures';
4
4
  export declare class BuiltinCommandConverters extends BuiltInModule {
5
5
  private cts;
@@ -11,4 +11,6 @@ export declare class BuiltinCommandConverters extends BuiltInModule {
11
11
  user(msg: Message, value: string): User | null;
12
12
  member(msg: Message, value: string): GuildMember | undefined;
13
13
  number(msg: Message, value: string): number | undefined;
14
+ getRoleIDByMention(mention: string): `${bigint}` | undefined;
15
+ role(msg: Message, value: string): Role | undefined;
14
16
  }
@@ -37,24 +37,55 @@ class BuiltinCommandConverters extends BuiltInModule_1.BuiltInModule {
37
37
  }
38
38
  }
39
39
  user(msg, value) {
40
+ let user = this.client.users.cache.get(value);
41
+ if (user)
42
+ return user;
43
+ user = this.client.users.cache.find(x => x.tag === value);
44
+ if (user)
45
+ return user;
40
46
  const id = this.getUserIDByMention(value);
41
47
  if (!id)
42
48
  return null;
43
- const user = this.client.users.cache.get(id);
49
+ user = this.client.users.cache.get(id);
44
50
  return user || null;
45
51
  }
46
52
  member(msg, value) {
47
- var _a;
53
+ var _a, _b, _c;
54
+ let user = (_a = msg.guild) === null || _a === void 0 ? void 0 : _a.members.cache.get(value);
55
+ if (!user)
56
+ return user;
57
+ user = (_b = msg.guild) === null || _b === void 0 ? void 0 : _b.members.cache.find(x => x.user.tag === value);
58
+ if (user)
59
+ return user;
48
60
  const id = this.getUserIDByMention(value);
49
61
  if (!id)
50
62
  return;
51
- const user = (_a = msg.guild) === null || _a === void 0 ? void 0 : _a.members.cache.get(id);
63
+ user = (_c = msg.guild) === null || _c === void 0 ? void 0 : _c.members.cache.get(id);
52
64
  return user || undefined;
53
65
  }
54
66
  number(msg, value) {
55
67
  const n = Number(value);
56
68
  return isNaN(n) ? undefined : n;
57
69
  }
70
+ getRoleIDByMention(mention) {
71
+ if (!mention)
72
+ return;
73
+ if (mention.startsWith('<@') && mention.endsWith('>')) {
74
+ mention = mention.slice(2, -1);
75
+ if (mention.startsWith('&')) {
76
+ mention = mention.slice(1);
77
+ }
78
+ return mention;
79
+ }
80
+ }
81
+ role(msg, value) {
82
+ var _a;
83
+ const id = this.getRoleIDByMention(value);
84
+ if (!id)
85
+ return;
86
+ const role = (_a = msg.guild) === null || _a === void 0 ? void 0 : _a.roles.cache.get(id);
87
+ return role || undefined;
88
+ }
58
89
  }
59
90
  __decorate([
60
91
  command_1.argumentConverter(discord_js_1.Message, false),
@@ -86,4 +117,10 @@ __decorate([
86
117
  __metadata("design:paramtypes", [discord_js_1.Message, String]),
87
118
  __metadata("design:returntype", void 0)
88
119
  ], BuiltinCommandConverters.prototype, "number", null);
120
+ __decorate([
121
+ command_1.argumentConverter(discord_js_1.Role),
122
+ __metadata("design:type", Function),
123
+ __metadata("design:paramtypes", [discord_js_1.Message, String]),
124
+ __metadata("design:returntype", Object)
125
+ ], BuiltinCommandConverters.prototype, "role", null);
89
126
  exports.BuiltinCommandConverters = BuiltinCommandConverters;
@@ -1,9 +1,10 @@
1
1
  import { BuiltInModule } from './BuiltInModule';
2
- import { Client, CommandInteraction } from 'discord.js';
2
+ import { Client, CommandInteraction, CommandInteractionOptionResolver } from 'discord.js';
3
3
  import { CommandClient } from '../structures';
4
4
  export declare class BuiltinSlashCommandConverters extends BuiltInModule {
5
5
  private cts;
6
6
  client: Client;
7
7
  constructor(cts: CommandClient);
8
8
  message(interaction: CommandInteraction): CommandInteraction;
9
+ optionResolver(interaction: CommandInteraction): CommandInteractionOptionResolver;
9
10
  }
@@ -22,6 +22,9 @@ class BuiltinSlashCommandConverters extends BuiltInModule_1.BuiltInModule {
22
22
  message(interaction) {
23
23
  return interaction;
24
24
  }
25
+ optionResolver(interaction) {
26
+ return interaction.options;
27
+ }
25
28
  }
26
29
  __decorate([
27
30
  command_1.slashArgumentConverter(discord_js_1.CommandInteraction),
@@ -29,4 +32,10 @@ __decorate([
29
32
  __metadata("design:paramtypes", [discord_js_1.CommandInteraction]),
30
33
  __metadata("design:returntype", void 0)
31
34
  ], BuiltinSlashCommandConverters.prototype, "message", null);
35
+ __decorate([
36
+ command_1.slashArgumentConverter(discord_js_1.CommandInteractionOptionResolver),
37
+ __metadata("design:type", Function),
38
+ __metadata("design:paramtypes", [discord_js_1.CommandInteraction]),
39
+ __metadata("design:returntype", discord_js_1.CommandInteractionOptionResolver)
40
+ ], BuiltinSlashCommandConverters.prototype, "optionResolver", null);
32
41
  exports.BuiltinSlashCommandConverters = BuiltinSlashCommandConverters;
@@ -32,6 +32,9 @@ class CommandHandler extends BuiltInModule_1.BuiltInModule {
32
32
  }
33
33
  message(msg) {
34
34
  return __awaiter(this, void 0, void 0, function* () {
35
+ if (!(yield this.client.options.command.check(msg))) {
36
+ return;
37
+ }
35
38
  const error = (error) => this.client.client.emit('commandError', error, msg);
36
39
  try {
37
40
  const prefixList = typeof this.client.options.command.prefix === 'string'
@@ -75,9 +75,33 @@ const rest = (target, propertyKey, parameterIndex) => {
75
75
  Reflect.defineMetadata(constants_1.KRest, parameterIndex, target, propertyKey);
76
76
  };
77
77
  exports.rest = rest;
78
- exports.ownerOnly = utils_2.createCheckDecorator((msg) => msg.data.cts.owners.includes(msg.author.id), (i) => i.data.cts.owners.includes(i.user.id));
79
- exports.guildOnly = utils_2.createCheckDecorator((msg) => !!msg.guild, (i) => !!i.guildId);
80
- exports.dmOnly = utils_2.createCheckDecorator((msg) => !msg.guild, (i) => !i.guildId);
78
+ exports.ownerOnly = utils_2.createCheckDecorator((msg) => {
79
+ if (msg.data.cts.owners.includes(msg.author.id))
80
+ return true;
81
+ throw new error_1.OwnerOnlyCommandError();
82
+ }, (i) => {
83
+ if (i.data.cts.owners.includes(i.user.id))
84
+ return true;
85
+ throw new error_1.OwnerOnlyCommandError();
86
+ });
87
+ exports.guildOnly = utils_2.createCheckDecorator((msg) => {
88
+ if (!!msg.guild)
89
+ return true;
90
+ throw new error_1.GuildOnlyCommandError();
91
+ }, (i) => {
92
+ if (!!i.guildId)
93
+ return true;
94
+ throw new error_1.GuildOnlyCommandError();
95
+ });
96
+ exports.dmOnly = utils_2.createCheckDecorator((msg) => {
97
+ if (!msg.guild)
98
+ return true;
99
+ throw new error_1.DMOnlyCommandError();
100
+ }, (i) => {
101
+ if (!i.guildId)
102
+ return true;
103
+ throw new error_1.DMOnlyCommandError();
104
+ });
81
105
  const requireUserPermissions = (permission) => utils_2.createCheckDecorator((msg) => {
82
106
  if (!msg.guild || !msg.member)
83
107
  throw new Error('This command must be used in guild.');
@@ -1,5 +1,6 @@
1
1
  export declare class ModuleLoadError extends Error {
2
- constructor(file: string);
2
+ error: Error;
3
+ constructor(file: string, error: Error);
3
4
  }
4
5
  export declare class InvalidModuleError extends Error {
5
6
  }
@@ -2,8 +2,9 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.InvalidModuleError = exports.ModuleLoadError = void 0;
4
4
  class ModuleLoadError extends Error {
5
- constructor(file) {
5
+ constructor(file, error) {
6
6
  super('Failed to load module ' + file);
7
+ this.error = error;
7
8
  }
8
9
  }
9
10
  exports.ModuleLoadError = ModuleLoadError;
@@ -0,0 +1,3 @@
1
+ export declare class DMOnlyCommandError extends Error {
2
+ constructor();
3
+ }
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DMOnlyCommandError = void 0;
4
+ class DMOnlyCommandError extends Error {
5
+ constructor() {
6
+ super();
7
+ }
8
+ }
9
+ exports.DMOnlyCommandError = DMOnlyCommandError;
@@ -0,0 +1,3 @@
1
+ export declare class GuildOnlyCommandError extends Error {
2
+ constructor();
3
+ }
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.GuildOnlyCommandError = void 0;
4
+ class GuildOnlyCommandError extends Error {
5
+ constructor() {
6
+ super();
7
+ }
8
+ }
9
+ exports.GuildOnlyCommandError = GuildOnlyCommandError;
@@ -0,0 +1,3 @@
1
+ export declare class OwnerOnlyCommandError extends Error {
2
+ constructor();
3
+ }
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.OwnerOnlyCommandError = void 0;
4
+ class OwnerOnlyCommandError extends Error {
5
+ constructor() {
6
+ super();
7
+ }
8
+ }
9
+ exports.OwnerOnlyCommandError = OwnerOnlyCommandError;
@@ -0,0 +1,3 @@
1
+ export * from './OwnerOnlyCommand';
2
+ export * from './GuildOnlyCommand';
3
+ export * from './DMOnlyCommand';
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
5
+ }) : (function(o, m, k, k2) {
6
+ if (k2 === undefined) k2 = k;
7
+ o[k2] = m[k];
8
+ }));
9
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
10
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
11
+ };
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ __exportStar(require("./OwnerOnlyCommand"), exports);
14
+ __exportStar(require("./GuildOnlyCommand"), exports);
15
+ __exportStar(require("./DMOnlyCommand"), exports);
@@ -4,3 +4,4 @@ export * from './ArgumentNotProvided';
4
4
  export * from './ArgumentConverterNotFound';
5
5
  export * from './CommandCheckFailed';
6
6
  export * from './PermissionRequired';
7
+ export * from './checks';
@@ -16,3 +16,4 @@ __exportStar(require("./ArgumentNotProvided"), exports);
16
16
  __exportStar(require("./ArgumentConverterNotFound"), exports);
17
17
  __exportStar(require("./CommandCheckFailed"), exports);
18
18
  __exportStar(require("./PermissionRequired"), exports);
19
+ __exportStar(require("./checks"), exports);
@@ -1,9 +1,10 @@
1
1
  import { Registry } from './Registry';
2
- import { Client, Snowflake } from 'discord.js';
2
+ import { Client, Message, Snowflake } from 'discord.js';
3
3
  import { CoolDownAdapter } from '../command';
4
4
  import { REST } from '@discordjs/rest';
5
5
  export interface CommandOptions {
6
6
  prefix: string | ((msg: any) => string | Promise<string | string[]> | string[]) | string[];
7
+ check: (msg: Message) => boolean | Promise<boolean>;
7
8
  }
8
9
  export interface SlashCommandOptions {
9
10
  guild?: Snowflake | Snowflake[];
@@ -44,6 +44,7 @@ class CommandClient {
44
44
  this.options = lodash_1.default.merge({
45
45
  command: {
46
46
  prefix: '!',
47
+ check: () => true
47
48
  },
48
49
  owners: 'auto',
49
50
  slashCommands: {
@@ -102,7 +102,7 @@ class Registry {
102
102
  m = require(p);
103
103
  }
104
104
  catch (e) {
105
- throw new error_1.ModuleLoadError(p);
105
+ throw new error_1.ModuleLoadError(p, e);
106
106
  }
107
107
  if (m.loaded)
108
108
  throw new Error('MODULE_ALREADY_LOADED');
@@ -120,12 +120,19 @@ class Registry {
120
120
  }
121
121
  syncCommands() {
122
122
  return __awaiter(this, void 0, void 0, function* () {
123
+ console.log(`[Command.TS] Syncing commands...`);
123
124
  const commands = this.slashCommands.filter((x) => !x.guild);
124
125
  const guild = this.client.options.slashCommands.guild;
125
126
  if (guild) {
126
127
  const syncForGuild = (g) => __awaiter(this, void 0, void 0, function* () {
128
+ console.log(`Syncing for guild ${g.name}(${g.id})`);
129
+ const commandsToRegister = [
130
+ ...commands.map((x) => x.commandBuilder),
131
+ ...this.slashCommands.filter((y) => { var _a; return y.guild === g.id || ((_a = y.guild) === null || _a === void 0 ? void 0 : _a.includes(g.id)) || false; }).map((x) => x.commandBuilder),
132
+ ];
133
+ console.log(`Command List: ${commandsToRegister.map((x) => x.name).join(', ')}`);
127
134
  yield this.client.rest.put(v9_1.Routes.applicationGuildCommands(this.client.client.application.id, g.id), {
128
- body: commands.map((x) => x.commandBuilder.toJSON()),
135
+ body: commandsToRegister.map((x) => x.toJSON()),
129
136
  });
130
137
  });
131
138
  if (typeof guild === 'string') {
@@ -138,10 +145,12 @@ class Registry {
138
145
  }
139
146
  }
140
147
  else {
148
+ console.log('Syncing global...');
141
149
  yield this.client.rest.put(v9_1.Routes.applicationCommands(this.client.client.application.id), {
142
150
  body: commands.map((x) => x.commandBuilder.toJSON()),
143
151
  });
144
152
  }
153
+ console.log('Syncing ended.');
145
154
  });
146
155
  }
147
156
  unregisterModule(module) {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@pikokr/command.ts",
3
3
  "description": "Discord.js command framework for typescript.",
4
- "version": "3.0.6",
4
+ "version": "3.0.8-dev.3955b1f",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
7
  "license": "MIT",
@@ -31,4 +31,4 @@
31
31
  "docs:dev": "typedoc",
32
32
  "docs:build": "typedoc"
33
33
  }
34
- }
34
+ }
@@ -1,6 +1,6 @@
1
1
  import { BuiltInModule } from './BuiltInModule'
2
2
  import { argumentConverter } from '../command'
3
- import { Client, GuildMember, Message, User } from 'discord.js'
3
+ import { Client, GuildMember, Message, User, Role } from 'discord.js'
4
4
  import { CommandClient } from '../structures'
5
5
 
6
6
  export class BuiltinCommandConverters extends BuiltInModule {
@@ -34,17 +34,25 @@ export class BuiltinCommandConverters extends BuiltInModule {
34
34
 
35
35
  @argumentConverter(User)
36
36
  user(msg: Message, value: string): User | null {
37
+ let user = this.client.users.cache.get(value)
38
+ if (user) return user
39
+ user = this.client.users.cache.find(x=>x.tag === value)
40
+ if (user) return user
37
41
  const id = this.getUserIDByMention(value)
38
42
  if (!id) return null
39
- const user = this.client.users.cache.get(id)
43
+ user = this.client.users.cache.get(id)
40
44
  return user || null
41
45
  }
42
46
 
43
47
  @argumentConverter(GuildMember)
44
48
  member(msg: Message, value: string): GuildMember | undefined {
49
+ let user = msg.guild?.members.cache.get(value)
50
+ if (!user) return user
51
+ user = msg.guild?.members.cache.find(x=>x.user.tag===value)
52
+ if (user) return user
45
53
  const id = this.getUserIDByMention(value)
46
54
  if (!id) return
47
- const user = msg.guild?.members.cache.get(id)
55
+ user = msg.guild?.members.cache.get(id)
48
56
  return user || undefined
49
57
  }
50
58
 
@@ -53,4 +61,24 @@ export class BuiltinCommandConverters extends BuiltInModule {
53
61
  const n = Number(value)
54
62
  return isNaN(n) ? undefined : n
55
63
  }
64
+
65
+ getRoleIDByMention(mention: string): `${bigint}` | undefined {
66
+ if (!mention) return
67
+ if (mention.startsWith('<@') && mention.endsWith('>')) {
68
+ mention = mention.slice(2, -1)
69
+ if (mention.startsWith('&')) {
70
+ mention = mention.slice(1)
71
+ }
72
+ return mention as `${bigint}`
73
+ }
74
+ }
75
+
76
+ @argumentConverter(Role)
77
+ role(msg: Message, value: string): Role | undefined{
78
+ const id = this.getRoleIDByMention(value)
79
+ if (!id) return
80
+ const role = msg.guild?.roles.cache.get(id)
81
+ return role || undefined
82
+ }
83
+
56
84
  }
@@ -1,6 +1,6 @@
1
1
  import { BuiltInModule } from './BuiltInModule'
2
2
  import { slashArgumentConverter } from '../command'
3
- import { Client, CommandInteraction } from 'discord.js'
3
+ import { Client, CommandInteraction, CommandInteractionOptionResolver } from 'discord.js'
4
4
  import { CommandClient } from '../structures'
5
5
 
6
6
  export class BuiltinSlashCommandConverters extends BuiltInModule {
@@ -15,4 +15,9 @@ export class BuiltinSlashCommandConverters extends BuiltInModule {
15
15
  message(interaction: CommandInteraction) {
16
16
  return interaction
17
17
  }
18
+
19
+ @slashArgumentConverter(CommandInteractionOptionResolver)
20
+ optionResolver(interaction: CommandInteraction): CommandInteractionOptionResolver {
21
+ return interaction.options
22
+ }
18
23
  }
@@ -17,6 +17,10 @@ export class CommandHandler extends BuiltInModule {
17
17
 
18
18
  @listener('messageCreate')
19
19
  async message(msg: Message) {
20
+ if (!await this.client.options.command.check(msg)) {
21
+ return
22
+ }
23
+
20
24
  const error = (error: Error) => this.client.client.emit('commandError', error, msg)
21
25
 
22
26
  try {
@@ -5,7 +5,7 @@ import { ArgumentConverter, SlashArgumentConverter } from './ArgumentConverter'
5
5
  import { Module } from '../structures'
6
6
  import { createCheckDecorator } from './utils'
7
7
  import { GuildMember, Message, PermissionResolvable, Permissions, TextChannel } from 'discord.js'
8
- import { ClientPermissionRequired, UserPermissionRequired } from '../error'
8
+ import { ClientPermissionRequired, DMOnlyCommandError, GuildOnlyCommandError, OwnerOnlyCommandError, UserPermissionRequired } from '../error'
9
9
 
10
10
  type CommandOptions = {
11
11
  name: string
@@ -111,18 +111,36 @@ export const rest: ParameterDecorator = (target, propertyKey, parameterIndex) =>
111
111
  }
112
112
 
113
113
  export const ownerOnly = createCheckDecorator(
114
- (msg) => msg.data.cts.owners.includes(msg.author.id),
115
- (i) => i.data.cts.owners.includes(i.user.id),
114
+ (msg) => {
115
+ if (msg.data.cts.owners.includes(msg.author.id)) return true
116
+ throw new OwnerOnlyCommandError()
117
+ },
118
+ (i) => {
119
+ if (i.data.cts.owners.includes(i.user.id)) return true
120
+ throw new OwnerOnlyCommandError()
121
+ },
116
122
  )
117
123
 
118
124
  export const guildOnly = createCheckDecorator(
119
- (msg) => !!msg.guild,
120
- (i) => !!i.guildId,
125
+ (msg) => {
126
+ if (!!msg.guild) return true
127
+ throw new GuildOnlyCommandError()
128
+ },
129
+ (i) => {
130
+ if (!!i.guildId) return true
131
+ throw new GuildOnlyCommandError()
132
+ },
121
133
  )
122
134
 
123
135
  export const dmOnly = createCheckDecorator(
124
- (msg) => !msg.guild,
125
- (i) => !i.guildId,
136
+ (msg) => {
137
+ if (!msg.guild) return true
138
+ throw new DMOnlyCommandError()
139
+ },
140
+ (i) => {
141
+ if (!i.guildId) return true
142
+ throw new DMOnlyCommandError()
143
+ },
126
144
  )
127
145
 
128
146
  export const requireUserPermissions = (permission: PermissionResolvable) =>
@@ -1,5 +1,5 @@
1
1
  export class ModuleLoadError extends Error {
2
- constructor(file: string) {
2
+ constructor(file: string, public error: Error) {
3
3
  super('Failed to load module ' + file)
4
4
  }
5
5
  }
@@ -0,0 +1,5 @@
1
+ export class DMOnlyCommandError extends Error {
2
+ constructor() {
3
+ super()
4
+ }
5
+ }
@@ -0,0 +1,5 @@
1
+ export class GuildOnlyCommandError extends Error {
2
+ constructor() {
3
+ super()
4
+ }
5
+ }
@@ -0,0 +1,5 @@
1
+ export class OwnerOnlyCommandError extends Error {
2
+ constructor() {
3
+ super()
4
+ }
5
+ }
@@ -0,0 +1,3 @@
1
+ export * from './OwnerOnlyCommand'
2
+ export * from './GuildOnlyCommand'
3
+ export * from './DMOnlyCommand'
@@ -4,3 +4,4 @@ export * from './ArgumentNotProvided'
4
4
  export * from './ArgumentConverterNotFound'
5
5
  export * from './CommandCheckFailed'
6
6
  export * from './PermissionRequired'
7
+ export * from './checks'
@@ -1,12 +1,13 @@
1
1
  import _ from 'lodash'
2
2
  import { Registry } from './Registry'
3
- import { Client, Snowflake, User } from 'discord.js'
3
+ import {Client, Message, Snowflake, User} from 'discord.js'
4
4
  import { BuiltinCommandConverters, BuiltinSlashCommandConverters, CommandHandler } from '../builtinModules'
5
5
  import { CoolDownAdapter, DefaultCoolDownAdapter } from '../command'
6
6
  import { REST } from '@discordjs/rest'
7
7
 
8
8
  export interface CommandOptions {
9
9
  prefix: string | ((msg: any) => string | Promise<string | string[]> | string[]) | string[]
10
+ check: (msg: Message) => boolean|Promise<boolean>
10
11
  }
11
12
 
12
13
  export interface SlashCommandOptions {
@@ -64,6 +65,7 @@ export class CommandClient {
64
65
  {
65
66
  command: {
66
67
  prefix: '!',
68
+ check: () => true
67
69
  },
68
70
  owners: 'auto',
69
71
  slashCommands: {
@@ -95,7 +95,7 @@ export class Registry {
95
95
  try {
96
96
  m = require(p)
97
97
  } catch (e: any) {
98
- throw new ModuleLoadError(p)
98
+ throw new ModuleLoadError(p, e)
99
99
  }
100
100
 
101
101
  if (m.loaded) throw new Error('MODULE_ALREADY_LOADED')
@@ -118,12 +118,19 @@ export class Registry {
118
118
  }
119
119
 
120
120
  async syncCommands() {
121
+ console.log(`[Command.TS] Syncing commands...`)
121
122
  const commands = this.slashCommands.filter((x) => !x.guild)
122
123
  const guild = this.client.options.slashCommands.guild
123
124
  if (guild) {
124
125
  const syncForGuild = async (g: Guild) => {
126
+ console.log(`Syncing for guild ${g.name}(${g.id})`)
127
+ const commandsToRegister = [
128
+ ...commands.map((x) => x.commandBuilder),
129
+ ...this.slashCommands.filter((y) => y.guild === g.id || y.guild?.includes(g.id) || false).map((x) => x.commandBuilder),
130
+ ]
131
+ console.log(`Command List: ${commandsToRegister.map((x) => x.name).join(', ')}`)
125
132
  await this.client.rest.put(Routes.applicationGuildCommands(this.client.client.application!.id, g.id) as any, {
126
- body: commands.map((x) => x.commandBuilder.toJSON()),
133
+ body: commandsToRegister.map((x) => x.toJSON()),
127
134
  })
128
135
  }
129
136
 
@@ -135,10 +142,12 @@ export class Registry {
135
142
  }
136
143
  }
137
144
  } else {
145
+ console.log('Syncing global...')
138
146
  await this.client.rest.put(Routes.applicationCommands(this.client.client.application!.id) as any, {
139
147
  body: commands.map((x) => x.commandBuilder.toJSON()),
140
148
  })
141
149
  }
150
+ console.log('Syncing ended.')
142
151
  }
143
152
 
144
153
  async unregisterModule(module: Module) {