You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

main.go 3.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. package main
  2. import (
  3. "crypto/tls"
  4. "fmt"
  5. "github.com/deckarep/golang-set"
  6. "github.com/fsnotify/fsnotify"
  7. "github.com/irccloud/irccat/httplistener"
  8. "github.com/irccloud/irccat/tcplistener"
  9. "github.com/juju/loggo"
  10. "github.com/spf13/viper"
  11. "github.com/thoj/go-ircevent"
  12. "os"
  13. "os/signal"
  14. "syscall"
  15. )
  16. var log = loggo.GetLogger("main")
  17. type IRCCat struct {
  18. auth_channel string
  19. channels mapset.Set
  20. auth_users map[string]bool
  21. irc *irc.Connection
  22. tcp *tcplistener.TCPListener
  23. signals chan os.Signal
  24. }
  25. func main() {
  26. loggo.ConfigureLoggers("<root>=DEBUG")
  27. log.Infof("IRCCat starting...")
  28. viper.SetConfigName("irccat")
  29. viper.AddConfigPath("/etc")
  30. viper.AddConfigPath(".")
  31. var err error
  32. err = viper.ReadInConfig()
  33. if err != nil {
  34. log.Errorf("Error reading config file - exiting. I'm looking for irccat.[json|yaml|toml|hcl] in . or /etc")
  35. return
  36. }
  37. irccat := IRCCat{auth_users: map[string]bool{},
  38. signals: make(chan os.Signal, 1),
  39. channels: mapset.NewSet(),
  40. auth_channel: viper.GetString("commands.auth_channel")}
  41. viper.WatchConfig()
  42. viper.OnConfigChange(irccat.handleConfigChange)
  43. signal.Notify(irccat.signals, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)
  44. go irccat.signalHandler()
  45. irccat.tcp, err = tcplistener.New()
  46. if err != nil {
  47. return
  48. }
  49. err = irccat.connectIRC()
  50. if err != nil {
  51. log.Criticalf("Error connecting to IRC server: %s", err)
  52. return
  53. }
  54. if viper.IsSet("http") {
  55. httplistener.New(irccat.irc)
  56. }
  57. irccat.tcp.Run(irccat.irc)
  58. irccat.irc.Loop()
  59. }
  60. func (i *IRCCat) signalHandler() {
  61. sig := <-i.signals
  62. log.Infof("Exiting on %s", sig)
  63. i.irc.QuitMessage = fmt.Sprintf("Exiting on %s", sig)
  64. i.irc.Quit()
  65. }
  66. func (i *IRCCat) connectIRC() error {
  67. irccon := irc.IRC(viper.GetString("irc.nick"), viper.GetString("irc.realname"))
  68. irccon.UseTLS = viper.GetBool("irc.tls")
  69. if viper.GetBool("irc.tls_skip_verify") {
  70. irccon.TLSConfig = &tls.Config{InsecureSkipVerify: true}
  71. }
  72. err := irccon.Connect(viper.GetString("irc.server"))
  73. if err != nil {
  74. return err
  75. }
  76. irccon.AddCallback("001", i.handleWelcome)
  77. irccon.AddCallback("PRIVMSG", func(event *irc.Event) {
  78. if event.Message()[0] == '?' || event.Message()[0] == '!' {
  79. go i.handleCommand(event)
  80. }
  81. })
  82. irccon.AddCallback("353", i.handleNames)
  83. irccon.AddCallback("JOIN", i.handleJoin)
  84. irccon.AddCallback("PART", i.handlePart)
  85. irccon.AddCallback("QUIT", i.handlePart)
  86. i.irc = irccon
  87. return nil
  88. }
  89. func (i *IRCCat) handleWelcome(e *irc.Event) {
  90. if viper.IsSet("irc.identify_pass") && viper.GetString("irc.identify_pass") != "" {
  91. i.irc.SendRawf("NICKSERV IDENTIFY %s", viper.GetString("irc.identify_pass"))
  92. }
  93. log.Infof("Connected, joining channels...")
  94. for _, channel := range viper.GetStringSlice("irc.channels") {
  95. i.irc.Join(channel)
  96. i.channels.Add(channel)
  97. }
  98. }
  99. func (i *IRCCat) handleConfigChange(e fsnotify.Event) {
  100. log.Infof("Reloaded config")
  101. new_channels := mapset.NewSet()
  102. for _, channel := range viper.GetStringSlice("irc.channels") {
  103. new_channels.Add(channel)
  104. if !i.channels.Contains(channel) {
  105. log.Infof("Joining new channel %s", channel)
  106. i.irc.Join(channel)
  107. i.channels.Add(channel)
  108. }
  109. }
  110. it := i.channels.Difference(new_channels).Iterator()
  111. for channel := range it.C {
  112. log.Infof("Leaving channel %s", channel)
  113. i.irc.Part(channel.(string))
  114. i.channels.Remove(channel)
  115. }
  116. }