kunt

golang IRC bot
git clone git://git.2f30.org/kunt
Log | Files | Refs | LICENSE

message.go (3623B)


      1 // Copyright 2013 TLH and dsp. All rights reserved.
      2 // Use of this source code is governed by a BSD-style
      3 // license that can be found in the LICENSE file.
      4 
      5 package irc
      6 
      7 import (
      8 	"fmt"
      9 	"strings"
     10 )
     11 
     12 type Message struct {
     13 	Command string
     14 	Raw     string
     15 	Nick    string
     16 	Host    string
     17 	Source  string
     18 	User    string
     19 	Args    []string
     20 }
     21 
     22 func (i *Context) Pong(host string) {
     23 	msg := Message{
     24 		Command: "PONG",
     25 		Args:    []string{":" + host},
     26 	}
     27 	i.outgoingMsg <- msg
     28 }
     29 
     30 func (i *Context) Pass() {
     31 	msg := Message{
     32 		Command: "PASS",
     33 		Args:    []string{i.network.pass},
     34 	}
     35 	i.outgoingMsg <- msg
     36 }
     37 
     38 func (i *Context) Nick() {
     39 	msg := Message{
     40 		Command: "NICK",
     41 		Args:    []string{i.network.nick},
     42 	}
     43 	i.outgoingMsg <- msg
     44 }
     45 
     46 func (i *Context) User() {
     47 	msg := Message{
     48 		Command: "USER",
     49 		Args: []string{
     50 			i.network.user,
     51 			"* 8",
     52 			":" + i.network.realName,
     53 		},
     54 	}
     55 	i.outgoingMsg <- msg
     56 }
     57 
     58 func (i *Context) Join(channel string, key string) {
     59 	msg := Message{
     60 		Command: "JOIN",
     61 		Args:    []string{channel, key},
     62 	}
     63 	i.outgoingMsg <- msg
     64 }
     65 
     66 func (i *Context) Part(channel string, text string) {
     67 	msg := Message{
     68 		Command: "PART",
     69 		Args: []string{
     70 			channel,
     71 			":" + text,
     72 		},
     73 	}
     74 	i.outgoingMsg <- msg
     75 }
     76 
     77 func (i *Context) Quit(text string) {
     78 	msg := Message{
     79 		Command: "QUIT",
     80 		Args:    []string{":" + text},
     81 	}
     82 	i.outgoingMsg <- msg
     83 }
     84 
     85 func (i *Context) Privmsg(channel string, text string) {
     86 	msg := Message{
     87 		Command: "PRIVMSG",
     88 		Args: []string{
     89 			channel,
     90 			":" + text,
     91 		},
     92 	}
     93 	i.outgoingMsg <- msg
     94 }
     95 
     96 func (i *Context) Notice(nick string, text string) {
     97 	msg := Message{
     98 		Command: "NOTICE",
     99 		Args: []string{
    100 			nick,
    101 			":" + text,
    102 		},
    103 	}
    104 	i.outgoingMsg <- msg
    105 }
    106 
    107 func (i *Context) Topic(channel string, text string) {
    108 	msg := Message{
    109 		Command: "TOPIC",
    110 		Args: []string{
    111 			channel,
    112 			":" + text,
    113 		},
    114 	}
    115 	i.outgoingMsg <- msg
    116 }
    117 
    118 func (i *Context) ParseRawMessage(raw string) (*Message, error) {
    119 	var msg Message
    120 	msg.Raw = raw
    121 	raw = strings.TrimSpace(raw)
    122 	if raw[0] == ':' {
    123 		if i := strings.Index(raw, " "); i != -1 {
    124 			msg.Source = raw[1:i]
    125 			raw = raw[1:]
    126 		} else {
    127 			return nil, fmt.Errorf("Could not parse source, ignoring...")
    128 		}
    129 		if i := strings.Index(raw, "!"); i != -1 {
    130 			msg.Nick = raw[:i]
    131 			raw = raw[i+1:]
    132 		} else {
    133 			return nil, fmt.Errorf("Could not parse nick, ignoring...")
    134 		}
    135 		if i := strings.Index(raw, "@"); i != -1 {
    136 			msg.User = raw[:i]
    137 			raw = raw[i+1:]
    138 		} else {
    139 			return nil, fmt.Errorf("Could not parse user, ignoring...")
    140 		}
    141 		if i := strings.Index(raw, " "); i != -1 {
    142 			msg.Host = raw[:i]
    143 			raw = raw[i+1:]
    144 		} else {
    145 			return nil, fmt.Errorf("Could not parse host, ignoring...")
    146 		}
    147 	}
    148 	if i := strings.Index(raw, " "); i != -1 {
    149 		msg.Command = raw[:i]
    150 		raw = raw[i+1:]
    151 	} else {
    152 		return nil, fmt.Errorf("Could not parse command, ignoring...")
    153 	}
    154 	if raw[0] == ':' {
    155 		msg.Args = []string{raw[1:]}
    156 	} else {
    157 		msg.Args = strings.SplitN(raw, " :", 2)
    158 	}
    159 	return &msg, nil
    160 }
    161 
    162 // Unpack a message into a byte array
    163 func (i *Context) UnpackMessage(msg Message) []byte {
    164 	rawMsg := msg.Command + " " + strings.Join(msg.Args, " ")
    165 	rawMsg = strings.TrimSpace(rawMsg) + "\r\n"
    166 	return []byte(rawMsg)
    167 }
    168 
    169 func (i *Context) incomingMsgLoop() error {
    170 	for {
    171 		select {
    172 		case msg, ok := <-i.incomingMsg:
    173 			if !ok {
    174 				return nil
    175 			}
    176 			i.dispatchHandler(msg)
    177 		}
    178 	}
    179 	return nil
    180 }
    181 
    182 func (i *Context) outgoingMsgLoop() error {
    183 	for {
    184 		select {
    185 		case msg, ok := <-i.outgoingMsg:
    186 			if !ok {
    187 				return nil
    188 			}
    189 			rawMsg := i.UnpackMessage(msg)
    190 			err := i.TxRawMessage(rawMsg)
    191 			if err != nil {
    192 				return err
    193 			}
    194 		}
    195 	}
    196 	return nil
    197 }