123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354 |
- package irc
-
- import (
- "errors"
- "fmt"
- "regexp"
- "strconv"
- "strings"
- )
-
- type Message interface {
- Handle(s *Server, c *Client)
- }
-
- var (
- ErrNotEnoughArgs = errors.New("not enough arguments")
- ErrUModeUnknownFlag = errors.New("unknown umode flag")
- )
-
- // unknown
-
- type UnknownMessage struct {
- command string
- }
-
- // NB: no constructor, created on demand in parser for invalid messages.
-
- func (m *UnknownMessage) Handle(s *Server, c *Client) {
- c.send <- ErrUnknownCommand(s, m.command)
- }
-
- // PING
-
- type PingMessage struct {
- server string
- server2 string
- }
-
- func NewPingMessage(args []string) (Message, error) {
- if len(args) < 1 {
- return nil, ErrNotEnoughArgs
- }
- msg := &PingMessage{server: args[0]}
- if len(args) > 1 {
- msg.server2 = args[1]
- }
- return msg, nil
- }
-
- func (m *PingMessage) Handle(s *Server, c *Client) {
- c.send <- RplPong(s)
- }
-
- // PONG
-
- type PongMessage struct {
- server1 string
- server2 string
- }
-
- func NewPongMessage(args []string) (Message, error) {
- if len(args) < 1 {
- return nil, ErrNotEnoughArgs
- }
- message := &PongMessage{server1: args[0]}
- if len(args) > 1 {
- message.server2 = args[1]
- }
- return message, nil
- }
-
- func (m *PongMessage) Handle(s *Server, c *Client) {
- // no-op
- }
-
- // NICK
-
- type NickMessage struct {
- nickname string
- }
-
- func NewNickMessage(args []string) (Message, error) {
- if len(args) != 1 {
- return nil, ErrNotEnoughArgs
- }
- return &NickMessage{args[0]}, nil
- }
-
- func (m *NickMessage) Handle(s *Server, c *Client) {
- s.ChangeNick(c, m.nickname)
- }
-
- // USER
-
- type UserMessage struct {
- user string
- mode uint8
- unused string
- realname string
- }
-
- func NewUserMessage(args []string) (Message, error) {
- if len(args) != 4 {
- return nil, ErrNotEnoughArgs
- }
- msg := &UserMessage{
- user: args[0],
- unused: args[2],
- realname: args[3],
- }
- mode, err := strconv.ParseUint(args[1], 10, 8)
- if err == nil {
- msg.mode = uint8(mode)
- }
- return msg, nil
- }
-
- func (m *UserMessage) Handle(s *Server, c *Client) {
- s.UserLogin(c, m.user, m.realname)
- }
-
- // QUIT
-
- type QuitMessage struct {
- message string
- }
-
- func NewQuitMessage(args []string) (Message, error) {
- msg := &QuitMessage{}
- if len(args) > 0 {
- msg.message = args[0]
- }
- return msg, nil
- }
-
- func (m *QuitMessage) Handle(s *Server, c *Client) {
- s.Quit(c, m.message)
- }
-
- // MODE
-
- type ModeMessage struct {
- nickname string
- modes []string
- }
-
- var MODE_RE = regexp.MustCompile("^[-+][a-zA-Z]+$")
-
- func NewModeMessage(args []string) (Message, error) {
- if len(args) < 1 {
- return nil, ErrNotEnoughArgs
- }
- msg := &ModeMessage{
- nickname: args[0],
- }
- for _, arg := range args[1:] {
- if !MODE_RE.MatchString(arg) {
- return nil, ErrUModeUnknownFlag
- }
- prefix := arg[0]
- for _, c := range arg[1:] {
- mode := fmt.Sprintf("%c%c", prefix, c)
- msg.modes = append(msg.modes, mode)
- }
- }
- return msg, nil
- }
-
- func (m *ModeMessage) Handle(s *Server, c *Client) {
- if m.nickname != c.nick {
- c.send <- ErrUsersDontMatch(s)
- return
- }
- s.ChangeUserMode(c, m.modes)
- }
-
- // JOIN
-
- type JoinMessage struct {
- channels []string
- keys []string
- zero bool
- }
-
- func NewJoinMessage(args []string) (Message, error) {
- msg := &JoinMessage{}
- if len(args) > 0 {
- if args[0] == "0" {
- msg.zero = true
- } else {
- msg.channels = strings.Split(args[0], ",")
- }
-
- if len(args) > 1 {
- msg.keys = strings.Split(args[1], ",")
- }
- }
- return msg, nil
- }
-
- func (m *JoinMessage) Handle(s *Server, c *Client) {
- if m.zero {
- for channel := range c.channels {
- channel.Part(c, "")
- }
- } else {
- for i, name := range m.channels {
- key := ""
- if len(m.keys) > i {
- key = m.keys[i]
- }
-
- s.GetOrMakeChannel(name).Join(c, key)
- }
- }
- }
-
- // PART
-
- type PartMessage struct {
- channels []string
- message string
- }
-
- func NewPartMessage(args []string) (Message, error) {
- if len(args) < 1 {
- return nil, ErrNotEnoughArgs
- }
- msg := &PartMessage{channels: strings.Split(args[0], ",")}
- if len(args) > 1 {
- msg.message = args[1]
- }
- return msg, nil
- }
-
- func (m *PartMessage) Handle(s *Server, c *Client) {
- for _, chname := range m.channels {
- channel := s.channels[chname]
-
- if channel == nil {
- c.send <- ErrNoSuchChannel(s, chname)
- continue
- }
-
- channel.Part(c, m.message)
- }
- }
-
- // PRIVMSG
-
- type PrivMsgMessage struct {
- target string
- message string
- }
-
- func NewPrivMsgMessage(args []string) (Message, error) {
- if len(args) < 2 {
- return nil, ErrNotEnoughArgs
- }
- return &PrivMsgMessage{
- target: args[0],
- message: args[1],
- }, nil
- }
-
- func (m *PrivMsgMessage) TargetIsChannel() bool {
- switch m.target[0] {
- case '&', '#', '+', '!':
- return true
- }
- return false
- }
-
- func (m *PrivMsgMessage) Handle(s *Server, c *Client) {
- if m.TargetIsChannel() {
- channel := s.channels[m.target]
- if channel != nil {
- channel.PrivMsg(c, m.message)
- } else {
- c.send <- ErrNoSuchNick(s, m.target)
- }
- } else {
- client := s.nicks[m.target]
- if client != nil {
- client.send <- RplPrivMsg(client, m.message)
- } else {
- c.send <- ErrNoSuchNick(s, m.target)
- }
- }
- }
-
- // TOPIC [newtopic]
-
- type TopicMessage struct {
- channel string
- topic string
- }
-
- func NewTopicMessage(args []string) (Message, error) {
- if len(args) < 1 {
- return nil, ErrNotEnoughArgs
- }
- msg := &TopicMessage{channel: args[0]}
- if len(args) > 1 {
- msg.topic = args[1]
- }
- return msg, nil
- }
-
- func (m *TopicMessage) Handle(s *Server, c *Client) {
- channel := s.channels[m.channel]
- if channel == nil {
- c.send <- ErrNoSuchChannel(s, m.channel)
- return
- }
- if m.topic == "" {
- channel.GetTopic(c)
- } else {
- channel.ChangeTopic(c, m.topic)
- }
- }
-
- // INVITE <nickname> <channel>
-
- type InviteMessage struct {
- nickname string
- channel string
- }
-
- func NewInviteMessage(args []string) (Message, error) {
- if len(args) < 2 {
- return nil, ErrNotEnoughArgs
- }
- return &InviteMessage{
- nickname: args[0],
- channel: args[1],
- }, nil
- }
-
- func (m *InviteMessage) Handle(s *Server, c *Client) {
- channel := s.channels[m.channel]
- if channel == nil {
- c.send <- ErrNoSuchNick(s, m.channel)
- return
- }
-
- invitee := s.nicks[m.nickname]
- if invitee == nil {
- c.send <- ErrNoSuchNick(s, m.nickname)
- return
- }
-
- channel.Invite(c, invitee)
- }
|