import { Message , Collection , Guild } from 'discord.js' ; import * as fs from 'fs' ; import { Bot } from '.' ; import { CommandCache , UserWrapper } from './database/schemas' ; import { permLevels } from './utils/permissions' ; import { permToString , durationToString } from './utils/parsers' ; export interface export interface commandInterface { type { string } memberof name : string ; type { string } memberof path : string ; type { boolean } memberof dm : boolean ; type { ( 0 | 1 | 2 | 3 | 4 ) } memberof permLevel : 0 | 1 | 2 | 3 | 4 ; type { boolean } memberof togglable : boolean ; type { number } memberof cooldownLocal ? : number ; type { number } memberof cooldownGlobal ? : number ; memberof help : { type { string } shortDescription : string ; type { string } longDescription : string ; type { string [ ] } usages : string [ ] ; type { string [ ] } examples : string [ ] ; /**
         * Array of additional fields that should be added in the help embed.
         *
         */ additionalFields ? : { name : string ; value : string ; inline ? : boolean ; } [ ] ; } ; param { Message } message param { string } args param { number } permLevel param { boolean } dm param { [ number , number ] } requestTime param { CommandCache } commandCache returns memberof run ( message , args , permLevel , dm , requestTime , commandCache ? ) : Promise < boolean > ; } export class export class Commands { type { Collection < string , commandInterface > } memberof commands : Collection < string , commandInterface > ; type { * } memberof structure : any ; param { string } dir memberof constructor ( dir ) { this . commands = new Collection ( ) ; this . structure = { } ; this . loadCommands ( dir , this . structure ) ; } param { string } dir param { * } structureObject memberof loadCommands ( dir , structureObject ) { fs . readdir ( dir , ( err , files ) => { if ( err ) console . error ( err ) ; var folders = files . filter ( f => fs . lstatSync ( dir + f ) . isDirectory ( ) ) ; folders . forEach ( ( f , i ) => { structureObject [ f . toLowerCase ( ) ] = { _categoryName : f } ; this . loadCommands ( dir + f + '/' , structureObject [ f . toLowerCase ( ) ] ) ; } ) ; var commands = files . filter ( f => f . split ( '.' ) . pop ( ) == 'js' ) ; if ( commands . length <= 0 ) { console . error ( 'no commands to load in ' + dir ) ; return ; } console . info ( `loading ${ commands . length } commands in ${ dir }` ) ; commands . forEach ( ( f , i ) => { var props = require ( dir + f ) . default ; console . info ( `${ i + 1 }: ${ f } loaded!` ) ; this . commands . set ( props . name , props ) ; var strucObject = structureObject ; if ( props . path != '' ) { var keys = props . path . toLowerCase ( ) . split ( '/' ) ; strucObject = this . structure ; for ( var i = 0 ; i < keys . length ; i ++ ) { if ( ! strucObject [ keys [ i ] ] ) { strucObject [ keys [ i ] ] = { _categoryName : keys [ i ] } ; } strucObject = strucObject [ keys [ i ] ] ; } } strucObject [ props . name ] = props ; } ) ; } ) ; } param { Message } message param { string } args param { string } command param { number } permLevel param { boolean } dm param { [ number , number ] } requestTime returns memberof async runCommand ( message , args , command , permLevel , dm , requestTime ) { var cmd = this . commands . get ( command ) ; if ( ! cmd ) return ; if ( ! cmd . dm && dm ) { message . channel . send ( await this . getHelpEmbed ( cmd ) ) ; return ; } if ( permLevel < cmd . permLevel ) return ; let user ; if ( cmd . cooldownGlobal || cmd . cooldownLocal ) { user = await Bot . database . getUser ( message . author ) ; if ( user ) { if ( cmd . cooldownLocal && Date . now ( ) < user . getCooldown ( ( dm ? 'dm' : message . guild . id ) , command ) ) return ; if ( cmd . cooldownGlobal && Date . now ( ) < user . getCooldown ( 'global' , command ) ) return ; } } if ( ! dm && cmd . togglable ) { var commandSettings = await Bot . database . getCommandSettings ( message . guild . id , command ) ; if ( commandSettings && ! commandSettings . _enabled ) return ; } let output = await cmd . run ( message , args , permLevel , dm , requestTime ) ; if ( ( cmd . cooldownGlobal || cmd . cooldownLocal ) && output !== false ) { if ( ! user ) user = new UserWrapper ( undefined , message . author ) ; if ( cmd . cooldownGlobal ) user . setCooldown ( 'global' , command , message . createdTimestamp + cmd . cooldownGlobal , false ) ; if ( cmd . cooldownLocal ) user . setCooldown ( ( dm ? 'dm' : message . guild . id ) , command , Date . now ( ) + cmd . cooldownLocal , false ) ; user . save ( ) ; } } param { Message } message param { CommandCache } commandCache param { permLevels } permLevel param { boolean } dm param { [ number , number ] } requestTime returns memberof async runCachedCommand ( message , commandCache , permLevel , dm , requestTime ) { var cmd = this . commands . get ( commandCache . command ) ; if ( ! cmd ) { commandCache . remove ( ) ; return ; } if ( ! cmd . dm && dm ) { message . channel . send ( 'This command can\'t be used in dms. The action was canceled.' ) ; commandCache . remove ( ) ; return ; } cmd . run ( message , message . content , permLevel , dm , requestTime , commandCache ) ; } param { string } command returns memberof get ( command ) { return this . commands . get ( command ) ; } param { ( string | commandInterface ) } command param { ( string | Guild ) } guild returns memberof async getHelpEmbed ( command , guild ? ) { if ( typeof command === "string" ) command = this . commands . get ( command ) ; if ( ! command ) throw new Error ( "Command was not set or found. Value of command: " + command ) ; if ( guild instanceof Guild ) guild = guild . id ; let prefix = await Bot . database . getPrefix ( undefined , guild ) ; let embed = { color : Bot . database . settingsDB . cache . embedColors . help , author : { name : `Command: ${ prefix }${ command . name }` } , fields : [ { name : 'Description:' , value : command . help . longDescription } , { name : 'Need to be:' , value : permToString ( command . permLevel ) , inline : true } , { name : 'DM capable:' , value : command . dm , inline : true } , { name : 'Togglable:' , value : command . togglable , inline : true } , { name : 'Usage:' , value : command . help . usages . join ( '\n' ) . replace ( /\{command\}/g , prefix + command . name ) } , { name : 'Example:' , value : command . help . examples . join ( '\n' ) . replace ( /\{command\}/g , prefix + command . name ) } ] } ; if ( command . cooldownGlobal ) embed . fields . splice ( 4 , 0 , { name : 'Global Cooldown' , value : durationToString ( command . cooldownGlobal ) , inline : true } ) ; if ( command . cooldownLocal ) embed . fields . splice ( 4 , 0 , { name : 'Local Cooldown' , value : durationToString ( command . cooldownLocal ) , inline : true } ) ; if ( command . help . additionalFields ) for ( const field of command . help . additionalFields . reverse ( ) ) embed . fields . splice ( 1 , 0 , field ) ; return { embed } ; } }