From fbf51fd7fc5890587e844208644be76fd9102c8d Mon Sep 17 00:00:00 2001 From: Rogee Date: Mon, 2 Dec 2024 19:34:22 +0800 Subject: [PATCH] feat: add media sources --- backend/database/.transform.yaml | 1 + backend/modules/medias/controller.go | 27 ++++++++++++ backend/modules/medias/router.go | 2 +- backend/modules/medias/service.go | 66 ++++++++++++++++++++++++++-- backend/pkg/pg/media.go | 33 ++++++++++++++ 5 files changed, 125 insertions(+), 4 deletions(-) diff --git a/backend/database/.transform.yaml b/backend/database/.transform.yaml index 5c40142..a7e5ef8 100755 --- a/backend/database/.transform.yaml +++ b/backend/database/.transform.yaml @@ -5,3 +5,4 @@ types: media_resources: # table name type: backend/pkg/pg.MediaType + source: backend/pkg/pg.MediaSource diff --git a/backend/modules/medias/controller.go b/backend/modules/medias/controller.go index b6de9c4..d1fcd14 100644 --- a/backend/modules/medias/controller.go +++ b/backend/modules/medias/controller.go @@ -28,3 +28,30 @@ func (c *Controller) List(ctx fiber.Ctx) error { return ctx.JSON(items) } + +// Show +func (c *Controller) Show(ctx fiber.Ctx) error { + id := ToInt64(ctx.Params("id")) + tenantId, userId := ToInt64(ctx.Locals("tenantId")), ToInt64(ctx.Locals("userId")) + + item, err := c.svc.GetByID(ctx.Context(), tenantId, userId, id) + if err != nil { + return ctx.Status(fiber.StatusInternalServerError).JSON(errorx.InternalError) + } + + return ctx.JSON(item) +} + +// Audio +func (c *Controller) Video(ctx fiber.Ctx) error { + mediaId := ToInt64(ctx.Params("media")) + tenantId := ToInt64(ctx.Locals("tenantId")) + userId := ToInt64(ctx.Locals("userId")) + + item, err := c.svc.GetVideo(ctx.Context(), tenantId, userId, mediaId) + if err != nil { + return ctx.Status(fiber.StatusInternalServerError).JSON(errorx.InternalError) + } + + return ctx.JSON(item) +} diff --git a/backend/modules/medias/router.go b/backend/modules/medias/router.go index a2a3f60..990c36c 100755 --- a/backend/modules/medias/router.go +++ b/backend/modules/medias/router.go @@ -20,7 +20,7 @@ func (r *Router) Register() error { group := r.http.Engine.Group("medias") log.Infof("register route group: %s", group.(*fiber.Group).Prefix) group.Get("", r.controller.List) - group.Get("{id}", r.controller.List) + group.Get("{id}", r.controller.Show) return nil } diff --git a/backend/modules/medias/service.go b/backend/modules/medias/service.go index f46b776..955f9e0 100644 --- a/backend/modules/medias/service.go +++ b/backend/modules/medias/service.go @@ -6,6 +6,7 @@ import ( "backend/database/models/qvyun/public/model" "backend/database/models/qvyun/public/table" + "backend/pkg/pg" . "github.com/go-jet/jet/v2/postgres" "github.com/pkg/errors" @@ -25,11 +26,15 @@ func (svc *Service) Prepare() error { } // GetByID -func (svc *Service) GetByID(ctx context.Context, id, userId int64) (*ListItem, error) { +func (svc *Service) GetByID(ctx context.Context, tenantId, userId, id int64) (*ListItem, error) { log := svc.log.WithField("method", "GetByID") tbl := table.Medias - stmt := tbl.SELECT(tbl.AllColumns).WHERE(tbl.ID.EQ(Int(id))) + stmt := tbl.SELECT(tbl.AllColumns).WHERE( + tbl.ID.EQ(Int(id)).AND( + tbl.TenantID.EQ(Int(tenantId)), + ), + ) log.Debug(stmt.Sql()) var media ListItem @@ -59,7 +64,7 @@ func (svc *Service) GetByID(ctx context.Context, id, userId int64) (*ListItem, e media.MediaResources = resources var err error - media.Bought, err = svc.HasUserBought(ctx, media.TenantID, userId, media.ID) + media.Bought, err = svc.HasUserBought(ctx, tenantId, userId, media.ID) if err != nil { return nil, errors.Wrap(err, "check user bought") } @@ -220,3 +225,58 @@ func (svc *Service) HasUserBought(ctx context.Context, tenantId, userId, mediaId return mediaID > 0, nil } + +// GetVideo +func (svc *Service) GetVideo(ctx context.Context, tenantId, userId, mediaId int64) (*pg.MediaSource, error) { + log := svc.log.WithField("method", "GetVideo") + + ok, err := svc.HasUserBought(ctx, tenantId, userId, mediaId) + if err != nil { + return nil, errors.Wrap(err, "check user bought") + } + log.Debugf("user bought media: %d of tennatID: %d", mediaId, tenantId) + + source, err := svc.GetResourceOfType(ctx, mediaId, pg.MediaTypeVideo) + if err != nil { + return nil, errors.Wrap(err, "get video resource") + } + + if ok { + return source, nil + } + // cut 1 min video + maxDuration := int64(60) + duration := int64(0) + + for i, item := range source.Items { + duration += item.Duration + if duration >= maxDuration { + source.Items = source.Items[:i] + break + } + } + + return source, nil +} + +// GetResourceOfType +func (svc *Service) GetResourceOfType(ctx context.Context, mediaId int64, resourceType pg.MediaType) (*pg.MediaSource, error) { + log := svc.log.WithField("method", "GetResourceOfType") + + tbl := table.MediaResources + stmt := tbl. + SELECT(tbl.Source). + WHERE( + tbl.MediaID.EQ(Int(mediaId)).AND( + tbl.Type.EQ(String(resourceType.String())), + ), + ) + log.Debug(stmt.DebugSql()) + + var source pg.MediaSource + if err := stmt.QueryContext(ctx, svc.db, &source); err != nil { + return nil, errors.Wrap(err, "query media source") + } + + return &source, nil +} diff --git a/backend/pkg/pg/media.go b/backend/pkg/pg/media.go index d4e03e3..16cbcb6 100644 --- a/backend/pkg/pg/media.go +++ b/backend/pkg/pg/media.go @@ -1,5 +1,11 @@ package pg +import ( + "database/sql/driver" + "encoding/json" + "errors" +) + // swagger:enum MediaType // ENUM( // Video = "video", @@ -7,3 +13,30 @@ package pg // Pdf = "pdf", // ) type MediaType string + +type MediaSource struct { + Duration int64 `json:"duration"` + Items []MediaSourceItem `json:"items"` +} + +func (x MediaSource) Scan(value interface{}) (err error) { + switch v := value.(type) { + case string: + return json.Unmarshal([]byte(v), &x) + case []byte: + return json.Unmarshal(v, &x) + case *string: + return json.Unmarshal([]byte(*v), &x) + } + return errors.New("Unknown type for ") +} + +func (x MediaSource) Value() (driver.Value, error) { + return json.Marshal(x) +} + +type MediaSourceItem struct { + Source string `json:"source"` + Size int64 `json:"size"` + Duration int64 `json:"duration"` +}