-
Notifications
You must be signed in to change notification settings - Fork 0
/
plugin.go
151 lines (126 loc) · 3.24 KB
/
plugin.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
package javascript
import (
"fmt"
"github.com/fsnotify/fsnotify"
"github.com/robertkrimen/otto"
"logger/stderr"
"mouse"
"path/filepath"
"sync"
)
// A Plugin represents a JavaScript Plugin for a Mouse bot.
type Plugin struct {
Config *Config
Mouse *mouse.Mouse
event *otto.Object
storage *otto.Object
files []string
vm *otto.Otto
mutex *sync.Mutex
watcher *fsnotify.Watcher
}
// NewPlugin creates a new JavaScript Plugin for a mouse bot.
func NewPlugin(mouse *mouse.Mouse, config *Config) func(*mouse.Event) {
plugin := &Plugin{
Config: config,
Mouse: mouse,
mutex: &sync.Mutex{},
vm: otto.New(),
}
// Register javascript functions
plugin.register()
go plugin.watchFiles()
// Load initial scripts
if err := plugin.load(); err != nil {
stderr.Printf("Could not load javascript plugins:", err)
}
return plugin.handler
}
func (plugin *Plugin) watchFiles() {
var err error
plugin.watcher, err = fsnotify.NewWatcher()
if err != nil {
panic(err)
}
defer plugin.watcher.Close()
for _, folder := range plugin.Config.Folders {
if err = plugin.watcher.Add(folder); err != nil {
panic(err)
}
}
for {
select {
case _ = <-plugin.watcher.Events:
if err = plugin.load(); err != nil {
stderr.Printf("Could not reload javascript plugins:", err)
}
case err := <-plugin.watcher.Errors:
stderr.Printf("Error occurred while watching javascript plugins:", err)
}
}
}
func (plugin *Plugin) handler(event *mouse.Event) {
skip := true
for _, eventType := range plugin.Config.EventTypes {
if event.Command == eventType {
skip = false
break
}
}
if skip {
return
}
// Update global variables
plugin.event.Set("command", event.Command)
plugin.event.Set("channel", event.Channel)
plugin.event.Set("message", event.Message)
plugin.event.Set("host", event.Host)
plugin.event.Set("nick", event.Nick)
plugin.event.Set("user", event.User)
plugin.storage.Set("event", plugin.event)
for _, file := range plugin.files {
plugin.mutex.Lock()
script, err := plugin.vm.Compile(file, nil)
if err != nil {
stderr.Printf("Error occurred while compiling javascript plugin:", err)
}
plugin.vm.Run(script)
plugin.mutex.Unlock()
}
}
func (plugin *Plugin) load() (err error) {
plugin.mutex.Lock()
defer plugin.mutex.Unlock()
var files []string
for _, folder := range plugin.Config.Folders {
f, _ := filepath.Glob(fmt.Sprintf(
"%s%s",
folder,
plugin.Config.Pattern,
))
files = append(files, f...)
}
plugin.files = files
return
}
func (plugin *Plugin) register() {
// Register event object
plugin.event, _ = plugin.vm.Object("event = {}")
plugin.vm.Set("event", plugin.event)
// Register storage object and functions
plugin.storage, _ = plugin.vm.Object("storage = {}")
plugin.vm.Set("storage", plugin.storage)
plugin.storage.Set("get", plugin.get)
plugin.storage.Set("put", plugin.put)
plugin.storage.Set("delete", plugin.delete)
// Register global functions
plugin.vm.Set("join", plugin.join)
plugin.vm.Set("part", plugin.part)
plugin.vm.Set("cycle", plugin.cycle)
plugin.vm.Set("say", plugin.say)
plugin.vm.Set("kick", plugin.kick)
plugin.vm.Set("ban", plugin.ban)
plugin.vm.Set("unban", plugin.unban)
plugin.vm.Set("op", plugin.op)
plugin.vm.Set("deop", plugin.deop)
}