aboutsummaryrefslogtreecommitdiff
path: root/vendor/github.com/belak/irc/parser.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/belak/irc/parser.go')
-rw-r--r--vendor/github.com/belak/irc/parser.go394
1 files changed, 0 insertions, 394 deletions
diff --git a/vendor/github.com/belak/irc/parser.go b/vendor/github.com/belak/irc/parser.go
deleted file mode 100644
index 819de4d..0000000
--- a/vendor/github.com/belak/irc/parser.go
+++ /dev/null
@@ -1,394 +0,0 @@
-package irc
-
-import (
- "bytes"
- "errors"
- "strings"
-)
-
-var tagDecodeSlashMap = map[rune]rune{
- ':': ';',
- 's': ' ',
- '\\': '\\',
- 'r': '\r',
- 'n': '\n',
-}
-
-var tagEncodeMap = map[rune]string{
- ';': "\\:",
- ' ': "\\s",
- '\\': "\\\\",
- '\r': "\\r",
- '\n': "\\n",
-}
-
-var (
- // ErrZeroLengthMessage is returned when parsing if the input is
- // zero-length.
- ErrZeroLengthMessage = errors.New("irc: Cannot parse zero-length message")
-
- // ErrMissingDataAfterPrefix is returned when parsing if there is
- // no message data after the prefix.
- ErrMissingDataAfterPrefix = errors.New("irc: No message data after prefix")
-
- // ErrMissingDataAfterTags is returned when parsing if there is no
- // message data after the tags.
- ErrMissingDataAfterTags = errors.New("irc: No message data after tags")
-
- // ErrMissingCommand is returned when parsing if there is no
- // command in the parsed message.
- ErrMissingCommand = errors.New("irc: Missing message command")
-)
-
-// TagValue represents the value of a tag.
-type TagValue string
-
-// ParseTagValue parses a TagValue from the connection. If you need to
-// set a TagValue, you probably want to just set the string itself, so
-// it will be encoded properly.
-func ParseTagValue(v string) TagValue {
- ret := &bytes.Buffer{}
-
- input := bytes.NewBufferString(v)
-
- for {
- c, _, err := input.ReadRune()
- if err != nil {
- break
- }
-
- if c == '\\' {
- c2, _, err := input.ReadRune()
-
- // If we got a backslash then the end of the tag value, we should
- // just ignore the backslash.
- if err != nil {
- break
- }
-
- if replacement, ok := tagDecodeSlashMap[c2]; ok {
- ret.WriteRune(replacement)
- } else {
- ret.WriteRune(c2)
- }
- } else {
- ret.WriteRune(c)
- }
- }
-
- return TagValue(ret.String())
-}
-
-// Encode converts a TagValue to the format in the connection.
-func (v TagValue) Encode() string {
- ret := &bytes.Buffer{}
-
- for _, c := range v {
- if replacement, ok := tagEncodeMap[c]; ok {
- ret.WriteString(replacement)
- } else {
- ret.WriteRune(c)
- }
- }
-
- return ret.String()
-}
-
-// Tags represents the IRCv3 message tags.
-type Tags map[string]TagValue
-
-// ParseTags takes a tag string and parses it into a tag map. It will
-// always return a tag map, even if there are no valid tags.
-func ParseTags(line string) Tags {
- ret := Tags{}
-
- tags := strings.Split(line, ";")
- for _, tag := range tags {
- parts := strings.SplitN(tag, "=", 2)
- if len(parts) < 2 {
- ret[parts[0]] = ""
- continue
- }
-
- ret[parts[0]] = ParseTagValue(parts[1])
- }
-
- return ret
-}
-
-// GetTag is a convenience method to look up a tag in the map.
-func (t Tags) GetTag(key string) (string, bool) {
- ret, ok := t[key]
- return string(ret), ok
-}
-
-// Copy will create a new copy of all IRC tags attached to this
-// message.
-func (t Tags) Copy() Tags {
- ret := Tags{}
-
- for k, v := range t {
- ret[k] = v
- }
-
- return ret
-}
-
-// String ensures this is stringable
-func (t Tags) String() string {
- buf := &bytes.Buffer{}
-
- for k, v := range t {
- buf.WriteByte(';')
- buf.WriteString(k)
- if v != "" {
- buf.WriteByte('=')
- buf.WriteString(v.Encode())
- }
- }
-
- // We don't need the first byte because that's an extra ';'
- // character.
- buf.ReadByte()
-
- return buf.String()
-}
-
-// Prefix represents the prefix of a message, generally the user who sent it
-type Prefix struct {
- // Name will contain the nick of who sent the message, the
- // server who sent the message, or a blank string
- Name string
-
- // User will either contain the user who sent the message or a blank string
- User string
-
- // Host will either contain the host of who sent the message or a blank string
- Host string
-}
-
-// ParsePrefix takes an identity string and parses it into an
-// identity struct. It will always return an Prefix struct and never
-// nil.
-func ParsePrefix(line string) *Prefix {
- // Start by creating an Prefix with nothing but the host
- id := &Prefix{
- Name: line,
- }
-
- uh := strings.SplitN(id.Name, "@", 2)
- if len(uh) == 2 {
- id.Name, id.Host = uh[0], uh[1]
- }
-
- nu := strings.SplitN(id.Name, "!", 2)
- if len(nu) == 2 {
- id.Name, id.User = nu[0], nu[1]
- }
-
- return id
-}
-
-// Copy will create a new copy of an Prefix
-func (p *Prefix) Copy() *Prefix {
- if p == nil {
- return nil
- }
-
- newPrefix := &Prefix{}
-
- *newPrefix = *p
-
- return newPrefix
-}
-
-// String ensures this is stringable
-func (p *Prefix) String() string {
- buf := &bytes.Buffer{}
- buf.WriteString(p.Name)
-
- if p.User != "" {
- buf.WriteString("!")
- buf.WriteString(p.User)
- }
-
- if p.Host != "" {
- buf.WriteString("@")
- buf.WriteString(p.Host)
- }
-
- return buf.String()
-}
-
-// Message represents a line parsed from the server
-type Message struct {
- // Each message can have IRCv3 tags
- Tags
-
- // Each message can have a Prefix
- *Prefix
-
- // Command is which command is being called.
- Command string
-
- // Params are all the arguments for the command.
- Params []string
-}
-
-// MustParseMessage calls ParseMessage and either returns the message
-// or panics if an error is returned.
-func MustParseMessage(line string) *Message {
- m, err := ParseMessage(line)
- if err != nil {
- panic(err.Error())
- }
- return m
-}
-
-// ParseMessage takes a message string (usually a whole line) and
-// parses it into a Message struct. This will return nil in the case
-// of invalid messages.
-func ParseMessage(line string) (*Message, error) {
- // Trim the line and make sure we have data
- line = strings.TrimRight(line, "\r\n")
- if len(line) == 0 {
- return nil, ErrZeroLengthMessage
- }
-
- c := &Message{
- Tags: Tags{},
- Prefix: &Prefix{},
- }
-
- if line[0] == '@' {
- split := strings.SplitN(line, " ", 2)
- if len(split) < 2 {
- return nil, ErrMissingDataAfterTags
- }
-
- c.Tags = ParseTags(split[0][1:])
- line = split[1]
- }
-
- if line[0] == ':' {
- split := strings.SplitN(line, " ", 2)
- if len(split) < 2 {
- return nil, ErrMissingDataAfterPrefix
- }
-
- // Parse the identity, if there was one
- c.Prefix = ParsePrefix(split[0][1:])
- line = split[1]
- }
-
- // Split out the trailing then the rest of the args. Because
- // we expect there to be at least one result as an arg (the
- // command) we don't need to special case the trailing arg and
- // can just attempt a split on " :"
- split := strings.SplitN(line, " :", 2)
- c.Params = strings.FieldsFunc(split[0], func(r rune) bool {
- return r == ' '
- })
-
- // If there are no args, we need to bail because we need at
- // least the command.
- if len(c.Params) == 0 {
- return nil, ErrMissingCommand
- }
-
- // If we had a trailing arg, append it to the other args
- if len(split) == 2 {
- c.Params = append(c.Params, split[1])
- }
-
- // Because of how it's parsed, the Command will show up as the
- // first arg.
- c.Command = strings.ToUpper(c.Params[0])
- c.Params = c.Params[1:]
-
- // If there are no params, set it to nil, to make writing tests and other
- // things simpler.
- if len(c.Params) == 0 {
- c.Params = nil
- }
-
- return c, nil
-}
-
-// Trailing returns the last argument in the Message or an empty string
-// if there are no args
-func (m *Message) Trailing() string {
- if len(m.Params) < 1 {
- return ""
- }
-
- return m.Params[len(m.Params)-1]
-}
-
-// Copy will create a new copy of an message
-func (m *Message) Copy() *Message {
- // Create a new message
- newMessage := &Message{}
-
- // Copy stuff from the old message
- *newMessage = *m
-
- // Copy any IRcv3 tags
- newMessage.Tags = m.Tags.Copy()
-
- // Copy the Prefix
- newMessage.Prefix = m.Prefix.Copy()
-
- // Copy the Params slice
- newMessage.Params = append(make([]string, 0, len(m.Params)), m.Params...)
-
- // Similar to parsing, if Params is empty, set it to nil
- if len(newMessage.Params) == 0 {
- newMessage.Params = nil
- }
-
- return newMessage
-}
-
-// String ensures this is stringable
-func (m *Message) String() string {
- buf := &bytes.Buffer{}
-
- // Write any IRCv3 tags if they exist in the message
- if len(m.Tags) > 0 {
- buf.WriteByte('@')
- buf.WriteString(m.Tags.String())
- buf.WriteByte(' ')
- }
-
- // Add the prefix if we have one
- if m.Prefix != nil && m.Prefix.Name != "" {
- buf.WriteByte(':')
- buf.WriteString(m.Prefix.String())
- buf.WriteByte(' ')
- }
-
- // Add the command since we know we'll always have one
- buf.WriteString(m.Command)
-
- if len(m.Params) > 0 {
- args := m.Params[:len(m.Params)-1]
- trailing := m.Params[len(m.Params)-1]
-
- if len(args) > 0 {
- buf.WriteByte(' ')
- buf.WriteString(strings.Join(args, " "))
- }
-
- // If trailing is zero-length, contains a space or starts with
- // a : we need to actually specify that it's trailing.
- if len(trailing) == 0 || strings.ContainsRune(trailing, ' ') || trailing[0] == ':' {
- buf.WriteString(" :")
- } else {
- buf.WriteString(" ")
- }
- buf.WriteString(trailing)
- }
-
- return buf.String()
-}