Files
quyun-v2/backend/app/http/tenant/content.go

200 lines
5.7 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package tenant
import (
"encoding/json"
"net/url"
"time"
"quyun/v2/app/errorx"
"quyun/v2/app/http/tenant/dto"
"quyun/v2/app/requests"
"quyun/v2/app/services"
"quyun/v2/database/models"
"quyun/v2/pkg/consts"
"github.com/gofiber/fiber/v3"
log "github.com/sirupsen/logrus"
)
// content provides tenant-side read-only content endpoints.
//
// @provider
type content struct{}
// list
//
// @Summary 内容列表(已发布)
// @Tags Tenant
// @Accept json
// @Produce json
// @Param tenantCode path string true "Tenant Code"
// @Param filter query dto.ContentListFilter true "Filter"
// @Success 200 {object} requests.Pager{items=dto.ContentItem}
//
// @Router /t/:tenantCode/v1/contents [get]
// @Bind tenant local key(tenant)
// @Bind user local key(user)
// @Bind filter query
func (*content) list(ctx fiber.Ctx, tenant *models.Tenant, user *models.User, filter *dto.ContentListFilter) (*requests.Pager, error) {
log.WithFields(log.Fields{
"tenant_id": tenant.ID,
"user_id": user.ID,
}).Info("tenant.contents.list")
filter.Pagination.Format()
return services.Content.ListPublished(ctx, tenant.ID, user.ID, filter)
}
// show
//
// @Summary 内容详情(可见性+权益校验)
// @Tags Tenant
// @Accept json
// @Produce json
// @Param tenantCode path string true "Tenant Code"
// @Param contentID path int64 true "ContentID"
// @Success 200 {object} dto.ContentDetail
//
// @Router /t/:tenantCode/v1/contents/:contentID [get]
// @Bind tenant local key(tenant)
// @Bind user local key(user)
// @Bind contentID path
func (*content) show(ctx fiber.Ctx, tenant *models.Tenant, user *models.User, contentID int64) (*dto.ContentDetail, error) {
log.WithFields(log.Fields{
"tenant_id": tenant.ID,
"user_id": user.ID,
"content_id": contentID,
}).Info("tenant.contents.show")
item, err := services.Content.Detail(ctx, tenant.ID, user.ID, contentID)
if err != nil {
return nil, err
}
return &dto.ContentDetail{
Content: item.Content,
Price: item.Price,
HasAccess: item.HasAccess,
}, nil
}
// previewAssets
//
// @Summary 获取试看资源preview role
// @Tags Tenant
// @Accept json
// @Produce json
// @Param tenantCode path string true "Tenant Code"
// @Param contentID path int64 true "ContentID"
// @Success 200 {object} dto.ContentAssetsResponse
//
// @Router /t/:tenantCode/v1/contents/:contentID/preview [get]
// @Bind tenant local key(tenant)
// @Bind user local key(user)
// @Bind contentID path
func (*content) previewAssets(ctx fiber.Ctx, tenant *models.Tenant, user *models.User, contentID int64) (*dto.ContentAssetsResponse, error) {
log.WithFields(log.Fields{
"tenant_id": tenant.ID,
"user_id": user.ID,
"content_id": contentID,
}).Info("tenant.contents.preview_assets")
detail, err := services.Content.Detail(ctx, tenant.ID, user.ID, contentID)
if err != nil {
return nil, err
}
assets, err := services.Content.AssetsByRole(ctx, tenant.ID, contentID, consts.ContentAssetRolePreview)
if err != nil {
return nil, err
}
playables := make([]*dto.ContentPlayableAsset, 0, len(assets))
for _, asset := range assets {
token, expiresAt, err := services.MediaDelivery.CreatePlayToken(tenant.ID, contentID, asset.ID, consts.ContentAssetRolePreview, user.ID, 0, time.Now())
if err != nil {
return nil, err
}
var meta json.RawMessage
if len(asset.Meta) > 0 {
meta = json.RawMessage(asset.Meta)
}
playables = append(playables, &dto.ContentPlayableAsset{
AssetID: asset.ID,
Type: asset.Type,
PlayURL: "/t/" + tenant.Code + "/v1/media/play?token=" + url.QueryEscape(token),
ExpiresAt: expiresAt,
Meta: meta,
})
}
previewSeconds := int32(detail.Content.PreviewSeconds)
if previewSeconds <= 0 {
previewSeconds = consts.DefaultContentPreviewSeconds
}
return &dto.ContentAssetsResponse{
Content: detail.Content,
Assets: playables,
PreviewSeconds: previewSeconds,
}, nil
}
// mainAssets
//
// @Summary 获取正片资源main role需要已购或免费
// @Tags Tenant
// @Accept json
// @Produce json
// @Param tenantCode path string true "Tenant Code"
// @Param contentID path int64 true "ContentID"
// @Success 200 {object} dto.ContentAssetsResponse
//
// @Router /t/:tenantCode/v1/contents/:contentID/assets [get]
// @Bind tenant local key(tenant)
// @Bind user local key(user)
// @Bind contentID path
func (*content) mainAssets(ctx fiber.Ctx, tenant *models.Tenant, user *models.User, contentID int64) (*dto.ContentAssetsResponse, error) {
log.WithFields(log.Fields{
"tenant_id": tenant.ID,
"user_id": user.ID,
"content_id": contentID,
}).Info("tenant.contents.main_assets")
detail, err := services.Content.Detail(ctx, tenant.ID, user.ID, contentID)
if err != nil {
return nil, err
}
if !detail.HasAccess {
return nil, errorx.ErrPermissionDenied.WithMsg("未购买或无权限访问")
}
assets, err := services.Content.AssetsByRole(ctx, tenant.ID, contentID, consts.ContentAssetRoleMain)
if err != nil {
return nil, err
}
playables := make([]*dto.ContentPlayableAsset, 0, len(assets))
for _, asset := range assets {
token, expiresAt, err := services.MediaDelivery.CreatePlayToken(tenant.ID, contentID, asset.ID, consts.ContentAssetRoleMain, user.ID, 0, time.Now())
if err != nil {
return nil, err
}
var meta json.RawMessage
if len(asset.Meta) > 0 {
meta = json.RawMessage(asset.Meta)
}
playables = append(playables, &dto.ContentPlayableAsset{
AssetID: asset.ID,
Type: asset.Type,
PlayURL: "/t/" + tenant.Code + "/v1/media/play?token=" + url.QueryEscape(token),
ExpiresAt: expiresAt,
Meta: meta,
})
}
return &dto.ContentAssetsResponse{
Content: detail.Content,
Assets: playables,
}, nil
}