-
Notifications
You must be signed in to change notification settings - Fork 0
/
events.go
167 lines (146 loc) · 4.6 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
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
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
package events
// Events and dispatcher.
//go:generate stringer -type=EventCode
import (
"github.com/sirupsen/logrus"
)
type EventCode int
// Single event codes.
const (
// Normal chat message.
EventChatMessage EventCode = iota
// Chat notice.
EventChatNotice
// Private message received.
EventPrivateMessage
// URL found in the message.
EventURLFound
// Bot activity, like command or event handler started.
EventBotWorking
// Bot finished activity.
EventBotDone
// Transport connected.
EventConnected
// Someone joined a channel.
EventJoinedChannel
// Bot re-joined a channel.
EventReJoinedChannel
// Someone left a channel.
EventPartChannel
// Someone was kicked from a channel.
EventKickedFromChannel
// Someone was banned from a channel.
EventBannedFromChannel
// Other channel operations.
EventChannelOps
// Bot tick.
EventTick
// Daily bot tick.
EventDailyTick
)
// Event code groups, for convenience.
var EventsChannelActivity = []EventCode{
EventChannelOps, EventJoinedChannel, EventReJoinedChannel, EventPartChannel, EventKickedFromChannel,
EventBannedFromChannel}
var EventsChannelMessages = []EventCode{EventChatNotice, EventChatMessage}
// Message formatting options.
type Formatting int
const (
FormatPlain Formatting = iota
FormatIRC
FormatMarkdown
)
// Message for the events channel.
type EventMessage struct {
// Name of the transport that triggered the event.
TransportName string
// Message formatting accepted by the transport.
TransportFormatting Formatting
// Event code.
EventCode EventCode
// Sender information
Nick, UserId string
Channel string
Message string
// Context for the message, will be passed back if any listener sends a message.
Context string
// Was the message directed at the bot? If yes, bot will check for commands.
// Message directed at the bot should be stripped of the prefixes like dot or bot's name.
// In case of join, part etc. this will indicate whether bot was the subject.
AtBot bool
}
// IsPrivate will tell if an event was triggered by a private chat message.
func (message *EventMessage) IsPrivate() bool {
if message.EventCode == EventPrivateMessage {
return true
}
return false
}
// ChannelId will return a channel id that is (most likely) unique.
func (message *EventMessage) ChannelId() string {
return message.TransportName + ";" + message.Channel
}
// Type for a valid event listener function.
type EventListenerFunc func(message EventMessage)
// Event dispatcher.
type EventDispatcher struct {
listeners map[EventCode][]EventListenerFunc
log *logrus.Logger
// List of people whos events will be ignored, in the form of transport~nick.
blackList []string
}
// RegisterMultiListener will attach a listener to multiple events.
func (dispatcher *EventDispatcher) RegisterMultiListener(eventCodes []EventCode, listener EventListenerFunc) {
for _, eventCode := range eventCodes {
dispatcher.RegisterListener(eventCode, listener)
}
}
// RegisterListener will register a listener to an event.
func (dispatcher *EventDispatcher) RegisterListener(eventCode EventCode, listener EventListenerFunc) {
// RegisterExtension will register a new extension with the bot.
dispatcher.listeners[eventCode] = append(dispatcher.listeners[eventCode], listener)
dispatcher.log.Debugf("Added listener for event \"%s\": %v", eventCode, listener)
}
// Trigger will trigger an event.
func (dispatcher *EventDispatcher) Trigger(eventMessage EventMessage) {
if dispatcher.isIgnored(eventMessage) {
dispatcher.log.Infof(
"Ignoring event %s from %s (%s)", eventMessage.EventCode, eventMessage.Nick, eventMessage.UserId)
return
}
for _, listener := range dispatcher.listeners[eventMessage.EventCode] {
go func(listener EventListenerFunc) {
// Catch errors.
defer func() {
if r := recover(); r != nil {
dispatcher.log.Errorf("FATAL ERROR in event handler for %v: %v", eventMessage.EventCode, r)
}
}()
listener(eventMessage)
}(listener)
}
}
// isIgnored will check whether the message comes from an ignored person.
func (dispatcher *EventDispatcher) isIgnored(eventMessage EventMessage) bool {
if eventMessage.UserId == "" {
return false
}
for _, person := range dispatcher.blackList {
if person == eventMessage.UserId {
return true
}
}
return false
}
// SetBlackList sets the ignore list.
func (dispatcher *EventDispatcher) SetBlackList(blackList []string) {
dispatcher.blackList = blackList
}
// New will create a new event dispatcher instance.
func New(logger *logrus.Logger) *EventDispatcher {
dispatcher := &EventDispatcher{
listeners: map[EventCode][]EventListenerFunc{},
log: logger,
}
return dispatcher
}