-
Notifications
You must be signed in to change notification settings - Fork 2
/
client.go
176 lines (165 loc) · 3.8 KB
/
client.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
package etcdircd
import (
"strings"
"sync"
"github.com/golang/glog"
"gopkg.in/sorcix/irc.v2"
)
// Client accepts messages from a connected IRC client.
type Client interface {
ConnIRC
Nick(n string) error
Mode(m []string) error
Join(ch string) error
List(ch []string) error
Names(ch string) error
Ping(msg string) error
Part(ch, msg string) error
Quit(msg string) error
Whois(n string) error
Who(args []string) error
PrivMsg(target, msg string) error
Topic(ch string, msg *string) error
Away(msg string) error
Oper(login, pass string) error
Die() error
Kick(ch string, nicks []string, msg string) error
Close() error
sendHostMsg(cmd string, params ...string) error
}
func ClientDo(c Client, msg *irc.Message) error {
glog.V(7).Infof("GOT %+v", msg)
switch msg.Command {
case irc.KICK:
if len(msg.Params) < 2 {
return needMoreParams(c)
}
ch := msg.Params[0]
if !isChan(ch) {
return badChanMask(c, ch)
}
nicks := strings.Split(msg.Params[1], ",")
kickMsg := ""
if len(msg.Params) >= 3 {
kickMsg = msg.Params[2]
}
return c.Kick(ch, nicks, kickMsg)
case irc.DIE:
return c.Die()
case irc.AWAY:
awayMsg := ""
if len(msg.Params) > 0 {
if awayMsg = msg.Params[0]; awayMsg == "" {
awayMsg = "User is away"
}
}
return c.Away(awayMsg)
case irc.OPER:
if len(msg.Params) < 2 {
return needMoreParams(c)
}
return c.Oper(msg.Params[0], msg.Params[1])
case irc.CAP:
case irc.WHOIS:
n := ""
if len(msg.Params) > 0 {
n = msg.Params[0]
if isChan(n) {
glog.V(9).Infof("whois: no such nick %q", n)
return noSuchNick(c, n)
}
}
return c.Whois(n)
case irc.WHO:
return c.Who(msg.Params)
case irc.JOIN:
// Parameters: ( <ch> *( "," <ch> ) [ <key> *( "," <key> ) ] ) / "0"
if len(msg.Params) == 0 {
return needMoreParams(c)
}
if len(msg.Params) > 1 {
glog.V(9).Infof("not supported %+v", msg)
}
chs := strings.Split(msg.Params[0], ",")
for i := range chs {
if !isChan(chs[i]) {
return noSuchChannel(c, chs[i])
}
}
errc := make(chan error, len(chs))
var wg sync.WaitGroup
wg.Add(len(chs))
for i := range chs {
go func(ch string) {
defer wg.Done()
if err := c.Join(ch); err != nil {
errc <- err
}
}(chs[i])
}
wg.Wait()
close(errc)
return <-errc
case irc.MODE:
if len(msg.Params) == 0 {
return needMoreParams(c)
}
return c.Mode(msg.Params)
case irc.LIST:
// Parameters: [ <channel> *( "," <channel> ) [ <target> ] ]
args := []string{}
if len(msg.Params) > 0 {
args = strings.Split(msg.Params[0], ",")
}
return c.List(args)
case irc.NAMES:
// Command: NAMES
// Parameters: [ <channel> *( "," <channel> ) [ <target> ] ]
return c.Names(msg.Params[0])
case irc.PING:
return c.Ping(msg.Params[0])
case irc.PART:
if len(msg.Params) == 0 {
return needMoreParams(c)
}
ch := msg.Params[0]
if !isChan(ch) {
return noSuchChannel(c, ch)
}
partMsg := ""
if len(msg.Params) > 1 {
partMsg = msg.Params[1]
}
return c.Part(ch, partMsg)
case irc.QUIT:
return c.Quit(msg.Params[0])
case irc.PRIVMSG:
return c.PrivMsg(msg.Params[0], msg.Params[1])
case irc.TOPIC:
if len(msg.Params) < 1 {
return needMoreParams(c)
}
ch := msg.Params[0]
if !isChan(ch) {
return badChanMask(c, ch)
}
var topic *string
if len(msg.Params) > 1 {
topic = &msg.Params[1]
}
return c.Topic(ch, topic)
}
return nil
}
func needMoreParams(c Client) error {
return c.sendHostMsg(irc.ERR_NEEDMOREPARAMS, "Need more parameters")
}
func badChanMask(c Client, ch string) error {
return c.sendHostMsg(irc.ERR_BADCHANMASK, ch, "Bad Channel Mask")
}
func noSuchChannel(c Client, ch string) error {
return c.sendHostMsg(irc.ERR_NOSUCHCHANNEL, ch, "No such channel")
}
func noSuchNick(c Client, n string) error {
return c.sendHostMsg(irc.ERR_NOSUCHNICK, n, "No such nick/channel")
}