mirror of
https://github.com/Xevion/banner.git
synced 2025-12-14 16:11:04 -06:00
Add structhash, hash command definition with xxhash, store & compare with redis
This commit is contained in:
1
go.mod
1
go.mod
@@ -8,6 +8,7 @@ require github.com/joho/godotenv v1.5.1
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
||||||
|
github.com/cnf/structhash v0.0.0-20201127153200-e1b16c1ebc08 // indirect
|
||||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
|
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
|
||||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.19 // indirect
|
github.com/mattn/go-isatty v0.0.19 // indirect
|
||||||
|
|||||||
2
go.sum
2
go.sum
@@ -4,6 +4,8 @@ github.com/bwmarrin/discordgo v0.27.1 h1:ib9AIc/dom1E/fSIulrBwnez0CToJE113ZGt4Ho
|
|||||||
github.com/bwmarrin/discordgo v0.27.1/go.mod h1:NJZpH+1AfhIcyQsPeuBKsUtYrRnjkyu0kIVMCHkZtRY=
|
github.com/bwmarrin/discordgo v0.27.1/go.mod h1:NJZpH+1AfhIcyQsPeuBKsUtYrRnjkyu0kIVMCHkZtRY=
|
||||||
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
|
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
|
||||||
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||||
|
github.com/cnf/structhash v0.0.0-20201127153200-e1b16c1ebc08 h1:ox2F0PSMlrAAiAdknSRMDrAr8mfxPCfSZolH+/qQnyQ=
|
||||||
|
github.com/cnf/structhash v0.0.0-20201127153200-e1b16c1ebc08/go.mod h1:pCxVEbcm3AMg7ejXyorUXi6HQCzOIBf7zEDVPtw0/U4=
|
||||||
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
|||||||
55
main.go
55
main.go
@@ -1,13 +1,18 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/base64"
|
||||||
"flag"
|
"flag"
|
||||||
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/cookiejar"
|
"net/http/cookiejar"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
|
|
||||||
"github.com/bwmarrin/discordgo"
|
"github.com/bwmarrin/discordgo"
|
||||||
|
"github.com/cespare/xxhash/v2"
|
||||||
|
"github.com/cnf/structhash"
|
||||||
"github.com/joho/godotenv"
|
"github.com/joho/godotenv"
|
||||||
"github.com/redis/go-redis/v9"
|
"github.com/redis/go-redis/v9"
|
||||||
"github.com/rs/zerolog"
|
"github.com/rs/zerolog"
|
||||||
@@ -20,6 +25,7 @@ var (
|
|||||||
baseURL string
|
baseURL string
|
||||||
client http.Client
|
client http.Client
|
||||||
kv *redis.Client
|
kv *redis.Client
|
||||||
|
ctx context.Context
|
||||||
cookies http.CookieJar
|
cookies http.CookieJar
|
||||||
session *discordgo.Session
|
session *discordgo.Session
|
||||||
RemoveCommands = flag.Bool("rmcmd", true, "Remove all commands after shutdowning or not")
|
RemoveCommands = flag.Bool("rmcmd", true, "Remove all commands after shutdowning or not")
|
||||||
@@ -50,6 +56,8 @@ func (l logOut) WriteLevel(level zerolog.Level, p []byte) (n int, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
ctx = context.Background()
|
||||||
|
|
||||||
// Try to grab the environment variable, or default to development
|
// Try to grab the environment variable, or default to development
|
||||||
env := os.Getenv("ENVIRONMENT")
|
env := os.Getenv("ENVIRONMENT")
|
||||||
if env == "" {
|
if env == "" {
|
||||||
@@ -83,6 +91,13 @@ func main() {
|
|||||||
}
|
}
|
||||||
kv = redis.NewClient(options)
|
kv = redis.NewClient(options)
|
||||||
|
|
||||||
|
// Test the redis instance
|
||||||
|
pong, err := kv.Ping(ctx).Result()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal().Err(err).Msg("Cannot connect to redis")
|
||||||
|
}
|
||||||
|
log.Debug().Str("ping", pong).Msg("Redis connection successful")
|
||||||
|
|
||||||
// Create cookie jar
|
// Create cookie jar
|
||||||
cookies, err = cookiejar.New(nil)
|
cookies, err = cookiejar.New(nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -128,14 +143,39 @@ func main() {
|
|||||||
// Register commands
|
// Register commands
|
||||||
registeredCommands := make([]*discordgo.ApplicationCommand, len(commandDefinitions))
|
registeredCommands := make([]*discordgo.ApplicationCommand, len(commandDefinitions))
|
||||||
for i, cmdDefinition := range commandDefinitions {
|
for i, cmdDefinition := range commandDefinitions {
|
||||||
cmdInstance, err := session.ApplicationCommandCreate(session.State.User.ID, os.Getenv("BOT_TARGET_GUILD"), cmdDefinition)
|
// Compare the hash to the hash stored in redis
|
||||||
|
hash := xxhash.Sum64(structhash.Dump(cmdDefinition, 1))
|
||||||
|
key := fmt.Sprintf("command:%s:xxhash", cmdDefinition.Name)
|
||||||
|
keyB64 := base64.StdEncoding.EncodeToString([]byte(key))
|
||||||
|
storedHash, err := kv.Get(ctx, key).Uint64()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Panic().Err(err).Str("name", cmdDefinition.Name).Msgf("Cannot register command")
|
if err != redis.Nil {
|
||||||
|
log.Err(err).Msg("Cannot get command hash from redis")
|
||||||
|
} else {
|
||||||
|
log.Debug().Str("command", cmdDefinition.Name).Str("key", keyB64).Msg("Command hash not found in redis")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the hash is the same, skip registering the command
|
||||||
|
if hash == storedHash {
|
||||||
|
log.Debug().Str("command", cmdDefinition.Name).Str("key", keyB64).Msg("Command hash matches, skipping registration")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Register the command
|
||||||
|
cmdInstance, err := session.ApplicationCommandCreate(session.State.User.ID, "", cmdDefinition)
|
||||||
|
if err != nil {
|
||||||
|
log.Panic().Err(err).Str("name", cmdDefinition.Name).Str("key", keyB64).Msg("Cannot register command")
|
||||||
|
}
|
||||||
|
err = kv.Set(ctx, key, hash, 0).Err()
|
||||||
|
if err != nil {
|
||||||
|
log.Err(err).Str("name", cmdDefinition.Name).Str("key", keyB64).Msg("Cannot set command hash in redis")
|
||||||
}
|
}
|
||||||
registeredCommands[i] = cmdInstance
|
registeredCommands[i] = cmdInstance
|
||||||
|
log.Info().Str("name", cmdDefinition.Name).Str("key", keyB64).Msg("Registered command")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cloes session, ensure
|
// Cloes session, ensure http client closes idle connections
|
||||||
defer session.Close()
|
defer session.Close()
|
||||||
defer client.CloseIdleConnections()
|
defer client.CloseIdleConnections()
|
||||||
|
|
||||||
@@ -144,15 +184,6 @@ func main() {
|
|||||||
log.Info().Msg("Press Ctrl+C to exit")
|
log.Info().Msg("Press Ctrl+C to exit")
|
||||||
<-stop
|
<-stop
|
||||||
|
|
||||||
if *RemoveCommands {
|
|
||||||
for _, cmd := range registeredCommands {
|
|
||||||
err := session.ApplicationCommandDelete(session.State.User.ID, os.Getenv("BOT_TARGET_GUILD"), cmd.ID)
|
|
||||||
if err != nil {
|
|
||||||
log.Err(err).Str("command", cmd.Name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Warn().Msg("Gracefully shutting down")
|
log.Warn().Msg("Gracefully shutting down")
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user