// Copyright (c) 2016 Tristan Colgate-McFarlane // // This file is part of hugot. // // hugot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // hugot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with hugot. If not, see . // Package irc implements a simple adapter for IRC using // github.com/fluffle/goirc/client package irc import ( "fmt" "regexp" "strings" "sync" "time" "context" "github.com/fluffle/goirc/client" iglog "github.com/fluffle/goirc/logging/glog" "github.com/golang/glog" "github.com/tcolgate/hugot" ) type irc struct { cfg *client.Config defChans []string c chan *hugot.Message start sync.Once *client.Conn } // New creates a new adapter that communicates with an IRC server using // github.com/thoj/go-ircevent func New(c *client.Config, chans ...string) hugot.Adapter { a := &irc{ c, chans, make(chan *hugot.Message), sync.Once{}, nil, } return a } func (i *irc) Send(ctx context.Context, m *hugot.Message) { i.Start() if m.Private { if m.Channel == "" { if m.To != "" { m.Channel = m.To } else { m.Channel = m.From } } } if glog.V(3) { glog.Infof("Sending %#v", *m) } for _, l := range strings.Split(m.Text, "\n") { i.Privmsg(m.Channel, l) } } func (i *irc) Receive() <-chan *hugot.Message { i.Start() return i.c } func (i *irc) Start() { i.start.Do(func() { go i.run() }) } func (i *irc) run() { iglog.Init() for { i.Conn = client.Client(i.cfg) disconnected := make(chan struct{}) i.HandleFunc(client.DISCONNECTED, func(c *client.Conn, l *client.Line) { if glog.V(1) { glog.Info("IRC Disconnected") } close(disconnected) }) // Connect to an IRC server. if err := i.ConnectTo(i.cfg.Server); err != nil { glog.Errorf("could not connect to server, %v", err) <-time.After(5 * time.Second) continue } i.HandleFunc(client.PRIVMSG, func(conn *client.Conn, l *client.Line) { i.c <- i.eventToHugot(l) }) i.HandleFunc(client.CONNECTED, func(conn *client.Conn, l *client.Line) { if glog.V(1) { glog.Info("IRC Connected") } for _, c := range i.defChans { i.Join(c) } }) // Wait for disconnection. <-disconnected } } func (i *irc) eventToHugot(l *client.Line) *hugot.Message { txt := l.Text() nick := i.Me().Nick tobot := false priv := false channel := l.Target() if l.Public() { // Check if the message was sent @bot, if so, set it as to us // and strip the leading politeness dir := regexp.MustCompile(fmt.Sprintf("^%s[:, ]+(.*)", nick)) dirMatch := dir.FindStringSubmatch(txt) if glog.V(3) { glog.Infof("Match %#v", dirMatch) } if len(dirMatch) > 1 { tobot = true txt = strings.Trim(dirMatch[1], " ") } } else { tobot = true priv = true } return &hugot.Message{ Channel: channel, From: l.Nick, To: nick, Text: txt, ToBot: tobot, UserID: fmt.Sprintf("%s@%s", l.Ident, l.Host), Private: priv, } }