/
zombie.go
187 lines (152 loc) · 3.81 KB
/
zombie.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
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
package zombies
import (
"fmt"
log "github.com/sirupsen/logrus"
"github.com/nickvanw/ircx"
"github.com/sorcix/irc"
)
// Zombie is a struct which represents a Big Room user inside of an IRC server.
type Zombie struct {
Messages chan Send
irc *ircx.Bot
nick string
server string
Channels []string
}
// NewZombie either creates or retrieves a zombie. Zombies will be created if
// they do not already exist for that user on a server. Zombies will be
// retrieved if a zombie for the user on a server already exists
func NewZombie(server, nick string) (*Zombie, error) {
zombie := ircx.Classic(server, nick)
if err := zombie.Connect(); err != nil {
return nil, err
}
user := &Zombie{
Messages: make(chan Send),
irc: zombie,
server: server,
nick: nick,
}
zombie.HandleFunc(irc.PING, user.pingHandler)
zombie.HandleFunc(irc.RPL_WELCOME, user.registerHandler)
zombie.HandleFunc(irc.JOIN, user.messageHandler)
go zombie.HandleLoop()
return user, nil
}
func (z *Zombie) Invite(nick, channel string) {
m := &irc.Message{
Command: irc.INVITE,
Params: []string{nick, channel},
}
z.irc.Sender.Send(m)
}
// SetNick will change the username of an IRC zombie
func (z *Zombie) SetNick(name string) {
z.nick = name
z.irc.Sender.Send(&irc.Message{
Command: irc.NICK,
Params: []string{z.nick},
})
}
// Join makes the zombie join a bunch of channels. Channels are parsed in the form: x.x.x.x:6667/#channel
func (z *Zombie) Join(channels ...string) {
// uggerrsss
n := []string{}
for i := range channels {
channel, err := ParseChannelKey(channels[i])
if err != nil {
log.WithFields(log.Fields{
"channel_key": channel,
"error": err,
}).Error("Failed getting key of channel")
}
add := true
for _, c := range z.Channels {
if c == channel {
log.WithFields(log.Fields{
"channel": channel,
}).Warn("User is already in that channel")
add = false
break
}
}
if add {
n = append(n, channel)
}
}
log.WithFields(log.Fields{
"channels": n,
}).Info("Added channels")
err := z.irc.Sender.Send(&irc.Message{
Command: irc.JOIN,
Params: n,
})
if err != nil {
log.WithFields(log.Fields{
"error": err,
"channels": n,
}).Warn("Could not join channels")
return
}
z.Channels = append(z.Channels, n...)
}
func (z *Zombie) messageHandler(s ircx.Sender, m *irc.Message) {
go func() {
for {
log.Info("Waiting for message")
msg := <-z.Messages
log.WithFields(log.Fields{
"message": msg.Message,
"channel_key": msg.Channel,
}).Info("Received message going to send to IRC")
channel, err := ParseChannelKey(msg.Channel)
if err != nil {
log.WithFields(log.Fields{
"error": err,
"channel_key": msg.Channel,
}).Error("Couldnt get channel")
return
}
log.WithFields(log.Fields{
"channel": channel,
}).Info("Succesfully parsed channels")
err = s.Send(&irc.Message{
Command: irc.PRIVMSG,
Params: []string{channel},
Trailing: msg.Message,
})
if err != nil {
log.WithFields(log.Fields{
"error": err,
}).Warn("Couldn't send message")
}
log.Info("Message sent")
}
}()
}
func (z *Zombie) registerHandler(s ircx.Sender, m *irc.Message) {
log.Info("Registered")
}
func (z *Zombie) pingHandler(s ircx.Sender, m *irc.Message) {
s.Send(&irc.Message{
Command: irc.PONG,
Params: m.Params,
Trailing: m.Trailing,
})
}
// ParseChannelKey transforms a channel key in form x.x.x.x:6667/#channel into a channel and error
// TODO Fix when not parsing channel keys with the host is not an IP
func ParseChannelKey(s string) (string, error) {
var channel string
var (
h1 int
h2 int
h3 int
h4 int
)
_, err := fmt.Sscanf(s, "%d.%d.%d.%d:6667/%v", &h1, &h2, &h3, &h4, &channel)
if err != nil {
return channel, err
}
return channel, nil
}