diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..de0c700b9fdfd6c4df734a93f0d4394ade5bfc92 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +server.conf diff --git a/cleanup.go b/cleanup.go new file mode 100644 index 0000000000000000000000000000000000000000..6e7957e59c96a1f0511acd26cb4735666a6fbaf7 --- /dev/null +++ b/cleanup.go @@ -0,0 +1,14 @@ +package main + +import ( + "git.randomchars.net/freenitori/log" + "os" +) + +func cleanup() { + // Close session + if err := session.Close(); err != nil { + log.Fatalf("Error closing session, %s", err) + os.Exit(1) + } +} diff --git a/command.go b/command.go new file mode 100644 index 0000000000000000000000000000000000000000..1b5f242ed72f76f7fb8b24f4458c3b9c92a3c5d1 --- /dev/null +++ b/command.go @@ -0,0 +1,38 @@ +package main + +import ( + "git.randomchars.net/freenitori/log" + "git.randomchars.net/freenitori/multiplexer" +) + +func init() { + m.Route(&multiplexer.Route{ + Pattern: "ping", + AliasPatterns: []string{"pong"}, + Description: "ping pong.", + Category: system, + Handler: func(context *multiplexer.Context) { + err := Database.Set("key", "hello world") + if err != nil { + log.Info(err) + } + context.Session.ChannelMessageSend(context.Channel.ID, "Pong") + log.Infof("Pong! " + context.User.Username) + }, + }) + + m.Route(&multiplexer.Route{ + Pattern: "get", + AliasPatterns: []string{"value"}, + Description: "database test.", + Category: system, + Handler: func(context *multiplexer.Context) { + data, err := Database.Get("key2") + if err != nil { + log.Info(err) + } + context.Session.ChannelMessageSend(context.Channel.ID, "getting value " + data) + log.Infof("Nice! " + context.User.Username ) + }, + }) +} diff --git a/config.go b/config.go new file mode 100644 index 0000000000000000000000000000000000000000..d996c55cd561d2975e46152b632a00d135d0079d --- /dev/null +++ b/config.go @@ -0,0 +1,46 @@ +package main + +import ( + "flag" + "git.randomchars.net/freenitori/log" + "github.com/BurntSushi/toml" + "os" +) + +var config configPayload +var configPath string +var defaultConfig = configPayload{ + Prefix: "!", + Token: "TOKEN", +} + +type configPayload struct { + Prefix string + Token string +} + +func init() { + flag.StringVar(&configPath, "c", "server.conf", "Specify configuration file location.") +} + +func parse() { + if _, err := toml.DecodeFile(configPath, &config); err != nil { + if os.IsNotExist(err) { + var file *os.File + if file, err = os.Create(configPath); err != nil { + log.Fatalf("Error while creating configuration file, %s", err) + os.Exit(1) + } + if err = toml.NewEncoder(file).Encode(defaultConfig); err != nil { + log.Fatalf("Error while encoding default configuration, %s", err) + os.Exit(1) + } + log.Warnf("Default configuration generated at %s, edit before next startup.", configPath) + os.Exit(1) + } + log.Fatalf("Error while decoding configuration file, %s", err) + os.Exit(1) + } else { + log.Infof("Loaded config at %s.", configPath) + } +} \ No newline at end of file diff --git a/database.go b/database.go new file mode 100644 index 0000000000000000000000000000000000000000..7c26c776c95241679710472a17f27cfc63d4b804 --- /dev/null +++ b/database.go @@ -0,0 +1,40 @@ +package main + +import ( + ldb "github.com/syndtr/goleveldb/leveldb" +) + +var Database LevelDB + +type LevelDB struct { + database *ldb.DB +} + +func (db *LevelDB) Open(path string) error { + if instance, err := ldb.OpenFile(path, nil); err != nil { + return err + } else { + db.database = instance + } + return nil +} + +func (db *LevelDB) Get(key string) (string, error) { + + data , err := db.database.Get([]byte(key), nil) + + if err != nil { + return string(data), err + } + + return string(data), err +} + +func (db *LevelDB) Set(key, value string) error { + err := db.database.Put([]byte(key), []byte(value), nil) + if err != nil { + return err + } else { + return nil + } +} \ No newline at end of file diff --git a/go.mod b/go.mod new file mode 100644 index 0000000000000000000000000000000000000000..a3e0a32f55f7f54c3717e2a4e6b0f61b128dcd44 --- /dev/null +++ b/go.mod @@ -0,0 +1,18 @@ +module main + +go 1.17 + +require ( + git.randomchars.net/freenitori/embedutil v1.0.2 // indirect + git.randomchars.net/freenitori/log v1.0.0 // indirect + git.randomchars.net/freenitori/multiplexer v1.0.14 // indirect + github.com/BurntSushi/toml v0.4.1 // indirect + github.com/bwmarrin/discordgo v0.23.2 // indirect + github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db // indirect + github.com/gorilla/websocket v1.4.0 // indirect + github.com/magefile/mage v1.10.0 // indirect + github.com/sirupsen/logrus v1.8.0 // indirect + github.com/syndtr/goleveldb v1.0.0 // indirect + golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16 // indirect + golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000000000000000000000000000000000000..13ee06da815ba79161064c94c82933a04fc8c94e --- /dev/null +++ b/go.sum @@ -0,0 +1,41 @@ +git.randomchars.net/freenitori/embedutil v1.0.2 h1:8A3zSLkRRpslR0VG3vwtgxcEka4A163+K7UsKVhkHhs= +git.randomchars.net/freenitori/embedutil v1.0.2/go.mod h1:ELkCpzF7OBB7Mn//AdkRNkmj+M61DPWllArBgX3A8x4= +git.randomchars.net/freenitori/log v1.0.0 h1:hU99jGk940I1O5OcaTfnXOpN8ozXiarxhu6xpL0xe7c= +git.randomchars.net/freenitori/log v1.0.0/go.mod h1:YZFRZgVWDIrbyDGHyDeRlIRWeq0DXamXONxIt12eq2Q= +git.randomchars.net/freenitori/multiplexer v1.0.14 h1:j6r0dhI+VBDDog7Uc8a492vSSdu/BfiivweTF1sAFK8= +git.randomchars.net/freenitori/multiplexer v1.0.14/go.mod h1:Bx9vu2RXDtBrsKBslrhrc8v3IJl5Dna7I/rsHF586w0= +github.com/BurntSushi/toml v0.4.1 h1:GaI7EiDXDRfa8VshkTj7Fym7ha+y8/XxIgD2okUIjLw= +github.com/BurntSushi/toml v0.4.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/bwmarrin/discordgo v0.23.2 h1:BzrtTktixGHIu9Tt7dEE6diysEF9HWnXeHuoJEt2fH4= +github.com/bwmarrin/discordgo v0.23.2/go.mod h1:c1WtWUGN6nREDmzIpyTp/iD3VYt4Fpx+bVyfBG7JE+M= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db h1:woRePGFeVFfLKN/pOkfl+p/TAqKOfFu+7KPlMVpok/w= +github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q= +github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/magefile/mage v1.10.0 h1:3HiXzCUY12kh9bIuyXShaVe529fJfyqoVM42o/uom2g= +github.com/magefile/mage v1.10.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/sirupsen/logrus v1.8.0 h1:nfhvjKcUMhBMVqbKHJlk5RPrrfYr/NMo3692g0dwfWU= +github.com/sirupsen/logrus v1.8.0/go.mod h1:4GuYW9TZmE769R5STWrRakJc4UqQ3+QQ95fyz7ENv1A= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE= +github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ= +golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16 h1:y6ce7gCWtnH+m3dCjzQ1PCuwl28DDIc3VNnvY29DlIA= +golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 h1:YyJpGZS1sBuBCzLAR1VEpK193GlqGZbnPFnPV/5Rsb4= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/handler.go b/handler.go new file mode 100644 index 0000000000000000000000000000000000000000..88558293cfc86666d49a01eb2302a20561222fa0 --- /dev/null +++ b/handler.go @@ -0,0 +1,14 @@ +package main + +import ( + "git.randomchars.net/freenitori/log" + "git.randomchars.net/freenitori/multiplexer" +) + +func init() { + m.MessageCreate = append(m.MessageCreate, messageHandler) +} + +func messageHandler(context *multiplexer.Context) { + log.Infof(context.User.Username + "#" + context.User.Discriminator + " sent the following message: " + context.Message.Content) +} \ No newline at end of file diff --git a/main.go b/main.go new file mode 100644 index 0000000000000000000000000000000000000000..e9f6f32d904ef56156f9c4fff6ef3d4d3352c863 --- /dev/null +++ b/main.go @@ -0,0 +1,132 @@ +package main + +import ( + "flag" + "fmt" + "git.randomchars.net/freenitori/log" + "git.randomchars.net/freenitori/multiplexer" + "github.com/bwmarrin/discordgo" + "github.com/sirupsen/logrus" + "os" + "os/signal" + "syscall" +) + +var ( + session *discordgo.Session + m = multiplexer.New() + system = multiplexer.NewCategory("System", "System-related utilities.") + verbose bool +) + +func init() { + flag.BoolVar(&verbose, "v", false, "Start up with debug logging.") +} + +func main() { + flag.Parse() + parse() + + if verbose { + log.SetLevel(logrus.DebugLevel) + } else { + log.SetLevel(logrus.InfoLevel) + } + + // Set discordgo log handler + discordgo.Logger = func(msgL, _ int, format string, a ...interface{}) { + var level logrus.Level + switch msgL { + case discordgo.LogDebug: + level = logrus.DebugLevel + case discordgo.LogInformational: + level = logrus.InfoLevel + case discordgo.LogWarning: + level = logrus.WarnLevel + case discordgo.LogError: + level = logrus.ErrorLevel + } + log.Instance.Log(level, fmt.Sprintf(format, a...)) + } + + // Set command not found handler + multiplexer.NoCommandMatched = func(context *multiplexer.Context) { + } + + // Configure session + if s, err := discordgo.New(); err != nil { + log.Fatalf("Error while creating session, %s", err) + os.Exit(1) + } else { + session = s + } + session.UserAgent = "DiscordBot (voice-bot)" + session.Token = "Bot " + config.Token + session.ShouldReconnectOnError = true + session.Identify.Intents = discordgo.IntentsAll + session.State.TrackVoice = true + + // Open session + func() { + open: + if err := session.Open(); err != nil { + if session.Identify.Intents == discordgo.IntentsAll { + log.Warnf("Wasn't able to start with full intents, some stuff might not work (%s)", err) + session.Identify.Intents = discordgo.IntentsAllWithoutPrivileged + goto open + } + + log.Fatalf("Error while opening session, %s", err) + os.Exit(1) + } + }() + + + // Setup multiplexer + m.SessionRegisterHandlers(session) + m.Prefix = config.Prefix + m.Categories = append(m.Categories, system) + err := Database.Open("/tmp/test.db") + if err != nil { + log.Info(err) + } + // Output message + log.Infof("Logged in as %s#%s (%s).", + session.State.User.Username, + session.State.User.Discriminator, + session.State.User.ID) + if application, err := session.Application("@me"); err != nil { + log.Fatalf("Unable to get application, %s", err) + os.Exit(1) + } else { + log.Infof("Invite URL: https://discord.com/oauth2/authorize?client_id=%s&scope=bot&permissions=8", application.ID) + } + + // Signal handling + signalChannel := make(chan os.Signal, 1) + signal.Notify(signalChannel, syscall.SIGINT, syscall.SIGTERM, syscall.SIGHUP, os.Interrupt, syscall.SIGTERM) + var exit int + func() { + for { + currentSignal := <-signalChannel + switch currentSignal { + case os.Interrupt: + exit = 0 + println() + log.Info("Gracefully exiting.") + return + default: + exit = 0 + log.Info("Gracefully exiting.") + return + } + } + }() + + switch exit { + case 0: + cleanup() + default: + os.Exit(exit) + } +}