package medias import ( "context" "database/sql" "backend/database/models/qvyun/public/model" "backend/database/models/qvyun/public/table" . "github.com/go-jet/jet/v2/postgres" "github.com/pkg/errors" "github.com/samber/lo" "github.com/sirupsen/logrus" ) // @provider:except type Service struct { db *sql.DB log *logrus.Entry `inject:"false"` } func (svc *Service) Prepare() error { svc.log = logrus.WithField("module", "medias.service") return nil } // GetByID func (svc *Service) GetByID(ctx context.Context, id, userId int64) (*ListItem, error) { log := svc.log.WithField("method", "GetByID") tbl := table.Medias stmt := tbl.SELECT(tbl.AllColumns).WHERE(tbl.ID.EQ(Int(id))) log.Debug(stmt.Sql()) var media ListItem if err := stmt.QueryContext(ctx, svc.db, &media); err != nil { return nil, errors.Wrap(err, "query media by id") } tblResource := table.MediaResources stmtResource := tblResource. SELECT( tblResource.MediaID, tblResource.Type, tblResource.Size, ). WHERE(tblResource.MediaID.EQ(Int(id))) log.Debug(stmtResource.DebugSql()) var resources []model.MediaResources if err := stmt.QueryContext(ctx, svc.db, &resources); err != nil { return nil, errors.Wrap(err, "query media resources") } if len(resources) == 0 { return &media, nil } media.MediaResources = resources var err error media.Bought, err = svc.HasUserBought(ctx, media.TenantID, userId, media.ID) if err != nil { return nil, errors.Wrap(err, "check user bought") } return &media, nil } // Decorate List Resources func (svc *Service) DecorateListResources(ctx context.Context, tenantId, userId int64, items []ListItem) ([]ListItem, error) { log := svc.log.WithField("method", "DecorateListResources") mediaIDs := make([]int64, len(items)) for i, item := range items { mediaIDs[i] = item.ID } tbl := table.MediaResources stmt := tbl. SELECT( tbl.MediaID, tbl.Type, tbl.Size, ). WHERE(tbl.MediaID.IN(lo.Map(mediaIDs, func(item int64, _ int) Expression { return Int(item) })...)) log.Debug(stmt.DebugSql()) var resources []model.MediaResources if err := stmt.QueryContext(ctx, svc.db, &resources); err != nil { return nil, errors.Wrap(err, "query media resources") } if len(resources) == 0 { return nil, nil } // group resources by media id resourcesMap := make(map[int64][]model.MediaResources) for _, resource := range resources { if _, ok := resourcesMap[resource.MediaID]; !ok { resourcesMap[resource.MediaID] = make([]model.MediaResources, 0) } resourcesMap[resource.MediaID] = append(resourcesMap[resource.MediaID], resource) } // set resources to items for i, item := range items { if resources, ok := resourcesMap[item.ID]; ok { items[i].MediaResources = resources } } return items, nil } // List func (svc *Service) List(ctx context.Context, tenantId, userId int64, filter *ListFilter) ([]ListItem, error) { log := svc.log.WithField("method", "List") boughtIDs, err := svc.GetUserBoughtMedias(ctx, tenantId, userId) if err != nil { return nil, errors.Wrap(err, "get user bought medias") } tbl := table.Medias stmt := tbl. SELECT(tbl.AllColumns). WHERE(tbl.TenantID.EQ(Int(tenantId))). ORDER_BY(tbl.ID.DESC()) if filter.Title != nil && *filter.Title != "" { stmt = stmt.WHERE(tbl.Title.LIKE(String("%" + *filter.Title + "%"))) } if filter.Bought != nil && *filter.Bought { if len(boughtIDs) > 0 { stmt = stmt. WHERE(tbl.ID.IN(lo.Map(boughtIDs, func(item int64, _ int) Expression { return Int(item) })...)) } } else { stmt = stmt.WHERE(tbl.Publish.EQ(Bool(true))) } if filter.OffsetID > 0 { if filter.Action == 0 { stmt = stmt.WHERE(tbl.ID.GT(Int(filter.OffsetID))) } if filter.Action == 1 { stmt = stmt.WHERE(tbl.ID.LT(Int(filter.OffsetID))) stmt = stmt.LIMIT(10) } } else { stmt = stmt.LIMIT(10) } log.Debug(stmt.DebugSql()) var dest []ListItem if err := stmt.QueryContext(ctx, svc.db, &dest); err != nil { return nil, errors.Wrap(err, "query medias") } items := lo.Map(dest, func(item ListItem, _ int) ListItem { if lo.Contains(boughtIDs, item.ID) { item.Bought = true } return item }) return items, nil } // GetUserBoughtMedias func (svc *Service) GetUserBoughtMedias(ctx context.Context, tenant int64, userID int64) ([]int64, error) { log := svc.log.WithField("method", "GetUserBoughtMedias") tbl := table.UserMedias stmt := tbl. SELECT(tbl.MediaID). WHERE( tbl.TenantID.EQ(Int(tenant)).AND( tbl.UserID.EQ(Int(userID)), ), ) log.Debug(stmt.Sql()) var mediaIDs []int64 if err := stmt.QueryContext(ctx, svc.db, &mediaIDs); err != nil { return nil, errors.Wrap(err, "query user bought medias") } return mediaIDs, nil } // HasUserBought func (svc *Service) HasUserBought(ctx context.Context, tenantId, userId, mediaId int64) (bool, error) { log := svc.log.WithField("method", "HasUserBought") tbl := table.UserMedias stmt := tbl. SELECT(tbl.MediaID). WHERE( tbl.TenantID.EQ(Int(tenantId)).AND( tbl.UserID.EQ(Int(userId)).AND( tbl.MediaID.EQ(Int(mediaId)), ), ), ) log.Debug(stmt.DebugSql()) var mediaID int64 if err := stmt.QueryContext(ctx, svc.db, &mediaID); err != nil { return false, errors.Wrap(err, "query user bought media") } return mediaID > 0, nil }