229 lines
8.0 KiB
Go
Executable File
229 lines
8.0 KiB
Go
Executable File
package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"math/rand"
|
|
"os"
|
|
"path/filepath"
|
|
"time"
|
|
|
|
builtins "git.martyn.berlin/martyn/twitchsingstools/internal/builtins"
|
|
data "git.martyn.berlin/martyn/twitchsingstools/internal/data"
|
|
irc "git.martyn.berlin/martyn/twitchsingstools/internal/irc"
|
|
webserver "git.martyn.berlin/martyn/twitchsingstools/internal/webserver"
|
|
rgb "github.com/foresthoffman/rgblog"
|
|
scribble "github.com/nanobox-io/golang-scribble"
|
|
)
|
|
|
|
type customStringsStruct struct {
|
|
Strings []string `json:"strings,omitempty"`
|
|
}
|
|
|
|
var selectablePrompts []string
|
|
|
|
var customStrings customStringsStruct
|
|
|
|
var config data.ConfigStruct
|
|
|
|
func readConfig() {
|
|
var data []byte
|
|
var err error
|
|
configFile := ""
|
|
if os.Getenv("TSTOOLS_CONFIGFILE") != "" {
|
|
if _, err := os.Stat(os.Getenv("TSTOOLS_CONFIGFILE")); os.IsNotExist(err) {
|
|
rgb.RPrintf("[%s] Error, TSTOOLS_CONFIGFILE env var set and '%s' doesn't exist!\n", irc.TimeStamp(), os.Getenv("TSTOOLS_CONFIGFILE"))
|
|
os.Exit(1)
|
|
}
|
|
configFile = os.Getenv("TSTOOLS_CONFIGFILE")
|
|
} else {
|
|
ex, err := os.Executable()
|
|
if err != nil {
|
|
rgb.YPrintf("[%s] Warning, TSTOOLS_CONFIGFILE env var unset and cannot find executable!\n", irc.TimeStamp())
|
|
}
|
|
exPath := filepath.Dir(ex)
|
|
if _, err := os.Stat(exPath + "/config.json"); os.IsNotExist(err) {
|
|
rgb.YPrintf("[%s] Warning, TSTOOLS_CONFIGFILE env var unset and `config.json` not alongside executable!\n", irc.TimeStamp())
|
|
if _, err := os.Stat("/etc/tstools/config.json"); os.IsNotExist(err) {
|
|
rgb.RPrintf("[%s] Error, TSTOOLS_CONFIGFILE env var unset and neither '%s' nor '%s' exist!\n", irc.TimeStamp(), exPath+"/config.json", "/etc/tstools/config.json")
|
|
os.Exit(1)
|
|
} else {
|
|
configFile = "/etc/tstools/config.json"
|
|
}
|
|
} else {
|
|
configFile = exPath + "/config.json"
|
|
}
|
|
}
|
|
data, err = ioutil.ReadFile(configFile)
|
|
if err != nil {
|
|
rgb.RPrintf("[%s] Could not read `%s`. File reading error: %s\n", irc.TimeStamp(), configFile, err)
|
|
os.Exit(1)
|
|
}
|
|
err = json.Unmarshal(data, &config)
|
|
if err != nil {
|
|
rgb.RPrintf("[%s] Could not unmarshal `%s`. Unmarshal error: %s\n", irc.TimeStamp(), configFile, err)
|
|
os.Exit(1)
|
|
}
|
|
rgb.YPrintf("[%s] Read config file from `%s`\n", irc.TimeStamp(), configFile)
|
|
rgb.YPrintf("[%s] config %v\n", irc.TimeStamp(), config)
|
|
return
|
|
}
|
|
|
|
//openDatabase "database" in this sense being a scribble db
|
|
func openDatabase() *scribble.Driver {
|
|
dataPath := ""
|
|
if config.DataPath == "" {
|
|
if os.Getenv("TSTOOLS_DATA_FOLDER") != "" {
|
|
if _, err := os.Stat(os.Getenv("TSTOOLS_DATA_FOLDER")); os.IsNotExist(err) {
|
|
rgb.RPrintf("[%s] Error, TSTOOLS_DATA_FOLDER env var set and '%s' doesn't exist!\n", irc.TimeStamp(), os.Getenv("TSTOOLS_DATA_FOLDER"))
|
|
os.Exit(1)
|
|
}
|
|
dataPath = os.Getenv("TSTOOLS_DATA_FOLDER")
|
|
} else {
|
|
ex, err := os.Executable()
|
|
if err != nil {
|
|
rgb.RPrintf("[%s] Error, TSTOOLS_DATA_FOLDER env var unset and cannot find executable!\n", irc.TimeStamp())
|
|
os.Exit(1)
|
|
}
|
|
exPath := filepath.Dir(ex)
|
|
if _, err := os.Stat(exPath + "/data"); os.IsNotExist(err) {
|
|
rgb.YPrintf("[%s] Warning %s doesn't exist, trying to create it.\n", irc.TimeStamp(), exPath+"/data")
|
|
err = os.Mkdir(exPath+"/data", 0770)
|
|
if err != nil {
|
|
rgb.RPrintf("[%s] Error cannot create %s: %s!\n", irc.TimeStamp(), exPath+"/data", err)
|
|
os.Exit(1)
|
|
}
|
|
}
|
|
dataPath = exPath + "/data"
|
|
}
|
|
} else {
|
|
if _, err := os.Stat(config.DataPath); os.IsNotExist(err) {
|
|
rgb.RPrintf("[%s] Error, config-specified path '%s' doesn't exist!\n", irc.TimeStamp(), config.DataPath)
|
|
os.Exit(1)
|
|
}
|
|
dataPath = config.DataPath
|
|
}
|
|
db, err := scribble.New(dataPath, nil)
|
|
if err != nil {
|
|
rgb.RPrintf("[%s] Error opening database in '%s' : %s\n", irc.TimeStamp(), dataPath, err)
|
|
os.Exit(1)
|
|
}
|
|
return db
|
|
}
|
|
|
|
var buildDate string
|
|
|
|
func main() {
|
|
rgb.YPrintf("[%s] starting twitchsingstools bot build %s\n", irc.TimeStamp(), buildDate)
|
|
readConfig()
|
|
rand.Seed(time.Now().UnixNano())
|
|
for _, val := range builtins.Karaokards {
|
|
selectablePrompts = append(selectablePrompts, val)
|
|
}
|
|
persistentData := openDatabase()
|
|
var dbGlobalPrompts []string
|
|
if err := persistentData.Read("prompts", "global", &dbGlobalPrompts); err != nil {
|
|
persistentData.Write("prompts", "common", dbGlobalPrompts)
|
|
}
|
|
selectablePrompts := append(selectablePrompts, dbGlobalPrompts...)
|
|
|
|
rgb.YPrintf("[%s] %d prompts available.\n", irc.TimeStamp(), len(selectablePrompts))
|
|
ircOauthPath := ""
|
|
if config.IrcOAuthPath == "" {
|
|
if os.Getenv("TSTOOLS_OAUTH_JSON") != "" {
|
|
if _, err := os.Stat(os.Getenv("TSTOOLS_OAUTH_JSON")); os.IsNotExist(err) {
|
|
os.Exit(1)
|
|
}
|
|
ircOauthPath = os.Getenv("TSTOOLS_OAUTH_JSON")
|
|
} else {
|
|
if _, err := os.Stat(os.Getenv("HOME") + "/.tstools/ircoauth.json"); os.IsNotExist(err) {
|
|
rgb.YPrintf("[%s] Warning %s doesn't exist, trying %s next!\n", irc.TimeStamp(), os.Getenv("HOME")+"/.tstools/ircoauth.json", "/etc/tstools/ircoauth.json")
|
|
if _, err := os.Stat("/etc/tstools/ircoauth.json"); os.IsNotExist(err) {
|
|
rgb.YPrintf("[%s] Error %s doesn't exist either, cannot connect to irc!\n", irc.TimeStamp(), "/etc/tstools/ircoauth.json")
|
|
} else {
|
|
ircOauthPath = "/etc/tstools/ircoauth.json"
|
|
}
|
|
} else {
|
|
ircOauthPath = os.Getenv("HOME") + "/.tstools/ircoauth.json"
|
|
}
|
|
}
|
|
} else {
|
|
if _, err := os.Stat(config.IrcOAuthPath); os.IsNotExist(err) {
|
|
rgb.YPrintf("[%s] Error config-specified oauth file %s doesn't exist, cannot connect to irc!\n", irc.TimeStamp(), config.IrcOAuthPath)
|
|
} else {
|
|
ircOauthPath = config.IrcOAuthPath
|
|
}
|
|
}
|
|
appOauthPath := ""
|
|
if config.AppOAuthPath == "" {
|
|
if os.Getenv("TSTOOLS_OAUTH_JSON") != "" {
|
|
if _, err := os.Stat(os.Getenv("TSTOOLS_OAUTH_JSON")); os.IsNotExist(err) {
|
|
os.Exit(1)
|
|
}
|
|
appOauthPath = os.Getenv("TSTOOLS_OAUTH_JSON")
|
|
} else {
|
|
if _, err := os.Stat(os.Getenv("HOME") + "/.tstools/appoauth.json"); os.IsNotExist(err) {
|
|
rgb.YPrintf("[%s] Warning %s doesn't exist, trying %s next!\n", irc.TimeStamp(), os.Getenv("HOME")+"/.tstools/appoauth.json", "/etc/tstools/appoauth.json")
|
|
if _, err := os.Stat("/etc/tstools/appoauth.json"); os.IsNotExist(err) {
|
|
rgb.YPrintf("[%s] Error %s doesn't exist either, bailing!\n", irc.TimeStamp(), "/etc/tstools/appoauth.json")
|
|
os.Exit(1)
|
|
}
|
|
appOauthPath = "/etc/tstools/appoauth.json"
|
|
} else {
|
|
appOauthPath = os.Getenv("HOME") + "/.tstools/appoauth.json"
|
|
}
|
|
}
|
|
} else {
|
|
if _, err := os.Stat(config.AppOAuthPath); os.IsNotExist(err) {
|
|
rgb.RPrintf("[%s] Error config-specified oauth file %s doesn't exist, bailing!\n", irc.TimeStamp(), config.AppOAuthPath)
|
|
os.Exit(1)
|
|
}
|
|
appOauthPath = config.AppOAuthPath
|
|
}
|
|
|
|
rgb.YPrintf("[%s] Starting connection to redis...\n", irc.TimeStamp())
|
|
//TODO: unhardcode this
|
|
if os.Getenv("TSTOOLS_REDIS_HOST") != "" {
|
|
config.DatabaseSVC = os.Getenv("TSTOOLS_REDIS_HOST")
|
|
} else {
|
|
// assume localhost, which should fail.
|
|
config.DatabaseSVC = "localhost"
|
|
}
|
|
var globalData data.GlobalData
|
|
globalData.Config = config
|
|
globalData.ConnectDatabase()
|
|
defer globalData.Database.Close()
|
|
rgb.GPrintf("[%s] Connected to \"redis\" %s\n", irc.TimeStamp(), "config.DatabaseSVC")
|
|
err := globalData.ReadChannelData()
|
|
if nil != err {
|
|
fmt.Println(err)
|
|
fmt.Println("Aborting!")
|
|
os.Exit(1)
|
|
}
|
|
rgb.GPrintf("[%s] Read the channel data from \"redis\" successfully, now have %d records\n", irc.TimeStamp(), len(globalData.ChannelData))
|
|
// Replace the channel name, bot name, and the path to the private directory with your respective
|
|
// values.
|
|
var myBot irc.KardBot
|
|
if ircOauthPath != "" {
|
|
myBot = irc.KardBot{
|
|
Channel: "twitchsingstools",
|
|
MsgRate: time.Duration(20/30) * time.Millisecond,
|
|
Name: "twitchsingstools",
|
|
Port: "6667",
|
|
IrcPrivatePath: ircOauthPath,
|
|
AppPrivatePath: appOauthPath,
|
|
Server: "irc.chat.twitch.tv",
|
|
Prompts: selectablePrompts,
|
|
GlobalData: globalData,
|
|
}
|
|
}
|
|
go func() {
|
|
rgb.YPrintf("[%s] Starting webserver on port %s\n", irc.TimeStamp(), "5353")
|
|
webserver.HandleHTTP(&myBot, &globalData)
|
|
}()
|
|
if ircOauthPath != "" {
|
|
myBot.Start()
|
|
}
|
|
}
|