Skip to content

Commit

Permalink
feat: argument types
Browse files Browse the repository at this point in the history
  • Loading branch information
xhyrom committed Feb 9, 2022
1 parent eed6678 commit 3138149
Show file tree
Hide file tree
Showing 12 changed files with 135 additions and 34 deletions.
10 changes: 6 additions & 4 deletions src/handlers/MessageCommandHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@ import { CommandType } from '../lib/structures/Command';
import { Commands } from '../lib/managers/CommandManager';
import { Handlers } from '../lib/managers/HandlerManager';
import Logger from 'js-logger';
import { UserType } from '../lib/structures/arguments/User';
import type { Argument } from '../lib/structures/Argument';
import { Argument, ArgumentType } from '../lib/structures/Argument';
import { MessageArgumentTypeBase, MessageArgumentTypes } from '../lib/structures/arguments/base';
import { Util } from '../lib/util/Util';

const cooldowns = new Collection<string, Collection<string, number>>();

const checkValidation = async(arg: UserType, content: string, client: Client, guild: Guild, argument: Argument, channel: TextChannel, user: User) => {
const checkValidation = async(arg: MessageArgumentTypes, content: string, client: Client, guild: Guild, argument: Argument, channel: TextChannel, user: User) => {
if (!content) {
channel.send(`${user.toString()}, please define argument \`${argument.name}\`, type: ${Util.toPascalCase(ArgumentType[argument.type.toString()])}`);
const message = await channel.awaitMessages({ filter: (m) => m.author.id === user.id && m.channelId === channel.id, time: 60000, max: 1 });

content = [...message.values()]?.[0]?.content;
Expand Down Expand Up @@ -71,7 +73,7 @@ export async function MessageCommandHandler(
args[0].options[0].options = args[0].options.splice(1);*/

for (const argument in command.arguments) {
const arg = new UserType();
const arg = await MessageArgumentTypeBase.createArgument(command.arguments[argument].type);

args[argument] = await checkValidation(arg, args[argument] as string, client, message.guild, command.arguments[argument], message.channel as TextChannel, message.author);
}
Expand Down
17 changes: 5 additions & 12 deletions src/lib/structures/Provider.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import Logger from 'js-logger';
import { EventEmitter } from 'events';
import { Util } from '../util/Util';

Expand All @@ -21,39 +20,33 @@ export declare interface Provider {
delete(...args): Promise<any> | any;
}

const throwError = (error, name) => {
const trace = Util.resolveValidationErrorTrace([name]);

Logger.error(error, trace);
};

export class Provider extends EventEmitter {
init() {
throwError('Init method is not implemented!', this.constructor.name);
Util.throwError('Init method is not implemented!', this.constructor.name);
return;
}

// eslint-disable-next-line @typescript-eslint/no-unused-vars
insert(...args) {
throwError('Insert method is not implemented!', this.constructor.name);
Util.throwError('Insert method is not implemented!', this.constructor.name);
return;
}

// eslint-disable-next-line @typescript-eslint/no-unused-vars
get(...args) {
throwError('Get method is not implemented!', this.constructor.name);
Util.throwError('Get method is not implemented!', this.constructor.name);
return;
}

// eslint-disable-next-line @typescript-eslint/no-unused-vars
update(...args) {
throwError('Update method is not implemented!', this.constructor.name);
Util.throwError('Update method is not implemented!', this.constructor.name);
return;
}

// eslint-disable-next-line @typescript-eslint/no-unused-vars
delete(...args) {
throwError('Delete method is not implemented!', this.constructor.name);
Util.throwError('Delete method is not implemented!', this.constructor.name);
return;
}
}
29 changes: 26 additions & 3 deletions src/lib/structures/arguments/Boolean.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,28 @@
export class BooleanType {
validate() {

import { Argument, ArgumentType } from '../Argument';
import { MessageArgumentTypeBase } from './base';

const truthy = new Set(['true', 't', 'yes', 'y', 'on', 'enable', 'enabled', '1', '+']);
const falsy = new Set(['false', 'f', 'no', 'n', 'off', 'disable', 'disabled', '0', '-']);

export class BooleanType extends MessageArgumentTypeBase {
value;

validate(content: string): boolean {
const yes = truthy.has(content.toLowerCase());
const no = falsy.has(content.toLowerCase());

if (!yes && !no) return false;
else {
this.value = yes ? true : false;
return true;
};
}

resolve(argument: Argument) {
return {
...argument.toJSON(),
type: ArgumentType[argument.type],
value: this.value
}
}
}
6 changes: 4 additions & 2 deletions src/lib/structures/arguments/Channel.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
export class ChannelType {
import { MessageArgumentTypeBase } from './base';

export class ChannelType extends MessageArgumentTypeBase {
validate() {

return true;
}
}
5 changes: 3 additions & 2 deletions src/lib/structures/arguments/Integer.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { Argument, ArgumentType } from '../Argument';
import { MessageArgumentTypeBase } from './base';

export class IntegerType {
export class IntegerType extends MessageArgumentTypeBase {
value;

validate(content: string) {
validate(content: string): boolean {
if (Number.isInteger(Number(content))) {
this.value = content;
return true
Expand Down
6 changes: 4 additions & 2 deletions src/lib/structures/arguments/Mentionable.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
export class MentionableType {
import { MessageArgumentTypeBase } from './base';

export class MentionableType extends MessageArgumentTypeBase {
validate() {

return true;
}
}
5 changes: 3 additions & 2 deletions src/lib/structures/arguments/Number.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { Argument, ArgumentType } from '../Argument';
import { MessageArgumentTypeBase } from './base';

export class NumberType {
export class NumberType extends MessageArgumentTypeBase {
value;

validate(content: string) {
validate(content: string): boolean {
if (!isNaN(Number(content))) {
this.value = content;
return true
Expand Down
6 changes: 4 additions & 2 deletions src/lib/structures/arguments/Role.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
export class RoleType {
import { MessageArgumentTypeBase } from './base';

export class RoleType extends MessageArgumentTypeBase {
validate() {

return true;
}
}
5 changes: 3 additions & 2 deletions src/lib/structures/arguments/String.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { Argument, ArgumentType } from '../Argument';
import { MessageArgumentTypeBase } from './base';

export class StringType {
export class StringType extends MessageArgumentTypeBase {
value;

validate(content: string) {
validate(content: string): boolean {
if (typeof content === 'string') {
this.value = content;
return true
Expand Down
7 changes: 4 additions & 3 deletions src/lib/structures/arguments/User.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import type { Client, Guild } from 'discord.js';
import { Argument, ArgumentType } from '../Argument';
import { MessageArgumentTypeBase } from './base';

export class UserType {
export class UserType extends MessageArgumentTypeBase {
matches;

validate(content: string) {
validate(content: string): boolean {
const matches = content.match(/([0-9]+)/);

if (!matches) return false;
Expand All @@ -19,7 +20,7 @@ export class UserType {
...argument.toJSON(),
type: ArgumentType[argument.type],
user: client.users.cache.get(this.matches[1]),
member: guild.members.cache.get(this.matches[1])
member: guild.members?.cache?.get(this.matches[1])
}
}
}
54 changes: 54 additions & 0 deletions src/lib/structures/arguments/base.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { Util } from '../../util/Util';
import { Argument, ArgumentType } from '../Argument';
import type { BooleanType } from './Boolean';
import type { ChannelType } from './Channel';
import type { IntegerType } from './Integer';
import type { MentionableType } from './Mentionable';
import type { NumberType } from './Number';
import type { RoleType } from './Role';
import type { StringType } from './String';
import type { UserType } from './User';

export type MessageArgumentTypes = BooleanType | ChannelType | IntegerType | MentionableType | NumberType | RoleType | StringType | UserType;

export class MessageArgumentTypeBase {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
validate(content: string): boolean {
Util.throwError('Validate method is not implemented!', this.constructor.name);
return true;
}

// eslint-disable-next-line @typescript-eslint/no-unused-vars
resolve(argument: Argument, ...args) {
Util.throwError('Resolve method is not implemented!', this.constructor.name);
}

static async createArgument(type: ArgumentType | keyof typeof ArgumentType) {
switch(type) {
case ArgumentType.BOOLEAN:
const { BooleanType } = await import('./Boolean');
return new BooleanType();
case ArgumentType.CHANNEL:
const { ChannelType } = await import('./Channel');
return new ChannelType();
case ArgumentType.INTEGER:
const { IntegerType } = await import('./Integer');
return new IntegerType();
case ArgumentType.MENTIONABLE:
const { MentionableType } = await import('./Mentionable');
return new MentionableType();
case ArgumentType.NUMBER:
const { NumberType } = await import('./Number');
return new NumberType();
case ArgumentType.ROLE:
const { RoleType } = await import('./Role');
return new RoleType();
case ArgumentType.STRING:
const { StringType } = await import('./String');
return new StringType();
case ArgumentType.USER:
const { UserType } = await import('./User');
return new UserType();
}
}
}
19 changes: 19 additions & 0 deletions src/lib/util/Util.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import Logger from "js-logger";

export class Util {
/**
* @deprecated We don't support arguments in object/array
Expand Down Expand Up @@ -91,4 +93,21 @@ export class Util {
array = array.filter(item => typeof item === 'string');
return `(${array.join(' -> ') || 'unknown'})`;
}

static throwError(error, name): void {
const trace = Util.resolveValidationErrorTrace([name]);

Logger.error(error, trace);
}

static toPascalCase(input: string): string {
return input
.replace(new RegExp(/[-_]+/, 'g'), ' ')
.replace(new RegExp(/[^\w\s]/, 'g'), '')
.replace(
new RegExp(/\s+(.)(\w*)/, 'g'),
($1, $2, $3) => `${$2.toUpperCase() + $3.toLowerCase()}`
)
.replace(new RegExp(/\w/), s => s.toUpperCase());
}
}

0 comments on commit 3138149

Please sign in to comment.