Add plugin API (#48)

master
HimbeerserverDE 2021-09-05 19:19:27 +02:00
parent e2815094d1
commit 1de8660e9d
No known key found for this signature in database
GPG Key ID: 1A651504791E6A8B
6 changed files with 107 additions and 3 deletions

View File

@ -553,7 +553,49 @@ func handleClt(cc *clientConn) {
cc.log("-->", "no server")
break
}
cc.server().SendCmd(cmd)
var handled bool
if strings.HasPrefix(cmd.Msg, conf().CmdPrefix) {
substrs := strings.Split(cmd.Msg, " ")
cmdName := strings.Replace(substrs[0], conf().CmdPrefix, "", 1)
var args []string
if len(substrs) > 1 {
args = substrs[1:]
}
cc.log("-->", append([]string{"cmd", cmdName}, args...))
pluginsMu.RLock()
for _, p := range plugins {
sym, err := p.Lookup("HandleChatCmd")
if err != nil {
cc.log("-->", err)
continue
}
if handler, ok := sym.(func(string, []string) bool); ok {
if handler(cmdName, args) {
handled = true
break
}
}
}
pluginsMu.RUnlock()
if !handled {
cc.SendCmd(&mt.ToCltChatMsg{
Type: mt.SysMsg,
Text: "Command not found.",
Timestamp: time.Now().Unix(),
})
handled = true
}
}
if !handled {
cc.server().SendCmd(cmd)
}
case *mt.ToSrvDeletedBlks:
if cc.server() == nil {
cc.log("-->", "no server")

View File

@ -14,6 +14,7 @@ const maxPlayerNameLen = 20
const playerNameChars = "^[a-zA-Z0-9-_]+$"
const bytesPerMediaBunch = 5000
const defaultCmdPrefix = ">"
const defaultSendInterval = 0.09
const defaultUserLimit = 10
const defaultAuthBackend = "sqlite3"
@ -23,6 +24,8 @@ var config Config
var configMu sync.RWMutex
type Config struct {
NoPlugins bool
CmdPrefix string
RequirePasswd bool
SendInterval float32
UserLimit int
@ -56,6 +59,7 @@ func loadConfig() error {
oldConf := config
config.CmdPrefix = defaultCmdPrefix
config.SendInterval = defaultSendInterval
config.UserLimit = defaultUserLimit
config.AuthBackend = defaultAuthBackend

View File

@ -5,6 +5,13 @@ The file name is `config.json`.
## Format
The configuration file contains JSON data. The fields are as follows.
> `NoPlugins`
```
Type: bool
Default: false
Description: Plugins are not loaded if this is true.
```
> `RequirePasswd`
```
Type: bool

4
log.go
View File

@ -22,13 +22,13 @@ func (lw *LogWriter) Write(p []byte) (n int, err error) {
func init() {
executable, err := os.Executable()
if err != nil {
log.Fatal(err)
log.Fatal("{←|⇶} ", err)
}
path := filepath.Dir(executable) + "/latest.log"
f, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666)
if err != nil {
log.Fatal(err)
log.Fatal("{←|⇶} ", err)
}
go func() {

View File

@ -17,6 +17,12 @@ func main() {
log.Fatal("{←|⇶} ", err)
}
if !conf().NoPlugins {
if err := loadPlugins(); err != nil {
log.Fatal("{←|⇶} ", err)
}
}
var err error
switch conf().AuthBackend {
case "sqlite3":

45
plugin.go Normal file
View File

@ -0,0 +1,45 @@
package main
import (
"log"
"os"
"path/filepath"
"plugin"
"sync"
)
var plugins []*plugin.Plugin
var pluginsMu sync.RWMutex
func loadPlugins() error {
executable, err := os.Executable()
if err != nil {
return err
}
path := filepath.Dir(executable) + "/plugins"
os.Mkdir(path, 0777)
dir, err := os.ReadDir(path)
if err != nil {
return err
}
pluginsMu.Lock()
defer pluginsMu.Unlock()
plugins = []*plugin.Plugin{}
for _, file := range dir {
p, err := plugin.Open(path + "/" + file.Name())
if err != nil {
log.Print("{←|⇶} ", err)
continue
}
plugins = append(plugins, p)
}
log.Print("{←|⇶} load plugins")
return nil
}