114 lines
3.1 KiB
TypeScript
114 lines
3.1 KiB
TypeScript
import * as readline from 'readline'
|
|
import * as fs from 'fs'
|
|
import * as path from 'path'
|
|
import { Server } from 'socket.io'
|
|
import { commandLogger } from '../utilities/logger'
|
|
import config from '../utilities/config'
|
|
|
|
class CommandManager {
|
|
private commands: Map<string, any> = new Map()
|
|
private rl: readline.Interface
|
|
private io: Server | null = null
|
|
private rlClosed: boolean = false
|
|
|
|
constructor() {
|
|
this.rl = readline.createInterface({
|
|
input: process.stdin,
|
|
output: process.stdout
|
|
})
|
|
|
|
this.rl.on('close', () => {
|
|
this.rlClosed = true
|
|
})
|
|
}
|
|
|
|
public async boot(io: Server) {
|
|
this.io = io
|
|
await this.loadCommands()
|
|
commandLogger.info('Command manager loaded')
|
|
this.startPrompt()
|
|
}
|
|
|
|
private startPrompt() {
|
|
if (this.rlClosed) return
|
|
|
|
this.rl.question('> ', (command: string) => {
|
|
this.processCommand(command)
|
|
this.startPrompt()
|
|
})
|
|
}
|
|
|
|
private async processCommand(command: string): Promise<void> {
|
|
const [cmd, ...args] = command.trim().split(' ')
|
|
if (this.commands.has(cmd)) {
|
|
const CommandClass = this.commands.get(cmd)
|
|
const commandInstance = new CommandClass(this.io as Server)
|
|
await commandInstance.execute(args)
|
|
} else {
|
|
this.handleUnknownCommand(cmd)
|
|
}
|
|
}
|
|
|
|
private handleUnknownCommand(command: string) {
|
|
switch (command) {
|
|
case 'exit':
|
|
this.rl.close()
|
|
break
|
|
default:
|
|
console.error(`Unknown command: ${command}`)
|
|
break
|
|
}
|
|
}
|
|
|
|
private async loadCommands() {
|
|
const commandsDir = path.join(process.cwd(), 'src', 'commands')
|
|
try {
|
|
const files: string[] = await fs.promises.readdir(commandsDir)
|
|
|
|
for (const file of files) {
|
|
try {
|
|
const extension = path.extname(file)
|
|
const commandName = path.basename(file, extension)
|
|
|
|
let commandPath: string
|
|
commandPath = path.join(commandsDir, `${commandName}.js`)
|
|
|
|
if (config.ENV === 'development') {
|
|
commandPath = path.join(commandsDir, `${commandName}.ts`)
|
|
}
|
|
|
|
if (!fs.existsSync(commandPath)) {
|
|
commandLogger.warn(`Command file not found: ${commandPath}`)
|
|
continue
|
|
}
|
|
|
|
// Use dynamic import
|
|
const CommandModule = await import(commandPath)
|
|
const CommandClass = CommandModule.default
|
|
|
|
if (!CommandClass || typeof CommandClass !== 'function') {
|
|
commandLogger.warn(`Invalid command class in file: ${commandPath}`)
|
|
continue
|
|
}
|
|
|
|
this.registerCommand(commandName, CommandClass)
|
|
} catch (error) {
|
|
commandLogger.error(`Failed to load command: ${file}: ${error}`)
|
|
}
|
|
}
|
|
} catch (error) {
|
|
commandLogger.error(`Failed to read commands directory: ${error}`)
|
|
}
|
|
}
|
|
|
|
private registerCommand(name: string, CommandClass: any) {
|
|
if (this.commands.has(name)) {
|
|
commandLogger.warn(`Command '${name}' is already registered. Overwriting...`)
|
|
}
|
|
this.commands.set(name, CommandClass)
|
|
commandLogger.info(`Registered command: ${name}`)
|
|
}
|
|
}
|
|
|
|
export default new CommandManager()
|