145 lines
3.4 KiB
Go
145 lines
3.4 KiB
Go
/* Copyright Azareal 2016 - 2017 */
|
|
package main
|
|
import "log"
|
|
|
|
var plugins map[string]*Plugin = make(map[string]*Plugin)
|
|
var hooks map[string][]func(interface{})interface{} = make(map[string][]func(interface{})interface{})
|
|
var vhooks map[string]func(...interface{})interface{} = make(map[string]func(...interface{})interface{})
|
|
|
|
func LoadPlugins() error {
|
|
rows, err := get_plugins_stmt.Query()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer rows.Close()
|
|
|
|
var uname string
|
|
var active bool
|
|
for rows.Next() {
|
|
err = rows.Scan(&uname, &active)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// Was the plugin deleted at some point?
|
|
plugin, ok := plugins[uname]
|
|
if !ok {
|
|
continue
|
|
}
|
|
plugin.Active = active
|
|
plugins[uname] = plugin
|
|
}
|
|
err = rows.Err()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
type Plugin struct
|
|
{
|
|
UName string
|
|
Name string
|
|
Author string
|
|
URL string
|
|
Settings string
|
|
Active bool
|
|
Tag string
|
|
Type string
|
|
Init func()
|
|
Activate func()error
|
|
Deactivate func()
|
|
|
|
Hooks map[string]int
|
|
}
|
|
|
|
func NewPlugin(uname string, name string, author string, url string, settings string, tag string, ptype string, init func(), activate func()error, deactivate func()) *Plugin {
|
|
return &Plugin{
|
|
UName: uname,
|
|
Name: name,
|
|
Author: author,
|
|
URL: url,
|
|
Settings: settings,
|
|
Tag: tag,
|
|
Type: ptype,
|
|
Init: init,
|
|
Activate: activate,
|
|
Deactivate: deactivate,
|
|
|
|
/*
|
|
The Active field should never be altered by a plugin. It's used internally by the software to determine whether an admin has enabled a plugin or not and whether to run it. This will be overwritten by the user's preference.
|
|
*/
|
|
Active: false,
|
|
Hooks: make(map[string]int),
|
|
}
|
|
}
|
|
|
|
func (plugin *Plugin) AddHook(name string, handler interface{}) {
|
|
switch h := handler.(type) {
|
|
case func(interface{})interface{}:
|
|
if len(hooks[name]) == 0 {
|
|
var hookSlice []func(interface{})interface{}
|
|
hookSlice = append(hookSlice, h)
|
|
hooks[name] = hookSlice
|
|
} else {
|
|
hooks[name] = append(hooks[name], h)
|
|
}
|
|
plugin.Hooks[name] = len(hooks[name])
|
|
case func(...interface{}) interface{}:
|
|
vhooks[name] = h
|
|
plugin.Hooks[name] = 0
|
|
default:
|
|
panic("I don't recognise this kind of handler!") // Should this be an error for the plugin instead of a panic()?
|
|
}
|
|
}
|
|
|
|
func (plugin *Plugin) RemoveHook(name string, handler interface{}) {
|
|
switch handler.(type) {
|
|
case func(interface{})interface{}:
|
|
key := plugin.Hooks[name]
|
|
hook := hooks[name]
|
|
if len(hook) == 1 {
|
|
hook = []func(interface{})interface{}{}
|
|
} else {
|
|
hook = append(hook[:key], hook[key + 1:]...)
|
|
}
|
|
hooks[name] = hook
|
|
case func(...interface{}) interface{}:
|
|
delete(vhooks, name)
|
|
default:
|
|
panic("I don't recognise this kind of handler!") // Should this be an error for the plugin instead of a panic()?
|
|
}
|
|
delete(plugin.Hooks, name)
|
|
}
|
|
|
|
var plugins_inited bool = false
|
|
func init_plugins() {
|
|
for name, body := range plugins {
|
|
log.Print("Added plugin " + name)
|
|
if body.Active {
|
|
log.Print("Initialised plugin " + name)
|
|
if plugins[name].Init != nil {
|
|
plugins[name].Init()
|
|
} else {
|
|
log.Print("Plugin " + name + " doesn't have an initialiser.")
|
|
}
|
|
}
|
|
}
|
|
plugins_inited = true
|
|
}
|
|
|
|
func run_hook(name string, data interface{}) interface{} {
|
|
for _, hook := range hooks[name] {
|
|
data = hook(data)
|
|
}
|
|
return data
|
|
}
|
|
|
|
func run_vhook(name string, data ...interface{}) interface{} {
|
|
return vhooks[name](data...)
|
|
}
|
|
|
|
func run_vhook_noreturn(name string, data ...interface{}) {
|
|
_ = vhooks[name](data...)
|
|
}
|