Import upstream version 1.1.4
Debian Janitor
2 years ago
0 | language: go | |
1 | go_import_path: gopkg.in/sorcix/irc.v1 | |
2 | go: | |
3 | - 1.0 | |
4 | - 1.1 | |
5 | - 1.2 | |
6 | - 1.3 | |
7 | - 1.4 | |
8 | - 1.5 | |
9 | - 1.6 | |
10 | - tip | |
11 | script: | |
12 | - go test -v -bench=. | |
13 | matrix: | |
14 | allow_failures: | |
15 | - go: 1.0 | |
16 | - go: 1.1 |
0 | 0 | # Go **irc** package |
1 | 1 | |
2 | [Package Documentation][Documentation] @ godoc.org | |
2 | Please use the [**v2** branch][v2] for new projects! | |
3 | 3 | |
4 | [![Build Status](https://drone.io/github.com/sorcix/irc/status.png)](https://drone.io/github.com/sorcix/irc/latest) | |
4 | [![GoDoc](https://godoc.org/gopkg.in/sorcix/irc.v1?status.svg)](https://godoc.org/gopkg.in/sorcix/irc.v1) | |
5 | 5 | |
6 | 6 | ## Features |
7 | 7 | Package irc allows your application to speak the IRC protocol. |
13 | 13 | |
14 | 14 | *This package does not manage your entire IRC connection. It only translates the protocol to easy to use Go types. It is meant as a single component in a larger IRC library, or for basic IRC bots for which a large IRC package would be overkill.* |
15 | 15 | |
16 | ### Message | |
17 | The [Message][] and [Prefix][] types provide translation to and from IRC message format. | |
16 | ## Usage | |
18 | 17 | |
19 | // Parse the IRC-encoded data and stores the result in a new struct. | |
20 | message := irc.ParseMessage(raw) | |
18 | Please use the [**v2** branch][v2] for new projects! | |
21 | 19 | |
22 | // Returns the IRC encoding of the message. | |
23 | raw = message.String() | |
24 | ||
25 | ### Encoder & Decoder | |
26 | The [Encoder][] and [Decoder][] types allow working with IRC message streams. | |
27 | ||
28 | // Create a decoder that reads from given io.Reader | |
29 | dec := irc.NewDecoder(reader) | |
30 | ||
31 | // Decode the next IRC message | |
32 | message, err := dec.Decode() | |
33 | ||
34 | // Create an encoder that writes to given io.Writer | |
35 | enc := irc.NewEncoder(writer) | |
36 | ||
37 | // Send a message to the writer. | |
38 | enc.Encode(message) | |
39 | ||
40 | ### Conn | |
41 | The [Conn][] type combines an [Encoder][] and [Decoder][] for a duplex connection. | |
42 | ||
43 | c, err := irc.Dial("irc.server.net:6667") | |
44 | ||
45 | // Methods from both Encoder and Decoder are available | |
46 | message, err := c.Decode() | |
47 | ||
48 | ## Examples | |
49 | Check these other projects for an example on how to use the package: | |
50 | ||
51 | Clients: | |
52 | ||
53 | - https://github.com/nickvanw/ircx (great simple example) | |
54 | - https://github.com/FSX/jun | |
55 | - https://github.com/jnwhiteh/wallops | |
56 | - https://github.com/Alligator/gomero | |
57 | - https://github.com/msparks/iq | |
58 | - https://github.com/TheCreeper/HackBot | |
59 | ||
60 | Servers: | |
61 | ||
62 | - https://github.com/nightexcessive/excessiveircd | |
63 | ||
64 | ||
65 | [Documentation]: https://godoc.org/github.com/sorcix/irc "Package documentation by Godoc.org" | |
66 | [Message]: https://godoc.org/github.com/sorcix/irc#Message "Message type documentation" | |
67 | [Prefix]: https://godoc.org/github.com/sorcix/irc#Prefix "Prefix type documentation" | |
68 | [Encoder]: https://godoc.org/github.com/sorcix/irc#Encoder "Encoder type documentation" | |
69 | [Decoder]: https://godoc.org/github.com/sorcix/irc#Decoder "Decoder type documentation" | |
70 | [Conn]: https://godoc.org/github.com/sorcix/irc#Conn "Conn type documentation" | |
71 | [RFC1459]: https://tools.ietf.org/html/rfc1459.html "RFC 1459" | |
20 | [Documentation]: https://godoc.org/gopkg.in/sorcix/irc.v1 "Package documentation by Godoc.org" | |
21 | [v2]: https://github.com/sorcix/irc/tree/v2 |
98 | 98 | RPL_CREATED = "003" |
99 | 99 | RPL_MYINFO = "004" |
100 | 100 | RPL_BOUNCE = "005" |
101 | RPL_ISUPPORT = "005" | |
101 | 102 | RPL_USERHOST = "302" |
102 | 103 | RPL_ISON = "303" |
103 | 104 | RPL_AWAY = "301" |
258 | 259 | ERR_SASLALREADY = "907" |
259 | 260 | RPL_SASLMECHS = "908" |
260 | 261 | ) |
262 | ||
263 | // RFC2812, section 5.3 | |
264 | const ( | |
265 | RPL_STATSCLINE = "213" | |
266 | RPL_STATSNLINE = "214" | |
267 | RPL_STATSILINE = "215" | |
268 | RPL_STATSKLINE = "216" | |
269 | RPL_STATSQLINE = "217" | |
270 | RPL_STATSYLINE = "218" | |
271 | RPL_SERVICEINFO = "231" | |
272 | RPL_ENDOFSERVICES = "232" | |
273 | RPL_SERVICE = "233" | |
274 | RPL_STATSVLINE = "240" | |
275 | RPL_STATSLLINE = "241" | |
276 | RPL_STATSHLINE = "244" | |
277 | RPL_STATSSLINE = "245" | |
278 | RPL_STATSPING = "246" | |
279 | RPL_STATSBLINE = "247" | |
280 | RPL_STATSDLINE = "250" | |
281 | RPL_NONE = "300" | |
282 | RPL_WHOISCHANOP = "316" | |
283 | RPL_KILLDONE = "361" | |
284 | RPL_CLOSING = "362" | |
285 | RPL_CLOSEEND = "363" | |
286 | RPL_INFOSTART = "373" | |
287 | RPL_MYPORTIS = "384" | |
288 | ERR_NOSERVICEHOST = "492" | |
289 | ) | |
290 | ||
291 | // Other constants | |
292 | const ( | |
293 | ERR_TOOMANYMATCHES = "416" // Used on IRCNet | |
294 | RPL_TOPICWHOTIME = "333" // From ircu, in use on Freenode | |
295 | RPL_LOCALUSERS = "265" // From aircd, Hybrid, Hybrid, Bahamut, in use on Freenode | |
296 | RPL_GLOBALUSERS = "266" // From aircd, Hybrid, Hybrid, Bahamut, in use on Freenode | |
297 | ) |
32 | 32 | // // Methods from both Encoder and Decoder are available |
33 | 33 | // message, err := c.Decode() |
34 | 34 | // |
35 | package irc // import "github.com/sorcix/irc" | |
35 | package irc |
20 | 20 | |
21 | 21 | func cutsetFunc(r rune) bool { |
22 | 22 | // Characters to trim from prefixes/messages. |
23 | return r == '\r' || r == '\n' || r == '\x20' || r == '\x00' | |
24 | } | |
25 | ||
26 | // Objects implementing the Sender interface are able to send messages to an IRC server. | |
23 | return r == '\r' || r == '\n' | |
24 | } | |
25 | ||
26 | // Sender represents objects that are able to send messages to an IRC server. | |
27 | 27 | // |
28 | 28 | // As there might be a message queue, it is possible that Send returns a nil |
29 | 29 | // error, but the message is not sent (yet). The error value is only used when |
193 | 193 | |
194 | 194 | // Extract command |
195 | 195 | if j > i { |
196 | m.Command = raw[i:j] | |
196 | m.Command = strings.ToUpper(raw[i:j]) | |
197 | 197 | } else { |
198 | m.Command = raw[i:] | |
198 | m.Command = strings.ToUpper(raw[i:]) | |
199 | 199 | |
200 | 200 | // We're done here! |
201 | 201 | return m |
207 | 207 | // Find prefix for trailer |
208 | 208 | i = indexByte(raw[j:], prefix) |
209 | 209 | |
210 | if i < 0 { | |
210 | if i < 0 || raw[j+i-1] != space { | |
211 | 211 | |
212 | 212 | // There is no trailing argument! |
213 | 213 | m.Params = strings.Split(raw[j:], string(space)) |
4 | 4 | package irc |
5 | 5 | |
6 | 6 | import ( |
7 | "fmt" | |
7 | 8 | "reflect" |
8 | 9 | "testing" |
9 | 10 | ) |
11 | ||
12 | func ExampleParseMessage() { | |
13 | message := ParseMessage("JOIN #help") | |
14 | ||
15 | fmt.Println(message.Params[0]) | |
16 | ||
17 | // Output: #help | |
18 | } | |
19 | ||
20 | func ExampleMessage_String() { | |
21 | message := &Message{ | |
22 | Prefix: &Prefix{ | |
23 | Name: "sorcix", | |
24 | User: "sorcix", | |
25 | Host: "myhostname", | |
26 | }, | |
27 | Command: "PRIVMSG", | |
28 | Trailing: "This is an example!", | |
29 | } | |
30 | ||
31 | fmt.Println(message.String()) | |
32 | ||
33 | // Output: :sorcix!sorcix@myhostname PRIVMSG :This is an example! | |
34 | } | |
10 | 35 | |
11 | 36 | var messageTests = [...]*struct { |
12 | 37 | parsed *Message |
253 | 278 | rawMessage: "TOPIC #foo :", |
254 | 279 | rawPrefix: "", |
255 | 280 | }, |
281 | { | |
282 | parsed: &Message{ | |
283 | Prefix: &Prefix{ | |
284 | Name: "name", | |
285 | User: "user", | |
286 | Host: "example.org", | |
287 | }, | |
288 | Command: "PRIVMSG", | |
289 | Params: []string{"#test"}, | |
290 | Trailing: "Message with spaces at the end! ", | |
291 | }, | |
292 | rawMessage: ":name!user@example.org PRIVMSG #test :Message with spaces at the end! ", | |
293 | rawPrefix: "name!user@example.org", | |
294 | hostmask: true, | |
295 | }, | |
296 | { | |
297 | parsed: &Message{ | |
298 | Command: "PASS", | |
299 | Params: []string{"oauth:token_goes_here"}, | |
300 | }, | |
301 | rawMessage: "PASS oauth:token_goes_here", | |
302 | rawPrefix: "", | |
303 | }, | |
256 | 304 | } |
257 | 305 | |
258 | 306 | // ----- |
5 | 5 | |
6 | 6 | import ( |
7 | 7 | "bytes" |
8 | "crypto/tls" | |
8 | 9 | "io" |
10 | "log" | |
9 | 11 | "reflect" |
10 | 12 | "strings" |
11 | 13 | "testing" |
12 | 14 | ) |
15 | ||
16 | // We use the Dial function as a simple shortcut for connecting to an IRC server using a standard TCP socket. | |
17 | func ExampleDial() { | |
18 | conn, err := Dial("irc.quakenet.org:6667") | |
19 | if err != nil { | |
20 | log.Fatalln("Could not connect to IRC server") | |
21 | } | |
22 | ||
23 | conn.Close() | |
24 | } | |
25 | ||
26 | // Use NewConn when you want to connect using something else than a standard TCP socket. | |
27 | // This example first opens an encrypted TLS connection and then uses that to communicate with the server. | |
28 | func ExampleNewConn() { | |
29 | tconn, err := tls.Dial("tcp", "irc.quakenet.org:6667", &tls.Config{}) | |
30 | if err != nil { | |
31 | log.Fatalln("Could not connect to IRC server") | |
32 | } | |
33 | conn := NewConn(tconn) | |
34 | ||
35 | conn.Close() | |
36 | } | |
13 | 37 | |
14 | 38 | var stream = "PING port80a.se.quakenet.org\r\n:port80a.se.quakenet.org PONG port80a.se.quakenet.org :port80a.se.quakenet.org\r\nPING chat.freenode.net\r\n:wilhelm.freenode.net PONG wilhelm.freenode.net :chat.freenode.net\r\n" |
15 | 39 |