From 5fc52405c9c6297446959e9f5b3d176d0f7f347b Mon Sep 17 00:00:00 2001 From: Your Name Date: Sat, 25 May 2024 08:15:18 +0000 Subject: [PATCH] fix current-status --- routes/list/endpoints/current_status/route.go | 22 ++++++-- routes/list/endpoints/search_list/route.go | 54 ++++++++----------- .../list/endpoints/search_list/sql/bots.tmpl | 13 +++-- .../endpoints/redeem_payment_offer/route.go | 25 +++++++++ types/user.go | 1 + 5 files changed, 75 insertions(+), 40 deletions(-) diff --git a/routes/list/endpoints/current_status/route.go b/routes/list/endpoints/current_status/route.go index 60df0020..4c060d4a 100644 --- a/routes/list/endpoints/current_status/route.go +++ b/routes/list/endpoints/current_status/route.go @@ -42,6 +42,18 @@ func Route(d uapi.RouteData, r *http.Request) uapi.HttpResponse { src = "instatus" } + // Check if response is on redis + cachedResp := state.Redis.Get(d.Context, "current_status:"+src) + + if cachedResp.Val() != "" { + return uapi.HttpResponse{ + Json: cachedResp.Val(), + Headers: map[string]string{ + "X-Cache": "HIT", + }, + } + } + switch src { case "instatus": res, err := http.Get(state.Config.Sites.Instatus + "/summary.json") @@ -106,10 +118,6 @@ func Route(d uapi.RouteData, r *http.Request) uapi.HttpResponse { if err != nil { return uapi.DefaultResponse(http.StatusInternalServerError) } - - // Get type of monitor key - //monitorType := listStatus["monitors"].([]interface{}) - //fmt.Println(monitorType) default: return uapi.HttpResponse{ Status: http.StatusBadRequest, @@ -119,7 +127,13 @@ func Route(d uapi.RouteData, r *http.Request) uapi.HttpResponse { } } + // Cache response + state.Redis.Set(d.Context, "current_status:"+src, listStatus, 3*time.Minute) + return uapi.HttpResponse{ Json: listStatus, + Headers: map[string]string{ + "X-Cache": "MISS", + }, } } diff --git a/routes/list/endpoints/search_list/route.go b/routes/list/endpoints/search_list/route.go index 4044f88e..cad673ac 100644 --- a/routes/list/endpoints/search_list/route.go +++ b/routes/list/endpoints/search_list/route.go @@ -6,8 +6,9 @@ import ( "strings" "text/template" - "popplio/assetmanager" "popplio/db" + botAssets "popplio/routes/bots/assets" + serverAssets "popplio/routes/servers/assets" "popplio/state" "popplio/types" @@ -143,7 +144,7 @@ func Route(d uapi.RouteData, r *http.Request) uapi.HttpResponse { } if payload.Query != "" { - args = append(args, "%"+strings.ToLower(payload.Query)+"%", strings.ToLower(payload.Query)) // 8-9 + args = append(args, strings.ToLower(payload.Query), "%"+strings.ToLower(payload.Query)+"%") // 8-9 } state.Logger.Debug("SQL result", zap.String("sql", sqlString.String()), zap.String("targetType", "bot")) @@ -157,37 +158,31 @@ func Route(d uapi.RouteData, r *http.Request) uapi.HttpResponse { if err != nil { state.Logger.Error("Failed to query", zap.Error(err), zap.String("targetType", "bot")) - return uapi.DefaultResponse(http.StatusInternalServerError) + return uapi.HttpResponse{ + Status: http.StatusInternalServerError, + Json: types.ApiError{Message: "Error querying: " + err.Error()}, + } } bots, err := pgx.CollectRows(rows, pgx.RowToStructByName[types.IndexBot]) if err != nil { - state.Logger.Error("Failed to collect rows", zap.Error(err), zap.String("sql", sqlString.String())) - return uapi.DefaultResponse(http.StatusInternalServerError) + state.Logger.Error("Failed to collect rows [bots]", zap.Error(err), zap.String("sql", sqlString.String())) + return uapi.HttpResponse{ + Status: http.StatusInternalServerError, + Json: types.ApiError{Message: "Error collecting rows: " + err.Error()}, + } } for i := range bots { - botUser, err := dovewing.GetUser(d.Context, bots[i].BotID, state.DovewingPlatformDiscord) - - if err != nil { - state.Logger.Error("Failed to get user", zap.Error(err), zap.String("botID", bots[i].BotID)) - return uapi.DefaultResponse(http.StatusInternalServerError) - } - - bots[i].User = botUser - - var code string - - err = state.Pool.QueryRow(d.Context, "SELECT code FROM vanity WHERE itag = $1", bots[i].VanityRef).Scan(&code) + err := botAssets.ResolveIndexBot(d.Context, &bots[i]) if err != nil { - state.Logger.Error("Failed to get vanity code", zap.Error(err), zap.String("botID", bots[i].BotID)) - return uapi.DefaultResponse(http.StatusInternalServerError) + return uapi.HttpResponse{ + Status: http.StatusInternalServerError, + Json: types.ApiError{Message: "Error resolving bot: " + err.Error()}, + } } - - bots[i].Vanity = code - bots[i].Banner = assetmanager.BannerInfo(assetmanager.AssetTargetTypeBots, bots[i].BotID) } sr.Bots = bots @@ -241,18 +236,15 @@ func Route(d uapi.RouteData, r *http.Request) uapi.HttpResponse { } for i := range servers { - var code string - - err = state.Pool.QueryRow(d.Context, "SELECT code FROM vanity WHERE itag = $1", servers[i].VanityRef).Scan(&code) + err := serverAssets.ResolveIndexServer(d.Context, &servers[i]) if err != nil { - state.Logger.Error("Failed to get vanity code", zap.Error(err), zap.String("serverID", servers[i].ServerID)) - return uapi.DefaultResponse(http.StatusInternalServerError) + state.Logger.Error("Failed to resolve server", zap.Error(err), zap.String("serverId", servers[i].ServerID)) + return uapi.HttpResponse{ + Status: http.StatusInternalServerError, + Json: types.ApiError{Message: "Error resolving server: " + err.Error()}, + } } - - servers[i].Vanity = code - servers[i].Avatar = assetmanager.AvatarInfo(assetmanager.AssetTargetTypeServers, servers[i].ServerID) - servers[i].Banner = assetmanager.BannerInfo(assetmanager.AssetTargetTypeServers, servers[i].ServerID) } sr.Servers = servers diff --git a/routes/list/endpoints/search_list/sql/bots.tmpl b/routes/list/endpoints/search_list/sql/bots.tmpl index cd40ac9f..1ca4faaf 100644 --- a/routes/list/endpoints/search_list/sql/bots.tmpl +++ b/routes/list/endpoints/search_list/sql/bots.tmpl @@ -1,6 +1,8 @@ -SELECT DISTINCT {{.Cols}} FROM bots +SELECT + {{.Cols}} +FROM bots {{if .Query}} - {{range $table := .PlatformTables }} + {{range $table := .PlatformTables}} INNER JOIN {{$table}} {{$table}}_users ON bots.bot_id = {{$table}}_users.id {{end}} {{end}} @@ -23,10 +25,11 @@ AND (cardinality($7::text[]) = 0 OR tags {{.TagMode}} $7) -- Where TagMode is on {{if .Query}} AND ( - {{range $table := .PlatformTables }} - {{$table}}_users.username ILIKE $8 OR + short @@ $8 OR bot_id = $8 OR client_id = $8 + {{range $index, $table := .PlatformTables}} + OR {{$table}}_users.username @@ $8 OR {{$table}}_users.username ILIKE $9 {{end}} - short @@ $9 OR bot_id = $9 OR client_id = $9) +) {{end}} ORDER BY votes DESC, type DESC LIMIT 12 diff --git a/routes/payments/endpoints/redeem_payment_offer/route.go b/routes/payments/endpoints/redeem_payment_offer/route.go index e5968417..2b9344d8 100644 --- a/routes/payments/endpoints/redeem_payment_offer/route.go +++ b/routes/payments/endpoints/redeem_payment_offer/route.go @@ -130,6 +130,31 @@ func Route(d uapi.RouteData, r *http.Request) uapi.HttpResponse { } } + var lastRedeemedBoosterOffer *time.Time + err = state.Pool.QueryRow(d.Context, "SELECT last_booster_claim FROM users WHERE user_id = $1", d.Auth.ID).Scan(&lastRedeemedBoosterOffer) + + if err != nil { + state.Logger.Error("Error while checking last booster claim", zap.Error(err), zap.String("userID", d.Auth.ID)) + return uapi.HttpResponse{ + Status: http.StatusBadRequest, + Json: types.ApiError{ + Message: "Error: " + err.Error(), + }, + } + } + + // Check the last time the user redeemed a booster offer + if lastRedeemedBoosterOffer != nil { + if time.Since(*lastRedeemedBoosterOffer) < 30*24*time.Hour { + return uapi.HttpResponse{ + Status: http.StatusBadRequest, + Json: types.ApiError{ + Message: "You can only redeem a booster offer once every 30 days", + }, + } + } + } + err = assets.GivePerks(d.Context, payload) if err != nil { diff --git a/types/user.go b/types/user.go index fd201939..af48b714 100644 --- a/types/user.go +++ b/types/user.go @@ -33,6 +33,7 @@ type User struct { UserPacks []BotPack `db:"-" json:"user_packs" description:"The list of packs the user has" ci:"internal"` // Must be handled internally CreatedAt time.Time `db:"created_at" json:"created_at" description:"The time the user was created"` UpdatedAt time.Time `db:"updated_at" json:"updated_at" description:"The time the user was last updated"` + LastBoosterClaim *time.Time `db:"last_booster_claim" json:"last_booster_claim" description:"The last time the user claimed a booster reward"` } type UserPerm struct {