|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"errors"
|
|
|
|
"fmt"
|
|
|
|
"io/ioutil"
|
|
|
|
"os"
|
|
|
|
"strings"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/nlopes/slack"
|
|
|
|
"github.com/unixvoid/glogger"
|
|
|
|
"gopkg.in/gcfg.v1"
|
|
|
|
"gopkg.in/redis.v5"
|
|
|
|
)
|
|
|
|
|
|
|
|
type Config struct {
|
|
|
|
Lorebot struct {
|
|
|
|
Loglevel string
|
|
|
|
BootstrapDelay time.Duration
|
|
|
|
APIToken string
|
|
|
|
}
|
|
|
|
Redis struct {
|
|
|
|
Host string
|
|
|
|
Password string
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
var (
|
|
|
|
config = Config{}
|
|
|
|
)
|
|
|
|
|
|
|
|
func main() {
|
|
|
|
// read in config file
|
|
|
|
readConf()
|
|
|
|
|
|
|
|
// initialize the logger with the configured loglevel
|
|
|
|
initLogger(config.Lorebot.Loglevel)
|
|
|
|
|
|
|
|
// initialize redis connection
|
|
|
|
redisClient, err := initRedisConnection()
|
|
|
|
if err != nil {
|
|
|
|
glogger.Debug.Printf("redis conneciton cannot be made, trying again in %d seconds", config.Lorebot.BootstrapDelay)
|
|
|
|
time.Sleep(config.Lorebot.BootstrapDelay * time.Second)
|
|
|
|
redisClient, err = initRedisConnection()
|
|
|
|
if err != nil {
|
|
|
|
glogger.Error.Println("redis connection cannot be made.")
|
|
|
|
os.Exit(1)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
glogger.Debug.Println("connection to redis succeeded.")
|
|
|
|
glogger.Info.Println("link to redis on", config.Redis.Host)
|
|
|
|
|
|
|
|
api := slack.New(config.Lorebot.APIToken)
|
|
|
|
//api.SetDebug(true)
|
|
|
|
|
|
|
|
rtm := api.NewRTM()
|
|
|
|
go rtm.ManageConnection()
|
|
|
|
|
|
|
|
Loop:
|
|
|
|
for {
|
|
|
|
select {
|
|
|
|
case msg := <-rtm.IncomingEvents:
|
|
|
|
switch ev := msg.Data.(type) {
|
|
|
|
case *slack.MessageEvent:
|
|
|
|
if ev.Type == "message" {
|
|
|
|
glogger.Debug.Printf("processing: %s", ev.Text)
|
|
|
|
// see if the message begins with '.', it could be a command
|
|
|
|
if len(ev.Text) == 0 {
|
|
|
|
// nil message, dont print
|
|
|
|
//glogger.Debug.Println("breaking on blank message")
|
|
|
|
break
|
|
|
|
} else {
|
|
|
|
comm := fmt.Sprintf("%c", ev.Text[0])
|
|
|
|
if comm == "." {
|
|
|
|
if strings.Count(ev.Text, " ") == 0 {
|
|
|
|
// no spaces, its a static command
|
|
|
|
staticCommandHandler(rtm, ev, redisClient)
|
|
|
|
} else {
|
|
|
|
// spaces, dynamic handler
|
|
|
|
dynamicCommandHandler(rtm, ev, redisClient)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
case *slack.RTMError:
|
|
|
|
fmt.Printf("Error: %s\n", ev.Error())
|
|
|
|
case *slack.InvalidAuthEvent:
|
|
|
|
fmt.Printf("Invalid credentials")
|
|
|
|
break Loop
|
|
|
|
default:
|
|
|
|
// ignore all other events
|
|
|
|
//fmt.Printf("Unknown error")
|
|
|
|
//fmt.Printf("%v\n", msg.Data)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func readConf() {
|
|
|
|
// init config file
|
|
|
|
err := gcfg.ReadFileInto(&config, "config.gcfg")
|
|
|
|
if err != nil {
|
|
|
|
panic(fmt.Sprintf("Could not load config.gcfg, error: %s\n", err))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func initLogger(logLevel string) {
|
|
|
|
// init logger
|
|
|
|
if logLevel == "debug" {
|
|
|
|
glogger.LogInit(os.Stdout, os.Stdout, os.Stdout, os.Stderr)
|
|
|
|
} else if logLevel == "cluster" {
|
|
|
|
glogger.LogInit(os.Stdout, os.Stdout, ioutil.Discard, os.Stderr)
|
|
|
|
} else if logLevel == "info" {
|
|
|
|
glogger.LogInit(os.Stdout, ioutil.Discard, ioutil.Discard, os.Stderr)
|
|
|
|
} else {
|
|
|
|
glogger.LogInit(ioutil.Discard, ioutil.Discard, ioutil.Discard, os.Stderr)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func initRedisConnection() (*redis.Client, error) {
|
|
|
|
// init redis connection
|
|
|
|
redisClient := redis.NewClient(&redis.Options{
|
|
|
|
Addr: config.Redis.Host,
|
|
|
|
Password: config.Redis.Password,
|
|
|
|
DB: 0,
|
|
|
|
})
|
|
|
|
|
|
|
|
_, redisErr := redisClient.Ping().Result()
|
|
|
|
return redisClient, redisErr
|
|
|
|
}
|
|
|
|
|
|
|
|
func dynamicCommandHandler(rtm *slack.RTM, ev *slack.MessageEvent, redisClient *redis.Client) {
|
|
|
|
message := ev.Text
|
|
|
|
if strings.Count(message, " ") < 1 {
|
|
|
|
glogger.Debug.Println("not proper syntax")
|
|
|
|
}
|
|
|
|
|
|
|
|
// verify syntax
|
|
|
|
s := strings.SplitN(message, " ", 2)
|
|
|
|
command, content := s[0], s[1]
|
|
|
|
trimmedPrefix := strings.TrimPrefix(command, ".")
|
|
|
|
|
|
|
|
switch trimmedPrefix {
|
|
|
|
case "lore":
|
|
|
|
s := strings.SplitN(string(ev.Text), " ", 2)
|
|
|
|
lorehandler(redisClient, rtm, ev, s[1])
|
|
|
|
case "newlore":
|
|
|
|
rtm.SendMessage(rtm.NewOutgoingMessage("command not yet supported", ev.Channel))
|
|
|
|
println(content)
|
|
|
|
case "rmlore":
|
|
|
|
rtm.SendMessage(rtm.NewOutgoingMessage("command not yet supported", ev.Channel))
|
|
|
|
case "rek":
|
|
|
|
s := strings.SplitN(string(ev.Text), " ", 2)
|
|
|
|
rekhandler(redisClient, rtm, ev, s[1])
|
|
|
|
case "gnu":
|
|
|
|
s := strings.SplitN(string(ev.Text), " ", 2)
|
|
|
|
gnuhandler(redisClient, rtm, ev, s[1])
|
|
|
|
case "created":
|
|
|
|
rtm.SendMessage(rtm.NewOutgoingMessage("command not yet supported", ev.Channel))
|
|
|
|
case "owner":
|
|
|
|
rtm.SendMessage(rtm.NewOutgoingMessage("command not yet supported", ev.Channel))
|
|
|
|
case "removedby":
|
|
|
|
rtm.SendMessage(rtm.NewOutgoingMessage("command not yet supported", ev.Channel))
|
|
|
|
case "removed":
|
|
|
|
rtm.SendMessage(rtm.NewOutgoingMessage("command not yet supported", ev.Channel))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func staticCommandHandler(rtm *slack.RTM, ev *slack.MessageEvent, redisClient *redis.Client) {
|
|
|
|
s := strings.SplitN(ev.Text, " ", 2)
|
|
|
|
command := s[0]
|
|
|
|
trimmedPrefix := strings.TrimPrefix(command, ".")
|
|
|
|
|
|
|
|
switch trimmedPrefix {
|
|
|
|
case "help":
|
|
|
|
helpmsg(rtm, ev)
|
|
|
|
case "help2":
|
|
|
|
advancedhelpmsg(rtm, ev)
|
|
|
|
case "rng":
|
|
|
|
rtm.SendMessage(rtm.NewOutgoingMessage("command not yet supported", ev.Channel))
|
|
|
|
case "version":
|
|
|
|
rtm.SendMessage(rtm.NewOutgoingMessage("command not yet supported", ev.Channel))
|
|
|
|
case "lorelist":
|
|
|
|
rtm.SendMessage(rtm.NewOutgoingMessage("command not yet supported", ev.Channel))
|
|
|
|
case "removedlore":
|
|
|
|
rtm.SendMessage(rtm.NewOutgoingMessage("command not yet supported", ev.Channel))
|
|
|
|
case "lorestatus":
|
|
|
|
rtm.SendMessage(rtm.NewOutgoingMessage("command not yet supported", ev.Channel))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func helpmsg(rtm *slack.RTM, ev *slack.MessageEvent) {
|
|
|
|
help1 := "I am the lore archival bot, I support the following commands:\n" +
|
|
|
|
"```" +
|
|
|
|
".lore: view lore\n" +
|
|
|
|
".newlore: add new lore\n" +
|
|
|
|
".rmlore: remove lore\n" +
|
|
|
|
".lorelist: view lore database\n" +
|
|
|
|
"use '.help2' to see advanced lookup commands." +
|
|
|
|
"```"
|
|
|
|
|
|
|
|
rtm.SendMessage(rtm.NewOutgoingMessage(help1, ev.Channel))
|
|
|
|
}
|
|
|
|
|
|
|
|
func advancedhelpmsg(rtm *slack.RTM, ev *slack.MessageEvent) {
|
|
|
|
help2 := "```" +
|
|
|
|
".created view creation timestamp\n" +
|
|
|
|
".owner: who created the lore\n" +
|
|
|
|
".removed: view removal timestamp\n" +
|
|
|
|
".removedby: who removed the lore" +
|
|
|
|
"```"
|
|
|
|
|
|
|
|
rtm.SendMessage(rtm.NewOutgoingMessage(help2, ev.Channel))
|
|
|
|
}
|
|
|
|
|
|
|
|
func lorehandler(redisClient *redis.Client, rtm *slack.RTM, ev *slack.MessageEvent, rawMessage string) {
|
|
|
|
loreTerm := strings.Replace(rawMessage, ".lore", "", -1)
|
|
|
|
println("searching for:", loreTerm)
|
|
|
|
//rtm.SendMessage(rtm.NewOutgoingMessage(fmt.Sprintf("searching for '%s'\n", loreTerm), ev.Channel))
|
|
|
|
|
|
|
|
content, err := checkLore(loreTerm, redisClient)
|
|
|
|
if err == nil {
|
|
|
|
// lore found, print it
|
|
|
|
rtm.SendMessage(rtm.NewOutgoingMessage(content, ev.Channel))
|
|
|
|
} else {
|
|
|
|
// lore not found, print error
|
|
|
|
rtm.SendMessage(rtm.NewOutgoingMessage(fmt.Sprintf("lore '%s' not found\n", loreTerm), ev.Channel))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func rekhandler(redisClient *redis.Client, rtm *slack.RTM, ev *slack.MessageEvent, target string) {
|
|
|
|
rektBit, _ := redisClient.SRandMember("index:rekt").Result()
|
|
|
|
rekFmt := fmt.Sprintf("%s %s", target, rektBit)
|
|
|
|
rtm.SendMessage(rtm.NewOutgoingMessage(rekFmt, ev.Channel))
|
|
|
|
}
|
|
|
|
|
|
|
|
func gnuhandler(redisClient *redis.Client, rtm *slack.RTM, ev *slack.MessageEvent, target string) {
|
|
|
|
gnuFmt := fmt.Sprintf("slaps the nonfree software out of %s's hands", target)
|
|
|
|
rtm.SendMessage(rtm.NewOutgoingMessage(gnuFmt, ev.Channel))
|
|
|
|
}
|
|
|
|
|
|
|
|
func checkLore(searchTerm string, redisClient *redis.Client) (string, error) {
|
|
|
|
val, err := redisClient.Get(fmt.Sprintf("lore:%s:content", searchTerm)).Result()
|
|
|
|
if err != nil {
|
|
|
|
return "", errors.New("String not found.")
|
|
|
|
} else {
|
|
|
|
return val, nil
|
|
|
|
}
|
|
|
|
//return "", nil
|
|
|
|
}
|