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.
149 lines
4.0 KiB
149 lines
4.0 KiB
package main |
|
|
|
import ( |
|
"bytes" |
|
"crypto/tls" |
|
"encoding/json" |
|
"fmt" |
|
"log" |
|
"net/http" |
|
"os" |
|
"os/signal" |
|
"regexp" |
|
"strings" |
|
"syscall" |
|
|
|
"gopkg.in/sorcix/irc.v2" |
|
) |
|
|
|
const disconnectExitStatus int = 2 |
|
|
|
const PushoverAPI string = "https://api.pushover.net/1/messages.json" |
|
|
|
func main() { |
|
config, err := LoadConfig() |
|
if err != nil { |
|
log.Fatalf("Unable to configure: %s", err) |
|
} |
|
//TODO (noah): probably should check for protocol + port or something |
|
conn, err := irc.DialTLS(config.Host, &tls.Config{}) |
|
if err != nil { |
|
log.Fatalf("Unable to connect to IRC server: %s", err) |
|
} |
|
|
|
running := true |
|
//Register signal so we can clean up the socket before we exit |
|
c := make(chan os.Signal) |
|
signal.Notify(c, os.Interrupt, syscall.SIGTERM) |
|
signal.Notify(c, os.Interrupt, syscall.SIGINT) |
|
|
|
go func() { |
|
<-c |
|
log.Printf("Exiting") |
|
running = false |
|
conn.Close() |
|
os.Exit(0) |
|
}() |
|
if config.Pass != "" { |
|
_, err = conn.Write([]byte("PASS " + config.Pass)) |
|
if err != nil { |
|
log.Fatalf("Unable to authenticate to server: %s", err) |
|
} |
|
} |
|
log.Printf("User: %s", config.User) |
|
_, err = conn.Write([]byte("USER " + config.User)) |
|
if err != nil { |
|
log.Fatalf("Unable to send message to server: %s", err) |
|
} |
|
log.Printf("Nick: %s", config.Nick) |
|
_, err = conn.Write([]byte("NICK " + config.Nick)) |
|
if err != nil { |
|
log.Fatalf("Unable to send message to server: %s", err) |
|
} |
|
_, err = conn.Write([]byte("WHOIS " + config.Nick)) |
|
if err != nil { |
|
log.Fatalf("Unable to send message to server: %s", err) |
|
} |
|
userRegexp, err := regexp.Compile(`(\w+)!(\w+)@\S+`) |
|
if err != nil { |
|
log.Fatalf("Unable to compile user regexp: %s", err) |
|
} |
|
|
|
away := false |
|
for running { |
|
message, err := conn.Decode() |
|
if err != nil { |
|
log.Printf("Unable to decode: %s", err) |
|
os.Exit(disconnectExitStatus) |
|
} |
|
if message == nil { |
|
continue |
|
} |
|
if message.Command == irc.QUIT && message.Prefix.Name == config.Nick { |
|
log.Printf("Server sent QUIT, exiting") |
|
running = false |
|
//Exit with a non-zero status so the system process restarts this process |
|
os.Exit(disconnectExitStatus) |
|
} |
|
for _, user := range config.ExcludeUsers { |
|
if user == message.Prefix.Name { |
|
log.Printf("User %s is in excluded users, skipping message", message.Prefix.Name) |
|
continue |
|
} |
|
} |
|
for _, excludedChannel := range config.ExcludeChannels { |
|
if message.Params[0] == excludedChannel { |
|
log.Printf("Channel %s is in excluded channels, skipping message", message.Params[0]) |
|
continue |
|
} |
|
} |
|
if away && message.Command == irc.PRIVMSG { |
|
matched := false |
|
for _, matchString := range config.Match { |
|
if strings.Contains(message.Params[1], matchString) { |
|
log.Printf("match %s is contained in %s", matchString, message.Params[1]) |
|
matched = true |
|
break |
|
} |
|
} |
|
if matched { |
|
log.Print("Message contains search word, sending notification") |
|
err = sendNotification(config.UserToken, config.AppToken, message) |
|
if err != nil { |
|
log.Printf("Unable to send notification: %s", err) |
|
} |
|
} |
|
} else if message.Command == irc.RPL_NOWAWAY { |
|
log.Printf("Marking as away, will notify") |
|
away = true |
|
} else if message.Command == irc.RPL_UNAWAY { |
|
log.Printf("No longer away, won't notify") |
|
away = false |
|
} else if message.Command == irc.RPL_WELCOME { |
|
matches := userRegexp.FindSubmatch([]byte(message.Params[0])) |
|
if matches != nil { |
|
config.Nick = string(matches[0]) |
|
log.Printf("Nick: %s\tUsername %s\tHost: %s", matches[0], matches[1], matches[2]) |
|
} |
|
} |
|
} |
|
} |
|
|
|
func sendNotification(user_token, app_token string, message *irc.Message) error { |
|
body := map[string]string{ |
|
"token": app_token, |
|
"user": user_token, |
|
"title": fmt.Sprintf("%s on %s mentioned you", message.Prefix.User, message.Params[0]), |
|
"message": message.Params[1], |
|
} |
|
json_body, err := json.Marshal(body) |
|
if err != nil { |
|
return err |
|
} |
|
resp, err := http.Post(PushoverAPI, "application/json", bytes.NewBuffer(json_body)) |
|
if err != nil { |
|
return err |
|
} |
|
log.Printf("Pushover API notify resp code: %d %s", resp.StatusCode, resp.Status) |
|
return nil |
|
}
|
|
|