Skip to content
This repository has been archived by the owner on Jan 6, 2022. It is now read-only.

Commit

Permalink
feat(*): add cooldowns && owners && fix a small bug
Browse files Browse the repository at this point in the history
  • Loading branch information
alexthemaster committed Jul 22, 2020
1 parent 46c240c commit c9106c4
Show file tree
Hide file tree
Showing 8 changed files with 65 additions and 6 deletions.
5 changes: 5 additions & 0 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
Expand Up @@ -48,6 +48,7 @@
},
"dependencies": {
"fs-extra": "^9.0.1",
"klaw": "^3.0.0"
"klaw": "^3.0.0",
"moment": "^2.27.0"
}
}
2 changes: 1 addition & 1 deletion src/commands/Ping.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { Message } from 'discord.js';
/** @ignore */
export default class extends Command {
constructor(client: MoonlightClient, pool: BasePool<string, Command>) {
super(client, pool);
super(client, pool, { cooldown: 5 });
}

public async run(message: Message) {
Expand Down
30 changes: 29 additions & 1 deletion src/events/Message.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { MoonlightClient } from '../lib/Client';
import { Message } from 'discord.js';
import { BasePool } from '../lib/structures/Pools/Base/BasePool';
import { Command } from '../lib/structures/Command';
import moment from 'moment';

export default class extends Event {
constructor(client: MoonlightClient, pool: BasePool<string, Event>) {
Expand Down Expand Up @@ -33,9 +34,36 @@ export default class extends Event {
const command = args.shift()?.toLowerCase();
if (!command) return;

const cmd: Command | null = this.client.commands.get(command) || this.client.commands.get((this.client.aliases.get(command) as string)) || null;
const cmd: Command | null = this.client.commands.get(command.toLowerCase()) || this.client.commands.get((this.client.aliases.get(command.toLowerCase()) as string)) || null;
if (!cmd) return;

if (!this.client.owners.some(owner => owner === message.author.id) && this.client.cooldowns.has(cmd)) {

// Shout-out to this amazing Stack Overflow answer for this solution https://stackoverflow.com/a/53829705
const cooldownEnd = moment(this.client.cooldowns.get(cmd));
const now = moment();
moment.relativeTimeThreshold('ss', 60);
moment.updateLocale('en', {
relativeTime: {
s: function (number) {
return number + ' seconds';
}
}
});

const duration = moment.duration(cooldownEnd.diff(now)).humanize();

return message.channel.send(`You have already used this command recently. Please try again ${duration}.`);
};

const cooldownEnd = moment(new Date()).add(cmd.cooldown, 'seconds').toDate();

this.client.cooldowns.set(cmd, cooldownEnd);

setTimeout(() => {
this.client.cooldowns.delete(cmd);
}, cmd.cooldown * 1000);

if (cmd.disabled) return message.channel.send(`This command was globally disabled by the bot owner.`);

if (!cmd.canRunInDM && message.channel.type === 'dm') return;
Expand Down
14 changes: 13 additions & 1 deletion src/events/OnceReady.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Event } from '../lib/structures/Event';
import { BasePool } from '../lib/structures/Pools/Base/BasePool';
import { MoonlightClient } from '../lib/Client';
import { Team } from 'discord.js';

export default class extends Event {
constructor(client: MoonlightClient, pool: BasePool<string, Event>) {
Expand All @@ -11,11 +12,22 @@ export default class extends Event {
})
}

public run() {
public async run() {
if (this.client.options.readyMessage && typeof this.client.options.readyMessage == 'function') {
console.log(this.client.options.readyMessage(this.client))
}

const applicationDetails = await this.client.fetchApplication();

if ((applicationDetails.owner as Team).members) {
this.client.owners.push(...(applicationDetails.owner as Team).members.map(member => member.user.id));
} else {
this.client.owners.push(applicationDetails.owner!.id);
};

// This will remove the duplicates
this.client.owners = [...new Set(this.client.owners)];

this.client.prefixes.push(`${this.client.user!.username}, `, `<@!${this.client.user!.id}>`);

this.client.pools.forEach(pool => pool.init());
Expand Down
9 changes: 9 additions & 0 deletions src/lib/Client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,11 @@ export class MoonlightClient extends Client {
/** The monitor pool that stores all monitors */
public readonly monitors: MonitorPool<string, Monitor> = new MonitorPool(this);

/** The Map that stores command cooldowns */
public cooldowns: Map<Command, Date> = new Map();

public owners: string[] = new Array();

// Additional options
/** An array containing all the prefixes */
public readonly prefixes: string[] = new Array();
Expand All @@ -63,6 +68,8 @@ export class MoonlightClient extends Client {
if (options?.displayErrors || !options?.displayErrors) {
this.on('error', error => console.error(`[Error] ${error}`));
}

if (options?.owners) this.owners.push(...options.owners);
}


Expand Down Expand Up @@ -110,6 +117,8 @@ export interface MoonlightClientOptions extends ClientOptions {
prefix?: string | string[];
/** Whether or not to display error messages send as the error event */
displayErrors?: boolean;
/** An array that contains the ID's of the owners */
owners?: string[];
/**
* Set the ready message to display when the bot is ready -> should return a string
* @example readyMessage: (client) => `Logged in and serving in ${client.guilds.size}!`
Expand Down
6 changes: 5 additions & 1 deletion src/lib/structures/Command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ export class Command extends BasePiece<Command> {
public readonly nsfw: boolean;
/** Whether or not this command can be called by a user when DM-ing the bot */
public readonly canRunInDM: boolean;
/** The amount of time in seconds of the command's cooldown */
public readonly cooldown: number;

public run(_message: Message, ..._arg: any[]): void {
throw new Error(`Run function not defined in ${__filename}`);
Expand All @@ -24,7 +26,7 @@ export class Command extends BasePiece<Command> {
this.aliases = options?.aliases ?? new Array();
this.nsfw = options?.nsfw ?? false;
this.canRunInDM = options?.canRunInDM ?? true;

this.cooldown = options?.cooldown ?? 0;
}
}

Expand All @@ -35,4 +37,6 @@ interface CommandOptions extends BasePieceOptions {
nsfw?: boolean;
/** Whether or not this command can be called by a user when DM-ing the bot */
canRunInDM?: boolean;
/** The amount of time in seconds of a command's cooldown */
cooldown: number;
}
2 changes: 1 addition & 1 deletion src/lib/structures/Pools/Base/BasePool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ export class BasePool<K, V> extends Map<K, V> {
if ((init instanceof (this.type as Function)) == false) throw `The file at ${filePath} doesn't appear to be an instance of ${(this.type as Function).name}`;

// If the user provided a name in the options then use that, otherwise use the name of the file
const name = init.name?.toLowerCase() || path.parse(filePath).name;
const name = init.name?.toLowerCase() || path.parse(filePath).name.toLowerCase();


// If the class is an instance of Command and there are aliases present then set them
Expand Down

0 comments on commit c9106c4

Please sign in to comment.