feat: split plugin ext stage exec
Signed-off-by: MiaoWoo <admin@yumc.pw>
This commit is contained in:
		@@ -152,21 +152,21 @@ export namespace plugin {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
    export interface PluginMetadata extends BaseMetadata {
 | 
					    export interface PluginMetadata extends BaseMetadata {
 | 
				
			||||||
        /**
 | 
					        /**
 | 
				
			||||||
         * 插件名称
 | 
					         * 插件名称 不填默认为类名
 | 
				
			||||||
         */
 | 
					         */
 | 
				
			||||||
        name: string
 | 
					        name?: string
 | 
				
			||||||
        /**
 | 
					        /**
 | 
				
			||||||
         * 前缀
 | 
					         * 前缀
 | 
				
			||||||
         */
 | 
					         */
 | 
				
			||||||
        prefix?: string
 | 
					        prefix?: string
 | 
				
			||||||
        /**
 | 
					        /**
 | 
				
			||||||
         * 插件版本
 | 
					         * 插件版本 不填默认为 1.0.0
 | 
				
			||||||
         */
 | 
					         */
 | 
				
			||||||
        version: string
 | 
					        version?: string
 | 
				
			||||||
        /**
 | 
					        /**
 | 
				
			||||||
         * 插件版本
 | 
					         * 插件作者 不填默认为 Unknow
 | 
				
			||||||
         */
 | 
					         */
 | 
				
			||||||
        author: string | string[]
 | 
					        author?: string | string[]
 | 
				
			||||||
        /**
 | 
					        /**
 | 
				
			||||||
         * 插件源文件 必须指定为 __filename
 | 
					         * 插件源文件 必须指定为 __filename
 | 
				
			||||||
         */
 | 
					         */
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										36
									
								
								packages/plugin/src/command.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								packages/plugin/src/command.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,36 @@
 | 
				
			|||||||
 | 
					import { command, plugin, server } from '@ccms/api'
 | 
				
			||||||
 | 
					import { provideSingleton, postConstruct, inject } from '@ccms/container'
 | 
				
			||||||
 | 
					import { getPluginCommandMetadata, getPluginTabCompleterMetadata } from './utils'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@provideSingleton(PluginCommandManager)
 | 
				
			||||||
 | 
					export class PluginCommandManager {
 | 
				
			||||||
 | 
					    @inject(server.ServerChecker)
 | 
				
			||||||
 | 
					    private ServerChecker: server.ServerChecker
 | 
				
			||||||
 | 
					    @inject(command.Command)
 | 
				
			||||||
 | 
					    private CommandManager: command.Command
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    constructor() {
 | 
				
			||||||
 | 
					        process.on('plugin.before.enable', (plugin: plugin.Plugin) => this.registryCommand(plugin))
 | 
				
			||||||
 | 
					        process.on('plugin.after.disable', (plugin: plugin.Plugin) => this.unregistryCommand(plugin))
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private registryCommand(pluginInstance: plugin.Plugin) {
 | 
				
			||||||
 | 
					        let cmds = getPluginCommandMetadata(pluginInstance)
 | 
				
			||||||
 | 
					        let tabs = getPluginTabCompleterMetadata(pluginInstance)
 | 
				
			||||||
 | 
					        for (const [_, cmd] of cmds) {
 | 
				
			||||||
 | 
					            let tab = tabs.get(cmd.name)
 | 
				
			||||||
 | 
					            if (!this.ServerChecker.check(cmd.servers)) { continue }
 | 
				
			||||||
 | 
					            this.CommandManager.on(pluginInstance, cmd.name, {
 | 
				
			||||||
 | 
					                cmd: pluginInstance[cmd.executor].bind(pluginInstance),
 | 
				
			||||||
 | 
					                tab: tab ? pluginInstance[tab.executor].bind(pluginInstance) : undefined
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private unregistryCommand(pluginInstance: plugin.Plugin) {
 | 
				
			||||||
 | 
					        let cmds = getPluginCommandMetadata(pluginInstance)
 | 
				
			||||||
 | 
					        cmds.forEach(cmd => {
 | 
				
			||||||
 | 
					            this.CommandManager.off(pluginInstance, cmd.name)
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -1,33 +1,75 @@
 | 
				
			|||||||
import * as yaml from 'js-yaml'
 | 
					import * as yaml from 'js-yaml'
 | 
				
			||||||
 | 
					import * as fs from '@ccms/common/dist/fs'
 | 
				
			||||||
 | 
					import { plugin } from '@ccms/api'
 | 
				
			||||||
 | 
					import { getPluginConfigMetadata } from './utils'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export interface PluginConfigLoader {
 | 
					export interface PluginConfigLoader {
 | 
				
			||||||
    load(content: string): any;
 | 
					    load(content: string): any
 | 
				
			||||||
    dump(variable: any): string;
 | 
					    dump(variable: any): string
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export class YamlPluginConfig implements PluginConfigLoader {
 | 
					export class YamlPluginConfig implements PluginConfigLoader {
 | 
				
			||||||
    load(content: string) {
 | 
					    load(content: string) {
 | 
				
			||||||
        return yaml.safeLoad(content);
 | 
					        return yaml.safeLoad(content)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    dump(variable: any): string {
 | 
					    dump(variable: any): string {
 | 
				
			||||||
        return yaml.safeDump(variable, { skipInvalid: true });
 | 
					        return yaml.safeDump(variable, { skipInvalid: true })
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export class JsonPluginConfig implements PluginConfigLoader {
 | 
					export class JsonPluginConfig implements PluginConfigLoader {
 | 
				
			||||||
    load(content: string) {
 | 
					    load(content: string) {
 | 
				
			||||||
        return JSON.parse(content);
 | 
					        return JSON.parse(content)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    dump(variable: any): string {
 | 
					    dump(variable: any): string {
 | 
				
			||||||
        return JSON.stringify(variable);
 | 
					        return JSON.stringify(variable)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const configLoaderMap = new Map<string, PluginConfigLoader>();
 | 
					const configLoaderMap = new Map<string, PluginConfigLoader>()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export function getConfigLoader(format: string) {
 | 
					export function getConfigLoader(format: string) {
 | 
				
			||||||
    if (!configLoaderMap.has(format)) { throw new Error(`Unsupport config format ${format} !`) }
 | 
					    if (!configLoaderMap.has(format)) { throw new Error(`Unsupport config format ${format} !`) }
 | 
				
			||||||
    return configLoaderMap.get(format);
 | 
					    return configLoaderMap.get(format)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function loadConfig(plugin: plugin.Plugin) {
 | 
				
			||||||
 | 
					    let configs = getPluginConfigMetadata(plugin)
 | 
				
			||||||
 | 
					    for (let [_, config] of configs) {
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            let configFile = fs.concat(fs.file(plugin.description.loadMetadata.file).parent, plugin.description.name, config.name + '.' + config.format)
 | 
				
			||||||
 | 
					            let configFactory = getConfigLoader(config.format)
 | 
				
			||||||
 | 
					            if (!fs.exists(configFile)) {
 | 
				
			||||||
 | 
					                base.save(configFile, configFactory.dump(plugin[config.variable]))
 | 
				
			||||||
 | 
					                console.i18n("ms.plugin.manager.config.save.default", { plugin: plugin.description.name, name: config.name, format: config.format })
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                plugin[config.variable] = configFactory.load(base.read(configFile))
 | 
				
			||||||
 | 
					                plugin[config.variable].save = () => {
 | 
				
			||||||
 | 
					                    let result = configFactory.dump(plugin[config.variable])
 | 
				
			||||||
 | 
					                    base.save(configFile, result)
 | 
				
			||||||
 | 
					                    console.debug(`[${plugin.description.name}] Save Config ${config.variable} to file ${configFile} result ${result}`)
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                console.debug(`[${plugin.description.name}] Load Config ${config.variable} from file ${configFile} result ${JSON.stringify(plugin[config.variable])}`)
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        } catch (error) {
 | 
				
			||||||
 | 
					            console.i18n("ms.plugin.manager.config.load.error", { plugin: plugin.description.name, name: config.name, format: config.format, error })
 | 
				
			||||||
 | 
					            console.ex(error)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function saveConfig(plugin: plugin.Plugin) {
 | 
				
			||||||
 | 
					    let configs = getPluginConfigMetadata(plugin)
 | 
				
			||||||
 | 
					    for (let [_, config] of configs) {
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            let configFile = fs.concat(fs.file(plugin.description.loadMetadata.file).parent, plugin.description.name, config.name + '.' + config.format)
 | 
				
			||||||
 | 
					            let configFactory = getConfigLoader(config.format)
 | 
				
			||||||
 | 
					            if (!config.readonly) { base.save(configFile, configFactory.dump(plugin[config.variable])) }
 | 
				
			||||||
 | 
					        } catch (error) {
 | 
				
			||||||
 | 
					            console.i18n("ms.plugin.manager.config.save.error", { plugin: plugin.description.name, name: config.name, format: config.format, error })
 | 
				
			||||||
 | 
					            console.ex(error)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function init() {
 | 
					function init() {
 | 
				
			||||||
@@ -35,6 +77,8 @@ function init() {
 | 
				
			|||||||
    let yaml = new YamlPluginConfig()
 | 
					    let yaml = new YamlPluginConfig()
 | 
				
			||||||
    configLoaderMap.set("yml", yaml)
 | 
					    configLoaderMap.set("yml", yaml)
 | 
				
			||||||
    configLoaderMap.set("yaml", yaml)
 | 
					    configLoaderMap.set("yaml", yaml)
 | 
				
			||||||
 | 
					    process.on('plugin.before.load', loadConfig)
 | 
				
			||||||
 | 
					    process.on('plugin.after.load', saveConfig)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
init()
 | 
					init()
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,10 +8,10 @@ import { getPluginMetadatas, getPluginCommandMetadata, getPluginListenerMetadata
 | 
				
			|||||||
 * MiaoScript plugin
 | 
					 * MiaoScript plugin
 | 
				
			||||||
 * @param metadata PluginMetadata
 | 
					 * @param metadata PluginMetadata
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
export function plugin(metadata: pluginApi.PluginMetadata) {
 | 
					export function plugin(metadata: pluginApi.PluginMetadata | any) {
 | 
				
			||||||
    return function (target: any) {
 | 
					    return function (target: any) {
 | 
				
			||||||
        metadata.target = target
 | 
					        if (!metadata.source) metadata = { souece: metadata }
 | 
				
			||||||
        metadata.type = "ioc"
 | 
					        metadata = { name: target.name, version: '1.0.0', author: 'Unknow', target, type: 'ioc', ...metadata }
 | 
				
			||||||
        decorate(injectable(), target)
 | 
					        decorate(injectable(), target)
 | 
				
			||||||
        Reflect.defineMetadata(METADATA_KEY.plugin, metadata, target)
 | 
					        Reflect.defineMetadata(METADATA_KEY.plugin, metadata, target)
 | 
				
			||||||
        const previousMetadata: Map<string, pluginApi.PluginMetadata> = getPluginMetadatas()
 | 
					        const previousMetadata: Map<string, pluginApi.PluginMetadata> = getPluginMetadatas()
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										30
									
								
								packages/plugin/src/event.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								packages/plugin/src/event.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,30 @@
 | 
				
			|||||||
 | 
					import { event, plugin, server } from '@ccms/api'
 | 
				
			||||||
 | 
					import { provideSingleton, postConstruct, inject } from '@ccms/container'
 | 
				
			||||||
 | 
					import { getPluginListenerMetadata } from './utils'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@provideSingleton(PluginEventManager)
 | 
				
			||||||
 | 
					export class PluginEventManager {
 | 
				
			||||||
 | 
					    @inject(server.ServerChecker)
 | 
				
			||||||
 | 
					    private ServerChecker: server.ServerChecker
 | 
				
			||||||
 | 
					    @inject(event.Event)
 | 
				
			||||||
 | 
					    private EventManager: event.Event
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    constructor() {
 | 
				
			||||||
 | 
					        process.on('plugin.before.enable', (plugin: plugin.Plugin) => this.registryListener(plugin))
 | 
				
			||||||
 | 
					        process.on('plugin.after.disable', (plugin: plugin.Plugin) => this.unregistryListener(plugin))
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private registryListener(pluginInstance: plugin.Plugin) {
 | 
				
			||||||
 | 
					        let events = getPluginListenerMetadata(pluginInstance)
 | 
				
			||||||
 | 
					        for (const event of events) {
 | 
				
			||||||
 | 
					            // ignore space listener
 | 
				
			||||||
 | 
					            if (!this.ServerChecker.check(event.servers)) { continue }
 | 
				
			||||||
 | 
					            // here must bind this to pluginInstance
 | 
				
			||||||
 | 
					            this.EventManager.listen(pluginInstance, event.name, pluginInstance[event.executor].bind(pluginInstance))
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private unregistryListener(pluginInstance: plugin.Plugin) {
 | 
				
			||||||
 | 
					        this.EventManager.disable(pluginInstance)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -1,11 +1,11 @@
 | 
				
			|||||||
import i18n from '@ccms/i18n'
 | 
					import i18n from '@ccms/i18n'
 | 
				
			||||||
import { plugin, server, command, event } from '@ccms/api'
 | 
					import { plugin, server, event } from '@ccms/api'
 | 
				
			||||||
import { inject, provideSingleton, Container, ContainerInstance } from '@ccms/container'
 | 
					import { inject, provideSingleton, Container, ContainerInstance } from '@ccms/container'
 | 
				
			||||||
import * as fs from '@ccms/common/dist/fs'
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import './config'
 | 
				
			||||||
import { interfaces } from './interfaces'
 | 
					import { interfaces } from './interfaces'
 | 
				
			||||||
import { getConfigLoader } from './config'
 | 
					import { PluginCommandManager } from './command'
 | 
				
			||||||
import { getPluginCommandMetadata, getPluginListenerMetadata, getPluginTabCompleterMetadata, getPluginConfigMetadata } from './utils'
 | 
					import { PluginEventManager } from './event'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const Thread = Java.type('java.lang.Thread')
 | 
					const Thread = Java.type('java.lang.Thread')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -15,15 +15,16 @@ export class PluginManagerImpl implements plugin.PluginManager {
 | 
				
			|||||||
    private container: Container
 | 
					    private container: Container
 | 
				
			||||||
    @inject(plugin.PluginInstance)
 | 
					    @inject(plugin.PluginInstance)
 | 
				
			||||||
    private pluginInstance: any
 | 
					    private pluginInstance: any
 | 
				
			||||||
    @inject(plugin.PluginFolder)
 | 
					 | 
				
			||||||
    private pluginFolder: string
 | 
					 | 
				
			||||||
    @inject(server.ServerType)
 | 
					    @inject(server.ServerType)
 | 
				
			||||||
    private serverType: string
 | 
					    private serverType: string
 | 
				
			||||||
    @inject(command.Command)
 | 
					 | 
				
			||||||
    private CommandManager: command.Command
 | 
					 | 
				
			||||||
    @inject(event.Event)
 | 
					    @inject(event.Event)
 | 
				
			||||||
    private EventManager: event.Event
 | 
					    private EventManager: event.Event
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @inject(PluginCommandManager)
 | 
				
			||||||
 | 
					    private commandManager: PluginCommandManager
 | 
				
			||||||
 | 
					    @inject(PluginEventManager)
 | 
				
			||||||
 | 
					    private eventManager: PluginEventManager
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private initialized: boolean = false
 | 
					    private initialized: boolean = false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private sacnnerMap: Map<string, plugin.PluginScanner>
 | 
					    private sacnnerMap: Map<string, plugin.PluginScanner>
 | 
				
			||||||
@@ -38,6 +39,10 @@ export class PluginManagerImpl implements plugin.PluginManager {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        this.instanceMap = new Map()
 | 
					        this.instanceMap = new Map()
 | 
				
			||||||
        this.metadataMap = new Map()
 | 
					        this.metadataMap = new Map()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // ignore unused
 | 
				
			||||||
 | 
					        this.commandManager
 | 
				
			||||||
 | 
					        this.eventManager
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    initialize() {
 | 
					    initialize() {
 | 
				
			||||||
@@ -90,14 +95,15 @@ export class PluginManagerImpl implements plugin.PluginManager {
 | 
				
			|||||||
        console.i18n("ms.plugin.manager.stage", { stage, plugin: plugin.description.name, version: plugin.description.version, author: plugin.description.author })
 | 
					        console.i18n("ms.plugin.manager.stage", { stage, plugin: plugin.description.name, version: plugin.description.version, author: plugin.description.author })
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private runPluginStage(plugin: plugin.Plugin, stage: string, ext: Function) {
 | 
					    private runPluginStage(plugin: plugin.Plugin, stage: string) {
 | 
				
			||||||
        if (!plugin) { throw new Error(`can't run runPluginStage ${stage} because plugin is ${plugin}`) }
 | 
					        if (!plugin) { throw new Error(`can't run runPluginStage ${stage} because plugin is ${plugin}`) }
 | 
				
			||||||
        try {
 | 
					        try {
 | 
				
			||||||
            this.logStage(plugin, i18n.translate(`ms.plugin.manager.stage.${stage}`))
 | 
					            this.logStage(plugin, i18n.translate(`ms.plugin.manager.stage.${stage}`))
 | 
				
			||||||
            ext()
 | 
					            process.emit(`plugin.before.${stage}`, plugin)
 | 
				
			||||||
            this.runCatch(plugin, stage)
 | 
					            this.runCatch(plugin, stage)
 | 
				
			||||||
            this.runCatch(plugin, `${this.serverType}${stage}`)
 | 
					            this.runCatch(plugin, `${this.serverType}${stage}`)
 | 
				
			||||||
            plugin.description.loadMetadata.loader[stage](plugin)
 | 
					            plugin.description.loadMetadata.loader[stage](plugin)
 | 
				
			||||||
 | 
					            process.emit(`plugin.after.${stage}`, plugin)
 | 
				
			||||||
        } catch (ex) {
 | 
					        } catch (ex) {
 | 
				
			||||||
            console.i18n("ms.plugin.manager.stage.exec.error", { plugin: plugin.description.name, executor: stage, error: ex })
 | 
					            console.i18n("ms.plugin.manager.stage.exec.error", { plugin: plugin.description.name, executor: stage, error: ex })
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -108,14 +114,24 @@ export class PluginManagerImpl implements plugin.PluginManager {
 | 
				
			|||||||
        if (loadMetadata.loaded) { throw new Error(`Plugin ${loadMetadata.name} is already loaded by ${loadMetadata.loader?.type}!`) }
 | 
					        if (loadMetadata.loaded) { throw new Error(`Plugin ${loadMetadata.name} is already loaded by ${loadMetadata.loader?.type}!`) }
 | 
				
			||||||
        try {
 | 
					        try {
 | 
				
			||||||
            for (const [, loader] of this.loaderMap) {
 | 
					            for (const [, loader] of this.loaderMap) {
 | 
				
			||||||
 | 
					                if (this.loaderRequirePlugin(loadMetadata, loader)?.loaded) return loadMetadata.metadata
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        } catch (error) {
 | 
				
			||||||
 | 
					            console.i18n("ms.plugin.manager.initialize.error", { name: loadMetadata.file, ex: error })
 | 
				
			||||||
 | 
					            console.ex(error)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        console.console(`§6scanner: §b${loadMetadata.scanner.type} §ccan\'t load §6file §b${loadMetadata.file}. §eskip!`)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private loaderRequirePlugin(loadMetadata: plugin.PluginLoadMetadata, loader: plugin.PluginLoader) {
 | 
				
			||||||
        try {
 | 
					        try {
 | 
				
			||||||
            if (loader.require(loadMetadata).loaded) {
 | 
					            if (loader.require(loadMetadata).loaded) {
 | 
				
			||||||
                loadMetadata.loader = loader
 | 
					                loadMetadata.loader = loader
 | 
				
			||||||
                let metadata = loadMetadata.metadata
 | 
					                let metadata = loadMetadata.metadata
 | 
				
			||||||
                this.metadataMap.set(metadata.name, metadata)
 | 
					                this.metadataMap.set(metadata.name, metadata)
 | 
				
			||||||
                metadata.loadMetadata = loadMetadata
 | 
					                metadata.loadMetadata = loadMetadata
 | 
				
			||||||
                        return metadata
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					            return loadMetadata
 | 
				
			||||||
        } catch (error) {
 | 
					        } catch (error) {
 | 
				
			||||||
            if (global.debug) {
 | 
					            if (global.debug) {
 | 
				
			||||||
                console.console(`§6Loader §b${loader.type} §6load §a${loadMetadata.file} §cerror. §4Err: §c${error}`)
 | 
					                console.console(`§6Loader §b${loader.type} §6load §a${loadMetadata.file} §cerror. §4Err: §c${error}`)
 | 
				
			||||||
@@ -125,12 +141,6 @@ export class PluginManagerImpl implements plugin.PluginManager {
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
        } catch (error) {
 | 
					 | 
				
			||||||
            console.i18n("ms.plugin.manager.initialize.error", { name: loadMetadata.file, ex: error })
 | 
					 | 
				
			||||||
            console.ex(error)
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        console.console(`§6scanner: §b${loadMetadata.scanner.type} §ccan\'t load §6file §b${loadMetadata.file}. §eskip!`)
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * 从文件加载插件
 | 
					     * 从文件加载插件
 | 
				
			||||||
@@ -147,36 +157,21 @@ export class PluginManagerImpl implements plugin.PluginManager {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    load(...args: any[]): void {
 | 
					    load(...args: any[]): void {
 | 
				
			||||||
        this.checkAndGet(args[0]).forEach((plugin: plugin.Plugin) => {
 | 
					        this.checkAndGet(args[0]).forEach((plugin: plugin.Plugin) => this.runPluginStage(plugin, 'load'))
 | 
				
			||||||
            this.runPluginStage(plugin, 'load', () => {
 | 
					 | 
				
			||||||
                this.loadConfig(plugin)
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
        })
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    enable(...args: any[]): void {
 | 
					    enable(...args: any[]): void {
 | 
				
			||||||
        this.checkAndGet(args[0]).forEach((plugin: plugin.Plugin) => {
 | 
					        this.checkAndGet(args[0]).forEach((plugin: plugin.Plugin) => this.runPluginStage(plugin, 'enable'))
 | 
				
			||||||
            this.runPluginStage(plugin, 'enable', () => {
 | 
					 | 
				
			||||||
                this.registryCommand(plugin)
 | 
					 | 
				
			||||||
                this.registryListener(plugin)
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
        })
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    disable(...args: any[]): void {
 | 
					    disable(...args: any[]): void {
 | 
				
			||||||
        this.checkAndGet(args[0]).forEach((plugin: plugin.Plugin) => {
 | 
					        this.checkAndGet(args[0]).forEach((plugin: plugin.Plugin) => this.runPluginStage(plugin, 'disable'))
 | 
				
			||||||
            this.runPluginStage(plugin, 'disable', () => {
 | 
					 | 
				
			||||||
                this.saveConfig(plugin)
 | 
					 | 
				
			||||||
                this.unregistryCommand(plugin)
 | 
					 | 
				
			||||||
                this.unregistryListener(plugin)
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
        })
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    reload(...args: any[]): void {
 | 
					    reload(...args: any[]): void {
 | 
				
			||||||
        this.checkAndGet(args[0]).forEach((pl: plugin.Plugin) => {
 | 
					        this.checkAndGet(args[0]).forEach((pl: plugin.Plugin) => {
 | 
				
			||||||
            this.disable(pl)
 | 
					            this.disable(pl)
 | 
				
			||||||
            this.loadFromFile(pl.description.source.toString(), pl.description.loadMetadata.scanner)
 | 
					            this.loadFromFile(pl.description.loadMetadata.file, pl.description.loadMetadata.scanner)
 | 
				
			||||||
        })
 | 
					        })
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -206,19 +201,6 @@ export class PluginManagerImpl implements plugin.PluginManager {
 | 
				
			|||||||
        throw new Error(`Plugin ${JSON.stringify(name)} not exist!`)
 | 
					        throw new Error(`Plugin ${JSON.stringify(name)} not exist!`)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private allowProcess(servers: string[]) {
 | 
					 | 
				
			||||||
        // Not set servers -> allow
 | 
					 | 
				
			||||||
        if (!servers || !servers.length) return true
 | 
					 | 
				
			||||||
        // include !type -> deny
 | 
					 | 
				
			||||||
        let denyServers = servers.filter(svr => svr.startsWith("!"))
 | 
					 | 
				
			||||||
        if (denyServers.length !== 0) {
 | 
					 | 
				
			||||||
            return !denyServers.includes(`!${this.serverType}`)
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            // only include -> allow
 | 
					 | 
				
			||||||
            return servers.includes(this.serverType)
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private buildPlugins() {
 | 
					    private buildPlugins() {
 | 
				
			||||||
        for (const [, metadata] of this.metadataMap) {
 | 
					        for (const [, metadata] of this.metadataMap) {
 | 
				
			||||||
            let pluginInstance: plugin.Plugin
 | 
					            let pluginInstance: plugin.Plugin
 | 
				
			||||||
@@ -231,77 +213,4 @@ export class PluginManagerImpl implements plugin.PluginManager {
 | 
				
			|||||||
            this.instanceMap.set(metadata.name, pluginInstance)
 | 
					            this.instanceMap.set(metadata.name, pluginInstance)
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					 | 
				
			||||||
    private loadConfig(plugin: plugin.Plugin) {
 | 
					 | 
				
			||||||
        let configs = getPluginConfigMetadata(plugin)
 | 
					 | 
				
			||||||
        for (let [_, config] of configs) {
 | 
					 | 
				
			||||||
            try {
 | 
					 | 
				
			||||||
                let configFile = fs.concat(root, this.pluginFolder, plugin.description.name, config.name + '.' + config.format)
 | 
					 | 
				
			||||||
                let configFactory = getConfigLoader(config.format)
 | 
					 | 
				
			||||||
                if (!fs.exists(configFile)) {
 | 
					 | 
				
			||||||
                    base.save(configFile, configFactory.dump(plugin[config.variable]))
 | 
					 | 
				
			||||||
                    console.i18n("ms.plugin.manager.config.save.default", { plugin: plugin.description.name, name: config.name, format: config.format })
 | 
					 | 
				
			||||||
                } else {
 | 
					 | 
				
			||||||
                    plugin[config.variable] = configFactory.load(base.read(configFile))
 | 
					 | 
				
			||||||
                    plugin[config.variable].save = () => {
 | 
					 | 
				
			||||||
                        let result = configFactory.dump(plugin[config.variable])
 | 
					 | 
				
			||||||
                        base.save(configFile, result)
 | 
					 | 
				
			||||||
                        console.debug(`[${plugin.description.name}] Save Config ${config.variable} to file ${configFile} result ${result}`)
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                    console.debug(`[${plugin.description.name}] Load Config ${config.variable} from file ${configFile} result ${JSON.stringify(plugin[config.variable])}`)
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            } catch (error) {
 | 
					 | 
				
			||||||
                console.i18n("ms.plugin.manager.config.load.error", { plugin: plugin.description.name, name: config.name, format: config.format, error })
 | 
					 | 
				
			||||||
                console.ex(error)
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private saveConfig(plugin: plugin.Plugin) {
 | 
					 | 
				
			||||||
        let configs = getPluginConfigMetadata(plugin)
 | 
					 | 
				
			||||||
        for (let [_, config] of configs) {
 | 
					 | 
				
			||||||
            try {
 | 
					 | 
				
			||||||
                let configFile = fs.concat(root, this.pluginFolder, plugin.description.name, config.name + '.' + config.format)
 | 
					 | 
				
			||||||
                let configFactory = getConfigLoader(config.format)
 | 
					 | 
				
			||||||
                if (!config.readonly) { base.save(configFile, configFactory.dump(plugin[config.variable])) }
 | 
					 | 
				
			||||||
            } catch (error) {
 | 
					 | 
				
			||||||
                console.i18n("ms.plugin.manager.config.save.error", { plugin: plugin.description.name, name: config.name, format: config.format, error })
 | 
					 | 
				
			||||||
                console.ex(error)
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private registryCommand(pluginInstance: plugin.Plugin) {
 | 
					 | 
				
			||||||
        let cmds = getPluginCommandMetadata(pluginInstance)
 | 
					 | 
				
			||||||
        let tabs = getPluginTabCompleterMetadata(pluginInstance)
 | 
					 | 
				
			||||||
        for (const [_, cmd] of cmds) {
 | 
					 | 
				
			||||||
            let tab = tabs.get(cmd.name)
 | 
					 | 
				
			||||||
            if (!this.allowProcess(cmd.servers)) { continue }
 | 
					 | 
				
			||||||
            this.CommandManager.on(pluginInstance, cmd.name, {
 | 
					 | 
				
			||||||
                cmd: pluginInstance[cmd.executor].bind(pluginInstance),
 | 
					 | 
				
			||||||
                tab: tab ? pluginInstance[tab.executor].bind(pluginInstance) : undefined
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private registryListener(pluginInstance: plugin.Plugin) {
 | 
					 | 
				
			||||||
        let events = getPluginListenerMetadata(pluginInstance)
 | 
					 | 
				
			||||||
        for (const event of events) {
 | 
					 | 
				
			||||||
            // ignore space listener
 | 
					 | 
				
			||||||
            if (!this.allowProcess(event.servers)) { continue }
 | 
					 | 
				
			||||||
            // here must bind this to pluginInstance
 | 
					 | 
				
			||||||
            this.EventManager.listen(pluginInstance, event.name, pluginInstance[event.executor].bind(pluginInstance))
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private unregistryCommand(pluginInstance: plugin.Plugin) {
 | 
					 | 
				
			||||||
        let cmds = getPluginCommandMetadata(pluginInstance)
 | 
					 | 
				
			||||||
        cmds.forEach(cmd => {
 | 
					 | 
				
			||||||
            this.CommandManager.off(pluginInstance, cmd.name)
 | 
					 | 
				
			||||||
        })
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private unregistryListener(pluginInstance: plugin.Plugin) {
 | 
					 | 
				
			||||||
        this.EventManager.disable(pluginInstance)
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user