topfans/backend/services/socialService/service/asset_like_service.go
2026-05-16 02:42:32 +08:00

481 lines
13 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 service
import (
"context"
"fmt"
"time"
"github.com/topfans/backend/pkg/logger"
assetPb "github.com/topfans/backend/pkg/proto/asset"
pbCommon "github.com/topfans/backend/pkg/proto/common"
pb "github.com/topfans/backend/pkg/proto/social"
"github.com/topfans/backend/services/socialService/client"
"github.com/topfans/backend/services/socialService/repository"
"go.uber.org/zap"
)
// AssetLikeService 资产点赞业务逻辑层
type AssetLikeService struct {
assetClient *client.AssetClient
socialRepo repository.SocialRepository
}
// NewAssetLikeService 创建资产点赞Service实例
func NewAssetLikeService(assetClient *client.AssetClient, socialRepo repository.SocialRepository) *AssetLikeService {
return &AssetLikeService{
assetClient: assetClient,
socialRepo: socialRepo,
}
}
// LikeAsset 点赞资产
func (s *AssetLikeService) LikeAsset(ctx context.Context, assetID, userID, starID int64) error {
logger.Logger.Debug("AssetLikeService.LikeAsset called",
zap.Int64("asset_id", assetID),
zap.Int64("user_id", userID),
zap.Int64("star_id", starID),
)
// 1. 验证资产是否存在使用内部RPC不验证所有权
getAssetReq := &assetPb.GetAssetForRPCRequest{
AssetId: assetID,
}
getAssetResp, err := s.assetClient.GetAssetForRPC(ctx, getAssetReq)
if err != nil {
logger.Logger.Error("Failed to get asset for RPC",
zap.Error(err),
zap.Int64("asset_id", assetID),
)
return fmt.Errorf("failed to get asset: %w", err)
}
if getAssetResp.Base.Code != pbCommon.StatusCode_STATUS_OK {
logger.Logger.Warn("Asset not found or error",
zap.Int64("asset_id", assetID),
zap.Int32("code", int32(getAssetResp.Base.Code)),
zap.String("message", getAssetResp.Base.Message),
)
return fmt.Errorf("asset not found: %s", getAssetResp.Base.Message)
}
// 2. 检查是否已点赞
checkLikeReq := &assetPb.CheckAssetLikeRequest{
AssetId: assetID,
}
checkLikeResp, err := s.assetClient.CheckAssetLike(ctx, checkLikeReq)
if err != nil {
logger.Logger.Error("Failed to check asset like",
zap.Error(err),
zap.Int64("asset_id", assetID),
)
return fmt.Errorf("failed to check asset like: %w", err)
}
if checkLikeResp.IsLiked {
logger.Logger.Warn("Already liked asset",
zap.Int64("asset_id", assetID),
zap.Int64("user_id", userID),
)
return fmt.Errorf("already liked this asset")
}
// 3. 调用 Asset Service 点赞接口
likeReq := &assetPb.LikeAssetRequest{
AssetId: assetID,
}
likeResp, err := s.assetClient.LikeAsset(ctx, likeReq)
if err != nil {
logger.Logger.Error("Failed to like asset",
zap.Error(err),
zap.Int64("asset_id", assetID),
)
return fmt.Errorf("failed to like asset: %w", err)
}
if likeResp.Base.Code != pbCommon.StatusCode_STATUS_OK {
logger.Logger.Warn("Like asset failed",
zap.Int64("asset_id", assetID),
zap.Int32("code", int32(likeResp.Base.Code)),
zap.String("message", likeResp.Base.Message),
)
return fmt.Errorf("like asset failed: %s", likeResp.Base.Message)
}
logger.Logger.Info("Successfully liked asset",
zap.Int64("asset_id", assetID),
zap.Int64("user_id", userID),
zap.Int64("star_id", starID),
)
return nil
}
// UnlikeAsset 取消点赞资产
func (s *AssetLikeService) UnlikeAsset(ctx context.Context, assetID, userID, starID int64) error {
logger.Logger.Debug("AssetLikeService.UnlikeAsset called",
zap.Int64("asset_id", assetID),
zap.Int64("user_id", userID),
zap.Int64("star_id", starID),
)
// 1. 检查是否已点赞
checkLikeReq := &assetPb.CheckAssetLikeRequest{
AssetId: assetID,
}
checkLikeResp, err := s.assetClient.CheckAssetLike(ctx, checkLikeReq)
if err != nil {
logger.Logger.Error("Failed to check asset like",
zap.Error(err),
zap.Int64("asset_id", assetID),
)
return fmt.Errorf("failed to check asset like: %w", err)
}
if !checkLikeResp.IsLiked {
logger.Logger.Warn("Not liked asset yet",
zap.Int64("asset_id", assetID),
zap.Int64("user_id", userID),
)
return fmt.Errorf("not liked this asset yet")
}
// 2. 调用 Asset Service 取消点赞接口
unlikeReq := &assetPb.UnlikeAssetRequest{
AssetId: assetID,
}
unlikeResp, err := s.assetClient.UnlikeAsset(ctx, unlikeReq)
if err != nil {
logger.Logger.Error("Failed to unlike asset",
zap.Error(err),
zap.Int64("asset_id", assetID),
)
return fmt.Errorf("failed to unlike asset: %w", err)
}
if unlikeResp.Base.Code != pbCommon.StatusCode_STATUS_OK {
logger.Logger.Warn("Unlike asset failed",
zap.Int64("asset_id", assetID),
zap.Int32("code", int32(unlikeResp.Base.Code)),
zap.String("message", unlikeResp.Base.Message),
)
return fmt.Errorf("unlike asset failed: %s", unlikeResp.Base.Message)
}
logger.Logger.Info("Successfully unliked asset",
zap.Int64("asset_id", assetID),
zap.Int64("user_id", userID),
zap.Int64("star_id", starID),
)
return nil
}
// CheckAssetLike 检查是否已点赞资产
func (s *AssetLikeService) CheckAssetLike(ctx context.Context, assetID, userID, starID int64) (bool, error) {
logger.Logger.Debug("AssetLikeService.CheckAssetLike called",
zap.Int64("asset_id", assetID),
zap.Int64("user_id", userID),
zap.Int64("star_id", starID),
)
checkLikeReq := &assetPb.CheckAssetLikeRequest{
AssetId: assetID,
}
checkLikeResp, err := s.assetClient.CheckAssetLike(ctx, checkLikeReq)
if err != nil {
logger.Logger.Error("Failed to check asset like",
zap.Error(err),
zap.Int64("asset_id", assetID),
)
return false, fmt.Errorf("failed to check asset like: %w", err)
}
if checkLikeResp.Base.Code != pbCommon.StatusCode_STATUS_OK {
logger.Logger.Warn("Check asset like failed",
zap.Int64("asset_id", assetID),
zap.Int32("code", int32(checkLikeResp.Base.Code)),
zap.String("message", checkLikeResp.Base.Message),
)
return false, fmt.Errorf("check asset like failed: %s", checkLikeResp.Base.Message)
}
return checkLikeResp.IsLiked, nil
}
// GetAssetLikes 获取资产点赞列表
func (s *AssetLikeService) GetAssetLikes(ctx context.Context, assetID int64, page, pageSize int32) (*assetPb.GetAssetLikesResponse, error) {
logger.Logger.Debug("AssetLikeService.GetAssetLikes called",
zap.Int64("asset_id", assetID),
zap.Int32("page", page),
zap.Int32("page_size", pageSize),
)
getLikesReq := &assetPb.GetAssetLikesRequest{
AssetId: assetID,
Page: page,
PageSize: pageSize,
}
getLikesResp, err := s.assetClient.GetAssetLikes(ctx, getLikesReq)
if err != nil {
logger.Logger.Error("Failed to get asset likes",
zap.Error(err),
zap.Int64("asset_id", assetID),
)
return nil, fmt.Errorf("failed to get asset likes: %w", err)
}
if getLikesResp.Base.Code != pbCommon.StatusCode_STATUS_OK {
logger.Logger.Warn("Get asset likes failed",
zap.Int64("asset_id", assetID),
zap.Int32("code", int32(getLikesResp.Base.Code)),
zap.String("message", getLikesResp.Base.Message),
)
return nil, fmt.Errorf("get asset likes failed: %s", getLikesResp.Base.Message)
}
return getLikesResp, nil
}
// GetMyLikedAssets 获取我点赞的作品列表
func (s *AssetLikeService) GetMyLikedAssets(ctx context.Context, req *pb.GetMyLikedAssetsRequest, userID, starID int64) (*pb.GetMyLikedAssetsResponse, error) {
page := req.Page
if page <= 0 {
page = 1
}
pageSize := req.PageSize
if pageSize <= 0 {
pageSize = 20
}
if pageSize > 100 {
pageSize = 100
}
items, total, err := s.socialRepo.GetMyLikedAssets(userID, starID, int(page), int(pageSize))
if err != nil {
logger.Logger.Error("Failed to get my liked assets",
zap.Error(err),
zap.Int64("user_id", userID),
zap.Int64("star_id", starID),
)
return &pb.GetMyLikedAssetsResponse{
Base: &pbCommon.BaseResponse{
Code: pbCommon.StatusCode_STATUS_INTERNAL_ERROR,
Message: "Failed to get my liked assets: " + err.Error(),
Timestamp: time.Now().UnixMilli(),
},
}, nil
}
// 转换为 proto 类型
pbItems := make([]*pb.LikedAssetItem, 0, len(items))
for _, item := range items {
pbItems = append(pbItems, &pb.LikedAssetItem{
AssetId: item.AssetID,
Name: item.Name,
CoverUrl: item.CoverURL,
LikeCount: item.LikeCount,
LikedAt: item.LikedAt,
Earnings: item.Earnings,
})
}
hasMore := int64(page)*int64(pageSize) < total
return &pb.GetMyLikedAssetsResponse{
Base: &pbCommon.BaseResponse{
Code: pbCommon.StatusCode_STATUS_OK,
Message: "success",
Timestamp: time.Now().UnixMilli(),
},
Data: &pb.LikedAssetsData{
Items: pbItems,
Page: page,
PageSize: pageSize,
Total: total,
HasMore: hasMore,
},
}, nil
}
// GetMyTodayLikedAssets 获取我今日点赞的作品列表
func (s *AssetLikeService) GetMyTodayLikedAssets(ctx context.Context, req *pb.GetMyTodayLikedAssetsRequest, userID, starID int64) (*pb.GetMyTodayLikedAssetsResponse, error) {
page := req.Page
if page <= 0 {
page = 1
}
pageSize := req.PageSize
if pageSize <= 0 {
pageSize = 20
}
if pageSize > 100 {
pageSize = 100
}
items, total, err := s.socialRepo.GetMyTodayLikedAssets(userID, starID, int(page), int(pageSize))
if err != nil {
logger.Logger.Error("Failed to get my today liked assets",
zap.Error(err),
zap.Int64("user_id", userID),
zap.Int64("star_id", starID),
)
return &pb.GetMyTodayLikedAssetsResponse{
Base: &pbCommon.BaseResponse{
Code: pbCommon.StatusCode_STATUS_INTERNAL_ERROR,
Message: "Failed to get my today liked assets: " + err.Error(),
Timestamp: time.Now().UnixMilli(),
},
}, nil
}
pbItems := make([]*pb.LikedAssetItem, 0, len(items))
for _, item := range items {
pbItems = append(pbItems, &pb.LikedAssetItem{
AssetId: item.AssetID,
Name: item.Name,
CoverUrl: item.CoverURL,
LikeCount: item.LikeCount,
LikedAt: item.LikedAt,
Earnings: item.Earnings,
})
}
hasMore := int64(page)*int64(pageSize) < total
return &pb.GetMyTodayLikedAssetsResponse{
Base: &pbCommon.BaseResponse{
Code: pbCommon.StatusCode_STATUS_OK,
Message: "success",
Timestamp: time.Now().UnixMilli(),
},
Data: &pb.LikedAssetsData{
Items: pbItems,
Page: page,
PageSize: pageSize,
Total: total,
HasMore: hasMore,
},
}, nil
}
// GetMyWeekLikedAssets 获取我本周点赞的作品列表
func (s *AssetLikeService) GetMyWeekLikedAssets(ctx context.Context, req *pb.GetMyWeekLikedAssetsRequest, userID, starID int64) (*pb.GetMyWeekLikedAssetsResponse, error) {
page := req.Page
if page <= 0 {
page = 1
}
pageSize := req.PageSize
if pageSize <= 0 {
pageSize = 20
}
if pageSize > 100 {
pageSize = 100
}
items, total, err := s.socialRepo.GetMyWeekLikedAssets(userID, starID, int(page), int(pageSize))
if err != nil {
logger.Logger.Error("Failed to get my week liked assets",
zap.Error(err),
zap.Int64("user_id", userID),
zap.Int64("star_id", starID),
)
return &pb.GetMyWeekLikedAssetsResponse{
Base: &pbCommon.BaseResponse{
Code: pbCommon.StatusCode_STATUS_INTERNAL_ERROR,
Message: "Failed to get my week liked assets: " + err.Error(),
Timestamp: time.Now().UnixMilli(),
},
}, nil
}
pbItems := make([]*pb.LikedAssetItem, 0, len(items))
for _, item := range items {
pbItems = append(pbItems, &pb.LikedAssetItem{
AssetId: item.AssetID,
Name: item.Name,
CoverUrl: item.CoverURL,
LikeCount: item.LikeCount,
LikedAt: item.LikedAt,
Earnings: item.Earnings,
})
}
hasMore := int64(page)*int64(pageSize) < total
return &pb.GetMyWeekLikedAssetsResponse{
Base: &pbCommon.BaseResponse{
Code: pbCommon.StatusCode_STATUS_OK,
Message: "success",
Timestamp: time.Now().UnixMilli(),
},
Data: &pb.LikedAssetsData{
Items: pbItems,
Page: page,
PageSize: pageSize,
Total: total,
HasMore: hasMore,
},
}, nil
}
// GetUserLikedAssets 获取他人点赞的作品列表
func (s *AssetLikeService) GetUserLikedAssets(ctx context.Context, req *pb.GetUserLikedAssetsRequest, userID, starID int64) (*pb.GetUserLikedAssetsResponse, error) {
page := req.Page
if page <= 0 {
page = 1
}
pageSize := req.PageSize
if pageSize <= 0 {
pageSize = 20
}
if pageSize > 100 {
pageSize = 100
}
items, total, err := s.socialRepo.GetUserLikedAssets(userID, starID, int(page), int(pageSize))
if err != nil {
logger.Logger.Error("Failed to get user liked assets",
zap.Error(err),
zap.Int64("user_id", userID),
zap.Int64("star_id", starID),
)
return &pb.GetUserLikedAssetsResponse{
Base: &pbCommon.BaseResponse{
Code: pbCommon.StatusCode_STATUS_INTERNAL_ERROR,
Message: "Failed to get user liked assets: " + err.Error(),
Timestamp: time.Now().UnixMilli(),
},
}, nil
}
pbItems := make([]*pb.LikedAssetItem, 0, len(items))
for _, item := range items {
pbItems = append(pbItems, &pb.LikedAssetItem{
AssetId: item.AssetID,
Name: item.Name,
CoverUrl: item.CoverURL,
LikeCount: item.LikeCount,
LikedAt: item.LikedAt,
Earnings: item.Earnings,
})
}
hasMore := int64(page)*int64(pageSize) < total
return &pb.GetUserLikedAssetsResponse{
Base: &pbCommon.BaseResponse{
Code: pbCommon.StatusCode_STATUS_OK,
Message: "success",
Timestamp: time.Now().UnixMilli(),
},
Data: &pb.LikedAssetsData{
Items: pbItems,
Page: page,
PageSize: pageSize,
Total: total,
HasMore: hasMore,
},
}, nil
}