From 1dae4052321b73b935ba62fc04c0cb6d72259801 Mon Sep 17 00:00:00 2001 From: LittleSheep Date: Sun, 23 Feb 2025 12:02:55 +0800 Subject: [PATCH] :sparkles: Sticker pack ownership --- pkg/internal/database/migrator.go | 1 + pkg/internal/models/stickers.go | 5 ++ pkg/internal/server/api/index.go | 3 + pkg/internal/server/api/sticker_packs_api.go | 64 ++++++++++++++++++++ pkg/internal/server/api/stickers_api.go | 41 ++++--------- pkg/internal/services/stickers.go | 35 +++++++++++ 6 files changed, 120 insertions(+), 29 deletions(-) diff --git a/pkg/internal/database/migrator.go b/pkg/internal/database/migrator.go index 84b68ab..69181c3 100644 --- a/pkg/internal/database/migrator.go +++ b/pkg/internal/database/migrator.go @@ -12,6 +12,7 @@ var AutoMaintainRange = []any{ &models.AttachmentBoost{}, &models.StickerPack{}, &models.Sticker{}, + &models.StickerPackOwnership{}, } func RunMigration(source *gorm.DB) error { diff --git a/pkg/internal/models/stickers.go b/pkg/internal/models/stickers.go index 1dc5c57..cdf7606 100644 --- a/pkg/internal/models/stickers.go +++ b/pkg/internal/models/stickers.go @@ -25,3 +25,8 @@ type StickerPack struct { Stickers []Sticker `json:"stickers" gorm:"foreignKey:PackID;constraint:OnDelete:CASCADE"` AccountID uint `json:"account_id"` } + +type StickerPackOwnership struct { + PackID uint `json:"pack_id" gorm:"primaryKey"` + AccountID uint `json:"account_id" gorm:"primaryKey"` +} diff --git a/pkg/internal/server/api/index.go b/pkg/internal/server/api/index.go index 1e63709..8ec183f 100644 --- a/pkg/internal/server/api/index.go +++ b/pkg/internal/server/api/index.go @@ -62,10 +62,13 @@ func MapAPIs(app *fiber.App, baseURL string) { packs := stickers.Group("/packs").Name("Sticker Packs API") { packs.Get("/", listStickerPacks) + packs.Get("/own", listOwnedStickerPacks) packs.Get("/:packId", getStickerPack) packs.Post("/", sec.ValidatorMiddleware, createStickerPack) packs.Put("/:packId", sec.ValidatorMiddleware, updateStickerPack) packs.Delete("/:packId", sec.ValidatorMiddleware, deleteStickerPack) + packs.Post("/:packId/own", addStickerPack) + packs.Delete("/:packId/own", removeStickerPack) } } } diff --git a/pkg/internal/server/api/sticker_packs_api.go b/pkg/internal/server/api/sticker_packs_api.go index 323c243..0b821d3 100644 --- a/pkg/internal/server/api/sticker_packs_api.go +++ b/pkg/internal/server/api/sticker_packs_api.go @@ -9,6 +9,7 @@ import ( "git.solsynth.dev/hypernet/paperclip/pkg/internal/services" "git.solsynth.dev/hypernet/passport/pkg/authkit" "github.com/gofiber/fiber/v2" + "github.com/samber/lo" ) func listStickerPacks(c *fiber.Ctx) error { @@ -44,6 +45,29 @@ func listStickerPacks(c *fiber.Ctx) error { }) } +func listOwnedStickerPacks(c *fiber.Ctx) error { + if err := sec.EnsureAuthenticated(c); err != nil { + return err + } + user := c.Locals("nex_user").(*sec.UserInfo) + + var ownerships []models.StickerPackOwnership + if err := database.C.Where("account_id = ?", user.ID).Find(&ownerships).Error; err != nil { + return fiber.NewError(fiber.StatusInternalServerError, err.Error()) + } + + idSet := lo.Map(ownerships, func(o models.StickerPackOwnership, _ int) uint { + return o.PackID + }) + + var packs []models.StickerPack + if err := database.C.Where("id IN ?", idSet).Find(&packs).Error; err != nil { + return fiber.NewError(fiber.StatusInternalServerError, err.Error()) + } + + return c.JSON(packs) +} + func getStickerPack(c *fiber.Ctx) error { id, _ := c.ParamsInt("packId", 0) pack, err := services.GetStickerPack(uint(id)) @@ -120,3 +144,43 @@ func deleteStickerPack(c *fiber.Ctx) error { return c.JSON(pack) } + +func addStickerPack(c *fiber.Ctx) error { + if err := sec.EnsureAuthenticated(c); err != nil { + return err + } + user := c.Locals("nex_user").(*sec.UserInfo) + + packId, _ := c.ParamsInt("packId", 0) + var pack models.StickerPack + if err := database.C.Where("id = ?", packId).First(&pack).Error; err != nil { + return fiber.NewError(fiber.StatusNotFound, err.Error()) + } + + ownership, err := services.AddStickerPack(user.ID, pack) + if err != nil { + return fiber.NewError(fiber.StatusBadRequest, err.Error()) + } + + return c.JSON(ownership) +} + +func removeStickerPack(c *fiber.Ctx) error { + if err := sec.EnsureAuthenticated(c); err != nil { + return err + } + user := c.Locals("nex_user").(*sec.UserInfo) + + packId, _ := c.ParamsInt("packId", 0) + var pack models.StickerPack + if err := database.C.Where("id = ?", packId).First(&pack).Error; err != nil { + return fiber.NewError(fiber.StatusNotFound, err.Error()) + } + + ownership, err := services.RemoveStickerPack(user.ID, pack) + if err != nil { + return fiber.NewError(fiber.StatusBadRequest, err.Error()) + } + + return c.JSON(ownership) +} diff --git a/pkg/internal/server/api/stickers_api.go b/pkg/internal/server/api/stickers_api.go index 80fe95b..a3b6688 100644 --- a/pkg/internal/server/api/stickers_api.go +++ b/pkg/internal/server/api/stickers_api.go @@ -2,12 +2,10 @@ package api import ( "fmt" + "github.com/samber/lo" "strings" "git.solsynth.dev/hypernet/nexus/pkg/nex/sec" - "git.solsynth.dev/hypernet/paperclip/pkg/internal/gap" - "git.solsynth.dev/hypernet/passport/pkg/authkit" - "git.solsynth.dev/hypernet/paperclip/pkg/internal/database" "git.solsynth.dev/hypernet/paperclip/pkg/internal/models" "git.solsynth.dev/hypernet/paperclip/pkg/internal/server/exts" @@ -64,43 +62,28 @@ func openStickerByAlias(c *fiber.Ctx) error { } func listStickers(c *fiber.Ctx) error { - take := c.QueryInt("take", 0) - offset := c.QueryInt("offset", 0) - - if take > 100 { - take = 100 + if err := sec.EnsureAuthenticated(c); err != nil { + return err } + user := c.Locals("nex_user").(*sec.UserInfo) - tx := database.C - - if len(c.Query("author")) > 0 { - author, err := authkit.GetUserByName(gap.Nx, c.Query("author")) - if err == nil { - tx = tx.Where("account_id = ?", author.ID) - } - } - - if val := c.QueryInt("pack", 0); val > 0 { - tx = tx.Where("pack_id = ?", val) - } - - var count int64 - countTx := tx - if err := countTx.Model(&models.Sticker{}).Count(&count).Error; err != nil { + var ownerships []models.StickerPackOwnership + if err := database.C.Where("account_id = ?", user.ID).Find(&ownerships).Error; err != nil { return fiber.NewError(fiber.StatusInternalServerError, err.Error()) } + tx := database.C.Where("pack_id IN ?", lo.Map(ownerships, func(o models.StickerPackOwnership, _ int) uint { + return o.PackID + })) + var stickers []models.Sticker - if err := tx.Limit(take).Offset(offset). + if err := tx. Preload("Attachment").Preload("Pack"). Find(&stickers).Error; err != nil { return fiber.NewError(fiber.StatusInternalServerError, err.Error()) } - return c.JSON(fiber.Map{ - "count": count, - "data": stickers, - }) + return c.JSON(stickers) } func getSticker(c *fiber.Ctx) error { diff --git a/pkg/internal/services/stickers.go b/pkg/internal/services/stickers.go index 9a6e786..1e8c8a9 100644 --- a/pkg/internal/services/stickers.go +++ b/pkg/internal/services/stickers.go @@ -1,7 +1,9 @@ package services import ( + "errors" "fmt" + "gorm.io/gorm" "git.solsynth.dev/hypernet/paperclip/pkg/internal/database" "git.solsynth.dev/hypernet/paperclip/pkg/internal/models" @@ -71,3 +73,36 @@ func DeleteSticker(sticker models.Sticker) (models.Sticker, error) { } return sticker, nil } + +func AddStickerPack(user uint, pack models.StickerPack) (models.StickerPackOwnership, error) { + var ownership models.StickerPackOwnership + if err := database.C. + Where("account_id = ?", user). + First(&ownership).Error; err != nil && !errors.Is(err, gorm.ErrRecordNotFound) { + return ownership, fmt.Errorf("unable to get current ownership: %v", err) + } else if err == nil { + return ownership, fmt.Errorf("you already own this pack") + } + + ownership = models.StickerPackOwnership{ + AccountID: user, + PackID: pack.ID, + } + + err := database.C.Save(&ownership).Error + + return ownership, err +} + +func RemoveStickerPack(user uint, pack models.StickerPack) (models.StickerPackOwnership, error) { + var ownership models.StickerPackOwnership + if err := database.C. + Where("account_id = ? AND pack_id = ?", user, pack.ID). + First(&ownership).Error; err != nil { + return ownership, fmt.Errorf("unable to get current ownership: %v", err) + } + + err := database.C.Delete(&ownership).Error + + return ownership, err +}