import { ClusterClient , Command , CommandClient , ShardClient } from 'detritus-client' ; import { DIRECTORY } from '../../../../config.json' ; import { NotSoCommandClient } from '../../../commandclient' ; import { CommandTypes } from '../../../constants' ; import { NotSoInteractionClient } from '../../../interactioncommandclient' ; import { Listener } from '../../../listeners' ; import { Store } from '../../../stores' ; import { editOrReply } from '../../../utils' ; import { BaseCommand } from '../basecommand' ; async function refreshCommands ( cluster , refreshListeners , refreshStores , LIB_PATH ) { const LISTENERS_PATH = '/listeners/' ; const STORE_PATH = '/stores/' ; const IGNORE = [ '/bot.' , '/redis.' ] ; for ( let key in require . cache ) { if ( ! key . includes ( LIB_PATH ) ) { continue ; } if ( IGNORE . some ( ( file ) => key . includes ( file ) ) ) { continue ; } if ( key . includes ( LISTENERS_PATH ) || key . includes ( STORE_PATH ) ) { if ( key . includes ( LISTENERS_PATH ) ) { if ( ! refreshListeners ) { continue ; } } else if ( key . includes ( STORE_PATH ) ) { if ( ! refreshStores ) { continue ; } } const oldModule = require ( key ) ; if ( oldModule . default ) { const { default : oldObject } = oldModule ; oldObject . stop ( cluster ) ; delete require . cache [ key ] ; const newModule = require ( key ) ; const { default : newObject } = newModule ; const oldCache = require . cache [ key ] ; if ( oldCache ) { oldCache . exports = oldModule ; } for ( let key of Object . getOwnPropertyNames ( newObject . constructor . prototype ) ) { if ( key !== 'constructor' && typeof ( newObject [ key ] ) === 'function' ) { oldObject [ key ] = newObject . constructor . prototype [ key ] . bind ( oldObject ) ; } } oldObject . connect ( cluster ) ; } } else { delete require . cache [ key ] ; } } if ( cluster . commandClient ) { const commandClient = cluster . commandClient as NotSoCommandClient ; await commandClient . resetCommands ( ) ; } if ( cluster . interactionCommandClient ) { const interactionCommandClient = cluster . interactionCommandClient as NotSoInteractionClient ; try { await interactionCommandClient . resetCommands ( ) ; } catch ( error ) { console . log ( 'a' . repeat ( 100 ) , error ) ; console . log ( 'a' . repeat ( 100 ) , await error . response . text ( ) ) ; } } return cluster . shards . map ( ( shard ) => shard . shardId ) ; } export interface CommandArgs { listeners : boolean ; stores : boolean ; } export const COMMAND_NAME = 'refresh' ; export default class RefreshCommand extends BaseCommand { constructor ( client ) { super ( client , { name : COMMAND_NAME , aliases : [ 'reload' ] , args : [ { name : 'listeners' , type : Boolean } , { name : 'stores' , type : Boolean } , ] , metadata : { description : 'Reload the bot\'s commands.' , examples : [ COMMAND_NAME , `${ COMMAND_NAME } -stores` , `${ COMMAND_NAME } -listeners` , ] , type : CommandTypes . OWNER , usage : '(-listeners) (-stores)' , } , responseOptional : true , } ) ; } onBefore ( context ) { return context . user . isClientOwner ; } async run ( context , args ) { if ( ! context . manager ) { return editOrReply ( context , 'no cluster manager found' ) ; } const message = await editOrReply ( context , 'ok, refreshing...' ) ; const shardIds = await context . manager . broadcastEval ( refreshCommands , args . listeners , args . stores , DIRECTORY ) ; const error = shardIds . find ( ( shardId ) => shardId instanceof Error ) ; if ( error ) { if ( error . errors ) { return message . edit ( `${ error . message } (${ JSON . stringify ( error . errors ) })` ) ; } return message . edit ( `Error: ${ error . message }` ) ; } return message . edit ( `ok, refreshed commands on ${ shardIds . flat ( ) . length } shards.` ) ; } }