rename to Message and Reader; remove Event
This commit is contained in:
parent
4d7631f681
commit
23a3bb8f66
|
@ -23,12 +23,12 @@ irc := ircevent.Connection{
|
|||
RequestCaps: []string{"server-time", "message-tags"},
|
||||
}
|
||||
|
||||
irc.AddCallback("001", func(e ircevent.Event) { irc.Join("#ircevent-test") })
|
||||
irc.AddCallback("001", func(e ircmsg.Message) { irc.Join("#ircevent-test") })
|
||||
|
||||
irc.AddCallback("PRIVMSG", func(event ircevent.Event) {
|
||||
//event.Message() contains the message
|
||||
//event.Nick() Contains the sender
|
||||
//event.Params[0] Contains the channel
|
||||
irc.AddCallback("PRIVMSG", func(event ircmsg.Message) {
|
||||
// event.Prefix is the source;
|
||||
// event.Params[0] is the target (the channel or nickname the message was sent to)
|
||||
// and event.Params[1] is the message itself
|
||||
});
|
||||
|
||||
err := irc.Connect()
|
||||
|
|
|
@ -8,6 +8,7 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/goshuirc/irc-go/ircevent"
|
||||
"github.com/goshuirc/irc-go/ircmsg"
|
||||
)
|
||||
|
||||
func getenv(key, defaultValue string) (value string) {
|
||||
|
@ -36,15 +37,15 @@ func main() {
|
|||
SASLPassword: saslPassword,
|
||||
}
|
||||
|
||||
irc.AddConnectCallback(func(e ircevent.Event) {
|
||||
irc.AddConnectCallback(func(e ircmsg.Message) {
|
||||
// attempt to set the BOT mode on ourself:
|
||||
if botMode := irc.ISupport()["BOT"]; botMode != "" {
|
||||
irc.Send("MODE", irc.CurrentNick(), "+"+botMode)
|
||||
}
|
||||
irc.Join(channel)
|
||||
})
|
||||
irc.AddCallback("JOIN", func(e ircevent.Event) {}) // TODO try to rejoin if we *don't* get this
|
||||
irc.AddCallback("PRIVMSG", func(e ircevent.Event) {
|
||||
irc.AddCallback("JOIN", func(e ircmsg.Message) {}) // TODO try to rejoin if we *don't* get this
|
||||
irc.AddCallback("PRIVMSG", func(e ircmsg.Message) {
|
||||
if len(e.Params) < 2 {
|
||||
return
|
||||
}
|
||||
|
@ -65,7 +66,7 @@ func main() {
|
|||
// example client-to-client extension via message-tags:
|
||||
// have the bot maintain a running sum of integers
|
||||
var sum int64 // doesn't need synchronization as long as it's only visible from a single callback
|
||||
irc.AddCallback("TAGMSG", func(e ircevent.Event) {
|
||||
irc.AddCallback("TAGMSG", func(e ircmsg.Message) {
|
||||
_, tv := e.GetTag("+summand")
|
||||
if v, err := strconv.ParseInt(tv, 10, 64); err == nil {
|
||||
sum += v
|
||||
|
|
|
@ -9,6 +9,7 @@ import (
|
|||
_ "net/http/pprof"
|
||||
|
||||
"github.com/goshuirc/irc-go/ircevent"
|
||||
"github.com/goshuirc/irc-go/ircmsg"
|
||||
)
|
||||
|
||||
/*
|
||||
|
@ -48,11 +49,11 @@ func main() {
|
|||
RequestCaps: []string{"server-time", "echo-message"},
|
||||
}
|
||||
|
||||
irc.AddCallback("001", func(e ircevent.Event) { irc.Join(channel) })
|
||||
irc.AddCallback("JOIN", func(e ircevent.Event) { irc.Privmsg(channel, "hi there friend!") })
|
||||
irc.AddCallback("001", func(e ircmsg.Message) { irc.Join(channel) })
|
||||
irc.AddCallback("JOIN", func(e ircmsg.Message) { irc.Privmsg(channel, "hi there friend!") })
|
||||
// echo whatever we get back
|
||||
count := 0
|
||||
irc.AddCallback("PRIVMSG", func(e ircevent.Event) {
|
||||
irc.AddCallback("PRIVMSG", func(e ircmsg.Message) {
|
||||
if limit != 0 && count >= limit {
|
||||
irc.Quit()
|
||||
} else {
|
||||
|
|
|
@ -142,7 +142,7 @@ func (irc *Connection) readLoop() {
|
|||
}
|
||||
|
||||
func readMsgLoop(socket net.Conn, maxLineLen int, msgChan chan string, errChan chan error, end chan empty) {
|
||||
var reader ircreader.IRCReader
|
||||
var reader ircreader.Reader
|
||||
reader.Initialize(socket, 1024, maxLineLen+maxlenTags)
|
||||
for {
|
||||
msgBytes, err := reader.ReadLine()
|
||||
|
@ -348,8 +348,8 @@ func (irc *Connection) sendInternal(b []byte) (err error) {
|
|||
}
|
||||
}
|
||||
|
||||
// Send a built ircmsg.IRCMessage.
|
||||
func (irc *Connection) SendIRCMessage(msg ircmsg.IRCMessage) error {
|
||||
// Send a built ircmsg.Message.
|
||||
func (irc *Connection) SendIRCMessage(msg ircmsg.Message) error {
|
||||
b, err := msg.LineBytesStrict(true, irc.MaxLineLen)
|
||||
if err != nil {
|
||||
if irc.Debug {
|
||||
|
|
|
@ -23,10 +23,10 @@ type CallbackID struct {
|
|||
}
|
||||
|
||||
// Register a callback to a connection and event code. A callback is a function
|
||||
// which takes only an Event object as parameter. Valid event codes are all
|
||||
// which takes only an ircmsg.Message object as parameter. Valid event codes are all
|
||||
// IRC/CTCP commands and error/response codes. This function returns the ID of the
|
||||
// registered callback for later management.
|
||||
func (irc *Connection) AddCallback(eventCode string, callback func(Event)) CallbackID {
|
||||
func (irc *Connection) AddCallback(eventCode string, callback func(ircmsg.Message)) CallbackID {
|
||||
return irc.addCallback(eventCode, Callback(callback), false, 0)
|
||||
}
|
||||
|
||||
|
@ -103,7 +103,7 @@ func (irc *Connection) ClearCallback(eventcode string) {
|
|||
}
|
||||
|
||||
// Replace callback i (ID) associated with a given event code with a new callback function.
|
||||
func (irc *Connection) ReplaceCallback(id CallbackID, callback func(Event)) bool {
|
||||
func (irc *Connection) ReplaceCallback(id CallbackID, callback func(ircmsg.Message)) bool {
|
||||
irc.eventsMutex.Lock()
|
||||
defer irc.eventsMutex.Unlock()
|
||||
|
||||
|
@ -153,7 +153,7 @@ func (irc *Connection) removeBatchCallbackNoMutex(idNum uint64) {
|
|||
// Convenience function to add a callback that will be called once the
|
||||
// connection is completed (this is traditionally referred to as "connection
|
||||
// registration").
|
||||
func (irc *Connection) AddConnectCallback(callback func(Event)) (id CallbackID) {
|
||||
func (irc *Connection) AddConnectCallback(callback func(ircmsg.Message)) (id CallbackID) {
|
||||
// XXX: forcibly use the same ID number for both copies of the callback
|
||||
id376 := irc.AddCallback(RPL_ENDOFMOTD, callback)
|
||||
irc.addCallback(ERR_NOMOTD, callback, false, id376.id)
|
||||
|
@ -184,7 +184,7 @@ var (
|
|||
errorUnknownLabel = errors.New("received labeled response from server, but we don't recognize the label")
|
||||
)
|
||||
|
||||
func (irc *Connection) handleBatchCommand(msg ircmsg.IRCMessage) {
|
||||
func (irc *Connection) handleBatchCommand(msg ircmsg.Message) {
|
||||
if len(msg.Params) < 1 || len(msg.Params[0]) < 2 {
|
||||
irc.Log.Printf("Invalid BATCH command from server\n")
|
||||
return
|
||||
|
@ -214,7 +214,7 @@ func (irc *Connection) handleBatchCommand(msg ircmsg.IRCMessage) {
|
|||
return
|
||||
}
|
||||
batchObj := new(Batch)
|
||||
batchObj.IRCMessage = msg
|
||||
batchObj.Message = msg
|
||||
irc.batches[batchID] = batchInProgress{
|
||||
createdAt: time.Now(),
|
||||
batch: batchObj,
|
||||
|
@ -295,14 +295,14 @@ func (irc *Connection) HandleBatch(batch *Batch) {
|
|||
// recursively "flatten" the nested batch; process every command individually
|
||||
func (irc *Connection) handleBatchNaively(batch *Batch) {
|
||||
if batch.Command != "BATCH" {
|
||||
irc.HandleEvent(Event{IRCMessage: batch.IRCMessage})
|
||||
irc.HandleMessage(batch.Message)
|
||||
}
|
||||
for _, item := range batch.Items {
|
||||
irc.handleBatchNaively(item)
|
||||
}
|
||||
}
|
||||
|
||||
func (irc *Connection) handleBatchedCommand(msg ircmsg.IRCMessage, batchID string) {
|
||||
func (irc *Connection) handleBatchedCommand(msg ircmsg.Message, batchID string) {
|
||||
irc.batchMutex.Lock()
|
||||
defer irc.batchMutex.Unlock()
|
||||
|
||||
|
@ -311,11 +311,11 @@ func (irc *Connection) handleBatchedCommand(msg ircmsg.IRCMessage, batchID strin
|
|||
irc.Log.Printf("ignoring command with unknown batch ID %s\n", batchID)
|
||||
return
|
||||
}
|
||||
bip.batch.Items = append(bip.batch.Items, &Batch{IRCMessage: msg})
|
||||
bip.batch.Items = append(bip.batch.Items, &Batch{Message: msg})
|
||||
}
|
||||
|
||||
// Execute all callbacks associated with a given event.
|
||||
func (irc *Connection) runCallbacks(msg ircmsg.IRCMessage) {
|
||||
func (irc *Connection) runCallbacks(msg ircmsg.Message) {
|
||||
if !irc.AllowPanic {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
|
@ -347,7 +347,7 @@ func (irc *Connection) runCallbacks(msg ircmsg.IRCMessage) {
|
|||
return
|
||||
} else {
|
||||
labelCallback(&Batch{
|
||||
IRCMessage: msg,
|
||||
Message: msg,
|
||||
})
|
||||
}
|
||||
return
|
||||
|
@ -355,12 +355,12 @@ func (irc *Connection) runCallbacks(msg ircmsg.IRCMessage) {
|
|||
}
|
||||
|
||||
// OK, it's a normal IRC command
|
||||
irc.HandleEvent(Event{IRCMessage: msg})
|
||||
irc.HandleMessage(msg)
|
||||
}
|
||||
|
||||
// HandleEvent handles an IRC line using the available handlers. This can be
|
||||
// HandleMessage handles an IRC line using the available handlers. This can be
|
||||
// used in a batch or labeled-response callback to process an individual line.
|
||||
func (irc *Connection) HandleEvent(event Event) {
|
||||
func (irc *Connection) HandleMessage(event ircmsg.Message) {
|
||||
if irc.EnableCTCP {
|
||||
eventRewriteCTCP(&event)
|
||||
}
|
||||
|
@ -386,12 +386,10 @@ func (irc *Connection) setupCallbacks() {
|
|||
}
|
||||
|
||||
// PING: we must respond with the correct PONG
|
||||
irc.AddCallback("PING", func(e Event) { irc.Send("PONG", e.Message()) })
|
||||
irc.AddCallback("PING", func(e ircmsg.Message) { irc.Send("PONG", lastParam(&e)) })
|
||||
|
||||
// PONG: record time to make sure the server is responding to us
|
||||
irc.AddCallback("PONG", func(e Event) {
|
||||
irc.recordPong(e.Message())
|
||||
})
|
||||
irc.AddCallback("PONG", func(e ircmsg.Message) { irc.recordPong(lastParam(&e)) })
|
||||
|
||||
// 433: ERR_NICKNAMEINUSE "<nick> :Nickname is already in use"
|
||||
// 437: ERR_UNAVAILRESOURCE "<nick/channel> :Nick/channel is temporarily unavailable"
|
||||
|
@ -406,13 +404,13 @@ func (irc *Connection) setupCallbacks() {
|
|||
irc.AddCallback(RPL_ISUPPORT, irc.handleISupport)
|
||||
|
||||
// respond to NICK from the server (in response to our own NICK, or sent unprompted)
|
||||
irc.AddCallback("NICK", func(e Event) {
|
||||
if e.Nick() == irc.CurrentNick() && len(e.Params) > 0 {
|
||||
irc.AddCallback("NICK", func(e ircmsg.Message) {
|
||||
if ExtractNick(e.Prefix) == irc.CurrentNick() && len(e.Params) > 0 {
|
||||
irc.setCurrentNick(e.Params[0])
|
||||
}
|
||||
})
|
||||
|
||||
irc.AddCallback("ERROR", func(e Event) {
|
||||
irc.AddCallback("ERROR", func(e ircmsg.Message) {
|
||||
if !irc.isQuitting() {
|
||||
irc.Log.Printf("ERROR received from server: %s", strings.Join(e.Params, " "))
|
||||
}
|
||||
|
@ -438,7 +436,7 @@ func (irc *Connection) setupCallbacks() {
|
|||
irc.AddCallback("NOTE", irc.handleStandardReplies)
|
||||
}
|
||||
|
||||
func (irc *Connection) handleRplWelcome(e Event) {
|
||||
func (irc *Connection) handleRplWelcome(e ircmsg.Message) {
|
||||
irc.stateMutex.Lock()
|
||||
defer irc.stateMutex.Unlock()
|
||||
|
||||
|
@ -448,7 +446,7 @@ func (irc *Connection) handleRplWelcome(e Event) {
|
|||
}
|
||||
}
|
||||
|
||||
func (irc *Connection) handleRegistration(e Event) {
|
||||
func (irc *Connection) handleRegistration(e ircmsg.Message) {
|
||||
// wake up Connect() if applicable
|
||||
defer func() {
|
||||
select {
|
||||
|
@ -471,7 +469,7 @@ func (irc *Connection) handleRegistration(e Event) {
|
|||
|
||||
}
|
||||
|
||||
func (irc *Connection) handleUnavailableNick(e Event) {
|
||||
func (irc *Connection) handleUnavailableNick(e ircmsg.Message) {
|
||||
// only try to change the nick if we're not registered yet,
|
||||
// otherwise we'll change in response to pingLoop unsuccessfully
|
||||
// trying to restore the intended nick (swapping one undesired nick
|
||||
|
@ -489,7 +487,7 @@ func (irc *Connection) handleUnavailableNick(e Event) {
|
|||
}
|
||||
}
|
||||
|
||||
func (irc *Connection) handleISupport(e Event) {
|
||||
func (irc *Connection) handleISupport(e ircmsg.Message) {
|
||||
irc.stateMutex.Lock()
|
||||
defer irc.stateMutex.Unlock()
|
||||
|
||||
|
@ -530,7 +528,7 @@ func unescapeISupportValue(in string) (out string) {
|
|||
return buf.String()
|
||||
}
|
||||
|
||||
func (irc *Connection) handleCAP(e Event) {
|
||||
func (irc *Connection) handleCAP(e ircmsg.Message) {
|
||||
if len(e.Params) < 3 {
|
||||
return
|
||||
}
|
||||
|
@ -666,7 +664,7 @@ func splitCAPToken(token string) (name, value string) {
|
|||
}
|
||||
}
|
||||
|
||||
func (irc *Connection) handleStandardReplies(e Event) {
|
||||
func (irc *Connection) handleStandardReplies(e ircmsg.Message) {
|
||||
// unconditionally print messages for FAIL and WARN;
|
||||
// re. NOTE, if debug is enabled, we print the raw line anyway
|
||||
switch e.Command {
|
||||
|
|
|
@ -4,9 +4,11 @@ import (
|
|||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/goshuirc/irc-go/ircmsg"
|
||||
)
|
||||
|
||||
func eventRewriteCTCP(event *Event) {
|
||||
func eventRewriteCTCP(event *ircmsg.Message) {
|
||||
// XXX rewrite event.Command for CTCP
|
||||
if !(event.Command == "PRIVMSG" && len(event.Params) == 2 && strings.HasPrefix(event.Params[1], "\x01")) {
|
||||
return
|
||||
|
@ -44,21 +46,23 @@ func eventRewriteCTCP(event *Event) {
|
|||
}
|
||||
|
||||
func (irc *Connection) setupCTCPCallbacks() {
|
||||
irc.AddCallback("CTCP_VERSION", func(e Event) {
|
||||
irc.SendRaw(fmt.Sprintf("NOTICE %s :\x01VERSION %s\x01", e.Nick(), irc.Version))
|
||||
irc.AddCallback("CTCP_VERSION", func(e ircmsg.Message) {
|
||||
irc.SendRaw(fmt.Sprintf("NOTICE %s :\x01VERSION %s\x01", ExtractNick(e.Prefix), irc.Version))
|
||||
})
|
||||
|
||||
irc.AddCallback("CTCP_USERINFO", func(e Event) {
|
||||
irc.SendRaw(fmt.Sprintf("NOTICE %s :\x01USERINFO %s\x01", e.Nick(), irc.User))
|
||||
irc.AddCallback("CTCP_USERINFO", func(e ircmsg.Message) {
|
||||
irc.SendRaw(fmt.Sprintf("NOTICE %s :\x01USERINFO %s\x01", ExtractNick(e.Prefix), irc.User))
|
||||
})
|
||||
|
||||
irc.AddCallback("CTCP_CLIENTINFO", func(e Event) {
|
||||
irc.SendRaw(fmt.Sprintf("NOTICE %s :\x01CLIENTINFO PING VERSION TIME USERINFO CLIENTINFO\x01", e.Nick()))
|
||||
irc.AddCallback("CTCP_CLIENTINFO", func(e ircmsg.Message) {
|
||||
irc.SendRaw(fmt.Sprintf("NOTICE %s :\x01CLIENTINFO PING VERSION TIME USERINFO CLIENTINFO\x01", ExtractNick(e.Prefix)))
|
||||
})
|
||||
|
||||
irc.AddCallback("CTCP_TIME", func(e Event) {
|
||||
irc.SendRaw(fmt.Sprintf("NOTICE %s :\x01TIME %s\x01", e.Nick(), time.Now().UTC().Format(time.RFC1123)))
|
||||
irc.AddCallback("CTCP_TIME", func(e ircmsg.Message) {
|
||||
irc.SendRaw(fmt.Sprintf("NOTICE %s :\x01TIME %s\x01", ExtractNick(e.Prefix), time.Now().UTC().Format(time.RFC1123)))
|
||||
})
|
||||
|
||||
irc.AddCallback("CTCP_PING", func(e Event) { irc.SendRaw(fmt.Sprintf("NOTICE %s :\x01%s\x01", e.Nick(), e.Message())) })
|
||||
irc.AddCallback("CTCP_PING", func(e ircmsg.Message) {
|
||||
irc.SendRaw(fmt.Sprintf("NOTICE %s :\x01%s\x01", ExtractNick(e.Prefix), e.Params[1]))
|
||||
})
|
||||
}
|
||||
|
|
|
@ -6,6 +6,8 @@ import (
|
|||
"encoding/hex"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/goshuirc/irc-go/ircmsg"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -21,7 +23,7 @@ func TestLabeledResponse(t *testing.T) {
|
|||
irccon.RequestCaps = []string{"message-tags", "batch", "labeled-response"}
|
||||
irccon.RealName = "ecf61da38b58"
|
||||
results := make(map[string]string)
|
||||
irccon.AddConnectCallback(func(e Event) {
|
||||
irccon.AddConnectCallback(func(e ircmsg.Message) {
|
||||
irccon.SendWithLabel(func(batch *Batch) {
|
||||
if batch == nil {
|
||||
return
|
||||
|
@ -192,7 +194,7 @@ func TestBatchHandlers(t *testing.T) {
|
|||
}
|
||||
return false
|
||||
})
|
||||
alice.AddCallback("PRIVMSG", func(e Event) {
|
||||
alice.AddCallback("PRIVMSG", func(e ircmsg.Message) {
|
||||
alicePrivmsgCount++
|
||||
})
|
||||
|
||||
|
|
|
@ -7,16 +7,16 @@ import (
|
|||
)
|
||||
|
||||
func TestParse(t *testing.T) {
|
||||
event := new(Event)
|
||||
event.Prefix = "nick!~user@host"
|
||||
source := "nick!~user@host"
|
||||
nick, user, host := SplitNUH(source)
|
||||
|
||||
if event.Nick() != "nick" {
|
||||
if nick != "nick" {
|
||||
t.Fatal("Parse failed: nick")
|
||||
}
|
||||
if event.User() != "~user" {
|
||||
if user != "~user" {
|
||||
t.Fatal("Parse failed: user")
|
||||
}
|
||||
if event.Host() != "host" {
|
||||
if host != "host" {
|
||||
t.Fatal("Parse failed: host")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,8 @@ import (
|
|||
"encoding/base64"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/goshuirc/irc-go/ircmsg"
|
||||
)
|
||||
|
||||
type saslResult struct {
|
||||
|
@ -28,35 +30,35 @@ func (irc *Connection) submitSASLResult(r saslResult) {
|
|||
}
|
||||
|
||||
func (irc *Connection) setupSASLCallbacks() {
|
||||
irc.AddCallback("AUTHENTICATE", func(e Event) {
|
||||
irc.AddCallback("AUTHENTICATE", func(e ircmsg.Message) {
|
||||
str := base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%s\x00%s\x00%s", irc.SASLLogin, irc.SASLLogin, irc.SASLPassword)))
|
||||
irc.Send("AUTHENTICATE", str)
|
||||
})
|
||||
|
||||
irc.AddCallback(RPL_LOGGEDOUT, func(e Event) {
|
||||
irc.AddCallback(RPL_LOGGEDOUT, func(e ircmsg.Message) {
|
||||
irc.SendRaw("CAP END")
|
||||
irc.SendRaw("QUIT")
|
||||
irc.submitSASLResult(saslResult{true, errors.New(e.Params[1])})
|
||||
})
|
||||
|
||||
irc.AddCallback(ERR_NICKLOCKED, func(e Event) {
|
||||
irc.AddCallback(ERR_NICKLOCKED, func(e ircmsg.Message) {
|
||||
irc.SendRaw("CAP END")
|
||||
irc.SendRaw("QUIT")
|
||||
irc.submitSASLResult(saslResult{true, errors.New(e.Params[1])})
|
||||
})
|
||||
|
||||
irc.AddCallback(RPL_SASLSUCCESS, func(e Event) {
|
||||
irc.AddCallback(RPL_SASLSUCCESS, func(e ircmsg.Message) {
|
||||
irc.submitSASLResult(saslResult{false, nil})
|
||||
})
|
||||
|
||||
irc.AddCallback(ERR_SASLFAIL, func(e Event) {
|
||||
irc.AddCallback(ERR_SASLFAIL, func(e ircmsg.Message) {
|
||||
irc.SendRaw("CAP END")
|
||||
irc.SendRaw("QUIT")
|
||||
irc.submitSASLResult(saslResult{true, errors.New(e.Params[1])})
|
||||
})
|
||||
|
||||
// this could potentially happen with auto-login via certfp?
|
||||
irc.AddCallback(ERR_SASLALREADY, func(e Event) {
|
||||
irc.AddCallback(ERR_SASLALREADY, func(e ircmsg.Message) {
|
||||
irc.submitSASLResult(saslResult{false, nil})
|
||||
})
|
||||
}
|
||||
|
|
|
@ -5,6 +5,8 @@ import (
|
|||
"fmt"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/goshuirc/irc-go/ircmsg"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -48,9 +50,9 @@ func runCAPTest(caps []string, useSASL bool, t *testing.T) {
|
|||
}
|
||||
irccon.RequestCaps = caps
|
||||
irccon.TLSConfig = &tls.Config{InsecureSkipVerify: true}
|
||||
irccon.AddCallback("001", func(e Event) { irccon.Join("#go-eventirc") })
|
||||
irccon.AddCallback("001", func(e ircmsg.Message) { irccon.Join("#go-eventirc") })
|
||||
|
||||
irccon.AddCallback("366", func(e Event) {
|
||||
irccon.AddCallback("366", func(e ircmsg.Message) {
|
||||
irccon.Privmsg("#go-eventirc", "Test Message SASL")
|
||||
irccon.Quit()
|
||||
})
|
||||
|
@ -96,7 +98,7 @@ func TestSASLFail(t *testing.T) {
|
|||
irccon.UseTLS = true
|
||||
setSaslTestCreds(irccon, t)
|
||||
irccon.TLSConfig = &tls.Config{InsecureSkipVerify: true}
|
||||
irccon.AddCallback("001", func(e Event) { irccon.Join("#go-eventirc") })
|
||||
irccon.AddCallback("001", func(e ircmsg.Message) { irccon.Join("#go-eventirc") })
|
||||
// intentionally break the password
|
||||
irccon.SASLPassword = irccon.SASLPassword + "_"
|
||||
err := irccon.Connect()
|
||||
|
|
|
@ -17,7 +17,7 @@ import (
|
|||
|
||||
type empty struct{}
|
||||
|
||||
type Callback func(Event)
|
||||
type Callback func(ircmsg.Message)
|
||||
|
||||
type callbackPair struct {
|
||||
id uint64
|
||||
|
@ -65,7 +65,7 @@ type Connection struct {
|
|||
|
||||
// networking and synchronization
|
||||
stateMutex sync.Mutex // innermost mutex: don't block while holding this
|
||||
end chan empty // closing this causes the goroutines to exit (think threading.Event)
|
||||
end chan empty // closing this causes the goroutines to exit
|
||||
pwrite chan []byte // receives IRC lines to be sent to the socket
|
||||
wg sync.WaitGroup // after closing end, wait on this for all the goroutines to stop
|
||||
socket net.Conn
|
||||
|
@ -123,74 +123,40 @@ type pendingLabel struct {
|
|||
callback LabelCallback
|
||||
}
|
||||
|
||||
// Event represents an individual IRC line.
|
||||
type Event struct {
|
||||
ircmsg.IRCMessage
|
||||
}
|
||||
|
||||
// Batch represents an IRCv3 batch, or a line within one. There are
|
||||
// two cases:
|
||||
// 1. (Batch).Command == "BATCH". This indicates the start of an IRCv3
|
||||
// batch; the embedded IRCMessage is the initial BATCH command, which
|
||||
// batch; the embedded Message is the initial BATCH command, which
|
||||
// may contain tags that pertain to the batch as a whole. (Batch).Items
|
||||
// contains zero or more *Batch elements, pointing to the contents of
|
||||
// the batch in order.
|
||||
// 2. (Batch).Command != "BATCH". This is an ordinary IRC line; its
|
||||
// tags, command, and parameters are available as members of the embedded
|
||||
// IRCMessage.
|
||||
// Message.
|
||||
// In the context of labeled-response, there is a third case: a `nil`
|
||||
// value of *Batch indicates that the server failed to respond in time.
|
||||
type Batch struct {
|
||||
ircmsg.IRCMessage
|
||||
ircmsg.Message
|
||||
Items []*Batch
|
||||
}
|
||||
|
||||
// Retrieve the last message from Event arguments.
|
||||
// This function leaves the arguments untouched and
|
||||
// returns an empty string if there are none.
|
||||
func (e *Event) Message() string {
|
||||
if len(e.Params) == 0 {
|
||||
return ""
|
||||
}
|
||||
return e.Params[len(e.Params)-1]
|
||||
}
|
||||
|
||||
/*
|
||||
// https://stackoverflow.com/a/10567935/6754440
|
||||
// Regex of IRC formatting.
|
||||
var ircFormat = regexp.MustCompile(`[\x02\x1F\x0F\x16\x1D\x1E]|\x03(\d\d?(,\d\d?)?)?`)
|
||||
|
||||
// Retrieve the last message from Event arguments, but without IRC formatting (color.
|
||||
// This function leaves the arguments untouched and
|
||||
// returns an empty string if there are none.
|
||||
func (e *Event) MessageWithoutFormat() string {
|
||||
if len(e.Arguments) == 0 {
|
||||
return ""
|
||||
}
|
||||
return ircFormat.ReplaceAllString(e.Arguments[len(e.Arguments)-1], "")
|
||||
}
|
||||
*/
|
||||
|
||||
func (e *Event) Nick() string {
|
||||
nick, _, _ := e.splitNUH()
|
||||
func ExtractNick(source string) string {
|
||||
nick, _, _ := SplitNUH(source)
|
||||
return nick
|
||||
}
|
||||
|
||||
func (e *Event) User() string {
|
||||
_, user, _ := e.splitNUH()
|
||||
return user
|
||||
}
|
||||
|
||||
func (e *Event) Host() string {
|
||||
_, _, host := e.splitNUH()
|
||||
return host
|
||||
}
|
||||
|
||||
func (event *Event) splitNUH() (nick, user, host string) {
|
||||
if i, j := strings.Index(event.Prefix, "!"), strings.Index(event.Prefix, "@"); i > -1 && j > -1 && i < j {
|
||||
nick = event.Prefix[0:i]
|
||||
user = event.Prefix[i+1 : j]
|
||||
host = event.Prefix[j+1:]
|
||||
func SplitNUH(source string) (nick, user, host string) {
|
||||
if i, j := strings.Index(source, "!"), strings.Index(source, "@"); i > -1 && j > -1 && i < j {
|
||||
nick = source[0:i]
|
||||
user = source[i+1 : j]
|
||||
host = source[j+1:]
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func lastParam(msg *ircmsg.Message) (result string) {
|
||||
if 0 < len(msg.Params) {
|
||||
return msg.Params[len(msg.Params)-1]
|
||||
}
|
||||
return
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ func connForTesting(nick, user string, tls bool) *Connection {
|
|||
return irc
|
||||
}
|
||||
|
||||
func mockEvent(command string) ircmsg.IRCMessage {
|
||||
func mockEvent(command string) ircmsg.Message {
|
||||
return ircmsg.MakeMessage(nil, ":server.name", command)
|
||||
}
|
||||
|
||||
|
@ -37,9 +37,9 @@ func TestRemoveCallback(t *testing.T) {
|
|||
|
||||
done := make(chan int, 10)
|
||||
|
||||
irccon.AddCallback("TEST", func(e Event) { done <- 1 })
|
||||
id := irccon.AddCallback("TEST", func(e Event) { done <- 2 })
|
||||
irccon.AddCallback("TEST", func(e Event) { done <- 3 })
|
||||
irccon.AddCallback("TEST", func(e ircmsg.Message) { done <- 1 })
|
||||
id := irccon.AddCallback("TEST", func(e ircmsg.Message) { done <- 2 })
|
||||
irccon.AddCallback("TEST", func(e ircmsg.Message) { done <- 3 })
|
||||
|
||||
// Should remove callback at index 1
|
||||
irccon.RemoveCallback(id)
|
||||
|
@ -62,11 +62,11 @@ func TestClearCallback(t *testing.T) {
|
|||
|
||||
done := make(chan int, 10)
|
||||
|
||||
irccon.AddCallback("TEST", func(e Event) { done <- 0 })
|
||||
irccon.AddCallback("TEST", func(e Event) { done <- 1 })
|
||||
irccon.AddCallback("TEST", func(e ircmsg.Message) { done <- 0 })
|
||||
irccon.AddCallback("TEST", func(e ircmsg.Message) { done <- 1 })
|
||||
irccon.ClearCallback("TEST")
|
||||
irccon.AddCallback("TEST", func(e Event) { done <- 2 })
|
||||
irccon.AddCallback("TEST", func(e Event) { done <- 3 })
|
||||
irccon.AddCallback("TEST", func(e ircmsg.Message) { done <- 2 })
|
||||
irccon.AddCallback("TEST", func(e ircmsg.Message) { done <- 3 })
|
||||
|
||||
irccon.runCallbacks(mockEvent("TEST"))
|
||||
|
||||
|
@ -106,10 +106,10 @@ func TestConnection(t *testing.T) {
|
|||
teststr := randStr(20)
|
||||
testmsgok := make(chan bool, 1)
|
||||
|
||||
irccon1.AddCallback("001", func(e Event) { irccon1.Join(channel) })
|
||||
irccon2.AddCallback("001", func(e Event) { irccon2.Join(channel) })
|
||||
irccon1.AddCallback("366", func(e Event) {
|
||||
go func(e Event) {
|
||||
irccon1.AddCallback("001", func(e ircmsg.Message) { irccon1.Join(channel) })
|
||||
irccon2.AddCallback("001", func(e ircmsg.Message) { irccon2.Join(channel) })
|
||||
irccon1.AddCallback("366", func(e ircmsg.Message) {
|
||||
go func(e ircmsg.Message) {
|
||||
tick := time.NewTicker(1 * time.Second)
|
||||
i := 10
|
||||
for {
|
||||
|
@ -131,14 +131,14 @@ func TestConnection(t *testing.T) {
|
|||
}(e)
|
||||
})
|
||||
|
||||
irccon2.AddCallback("366", func(e Event) {
|
||||
irccon2.AddCallback("366", func(e ircmsg.Message) {
|
||||
ircnick2 = randStr(8)
|
||||
irccon2.SetNick(ircnick2)
|
||||
})
|
||||
|
||||
irccon2.AddCallback("PRIVMSG", func(e Event) {
|
||||
if e.Message() == teststr {
|
||||
if e.Nick() == ircnick1 {
|
||||
irccon2.AddCallback("PRIVMSG", func(e ircmsg.Message) {
|
||||
if e.Params[1] == teststr {
|
||||
if ExtractNick(e.Prefix) == ircnick1 {
|
||||
testmsgok <- true
|
||||
irccon2.Quit()
|
||||
} else {
|
||||
|
@ -150,8 +150,8 @@ func TestConnection(t *testing.T) {
|
|||
}
|
||||
})
|
||||
|
||||
irccon2.AddCallback("NICK", func(e Event) {
|
||||
if !(e.Nick() == ircnick2orig && e.Message() == ircnick2) {
|
||||
irccon2.AddCallback("NICK", func(e ircmsg.Message) {
|
||||
if !(ExtractNick(e.Prefix) == ircnick2orig && e.Params[0] == ircnick2) {
|
||||
t.Errorf("Nick change did not work!")
|
||||
}
|
||||
})
|
||||
|
@ -181,9 +181,9 @@ func runReconnectTest(useSASL bool, t *testing.T) {
|
|||
debugTest(irccon)
|
||||
|
||||
connects := 0
|
||||
irccon.AddCallback("001", func(e Event) { irccon.Join(channel) })
|
||||
irccon.AddCallback("001", func(e ircmsg.Message) { irccon.Join(channel) })
|
||||
|
||||
irccon.AddCallback("366", func(e Event) {
|
||||
irccon.AddCallback("366", func(e ircmsg.Message) {
|
||||
connects += 1
|
||||
if connects > 2 {
|
||||
irccon.Privmsgf(channel, "Connection nr %d (test done)", connects)
|
||||
|
@ -226,9 +226,9 @@ func TestConnectionSSL(t *testing.T) {
|
|||
debugTest(irccon)
|
||||
irccon.UseTLS = true
|
||||
irccon.TLSConfig = &tls.Config{InsecureSkipVerify: true}
|
||||
irccon.AddCallback("001", func(e Event) { irccon.Join(channel) })
|
||||
irccon.AddCallback("001", func(e ircmsg.Message) { irccon.Join(channel) })
|
||||
|
||||
irccon.AddCallback("366", func(e Event) {
|
||||
irccon.AddCallback("366", func(e ircmsg.Message) {
|
||||
irccon.Privmsg(channel, "Test Message from SSL")
|
||||
irccon.Quit()
|
||||
})
|
||||
|
@ -284,8 +284,8 @@ func TestConnectionNickInUse(t *testing.T) {
|
|||
n2 := make(chan string, 1)
|
||||
|
||||
// check the actual nick after 001 is processed
|
||||
irccon1.AddCallback("002", func(e Event) { n1 <- irccon1.CurrentNick() })
|
||||
irccon2.AddCallback("002", func(e Event) { n2 <- irccon2.CurrentNick() })
|
||||
irccon1.AddCallback("002", func(e ircmsg.Message) { n1 <- irccon1.CurrentNick() })
|
||||
irccon2.AddCallback("002", func(e ircmsg.Message) { n2 <- irccon2.CurrentNick() })
|
||||
|
||||
err := irccon1.Connect()
|
||||
if err != nil {
|
||||
|
@ -318,7 +318,7 @@ func TestConnectionCallbacks(t *testing.T) {
|
|||
irccon1 := connForTesting(ircnick, "IRCTest1", false)
|
||||
debugTest(irccon1)
|
||||
resultChan := make(chan map[string]string, 1)
|
||||
irccon1.AddConnectCallback(func(e Event) {
|
||||
irccon1.AddConnectCallback(func(e ircmsg.Message) {
|
||||
resultChan <- irccon1.ISupport()
|
||||
})
|
||||
err := irccon1.Connect()
|
||||
|
|
|
@ -61,10 +61,10 @@ var (
|
|||
ErrorBadParam = errors.New("Cannot have an empty param, a param with spaces, or a param that starts with ':' before the last parameter")
|
||||
)
|
||||
|
||||
// IRCMessage represents an IRC message, as defined by the RFCs and as
|
||||
// Message represents an IRC message, as defined by the RFCs and as
|
||||
// extended by the IRCv3 Message Tags specification with the introduction
|
||||
// of message tags.
|
||||
type IRCMessage struct {
|
||||
type Message struct {
|
||||
Prefix string
|
||||
Command string
|
||||
Params []string
|
||||
|
@ -77,12 +77,12 @@ type IRCMessage struct {
|
|||
// will be encoded as a "trailing parameter" (preceded by a colon). This is
|
||||
// almost never necessary and should not be used except when having to interact
|
||||
// with broken implementations that don't correctly interpret IRC messages.
|
||||
func (msg *IRCMessage) ForceTrailing() {
|
||||
func (msg *Message) ForceTrailing() {
|
||||
msg.forceTrailing = true
|
||||
}
|
||||
|
||||
// GetTag returns whether a tag is present, and if so, what its value is.
|
||||
func (msg *IRCMessage) GetTag(tagName string) (present bool, value string) {
|
||||
func (msg *Message) GetTag(tagName string) (present bool, value string) {
|
||||
if len(tagName) == 0 {
|
||||
return
|
||||
} else if tagName[0] == '+' {
|
||||
|
@ -95,13 +95,13 @@ func (msg *IRCMessage) GetTag(tagName string) (present bool, value string) {
|
|||
}
|
||||
|
||||
// HasTag returns whether a tag is present.
|
||||
func (msg *IRCMessage) HasTag(tagName string) (present bool) {
|
||||
func (msg *Message) HasTag(tagName string) (present bool) {
|
||||
present, _ = msg.GetTag(tagName)
|
||||
return
|
||||
}
|
||||
|
||||
// SetTag sets a tag.
|
||||
func (msg *IRCMessage) SetTag(tagName, tagValue string) {
|
||||
func (msg *Message) SetTag(tagName, tagValue string) {
|
||||
if len(tagName) == 0 {
|
||||
return
|
||||
} else if tagName[0] == '+' {
|
||||
|
@ -118,7 +118,7 @@ func (msg *IRCMessage) SetTag(tagName, tagValue string) {
|
|||
}
|
||||
|
||||
// DeleteTag deletes a tag.
|
||||
func (msg *IRCMessage) DeleteTag(tagName string) {
|
||||
func (msg *Message) DeleteTag(tagName string) {
|
||||
if len(tagName) == 0 {
|
||||
return
|
||||
} else if tagName[0] == '+' {
|
||||
|
@ -129,14 +129,14 @@ func (msg *IRCMessage) DeleteTag(tagName string) {
|
|||
}
|
||||
|
||||
// UpdateTags is a convenience to set multiple tags at once.
|
||||
func (msg *IRCMessage) UpdateTags(tags map[string]string) {
|
||||
func (msg *Message) UpdateTags(tags map[string]string) {
|
||||
for name, value := range tags {
|
||||
msg.SetTag(name, value)
|
||||
}
|
||||
}
|
||||
|
||||
// AllTags returns all tags as a single map.
|
||||
func (msg *IRCMessage) AllTags() (result map[string]string) {
|
||||
func (msg *Message) AllTags() (result map[string]string) {
|
||||
result = make(map[string]string, len(msg.tags)+len(msg.clientOnlyTags))
|
||||
for name, value := range msg.tags {
|
||||
result[name] = value
|
||||
|
@ -148,23 +148,23 @@ func (msg *IRCMessage) AllTags() (result map[string]string) {
|
|||
}
|
||||
|
||||
// ClientOnlyTags returns the client-only tags (the tags with the + prefix).
|
||||
// The returned map may be internal storage of the IRCMessage object and
|
||||
// The returned map may be internal storage of the Message object and
|
||||
// should not be modified.
|
||||
func (msg *IRCMessage) ClientOnlyTags() map[string]string {
|
||||
func (msg *Message) ClientOnlyTags() map[string]string {
|
||||
return msg.clientOnlyTags
|
||||
}
|
||||
|
||||
// ParseLine creates and returns a message from the given IRC line.
|
||||
func ParseLine(line string) (ircmsg IRCMessage, err error) {
|
||||
func ParseLine(line string) (ircmsg Message, err error) {
|
||||
return parseLine(line, 0, 0)
|
||||
}
|
||||
|
||||
// ParseLineStrict creates and returns an IRCMessage from the given IRC line,
|
||||
// ParseLineStrict creates and returns an Message from the given IRC line,
|
||||
// taking the maximum length into account and truncating the message as appropriate.
|
||||
// If fromClient is true, it enforces the client limit on tag data length (4094 bytes),
|
||||
// allowing the server to return ERR_INPUTTOOLONG as appropriate. If truncateLen is
|
||||
// nonzero, it is the length at which the non-tag portion of the message is truncated.
|
||||
func ParseLineStrict(line string, fromClient bool, truncateLen int) (ircmsg IRCMessage, err error) {
|
||||
func ParseLineStrict(line string, fromClient bool, truncateLen int) (ircmsg Message, err error) {
|
||||
maxTagDataLength := MaxlenTagData
|
||||
if fromClient {
|
||||
maxTagDataLength = MaxlenClientTagData
|
||||
|
@ -180,7 +180,7 @@ func trimInitialSpaces(str string) string {
|
|||
return str[i:]
|
||||
}
|
||||
|
||||
func parseLine(line string, maxTagDataLength int, truncateLen int) (ircmsg IRCMessage, err error) {
|
||||
func parseLine(line string, maxTagDataLength int, truncateLen int) (ircmsg Message, err error) {
|
||||
// remove either \n or \r\n from the end of the line:
|
||||
line = strings.TrimSuffix(line, "\n")
|
||||
line = strings.TrimSuffix(line, "\r")
|
||||
|
@ -279,7 +279,7 @@ func parseLine(line string, maxTagDataLength int, truncateLen int) (ircmsg IRCMe
|
|||
}
|
||||
|
||||
// helper to parse tags
|
||||
func (ircmsg *IRCMessage) parseTags(tags string) (err error) {
|
||||
func (ircmsg *Message) parseTags(tags string) (err error) {
|
||||
for 0 < len(tags) {
|
||||
tagEnd := strings.IndexByte(tags, ';')
|
||||
endPos := tagEnd
|
||||
|
@ -311,8 +311,8 @@ func (ircmsg *IRCMessage) parseTags(tags string) (err error) {
|
|||
return nil
|
||||
}
|
||||
|
||||
// MakeMessage provides a simple way to create a new IRCMessage.
|
||||
func MakeMessage(tags map[string]string, prefix string, command string, params ...string) (ircmsg IRCMessage) {
|
||||
// MakeMessage provides a simple way to create a new Message.
|
||||
func MakeMessage(tags map[string]string, prefix string, command string, params ...string) (ircmsg Message) {
|
||||
ircmsg.Prefix = prefix
|
||||
ircmsg.Command = command
|
||||
ircmsg.Params = params
|
||||
|
@ -320,8 +320,8 @@ func MakeMessage(tags map[string]string, prefix string, command string, params .
|
|||
return ircmsg
|
||||
}
|
||||
|
||||
// Line returns a sendable line created from an IRCMessage.
|
||||
func (ircmsg *IRCMessage) Line() (result string, err error) {
|
||||
// Line returns a sendable line created from an Message.
|
||||
func (ircmsg *Message) Line() (result string, err error) {
|
||||
bytes, err := ircmsg.line(0, 0, 0, 0)
|
||||
if err == nil {
|
||||
result = string(bytes)
|
||||
|
@ -329,17 +329,17 @@ func (ircmsg *IRCMessage) Line() (result string, err error) {
|
|||
return
|
||||
}
|
||||
|
||||
// LineBytes returns a sendable line created from an IRCMessage.
|
||||
func (ircmsg *IRCMessage) LineBytes() (result []byte, err error) {
|
||||
// LineBytes returns a sendable line created from an Message.
|
||||
func (ircmsg *Message) LineBytes() (result []byte, err error) {
|
||||
result, err = ircmsg.line(0, 0, 0, 0)
|
||||
return
|
||||
}
|
||||
|
||||
// LineBytesStrict returns a sendable line, as a []byte, created from an IRCMessage.
|
||||
// LineBytesStrict returns a sendable line, as a []byte, created from an Message.
|
||||
// fromClient controls whether the server-side or client-side tag length limit
|
||||
// is enforced. If truncateLen is nonzero, it is the length at which the
|
||||
// non-tag portion of the message is truncated.
|
||||
func (ircmsg *IRCMessage) LineBytesStrict(fromClient bool, truncateLen int) ([]byte, error) {
|
||||
func (ircmsg *Message) LineBytesStrict(fromClient bool, truncateLen int) ([]byte, error) {
|
||||
var tagLimit, clientOnlyTagDataLimit, serverAddedTagDataLimit int
|
||||
if fromClient {
|
||||
// enforce client max tags:
|
||||
|
@ -359,8 +359,8 @@ func paramRequiresTrailing(param string) bool {
|
|||
return len(param) == 0 || strings.IndexByte(param, ' ') != -1 || param[0] == ':'
|
||||
}
|
||||
|
||||
// line returns a sendable line created from an IRCMessage.
|
||||
func (ircmsg *IRCMessage) line(tagLimit, clientOnlyTagDataLimit, serverAddedTagDataLimit, truncateLen int) (result []byte, err error) {
|
||||
// line returns a sendable line created from an Message.
|
||||
func (ircmsg *Message) line(tagLimit, clientOnlyTagDataLimit, serverAddedTagDataLimit, truncateLen int) (result []byte, err error) {
|
||||
if len(ircmsg.Command) == 0 {
|
||||
return nil, ErrorCommandMissing
|
||||
}
|
||||
|
|
|
@ -11,12 +11,12 @@ import (
|
|||
|
||||
type testcode struct {
|
||||
raw string
|
||||
message IRCMessage
|
||||
message Message
|
||||
}
|
||||
type testcodewithlen struct {
|
||||
raw string
|
||||
length int
|
||||
message IRCMessage
|
||||
message Message
|
||||
truncateExpected bool
|
||||
}
|
||||
|
||||
|
@ -256,7 +256,7 @@ func TestEncodeErrors(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
var testMessages = []IRCMessage{
|
||||
var testMessages = []Message{
|
||||
{
|
||||
tags: map[string]string{"time": "2019-02-27T04:38:57.489Z", "account": "dan-"},
|
||||
clientOnlyTags: map[string]string{"+status": "typing"},
|
||||
|
@ -329,7 +329,7 @@ func TestEncodeDecode(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestForceTrailing(t *testing.T) {
|
||||
message := IRCMessage{
|
||||
message := Message{
|
||||
Prefix: "shivaram",
|
||||
Command: "PRIVMSG",
|
||||
Params: []string{"#darwin", "nice"},
|
||||
|
@ -352,7 +352,7 @@ func TestForceTrailing(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestErrorLineTooLongGeneration(t *testing.T) {
|
||||
message := IRCMessage{
|
||||
message := Message{
|
||||
tags: map[string]string{"draft/msgid": "SAXV5OYJUr18CNJzdWa1qQ"},
|
||||
Prefix: "shivaram",
|
||||
Command: "PRIVMSG",
|
||||
|
|
|
@ -30,7 +30,7 @@ func init() {
|
|||
// EscapeTagValue takes a value, and returns an escaped message tag value.
|
||||
//
|
||||
// This function is automatically used when lines are created from an
|
||||
// IRCMessage, so you don't need to call it yourself before creating a line.
|
||||
// Message, so you don't need to call it yourself before creating a line.
|
||||
func EscapeTagValue(inString string) string {
|
||||
return valtoescape.Replace(inString)
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ import (
|
|||
)
|
||||
|
||||
/*
|
||||
IRCReader is an optimized line reader for IRC lines containing tags;
|
||||
Reader is an optimized line reader for IRC lines containing tags;
|
||||
most IRC lines will not approach the maximum line length (8191 bytes
|
||||
of tag data, plus 512 bytes of message data), so we want a buffered
|
||||
reader that can start with a smaller buffer and expand if necessary,
|
||||
|
@ -21,7 +21,7 @@ var (
|
|||
ErrReadQ = errors.New("readQ exceeded (read too many bytes without terminating newline)")
|
||||
)
|
||||
|
||||
type IRCReader struct {
|
||||
type Reader struct {
|
||||
conn io.Reader
|
||||
|
||||
initialSize int
|
||||
|
@ -34,17 +34,17 @@ type IRCReader struct {
|
|||
eof bool
|
||||
}
|
||||
|
||||
// Returns a new *IRCReader with sane buffer size limits.
|
||||
func NewIRCReader(conn io.Reader) *IRCReader {
|
||||
var reader IRCReader
|
||||
// Returns a new *Reader with sane buffer size limits.
|
||||
func NewIRCReader(conn io.Reader) *Reader {
|
||||
var reader Reader
|
||||
reader.Initialize(conn, 512, 8192+1024)
|
||||
return &reader
|
||||
}
|
||||
|
||||
// "Placement new" for an IRCReader; initializes it with custom buffer size
|
||||
// "Placement new" for a Reader; initializes it with custom buffer size
|
||||
// limits.
|
||||
func (cc *IRCReader) Initialize(conn io.Reader, initialSize, maxSize int) {
|
||||
*cc = IRCReader{}
|
||||
func (cc *Reader) Initialize(conn io.Reader, initialSize, maxSize int) {
|
||||
*cc = Reader{}
|
||||
cc.conn = conn
|
||||
cc.initialSize = initialSize
|
||||
cc.maxSize = maxSize
|
||||
|
@ -54,7 +54,7 @@ func (cc *IRCReader) Initialize(conn io.Reader, initialSize, maxSize int) {
|
|||
// or \r\n as the line terminator (but not \r in isolation). Passes through
|
||||
// errors from the underlying connection. Returns ErrReadQ if the buffer limit
|
||||
// was exceeded without a terminating \n.
|
||||
func (cc *IRCReader) ReadLine() ([]byte, error) {
|
||||
func (cc *Reader) ReadLine() ([]byte, error) {
|
||||
for {
|
||||
// try to find a terminated line in the buffered data already read
|
||||
nlidx := bytes.IndexByte(cc.buf[cc.searchFrom:cc.end], '\n')
|
||||
|
|
|
@ -158,7 +158,7 @@ func TestRegression(t *testing.T) {
|
|||
// this terminates the previous read, within the acceptable limit:
|
||||
c.reads = append(c.reads, makeLine(500, true))
|
||||
|
||||
var cc IRCReader
|
||||
var cc Reader
|
||||
cc.Initialize(&c, 512, 4096+512)
|
||||
|
||||
line, err := cc.ReadLine()
|
||||
|
|
Loading…
Reference in New Issue