2024-11-09 16:11:00 +00:00
|
|
|
package application_v1
|
|
|
|
|
|
|
|
import (
|
|
|
|
"github.com/gin-gonic/gin"
|
|
|
|
"leafdev.top/Ecosystem/recommender/internal/base/logger"
|
|
|
|
"leafdev.top/Ecosystem/recommender/internal/base/redis"
|
|
|
|
"leafdev.top/Ecosystem/recommender/internal/handler/http/request"
|
|
|
|
"leafdev.top/Ecosystem/recommender/internal/handler/http/response"
|
|
|
|
"leafdev.top/Ecosystem/recommender/internal/service/application"
|
|
|
|
"leafdev.top/Ecosystem/recommender/internal/service/auth"
|
2024-11-09 19:49:53 +00:00
|
|
|
"leafdev.top/Ecosystem/recommender/internal/service/category"
|
2024-11-09 16:11:00 +00:00
|
|
|
"leafdev.top/Ecosystem/recommender/internal/service/post"
|
|
|
|
"leafdev.top/Ecosystem/recommender/internal/service/user"
|
|
|
|
"leafdev.top/Ecosystem/recommender/pkg/consts"
|
|
|
|
"net/http"
|
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
|
|
|
const TaskProcessing = "user_likes"
|
|
|
|
|
|
|
|
var LockTTL = time.Minute * 10
|
|
|
|
|
|
|
|
type UserController struct {
|
|
|
|
authService *auth.Service
|
|
|
|
applicationService *application.Service
|
|
|
|
userService *user.Service
|
|
|
|
postService *post.Service
|
|
|
|
logger *logger.Logger
|
|
|
|
redis *redis.Redis
|
2024-11-09 19:49:53 +00:00
|
|
|
categoryService *category.Service
|
2024-11-09 16:11:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func NewUserController(
|
|
|
|
authService *auth.Service,
|
|
|
|
applicationService *application.Service,
|
|
|
|
userService *user.Service,
|
|
|
|
postService *post.Service,
|
|
|
|
logger *logger.Logger,
|
|
|
|
redis *redis.Redis,
|
2024-11-09 19:49:53 +00:00
|
|
|
categoryService *category.Service,
|
2024-11-09 16:11:00 +00:00
|
|
|
) *UserController {
|
|
|
|
return &UserController{
|
|
|
|
authService: authService,
|
|
|
|
applicationService: applicationService,
|
|
|
|
userService: userService,
|
|
|
|
postService: postService,
|
|
|
|
logger: logger,
|
|
|
|
redis: redis,
|
2024-11-09 19:49:53 +00:00
|
|
|
categoryService: categoryService,
|
2024-11-09 16:11:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Like godoc
|
|
|
|
// @Summary Like
|
|
|
|
// @Description 将标签附加到用户名
|
|
|
|
// @Tags application_api
|
|
|
|
// @Accept json
|
|
|
|
// @Produce json
|
|
|
|
// @Security ApiKeyAuth
|
|
|
|
// @Param UserLikePost body request.UserLikePost true "UserLikePost"
|
|
|
|
// @Failure 400 {object} response.ResponseBody
|
|
|
|
// @Router /applications/v1/users/_like [post]
|
|
|
|
func (uc *UserController) Like(c *gin.Context) {
|
|
|
|
app, err := uc.authService.GetApplication(c)
|
|
|
|
if err != nil {
|
|
|
|
response.Ctx(c).Error(err).Status(http.StatusBadRequest).Send()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
var userLikePostRequest = &request.UserLikePost{}
|
|
|
|
|
|
|
|
if err := c.ShouldBindJSON(userLikePostRequest); err != nil {
|
|
|
|
response.Ctx(c).Error(err).Status(http.StatusBadRequest).Send()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
externalUser, err := uc.userService.GetOrCreateExternalUser(c, userLikePostRequest.ExternalUserId, app)
|
|
|
|
if err != nil {
|
|
|
|
response.Ctx(c).Error(err).Status(http.StatusInternalServerError).Send()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// posts
|
|
|
|
postEntity, err := uc.postService.GetPostById(c, userLikePostRequest.PostId)
|
|
|
|
if err != nil {
|
|
|
|
response.Ctx(c).Error(err).Status(http.StatusInternalServerError).Send()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if postEntity.ApplicationId != app.Id {
|
|
|
|
response.Ctx(c).Status(http.StatusNotFound).Send()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2024-11-09 19:49:53 +00:00
|
|
|
if !postEntity.Vectorized || !postEntity.Processed {
|
|
|
|
response.Ctx(c).Status(http.StatusBadRequest).Error(consts.ErrPostNotReady).Send()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2024-11-09 16:11:00 +00:00
|
|
|
// 检测是否有
|
|
|
|
var cacheKey = uc.redis.Prefix(TaskProcessing + ":" + userLikePostRequest.PostId.String())
|
|
|
|
// if exists
|
|
|
|
exists, err := uc.redis.Client.Exists(c, cacheKey).Result()
|
|
|
|
if err != nil {
|
|
|
|
response.Ctx(c).Error(err).Status(http.StatusInternalServerError).Send()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if exists > 0 {
|
|
|
|
response.Ctx(c).Status(http.StatusTooEarly).Error(consts.ErrAnotherOperationInProgress).Send()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
_, err = uc.redis.Client.Set(c, cacheKey, userLikePostRequest.ExternalUserId, LockTTL).Result()
|
|
|
|
|
|
|
|
go func(prefix string) {
|
|
|
|
err = uc.userService.LikePost(c, externalUser, app, postEntity)
|
|
|
|
if err != nil {
|
|
|
|
response.Ctx(c).Error(err).Status(http.StatusInternalServerError).Send()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
_, err := uc.redis.Client.Del(c, prefix).Result()
|
|
|
|
if err != nil {
|
|
|
|
uc.logger.Sugar.Error(err)
|
|
|
|
}
|
|
|
|
}(cacheKey)
|
|
|
|
|
|
|
|
response.Ctx(c).Status(http.StatusNoContent).Send()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// Dislike godoc
|
|
|
|
// @Summary Dislike
|
|
|
|
// @Description 从用户的标签喜好中移除内容
|
|
|
|
// @Tags application_api
|
|
|
|
// @Accept json
|
|
|
|
// @Produce json
|
|
|
|
// @Security ApiKeyAuth
|
2024-11-09 19:49:53 +00:00
|
|
|
// @Param UserDislikePost body request.UserDislikePost true "UserDislikePost"
|
2024-11-09 16:11:00 +00:00
|
|
|
// @Failure 400 {object} response.ResponseBody
|
|
|
|
// @Router /applications/v1/users/_dislike [post]
|
|
|
|
func (uc *UserController) Dislike(c *gin.Context) {
|
|
|
|
app, err := uc.authService.GetApplication(c)
|
|
|
|
if err != nil {
|
|
|
|
response.Ctx(c).Error(err).Status(http.StatusBadRequest).Send()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
var userDislikePostRequest = &request.UserDislikePost{}
|
|
|
|
|
|
|
|
if err := c.ShouldBindJSON(userDislikePostRequest); err != nil {
|
|
|
|
response.Ctx(c).Error(err).Status(http.StatusBadRequest).Send()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
externalUser, err := uc.userService.GetOrCreateExternalUser(c, userDislikePostRequest.ExternalUserId, app)
|
|
|
|
if err != nil {
|
|
|
|
response.Ctx(c).Error(err).Status(http.StatusInternalServerError).Send()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// posts
|
|
|
|
postEntity, err := uc.postService.GetPostById(c, userDislikePostRequest.PostId)
|
|
|
|
if err != nil {
|
|
|
|
response.Ctx(c).Error(err).Status(http.StatusInternalServerError).Send()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if postEntity.ApplicationId != app.Id {
|
|
|
|
response.Ctx(c).Status(http.StatusNotFound).Send()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2024-11-09 19:49:53 +00:00
|
|
|
if !postEntity.Vectorized || !postEntity.Processed {
|
|
|
|
response.Ctx(c).Status(http.StatusBadRequest).Error(consts.ErrPostNotReady).Send()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2024-11-09 16:11:00 +00:00
|
|
|
// 检测是否有
|
|
|
|
var cacheKey = uc.redis.Prefix(TaskProcessing + ":" + userDislikePostRequest.PostId.String())
|
|
|
|
exists, err := uc.redis.Client.Exists(c, cacheKey).Result()
|
|
|
|
if err != nil {
|
|
|
|
response.Ctx(c).Error(err).Status(http.StatusInternalServerError).Send()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if exists > 0 {
|
|
|
|
response.Ctx(c).Status(http.StatusTooEarly).Error(consts.ErrAnotherOperationInProgress).Send()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
_, err = uc.redis.Client.Set(c, cacheKey, userDislikePostRequest.ExternalUserId, LockTTL).Result()
|
|
|
|
|
|
|
|
go func(prefix string) {
|
|
|
|
err = uc.userService.DislikePost(c, externalUser, app, postEntity)
|
|
|
|
if err != nil {
|
|
|
|
response.Ctx(c).Error(err).Status(http.StatusInternalServerError).Send()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
_, err := uc.redis.Client.Del(c, prefix).Result()
|
|
|
|
if err != nil {
|
|
|
|
uc.logger.Sugar.Error(err)
|
|
|
|
}
|
|
|
|
}(cacheKey)
|
|
|
|
|
|
|
|
response.Ctx(c).Status(http.StatusNoContent).Send()
|
|
|
|
return
|
|
|
|
}
|
2024-11-09 19:49:53 +00:00
|
|
|
|
|
|
|
// Suggest godoc
|
|
|
|
// @Summary Suggest
|
|
|
|
// @Description 推荐资源
|
|
|
|
// @Tags application_api
|
|
|
|
// @Accept json
|
|
|
|
// @Produce json
|
|
|
|
// @Security ApiKeyAuth
|
|
|
|
// @Param UserSuggestsRequest body request.UserSuggestsRequest true "UserSuggestsRequest"
|
|
|
|
// @Success 200 {object} response.ResponseBody{data=[]entity.Post}
|
|
|
|
// @Failure 400 {object} response.ResponseBody
|
|
|
|
// @Router /applications/v1/users/_suggest [post]
|
|
|
|
func (uc *UserController) Suggest(c *gin.Context) {
|
|
|
|
app, err := uc.authService.GetApplication(c)
|
|
|
|
if err != nil {
|
|
|
|
response.Ctx(c).Error(err).Status(http.StatusBadRequest).Send()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
var userSuggestsRequest = &request.UserSuggestsRequest{}
|
|
|
|
|
|
|
|
if err := c.ShouldBindJSON(userSuggestsRequest); err != nil {
|
|
|
|
response.Ctx(c).Error(err).Status(http.StatusBadRequest).Send()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
exists, err := uc.userService.UserExists(c, userSuggestsRequest.ExternalUserId, app)
|
|
|
|
if err != nil {
|
|
|
|
response.Ctx(c).Error(err).Status(http.StatusInternalServerError).Send()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if !exists {
|
|
|
|
response.Ctx(c).Status(http.StatusNotFound).Send()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
externalUserEntity, err := uc.userService.GetExternalUser(c, userSuggestsRequest.ExternalUserId, app)
|
|
|
|
if err != nil {
|
|
|
|
response.Ctx(c).Error(err).Status(http.StatusInternalServerError).Send()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// category
|
|
|
|
exists, err = uc.categoryService.CategoryExists(c, userSuggestsRequest.CategoryId, app)
|
|
|
|
if err != nil {
|
|
|
|
response.Ctx(c).Error(err).Status(http.StatusInternalServerError).Send()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if !exists {
|
|
|
|
response.Ctx(c).Status(http.StatusNotFound).Error(consts.ErrCategoryNotExists).Send()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
categoryEntity, err := uc.categoryService.GetCategoryById(c, userSuggestsRequest.CategoryId)
|
|
|
|
if err != nil {
|
|
|
|
response.Ctx(c).Error(err).Status(http.StatusInternalServerError).Send()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// 建议文章
|
|
|
|
err = uc.userService.SummaryUser(c, externalUserEntity, app)
|
|
|
|
if err != nil {
|
|
|
|
response.Ctx(c).Error(err).Status(http.StatusInternalServerError).Error(err).Send()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// 建议文章
|
|
|
|
posts, err := uc.userService.SuggestPosts(c, externalUserEntity, categoryEntity)
|
|
|
|
if err != nil {
|
|
|
|
response.Ctx(c).Error(err).Status(http.StatusInternalServerError).Send()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
response.Ctx(c).Data(posts).Send()
|
|
|
|
}
|