-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathevents.go
102 lines (79 loc) · 2.35 KB
/
events.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
package unison
import (
"sync"
"github.com/s1kx/unison/events"
)
// EventHandlerFunc handles a discord event and returns whether it handles the
// event type and if an error occured.
// self is true if event was fired by bot. eg bot sent a message to someone.
type EventHandlerFunc func(ctx *Context, ev *events.DiscordEvent, self bool) (handled bool, err error)
// EventHook interface for anything that is supposed to react on a event, besides commands.
type EventHook struct {
// Name of the hook
Name string
// Description of what the hook does
Usage string
// Events that the hook should react to
Events []events.EventType
// Check if this hook is deactivated
Deactivated bool
// Command behavior
OnEvent EventHandlerFunc
}
type eventDispatcher struct {
mu sync.RWMutex
hookMap map[string]*EventHook
typeToHooksMap map[events.EventType]map[string]*EventHook
}
func newEventDispatcher() *eventDispatcher {
return &eventDispatcher{
hookMap: make(map[string]*EventHook),
typeToHooksMap: make(map[events.EventType]map[string]*EventHook),
}
}
func (d *eventDispatcher) GetHooks() map[string]*EventHook {
d.mu.RLock()
defer d.mu.RUnlock()
// Copy elements to new map rather than passing on a pointer to the internal map
nm := make(map[string]*EventHook, len(d.hookMap))
for k, v := range d.hookMap {
nm[k] = v
}
return nm
}
func (d *eventDispatcher) AddHook(hook *EventHook) error {
d.mu.Lock()
defer d.mu.Unlock()
name := hook.Name
// Add to hookMap
if ex, exists := d.hookMap[name]; exists {
return &DuplicateEventHookError{Existing: ex, New: hook}
}
d.hookMap[name] = hook
// Add hook to reverse lookup map for type => hooks
for _, t := range hook.Events {
// Create entry in typeToHooksMap if it doesn't exist
if _, ok := d.typeToHooksMap[t]; !ok {
d.typeToHooksMap[t] = make(map[string]*EventHook)
}
hooks := d.typeToHooksMap[t]
// Add hook to hook map for given type
hooks[name] = hook
}
return nil
}
func (d *eventDispatcher) Dispatch(ctx *Context, event *events.DiscordEvent, self bool) error {
d.mu.RLock()
defer d.mu.RUnlock()
t := event.Type
if _, ok := d.typeToHooksMap[t]; !ok {
// No hooks exist for given event type
return nil
}
hooks := d.typeToHooksMap[t]
for _, hook := range hooks {
// TODO: Run event handler in goroutine
hook.OnEvent(ctx, event, self)
}
return nil
}