diff --git a/.idea/workspace.xml b/.idea/workspace.xml
index 5f2354a..c8bf724 100644
--- a/.idea/workspace.xml
+++ b/.idea/workspace.xml
@@ -4,9 +4,17 @@
-
+
+
+
+
-
+
+
+
+
+
+
@@ -118,7 +126,8 @@
-
+
+
true
diff --git a/pkg/internal/database/migrator.go b/pkg/internal/database/migrator.go
index e96e3b7..0e106de 100644
--- a/pkg/internal/database/migrator.go
+++ b/pkg/internal/database/migrator.go
@@ -8,6 +8,7 @@ import (
var AutoMaintainRange = []any{
&models.Account{},
&models.Attachment{},
+ &models.AttachmentPool{},
&models.StickerPack{},
&models.Sticker{},
}
diff --git a/pkg/internal/models/accounts.go b/pkg/internal/models/accounts.go
index 39702cb..af6c3b1 100644
--- a/pkg/internal/models/accounts.go
+++ b/pkg/internal/models/accounts.go
@@ -6,13 +6,15 @@ package models
type Account struct {
BaseModel
- Name string `json:"name"`
- Nick string `json:"nick"`
- Avatar string `json:"avatar"`
- Banner string `json:"banner"`
- Description string `json:"description"`
- EmailAddress string `json:"email_address"`
- PowerLevel int `json:"power_level"`
- Attachments []Attachment `json:"attachments"`
- ExternalID uint `json:"external_id"`
+ Name string `json:"name"`
+ Nick string `json:"nick"`
+ Avatar string `json:"avatar"`
+ Banner string `json:"banner"`
+ Description string `json:"description"`
+ EmailAddress string `json:"email_address"`
+ PowerLevel int `json:"power_level"`
+ ExternalID uint `json:"external_id"`
+
+ Attachments []Attachment `json:"attachments"`
+ Pools []AttachmentPool `json:"pools"`
}
diff --git a/pkg/internal/models/attachments.go b/pkg/internal/models/attachments.go
index 08f82fe..29ce7bc 100644
--- a/pkg/internal/models/attachments.go
+++ b/pkg/internal/models/attachments.go
@@ -1,6 +1,9 @@
package models
-import "gorm.io/datatypes"
+import (
+ "gorm.io/datatypes"
+ "time"
+)
type AttachmentDst = int8
@@ -22,6 +25,8 @@ type Attachment struct {
Destination AttachmentDst `json:"destination"`
RefCount int `json:"ref_count"`
+ CleanedAt *time.Time `json:"cleaned_at"`
+
Metadata datatypes.JSONMap `json:"metadata"`
IsMature bool `json:"is_mature"`
IsAnalyzed bool `json:"is_analyzed"`
@@ -30,6 +35,9 @@ type Attachment struct {
Ref *Attachment `json:"ref"`
RefID *uint `json:"ref_id"`
+ Pool *AttachmentPool `json:"pool"`
+ PoolID *uint `json:"pool_id"`
+
Account Account `json:"account"`
AccountID uint `json:"account_id"`
}
diff --git a/pkg/internal/models/metadata.go b/pkg/internal/models/metadata.go
deleted file mode 100644
index f448291..0000000
--- a/pkg/internal/models/metadata.go
+++ /dev/null
@@ -1,4 +0,0 @@
-package models
-
-type MediaMetadata struct {
-}
diff --git a/pkg/internal/models/pools.go b/pkg/internal/models/pools.go
new file mode 100644
index 0000000..6440891
--- /dev/null
+++ b/pkg/internal/models/pools.go
@@ -0,0 +1,22 @@
+package models
+
+import "gorm.io/datatypes"
+
+type AttachmentPool struct {
+ BaseModel
+
+ Alias string `json:"alias"`
+ Name string `json:"name"`
+ Description string `json:"description"`
+ Config datatypes.JSONType[AttachmentPoolConfig] `json:"config"`
+
+ Attachments []Attachment `json:"attachments"`
+
+ Account *Account `json:"account"`
+ AccountID *uint `json:"account_id"`
+}
+
+type AttachmentPoolConfig struct {
+ ExistLifecycle *int `json:"exist_lifecycle"`
+ IsPublicAccessible bool `json:"is_public_accessible"`
+}
diff --git a/pkg/internal/server/api/attachments_api.go b/pkg/internal/server/api/attachments_api.go
index 20efe37..34cc183 100644
--- a/pkg/internal/server/api/attachments_api.go
+++ b/pkg/internal/server/api/attachments_api.go
@@ -95,7 +95,7 @@ func createAttachment(c *fiber.Ctx) error {
return err
}
- if err := gap.H.EnsureGrantedPerm(c, "CreateAttachments", file.Size); err != nil {
+ if err = gap.H.EnsureGrantedPerm(c, "CreateAttachments", file.Size); err != nil {
return err
}
diff --git a/pkg/internal/server/api/index.go b/pkg/internal/server/api/index.go
index 2be246e..e0254be 100644
--- a/pkg/internal/server/api/index.go
+++ b/pkg/internal/server/api/index.go
@@ -7,6 +7,12 @@ func MapAPIs(app *fiber.App, baseURL string) {
api := app.Group(baseURL).Name("API")
{
+ api.Get("/pools", listPost)
+ api.Get("/pools/:id", getPool)
+ api.Post("/pools", createPool)
+ api.Put("/pools/:id", updatePool)
+ api.Delete("/pools/:id", deletePool)
+
api.Get("/attachments", listAttachment)
api.Get("/attachments/:id/meta", getAttachmentMeta)
api.Get("/attachments/:id", openAttachment)
diff --git a/pkg/internal/server/api/pools_api.go b/pkg/internal/server/api/pools_api.go
new file mode 100644
index 0000000..fc38aac
--- /dev/null
+++ b/pkg/internal/server/api/pools_api.go
@@ -0,0 +1,113 @@
+package api
+
+import (
+ "git.solsynth.dev/hydrogen/paperclip/pkg/internal/gap"
+ "git.solsynth.dev/hydrogen/paperclip/pkg/internal/models"
+ "git.solsynth.dev/hydrogen/paperclip/pkg/internal/server/exts"
+ "git.solsynth.dev/hydrogen/paperclip/pkg/internal/services"
+ "github.com/gofiber/fiber/v2"
+ "gorm.io/datatypes"
+)
+
+func listPost(c *fiber.Ctx) error {
+ pools, err := services.ListAttachmentPool()
+ if err != nil {
+ return fiber.NewError(fiber.StatusBadRequest, err.Error())
+ }
+ return c.JSON(pools)
+}
+
+func getPool(c *fiber.Ctx) error {
+ id, _ := c.ParamsInt("id")
+ pool, err := services.GetAttachmentPool(uint(id))
+ if err != nil {
+ return fiber.NewError(fiber.StatusBadRequest, err.Error())
+ }
+ return c.JSON(pool)
+}
+
+func createPool(c *fiber.Ctx) error {
+ if err := gap.H.EnsureGrantedPerm(c, "CreateAttachmentPools", true); err != nil {
+ return err
+ }
+ user := c.Locals("user").(models.Account)
+
+ var data struct {
+ Alias string `json:"alias" validate:"required"`
+ Name string `json:"name" validate:"required"`
+ Description string `json:"description"`
+ Config models.AttachmentPoolConfig `json:"config"`
+ }
+
+ if err := exts.BindAndValidate(c, &data); err != nil {
+ return err
+ }
+
+ pool := models.AttachmentPool{
+ Alias: data.Alias,
+ Name: data.Name,
+ Description: data.Description,
+ Config: datatypes.NewJSONType(data.Config),
+ AccountID: &user.ID,
+ }
+
+ if pool, err := services.NewAttachmentPool(pool); err != nil {
+ return fiber.NewError(fiber.StatusBadRequest, err.Error())
+ } else {
+ return c.JSON(pool)
+ }
+}
+
+func updatePool(c *fiber.Ctx) error {
+ if err := gap.H.EnsureAuthenticated(c); err != nil {
+ return err
+ }
+ user := c.Locals("user").(models.Account)
+
+ var data struct {
+ Alias string `json:"alias" validate:"required"`
+ Name string `json:"name" validate:"required"`
+ Description string `json:"description"`
+ Config models.AttachmentPoolConfig `json:"config"`
+ }
+
+ if err := exts.BindAndValidate(c, &data); err != nil {
+ return err
+ }
+
+ id, _ := c.ParamsInt("id")
+ pool, err := services.GetAttachmentPoolWithUser(uint(id), user.ID)
+ if err != nil {
+ return fiber.NewError(fiber.StatusBadRequest, err.Error())
+ }
+
+ pool.Alias = data.Alias
+ pool.Name = data.Name
+ pool.Description = data.Description
+ pool.Config = datatypes.NewJSONType(data.Config)
+
+ if pool, err := services.UpdateAttachmentPool(pool); err != nil {
+ return fiber.NewError(fiber.StatusBadRequest, err.Error())
+ } else {
+ return c.JSON(pool)
+ }
+}
+
+func deletePool(c *fiber.Ctx) error {
+ if err := gap.H.EnsureAuthenticated(c); err != nil {
+ return err
+ }
+ user := c.Locals("user").(models.Account)
+
+ id, _ := c.ParamsInt("id")
+ pool, err := services.GetAttachmentPoolWithUser(uint(id), user.ID)
+ if err != nil {
+ return fiber.NewError(fiber.StatusBadRequest, err.Error())
+ }
+
+ if pool, err := services.DeleteAttachmentPool(pool); err != nil {
+ return fiber.NewError(fiber.StatusBadRequest, err.Error())
+ } else {
+ return c.JSON(pool)
+ }
+}
diff --git a/pkg/internal/services/pools.go b/pkg/internal/services/pools.go
new file mode 100644
index 0000000..e5989b7
--- /dev/null
+++ b/pkg/internal/services/pools.go
@@ -0,0 +1,51 @@
+package services
+
+import (
+ "git.solsynth.dev/hydrogen/paperclip/pkg/internal/database"
+ "git.solsynth.dev/hydrogen/paperclip/pkg/internal/models"
+)
+
+func ListAttachmentPool() ([]models.AttachmentPool, error) {
+ var pools []models.AttachmentPool
+ if err := database.C.Find(&pools).Error; err != nil {
+ return pools, err
+ }
+ return pools, nil
+}
+
+func GetAttachmentPool(id uint) (models.AttachmentPool, error) {
+ var pool models.AttachmentPool
+ if err := database.C.Where("id = ?", id).First(&pool).Error; err != nil {
+ return pool, err
+ }
+ return pool, nil
+}
+
+func GetAttachmentPoolWithUser(id uint, userId uint) (models.AttachmentPool, error) {
+ var pool models.AttachmentPool
+ if err := database.C.Where("id = ? AND account_id = ?", id, userId).First(&pool).Error; err != nil {
+ return pool, err
+ }
+ return pool, nil
+}
+
+func NewAttachmentPool(pool models.AttachmentPool) (models.AttachmentPool, error) {
+ if err := database.C.Save(&pool).Error; err != nil {
+ return pool, err
+ }
+ return pool, nil
+}
+
+func UpdateAttachmentPool(pool models.AttachmentPool) (models.AttachmentPool, error) {
+ if err := database.C.Save(&pool).Error; err != nil {
+ return pool, err
+ }
+ return pool, nil
+}
+
+func DeleteAttachmentPool(pool models.AttachmentPool) (models.AttachmentPool, error) {
+ if err := database.C.Delete(&pool).Error; err != nil {
+ return pool, err
+ }
+ return pool, nil
+}