166 lines
3.4 KiB
Go
166 lines
3.4 KiB
Go
// 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 <http://www.gnu.org/licenses/>.
|
|
|
|
// 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,
|
|
}
|
|
}
|