| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384 |
- import { readdirSync, existsSync, readFileSync, watch } from 'fs'
- import { join, resolve } from 'path'
- import { format } from 'util'
- import syntaxerror from 'syntax-error'
- import importFile from './import.js'
- import Helper from './helper.js'
- const __dirname = Helper.__dirname(import.meta)
- const pluginFolder = Helper.__dirname(join(__dirname, '../plugins/index'))
- const pluginFilter = filename => /\.(mc)?js$/.test(filename)
- // inspired from https://github.com/Nurutomo/mahbod/blob/main/src/util/PluginManager.ts
- let watcher, plugins, pluginFolders = []
- watcher = plugins = {}
- async function filesInit(pluginFolder = pluginFolder, pluginFilter = pluginFilter, conn) {
- const folder = resolve(pluginFolder)
- if (folder in watcher) return
- pluginFolders.push(folder)
- await Promise.all(readdirSync(folder).filter(pluginFilter).map(async filename => {
- try {
- let file = global.__filename(join(folder, filename))
- const module = await import(file)
- if (module) plugins[filename] = 'default' in module ? module.default : module
- } catch (e) {
- conn?.logger.error(e)
- delete plugins[filename]
- }
- }))
- const watching = watch(folder, reload.bind(null, conn, folder, pluginFilter))
- watching.on('close', () => deletePluginFolder(folder, true))
- watcher[folder] = watching
- return plugins
- }
- function deletePluginFolder(folder, isAlreadyClosed = false) {
- const resolved = resolve(folder)
- if (!(resolved in watcher)) return
- if (!isAlreadyClosed) watcher[resolved].close()
- delete watcher[resolved]
- pluginFolders.splice(pluginFolders.indexOf(resolved), 1)
- }
- async function reload(conn, pluginFolder = pluginFolder, pluginFilter = pluginFilter, _ev, filename) {
- if (pluginFilter(filename)) {
- let dir = global.__filename(join(pluginFolder, filename), true)
- if (filename in plugins) {
- if (existsSync(dir)) conn.logger.info(` updated plugin - '${filename}'`)
- else {
- conn?.logger.warn(`deleted plugin - '${filename}'`)
- return delete plugins[filename]
- }
- } else conn?.logger.info(`new plugin - '${filename}'`)
- let err = syntaxerror(readFileSync(dir), filename, {
- sourceType: 'module',
- allowAwaitOutsideFunction: true
- })
- if (err) conn.logger.error(`syntax error while loading '${filename}'\n${format(err)}`)
- else try {
- const module = await importFile(global.__filename(dir)).catch(console.error)
- if (module) plugins[filename] = module
- } catch (e) {
- conn?.logger.error(`error require plugin '${filename}\n${format(e)}'`)
- } finally {
- plugins = Object.fromEntries(Object.entries(plugins).sort(([a], [b]) => a.localeCompare(b)))
- }
- }
- }
- export {
- pluginFolder,
- pluginFilter,
- plugins,
- watcher,
- pluginFolders,
- filesInit,
- deletePluginFolder,
- reload
- }
|