Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

运行时卸载插件 #52

Closed
arily opened this issue Jul 17, 2020 · 7 comments
Closed

运行时卸载插件 #52

arily opened this issue Jul 17, 2020 · 7 comments
Labels
has solution 已存在解决办法 next 下个大版本实装 question Further information is requested

Comments

@arily
Copy link
Contributor

arily commented Jul 17, 2020

Is your feature request related to a problem? Please describe.

我想在运行时安装卸载一些中间件(使用场景为给每个群安装群特有的中间件,并且可以通过命令禁用)

Describe the solution you'd like

增加一个卸载middleware的api

const middleware = require('my-middleware')
//其实我觉得叫install,use一类会更清楚一些
ctx.plugin(middleware)

ctx.plugin((meta,next) => {
const parsed = meta.$parsed
const tiggered = (
  ['atMe','nickname','prefix'].some(trigger => parsed[trigger]) &&
  parsed.message.startsWith('disable')
)
if (!triggered) return next()
const target = parsed.message.slice(8)
try {
  const middlewareToRemove = require(target)
  //here!
  ctx.remove(middlewareToRemove)
} catch (error) {
  meta.$send('unable to find that.')
}
}

Describe alternatives you've considered

每次增减插件时创建一个新的context安装这些插件,但对插件实现有限制,内部需要无状态,全部通过数据库实现
(我似乎也没找到销毁ctx的方法)
Additional context

@shigma
Copy link
Member

shigma commented Jul 27, 2020

@arily 试试 ctx.removeMiddleware

@arily
Copy link
Contributor Author

arily commented Jul 29, 2020

@shigma 抱歉!!好像我写的有些问题,上面想要被卸载掉的其实是插件

try {
  const pluginToRemove = require(target)
  ctx.remove(pluginToRemove)
}

大概是这样.
通过ctx.removeMiddleware的话应该需要拿到具体的中间件?

@shigma
Copy link
Member

shigma commented Jul 29, 2020

插件在 Koishi 的设计中,本身就不应该在运行时加载,自然也就不存在运行时卸载的概念。

如果你想要手动实现一个运行时卸载的功能,不妨考虑使用监听器:

// 定义一个插件
module.exports = (ctx, options) => {
  ctx.middleware(callback1)
  ctx.receiver.on(event, callback2)

  ctx.on('remove-my-plugin', () => {
    ctx.removeMiddleware(callback1)
    ctx.receiver.off(event, callback2)
  })
}
// 在你想要移除插件的地方
ctx.emit('remove-my-plugin')

@shigma shigma added the question Further information is requested label Jul 29, 2020
@undefined-moe
Copy link
Member

是否支持停用指令 ctx.removeCommand()(?

@shigma
Copy link
Member

shigma commented Jul 30, 2020

@masnn 目前没有这个接口,下个大版本会加上。在此之前可以使用暴力方式移除:

Context.prototype.removeCommand = function (cmd) {
    cmd.shortcuts.forEach(name => delete ctx.app._shortcutMap[name])
    ctx.app._shortcuts = difference(ctx.app._shortcuts, cmd.shortcuts)
    cmd._aliases.forEach(name => delete ctx.app._commandMap[name])
    ctx.app._commands = difference(ctx.app._commands, [cmd])
    if (cmd.parent) cmd.parent.children = difference(cmd.parent.children, [cmd])
}

得写这么多我很惭愧……

@shigma
Copy link
Member

shigma commented Aug 2, 2020

在 next 分支的最新一次更新 bd46fe8 中已经实装了下列方法:

command.dispose() // 移除指令及其子指令
context.dispose() // 移除当前插件中注册的监听器、中间件和指令

@shigma shigma added has solution 已存在解决办法 next 下个大版本实装 labels Aug 2, 2020
@shigma shigma mentioned this issue Aug 2, 2020
65 tasks
@shigma
Copy link
Member

shigma commented Aug 4, 2020

已经实装于 koishi v2 beta 版本。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
has solution 已存在解决办法 next 下个大版本实装 question Further information is requested
Projects
None yet
Development

No branches or pull requests

3 participants