From 65d761e25fb3faf26e40ed2f3310619855dbb0e3 Mon Sep 17 00:00:00 2001 From: = <=> Date: Wed, 12 Jun 2024 18:42:51 +0100 Subject: [PATCH 1/6] Add discordgo dependency --- go.mod | 2 ++ go.sum | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/go.mod b/go.mod index a6a5dd9..6539e0f 100644 --- a/go.mod +++ b/go.mod @@ -28,10 +28,12 @@ require ( require ( cloud.google.com/go v0.38.0 // indirect + github.com/bwmarrin/discordgo v0.28.1 // indirect github.com/gogs/chardet v0.0.0-20150115103509-2404f7772561 // indirect github.com/golang/protobuf v1.5.0 // indirect github.com/googleapis/gax-go/v2 v2.0.5 // indirect github.com/gorilla/schema v1.2.0 // indirect + github.com/gorilla/websocket v1.4.2 // indirect github.com/hashicorp/golang-lru v0.5.1 // indirect github.com/jaytaylor/html2text v0.0.0-20180606194806-57d518f124b0 // indirect github.com/kr/text v0.1.0 // indirect diff --git a/go.sum b/go.sum index 2e98b1a..9d2c5c8 100644 --- a/go.sum +++ b/go.sum @@ -7,6 +7,8 @@ github.com/VividCortex/ewma v1.1.1 h1:MnEK4VOv6n0RSY4vtRe3h11qjxL3+t0B8yOL8iMXdc github.com/VividCortex/ewma v1.1.1/go.mod h1:2Tkkvm3sRDVXaiyucHiACn4cqf7DpdyLvmxzcbUokwA= github.com/aymerick/raymond v2.0.2+incompatible h1:VEp3GpgdAnv9B2GFyTvqgcKvY+mfKMjPOA3SbKLtnU0= github.com/aymerick/raymond v2.0.2+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g= +github.com/bwmarrin/discordgo v0.28.1 h1:gXsuo2GBO7NbR6uqmrrBDplPUx2T3nzu775q/Rd1aG4= +github.com/bwmarrin/discordgo v0.28.1/go.mod h1:NJZpH+1AfhIcyQsPeuBKsUtYrRnjkyu0kIVMCHkZtRY= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cheggaaa/pb/v3 v3.0.8 h1:bC8oemdChbke2FHIIGy9mn4DPJ2caZYQnfbRqwmdCoA= github.com/cheggaaa/pb/v3 v3.0.8/go.mod h1:UICbiLec/XO6Hw6k+BHEtHeQFzzBH4i2/qk/ow1EJTA= @@ -59,6 +61,8 @@ github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB7 github.com/gorilla/schema v1.1.0/go.mod h1:kgLaKoK1FELgZqMAVxx/5cbj0kT+57qxUrAlIO2eleU= github.com/gorilla/schema v1.2.0 h1:YufUaxZYCKGFuAq3c96BOhjgd5nmXiOY9NGzF247Tsc= github.com/gorilla/schema v1.2.0/go.mod h1:kgLaKoK1FELgZqMAVxx/5cbj0kT+57qxUrAlIO2eleU= +github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= +github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= @@ -119,6 +123,7 @@ github.com/zond/replace v0.0.0-20180415193355-5a1dc330b27e/go.mod h1:J7mWP0y029F go.opencensus.io v0.21.0 h1:mU6zScU4U1YAFPHEHYk+3JC4SY7JxgkqS10ZOSyksNg= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.1.0 h1:MDRAIl0xIo9Io2xV565hzXHw3zVseKrJKodhohM5CjU= golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= From 1764495c81580066120cea225f6e84353a834df4 Mon Sep 17 00:00:00 2001 From: = <=> Date: Wed, 12 Jun 2024 20:06:28 +0100 Subject: [PATCH 2/6] Add DiscordBotToken to datastore --- auth/auth.go | 41 +++++++++++++++++++++++++++++++++++++++++ game/handler.go | 6 ++++++ 2 files changed, 47 insertions(+) diff --git a/auth/auth.go b/auth/auth.go index eb067f9..5b69a06 100644 --- a/auth/auth.go +++ b/auth/auth.go @@ -59,6 +59,7 @@ const ( redirectURLKind = "RedirectURL" superusersKind = "Superusers" discordBotCredentialsKind = "DiscordBotCredentials" + discordBotTokenKind = "DiscordBotTokenKind" prodKey = "prod" ) @@ -75,6 +76,8 @@ var ( prodSuperusersLock = sync.RWMutex{} prodDiscordBotCredentials *DiscordBotCredentials prodDiscordBotCredentialsLock = sync.RWMutex{} + prodDiscordBotToken *DiscordBotToken + prodDiscordBotTokenLock = sync.RWMutex{} router *mux.Router RedirectURLResource *Resource @@ -85,6 +88,10 @@ type DiscordBotCredentials struct { Password string } +type DiscordBotToken struct { + Token string +} + func getDiscordBotCredentialsKey(ctx context.Context) *datastore.Key { return datastore.NewKey(ctx, discordBotCredentialsKind, prodKey, 0, nil) } @@ -119,6 +126,40 @@ func getDiscordBotCredentials(ctx context.Context) (*DiscordBotCredentials, erro return prodDiscordBotCredentials, nil } +func getDiscordBotTokenKey(ctx context.Context) *datastore.Key { + return datastore.NewKey(ctx, discordBotTokenKind, prodKey, 0, nil) +} + +func SetDiscordBotToken(ctx context.Context, discordBotToken *DiscordBotToken) error { + return datastore.RunInTransaction(ctx, func(ctx context.Context) error { + currentDiscordBotToken := &DiscordBotToken{} + if err := datastore.Get(ctx, getDiscordBotTokenKey(ctx), currentDiscordBotToken); err == nil { + return HTTPErr{"DiscordBotToken already configured", http.StatusBadRequest} + } + if _, err := datastore.Put(ctx, getDiscordBotTokenKey(ctx), discordBotToken); err != nil { + return err + } + return nil + }, &datastore.TransactionOptions{XG: false}) +} + +func GetDiscordBotToken(ctx context.Context) (*DiscordBotToken, error) { + prodDiscordBotTokenLock.RLock() + if prodDiscordBotToken != nil { + defer prodDiscordBotTokenLock.RUnlock() + return prodDiscordBotToken, nil + } + prodDiscordBotTokenLock.RUnlock() + prodDiscordBotTokenLock.Lock() + defer prodDiscordBotTokenLock.Unlock() + foundDiscordBotToken := &DiscordBotToken{} + if err := datastore.Get(ctx, getDiscordBotTokenKey(ctx), foundDiscordBotToken); err != nil { + return nil, err + } + prodDiscordBotToken = foundDiscordBotToken + return prodDiscordBotToken, nil +} + func init() { RedirectURLResource = &Resource{ Delete: deleteRedirectURL, diff --git a/game/handler.go b/game/handler.go index 6e60618..329e9a6 100644 --- a/game/handler.go +++ b/game/handler.go @@ -660,6 +660,7 @@ type configuration struct { SendGrid *auth.SendGrid Superusers *auth.Superusers DiscordBotCredentials *auth.DiscordBotCredentials + DiscordBotToken *auth.DiscordBotToken } func handleConfigure(w ResponseWriter, r Request) error { @@ -694,6 +695,11 @@ func handleConfigure(w ResponseWriter, r Request) error { return err } } + if conf.DiscordBotToken != nil { + if err := auth.SetDiscordBotToken(ctx, conf.DiscordBotToken); err != nil { + return err + } + } return nil } From f889f34bb537623a5ac7fd3ba7d90f7c9719dd5b Mon Sep 17 00:00:00 2001 From: = <=> Date: Thu, 13 Jun 2024 17:44:29 +0100 Subject: [PATCH 3/6] wip --- game/game.go | 17 +++++++++++++++++ game/member.go | 10 ++++++++++ go.mod | 2 ++ go.sum | 5 +++++ 4 files changed, 34 insertions(+) diff --git a/game/game.go b/game/game.go index 34b2eb4..650aa1b 100644 --- a/game/game.go +++ b/game/game.go @@ -13,6 +13,7 @@ import ( "strings" "time" + "github.com/bwmarrin/discordgo" "github.com/davecgh/go-spew/spew" "github.com/zond/diplicity/auth" "github.com/zond/godip" @@ -1142,6 +1143,22 @@ func asyncStartGame(ctx context.Context, gameID *datastore.Key, host string) err } g.ID = gameID + gameStartedWebhook := g.DiscordWebhooks.GameStarted + // Invoke webhook using discordgo + if gameStartedWebhook.Id != "" && gameStartedWebhook.Token != "" { + discordSession, err := discordgo.New("Bot " + host) + if err != nil { + log.Errorf(ctx, "discordgo.New(...): %v", err) + return err + } + if err := discordSession.WebhookExecute(gameStartedWebhook.Id, gameStartedWebhook.Token, false, &discordgo.WebhookParams{ + Content: fmt.Sprintf("Game %v has started!", g.Desc), + }); err != nil { + log.Errorf(ctx, "discordSession.WebhookExecute(...): %v", err) + return err + } + } + variant := variants.Variants[g.Variant] if len(g.Members) != len(variant.Nations) { log.Warningf(ctx, "Variant %v has %v nations, game %v has %v nations, someone must have dropped out before we got here?", g.Variant, len(variant.Nations), g.ID, len(g.Members)) diff --git a/game/member.go b/game/member.go index 6c6bbd9..222be1f 100644 --- a/game/member.go +++ b/game/member.go @@ -14,6 +14,7 @@ import ( "golang.org/x/net/context" "google.golang.org/appengine/v2" "google.golang.org/appengine/v2/datastore" + "google.golang.org/appengine/v2/log" . "github.com/zond/goaeoas" ) @@ -452,16 +453,22 @@ func createMember(w ResponseWriter, r Request) (*Member, error) { if !ok { return nil, HTTPErr{"unauthenticated", http.StatusUnauthorized} } + log.Infof(ctx, "user %s", user.Id) + log.Infof(ctx, "r %s", r.Req().Body) + log.Infof(ctx, "r %s", r.Vars()) gameID, err := datastore.DecodeKey(r.Vars()["game_id"]) if err != nil { return nil, err } + log.Infof(ctx, "game %s", gameID) game := &Game{} if err := datastore.Get(ctx, gameID, game); err != nil { return nil, err } + log.Infof(ctx, "game %s", game) + filterList := Games{*game} if _, err := filterList.RemoveBanned(ctx, user.Id, true); err != nil { return nil, err @@ -482,10 +489,13 @@ func createMember(w ResponseWriter, r Request) (*Member, error) { return nil, HTTPErr{"filtered from this game", http.StatusPreconditionFailed} } + log.Infof(ctx, "Copying member") + log.Infof(ctx, "r %s", r.Req().Body) member := &Member{} if err := Copy(member, r, "POST"); err != nil { return nil, err } + log.Infof(ctx, "member %s", member) _, member, err = createMemberHelper(ctx, r, gameID, user, member) if err != nil { diff --git a/go.mod b/go.mod index a6a5dd9..6539e0f 100644 --- a/go.mod +++ b/go.mod @@ -28,10 +28,12 @@ require ( require ( cloud.google.com/go v0.38.0 // indirect + github.com/bwmarrin/discordgo v0.28.1 // indirect github.com/gogs/chardet v0.0.0-20150115103509-2404f7772561 // indirect github.com/golang/protobuf v1.5.0 // indirect github.com/googleapis/gax-go/v2 v2.0.5 // indirect github.com/gorilla/schema v1.2.0 // indirect + github.com/gorilla/websocket v1.4.2 // indirect github.com/hashicorp/golang-lru v0.5.1 // indirect github.com/jaytaylor/html2text v0.0.0-20180606194806-57d518f124b0 // indirect github.com/kr/text v0.1.0 // indirect diff --git a/go.sum b/go.sum index 2e98b1a..9d2c5c8 100644 --- a/go.sum +++ b/go.sum @@ -7,6 +7,8 @@ github.com/VividCortex/ewma v1.1.1 h1:MnEK4VOv6n0RSY4vtRe3h11qjxL3+t0B8yOL8iMXdc github.com/VividCortex/ewma v1.1.1/go.mod h1:2Tkkvm3sRDVXaiyucHiACn4cqf7DpdyLvmxzcbUokwA= github.com/aymerick/raymond v2.0.2+incompatible h1:VEp3GpgdAnv9B2GFyTvqgcKvY+mfKMjPOA3SbKLtnU0= github.com/aymerick/raymond v2.0.2+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g= +github.com/bwmarrin/discordgo v0.28.1 h1:gXsuo2GBO7NbR6uqmrrBDplPUx2T3nzu775q/Rd1aG4= +github.com/bwmarrin/discordgo v0.28.1/go.mod h1:NJZpH+1AfhIcyQsPeuBKsUtYrRnjkyu0kIVMCHkZtRY= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cheggaaa/pb/v3 v3.0.8 h1:bC8oemdChbke2FHIIGy9mn4DPJ2caZYQnfbRqwmdCoA= github.com/cheggaaa/pb/v3 v3.0.8/go.mod h1:UICbiLec/XO6Hw6k+BHEtHeQFzzBH4i2/qk/ow1EJTA= @@ -59,6 +61,8 @@ github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB7 github.com/gorilla/schema v1.1.0/go.mod h1:kgLaKoK1FELgZqMAVxx/5cbj0kT+57qxUrAlIO2eleU= github.com/gorilla/schema v1.2.0 h1:YufUaxZYCKGFuAq3c96BOhjgd5nmXiOY9NGzF247Tsc= github.com/gorilla/schema v1.2.0/go.mod h1:kgLaKoK1FELgZqMAVxx/5cbj0kT+57qxUrAlIO2eleU= +github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= +github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= @@ -119,6 +123,7 @@ github.com/zond/replace v0.0.0-20180415193355-5a1dc330b27e/go.mod h1:J7mWP0y029F go.opencensus.io v0.21.0 h1:mU6zScU4U1YAFPHEHYk+3JC4SY7JxgkqS10ZOSyksNg= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.1.0 h1:MDRAIl0xIo9Io2xV565hzXHw3zVseKrJKodhohM5CjU= golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= From 34da47781fc2de4db06a8f7f004ee2919f017f0d Mon Sep 17 00:00:00 2001 From: = <=> Date: Fri, 14 Jun 2024 11:50:04 +0100 Subject: [PATCH 4/6] Invoke webhooks on game start and phase start --- game/game.go | 31 ++++++++++++++++++------------- game/phase.go | 28 ++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 13 deletions(-) diff --git a/game/game.go b/game/game.go index 650aa1b..0b9486b 100644 --- a/game/game.go +++ b/game/game.go @@ -1143,19 +1143,24 @@ func asyncStartGame(ctx context.Context, gameID *datastore.Key, host string) err } g.ID = gameID - gameStartedWebhook := g.DiscordWebhooks.GameStarted - // Invoke webhook using discordgo - if gameStartedWebhook.Id != "" && gameStartedWebhook.Token != "" { - discordSession, err := discordgo.New("Bot " + host) - if err != nil { - log.Errorf(ctx, "discordgo.New(...): %v", err) - return err - } - if err := discordSession.WebhookExecute(gameStartedWebhook.Id, gameStartedWebhook.Token, false, &discordgo.WebhookParams{ - Content: fmt.Sprintf("Game %v has started!", g.Desc), - }); err != nil { - log.Errorf(ctx, "discordSession.WebhookExecute(...): %v", err) - return err + discordBotToken, err := auth.GetDiscordBotToken(ctx) + if err != nil { + log.Warningf(ctx, "auth.GetDiscordBotToken(...): %v", err) + } else { + gameStartedWebhook := g.DiscordWebhooks.GameStarted + // Invoke webhook using discordgo + if gameStartedWebhook.Id != "" && gameStartedWebhook.Token != "" { + discordSession, err := discordgo.New("Bot " + discordBotToken.Token) + if err != nil { + log.Errorf(ctx, "discordgo.New(...): %v", err) + return err + } + if _, err := discordSession.WebhookExecute(gameStartedWebhook.Id, gameStartedWebhook.Token, false, &discordgo.WebhookParams{ + Content: fmt.Sprintf("Game %v has started!", g.Desc), + }); err != nil { + log.Errorf(ctx, "discordSession.WebhookExecute(...): %v", err) + return err + } } } diff --git a/game/phase.go b/game/phase.go index d632ef8..7fd86a9 100644 --- a/game/phase.go +++ b/game/phase.go @@ -13,6 +13,7 @@ import ( "strings" "time" + "github.com/bwmarrin/discordgo" "github.com/dustin/go-humanize/english" "github.com/zond/diplicity/auth" "github.com/zond/godip" @@ -395,6 +396,33 @@ func sendPhaseNotificationsToFCM(ctx context.Context, host string, gameID *datas func sendPhaseNotificationsToUsers(ctx context.Context, host string, gameID *datastore.Key, phaseOrdinal int64, origUids []string) error { log.Infof(ctx, "sendPhaseNotificationsToUsers(..., %q, %v, %v, %+v)", host, gameID, phaseOrdinal, origUids) + g := &Game{} + if err := datastore.Get(ctx, gameID, g); err != nil { + log.Errorf(ctx, "datastore.Get(..., %v, %v): %v; hope datastore will get fixed", gameID, g, err) + return err + } + + discordBotToken, err := auth.GetDiscordBotToken(ctx) + if err != nil { + log.Warningf(ctx, "auth.GetDiscordBotToken(...): %v", err) + } else { + phaseStartedWebhook := g.DiscordWebhooks.PhaseStarted + // Invoke webhook using discordgo + if phaseStartedWebhook.Id != "" && phaseStartedWebhook.Token != "" { + discordSession, err := discordgo.New("Bot " + discordBotToken.Token) + if err != nil { + log.Errorf(ctx, "discordgo.New(...): %v", err) + return err + } + if _, err := discordSession.WebhookExecute(phaseStartedWebhook.Id, phaseStartedWebhook.Token, false, &discordgo.WebhookParams{ + Content: fmt.Sprintf("Phase %v has started!", phaseOrdinal), + }); err != nil { + log.Errorf(ctx, "discordSession.WebhookExecute(...): %v", err) + return err + } + } + } + if len(origUids) == 0 { log.Infof(ctx, "sendPhaseNotificationsToUsers(..., %q, %v, %v, %+v) *** NO UIDS ***", host, gameID, phaseOrdinal, origUids) return nil From 33a9c6449455c81d70022b148f8105d453cc6f12 Mon Sep 17 00:00:00 2001 From: = <=> Date: Fri, 14 Jun 2024 11:52:01 +0100 Subject: [PATCH 5/6] Remove logs --- game/member.go | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/game/member.go b/game/member.go index 222be1f..6c6bbd9 100644 --- a/game/member.go +++ b/game/member.go @@ -14,7 +14,6 @@ import ( "golang.org/x/net/context" "google.golang.org/appengine/v2" "google.golang.org/appengine/v2/datastore" - "google.golang.org/appengine/v2/log" . "github.com/zond/goaeoas" ) @@ -453,22 +452,16 @@ func createMember(w ResponseWriter, r Request) (*Member, error) { if !ok { return nil, HTTPErr{"unauthenticated", http.StatusUnauthorized} } - log.Infof(ctx, "user %s", user.Id) - log.Infof(ctx, "r %s", r.Req().Body) - log.Infof(ctx, "r %s", r.Vars()) gameID, err := datastore.DecodeKey(r.Vars()["game_id"]) if err != nil { return nil, err } - log.Infof(ctx, "game %s", gameID) game := &Game{} if err := datastore.Get(ctx, gameID, game); err != nil { return nil, err } - log.Infof(ctx, "game %s", game) - filterList := Games{*game} if _, err := filterList.RemoveBanned(ctx, user.Id, true); err != nil { return nil, err @@ -489,13 +482,10 @@ func createMember(w ResponseWriter, r Request) (*Member, error) { return nil, HTTPErr{"filtered from this game", http.StatusPreconditionFailed} } - log.Infof(ctx, "Copying member") - log.Infof(ctx, "r %s", r.Req().Body) member := &Member{} if err := Copy(member, r, "POST"); err != nil { return nil, err } - log.Infof(ctx, "member %s", member) _, member, err = createMemberHelper(ctx, r, gameID, user, member) if err != nil { From acffcef89bd5ccf29ae8c9ed2eba7a726cf7a053 Mon Sep 17 00:00:00 2001 From: = <=> Date: Mon, 17 Jun 2024 10:13:52 +0100 Subject: [PATCH 6/6] Refactor discord webook functionality --- game/discord.go | 35 +++++++++++++++++++++++++++++++++++ game/game.go | 46 ++++++++++++++++++++-------------------------- game/phase.go | 22 +++++----------------- 3 files changed, 60 insertions(+), 43 deletions(-) create mode 100644 game/discord.go diff --git a/game/discord.go b/game/discord.go new file mode 100644 index 0000000..8b1b2f9 --- /dev/null +++ b/game/discord.go @@ -0,0 +1,35 @@ +package game + +import ( + "context" + + "github.com/bwmarrin/discordgo" + "github.com/zond/diplicity/auth" + "google.golang.org/appengine/v2/log" +) + +type DiscordWebhook struct { + Id string + Token string +} + +type DiscordWebhooks struct { + GameStarted DiscordWebhook + PhaseStarted DiscordWebhook +} + +func CreateDiscordSession(ctx context.Context) (*discordgo.Session, error) { + log.Infof(ctx, "Creating Discord session") + discordBotToken, err := auth.GetDiscordBotToken(ctx) + if err != nil { + log.Warningf(ctx, "Error getting Discord bot token", err) + return nil, err + } else { + discordSession, err := discordgo.New("Bot " + discordBotToken.Token) + if err != nil { + log.Errorf(ctx, "Error creating Discord session", err) + return nil, err + } + return discordSession, nil + } +} diff --git a/game/game.go b/game/game.go index 0b9486b..7cb74bd 100644 --- a/game/game.go +++ b/game/game.go @@ -425,16 +425,6 @@ func (g Games) Item(r Request, user *auth.User, cursor *datastore.Cursor, limit return gamesItem } -type DiscordWebhook struct { - Id string - Token string -} - -type DiscordWebhooks struct { - GameStarted DiscordWebhook - PhaseStarted DiscordWebhook -} - type Game struct { ID *datastore.Key `datastore:"-"` @@ -499,6 +489,21 @@ func (g *Game) Load(props []datastore.Property) error { return err } +func (g *Game) invokeWebhook(session *discordgo.Session, webhook DiscordWebhook, content string) error { + _, err := session.WebhookExecute(webhook.Id, webhook.Token, false, &discordgo.WebhookParams{ + Content: content, + }) + return err +} + +func (g *Game) InvokePhaseStartedDiscordWebhook(session *discordgo.Session) error { + return g.invokeWebhook(session, g.DiscordWebhooks.PhaseStarted, "Phase has started!") +} + +func (g *Game) InvokeGameStartedDiscordWebhook(session *discordgo.Session) error { + return g.invokeWebhook(session, g.DiscordWebhooks.GameStarted, "Game has started!") +} + func (g *Game) canMergeInto(o *Game, avoid *auth.User) bool { if g.NoMerge || o.NoMerge { return false @@ -1143,24 +1148,13 @@ func asyncStartGame(ctx context.Context, gameID *datastore.Key, host string) err } g.ID = gameID - discordBotToken, err := auth.GetDiscordBotToken(ctx) + discordSession, err := CreateDiscordSession(ctx) if err != nil { - log.Warningf(ctx, "auth.GetDiscordBotToken(...): %v", err) + log.Warningf(ctx, "Error creating discord session", err) } else { - gameStartedWebhook := g.DiscordWebhooks.GameStarted - // Invoke webhook using discordgo - if gameStartedWebhook.Id != "" && gameStartedWebhook.Token != "" { - discordSession, err := discordgo.New("Bot " + discordBotToken.Token) - if err != nil { - log.Errorf(ctx, "discordgo.New(...): %v", err) - return err - } - if _, err := discordSession.WebhookExecute(gameStartedWebhook.Id, gameStartedWebhook.Token, false, &discordgo.WebhookParams{ - Content: fmt.Sprintf("Game %v has started!", g.Desc), - }); err != nil { - log.Errorf(ctx, "discordSession.WebhookExecute(...): %v", err) - return err - } + err = g.InvokeGameStartedDiscordWebhook(discordSession) + if err != nil { + log.Errorf(ctx, "Error invoking game started discord webhook", err) } } diff --git a/game/phase.go b/game/phase.go index 7fd86a9..877f61a 100644 --- a/game/phase.go +++ b/game/phase.go @@ -13,7 +13,6 @@ import ( "strings" "time" - "github.com/bwmarrin/discordgo" "github.com/dustin/go-humanize/english" "github.com/zond/diplicity/auth" "github.com/zond/godip" @@ -402,24 +401,13 @@ func sendPhaseNotificationsToUsers(ctx context.Context, host string, gameID *dat return err } - discordBotToken, err := auth.GetDiscordBotToken(ctx) + discordSession, err := CreateDiscordSession(ctx) if err != nil { - log.Warningf(ctx, "auth.GetDiscordBotToken(...): %v", err) + log.Warningf(ctx, "Error creating discord session", err) } else { - phaseStartedWebhook := g.DiscordWebhooks.PhaseStarted - // Invoke webhook using discordgo - if phaseStartedWebhook.Id != "" && phaseStartedWebhook.Token != "" { - discordSession, err := discordgo.New("Bot " + discordBotToken.Token) - if err != nil { - log.Errorf(ctx, "discordgo.New(...): %v", err) - return err - } - if _, err := discordSession.WebhookExecute(phaseStartedWebhook.Id, phaseStartedWebhook.Token, false, &discordgo.WebhookParams{ - Content: fmt.Sprintf("Phase %v has started!", phaseOrdinal), - }); err != nil { - log.Errorf(ctx, "discordSession.WebhookExecute(...): %v", err) - return err - } + err = g.InvokePhaseStartedDiscordWebhook(discordSession) + if err != nil { + log.Errorf(ctx, "Error invoking phase started discord webhook", err) } }