diff --git a/commands.go b/commands.go new file mode 100644 index 0000000..50a0ba2 --- /dev/null +++ b/commands.go @@ -0,0 +1,25 @@ +package main + +import "github.com/Karitham/corde" + +var ( + appCommand = corde.NewSlashCommand("app", "App commands", + corde.NewSubcommand("accept", "Accept an app", + corde.NewIntOption("app_id", "App ID", true), + ), + corde.NewSubcommand("deny", "Deny an app", + corde.NewIntOption("app_id", "App ID", true), + ), + corde.NewSubcommand("clear", "Clear an app", + corde.NewIntOption("app_id", "App ID", true), + ), + ) + infoCommand = corde.NewSlashCommand("info", "Info on an app", + corde.NewStringOption("username", "Username", false), + corde.NewIntOption("app_id", "App ID", false), + ) + searchCommand = corde.NewSlashCommand("search", "Searhc for apps", + corde.NewStringOption("username", "Username", false), + ) + syncCommand = corde.NewSlashCommand("sync", "Sync users with Discord") +) diff --git a/database/application.go b/database/application.go index 900fe4d..d180cca 100644 --- a/database/application.go +++ b/database/application.go @@ -19,6 +19,10 @@ type Application struct { Date string `db:"date"` } +func (a *Application) EscapeUsername() string { + return strings.ReplaceAll(a.Username, "_", `\_`) +} + func (a *Application) Status() string { switch { case !a.Accepted.Valid: diff --git a/database/player.go b/database/player.go index 553710f..9b0f393 100644 --- a/database/player.go +++ b/database/player.go @@ -18,6 +18,10 @@ type Player struct { DiscordID sql.NullString `db:"discord_id"` } +func (p *Player) EscapeUsername() string { + return strings.ReplaceAll(p.Username, "_", `\_`) +} + func (p *Player) String() string { return p.Username } @@ -50,6 +54,13 @@ func (d *Database) PlayersByDiscordIsNull() (pl []*Player, err error) { return pl, d.db.Select(pl, playersByDiscordIsNullSQL) } +//go:embed queries/players_by_discord_isnull_count.sql +var playersByDiscordIsNullCountSQL string + +func (d *Database) PlayersByDiscordIsNullCount() (count int64, err error) { + return count, d.db.Get(&count, playersByDiscordIsNullCountSQL) +} + //go:embed queries/player_update_application.sql var playerUpdateApplicationSQL string diff --git a/database/queries/players_by_discord_isnull_count.sql b/database/queries/players_by_discord_isnull_count.sql new file mode 100644 index 0000000..d9600a1 --- /dev/null +++ b/database/queries/players_by_discord_isnull_count.sql @@ -0,0 +1,3 @@ +SELECT COUNT(*) +FROM minecraft_manager_player +WHERE discord_id IS NULL; \ No newline at end of file diff --git a/discord/action.go b/discord/action.go index 1db7331..24b60ea 100644 --- a/discord/action.go +++ b/discord/action.go @@ -12,14 +12,14 @@ func (d Discord) accept(w corde.ResponseWriter, i *corde.Interaction) { app, err := d.store.ApplicationByID(id) if err != nil { - w.Respond(corde.NewResp().Contentf("No application #%d was found.", id).Ephemeral().B()) + w.Respond(corde.NewResp().Contentf("No application #%d was found.", id).Ephemeral()) return } if !app.Accepted.Bool { t := true if err := d.store.ApplicationUpdateAccepted(&t, app.ID); err != nil { - w.Respond(corde.NewResp().Contentf("Could not accept application #%d.", id).Ephemeral().B()) + w.Respond(corde.NewResp().Contentf("Could not accept application #%d.", id).Ephemeral()) return } @@ -28,20 +28,20 @@ func (d Discord) accept(w corde.ResponseWriter, i *corde.Interaction) { if errors.Is(err, sql.ErrNoRows) { return } - w.Respond(corde.NewResp().Contentf("Could not link player to application", id).Ephemeral().B()) + w.Respond(corde.NewResp().Contentf("Could not link player to application", id).Ephemeral()) return } if err := d.store.PlayerUpdateApplication(app.ID, players[0].ID); err != nil { - w.Respond(corde.NewResp().Contentf("Could not link player to application", id).Ephemeral().B()) + w.Respond(corde.NewResp().Contentf("Could not link player to application", id).Ephemeral()) } if err := d.sock.Command("accept", app.Username); err != nil { - w.Respond(corde.NewResp().Contentf("Could not accept player in-game, is the server running?", id).Ephemeral().B()) + w.Respond(corde.NewResp().Contentf("Could not accept player in-game, is the server running?", id).Ephemeral()) return } - w.Respond(corde.NewResp().Contentf("Application #%d was successfully accepted.", id).B()) + w.Respond(corde.NewResp().Contentf("Application #%d was successfully accepted.", id)) } } @@ -50,14 +50,14 @@ func (d Discord) deny(w corde.ResponseWriter, i *corde.Interaction) { app, err := d.store.ApplicationByID(id) if err != nil { - w.Respond(corde.NewResp().Contentf("No application #%d was found.", id).Ephemeral().B()) + w.Respond(corde.NewResp().Contentf("No application #%d was found.", id).Ephemeral()) return } if !app.Accepted.Bool { f := false if err := d.store.ApplicationUpdateAccepted(&f, app.ID); err != nil { - w.Respond(corde.NewResp().Contentf("Could not deny application #%d.", id).Ephemeral().B()) + w.Respond(corde.NewResp().Contentf("Could not deny application #%d.", id).Ephemeral()) return } @@ -66,20 +66,20 @@ func (d Discord) deny(w corde.ResponseWriter, i *corde.Interaction) { if errors.Is(err, sql.ErrNoRows) { return } - w.Respond(corde.NewResp().Contentf("Could not link player to application", id).Ephemeral().B()) + w.Respond(corde.NewResp().Contentf("Could not link player to application", id).Ephemeral()) return } if err := d.store.PlayerUpdateApplication(app.ID, players[0].ID); err != nil { - w.Respond(corde.NewResp().Contentf("Could not link player to application", id).Ephemeral().B()) + w.Respond(corde.NewResp().Contentf("Could not link player to application", id).Ephemeral()) } if err := d.sock.Command("deny", app.Username); err != nil { - w.Respond(corde.NewResp().Contentf("Could not deny player in-game, is the server running?", id).Ephemeral().B()) + w.Respond(corde.NewResp().Contentf("Could not deny player in-game, is the server running?", id).Ephemeral()) return } - w.Respond(corde.NewResp().Contentf("Application #%d was successfully denied.", id).B()) + w.Respond(corde.NewResp().Contentf("Application #%d was successfully denied.", id)) } } @@ -88,14 +88,14 @@ func (d Discord) clear(w corde.ResponseWriter, i *corde.Interaction) { app, err := d.store.ApplicationByID(id) if err != nil { - w.Respond(corde.NewResp().Contentf("No application #%d was found.", id).Ephemeral().B()) + w.Respond(corde.NewResp().Contentf("No application #%d was found.", id).Ephemeral()) return } if !app.Accepted.Bool { f := false if err := d.store.ApplicationUpdateAccepted(&f, app.ID); err != nil { - w.Respond(corde.NewResp().Contentf("Could not clear application #%d.", id).Ephemeral().B()) + w.Respond(corde.NewResp().Contentf("Could not clear application #%d.", id).Ephemeral()) return } @@ -104,14 +104,14 @@ func (d Discord) clear(w corde.ResponseWriter, i *corde.Interaction) { if errors.Is(err, sql.ErrNoRows) { return } - w.Respond(corde.NewResp().Contentf("Could not link player to application", id).Ephemeral().B()) + w.Respond(corde.NewResp().Contentf("Could not link player to application", id).Ephemeral()) return } if err := d.store.PlayerUpdateApplication(app.ID, players[0].ID); err != nil { - w.Respond(corde.NewResp().Contentf("Could not link player to application", id).Ephemeral().B()) + w.Respond(corde.NewResp().Contentf("Could not link player to application", id).Ephemeral()) } - w.Respond(corde.NewResp().Contentf("Application #%d was successfully cleared.", id).B()) + w.Respond(corde.NewResp().Contentf("Application #%d was successfully cleared.", id)) } } diff --git a/discord/info.go b/discord/info.go index 56500f9..d966008 100644 --- a/discord/info.go +++ b/discord/info.go @@ -8,14 +8,14 @@ import ( "github.com/Karitham/corde" ) -func appResponse(app *database.Application) *corde.InteractionRespData { +func appResponse(app *database.Application) *corde.RespB { embed := corde.NewEmbed(). Color(0x417505). Title("Application"). Thumbnail(corde.Image{ URL: fmt.Sprintf("https://minotar.net/helm/%s/100.png", app.Username), }). - Field("Username", strings.ReplaceAll(app.Username, "_", `\_`)). + Field("Username", app.EscapeUsername()). Field("Age", fmt.Sprint(app.Age)). Field("Type of Player", app.PlayerType). Field("Ever been Banned", fmt.Sprint(app.EverBanned)) @@ -27,14 +27,14 @@ func appResponse(app *database.Application) *corde.InteractionRespData { } embed.Field("Read the Rules", app.ReadRules). Field("Status", app.Status()) - return corde.NewResp().Embeds(embed.B()).B() + return corde.NewResp().Embeds(embed) } func (d Discord) info(w corde.ResponseWriter, i *corde.Interaction) { id := i.Data.Options.Int64("app_id") username := i.Data.Options.String("username") if id == 0 && username == "" { - w.Respond(corde.NewResp().Content("Info requires an application ID or username.").Ephemeral().B()) + w.Respond(corde.NewResp().Content("Info requires an application ID or username.").Ephemeral()) return } @@ -43,19 +43,19 @@ func (d Discord) info(w corde.ResponseWriter, i *corde.Interaction) { if id != 0 { app, err = d.store.ApplicationByID(id) if err != nil { - w.Respond(corde.NewResp().Contentf("No application #%d was found.", id).Ephemeral().B()) + w.Respond(corde.NewResp().Contentf("No application #%d was found.", id).Ephemeral()) return } } else { apps, err := d.store.ApplicationsByUsername(username) if err != nil { - w.Respond(corde.NewResp().Content("No applications matched.").Ephemeral().B()) + w.Respond(corde.NewResp().Content("No applications matched.").Ephemeral()) return } if len(apps) == 0 { apps, err = d.store.ApplicationsByPlayerUsername(username) if err != nil { - w.Respond(corde.NewResp().Content("No applications matched.").Ephemeral().B()) + w.Respond(corde.NewResp().Content("No applications matched.").Ephemeral()) return } if len(apps) == 1 { @@ -66,7 +66,7 @@ func (d Discord) info(w corde.ResponseWriter, i *corde.Interaction) { } } - w.Respond(appResponse(app)) + w.Respond(appResponse(app).Ephemeral()) } func (d Discord) search(w corde.ResponseWriter, i *corde.Interaction) { @@ -74,22 +74,69 @@ func (d Discord) search(w corde.ResponseWriter, i *corde.Interaction) { apps, err := d.store.ApplicationsByUsername(username) if err != nil { - w.Respond(corde.NewResp().Content("No applications matched.").Ephemeral().B()) + w.Respond(corde.NewResp().Content("No applications matched.").Ephemeral()) return } count, err := d.store.ApplicationsByUsernameCount(username) if err != nil { - w.Respond(corde.NewResp().Content("No applications matched.").Ephemeral().B()) + w.Respond(corde.NewResp().Content("No applications matched.").Ephemeral()) return } - var app *database.Application if count > 0 { if count == 1 { - app = apps[0] + w.Respond(appResponse(apps[0]).Ephemeral()) + return } else { + var sb strings.Builder + sb.WriteString("**Found the following applications**") + for _, app := range apps { + sb.WriteString(fmt.Sprintf("\n%d - %s (%s)", app.ID, app.EscapeUsername(), app.Status())) + } + if count > 10 { + sb.WriteString(fmt.Sprintf("\n**This is only 10 applications out of %d found. Please narrow your search if possible.**", count)) + } + w.Respond(corde.NewResp().Content(sb.String()).Ephemeral()) } } - w.Respond(appResponse(app)) + players, err := d.store.PlayersByUsernameApplicationNotNull(username) + if err != nil { + w.Respond(corde.NewResp().Content("No applications matched.").Ephemeral()) + return + } + count, err = d.store.PlayersByUsernameApplicationNotNullCount(username) + if err != nil { + w.Respond(corde.NewResp().Content("No applications matched.").Ephemeral()) + return + } + + if count > 0 { + if count == 1 { + app, err := d.store.ApplicationByID(players[0].ApplicationID.Int64) + if err != nil { + w.Respond(corde.NewResp().Content("No applications matched.").Ephemeral()) + return + } + w.Respond(appResponse(app).Ephemeral()) + return + } else { + var sb strings.Builder + sb.WriteString("**No applications matched, however there are player matches**") + for _, player := range players { + app, err := d.store.ApplicationByID(player.ApplicationID.Int64) + if err != nil { + w.Respond(corde.NewResp().Content("No applications matched.").Ephemeral()) + return + } + sb.WriteString(fmt.Sprintf("\n%d - %s AKA %s (%s)", app.ID, app.EscapeUsername(), player.EscapeUsername(), app.Status())) + } + if count > 10 { + sb.WriteString(fmt.Sprintf("\n**This is only 10 players out of %d found. Please narrow your search if possible.**", count)) + } + w.Respond(corde.NewResp().Content(sb.String()).Ephemeral()) + } + } + + w.Respond(corde.NewResp().Content("No applications matched.").Ephemeral()) } diff --git a/discord/mux.go b/discord/mux.go index 1587cbf..b8e7bd7 100644 --- a/discord/mux.go +++ b/discord/mux.go @@ -16,6 +16,7 @@ type Storer interface { PlayersByUsernameApplicationNotNull(string) ([]*database.Player, error) PlayersByUsernameApplicationNotNullCount(string) (int64, error) PlayersByDiscordIsNull() ([]*database.Player, error) + PlayersByDiscordIsNullCount() (int64, error) PlayerUpdateApplication(int64, int64) error PlayerUpdateDiscordID(string, int64) error } @@ -23,6 +24,7 @@ type Storer interface { type Discord struct { store Storer sock *socket.Socket + token string Mux *corde.Mux } @@ -32,6 +34,7 @@ func New(store Storer, sock *socket.Socket, publicKey, appID, botToken string) * d := &Discord{ store: store, sock: sock, + token: botToken, Mux: m, } @@ -46,7 +49,7 @@ func New(store Storer, sock *socket.Socket, publicKey, appID, botToken string) * m.Command("clear", d.clear) }) // Sync - m.Command("sync", nil) + m.Command("sync", d.sync) return d } diff --git a/discord/rest/rest.go b/discord/rest/rest.go new file mode 100644 index 0000000..6ca9a8b --- /dev/null +++ b/discord/rest/rest.go @@ -0,0 +1,58 @@ +package rest + +import ( + "encoding/json" + "fmt" + "net/http" +) + +const memberEndpoint = "https://discord.com/api/v9/guilds/%s/members?after=%s" + +func Members(guildID, token string) ([]Member, error) { + var mems []Member + + after := "0" + for { + m, err := members(guildID, token, after) + if err != nil { + return nil, err + } + mems = append(mems, m...) + if len(mems) < 1000 { + break + } + after = mems[len(mems)-1].User.ID + } + + return mems, nil +} + +func members(guildID, token, after string) ([]Member, error) { + var members []Member + + req, err := http.NewRequest(http.MethodGet, fmt.Sprintf(memberEndpoint, guildID, after), nil) + if err != nil { + return nil, err + } + req.Header.Set("Authorization", "Bot "+token) + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + if err := json.NewDecoder(resp.Body).Decode(&members); err != nil { + return nil, err + } + + return members, nil +} + +type Member struct { + Nick string `json:"nick"` + User struct { + ID string `json:"id"` + Username string `json:"username"` + } `json:"user"` +} diff --git a/discord/sync.go b/discord/sync.go index d9f7d22..d1be7ad 100644 --- a/discord/sync.go +++ b/discord/sync.go @@ -1 +1,61 @@ package discord + +import ( + "fmt" + "strings" + + "git.jojodev.com/minecraft/mcm-discord/database" + "git.jojodev.com/minecraft/mcm-discord/discord/rest" + "github.com/Karitham/corde" +) + +func (d Discord) sync(w corde.ResponseWriter, i *corde.Interaction) { + members, err := rest.Members(i.GuildID.String(), d.token) + if err != nil { + w.Respond(corde.NewResp().Content("Could not sync.").Ephemeral()) + return + } + + syncPlayer := func(pl *database.Player) (bool, error) { + for _, member := range members { + name := member.Nick + if name == "" { + name = member.User.Username + } + if strings.EqualFold(pl.Username, name) { + return true, d.store.PlayerUpdateDiscordID(member.User.ID, pl.ID) + } + } + return false, nil + } + + players, err := d.store.PlayersByDiscordIsNull() + if err != nil { + w.Respond(corde.NewResp().Content("Could not sync.").Ephemeral()) + return + } + needed, err := d.store.PlayersByDiscordIsNullCount() + if err != nil { + w.Respond(corde.NewResp().Content("Could not sync.").Ephemeral()) + return + } + + var synced []string + var notSynced []string + if needed > 0 { + for _, player := range players { + ok, err := syncPlayer(player) + if err != nil { + w.Respond(corde.NewResp().Content("Could not sync.").Ephemeral()) + return + } + if ok { + synced = append(synced, player.Username) + continue + } + notSynced = append(notSynced, player.Username) + } + } + txt := fmt.Sprintf("Synced\n\t%s\n\nNot Synced\n\t%s", strings.Join(synced, "\n\t"), strings.Join(notSynced, "\n\t")) + w.Respond(corde.NewResp().Attachment(strings.NewReader(txt), "sync.txt").Contentf("Successfully synced %d/%d players.", len(synced), needed)) +} diff --git a/go.mod b/go.mod index d9ca654..7b3d2cb 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,8 @@ require ( ) require ( - github.com/Karitham/corde v0.5.0 // indirect + github.com/Karitham/corde v0.5.1-0.20220106205813-fc0fcd4a872f // indirect github.com/akrennmair/go-radix v1.0.1-0.20211215212324-49d05194b0a3 // indirect + github.com/peterbourgon/ff/v3 v3.1.2 // indirect github.com/rs/zerolog v1.26.1 // indirect ) diff --git a/go.sum b/go.sum index baff890..49ac286 100644 --- a/go.sum +++ b/go.sum @@ -1,8 +1,12 @@ +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/Karitham/corde v0.5.0 h1:Y/H0uwRqTWlGfVt76Bto1BB338DZwZkwzhuqbvE8Vec= github.com/Karitham/corde v0.5.0/go.mod h1:1HP9kpDAN1293JjCv+IrE9xKI0seOm5ZORWm9Z0A4k0= +github.com/Karitham/corde v0.5.1-0.20220106205813-fc0fcd4a872f h1:wPUWbFE/Hhp8uCsyvfvVbINnBd0OYHd35YtXrT9bRd4= +github.com/Karitham/corde v0.5.1-0.20220106205813-fc0fcd4a872f/go.mod h1:37EsBl0rfe6S3+vsWzkUaYRxLw5iVguX2hMC5PbGCkc= github.com/akrennmair/go-radix v1.0.1-0.20211215212324-49d05194b0a3 h1:cC+usowX2qUArGE+BauZSn2qCxHqBXhBmA3CkFMULBg= github.com/akrennmair/go-radix v1.0.1-0.20211215212324-49d05194b0a3/go.mod h1:YPJ4C/zdh9bNuHZCccyEX3xnq7vtjMw2Lu8RgBohgRk= github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= @@ -13,6 +17,9 @@ github.com/lib/pq v1.2.0 h1:LXpIM/LZ5xGFhOpXAQUIMM1HdyqzVYM13zNdjCEEcA0= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/mattn/go-sqlite3 v1.14.6 h1:dNPt6NO46WmLVt2DLNpwczCmdV5boIZ6g/tlDrlRUbg= github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= +github.com/pelletier/go-toml v1.6.0/go.mod h1:5N711Q9dKgbdkxHL+MEfF31hpT7l0S0s/t2kKREewys= +github.com/peterbourgon/ff/v3 v3.1.2 h1:0GNhbRhO9yHA4CC27ymskOsuRpmX0YQxwxM9UPiP6JM= +github.com/peterbourgon/ff/v3 v3.1.2/go.mod h1:XNJLY8EIl6MjMVjBS4F0+G0LYoAqs0DTa4rmHHukKDE= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rs/zerolog v1.26.1 h1:/ihwxqH+4z8UxyI70wM1z9yCvkWcfz/a3mj48k/Zngc= @@ -43,3 +50,5 @@ golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/main.go b/main.go index da29a2c..79ee4a5 100644 --- a/main.go +++ b/main.go @@ -1,4 +1,42 @@ package main +import ( + "flag" + "fmt" + "os" + + "git.jojodev.com/minecraft/mcm-discord/database" + "git.jojodev.com/minecraft/mcm-discord/discord" + "git.jojodev.com/minecraft/mcm-discord/socket" + "github.com/peterbourgon/ff/v3" + + "github.com/rs/zerolog" + "github.com/rs/zerolog/log" +) + func main() { + log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr}) + + fs := flag.NewFlagSet("mcm-discord", flag.ExitOnError) + dns := flag.String("dns", "", "MariaDB DNS") + port := flag.Int("port", 8080, "Port to listen on") + pluginPort := flag.Int("plugin-port", 0, "Plugin port for socket connection") + publicKey := fs.String("public-ket", "", "App public key") + appID := fs.String("app-id", "", "App ID") + botToken := fs.String("bot-token", "", "Bot token") + if err := ff.Parse(fs, os.Args[1:], ff.WithEnvVarPrefix("MCM")); err != nil { + log.Fatal().Err(err).Msg("") + } + + store, err := database.New(*dns) + if err != nil { + log.Fatal().Err(err).Msg("") + } + sock := &socket.Socket{Port: *pluginPort} + + mux := discord.New(store, sock, *publicKey, *appID, *botToken) + + if err := mux.Mux.ListenAndServe(fmt.Sprintf(":%d", *port)); err != nil { + log.Fatal().Err(err).Msg("") + } }