fix: issues

This commit is contained in:
Rogee
2024-12-05 11:32:00 +08:00
parent 9ddd3f61ec
commit c6313f234b
17 changed files with 206 additions and 396 deletions

View File

@@ -16,7 +16,7 @@ type UUIDMap struct {
Name string Name string
} }
func NewStore(path string) (*Store, error) { func NewStore(path string) (Store, error) {
mapFile := filepath.Join(path, "map.json") mapFile := filepath.Join(path, "map.json")
log.Infof("read in from: %s", mapFile) log.Infof("read in from: %s", mapFile)
if _, err := os.Stat(mapFile); err != nil { if _, err := os.Stat(mapFile); err != nil {
@@ -38,10 +38,10 @@ func NewStore(path string) (*Store, error) {
return nil, errors.Wrapf(err, "unmarshal json: %s", mapFile) return nil, errors.Wrapf(err, "unmarshal json: %s", mapFile)
} }
return &store, nil return store, nil
} }
func (s *Store) Save(path string) error { func (s Store) Save(path string) error {
mapFile := filepath.Join(path, "map.json") mapFile := filepath.Join(path, "map.json")
b, err := json.Marshal(s) b, err := json.Marshal(s)
if err != nil { if err != nil {
@@ -55,13 +55,13 @@ func (s *Store) Save(path string) error {
return nil return nil
} }
func (s *Store) Add(uuid, name string) { func (s Store) Add(uuid, name string) {
*s = append(*s, UUIDMap{UUID: uuid, Name: name}) s = append(s, UUIDMap{UUID: uuid, Name: name})
} }
func (s *Store) UUIDs() []string { func (s Store) UUIDs() []string {
var uuids []string var uuids []string
for _, m := range *s { for _, m := range s {
uuids = append(uuids, m.UUID) uuids = append(uuids, m.UUID)
} }
@@ -69,8 +69,8 @@ func (s *Store) UUIDs() []string {
} }
// Exists // Exists
func (s *Store) Exists(name string) bool { func (s Store) Exists(name string) bool {
for _, m := range *s { for _, m := range s {
if m.Name == name { if m.Name == name {
return true return true
} }

View File

@@ -26,3 +26,7 @@ AesKey = "F6AqCxAV4W1eCrY6llJ2zapphKK49CQN3RgtPDrjhnI"
[HashIDs] [HashIDs]
Salt = "LiXi.Y@140202" Salt = "LiXi.Y@140202"
[Storage]
Type = "local"
Path = "/projects/mp-qvyun/backend/fixtures/medias"

View File

@@ -2,6 +2,5 @@ ignores: [] # ignore tables
types: types:
users: # table name users: # table name
oauth: backend/pkg/pg.UserOAuth oauth: backend/pkg/pg.UserOAuth
medias:
media_resources: # table name resources: backend/pkg/pg.MediaResources
type: backend/pkg/pg.MediaType

View File

@@ -71,10 +71,11 @@ CREATE TABLE
uuid uuid NOT NULL, uuid uuid NOT NULL,
tenant_id INT8 NOT NULL, tenant_id INT8 NOT NULL,
title VARCHAR(198) NOT NULL, title VARCHAR(198) NOT NULL,
description VARCHAR(198) NOT NULL, description VARCHAR(198) NOT NULL default '',
price INT8 NOT NULL, price INT8 NOT NULL default 0,
discount INT8 NOT NULL default 100, discount INT8 NOT NULL default 100,
publish BOOL NOT NULL, publish BOOL NOT NULL default false,
resources jsonb default '{}'::jsonb,
created_at timestamp NOT NULL default now(), created_at timestamp NOT NULL default now(),
updated_at timestamp NOT NULL default now() updated_at timestamp NOT NULL default now()
); );
@@ -83,20 +84,6 @@ CREATE INDEX idx_medias_tenant_id ON medias (tenant_id);
CREATE INDEX idx_medias_title ON medias (title); CREATE INDEX idx_medias_title ON medias (title);
CREATE TABLE
media_resources (
id SERIAL8 PRIMARY KEY,
media_id INT8 NOT NULL,
type VARCHAR(128) NOT NULL,
source text NOT NULL default '',
size INT8 NOT NULL,
publish BOOL NOT NULL,
created_at timestamp NOT NULL default now(),
updated_at timestamp NOT NULL default now()
);
CREATE INDEX idx_media_resources_media_id ON media_resources (media_id);
CREATE TABLE user_medias ( CREATE TABLE user_medias (
id SERIAL8 PRIMARY KEY, id SERIAL8 PRIMARY KEY,
user_id INT8 NOT NULL, user_id INT8 NOT NULL,

View File

@@ -1,24 +0,0 @@
//
// Code generated by go-jet DO NOT EDIT.
//
// WARNING: Changes to this file may cause incorrect behavior
// and will be lost if the code is regenerated
//
package model
import (
"backend/pkg/pg"
"time"
)
type MediaResources struct {
ID int64 `sql:"primary_key" json:"id"`
MediaID int64 `json:"media_id"`
Type pg.MediaType `json:"type"`
Source string `json:"source"`
Size int64 `json:"size"`
Publish bool `json:"publish"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}

View File

@@ -8,19 +8,21 @@
package model package model
import ( import (
"backend/pkg/pg"
"github.com/google/uuid" "github.com/google/uuid"
"time" "time"
) )
type Medias struct { type Medias struct {
ID int64 `sql:"primary_key" json:"id"` ID int64 `sql:"primary_key" json:"id"`
UUID uuid.UUID `json:"uuid"` UUID uuid.UUID `json:"uuid"`
TenantID int64 `json:"tenant_id"` TenantID int64 `json:"tenant_id"`
Title string `json:"title"` Title string `json:"title"`
Description string `json:"description"` Description string `json:"description"`
Price int64 `json:"price"` Price int64 `json:"price"`
Discount int64 `json:"discount"` Discount int64 `json:"discount"`
Publish bool `json:"publish"` Publish bool `json:"publish"`
CreatedAt time.Time `json:"created_at"` Resources pg.MediaResources `json:"resources"`
UpdatedAt time.Time `json:"updated_at"` CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
} }

View File

@@ -1,96 +0,0 @@
//
// Code generated by go-jet DO NOT EDIT.
//
// WARNING: Changes to this file may cause incorrect behavior
// and will be lost if the code is regenerated
//
package table
import (
"github.com/go-jet/jet/v2/postgres"
)
var MediaResources = newMediaResourcesTable("public", "media_resources", "")
type mediaResourcesTable struct {
postgres.Table
// Columns
ID postgres.ColumnInteger
MediaID postgres.ColumnInteger
Type postgres.ColumnString
Source postgres.ColumnString
Size postgres.ColumnInteger
Publish postgres.ColumnBool
CreatedAt postgres.ColumnTimestamp
UpdatedAt postgres.ColumnTimestamp
AllColumns postgres.ColumnList
MutableColumns postgres.ColumnList
}
type MediaResourcesTable struct {
mediaResourcesTable
EXCLUDED mediaResourcesTable
}
// AS creates new MediaResourcesTable with assigned alias
func (a MediaResourcesTable) AS(alias string) *MediaResourcesTable {
return newMediaResourcesTable(a.SchemaName(), a.TableName(), alias)
}
// Schema creates new MediaResourcesTable with assigned schema name
func (a MediaResourcesTable) FromSchema(schemaName string) *MediaResourcesTable {
return newMediaResourcesTable(schemaName, a.TableName(), a.Alias())
}
// WithPrefix creates new MediaResourcesTable with assigned table prefix
func (a MediaResourcesTable) WithPrefix(prefix string) *MediaResourcesTable {
return newMediaResourcesTable(a.SchemaName(), prefix+a.TableName(), a.TableName())
}
// WithSuffix creates new MediaResourcesTable with assigned table suffix
func (a MediaResourcesTable) WithSuffix(suffix string) *MediaResourcesTable {
return newMediaResourcesTable(a.SchemaName(), a.TableName()+suffix, a.TableName())
}
func newMediaResourcesTable(schemaName, tableName, alias string) *MediaResourcesTable {
return &MediaResourcesTable{
mediaResourcesTable: newMediaResourcesTableImpl(schemaName, tableName, alias),
EXCLUDED: newMediaResourcesTableImpl("", "excluded", ""),
}
}
func newMediaResourcesTableImpl(schemaName, tableName, alias string) mediaResourcesTable {
var (
IDColumn = postgres.IntegerColumn("id")
MediaIDColumn = postgres.IntegerColumn("media_id")
TypeColumn = postgres.StringColumn("type")
SourceColumn = postgres.StringColumn("source")
SizeColumn = postgres.IntegerColumn("size")
PublishColumn = postgres.BoolColumn("publish")
CreatedAtColumn = postgres.TimestampColumn("created_at")
UpdatedAtColumn = postgres.TimestampColumn("updated_at")
allColumns = postgres.ColumnList{IDColumn, MediaIDColumn, TypeColumn, SourceColumn, SizeColumn, PublishColumn, CreatedAtColumn, UpdatedAtColumn}
mutableColumns = postgres.ColumnList{MediaIDColumn, TypeColumn, SourceColumn, SizeColumn, PublishColumn, CreatedAtColumn, UpdatedAtColumn}
)
return mediaResourcesTable{
Table: postgres.NewTable(schemaName, tableName, alias, allColumns...),
//Columns
ID: IDColumn,
MediaID: MediaIDColumn,
Type: TypeColumn,
Source: SourceColumn,
Size: SizeColumn,
Publish: PublishColumn,
CreatedAt: CreatedAtColumn,
UpdatedAt: UpdatedAtColumn,
AllColumns: allColumns,
MutableColumns: mutableColumns,
}
}

View File

@@ -25,6 +25,7 @@ type mediasTable struct {
Price postgres.ColumnInteger Price postgres.ColumnInteger
Discount postgres.ColumnInteger Discount postgres.ColumnInteger
Publish postgres.ColumnBool Publish postgres.ColumnBool
Resources postgres.ColumnString
CreatedAt postgres.ColumnTimestamp CreatedAt postgres.ColumnTimestamp
UpdatedAt postgres.ColumnTimestamp UpdatedAt postgres.ColumnTimestamp
@@ -75,10 +76,11 @@ func newMediasTableImpl(schemaName, tableName, alias string) mediasTable {
PriceColumn = postgres.IntegerColumn("price") PriceColumn = postgres.IntegerColumn("price")
DiscountColumn = postgres.IntegerColumn("discount") DiscountColumn = postgres.IntegerColumn("discount")
PublishColumn = postgres.BoolColumn("publish") PublishColumn = postgres.BoolColumn("publish")
ResourcesColumn = postgres.StringColumn("resources")
CreatedAtColumn = postgres.TimestampColumn("created_at") CreatedAtColumn = postgres.TimestampColumn("created_at")
UpdatedAtColumn = postgres.TimestampColumn("updated_at") UpdatedAtColumn = postgres.TimestampColumn("updated_at")
allColumns = postgres.ColumnList{IDColumn, UUIDColumn, TenantIDColumn, TitleColumn, DescriptionColumn, PriceColumn, DiscountColumn, PublishColumn, CreatedAtColumn, UpdatedAtColumn} allColumns = postgres.ColumnList{IDColumn, UUIDColumn, TenantIDColumn, TitleColumn, DescriptionColumn, PriceColumn, DiscountColumn, PublishColumn, ResourcesColumn, CreatedAtColumn, UpdatedAtColumn}
mutableColumns = postgres.ColumnList{UUIDColumn, TenantIDColumn, TitleColumn, DescriptionColumn, PriceColumn, DiscountColumn, PublishColumn, CreatedAtColumn, UpdatedAtColumn} mutableColumns = postgres.ColumnList{UUIDColumn, TenantIDColumn, TitleColumn, DescriptionColumn, PriceColumn, DiscountColumn, PublishColumn, ResourcesColumn, CreatedAtColumn, UpdatedAtColumn}
) )
return mediasTable{ return mediasTable{
@@ -93,6 +95,7 @@ func newMediasTableImpl(schemaName, tableName, alias string) mediasTable {
Price: PriceColumn, Price: PriceColumn,
Discount: DiscountColumn, Discount: DiscountColumn,
Publish: PublishColumn, Publish: PublishColumn,
Resources: ResourcesColumn,
CreatedAt: CreatedAtColumn, CreatedAt: CreatedAtColumn,
UpdatedAt: UpdatedAtColumn, UpdatedAt: UpdatedAtColumn,

View File

@@ -10,7 +10,6 @@ package table
// UseSchema sets a new schema name for all generated table SQL builder types. It is recommended to invoke // UseSchema sets a new schema name for all generated table SQL builder types. It is recommended to invoke
// this method only once at the beginning of the program. // this method only once at the beginning of the program.
func UseSchema(schema string) { func UseSchema(schema string) {
MediaResources = MediaResources.FromSchema(schema)
Medias = Medias.FromSchema(schema) Medias = Medias.FromSchema(schema)
Migrations = Migrations.FromSchema(schema) Migrations = Migrations.FromSchema(schema)
TenantUserBalances = TenantUserBalances.FromSchema(schema) TenantUserBalances = TenantUserBalances.FromSchema(schema)

View File

@@ -44,14 +44,9 @@ func (c *Controller) Show(ctx fiber.Ctx) error {
// Audio // Audio
func (c *Controller) Video(ctx fiber.Ctx) error { func (c *Controller) Video(ctx fiber.Ctx) error {
mediaId := ToInt64(ctx.Params("media")) // mediaId := ToInt64(ctx.Params("media"))
tenantId := ToInt64(ctx.Locals("tenantId")) // tenantId := ToInt64(ctx.Locals("tenantId"))
userId := ToInt64(ctx.Locals("userId")) // userId := ToInt64(ctx.Locals("userId"))
item, err := c.svc.GetVideo(ctx.Context(), tenantId, userId, mediaId) return ctx.JSON(nil)
if err != nil {
return ctx.Status(fiber.StatusInternalServerError).JSON(errorx.InternalError)
}
return ctx.JSON(item)
} }

View File

@@ -13,6 +13,5 @@ type ListFilter struct {
type ListItem struct { type ListItem struct {
model.Medias model.Medias
Bought bool `json:"bought"` Bought bool `json:"bought"`
MediaResources []model.MediaResources `json:"media_resources"`
} }

View File

@@ -3,12 +3,15 @@ package medias
import ( import (
"context" "context"
"database/sql" "database/sql"
"path/filepath"
"backend/database/models/qvyun/public/model"
"backend/database/models/qvyun/public/table" "backend/database/models/qvyun/public/table"
"backend/pkg/path"
"backend/pkg/pg" "backend/pkg/pg"
"backend/providers/storage"
. "github.com/go-jet/jet/v2/postgres" . "github.com/go-jet/jet/v2/postgres"
"github.com/google/uuid"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/samber/lo" "github.com/samber/lo"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
@@ -16,8 +19,9 @@ import (
// @provider:except // @provider:except
type Service struct { type Service struct {
db *sql.DB db *sql.DB
log *logrus.Entry `inject:"false"` storageConfig *storage.Config
log *logrus.Entry `inject:"false"`
} }
func (svc *Service) Prepare() error { func (svc *Service) Prepare() error {
@@ -42,26 +46,7 @@ func (svc *Service) GetByID(ctx context.Context, tenantId, userId, id int64) (*L
return nil, errors.Wrap(err, "query media by id") return nil, errors.Wrap(err, "query media by id")
} }
tblResource := table.MediaResources // todo: resources
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 var err error
media.Bought, err = svc.HasUserBought(ctx, tenantId, userId, media.ID) media.Bought, err = svc.HasUserBought(ctx, tenantId, userId, media.ID)
@@ -72,55 +57,6 @@ func (svc *Service) GetByID(ctx context.Context, tenantId, userId, id int64) (*L
return &media, nil 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 // List
func (svc *Service) List(ctx context.Context, tenantId, userId int64, filter *ListFilter) ([]ListItem, error) { func (svc *Service) List(ctx context.Context, tenantId, userId int64, filter *ListFilter) ([]ListItem, error) {
log := svc.log.WithField("method", "List") log := svc.log.WithField("method", "List")
@@ -226,57 +162,76 @@ func (svc *Service) HasUserBought(ctx context.Context, tenantId, userId, mediaId
return mediaID > 0, nil return mediaID > 0, nil
} }
// GetVideo // UnPublishTenantWithNotInUUIDs
func (svc *Service) GetVideo(ctx context.Context, tenantId, userId, mediaId int64) (*pg.MediaSource, error) { func (svc *Service) UnPublishTenantWithNotInUUIDs(ctx context.Context, tenantId int64, uuids []string) error {
log := svc.log.WithField("method", "GetVideo") log := svc.log.WithField("method", "UnPublishTenantWithNotInUUIDs")
ok, err := svc.HasUserBought(ctx, tenantId, userId, mediaId) tbl := table.Medias
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. stmt := tbl.
SELECT(tbl.Source). UPDATE().
SET(
tbl.Publish.SET(Bool(false)),
).
WHERE( WHERE(
tbl.MediaID.EQ(Int(mediaId)).AND( tbl.TenantID.EQ(Int(tenantId)).AND(
tbl.Type.EQ(String(resourceType.String())), tbl.UUID.NOT_IN(lo.Map(uuids, func(item string, _ int) Expression {
return String(item)
})...),
), ),
) )
log.Debug(stmt.DebugSql()) log.Debug(stmt.DebugSql())
var source pg.MediaSource if _, err := stmt.ExecContext(ctx, svc.db); err != nil {
if err := stmt.QueryContext(ctx, svc.db, &source); err != nil { return errors.Wrap(err, "unpublish tenant with not in uuids")
return nil, errors.Wrap(err, "query media source")
} }
return &source, nil return nil
}
// GetTenantUUIDs
func (svc *Service) GetTenantUUIDs(ctx context.Context, tenantId int64) ([]string, error) {
log := svc.log.WithField("method", "GetTenantUUIDs")
tbl := table.Medias
stmt := tbl.
SELECT(tbl.UUID).
WHERE(tbl.TenantID.EQ(Int(tenantId)))
log.Debug(stmt.DebugSql())
var uuids []string
if err := stmt.QueryContext(ctx, svc.db, &uuids); err != nil {
return nil, errors.Wrap(err, "query tenant uuids")
}
return uuids, nil
}
// PublishTenant
func (svc *Service) PublishTenantMedia(ctx context.Context, tenantId int64, uuid uuid.UUID, name string) error {
log := svc.log.WithField("method", "PublishTenant")
resources := pg.MediaResources{}
if path.DirExists(filepath.Join(svc.storageConfig.Path, uuid.String(), pg.MediaTypeVideo.String())) {
resources = append(resources, pg.MediaTypeVideo)
}
if path.DirExists(filepath.Join(svc.storageConfig.Path, uuid.String(), pg.MediaTypeAudio.String())) {
resources = append(resources, pg.MediaTypeAudio)
}
if path.DirExists(filepath.Join(svc.storageConfig.Path, uuid.String(), pg.MediaTypePdf.String())) {
resources = append(resources, pg.MediaTypePdf)
}
tbl := table.Medias
stmt := tbl.
INSERT(tbl.TenantID, tbl.UUID, tbl.Title, tbl.Resources).
VALUES(Int(tenantId), UUID(uuid), String(name), Json(resources.MustValue()))
log.Debug(stmt.DebugSql())
if _, err := stmt.ExecContext(ctx, svc.db); err != nil {
return errors.Wrap(err, "publish tenant")
}
return nil
} }

View File

@@ -8,7 +8,7 @@ import (
"backend/database/models/qvyun/public/table" "backend/database/models/qvyun/public/table"
"backend/fixtures" "backend/fixtures"
dbUtil "backend/pkg/db" dbUtil "backend/pkg/db"
"backend/pkg/pg" "backend/providers/storage"
. "github.com/go-jet/jet/v2/postgres" . "github.com/go-jet/jet/v2/postgres"
"github.com/google/uuid" "github.com/google/uuid"
@@ -118,59 +118,6 @@ func TestService_List(t *testing.T) {
So(err, ShouldBeNil) So(err, ShouldBeNil)
}) })
Convey("create media's resources", func() {
items := []model.MediaResources{
{
MediaID: 1,
Type: pg.MediaTypeVideo,
Size: 100,
Publish: true,
},
{
MediaID: 1,
Type: pg.MediaTypeAudio,
Size: 100,
Publish: true,
},
{
MediaID: 2,
Type: pg.MediaTypeVideo,
Size: 100,
Publish: true,
},
{
MediaID: 2,
Type: pg.MediaTypeAudio,
Size: 100,
Publish: true,
},
{
MediaID: 3,
Type: pg.MediaTypeVideo,
Size: 100,
Publish: true,
},
{
MediaID: 3,
Type: pg.MediaTypeAudio,
Size: 100,
Publish: true,
},
}
tbl := table.MediaResources
stmt := tbl.INSERT(
tbl.MediaID,
tbl.Type,
tbl.Size,
tbl.Publish,
).MODELS(items)
t.Log(stmt.DebugSql())
_, err := stmt.Exec(db)
So(err, ShouldBeNil)
})
Convey("get list", func() { Convey("get list", func() {
svc := &Service{db: db} svc := &Service{db: db}
So(svc.Prepare(), ShouldBeNil) So(svc.Prepare(), ShouldBeNil)
@@ -213,61 +160,50 @@ func TestService_List1(t *testing.T) {
}) })
} }
func TestService_DecorateListResources(t *testing.T) { func TestService_PublishTenant(t *testing.T) {
Convey("TestService_DecorateListResources", t, func() { Convey("TestService_PublishTenant", t, func() {
db, err := fixtures.GetDB() db, err := fixtures.GetDB()
So(err, ShouldBeNil) So(err, ShouldBeNil)
defer db.Close() defer db.Close()
Convey("truncate all tables", func() { Convey("truncate all tables", func() {
So(dbUtil.TruncateAllTables(context.TODO(), db, "medias", "media_resources"), ShouldBeNil) So(dbUtil.TruncateAllTables(context.TODO(), db, "medias"), ShouldBeNil)
}) })
Convey("create media's resources", func() { u1, err := uuid.Parse("6c63c4d8-b2cb-4588-8dd3-9a2276918d17")
items := []model.MediaResources{ So(err, ShouldBeNil)
{
MediaID: 1, u2, err := uuid.Parse("8c183427-02b1-4426-ad65-18c6e7735072")
Type: pg.MediaTypeVideo, So(err, ShouldBeNil)
Size: 100,
Publish: true, u3, err := uuid.Parse("24aa56a1-a85b-4a03-9a1b-c39a36103ddf")
}, So(err, ShouldBeNil)
{
MediaID: 2, Convey("insert some data", func() {
Type: pg.MediaTypeAudio, items := []model.Medias{
Size: 100, {UUID: u1, TenantID: 1, Title: "title1", Description: "hello", Price: 100, Publish: true},
Publish: true, {UUID: u2, TenantID: 1, Title: "title2", Description: "hello", Price: 100, Publish: true},
}, {UUID: u3, TenantID: 1, Title: "title3", Description: "hello", Price: 100, Publish: true},
} }
tbl := table.MediaResources Convey("publish tenant", func() {
stmt := tbl.INSERT( svc := &Service{
tbl.MediaID, db: db,
tbl.Type, storageConfig: &storage.Config{
tbl.Size, Path: "/projects/mp-qvyun/backend/fixtures/medias",
tbl.Publish, },
).MODELS(items) }
t.Log(stmt.DebugSql()) So(svc.Prepare(), ShouldBeNil)
_, err := stmt.Exec(db) err := svc.PublishTenantMedia(context.TODO(), 1, items[0].UUID, items[0].Title)
So(err, ShouldBeNil) So(err, ShouldBeNil)
})
Convey("decorate list resources", func() { err = svc.PublishTenantMedia(context.TODO(), 1, items[1].UUID, items[1].Title)
items := []ListItem{ So(err, ShouldBeNil)
{Medias: model.Medias{ID: 1}},
{Medias: model.Medias{ID: 2}},
}
svc := &Service{db: db} err = svc.PublishTenantMedia(context.TODO(), 1, items[2].UUID, items[2].Title)
So(svc.Prepare(), ShouldBeNil) So(err, ShouldBeNil)
})
items, err := svc.DecorateListResources(context.TODO(), 1, 1, items)
So(err, ShouldBeNil)
for _, item := range items {
So(item.MediaResources, ShouldHaveLength, 1)
}
}) })
}) })
} }

View File

@@ -1,8 +1,14 @@
package store package store
import ( import (
"context"
"backend/common/media_store"
"backend/modules/medias" "backend/modules/medias"
"github.com/google/uuid"
"github.com/pkg/errors"
"github.com/samber/lo"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
) )
@@ -21,5 +27,44 @@ func (d *StoreMedias) Prepare() error {
func (d *StoreMedias) RunE(targetPath string) error { func (d *StoreMedias) RunE(targetPath string) error {
d.log.Infof("Store medias from: %s ", targetPath) d.log.Infof("Store medias from: %s ", targetPath)
store, err := media_store.NewStore(targetPath)
if err != nil {
return errors.Wrapf(err, "new store: %s", targetPath)
}
// uuids := lo.FilterMap(store.UUIDs(), func(item string, _ int) (uuid.UUID, bool) {
// u, err := uuid.FromBytes([]byte(item))
// if err != nil {
// return uuid.Nil, false
// }
// return u, true
// })
if err := d.mediasSvc.UnPublishTenantWithNotInUUIDs(context.Background(), 1, store.UUIDs()); err != nil {
return errors.Wrapf(err, "UnPublishTenantWithNotInUUIDs: %+v", store.UUIDs())
}
dbUUIDs, err := d.mediasSvc.GetTenantUUIDs(context.Background(), 1)
if err != nil {
return errors.Wrap(err, "GetTenantUUIDs")
}
for _, item := range store {
if lo.Contains(dbUUIDs, item.UUID) {
continue
}
u, err := uuid.FromBytes([]byte(item.UUID))
if err != nil {
return errors.Wrap(err, "uuid from bytes")
}
if err := d.mediasSvc.PublishTenantMedia(context.Background(), 1, u, item.Name); err != nil {
return errors.Wrapf(err, "PublishTenant: %+v", item)
}
d.log.Infof("PublishTenant: %+v", item)
}
return nil return nil
} }

View File

@@ -27,3 +27,11 @@ func GetSubDirs(root string) ([]string, error) {
return paths, nil return paths, nil
} }
func DirExists(path string) bool {
st, err := os.Stat(path)
if err != nil {
return false
}
return st.IsDir()
}

View File

@@ -4,6 +4,8 @@ import (
"database/sql/driver" "database/sql/driver"
"encoding/json" "encoding/json"
"errors" "errors"
"github.com/samber/lo"
) )
// swagger:enum MediaType // swagger:enum MediaType
@@ -14,12 +16,9 @@ import (
// ) // )
type MediaType string type MediaType string
type MediaSource struct { type MediaResources []MediaType
Duration int64 `json:"duration"`
Items []MediaSourceItem `json:"items"`
}
func (x MediaSource) Scan(value interface{}) (err error) { func (x MediaResources) Scan(value interface{}) (err error) {
switch v := value.(type) { switch v := value.(type) {
case string: case string:
return json.Unmarshal([]byte(v), &x) return json.Unmarshal([]byte(v), &x)
@@ -31,12 +30,10 @@ func (x MediaSource) Scan(value interface{}) (err error) {
return errors.New("Unknown type for ") return errors.New("Unknown type for ")
} }
func (x MediaSource) Value() (driver.Value, error) { func (x MediaResources) Value() (driver.Value, error) {
return json.Marshal(x) return json.Marshal(x)
} }
type MediaSourceItem struct { func (x MediaResources) MustValue() driver.Value {
Source string `json:"source"` return lo.Must(json.Marshal(x))
Size int64 `json:"size"`
Duration int64 `json:"duration"`
} }

Submodule backend/providers/storage added at 9de1e7b7b0