Start working on mux

Signed-off-by: jolheiser <john.olheiser@gmail.com>
main
jolheiser 2022-01-05 23:23:19 -06:00
parent 59c69250d9
commit 43ccae6916
Signed by: jolheiser
GPG Key ID: B853ADA5DA7BBF7A
15 changed files with 376 additions and 13 deletions

View File

@ -19,6 +19,19 @@ type Application struct {
Date string `db:"date"`
}
func (a *Application) Status() string {
switch {
case !a.Accepted.Valid:
return "Unanswered"
case a.Accepted.Bool:
return "Accepted"
case !a.Accepted.Bool:
return "Denied"
default:
return "Unknown"
}
}
func (a *Application) String() string {
return a.Username
}
@ -31,12 +44,11 @@ func (d *Database) ApplicationByID(id int64) (*Application, error) {
return &app, d.db.Get(&app, applicationByIDSQL, id)
}
//go:embed queries/application_by_player_username.sql
var applicationByPlayerUsernameSQL string
//go:embed queries/applications_by_player_username.sql
var applicationsByPlayerUsernameSQL string
func (d *Database) ApplicationByPlayerUsername(username string) (*Application, error) {
var app Application
return &app, d.db.Get(&app, applicationByPlayerUsernameSQL, strings.ToLower(username))
func (d *Database) ApplicationsByPlayerUsername(username string) (apps []*Application, err error) {
return apps, d.db.Select(&apps, applicationsByPlayerUsernameSQL, strings.ToLower(username))
}
//go:embed queries/applications_by_username.sql
@ -46,10 +58,17 @@ func (d *Database) ApplicationsByUsername(username string) (apps []*Application,
return apps, d.db.Select(&apps, applicationsByUsernameSQL, strings.ToLower(username))
}
//go:embed queries/applications_by_username_count.sql
var applicationsByUsernameCountSQL string
func (d *Database) ApplicationsByUsernameCount(username string) (count int64, err error) {
return count, d.db.Get(&count, applicationsByUsernameCountSQL, strings.ToLower(username))
}
//go:embed queries/application_update_accepted.sql
var applicationUpdateAcceptedSQL string
func (d *Database) ApplicationUpdateAccepted(accepted *bool) (*Application, error) {
var app Application
return &app, d.db.Get(&app, applicationUpdateAcceptedSQL, accepted)
func (d *Database) ApplicationUpdateAccepted(accepted *bool, appID int64) error {
_, err := d.db.Exec(applicationUpdateAcceptedSQL, accepted, appID)
return err
}

View File

@ -36,6 +36,13 @@ func (d *Database) PlayersByUsernameApplicationNotNull(username string) (pl []*P
return pl, d.db.Get(&pl, playersByUsernameApplicationNotNullSQL, strings.ToLower(username))
}
//go:embed queries/players_by_username_application_notnull_count.sql
var playersByUsernameApplicationNotNullCountSQL string
func (d *Database) PlayersByUsernameApplicationNotNullCount(username string) (count int64, err error) {
return count, d.db.Get(&count, playersByUsernameApplicationNotNullCountSQL, strings.ToLower(username))
}
//go:embed queries/players_by_discord_isnull.sql
var playersByDiscordIsNullSQL string

View File

@ -1,3 +0,0 @@
SELECT *
FROM minecraft_manager_application
WHERE id = (SELECT application_id FROM minecraft_manager_player WHERE LOWER(username) = ?);

View File

@ -0,0 +1,3 @@
SELECT *
FROM minecraft_manager_application
WHERE id IN (SELECT application_id FROM minecraft_manager_player WHERE LOWER(username) LIKE ?);

View File

@ -1,3 +1,3 @@
SELECT *
FROM minecraft_manager_application
WHERE LOWER(username) LIKE ?;
WHERE LOWER(username) LIKE ? LIMIT 10;

View File

@ -0,0 +1,3 @@
SELECT COUNT(*)
FROM minecraft_manager_application
WHERE LOWER(username) LIKE ?;

View File

@ -1,3 +1,3 @@
SELECT *
FROM minecraft_manager_player
WHERE username LIKE ?;
WHERE username LIKE ? LIMIT 10;

View File

@ -0,0 +1,4 @@
SELECT COUNT(*)
FROM minecraft_manager_player
WHERE username LIKE ?
AND application_id IS NOT NULL;

117
discord/action.go 100644
View File

@ -0,0 +1,117 @@
package discord
import (
"database/sql"
"errors"
"github.com/Karitham/corde"
)
func (d Discord) accept(w corde.ResponseWriter, i *corde.Interaction) {
id := i.Data.Options.Int64("app_id")
app, err := d.store.ApplicationByID(id)
if err != nil {
w.Respond(corde.NewResp().Contentf("No application #%d was found.", id).Ephemeral().B())
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())
return
}
players, err := d.store.PlayersByUsername(app.Username)
if err != nil || len(players) == 0 {
if errors.Is(err, sql.ErrNoRows) {
return
}
w.Respond(corde.NewResp().Contentf("Could not link player to application", id).Ephemeral().B())
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())
}
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())
return
}
w.Respond(corde.NewResp().Contentf("Application #%d was successfully accepted.", id).B())
}
}
func (d Discord) deny(w corde.ResponseWriter, i *corde.Interaction) {
id := i.Data.Options.Int64("app_id")
app, err := d.store.ApplicationByID(id)
if err != nil {
w.Respond(corde.NewResp().Contentf("No application #%d was found.", id).Ephemeral().B())
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())
return
}
players, err := d.store.PlayersByUsername(app.Username)
if err != nil || len(players) == 0 {
if errors.Is(err, sql.ErrNoRows) {
return
}
w.Respond(corde.NewResp().Contentf("Could not link player to application", id).Ephemeral().B())
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())
}
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())
return
}
w.Respond(corde.NewResp().Contentf("Application #%d was successfully denied.", id).B())
}
}
func (d Discord) clear(w corde.ResponseWriter, i *corde.Interaction) {
id := i.Data.Options.Int64("app_id")
app, err := d.store.ApplicationByID(id)
if err != nil {
w.Respond(corde.NewResp().Contentf("No application #%d was found.", id).Ephemeral().B())
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())
return
}
players, err := d.store.PlayersByUsername(app.Username)
if err != nil || len(players) == 0 {
if errors.Is(err, sql.ErrNoRows) {
return
}
w.Respond(corde.NewResp().Contentf("Could not link player to application", id).Ephemeral().B())
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("Application #%d was successfully cleared.", id).B())
}
}

95
discord/info.go 100644
View File

@ -0,0 +1,95 @@
package discord
import (
"fmt"
"strings"
"git.jojodev.com/minecraft/mcm-discord/database"
"github.com/Karitham/corde"
)
func appResponse(app *database.Application) *corde.InteractionRespData {
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("Age", fmt.Sprint(app.Age)).
Field("Type of Player", app.PlayerType).
Field("Ever been Banned", fmt.Sprint(app.EverBanned))
if app.EverBanned && app.EverBannedExplanation != "" {
embed.Field("Reason for being banned", app.EverBannedExplanation)
}
if app.Reference != "" {
embed.Field("Reference", app.Reference)
}
embed.Field("Read the Rules", app.ReadRules).
Field("Status", app.Status())
return corde.NewResp().Embeds(embed.B()).B()
}
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())
return
}
var app *database.Application
var err error
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())
return
}
} else {
apps, err := d.store.ApplicationsByUsername(username)
if err != nil {
w.Respond(corde.NewResp().Content("No applications matched.").Ephemeral().B())
return
}
if len(apps) == 0 {
apps, err = d.store.ApplicationsByPlayerUsername(username)
if err != nil {
w.Respond(corde.NewResp().Content("No applications matched.").Ephemeral().B())
return
}
if len(apps) == 1 {
app = apps[0]
}
} else if len(apps) == 1 {
app = apps[0]
}
}
w.Respond(appResponse(app))
}
func (d Discord) search(w corde.ResponseWriter, i *corde.Interaction) {
username := i.Data.Options.String("username")
apps, err := d.store.ApplicationsByUsername(username)
if err != nil {
w.Respond(corde.NewResp().Content("No applications matched.").Ephemeral().B())
return
}
count, err := d.store.ApplicationsByUsernameCount(username)
if err != nil {
w.Respond(corde.NewResp().Content("No applications matched.").Ephemeral().B())
return
}
var app *database.Application
if count > 0 {
if count == 1 {
app = apps[0]
} else {
}
}
w.Respond(appResponse(app))
}

52
discord/mux.go 100644
View File

@ -0,0 +1,52 @@
package discord
import (
"git.jojodev.com/minecraft/mcm-discord/database"
"git.jojodev.com/minecraft/mcm-discord/socket"
"github.com/Karitham/corde"
)
type Storer interface {
ApplicationByID(int64) (*database.Application, error)
ApplicationsByPlayerUsername(string) ([]*database.Application, error)
ApplicationsByUsername(string) ([]*database.Application, error)
ApplicationsByUsernameCount(string) (int64, error)
ApplicationUpdateAccepted(*bool, int64) error
PlayersByUsername(string) ([]*database.Player, error)
PlayersByUsernameApplicationNotNull(string) ([]*database.Player, error)
PlayersByUsernameApplicationNotNullCount(string) (int64, error)
PlayersByDiscordIsNull() ([]*database.Player, error)
PlayerUpdateApplication(int64, int64) error
PlayerUpdateDiscordID(string, int64) error
}
type Discord struct {
store Storer
sock *socket.Socket
Mux *corde.Mux
}
func New(store Storer, sock *socket.Socket, publicKey, appID, botToken string) *Discord {
m := corde.NewMux(publicKey, corde.SnowflakeFromString(appID), botToken)
d := &Discord{
store: store,
sock: sock,
Mux: m,
}
m.Route("app", func(m *corde.Mux) {
// Info
m.Command("search", d.search)
m.Command("info", d.info)
// Action
m.Command("accept", d.accept)
m.Command("deny", d.deny)
m.Command("clear", d.clear)
})
// Sync
m.Command("sync", nil)
return d
}

1
discord/sync.go 100644
View File

@ -0,0 +1 @@
package discord

6
go.mod
View File

@ -6,3 +6,9 @@ require (
github.com/go-sql-driver/mysql v1.6.0
github.com/jmoiron/sqlx v1.3.4
)
require (
github.com/Karitham/corde v0.5.0 // indirect
github.com/akrennmair/go-radix v1.0.1-0.20211215212324-49d05194b0a3 // indirect
github.com/rs/zerolog v1.26.1 // indirect
)

36
go.sum
View File

@ -1,9 +1,45 @@
github.com/Karitham/corde v0.5.0 h1:Y/H0uwRqTWlGfVt76Bto1BB338DZwZkwzhuqbvE8Vec=
github.com/Karitham/corde v0.5.0/go.mod h1:1HP9kpDAN1293JjCv+IrE9xKI0seOm5ZORWm9Z0A4k0=
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/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=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/jmoiron/sqlx v1.3.4 h1:wv+0IJZfL5z0uZoUjlpKgHkgaFSYD+r9CfrXjEXsO7w=
github.com/jmoiron/sqlx v1.3.4/go.mod h1:2BljVx/86SuTyjE+aPYlHCTNvZrnJXghYGpNiXLBMCQ=
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/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=
github.com/rs/zerolog v1.26.1/go.mod h1:/wSSJWX7lVrsOwlbyTRSOJvqRlc+WjWlfes+CiJ+tmc=
github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20211215165025-cf75a172585e/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
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=

23
socket/socket.go 100644
View File

@ -0,0 +1,23 @@
package socket
import (
"fmt"
"net"
"strings"
)
type Socket struct {
Port int
}
func (s *Socket) Command(args ...string) error {
conn, err := net.Dial("tcp", fmt.Sprintf("127.0.0.1:%d", s.Port))
if err != nil {
return err
}
if _, err := conn.Write([]byte(strings.Join(args, " "))); err != nil {
return err
}
return conn.Close()
}