123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163 |
- package main
-
- import (
- "crypto/tls"
- "fmt"
- "github.com/deckarep/golang-set"
- "github.com/fsnotify/fsnotify"
- "github.com/irccloud/go-ircevent"
- "github.com/irccloud/irccat/httplistener"
- "github.com/irccloud/irccat/tcplistener"
- "github.com/juju/loggo"
- "github.com/spf13/viper"
- "os"
- "os/signal"
- "strings"
- "syscall"
- )
-
- var log = loggo.GetLogger("main")
-
- var branch string
- var revision string
-
- type IRCCat struct {
- auth_channel string
- channels mapset.Set
- auth_users map[string]bool
- irc *irc.Connection
- tcp *tcplistener.TCPListener
- signals chan os.Signal
- }
-
- func main() {
- loggo.ConfigureLoggers("<root>=INFO")
- log.Infof("IRCCat %s (%s) starting...", branch, revision)
- viper.SetConfigName("irccat")
- viper.AddConfigPath("/etc")
- viper.AddConfigPath(".")
- var err error
-
- err = viper.ReadInConfig()
- if err != nil {
- log.Errorf("Error reading config file - exiting. I'm looking for irccat.[json|yaml|toml|hcl] in . or /etc")
- return
- }
-
- irccat := IRCCat{auth_users: map[string]bool{},
- signals: make(chan os.Signal, 1),
- channels: mapset.NewSet(),
- auth_channel: viper.GetString("commands.auth_channel")}
-
- viper.WatchConfig()
- viper.OnConfigChange(irccat.handleConfigChange)
-
- signal.Notify(irccat.signals, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)
- go irccat.signalHandler()
-
- irccat.tcp, err = tcplistener.New()
- if err != nil {
- log.Criticalf("Error starting TCP listener: %s", err)
- return
- }
-
- err = irccat.connectIRC()
-
- if err != nil {
- log.Criticalf("Error connecting to IRC server: %s", err)
- return
- }
-
- if viper.IsSet("http") {
- httplistener.New(irccat.irc)
- }
-
- irccat.tcp.Run(irccat.irc)
- irccat.irc.Loop()
- }
-
- func (i *IRCCat) signalHandler() {
- sig := <-i.signals
- log.Infof("Exiting on %s", sig)
- i.irc.QuitMessage = fmt.Sprintf("Exiting on %s", sig)
- i.irc.Quit()
- }
-
- func (i *IRCCat) connectIRC() error {
- irccon := irc.IRC(viper.GetString("irc.nick"), viper.GetString("irc.realname"))
- i.irc = irccon
- irccon.RequestCaps = []string{"away-notify", "account-notify", "draft/message-tags-0.2"}
- irccon.UseTLS = viper.GetBool("irc.tls")
- if viper.GetBool("irc.tls_skip_verify") {
- irccon.TLSConfig = &tls.Config{InsecureSkipVerify: true}
- }
- irccon.Password = viper.GetString("irc.server_pass")
-
- err := irccon.Connect(viper.GetString("irc.server"))
- if err != nil {
- return err
- }
-
- irccon.AddCallback("001", i.handleWelcome)
- irccon.AddCallback("PRIVMSG", func(event *irc.Event) {
- msg := event.Message()
- if (msg[0] == '?' || msg[0] == '!') && len(msg) > 1 {
- go i.handleCommand(event)
- }
- })
-
- irccon.AddCallback("353", i.handleNames)
- irccon.AddCallback("JOIN", i.handleJoin)
- irccon.AddCallback("PART", i.handlePart)
- irccon.AddCallback("QUIT", i.handleQuit)
- irccon.AddCallback("KILL", i.handleQuit)
- irccon.AddCallback("NICK", i.handleNick)
-
- return nil
- }
-
- func (i *IRCCat) handleWelcome(e *irc.Event) {
- log.Infof("Negotiated IRCv3 capabilities: %v", i.irc.AcknowledgedCaps)
- if viper.IsSet("irc.identify_pass") && viper.GetString("irc.identify_pass") != "" {
- i.irc.SendRawf("NICKSERV IDENTIFY %s", viper.GetString("irc.identify_pass"))
- }
-
- log.Infof("Connected, joining channels...")
- for _, channel := range viper.GetStringSlice("irc.channels") {
- key_var := fmt.Sprintf("irc.keys.%s", channel)
- if strings.ContainsAny(channel, " \t") {
- log.Errorf("Channel name '%s' contains whitespace. Set a channel key by setting the config variable irc.keys.#channel",
- channel)
- continue
- }
-
- if viper.IsSet(key_var) {
- i.irc.Join(channel + " " + viper.GetString(key_var))
- } else {
- i.irc.Join(channel)
- }
- i.channels.Add(channel)
- }
- }
-
- func (i *IRCCat) handleConfigChange(e fsnotify.Event) {
- log.Infof("Reloaded config")
-
- new_channels := mapset.NewSet()
-
- for _, channel := range viper.GetStringSlice("irc.channels") {
- new_channels.Add(channel)
- if !i.channels.Contains(channel) {
- log.Infof("Joining new channel %s", channel)
- i.irc.Join(channel)
- i.channels.Add(channel)
- }
- }
-
- it := i.channels.Difference(new_channels).Iterator()
- for channel := range it.C {
- log.Infof("Leaving channel %s", channel)
- i.irc.Part(channel.(string))
- i.channels.Remove(channel)
- }
- }
|