// Package control 控制插件的启用与优先级等 package control import ( "os" "strconv" "sync" "github.com/sirupsen/logrus" zero "github.com/wdvxdr1123/ZeroBot" "github.com/wdvxdr1123/ZeroBot/extension" "github.com/wdvxdr1123/ZeroBot/message" "github.com/FloatTech/ZeroBot-Plugin/data" ) var ( db = &data.Sqlite{DBPath: "data/control/plugins.db"} // managers 每个插件对应的管理 managers = map[string]*Control{} mu = sync.RWMutex{} hasinit bool ) // Control is to control the plugins. type Control struct { sync.RWMutex service string options Options } // newctrl returns Manager with settings. func newctrl(service string, o *Options) *Control { m := &Control{service: service, options: func() Options { if o == nil { return Options{} } return *o }(), } mu.Lock() defer mu.Unlock() managers[service] = m err := db.Create(service, &grpcfg{}) if err != nil { panic(err) } return m } // enable enables a group to pass the Manager. func (m *Control) enable(groupID int64) { m.Lock() err := db.Insert(m.service, &grpcfg{groupID, 0}) if err != nil { logrus.Errorf("[control] %v", err) } m.Unlock() } // disable disables a group to pass the Manager. func (m *Control) disable(groupID int64) { m.Lock() err := db.Insert(m.service, &grpcfg{groupID, 1}) if err != nil { logrus.Errorf("[control] %v", err) } m.Unlock() } func (m *Control) isEnabledIn(gid int64) bool { m.RLock() var c grpcfg err := db.Find(m.service, &c, "WHERE gid = "+strconv.FormatInt(gid, 10)) if err == nil { m.RUnlock() logrus.Debugf("[control] plugin %s of grp %d : %d", m.service, c.GroupID, c.Disable) return c.Disable == 0 } logrus.Errorf("[control] %v", err) m.RUnlock() if m.options.DisableOnDefault { m.disable(gid) } else { m.enable(gid) } return !m.options.DisableOnDefault } // Handler 返回 预处理器 func (m *Control) Handler() zero.Rule { return func(ctx *zero.Ctx) bool { ctx.State["manager"] = m return m.isEnabledIn(ctx.Event.GroupID) } } // lookup returns a Manager by the service name, if // not exist, it will returns nil. func lookup(service string) (*Control, bool) { mu.RLock() defer mu.RUnlock() m, ok := managers[service] return m, ok } // forEach iterates through managers. func forEach(iterator func(key string, manager *Control) bool) { mu.RLock() m := copyMap(managers) mu.RUnlock() for k, v := range m { if !iterator(k, v) { return } } } func copyMap(m map[string]*Control) map[string]*Control { ret := make(map[string]*Control, len(m)) for k, v := range m { ret[k] = v } return ret } func init() { if !hasinit { mu.Lock() if !hasinit { err := os.MkdirAll("data/control", 0755) if err != nil { panic(err) } else { hasinit = true zero.OnCommandGroup([]string{"启用", "enable"}, zero.AdminPermission, zero.OnlyGroup). Handle(func(ctx *zero.Ctx) { model := extension.CommandModel{} _ = ctx.Parse(&model) service, ok := lookup(model.Args) if !ok { ctx.Send("没有找到指定服务!") } service.enable(ctx.Event.GroupID) ctx.Send(message.Text("已启用服务: " + model.Args)) }) zero.OnCommandGroup([]string{"禁用", "disable"}, zero.AdminPermission, zero.OnlyGroup). Handle(func(ctx *zero.Ctx) { model := extension.CommandModel{} _ = ctx.Parse(&model) service, ok := lookup(model.Args) if !ok { ctx.Send("没有找到指定服务!") } service.disable(ctx.Event.GroupID) ctx.Send(message.Text("已关闭服务: " + model.Args)) }) zero.OnCommandGroup([]string{"用法", "usage"}, zero.AdminPermission, zero.OnlyGroup). Handle(func(ctx *zero.Ctx) { model := extension.CommandModel{} _ = ctx.Parse(&model) service, ok := lookup(model.Args) if !ok { ctx.Send("没有找到指定服务!") } if service.options.Help != "" { ctx.Send(service.options.Help) } else { ctx.Send("该服务无帮助!") } }) zero.OnCommandGroup([]string{"服务列表", "service_list"}, zero.AdminPermission, zero.OnlyGroup). Handle(func(ctx *zero.Ctx) { msg := `---服务列表---` i := 0 forEach(func(key string, manager *Control) bool { i++ msg += "\n" + strconv.Itoa(i) + `: ` if manager.isEnabledIn(ctx.Event.GroupID) { msg += "●" + key } else { msg += "○" + key } return true }) ctx.Send(message.Text(msg)) }) } } mu.Unlock() } }