mirror of https://github.com/rocboss/paopao-ce
commit
6bc22bf956
@ -0,0 +1,16 @@
|
|||||||
|
// Copyright 2023 ROC. All rights reserved.
|
||||||
|
// Use of this source code is governed by a MIT style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package chain
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/rocboss/paopao-ce/pkg/xerror"
|
||||||
|
)
|
||||||
|
|
||||||
|
// nolint
|
||||||
|
var (
|
||||||
|
_errUserHasBeenBanned = xerror.NewError(20006, "该账户已被封停")
|
||||||
|
_errAccountNoPhoneBind = xerror.NewError(20013, "拒绝操作: 账户未绑定手机号")
|
||||||
|
_errNoAdminPermission = xerror.NewError(20022, "无管理权限")
|
||||||
|
)
|
@ -1,13 +0,0 @@
|
|||||||
// Copyright 2022 ROC. All rights reserved.
|
|
||||||
// Use of this source code is governed by a MIT style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package broker
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/rocboss/paopao-ce/internal/core/cs"
|
|
||||||
)
|
|
||||||
|
|
||||||
func CreateAttachment(obj *cs.Attachment) (int64, error) {
|
|
||||||
return ds.CreateAttachment(obj)
|
|
||||||
}
|
|
@ -1,68 +0,0 @@
|
|||||||
// Copyright 2022 ROC. All rights reserved.
|
|
||||||
// Use of this source code is governed by a MIT style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package broker
|
|
||||||
|
|
||||||
import (
|
|
||||||
"math/rand"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
var defaultAvatars = []string{
|
|
||||||
"https://assets.paopao.info/public/avatar/default/zoe.png",
|
|
||||||
"https://assets.paopao.info/public/avatar/default/william.png",
|
|
||||||
"https://assets.paopao.info/public/avatar/default/walter.png",
|
|
||||||
"https://assets.paopao.info/public/avatar/default/thomas.png",
|
|
||||||
"https://assets.paopao.info/public/avatar/default/taylor.png",
|
|
||||||
"https://assets.paopao.info/public/avatar/default/sophia.png",
|
|
||||||
"https://assets.paopao.info/public/avatar/default/sam.png",
|
|
||||||
"https://assets.paopao.info/public/avatar/default/ryan.png",
|
|
||||||
"https://assets.paopao.info/public/avatar/default/ruby.png",
|
|
||||||
"https://assets.paopao.info/public/avatar/default/quinn.png",
|
|
||||||
"https://assets.paopao.info/public/avatar/default/paul.png",
|
|
||||||
"https://assets.paopao.info/public/avatar/default/owen.png",
|
|
||||||
"https://assets.paopao.info/public/avatar/default/olivia.png",
|
|
||||||
"https://assets.paopao.info/public/avatar/default/norman.png",
|
|
||||||
"https://assets.paopao.info/public/avatar/default/nora.png",
|
|
||||||
"https://assets.paopao.info/public/avatar/default/natalie.png",
|
|
||||||
"https://assets.paopao.info/public/avatar/default/naomi.png",
|
|
||||||
"https://assets.paopao.info/public/avatar/default/miley.png",
|
|
||||||
"https://assets.paopao.info/public/avatar/default/mike.png",
|
|
||||||
"https://assets.paopao.info/public/avatar/default/lucas.png",
|
|
||||||
"https://assets.paopao.info/public/avatar/default/kylie.png",
|
|
||||||
"https://assets.paopao.info/public/avatar/default/julia.png",
|
|
||||||
"https://assets.paopao.info/public/avatar/default/joshua.png",
|
|
||||||
"https://assets.paopao.info/public/avatar/default/john.png",
|
|
||||||
"https://assets.paopao.info/public/avatar/default/jane.png",
|
|
||||||
"https://assets.paopao.info/public/avatar/default/jackson.png",
|
|
||||||
"https://assets.paopao.info/public/avatar/default/ivy.png",
|
|
||||||
"https://assets.paopao.info/public/avatar/default/isaac.png",
|
|
||||||
"https://assets.paopao.info/public/avatar/default/henry.png",
|
|
||||||
"https://assets.paopao.info/public/avatar/default/harry.png",
|
|
||||||
"https://assets.paopao.info/public/avatar/default/harold.png",
|
|
||||||
"https://assets.paopao.info/public/avatar/default/hanna.png",
|
|
||||||
"https://assets.paopao.info/public/avatar/default/grace.png",
|
|
||||||
"https://assets.paopao.info/public/avatar/default/george.png",
|
|
||||||
"https://assets.paopao.info/public/avatar/default/freddy.png",
|
|
||||||
"https://assets.paopao.info/public/avatar/default/frank.png",
|
|
||||||
"https://assets.paopao.info/public/avatar/default/finn.png",
|
|
||||||
"https://assets.paopao.info/public/avatar/default/emma.png",
|
|
||||||
"https://assets.paopao.info/public/avatar/default/emily.png",
|
|
||||||
"https://assets.paopao.info/public/avatar/default/edward.png",
|
|
||||||
"https://assets.paopao.info/public/avatar/default/clara.png",
|
|
||||||
"https://assets.paopao.info/public/avatar/default/claire.png",
|
|
||||||
"https://assets.paopao.info/public/avatar/default/chloe.png",
|
|
||||||
"https://assets.paopao.info/public/avatar/default/audrey.png",
|
|
||||||
"https://assets.paopao.info/public/avatar/default/arthur.png",
|
|
||||||
"https://assets.paopao.info/public/avatar/default/anna.png",
|
|
||||||
"https://assets.paopao.info/public/avatar/default/andy.png",
|
|
||||||
"https://assets.paopao.info/public/avatar/default/alfred.png",
|
|
||||||
"https://assets.paopao.info/public/avatar/default/alexa.png",
|
|
||||||
"https://assets.paopao.info/public/avatar/default/abigail.png",
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetRandomAvatar() string {
|
|
||||||
rand.Seed(time.Now().UnixMicro())
|
|
||||||
return defaultAvatars[rand.Intn(len(defaultAvatars))]
|
|
||||||
}
|
|
@ -1,52 +0,0 @@
|
|||||||
// Copyright 2022 ROC. All rights reserved.
|
|
||||||
// Use of this source code is governed by a MIT style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package broker
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/alimy/cfg"
|
|
||||||
"github.com/redis/go-redis/v9"
|
|
||||||
"github.com/rocboss/paopao-ce/internal/conf"
|
|
||||||
"github.com/rocboss/paopao-ce/internal/core"
|
|
||||||
"github.com/rocboss/paopao-ce/internal/dao"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
ds core.DataService
|
|
||||||
ts core.TweetSearchService
|
|
||||||
oss core.ObjectStorageService
|
|
||||||
redisClient *redis.Client
|
|
||||||
DisablePhoneVerify bool
|
|
||||||
)
|
|
||||||
|
|
||||||
func Initialize() {
|
|
||||||
ds = dao.DataService()
|
|
||||||
ts = dao.TweetSearchService()
|
|
||||||
oss = dao.ObjectStorageService()
|
|
||||||
redisClient = conf.MustRedis()
|
|
||||||
DisablePhoneVerify = !cfg.If("Sms")
|
|
||||||
}
|
|
||||||
|
|
||||||
// persistMediaContents 获取媒体内容并持久化
|
|
||||||
func persistMediaContents(contents []*PostContentItem) (items []string, err error) {
|
|
||||||
items = make([]string, 0, len(contents))
|
|
||||||
for _, item := range contents {
|
|
||||||
switch item.Type {
|
|
||||||
case core.ContentTypeImage,
|
|
||||||
core.ContentTypeVideo,
|
|
||||||
core.ContentTypeAudio,
|
|
||||||
core.ContentTypeAttachment,
|
|
||||||
core.ContentTypeChargeAttachment:
|
|
||||||
items = append(items, item.Content)
|
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if err = oss.PersistObject(oss.ObjectKey(item.Content)); err != nil {
|
|
||||||
logrus.Errorf("service.persistMediaContents failed: %s", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
@ -1,348 +0,0 @@
|
|||||||
// Copyright 2022 ROC. All rights reserved.
|
|
||||||
// Use of this source code is governed by a MIT style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package broker
|
|
||||||
|
|
||||||
import (
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/rocboss/paopao-ce/internal/core"
|
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"github.com/rocboss/paopao-ce/internal/conf"
|
|
||||||
"github.com/rocboss/paopao-ce/pkg/errcode"
|
|
||||||
"github.com/rocboss/paopao-ce/pkg/utils"
|
|
||||||
)
|
|
||||||
|
|
||||||
type CommentCreationReq struct {
|
|
||||||
PostID int64 `json:"post_id" binding:"required"`
|
|
||||||
Contents []*PostContentItem `json:"contents" binding:"required"`
|
|
||||||
Users []string `json:"users" binding:"required"`
|
|
||||||
}
|
|
||||||
type CommentReplyCreationReq struct {
|
|
||||||
CommentID int64 `json:"comment_id" binding:"required"`
|
|
||||||
Content string `json:"content" binding:"required"`
|
|
||||||
AtUserID int64 `json:"at_user_id"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type CommentDelReq struct {
|
|
||||||
ID int64 `json:"id" binding:"required"`
|
|
||||||
}
|
|
||||||
type ReplyDelReq struct {
|
|
||||||
ID int64 `json:"id" binding:"required"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetPostComments(postID int64, sort string, offset, limit int) ([]*core.CommentFormated, int64, error) {
|
|
||||||
conditions := &core.ConditionsT{
|
|
||||||
"post_id": postID,
|
|
||||||
"ORDER": sort,
|
|
||||||
}
|
|
||||||
comments, err := ds.GetComments(conditions, offset, limit)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return nil, 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
userIDs := []int64{}
|
|
||||||
commentIDs := []int64{}
|
|
||||||
for _, comment := range comments {
|
|
||||||
userIDs = append(userIDs, comment.UserID)
|
|
||||||
commentIDs = append(commentIDs, comment.ID)
|
|
||||||
}
|
|
||||||
|
|
||||||
users, err := ds.GetUsersByIDs(userIDs)
|
|
||||||
if err != nil {
|
|
||||||
return nil, 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
contents, err := ds.GetCommentContentsByIDs(commentIDs)
|
|
||||||
if err != nil {
|
|
||||||
return nil, 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
replies, err := ds.GetCommentRepliesByID(commentIDs)
|
|
||||||
if err != nil {
|
|
||||||
return nil, 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
commentsFormated := []*core.CommentFormated{}
|
|
||||||
for _, comment := range comments {
|
|
||||||
commentFormated := comment.Format()
|
|
||||||
for _, content := range contents {
|
|
||||||
if content.CommentID == comment.ID {
|
|
||||||
commentFormated.Contents = append(commentFormated.Contents, content)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for _, reply := range replies {
|
|
||||||
if reply.CommentID == commentFormated.ID {
|
|
||||||
commentFormated.Replies = append(commentFormated.Replies, reply)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for _, user := range users {
|
|
||||||
if user.ID == comment.UserID {
|
|
||||||
commentFormated.User = user.Format()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
commentsFormated = append(commentsFormated, commentFormated)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取总量
|
|
||||||
totalRows, _ := ds.GetCommentCount(conditions)
|
|
||||||
|
|
||||||
return commentsFormated, totalRows, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func CreatePostComment(ctx *gin.Context, userID int64, param CommentCreationReq) (comment *core.Comment, err error) {
|
|
||||||
var mediaContents []string
|
|
||||||
|
|
||||||
defer func() {
|
|
||||||
if err != nil {
|
|
||||||
deleteOssObjects(mediaContents)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
if mediaContents, err = persistMediaContents(param.Contents); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 加载Post
|
|
||||||
post, err := ds.GetPostByID(param.PostID)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if post.CommentCount >= conf.AppSetting.MaxCommentCount {
|
|
||||||
return nil, errcode.MaxCommentCount
|
|
||||||
}
|
|
||||||
ip := ctx.ClientIP()
|
|
||||||
comment = &core.Comment{
|
|
||||||
PostID: post.ID,
|
|
||||||
UserID: userID,
|
|
||||||
IP: ip,
|
|
||||||
IPLoc: utils.GetIPLoc(ip),
|
|
||||||
}
|
|
||||||
comment, err = ds.CreateComment(comment)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, item := range param.Contents {
|
|
||||||
// 检查附件是否是本站资源
|
|
||||||
if item.Type == core.ContentTypeImage || item.Type == core.ContentTypeVideo || item.Type == core.ContentTypeAttachment {
|
|
||||||
if err := ds.CheckAttachment(item.Content); err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
postContent := &core.CommentContent{
|
|
||||||
CommentID: comment.ID,
|
|
||||||
UserID: userID,
|
|
||||||
Content: item.Content,
|
|
||||||
Type: item.Type,
|
|
||||||
Sort: item.Sort,
|
|
||||||
}
|
|
||||||
ds.CreateCommentContent(postContent)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 更新Post回复数
|
|
||||||
post.CommentCount++
|
|
||||||
post.LatestRepliedOn = time.Now().Unix()
|
|
||||||
ds.UpdatePost(post)
|
|
||||||
|
|
||||||
// 更新索引
|
|
||||||
PushPostToSearch(post)
|
|
||||||
|
|
||||||
// 创建用户消息提醒
|
|
||||||
postMaster, err := ds.GetUserByID(post.UserID)
|
|
||||||
if err == nil && postMaster.ID != userID {
|
|
||||||
go ds.CreateMessage(&core.Message{
|
|
||||||
SenderUserID: userID,
|
|
||||||
ReceiverUserID: postMaster.ID,
|
|
||||||
Type: core.MsgtypeComment,
|
|
||||||
Brief: "在泡泡中评论了你",
|
|
||||||
PostID: post.ID,
|
|
||||||
CommentID: comment.ID,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
for _, u := range param.Users {
|
|
||||||
user, err := ds.GetUserByUsername(u)
|
|
||||||
if err != nil || user.ID == userID || user.ID == postMaster.ID {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// 创建消息提醒
|
|
||||||
go ds.CreateMessage(&core.Message{
|
|
||||||
SenderUserID: userID,
|
|
||||||
ReceiverUserID: user.ID,
|
|
||||||
Type: core.MsgtypeComment,
|
|
||||||
Brief: "在泡泡评论中@了你",
|
|
||||||
PostID: post.ID,
|
|
||||||
CommentID: comment.ID,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return comment, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetPostComment(id int64) (*core.Comment, error) {
|
|
||||||
return ds.GetCommentByID(id)
|
|
||||||
}
|
|
||||||
|
|
||||||
func DeletePostComment(comment *core.Comment) error {
|
|
||||||
// 加载post
|
|
||||||
post, err := ds.GetPostByID(comment.PostID)
|
|
||||||
if err == nil {
|
|
||||||
// 更新post回复数
|
|
||||||
post.CommentCount--
|
|
||||||
ds.UpdatePost(post)
|
|
||||||
}
|
|
||||||
|
|
||||||
return ds.DeleteComment(comment)
|
|
||||||
}
|
|
||||||
|
|
||||||
func createPostPreHandler(commentID int64, userID, atUserID int64) (*core.Post, *core.Comment, int64,
|
|
||||||
error) {
|
|
||||||
// 加载Comment
|
|
||||||
comment, err := ds.GetCommentByID(commentID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, atUserID, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// 加载comment的post
|
|
||||||
post, err := ds.GetPostByID(comment.PostID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, atUserID, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if post.CommentCount >= conf.AppSetting.MaxCommentCount {
|
|
||||||
return nil, nil, atUserID, errcode.MaxCommentCount
|
|
||||||
}
|
|
||||||
|
|
||||||
if userID == atUserID {
|
|
||||||
atUserID = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
if atUserID > 0 {
|
|
||||||
// 检测目前用户是否存在
|
|
||||||
users, _ := ds.GetUsersByIDs([]int64{atUserID})
|
|
||||||
if len(users) == 0 {
|
|
||||||
atUserID = 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return post, comment, atUserID, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func CreatePostCommentReply(ctx *gin.Context, commentID int64, content string, userID, atUserID int64) (*core.CommentReply, error) {
|
|
||||||
var (
|
|
||||||
post *core.Post
|
|
||||||
comment *core.Comment
|
|
||||||
err error
|
|
||||||
)
|
|
||||||
if post, comment, atUserID, err = createPostPreHandler(commentID, userID, atUserID); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// 创建评论
|
|
||||||
ip := ctx.ClientIP()
|
|
||||||
reply := &core.CommentReply{
|
|
||||||
CommentID: commentID,
|
|
||||||
UserID: userID,
|
|
||||||
Content: content,
|
|
||||||
AtUserID: atUserID,
|
|
||||||
IP: ip,
|
|
||||||
IPLoc: utils.GetIPLoc(ip),
|
|
||||||
}
|
|
||||||
|
|
||||||
reply, err = ds.CreateCommentReply(reply)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// 更新Post回复数
|
|
||||||
post.CommentCount++
|
|
||||||
post.LatestRepliedOn = time.Now().Unix()
|
|
||||||
ds.UpdatePost(post)
|
|
||||||
|
|
||||||
// 更新索引
|
|
||||||
PushPostToSearch(post)
|
|
||||||
|
|
||||||
// 创建用户消息提醒
|
|
||||||
commentMaster, err := ds.GetUserByID(comment.UserID)
|
|
||||||
if err == nil && commentMaster.ID != userID {
|
|
||||||
go ds.CreateMessage(&core.Message{
|
|
||||||
SenderUserID: userID,
|
|
||||||
ReceiverUserID: commentMaster.ID,
|
|
||||||
Type: core.MsgTypeReply,
|
|
||||||
Brief: "在泡泡评论下回复了你",
|
|
||||||
PostID: post.ID,
|
|
||||||
CommentID: comment.ID,
|
|
||||||
ReplyID: reply.ID,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
postMaster, err := ds.GetUserByID(post.UserID)
|
|
||||||
if err == nil && postMaster.ID != userID && commentMaster.ID != postMaster.ID {
|
|
||||||
go ds.CreateMessage(&core.Message{
|
|
||||||
SenderUserID: userID,
|
|
||||||
ReceiverUserID: postMaster.ID,
|
|
||||||
Type: core.MsgTypeReply,
|
|
||||||
Brief: "在泡泡评论下发布了新回复",
|
|
||||||
PostID: post.ID,
|
|
||||||
CommentID: comment.ID,
|
|
||||||
ReplyID: reply.ID,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
if atUserID > 0 {
|
|
||||||
user, err := ds.GetUserByID(atUserID)
|
|
||||||
if err == nil && user.ID != userID && commentMaster.ID != user.ID && postMaster.ID != user.ID {
|
|
||||||
// 创建消息提醒
|
|
||||||
go ds.CreateMessage(&core.Message{
|
|
||||||
SenderUserID: userID,
|
|
||||||
ReceiverUserID: user.ID,
|
|
||||||
Type: core.MsgTypeReply,
|
|
||||||
Brief: "在泡泡评论的回复中@了你",
|
|
||||||
PostID: post.ID,
|
|
||||||
CommentID: comment.ID,
|
|
||||||
ReplyID: reply.ID,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return reply, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetPostCommentReply(id int64) (*core.CommentReply, error) {
|
|
||||||
return ds.GetCommentReplyByID(id)
|
|
||||||
}
|
|
||||||
|
|
||||||
func DeletePostCommentReply(reply *core.CommentReply) error {
|
|
||||||
err := ds.DeleteCommentReply(reply)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// 加载Comment
|
|
||||||
comment, err := ds.GetCommentByID(reply.CommentID)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// 加载comment的post
|
|
||||||
post, err := ds.GetPostByID(comment.PostID)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// 更新Post回复数
|
|
||||||
post.CommentCount--
|
|
||||||
post.LatestRepliedOn = time.Now().Unix()
|
|
||||||
ds.UpdatePost(post)
|
|
||||||
|
|
||||||
// 更新索引
|
|
||||||
PushPostToSearch(post)
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
@ -1,39 +0,0 @@
|
|||||||
// Copyright 2022 ROC. All rights reserved.
|
|
||||||
// Use of this source code is governed by a MIT style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package broker
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"sort"
|
|
||||||
|
|
||||||
"github.com/rocboss/paopao-ce/internal/conf"
|
|
||||||
"github.com/rocboss/paopao-ce/pkg/utils"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
)
|
|
||||||
|
|
||||||
func GetParamSign(param map[string]any, secretKey string) string {
|
|
||||||
signRaw := ""
|
|
||||||
|
|
||||||
rawStrs := []string{}
|
|
||||||
for k, v := range param {
|
|
||||||
if k != "sign" {
|
|
||||||
rawStrs = append(rawStrs, k+"="+fmt.Sprintf("%v", v))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sort.Strings(rawStrs)
|
|
||||||
for _, v := range rawStrs {
|
|
||||||
signRaw += v
|
|
||||||
}
|
|
||||||
|
|
||||||
if conf.ServerSetting.RunMode == "debug" {
|
|
||||||
logrus.Info(map[string]string{
|
|
||||||
"signRaw": signRaw,
|
|
||||||
"sysSign": utils.EncodeMD5(signRaw + secretKey),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return utils.EncodeMD5(signRaw + secretKey)
|
|
||||||
}
|
|
@ -1,487 +0,0 @@
|
|||||||
// Copyright 2022 ROC. All rights reserved.
|
|
||||||
// Use of this source code is governed by a MIT style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package broker
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"regexp"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
"unicode/utf8"
|
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"github.com/gofrs/uuid"
|
|
||||||
"github.com/rocboss/paopao-ce/internal/core"
|
|
||||||
"github.com/rocboss/paopao-ce/pkg/convert"
|
|
||||||
"github.com/rocboss/paopao-ce/pkg/errcode"
|
|
||||||
"github.com/rocboss/paopao-ce/pkg/utils"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
)
|
|
||||||
|
|
||||||
const _MaxCaptchaTimes = 2
|
|
||||||
|
|
||||||
type PhoneCaptchaReq struct {
|
|
||||||
Phone string `json:"phone" form:"phone" binding:"required"`
|
|
||||||
ImgCaptcha string `json:"img_captcha" form:"img_captcha" binding:"required"`
|
|
||||||
ImgCaptchaID string `json:"img_captcha_id" form:"img_captcha_id" binding:"required"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type UserPhoneBindReq struct {
|
|
||||||
Phone string `json:"phone" form:"phone" binding:"required"`
|
|
||||||
Captcha string `json:"captcha" form:"captcha" binding:"required"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type AuthRequest struct {
|
|
||||||
Username string `json:"username" form:"username" binding:"required"`
|
|
||||||
Password string `json:"password" form:"password" binding:"required"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type RegisterRequest struct {
|
|
||||||
Username string `json:"username" form:"username" binding:"required"`
|
|
||||||
Password string `json:"password" form:"password" binding:"required"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type ChangePasswordReq struct {
|
|
||||||
Password string `json:"password" form:"password" binding:"required"`
|
|
||||||
OldPassword string `json:"old_password" form:"old_password" binding:"required"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type ChangeNicknameReq struct {
|
|
||||||
Nickname string `json:"nickname" form:"nickname" binding:"required"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type ChangeAvatarReq struct {
|
|
||||||
Avatar string `json:"avatar" form:"avatar" binding:"required"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type ChangeUserStatusReq struct {
|
|
||||||
ID int64 `json:"id" form:"id" binding:"required"`
|
|
||||||
Status int `json:"status" form:"status" binding:"required"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type RequestingFriendReq struct {
|
|
||||||
UserId int64 `json:"user_id" binding:"required"`
|
|
||||||
Greetings string `json:"greetings" binding:"required"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type AddFriendReq struct {
|
|
||||||
UserId int64 `json:"user_id" binding:"required"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type RejectFriendReq struct {
|
|
||||||
UserId int64 `json:"user_id" binding:"required"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type DeleteFriendReq struct {
|
|
||||||
UserId int64 `json:"user_id"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type UserProfileResp struct {
|
|
||||||
ID int64 `json:"id"`
|
|
||||||
Nickname string `json:"nickname"`
|
|
||||||
Username string `json:"username"`
|
|
||||||
Status int `json:"status"`
|
|
||||||
Avatar string `json:"avatar"`
|
|
||||||
IsAdmin bool `json:"is_admin"`
|
|
||||||
IsFriend bool `json:"is_friend"`
|
|
||||||
}
|
|
||||||
|
|
||||||
const (
|
|
||||||
_LoginErrKey = "PaoPaoUserLoginErr"
|
|
||||||
_MaxLoginErrTimes = 10
|
|
||||||
)
|
|
||||||
|
|
||||||
// DoLogin 用户认证
|
|
||||||
func DoLogin(ctx *gin.Context, param *AuthRequest) (*core.User, error) {
|
|
||||||
user, err := ds.GetUserByUsername(param.Username)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errcode.UnauthorizedAuthNotExist
|
|
||||||
}
|
|
||||||
|
|
||||||
if user.Model != nil && user.ID > 0 {
|
|
||||||
if errTimes, err := redisClient.Get(ctx, fmt.Sprintf("%s:%d", _LoginErrKey, user.ID)).Result(); err == nil {
|
|
||||||
if convert.StrTo(errTimes).MustInt() >= _MaxLoginErrTimes {
|
|
||||||
return nil, errcode.TooManyLoginError
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 对比密码是否正确
|
|
||||||
if ValidPassword(user.Password, param.Password, user.Salt) {
|
|
||||||
|
|
||||||
if user.Status == core.UserStatusClosed {
|
|
||||||
return nil, errcode.UserHasBeenBanned
|
|
||||||
}
|
|
||||||
|
|
||||||
// 清空登录计数
|
|
||||||
redisClient.Del(ctx, fmt.Sprintf("%s:%d", _LoginErrKey, user.ID))
|
|
||||||
return user, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// 登录错误计数
|
|
||||||
_, err = redisClient.Incr(ctx, fmt.Sprintf("%s:%d", _LoginErrKey, user.ID)).Result()
|
|
||||||
if err == nil {
|
|
||||||
redisClient.Expire(ctx, fmt.Sprintf("%s:%d", _LoginErrKey, user.ID), time.Hour).Result()
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, errcode.UnauthorizedAuthFailed
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, errcode.UnauthorizedAuthNotExist
|
|
||||||
}
|
|
||||||
|
|
||||||
// ValidPassword 检查密码是否一致
|
|
||||||
func ValidPassword(dbPassword, password, salt string) bool {
|
|
||||||
return strings.Compare(dbPassword, utils.EncodeMD5(utils.EncodeMD5(password)+salt)) == 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// CheckStatus 检测用户权限
|
|
||||||
func CheckStatus(user *core.User) bool {
|
|
||||||
return user.Status == core.UserStatusNormal
|
|
||||||
}
|
|
||||||
|
|
||||||
// ValidUsername 验证用户
|
|
||||||
func ValidUsername(username string) error {
|
|
||||||
// 检测用户是否合规
|
|
||||||
if utf8.RuneCountInString(username) < 3 || utf8.RuneCountInString(username) > 12 {
|
|
||||||
return errcode.UsernameLengthLimit
|
|
||||||
}
|
|
||||||
|
|
||||||
if !regexp.MustCompile(`^[a-zA-Z0-9]+$`).MatchString(username) {
|
|
||||||
return errcode.UsernameCharLimit
|
|
||||||
}
|
|
||||||
|
|
||||||
// 重复检查
|
|
||||||
user, _ := ds.GetUserByUsername(username)
|
|
||||||
|
|
||||||
if user.Model != nil && user.ID > 0 {
|
|
||||||
return errcode.UsernameHasExisted
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// CheckPassword 密码检查
|
|
||||||
func CheckPassword(password string) error {
|
|
||||||
// 检测用户是否合规
|
|
||||||
if utf8.RuneCountInString(password) < 6 || utf8.RuneCountInString(password) > 16 {
|
|
||||||
return errcode.PasswordLengthLimit
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// CheckPhoneCaptcha 验证手机验证码
|
|
||||||
func CheckPhoneCaptcha(phone, captcha string) *errcode.Error {
|
|
||||||
// 如果禁止phone verify 则允许通过任意验证码
|
|
||||||
if DisablePhoneVerify {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
c, err := ds.GetLatestPhoneCaptcha(phone)
|
|
||||||
if err != nil {
|
|
||||||
return errcode.ErrorPhoneCaptcha
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.Captcha != captcha {
|
|
||||||
return errcode.ErrorPhoneCaptcha
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.ExpiredOn < time.Now().Unix() {
|
|
||||||
return errcode.ErrorPhoneCaptcha
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.UseTimes >= _MaxCaptchaTimes {
|
|
||||||
return errcode.MaxPhoneCaptchaUseTimes
|
|
||||||
}
|
|
||||||
|
|
||||||
// 更新检测次数
|
|
||||||
ds.UsePhoneCaptcha(c)
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// CheckPhoneExist 检测手机号是否存在
|
|
||||||
func CheckPhoneExist(uid int64, phone string) bool {
|
|
||||||
u, err := ds.GetUserByPhone(phone)
|
|
||||||
if err != nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
if u.Model == nil || u.ID == 0 {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
if u.ID == uid {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// EncryptPasswordAndSalt 密码加密&生成salt
|
|
||||||
func EncryptPasswordAndSalt(password string) (string, string) {
|
|
||||||
salt := uuid.Must(uuid.NewV4()).String()[:8]
|
|
||||||
password = utils.EncodeMD5(utils.EncodeMD5(password) + salt)
|
|
||||||
|
|
||||||
return password, salt
|
|
||||||
}
|
|
||||||
|
|
||||||
// Register 用户注册
|
|
||||||
func Register(username, password string) (*core.User, error) {
|
|
||||||
password, salt := EncryptPasswordAndSalt(password)
|
|
||||||
|
|
||||||
user := &core.User{
|
|
||||||
Nickname: username,
|
|
||||||
Username: username,
|
|
||||||
Password: password,
|
|
||||||
Avatar: GetRandomAvatar(),
|
|
||||||
Salt: salt,
|
|
||||||
Status: core.UserStatusNormal,
|
|
||||||
}
|
|
||||||
|
|
||||||
user, err := ds.CreateUser(user)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return user, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func RequestingFriend(user *core.User, param *RequestingFriendReq) error {
|
|
||||||
if _, err := ds.GetUserByID(param.UserId); err != nil {
|
|
||||||
return errcode.NotExistFriendId
|
|
||||||
}
|
|
||||||
return ds.RequestingFriend(user.ID, param.UserId, param.Greetings)
|
|
||||||
}
|
|
||||||
|
|
||||||
func AddFriend(user *core.User, param *AddFriendReq) error {
|
|
||||||
if _, err := ds.GetUserByID(param.UserId); err != nil {
|
|
||||||
return errcode.NotExistFriendId
|
|
||||||
}
|
|
||||||
return ds.AddFriend(user.ID, param.UserId)
|
|
||||||
}
|
|
||||||
|
|
||||||
func RejectFriend(user *core.User, param *RejectFriendReq) error {
|
|
||||||
if _, err := ds.GetUserByID(param.UserId); err != nil {
|
|
||||||
return errcode.NotExistFriendId
|
|
||||||
}
|
|
||||||
return ds.RejectFriend(user.ID, param.UserId)
|
|
||||||
}
|
|
||||||
|
|
||||||
func DeleteFriend(user *core.User, param *DeleteFriendReq) error {
|
|
||||||
if _, err := ds.GetUserByID(param.UserId); err != nil {
|
|
||||||
return errcode.NotExistFriendId
|
|
||||||
}
|
|
||||||
return ds.DeleteFriend(user.ID, param.UserId)
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetContacts(user *core.User, offset int, limit int) (*core.ContactList, error) {
|
|
||||||
return ds.GetContacts(user.ID, offset, limit)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetUserInfo 获取用户信息
|
|
||||||
func GetUserInfo(param *AuthRequest) (*core.User, error) {
|
|
||||||
user, err := ds.GetUserByUsername(param.Username)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if user.Model != nil && user.ID > 0 {
|
|
||||||
return user, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, errcode.UnauthorizedAuthNotExist
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetUserByID(id int64) (*core.User, error) {
|
|
||||||
user, err := ds.GetUserByID(id)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if user.Model != nil && user.ID > 0 {
|
|
||||||
return user, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, errcode.NoExistUsername
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetUserByUsername(user *core.User, username string) (*UserProfileResp, error) {
|
|
||||||
other, err := ds.GetUserByUsername(username)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var resp *UserProfileResp
|
|
||||||
if other.Model != nil && other.ID > 0 {
|
|
||||||
resp = &UserProfileResp{
|
|
||||||
ID: other.ID,
|
|
||||||
Nickname: other.Nickname,
|
|
||||||
Username: other.Username,
|
|
||||||
Status: other.Status,
|
|
||||||
Avatar: other.Avatar,
|
|
||||||
IsAdmin: other.IsAdmin,
|
|
||||||
IsFriend: !(user == nil || user.ID == other.ID),
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return nil, errcode.NoExistUsername
|
|
||||||
}
|
|
||||||
|
|
||||||
if user != nil && user.ID != other.ID {
|
|
||||||
resp.IsFriend = ds.IsFriend(user.ID, other.ID)
|
|
||||||
}
|
|
||||||
return resp, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// UpdateUserInfo 更新用户信息
|
|
||||||
func UpdateUserInfo(user *core.User) *errcode.Error {
|
|
||||||
if err := ds.UpdateUser(user); err != nil {
|
|
||||||
return errcode.ServerError
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func ChangeUserAvatar(user *core.User, avatar string) (err *errcode.Error) {
|
|
||||||
defer func() {
|
|
||||||
if err != nil {
|
|
||||||
deleteOssObjects([]string{avatar})
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
if err := ds.CheckAttachment(avatar); err != nil {
|
|
||||||
return errcode.InvalidParams
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := oss.PersistObject(oss.ObjectKey(avatar)); err != nil {
|
|
||||||
logrus.Errorf("service.ChangeUserAvatar persist object failed: %s", err)
|
|
||||||
return errcode.ServerError
|
|
||||||
}
|
|
||||||
|
|
||||||
user.Avatar = avatar
|
|
||||||
err = UpdateUserInfo(user)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetUserCollections 获取用户收藏列表
|
|
||||||
func GetUserCollections(userID int64, offset, limit int) ([]*core.PostFormated, int64, error) {
|
|
||||||
collections, err := ds.GetUserPostCollections(userID, offset, limit)
|
|
||||||
if err != nil {
|
|
||||||
return nil, 0, err
|
|
||||||
}
|
|
||||||
totalRows, err := ds.GetUserPostCollectionCount(userID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, 0, err
|
|
||||||
}
|
|
||||||
var posts []*core.Post
|
|
||||||
for _, collection := range collections {
|
|
||||||
posts = append(posts, collection.Post)
|
|
||||||
}
|
|
||||||
postsFormated, err := ds.MergePosts(posts)
|
|
||||||
if err != nil {
|
|
||||||
return nil, 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return postsFormated, totalRows, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetUserStars 获取用户点赞列表
|
|
||||||
func GetUserStars(userID int64, offset, limit int) ([]*core.PostFormated, int64, error) {
|
|
||||||
stars, err := ds.GetUserPostStars(userID, offset, limit)
|
|
||||||
if err != nil {
|
|
||||||
return nil, 0, err
|
|
||||||
}
|
|
||||||
totalRows, err := ds.GetUserPostStarCount(userID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var posts []*core.Post
|
|
||||||
for _, star := range stars {
|
|
||||||
posts = append(posts, star.Post)
|
|
||||||
}
|
|
||||||
postsFormated, err := ds.MergePosts(posts)
|
|
||||||
if err != nil {
|
|
||||||
return nil, 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return postsFormated, totalRows, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetUserWalletBills 获取用户账单列表
|
|
||||||
func GetUserWalletBills(userID int64, offset, limit int) ([]*core.WalletStatement, int64, error) {
|
|
||||||
bills, err := ds.GetUserWalletBills(userID, offset, limit)
|
|
||||||
if err != nil {
|
|
||||||
return nil, 0, err
|
|
||||||
}
|
|
||||||
totalRows, err := ds.GetUserWalletBillCount(userID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return bills, totalRows, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// SendPhoneCaptcha 发送短信验证码
|
|
||||||
func SendPhoneCaptcha(ctx *gin.Context, phone string) error {
|
|
||||||
|
|
||||||
err := ds.SendPhoneCaptcha(phone)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// 写入计数缓存
|
|
||||||
redisClient.Incr(ctx, "PaoPaoSmsCaptcha:"+phone).Result()
|
|
||||||
|
|
||||||
currentTime := time.Now()
|
|
||||||
endTime := time.Date(currentTime.Year(), currentTime.Month(), currentTime.Day(), 23, 59, 59, 0, currentTime.Location())
|
|
||||||
|
|
||||||
redisClient.Expire(ctx, "PaoPaoSmsCaptcha:"+phone, endTime.Sub(currentTime))
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetSuggestUsers 根据关键词获取用户推荐
|
|
||||||
func GetSuggestUsers(keyword string) ([]string, error) {
|
|
||||||
users, err := ds.GetUsersByKeyword(keyword)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
usernames := []string{}
|
|
||||||
for _, user := range users {
|
|
||||||
usernames = append(usernames, user.Username)
|
|
||||||
}
|
|
||||||
|
|
||||||
return usernames, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetSuggestTags 根据关键词获取标签推荐
|
|
||||||
func GetSuggestTags(keyword string) ([]string, error) {
|
|
||||||
tags, err := ds.TagsByKeyword(keyword)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
ts := []string{}
|
|
||||||
for _, t := range tags {
|
|
||||||
ts = append(ts, t.Tag)
|
|
||||||
}
|
|
||||||
|
|
||||||
return ts, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func IsFriend(userId, friendId int64) bool {
|
|
||||||
return ds.IsFriend(userId, friendId)
|
|
||||||
}
|
|
||||||
|
|
||||||
// checkPermision 检查是否拥有者或管理员
|
|
||||||
func checkPermision(user *core.User, targetUserId int64) *errcode.Error {
|
|
||||||
if user == nil || (user.ID != targetUserId && !user.IsAdmin) {
|
|
||||||
return errcode.NoPermission
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
@ -1,58 +0,0 @@
|
|||||||
// Copyright 2022 ROC. All rights reserved.
|
|
||||||
// Use of this source code is governed by a MIT style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package broker
|
|
||||||
|
|
||||||
import (
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/rocboss/paopao-ce/internal/core"
|
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"github.com/rocboss/paopao-ce/pkg/errcode"
|
|
||||||
)
|
|
||||||
|
|
||||||
type RechargeReq struct {
|
|
||||||
Amount int64 `json:"amount" form:"amount" binding:"required"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetRechargeByID(id int64) (*core.WalletRecharge, error) {
|
|
||||||
return ds.GetRechargeByID(id)
|
|
||||||
}
|
|
||||||
|
|
||||||
func CreateRecharge(userID, amount int64) (*core.WalletRecharge, error) {
|
|
||||||
return ds.CreateRecharge(userID, amount)
|
|
||||||
}
|
|
||||||
|
|
||||||
func FinishRecharge(ctx *gin.Context, id int64, tradeNo string) error {
|
|
||||||
if ok, _ := redisClient.SetNX(ctx, "PaoPaoRecharge:"+tradeNo, 1, time.Second*5).Result(); ok {
|
|
||||||
recharge, err := ds.GetRechargeByID(id)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if recharge.TradeStatus != "TRADE_SUCCESS" {
|
|
||||||
|
|
||||||
// 标记为已付款
|
|
||||||
err := ds.HandleRechargeSuccess(recharge, tradeNo)
|
|
||||||
defer redisClient.Del(ctx, "PaoPaoRecharge:"+tradeNo)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func BuyPostAttachment(post *core.Post, user *core.User) error {
|
|
||||||
if user.Balance < post.AttachmentPrice {
|
|
||||||
return errcode.InsuffientDownloadMoney
|
|
||||||
}
|
|
||||||
|
|
||||||
// 执行购买
|
|
||||||
return ds.HandlePostAttachmentBought(post, user)
|
|
||||||
}
|
|
@ -1,52 +0,0 @@
|
|||||||
// Copyright 2022 ROC. All rights reserved.
|
|
||||||
// Use of this source code is governed by a MIT style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package api
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/alimy/cfg"
|
|
||||||
"github.com/redis/go-redis/v9"
|
|
||||||
"github.com/rocboss/paopao-ce/internal/conf"
|
|
||||||
"github.com/rocboss/paopao-ce/internal/core"
|
|
||||||
"github.com/rocboss/paopao-ce/internal/dao"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
"github.com/smartwalle/alipay/v3"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
redisClient *redis.Client
|
|
||||||
alipayClient *alipay.Client
|
|
||||||
objectStorage core.ObjectStorageService
|
|
||||||
)
|
|
||||||
|
|
||||||
func Initialize() {
|
|
||||||
redisClient = conf.MustRedis()
|
|
||||||
objectStorage = dao.ObjectStorageService()
|
|
||||||
|
|
||||||
if cfg.If("Alipay") {
|
|
||||||
alipayClient = mustAlipayClient()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func mustAlipayClient() *alipay.Client {
|
|
||||||
s := conf.AlipaySetting
|
|
||||||
// 将 key 的验证调整到初始化阶段
|
|
||||||
client, err := alipay.New(s.AppID, s.PrivateKey, s.InProduction)
|
|
||||||
if err != nil {
|
|
||||||
logrus.Fatalf("alipay.New err: %s", err)
|
|
||||||
}
|
|
||||||
// 加载应用公钥证书
|
|
||||||
if err = client.LoadAppPublicCertFromFile(s.AppPublicCertFile); err != nil {
|
|
||||||
logrus.Fatalf("client.LoadAppPublicCertFromFile err: %s\n", err)
|
|
||||||
}
|
|
||||||
// 加载支付宝根证书
|
|
||||||
if err = client.LoadAliPayRootCertFromFile(s.RootCertFile); err != nil {
|
|
||||||
logrus.Fatalf("client.LoadAliPayRootCertFromFile err: %s\n", err)
|
|
||||||
}
|
|
||||||
// 加载支付宝公钥证书
|
|
||||||
if err = client.LoadAliPayPublicCertFromFile(s.PublicCertFile); err != nil {
|
|
||||||
logrus.Fatalf("client.LoadAliPayPublicCertFromFile err: %s\n", err)
|
|
||||||
}
|
|
||||||
return client
|
|
||||||
}
|
|
@ -1,257 +0,0 @@
|
|||||||
// Copyright 2022 ROC. All rights reserved.
|
|
||||||
// Use of this source code is governed by a MIT style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package api
|
|
||||||
|
|
||||||
import (
|
|
||||||
"image"
|
|
||||||
|
|
||||||
"github.com/disintegration/imaging"
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"github.com/gofrs/uuid"
|
|
||||||
"github.com/rocboss/paopao-ce/internal/core"
|
|
||||||
"github.com/rocboss/paopao-ce/internal/core/cs"
|
|
||||||
"github.com/rocboss/paopao-ce/internal/servants/web/broker"
|
|
||||||
"github.com/rocboss/paopao-ce/pkg/app"
|
|
||||||
"github.com/rocboss/paopao-ce/pkg/convert"
|
|
||||||
"github.com/rocboss/paopao-ce/pkg/errcode"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
)
|
|
||||||
|
|
||||||
var uploadAttachmentTypeMap = map[string]cs.AttachmentType{
|
|
||||||
"public/image": cs.AttachmentTypeImage,
|
|
||||||
"public/avatar": cs.AttachmentTypeImage,
|
|
||||||
"public/video": cs.AttachmentTypeVideo,
|
|
||||||
"attachment": cs.AttachmentTypeOther,
|
|
||||||
}
|
|
||||||
|
|
||||||
func GeneratePath(s string) string {
|
|
||||||
n := len(s)
|
|
||||||
if n <= 2 {
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
|
|
||||||
return GeneratePath(s[:n-2]) + "/" + s[n-2:]
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetFileExt(s string) (string, error) {
|
|
||||||
switch s {
|
|
||||||
case "image/png":
|
|
||||||
return ".png", nil
|
|
||||||
case "image/jpg":
|
|
||||||
return ".jpg", nil
|
|
||||||
case "image/jpeg":
|
|
||||||
return ".jpeg", nil
|
|
||||||
case "image/gif":
|
|
||||||
return ".gif", nil
|
|
||||||
case "video/mp4":
|
|
||||||
return ".mp4", nil
|
|
||||||
case "video/quicktime":
|
|
||||||
return ".mov", nil
|
|
||||||
case "application/zip":
|
|
||||||
return ".zip", nil
|
|
||||||
default:
|
|
||||||
return "", errcode.FileInvalidExt.WithDetails("仅允许 png/jpg/gif/mp4/mov/zip 类型")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
func GetImageSize(img image.Rectangle) (int, int) {
|
|
||||||
b := img.Bounds()
|
|
||||||
width := b.Max.X
|
|
||||||
height := b.Max.Y
|
|
||||||
return width, height
|
|
||||||
}
|
|
||||||
|
|
||||||
func fileCheck(uploadType string, size int64) error {
|
|
||||||
if uploadType != "public/video" &&
|
|
||||||
uploadType != "public/image" &&
|
|
||||||
uploadType != "public/avatar" &&
|
|
||||||
uploadType != "attachment" {
|
|
||||||
return errcode.InvalidParams
|
|
||||||
}
|
|
||||||
|
|
||||||
if size > 1024*1024*100 {
|
|
||||||
return errcode.FileInvalidSize.WithDetails("最大允许100MB")
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func UploadAttachment(c *gin.Context) {
|
|
||||||
response := app.NewResponse(c)
|
|
||||||
|
|
||||||
uploadType := c.Request.FormValue("type")
|
|
||||||
file, fileHeader, err := c.Request.FormFile("file")
|
|
||||||
if err != nil {
|
|
||||||
logrus.Errorf("api.UploadAttachment err: %v", err)
|
|
||||||
response.ToErrorResponse(errcode.FileUploadFailed)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer file.Close()
|
|
||||||
|
|
||||||
if err = fileCheck(uploadType, fileHeader.Size); err != nil {
|
|
||||||
cErr, _ := err.(*errcode.Error)
|
|
||||||
response.ToErrorResponse(cErr)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
contentType := fileHeader.Header.Get("Content-Type")
|
|
||||||
fileExt, err := GetFileExt(fileHeader.Header.Get("Content-Type"))
|
|
||||||
if err != nil {
|
|
||||||
logrus.Errorf("GetFileExt err: %v", err)
|
|
||||||
response.ToErrorResponse(err.(*errcode.Error))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 生成随机路径
|
|
||||||
randomPath := uuid.Must(uuid.NewV4()).String()
|
|
||||||
ossSavePath := uploadType + "/" + GeneratePath(randomPath[:8]) + "/" + randomPath[9:] + fileExt
|
|
||||||
|
|
||||||
objectUrl, err := objectStorage.PutObject(ossSavePath, file, fileHeader.Size, contentType, false)
|
|
||||||
if err != nil {
|
|
||||||
logrus.Errorf("putObject err: %v", err)
|
|
||||||
response.ToErrorResponse(errcode.FileUploadFailed)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 构造附件Model
|
|
||||||
attachment := &cs.Attachment{
|
|
||||||
FileSize: fileHeader.Size,
|
|
||||||
Content: objectUrl,
|
|
||||||
}
|
|
||||||
|
|
||||||
if userID, exists := c.Get("UID"); exists {
|
|
||||||
attachment.UserID = userID.(int64)
|
|
||||||
}
|
|
||||||
|
|
||||||
attachment.Type = uploadAttachmentTypeMap[uploadType]
|
|
||||||
if attachment.Type == cs.AttachmentTypeImage {
|
|
||||||
var src image.Image
|
|
||||||
src, err = imaging.Decode(file)
|
|
||||||
if err == nil {
|
|
||||||
attachment.ImgWidth, attachment.ImgHeight = GetImageSize(src.Bounds())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
attachment.ID, err = broker.CreateAttachment(attachment)
|
|
||||||
if err != nil {
|
|
||||||
logrus.Errorf("service.CreateAttachment err: %v", err)
|
|
||||||
response.ToErrorResponse(errcode.FileUploadFailed)
|
|
||||||
}
|
|
||||||
|
|
||||||
response.ToResponse(attachment)
|
|
||||||
}
|
|
||||||
|
|
||||||
func DownloadAttachmentPrecheck(c *gin.Context) {
|
|
||||||
response := app.NewResponse(c)
|
|
||||||
|
|
||||||
contentID := convert.StrTo(c.Query("id")).MustInt64()
|
|
||||||
// 加载content
|
|
||||||
content, err := broker.GetPostContentByID(contentID)
|
|
||||||
if err != nil {
|
|
||||||
logrus.Errorf("service.GetPostContentByID err: %v", err)
|
|
||||||
response.ToErrorResponse(errcode.InvalidDownloadReq)
|
|
||||||
}
|
|
||||||
user, _ := c.Get("USER")
|
|
||||||
if content.Type == core.ContentTypeChargeAttachment {
|
|
||||||
// 加载post
|
|
||||||
post, err := broker.GetPost(content.PostID)
|
|
||||||
if err != nil {
|
|
||||||
logrus.Errorf("service.GetPost err: %v", err)
|
|
||||||
response.ToResponse(gin.H{
|
|
||||||
"paid": false,
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 发布者或管理员免费下载
|
|
||||||
if post.UserID == user.(*core.User).ID || user.(*core.User).IsAdmin {
|
|
||||||
response.ToResponse(gin.H{
|
|
||||||
"paid": true,
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检测是否有购买记录
|
|
||||||
response.ToResponse(gin.H{
|
|
||||||
"paid": broker.CheckPostAttachmentIsPaid(post.ID, user.(*core.User).ID),
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
response.ToResponse(gin.H{
|
|
||||||
"paid": false,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func DownloadAttachment(c *gin.Context) {
|
|
||||||
response := app.NewResponse(c)
|
|
||||||
|
|
||||||
contentID := convert.StrTo(c.Query("id")).MustInt64()
|
|
||||||
|
|
||||||
// 加载content
|
|
||||||
content, err := broker.GetPostContentByID(contentID)
|
|
||||||
if err != nil {
|
|
||||||
logrus.Errorf("service.GetPostContentByID err: %v", err)
|
|
||||||
response.ToErrorResponse(errcode.InvalidDownloadReq)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 收费附件
|
|
||||||
if content.Type == core.ContentTypeChargeAttachment {
|
|
||||||
user, _ := c.Get("USER")
|
|
||||||
|
|
||||||
// 加载post
|
|
||||||
post, err := broker.GetPost(content.PostID)
|
|
||||||
if err != nil {
|
|
||||||
logrus.Errorf("service.GetPost err: %v", err)
|
|
||||||
response.ToResponse(gin.H{
|
|
||||||
"paid": false,
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
paidFlag := false
|
|
||||||
|
|
||||||
// 发布者或管理员免费下载
|
|
||||||
if post.UserID == user.(*core.User).ID || user.(*core.User).IsAdmin {
|
|
||||||
paidFlag = true
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检测是否有购买记录
|
|
||||||
if broker.CheckPostAttachmentIsPaid(post.ID, user.(*core.User).ID) {
|
|
||||||
paidFlag = true
|
|
||||||
}
|
|
||||||
|
|
||||||
if !paidFlag {
|
|
||||||
// 未购买,则尝试购买
|
|
||||||
err := broker.BuyPostAttachment(&core.Post{
|
|
||||||
Model: &core.Model{
|
|
||||||
ID: post.ID,
|
|
||||||
},
|
|
||||||
UserID: post.UserID,
|
|
||||||
AttachmentPrice: post.AttachmentPrice,
|
|
||||||
}, user.(*core.User))
|
|
||||||
if err != nil {
|
|
||||||
logrus.Errorf("service.BuyPostAttachment err: %v", err)
|
|
||||||
if err == errcode.InsuffientDownloadMoney {
|
|
||||||
|
|
||||||
response.ToErrorResponse(errcode.InsuffientDownloadMoney)
|
|
||||||
} else {
|
|
||||||
|
|
||||||
response.ToErrorResponse(errcode.DownloadExecFail)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
objectKey := objectStorage.ObjectKey(content.Content)
|
|
||||||
signedURL, err := objectStorage.SignURL(objectKey, 60)
|
|
||||||
if err != nil {
|
|
||||||
logrus.Errorf("client.SignURL err: %v", err)
|
|
||||||
response.ToErrorResponse(errcode.DownloadReqError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
response.ToResponse(gin.H{
|
|
||||||
"signed_url": signedURL,
|
|
||||||
})
|
|
||||||
}
|
|
@ -1,146 +0,0 @@
|
|||||||
// Copyright 2022 ROC. All rights reserved.
|
|
||||||
// Use of this source code is governed by a MIT style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package api
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"github.com/rocboss/paopao-ce/internal/core"
|
|
||||||
"github.com/rocboss/paopao-ce/internal/servants/web/broker"
|
|
||||||
"github.com/rocboss/paopao-ce/pkg/app"
|
|
||||||
"github.com/rocboss/paopao-ce/pkg/convert"
|
|
||||||
"github.com/rocboss/paopao-ce/pkg/errcode"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
)
|
|
||||||
|
|
||||||
func GetPostComments(c *gin.Context) {
|
|
||||||
postID := convert.StrTo(c.Query("id")).MustInt64()
|
|
||||||
response := app.NewResponse(c)
|
|
||||||
|
|
||||||
contents, totalRows, err := broker.GetPostComments(postID, "id ASC", 0, 0)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
logrus.Errorf("service.GetPostComments err: %v\n", err)
|
|
||||||
response.ToErrorResponse(errcode.GetCommentsFailed)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
response.ToResponseList(contents, totalRows)
|
|
||||||
}
|
|
||||||
|
|
||||||
func CreatePostComment(c *gin.Context) {
|
|
||||||
param := broker.CommentCreationReq{}
|
|
||||||
response := app.NewResponse(c)
|
|
||||||
valid, errs := app.BindAndValid(c, ¶m)
|
|
||||||
if !valid {
|
|
||||||
logrus.Errorf("app.BindAndValid errs: %v", errs)
|
|
||||||
response.ToErrorResponse(errcode.InvalidParams.WithDetails(errs.Errors()...))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
userID, _ := c.Get("UID")
|
|
||||||
comment, err := broker.CreatePostComment(c, userID.(int64), param)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
if err == errcode.MaxCommentCount {
|
|
||||||
response.ToErrorResponse(errcode.MaxCommentCount)
|
|
||||||
} else {
|
|
||||||
logrus.Errorf("service.CreatePostComment err: %v\n", err)
|
|
||||||
response.ToErrorResponse(errcode.CreateCommentFailed)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
response.ToResponse(comment)
|
|
||||||
}
|
|
||||||
|
|
||||||
func DeletePostComment(c *gin.Context) {
|
|
||||||
param := broker.CommentDelReq{}
|
|
||||||
response := app.NewResponse(c)
|
|
||||||
valid, errs := app.BindAndValid(c, ¶m)
|
|
||||||
if !valid {
|
|
||||||
logrus.Errorf("app.BindAndValid errs: %v", errs)
|
|
||||||
response.ToErrorResponse(errcode.InvalidParams.WithDetails(errs.Errors()...))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
user, _ := c.Get("USER")
|
|
||||||
|
|
||||||
comment, err := broker.GetPostComment(param.ID)
|
|
||||||
if err != nil {
|
|
||||||
logrus.Errorf("service.GetPostComment err: %v\n", err)
|
|
||||||
response.ToErrorResponse(errcode.GetCommentFailed)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if user.(*core.User).ID != comment.UserID && !user.(*core.User).IsAdmin {
|
|
||||||
response.ToErrorResponse(errcode.NoPermission)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 执行删除
|
|
||||||
err = broker.DeletePostComment(comment)
|
|
||||||
if err != nil {
|
|
||||||
logrus.Errorf("service.DeletePostComment err: %v\n", err)
|
|
||||||
response.ToErrorResponse(errcode.DeleteCommentFailed)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
response.ToResponse(nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
func CreatePostCommentReply(c *gin.Context) {
|
|
||||||
param := broker.CommentReplyCreationReq{}
|
|
||||||
response := app.NewResponse(c)
|
|
||||||
valid, errs := app.BindAndValid(c, ¶m)
|
|
||||||
if !valid {
|
|
||||||
logrus.Errorf("app.BindAndValid errs: %v", errs)
|
|
||||||
response.ToErrorResponse(errcode.InvalidParams.WithDetails(errs.Errors()...))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
user, _ := c.Get("USER")
|
|
||||||
|
|
||||||
comment, err := broker.CreatePostCommentReply(c, param.CommentID, param.Content, user.(*core.User).ID, param.AtUserID)
|
|
||||||
if err != nil {
|
|
||||||
logrus.Errorf("service.CreatePostCommentReply err: %v\n", err)
|
|
||||||
response.ToErrorResponse(errcode.CreateReplyFailed)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
response.ToResponse(comment)
|
|
||||||
}
|
|
||||||
|
|
||||||
func DeletePostCommentReply(c *gin.Context) {
|
|
||||||
param := broker.ReplyDelReq{}
|
|
||||||
response := app.NewResponse(c)
|
|
||||||
valid, errs := app.BindAndValid(c, ¶m)
|
|
||||||
if !valid {
|
|
||||||
logrus.Errorf("app.BindAndValid errs: %v", errs)
|
|
||||||
response.ToErrorResponse(errcode.InvalidParams.WithDetails(errs.Errors()...))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
user, _ := c.Get("USER")
|
|
||||||
|
|
||||||
reply, err := broker.GetPostCommentReply(param.ID)
|
|
||||||
if err != nil {
|
|
||||||
logrus.Errorf("service.GetPostCommentReply err: %v\n", err)
|
|
||||||
response.ToErrorResponse(errcode.GetReplyFailed)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if user.(*core.User).ID != reply.UserID && !user.(*core.User).IsAdmin {
|
|
||||||
response.ToErrorResponse(errcode.NoPermission)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 执行删除
|
|
||||||
err = broker.DeletePostCommentReply(reply)
|
|
||||||
if err != nil {
|
|
||||||
logrus.Errorf("service.DeletePostCommentReply err: %v\n", err)
|
|
||||||
response.ToErrorResponse(errcode.DeleteCommentFailed)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
response.ToResponse(nil)
|
|
||||||
}
|
|
@ -1,107 +0,0 @@
|
|||||||
// Copyright 2022 ROC. All rights reserved.
|
|
||||||
// Use of this source code is governed by a MIT style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package api
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding/base64"
|
|
||||||
"image/color"
|
|
||||||
"image/png"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/afocus/captcha"
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"github.com/gofrs/uuid"
|
|
||||||
"github.com/rocboss/paopao-ce/internal/core"
|
|
||||||
"github.com/rocboss/paopao-ce/internal/servants/web/assets"
|
|
||||||
"github.com/rocboss/paopao-ce/internal/servants/web/broker"
|
|
||||||
"github.com/rocboss/paopao-ce/pkg/app"
|
|
||||||
"github.com/rocboss/paopao-ce/pkg/convert"
|
|
||||||
"github.com/rocboss/paopao-ce/pkg/debug"
|
|
||||||
"github.com/rocboss/paopao-ce/pkg/errcode"
|
|
||||||
"github.com/rocboss/paopao-ce/pkg/utils"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
)
|
|
||||||
|
|
||||||
const MAX_PHONE_CAPTCHA = 10
|
|
||||||
|
|
||||||
func Version(c *gin.Context) {
|
|
||||||
response := app.NewResponse(c)
|
|
||||||
response.ToResponse(gin.H{
|
|
||||||
"BuildInfo": debug.ReadBuildInfo(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func SyncSearchIndex(c *gin.Context) {
|
|
||||||
response := app.NewResponse(c)
|
|
||||||
|
|
||||||
user, _ := c.Get("USER")
|
|
||||||
|
|
||||||
if user.(*core.User).IsAdmin {
|
|
||||||
go broker.PushPostsToSearch(c)
|
|
||||||
}
|
|
||||||
|
|
||||||
response.ToResponse(nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetCaptcha(c *gin.Context) {
|
|
||||||
cap := captcha.New()
|
|
||||||
|
|
||||||
if err := cap.AddFontFromBytes(assets.ComicBytes); err != nil {
|
|
||||||
panic(err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
cap.SetSize(160, 64)
|
|
||||||
cap.SetDisturbance(captcha.MEDIUM)
|
|
||||||
cap.SetFrontColor(color.RGBA{0, 0, 0, 255})
|
|
||||||
cap.SetBkgColor(color.RGBA{218, 240, 228, 255})
|
|
||||||
img, password := cap.Create(6, captcha.NUM)
|
|
||||||
emptyBuff := bytes.NewBuffer(nil)
|
|
||||||
_ = png.Encode(emptyBuff, img)
|
|
||||||
|
|
||||||
key := utils.EncodeMD5(uuid.Must(uuid.NewV4()).String())
|
|
||||||
|
|
||||||
// 五分钟有效期
|
|
||||||
redisClient.SetEx(c, "PaoPaoCaptcha:"+key, password, time.Minute*5)
|
|
||||||
|
|
||||||
response := app.NewResponse(c)
|
|
||||||
response.ToResponse(gin.H{
|
|
||||||
"id": key,
|
|
||||||
"b64s": "data:image/png;base64," + base64.StdEncoding.EncodeToString(emptyBuff.Bytes()),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func PostCaptcha(c *gin.Context) {
|
|
||||||
param := broker.PhoneCaptchaReq{}
|
|
||||||
response := app.NewResponse(c)
|
|
||||||
valid, errs := app.BindAndValid(c, ¶m)
|
|
||||||
if !valid {
|
|
||||||
logrus.Errorf("app.BindAndValid errs: %v", errs)
|
|
||||||
response.ToErrorResponse(errcode.InvalidParams.WithDetails(errs.Errors()...))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 验证图片验证码
|
|
||||||
if res, err := redisClient.Get(c.Request.Context(), "PaoPaoCaptcha:"+param.ImgCaptchaID).Result(); err != nil || res != param.ImgCaptcha {
|
|
||||||
response.ToErrorResponse(errcode.ErrorCaptchaPassword)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
redisClient.Del(c.Request.Context(), "PaoPaoCaptcha:"+param.ImgCaptchaID).Result()
|
|
||||||
|
|
||||||
// 今日频次限制
|
|
||||||
if res, _ := redisClient.Get(c.Request.Context(), "PaoPaoSmsCaptcha:"+param.Phone).Result(); convert.StrTo(res).MustInt() >= MAX_PHONE_CAPTCHA {
|
|
||||||
response.ToErrorResponse(errcode.TooManyPhoneCaptchaSend)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
err := broker.SendPhoneCaptcha(c, param.Phone)
|
|
||||||
if err != nil {
|
|
||||||
logrus.Errorf("app.SendPhoneCaptcha errs: %v", errs)
|
|
||||||
response.ToErrorResponse(errcode.GetPhoneCaptchaError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
response.ToResponse(nil)
|
|
||||||
}
|
|
@ -1,105 +0,0 @@
|
|||||||
// Copyright 2022 ROC. All rights reserved.
|
|
||||||
// Use of this source code is governed by a MIT style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package api
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"github.com/rocboss/paopao-ce/internal/core"
|
|
||||||
"github.com/rocboss/paopao-ce/internal/servants/web/broker"
|
|
||||||
"github.com/rocboss/paopao-ce/pkg/app"
|
|
||||||
"github.com/rocboss/paopao-ce/pkg/errcode"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
)
|
|
||||||
|
|
||||||
func GetUnreadMsgCount(c *gin.Context) {
|
|
||||||
response := app.NewResponse(c)
|
|
||||||
|
|
||||||
user := &core.User{}
|
|
||||||
if u, exists := c.Get("USER"); exists {
|
|
||||||
user = u.(*core.User)
|
|
||||||
}
|
|
||||||
|
|
||||||
count, _ := broker.GetUnreadCount(user.ID)
|
|
||||||
|
|
||||||
response.ToResponse(gin.H{
|
|
||||||
"count": count,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetMessages(c *gin.Context) {
|
|
||||||
response := app.NewResponse(c)
|
|
||||||
|
|
||||||
userID, _ := c.Get("UID")
|
|
||||||
messages, totalRows, err := broker.GetMessages(userID.(int64), (app.GetPage(c)-1)*app.GetPageSize(c), app.GetPageSize(c))
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
logrus.Errorf("service.GetMessages err: %v\n", err)
|
|
||||||
response.ToErrorResponse(errcode.GetMessagesFailed)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
response.ToResponseList(messages, totalRows)
|
|
||||||
}
|
|
||||||
|
|
||||||
func ReadMessage(c *gin.Context) {
|
|
||||||
param := broker.ReadMessageReq{}
|
|
||||||
response := app.NewResponse(c)
|
|
||||||
valid, errs := app.BindAndValid(c, ¶m)
|
|
||||||
if !valid {
|
|
||||||
logrus.Errorf("app.BindAndValid errs: %v", errs)
|
|
||||||
response.ToErrorResponse(errcode.InvalidParams.WithDetails(errs.Errors()...))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
userID, _ := c.Get("UID")
|
|
||||||
err := broker.ReadMessage(param.ID, userID.(int64))
|
|
||||||
if err != nil {
|
|
||||||
logrus.Errorf("service.ReadMessage err: %v\n", err)
|
|
||||||
response.ToErrorResponse(errcode.ReadMessageFailed)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
response.ToResponse(nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
func SendUserWhisper(c *gin.Context) {
|
|
||||||
param := broker.WhisperReq{}
|
|
||||||
response := app.NewResponse(c)
|
|
||||||
valid, errs := app.BindAndValid(c, ¶m)
|
|
||||||
if !valid {
|
|
||||||
logrus.Errorf("app.BindAndValid errs: %v", errs)
|
|
||||||
response.ToErrorResponse(errcode.InvalidParams.WithDetails(errs.Errors()...))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
userID, _ := c.Get("UID")
|
|
||||||
|
|
||||||
// 不允许发送私信给自己
|
|
||||||
if userID.(int64) == param.UserID {
|
|
||||||
response.ToErrorResponse(errcode.NoWhisperToSelf)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err := broker.CreateWhisper(c, &core.Message{
|
|
||||||
SenderUserID: userID.(int64),
|
|
||||||
ReceiverUserID: param.UserID,
|
|
||||||
Type: core.MsgTypeWhisper,
|
|
||||||
Brief: "给你发送新私信了",
|
|
||||||
Content: param.Content,
|
|
||||||
})
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
logrus.Errorf("service.CreateWhisper err: %v\n", err)
|
|
||||||
|
|
||||||
if err == errcode.TooManyWhisperNum {
|
|
||||||
response.ToErrorResponse(errcode.TooManyWhisperNum)
|
|
||||||
} else {
|
|
||||||
response.ToErrorResponse(errcode.SendWhisperFailed)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
response.ToResponse(nil)
|
|
||||||
}
|
|
@ -1,335 +0,0 @@
|
|||||||
// Copyright 2022 ROC. All rights reserved.
|
|
||||||
// Use of this source code is governed by a MIT style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package api
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"github.com/rocboss/paopao-ce/internal/core"
|
|
||||||
"github.com/rocboss/paopao-ce/internal/servants/web/broker"
|
|
||||||
"github.com/rocboss/paopao-ce/pkg/app"
|
|
||||||
"github.com/rocboss/paopao-ce/pkg/convert"
|
|
||||||
"github.com/rocboss/paopao-ce/pkg/errcode"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
)
|
|
||||||
|
|
||||||
func GetPostList(c *gin.Context) {
|
|
||||||
response := app.NewResponse(c)
|
|
||||||
|
|
||||||
q := &core.QueryReq{
|
|
||||||
Query: c.Query("query"),
|
|
||||||
Type: "search",
|
|
||||||
}
|
|
||||||
if c.Query("type") == "tag" {
|
|
||||||
q.Type = "tag"
|
|
||||||
}
|
|
||||||
|
|
||||||
user, _ := userFrom(c)
|
|
||||||
offset, limit := app.GetPageOffset(c)
|
|
||||||
if q.Query == "" && q.Type == "search" {
|
|
||||||
resp, err := broker.GetIndexPosts(user, offset, limit)
|
|
||||||
if err != nil {
|
|
||||||
logrus.Errorf("service.GetPostList err: %v\n", err)
|
|
||||||
response.ToErrorResponse(errcode.GetPostsFailed)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
response.ToResponseList(resp.Tweets, resp.Total)
|
|
||||||
} else {
|
|
||||||
posts, totalRows, err := broker.GetPostListFromSearch(user, q, offset, limit)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
logrus.Errorf("service.GetPostListFromSearch err: %v\n", err)
|
|
||||||
response.ToErrorResponse(errcode.GetPostsFailed)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
response.ToResponseList(posts, totalRows)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetPost(c *gin.Context) {
|
|
||||||
postID := convert.StrTo(c.Query("id")).MustInt64()
|
|
||||||
response := app.NewResponse(c)
|
|
||||||
|
|
||||||
postFormated, err := broker.GetPost(postID)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
logrus.Errorf("service.GetPost err: %v\n", err)
|
|
||||||
response.ToErrorResponse(errcode.GetPostFailed)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
response.ToResponse(postFormated)
|
|
||||||
}
|
|
||||||
|
|
||||||
func CreatePost(c *gin.Context) {
|
|
||||||
param := broker.PostCreationReq{}
|
|
||||||
response := app.NewResponse(c)
|
|
||||||
valid, errs := app.BindAndValid(c, ¶m)
|
|
||||||
if !valid {
|
|
||||||
logrus.Errorf("app.BindAndValid errs: %v", errs)
|
|
||||||
response.ToErrorResponse(errcode.InvalidParams.WithDetails(errs.Errors()...))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
userID, _ := c.Get("UID")
|
|
||||||
post, err := broker.CreatePost(c, userID.(int64), param)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
logrus.Errorf("service.CreatePost err: %v\n", err)
|
|
||||||
response.ToErrorResponse(errcode.CreatePostFailed)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
response.ToResponse(post)
|
|
||||||
}
|
|
||||||
|
|
||||||
func DeletePost(c *gin.Context) {
|
|
||||||
param := broker.PostDelReq{}
|
|
||||||
response := app.NewResponse(c)
|
|
||||||
valid, errs := app.BindAndValid(c, ¶m)
|
|
||||||
if !valid {
|
|
||||||
logrus.Errorf("app.BindAndValid errs: %v", errs)
|
|
||||||
response.ToErrorResponse(errcode.InvalidParams.WithDetails(errs.Errors()...))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
user, exist := userFrom(c)
|
|
||||||
if !exist {
|
|
||||||
response.ToErrorResponse(errcode.NoPermission)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
err := broker.DeletePost(user, param.ID)
|
|
||||||
if err != nil {
|
|
||||||
logrus.Errorf("service.DeletePost err: %v\n", err)
|
|
||||||
response.ToErrorResponse(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
response.ToResponse(nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetPostStar(c *gin.Context) {
|
|
||||||
postID := convert.StrTo(c.Query("id")).MustInt64()
|
|
||||||
response := app.NewResponse(c)
|
|
||||||
|
|
||||||
userID, _ := c.Get("UID")
|
|
||||||
|
|
||||||
_, err := broker.GetPostStar(postID, userID.(int64))
|
|
||||||
if err != nil {
|
|
||||||
response.ToResponse(gin.H{
|
|
||||||
"status": false,
|
|
||||||
})
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
response.ToResponse(gin.H{
|
|
||||||
"status": true,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func PostStar(c *gin.Context) {
|
|
||||||
param := broker.PostStarReq{}
|
|
||||||
response := app.NewResponse(c)
|
|
||||||
valid, errs := app.BindAndValid(c, ¶m)
|
|
||||||
if !valid {
|
|
||||||
logrus.Errorf("app.BindAndValid errs: %v", errs)
|
|
||||||
response.ToErrorResponse(errcode.InvalidParams.WithDetails(errs.Errors()...))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
userID, _ := c.Get("UID")
|
|
||||||
|
|
||||||
status := false
|
|
||||||
star, err := broker.GetPostStar(param.ID, userID.(int64))
|
|
||||||
if err != nil {
|
|
||||||
// 创建Star
|
|
||||||
_, err = broker.CreatePostStar(param.ID, userID.(int64))
|
|
||||||
status = true
|
|
||||||
} else {
|
|
||||||
// 取消Star
|
|
||||||
err = broker.DeletePostStar(star)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
response.ToErrorResponse(errcode.NoPermission)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
response.ToResponse(gin.H{
|
|
||||||
"status": status,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetPostCollection(c *gin.Context) {
|
|
||||||
postID := convert.StrTo(c.Query("id")).MustInt64()
|
|
||||||
response := app.NewResponse(c)
|
|
||||||
|
|
||||||
userID, _ := c.Get("UID")
|
|
||||||
|
|
||||||
_, err := broker.GetPostCollection(postID, userID.(int64))
|
|
||||||
if err != nil {
|
|
||||||
response.ToResponse(gin.H{
|
|
||||||
"status": false,
|
|
||||||
})
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
response.ToResponse(gin.H{
|
|
||||||
"status": true,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func PostCollection(c *gin.Context) {
|
|
||||||
param := broker.PostCollectionReq{}
|
|
||||||
response := app.NewResponse(c)
|
|
||||||
valid, errs := app.BindAndValid(c, ¶m)
|
|
||||||
if !valid {
|
|
||||||
logrus.Errorf("app.BindAndValid errs: %v", errs)
|
|
||||||
response.ToErrorResponse(errcode.InvalidParams.WithDetails(errs.Errors()...))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
userID, _ := c.Get("UID")
|
|
||||||
|
|
||||||
status := false
|
|
||||||
collection, err := broker.GetPostCollection(param.ID, userID.(int64))
|
|
||||||
if err != nil {
|
|
||||||
// 创建collection
|
|
||||||
_, err = broker.CreatePostCollection(param.ID, userID.(int64))
|
|
||||||
status = true
|
|
||||||
} else {
|
|
||||||
// 取消Star
|
|
||||||
err = broker.DeletePostCollection(collection)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
response.ToErrorResponse(errcode.NoPermission)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
response.ToResponse(gin.H{
|
|
||||||
"status": status,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func LockPost(c *gin.Context) {
|
|
||||||
param := broker.PostLockReq{}
|
|
||||||
response := app.NewResponse(c)
|
|
||||||
valid, errs := app.BindAndValid(c, ¶m)
|
|
||||||
if !valid {
|
|
||||||
logrus.Errorf("app.BindAndValid errs: %v", errs)
|
|
||||||
response.ToErrorResponse(errcode.InvalidParams.WithDetails(errs.Errors()...))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
user, _ := c.Get("USER")
|
|
||||||
|
|
||||||
// 获取Post
|
|
||||||
postFormated, err := broker.GetPost(param.ID)
|
|
||||||
if err != nil {
|
|
||||||
logrus.Errorf("service.GetPost err: %v\n", err)
|
|
||||||
response.ToErrorResponse(errcode.GetPostFailed)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if postFormated.UserID != user.(*core.User).ID && !user.(*core.User).IsAdmin {
|
|
||||||
response.ToErrorResponse(errcode.NoPermission)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
err = broker.LockPost(param.ID)
|
|
||||||
if err != nil {
|
|
||||||
logrus.Errorf("service.LockPost err: %v\n", err)
|
|
||||||
response.ToErrorResponse(errcode.LockPostFailed)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
response.ToResponse(gin.H{
|
|
||||||
"lock_status": 1 - postFormated.IsLock,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func StickPost(c *gin.Context) {
|
|
||||||
param := broker.PostStickReq{}
|
|
||||||
response := app.NewResponse(c)
|
|
||||||
valid, errs := app.BindAndValid(c, ¶m)
|
|
||||||
if !valid {
|
|
||||||
logrus.Errorf("app.BindAndValid errs: %v", errs)
|
|
||||||
response.ToErrorResponse(errcode.InvalidParams.WithDetails(errs.Errors()...))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
user, _ := c.Get("USER")
|
|
||||||
|
|
||||||
// 获取Post
|
|
||||||
postFormated, err := broker.GetPost(param.ID)
|
|
||||||
if err != nil {
|
|
||||||
logrus.Errorf("service.GetPost err: %v\n", err)
|
|
||||||
response.ToErrorResponse(errcode.GetPostFailed)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if !user.(*core.User).IsAdmin {
|
|
||||||
response.ToErrorResponse(errcode.NoPermission)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
err = broker.StickPost(param.ID)
|
|
||||||
if err != nil {
|
|
||||||
logrus.Errorf("service.StickPost err: %v\n", err)
|
|
||||||
response.ToErrorResponse(errcode.LockPostFailed)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
response.ToResponse(gin.H{
|
|
||||||
"top_status": 1 - postFormated.IsTop,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func VisiblePost(c *gin.Context) {
|
|
||||||
param := broker.PostVisibilityReq{}
|
|
||||||
response := app.NewResponse(c)
|
|
||||||
valid, errs := app.BindAndValid(c, ¶m)
|
|
||||||
if !valid {
|
|
||||||
logrus.Errorf("app.BindAndValid errs: %v", errs)
|
|
||||||
response.ToErrorResponse(errcode.InvalidParams.WithDetails(errs.Errors()...))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
user, _ := userFrom(c)
|
|
||||||
if err := broker.VisiblePost(user, param.ID, param.Visibility); err != nil {
|
|
||||||
logrus.Errorf("service.VisiblePost err: %v\n", err)
|
|
||||||
response.ToErrorResponse(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
response.ToResponse(gin.H{
|
|
||||||
"visibility": param.Visibility,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetPostTags(c *gin.Context) {
|
|
||||||
param := broker.PostTagsReq{}
|
|
||||||
response := app.NewResponse(c)
|
|
||||||
valid, errs := app.BindAndValid(c, ¶m)
|
|
||||||
if !valid {
|
|
||||||
logrus.Errorf("app.BindAndValid errs: %v", errs)
|
|
||||||
response.ToErrorResponse(errcode.InvalidParams.WithDetails(errs.Errors()...))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
tags, err := broker.GetPostTags(¶m)
|
|
||||||
if err != nil {
|
|
||||||
logrus.Errorf("service.GetPostTags err: %v\n", err)
|
|
||||||
response.ToErrorResponse(errcode.GetPostTagsFailed)
|
|
||||||
return
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
response.ToResponse(gin.H{
|
|
||||||
"topics": tags,
|
|
||||||
})
|
|
||||||
}
|
|
@ -1,650 +0,0 @@
|
|||||||
// Copyright 2022 ROC. All rights reserved.
|
|
||||||
// Use of this source code is governed by a MIT style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package api
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
"unicode/utf8"
|
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"github.com/rocboss/paopao-ce/internal/core"
|
|
||||||
"github.com/rocboss/paopao-ce/internal/servants/web/broker"
|
|
||||||
"github.com/rocboss/paopao-ce/pkg/app"
|
|
||||||
"github.com/rocboss/paopao-ce/pkg/convert"
|
|
||||||
"github.com/rocboss/paopao-ce/pkg/errcode"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
"github.com/smartwalle/alipay/v3"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Login 用户登录
|
|
||||||
func Login(c *gin.Context) {
|
|
||||||
param := broker.AuthRequest{}
|
|
||||||
response := app.NewResponse(c)
|
|
||||||
valid, errs := app.BindAndValid(c, ¶m)
|
|
||||||
if !valid {
|
|
||||||
logrus.Errorf("app.BindAndValid errs: %v", errs)
|
|
||||||
response.ToErrorResponse(errcode.InvalidParams.WithDetails(errs.Errors()...))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
user, err := broker.DoLogin(c, ¶m)
|
|
||||||
if err != nil {
|
|
||||||
logrus.Errorf("service.DoLogin err: %v", err)
|
|
||||||
response.ToErrorResponse(err.(*errcode.Error))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
token, err := app.GenerateToken(user)
|
|
||||||
if err != nil {
|
|
||||||
logrus.Errorf("app.GenerateToken err: %v", err)
|
|
||||||
response.ToErrorResponse(errcode.UnauthorizedTokenGenerate)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
response.ToResponse(gin.H{
|
|
||||||
"token": token,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Register 用户注册
|
|
||||||
func Register(c *gin.Context) {
|
|
||||||
|
|
||||||
param := broker.RegisterRequest{}
|
|
||||||
response := app.NewResponse(c)
|
|
||||||
valid, errs := app.BindAndValid(c, ¶m)
|
|
||||||
if !valid {
|
|
||||||
logrus.Errorf("app.BindAndValid errs: %v", errs)
|
|
||||||
response.ToErrorResponse(errcode.InvalidParams.WithDetails(errs.Errors()...))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 用户名检查
|
|
||||||
err := broker.ValidUsername(param.Username)
|
|
||||||
if err != nil {
|
|
||||||
logrus.Errorf("service.Register err: %v", err)
|
|
||||||
response.ToErrorResponse(err.(*errcode.Error))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 密码检查
|
|
||||||
err = broker.CheckPassword(param.Password)
|
|
||||||
if err != nil {
|
|
||||||
logrus.Errorf("service.Register err: %v", err)
|
|
||||||
response.ToErrorResponse(err.(*errcode.Error))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
user, err := broker.Register(
|
|
||||||
param.Username,
|
|
||||||
param.Password,
|
|
||||||
)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
logrus.Errorf("service.Register err: %v", err)
|
|
||||||
response.ToErrorResponse(errcode.UserRegisterFailed)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
response.ToResponse(gin.H{
|
|
||||||
"id": user.ID,
|
|
||||||
"username": user.Username,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func RequestingFriend(c *gin.Context) {
|
|
||||||
param := broker.RequestingFriendReq{}
|
|
||||||
response := app.NewResponse(c)
|
|
||||||
valid, errs := app.BindAndValid(c, ¶m)
|
|
||||||
if !valid {
|
|
||||||
logrus.Errorf("app.BindAndValid errs: %v", errs)
|
|
||||||
response.ToErrorResponse(errcode.InvalidParams.WithDetails(errs.Errors()...))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
user, ok := userFrom(c)
|
|
||||||
if !ok {
|
|
||||||
response.ToErrorResponse(errcode.UnauthorizedAuthNotExist)
|
|
||||||
}
|
|
||||||
if user.ID == param.UserId {
|
|
||||||
response.ToErrorResponse(errcode.NoRequestingFriendToSelf)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := broker.RequestingFriend(user, ¶m); err != nil {
|
|
||||||
logrus.Errorf("service.RequestingFriend err: %v", err)
|
|
||||||
response.ToErrorResponse(errcode.SendRequestingFriendFailed)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
response.ToResponse(nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
func AddFriend(c *gin.Context) {
|
|
||||||
param := broker.AddFriendReq{}
|
|
||||||
response := app.NewResponse(c)
|
|
||||||
valid, errs := app.BindAndValid(c, ¶m)
|
|
||||||
if !valid {
|
|
||||||
logrus.Errorf("app.BindAndValid errs: %v", errs)
|
|
||||||
response.ToErrorResponse(errcode.InvalidParams.WithDetails(errs.Errors()...))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
user, ok := userFrom(c)
|
|
||||||
if !ok {
|
|
||||||
response.ToErrorResponse(errcode.UnauthorizedAuthNotExist)
|
|
||||||
}
|
|
||||||
if user.ID == param.UserId {
|
|
||||||
response.ToErrorResponse(errcode.NoActionToSelf)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := broker.AddFriend(user, ¶m); err != nil {
|
|
||||||
logrus.Errorf("service.AddFriend err: %v", err)
|
|
||||||
response.ToErrorResponse(errcode.AddFriendFailed)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
response.ToResponse(nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
func RejectFriend(c *gin.Context) {
|
|
||||||
param := broker.RejectFriendReq{}
|
|
||||||
response := app.NewResponse(c)
|
|
||||||
valid, errs := app.BindAndValid(c, ¶m)
|
|
||||||
if !valid {
|
|
||||||
logrus.Errorf("app.BindAndValid errs: %v", errs)
|
|
||||||
response.ToErrorResponse(errcode.InvalidParams.WithDetails(errs.Errors()...))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
user, ok := userFrom(c)
|
|
||||||
if !ok {
|
|
||||||
response.ToErrorResponse(errcode.UnauthorizedAuthNotExist)
|
|
||||||
}
|
|
||||||
if user.ID == param.UserId {
|
|
||||||
response.ToErrorResponse(errcode.NoActionToSelf)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := broker.RejectFriend(user, ¶m); err != nil {
|
|
||||||
logrus.Errorf("service.RejectFriend err: %v", err)
|
|
||||||
response.ToErrorResponse(errcode.RejectFriendFailed)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
response.ToResponse(nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
func DeleteFriend(c *gin.Context) {
|
|
||||||
param := broker.DeleteFriendReq{}
|
|
||||||
response := app.NewResponse(c)
|
|
||||||
valid, errs := app.BindAndValid(c, ¶m)
|
|
||||||
if !valid {
|
|
||||||
logrus.Errorf("app.BindAndValid errs: %v", errs)
|
|
||||||
response.ToErrorResponse(errcode.InvalidParams.WithDetails(errs.Errors()...))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
user, ok := userFrom(c)
|
|
||||||
if !ok {
|
|
||||||
response.ToErrorResponse(errcode.UnauthorizedAuthNotExist)
|
|
||||||
}
|
|
||||||
if user.ID == param.UserId {
|
|
||||||
response.ToErrorResponse(errcode.NoActionToSelf)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := broker.DeleteFriend(user, ¶m); err != nil {
|
|
||||||
logrus.Errorf("service.DeleteFriend err: %v", err)
|
|
||||||
response.ToErrorResponse(errcode.DeleteFriendFailed)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
response.ToResponse(nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetContacts(c *gin.Context) {
|
|
||||||
response := app.NewResponse(c)
|
|
||||||
user, ok := userFrom(c)
|
|
||||||
if !ok {
|
|
||||||
response.ToErrorResponse(errcode.UnauthorizedAuthNotExist)
|
|
||||||
}
|
|
||||||
|
|
||||||
offset, limit := app.GetPageOffset(c)
|
|
||||||
resp, err := broker.GetContacts(user, offset, limit)
|
|
||||||
if err != nil {
|
|
||||||
logrus.Errorf("service.DeleteFriend err: %v", err)
|
|
||||||
response.ToErrorResponse(errcode.GetContactsFailed)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
response.ToResponseList(resp.Contacts, resp.Total)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取用户基本信息
|
|
||||||
func GetUserInfo(c *gin.Context) {
|
|
||||||
param := broker.AuthRequest{}
|
|
||||||
response := app.NewResponse(c)
|
|
||||||
|
|
||||||
if username, exists := c.Get("USERNAME"); exists {
|
|
||||||
param.Username = username.(string)
|
|
||||||
}
|
|
||||||
|
|
||||||
user, err := broker.GetUserInfo(¶m)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
response.ToErrorResponse(errcode.UnauthorizedAuthNotExist)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
phone := ""
|
|
||||||
if user.Phone != "" && len(user.Phone) == 11 {
|
|
||||||
phone = user.Phone[0:3] + "****" + user.Phone[7:]
|
|
||||||
}
|
|
||||||
|
|
||||||
response.ToResponse(gin.H{
|
|
||||||
"id": user.ID,
|
|
||||||
"nickname": user.Nickname,
|
|
||||||
"username": user.Username,
|
|
||||||
"status": user.Status,
|
|
||||||
"avatar": user.Avatar,
|
|
||||||
"balance": user.Balance,
|
|
||||||
"phone": phone,
|
|
||||||
"is_admin": user.IsAdmin,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 修改密码
|
|
||||||
func ChangeUserPassword(c *gin.Context) {
|
|
||||||
param := broker.ChangePasswordReq{}
|
|
||||||
response := app.NewResponse(c)
|
|
||||||
valid, errs := app.BindAndValid(c, ¶m)
|
|
||||||
if !valid {
|
|
||||||
logrus.Errorf("app.BindAndValid errs: %v", errs)
|
|
||||||
response.ToErrorResponse(errcode.InvalidParams.WithDetails(errs.Errors()...))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
user := &core.User{}
|
|
||||||
if u, exists := c.Get("USER"); exists {
|
|
||||||
user = u.(*core.User)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 密码检查
|
|
||||||
err := broker.CheckPassword(param.Password)
|
|
||||||
if err != nil {
|
|
||||||
logrus.Errorf("service.Register err: %v", err)
|
|
||||||
response.ToErrorResponse(err.(*errcode.Error))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 旧密码校验
|
|
||||||
if !broker.ValidPassword(user.Password, param.OldPassword, user.Salt) {
|
|
||||||
response.ToErrorResponse(errcode.ErrorOldPassword)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 更新入库
|
|
||||||
user.Password, user.Salt = broker.EncryptPasswordAndSalt(param.Password)
|
|
||||||
broker.UpdateUserInfo(user)
|
|
||||||
|
|
||||||
response.ToResponse(nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 修改昵称
|
|
||||||
func ChangeNickname(c *gin.Context) {
|
|
||||||
param := broker.ChangeNicknameReq{}
|
|
||||||
response := app.NewResponse(c)
|
|
||||||
valid, errs := app.BindAndValid(c, ¶m)
|
|
||||||
if !valid {
|
|
||||||
logrus.Errorf("app.BindAndValid errs: %v", errs)
|
|
||||||
response.ToErrorResponse(errcode.InvalidParams.WithDetails(errs.Errors()...))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
user := &core.User{}
|
|
||||||
if u, exists := c.Get("USER"); exists {
|
|
||||||
user = u.(*core.User)
|
|
||||||
}
|
|
||||||
|
|
||||||
if utf8.RuneCountInString(param.Nickname) < 2 || utf8.RuneCountInString(param.Nickname) > 12 {
|
|
||||||
response.ToErrorResponse(errcode.NicknameLengthLimit)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 执行绑定
|
|
||||||
user.Nickname = param.Nickname
|
|
||||||
broker.UpdateUserInfo(user)
|
|
||||||
|
|
||||||
response.ToResponse(nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 修改头像
|
|
||||||
func ChangeAvatar(c *gin.Context) {
|
|
||||||
param := broker.ChangeAvatarReq{}
|
|
||||||
response := app.NewResponse(c)
|
|
||||||
valid, errs := app.BindAndValid(c, ¶m)
|
|
||||||
if !valid {
|
|
||||||
logrus.Errorf("app.BindAndValid errs: %v", errs)
|
|
||||||
response.ToErrorResponse(errcode.InvalidParams.WithDetails(errs.Errors()...))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
user, exist := userFrom(c)
|
|
||||||
if !exist {
|
|
||||||
response.ToErrorResponse(errcode.UnauthorizedTokenError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := broker.ChangeUserAvatar(user, param.Avatar); err != nil {
|
|
||||||
response.ToErrorResponse(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
response.ToResponse(nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 用户绑定手机号
|
|
||||||
func BindUserPhone(c *gin.Context) {
|
|
||||||
param := broker.UserPhoneBindReq{}
|
|
||||||
response := app.NewResponse(c)
|
|
||||||
valid, errs := app.BindAndValid(c, ¶m)
|
|
||||||
if !valid {
|
|
||||||
logrus.Errorf("app.BindAndValid errs: %v", errs)
|
|
||||||
response.ToErrorResponse(errcode.InvalidParams.WithDetails(errs.Errors()...))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
user := &core.User{}
|
|
||||||
if u, exists := c.Get("USER"); exists {
|
|
||||||
user = u.(*core.User)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 手机重复性检查
|
|
||||||
if broker.CheckPhoneExist(user.ID, param.Phone) {
|
|
||||||
response.ToErrorResponse(errcode.ExistedUserPhone)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := broker.CheckPhoneCaptcha(param.Phone, param.Captcha); err != nil {
|
|
||||||
logrus.Errorf("service.CheckPhoneCaptcha err: %v\n", err)
|
|
||||||
response.ToErrorResponse(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 执行绑定
|
|
||||||
user.Phone = param.Phone
|
|
||||||
if err := broker.UpdateUserInfo(user); err != nil {
|
|
||||||
response.ToErrorResponse(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
response.ToResponse(nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 修改用户状态
|
|
||||||
func ChangeUserStatus(c *gin.Context) {
|
|
||||||
param := broker.ChangeUserStatusReq{}
|
|
||||||
response := app.NewResponse(c)
|
|
||||||
valid, errs := app.BindAndValid(c, ¶m)
|
|
||||||
if !valid {
|
|
||||||
logrus.Errorf("app.BindAndValid errs: %v", errs)
|
|
||||||
response.ToErrorResponse(errcode.InvalidParams.WithDetails(errs.Errors()...))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if param.Status != core.UserStatusNormal && param.Status != core.UserStatusClosed {
|
|
||||||
response.ToErrorResponse(errcode.InvalidParams)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
user, err := broker.GetUserByID(param.ID)
|
|
||||||
if err != nil {
|
|
||||||
logrus.Errorf("service.GetUserByID err: %v\n", err)
|
|
||||||
response.ToErrorResponse(errcode.NoExistUsername)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 执行更新
|
|
||||||
user.Status = param.Status
|
|
||||||
broker.UpdateUserInfo(user)
|
|
||||||
|
|
||||||
response.ToResponse(nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetUserProfile(c *gin.Context) {
|
|
||||||
response := app.NewResponse(c)
|
|
||||||
username := c.Query("username")
|
|
||||||
user, _ := userFrom(c)
|
|
||||||
|
|
||||||
resp, err := broker.GetUserByUsername(user, username)
|
|
||||||
if err != nil {
|
|
||||||
logrus.Errorf("service.GetUserByUsername err: %v\n", err)
|
|
||||||
response.ToErrorResponse(errcode.NoExistUsername)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
response.ToResponse(resp)
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetUserPosts(c *gin.Context) {
|
|
||||||
response := app.NewResponse(c)
|
|
||||||
username := c.Query("username")
|
|
||||||
user, exists := userFrom(c)
|
|
||||||
|
|
||||||
other, err := broker.GetUserByUsername(user, username)
|
|
||||||
if err != nil {
|
|
||||||
logrus.Errorf("service.GetUserByUsername err: %v\n", err)
|
|
||||||
response.ToErrorResponse(errcode.NoExistUsername)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
visibilities := []core.PostVisibleT{core.PostVisitPublic}
|
|
||||||
if exists {
|
|
||||||
if user.ID == other.ID || user.IsAdmin {
|
|
||||||
visibilities = append(visibilities, core.PostVisitPrivate, core.PostVisitFriend)
|
|
||||||
} else if other.IsFriend {
|
|
||||||
visibilities = append(visibilities, core.PostVisitFriend)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
conditions := core.ConditionsT{
|
|
||||||
"user_id": other.ID,
|
|
||||||
"visibility IN ?": visibilities,
|
|
||||||
"ORDER": "latest_replied_on DESC",
|
|
||||||
}
|
|
||||||
|
|
||||||
_, posts, err := broker.GetPostList(&broker.PostListReq{
|
|
||||||
Conditions: &conditions,
|
|
||||||
Offset: (app.GetPage(c) - 1) * app.GetPageSize(c),
|
|
||||||
Limit: app.GetPageSize(c),
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
logrus.Errorf("service.GetPostList err: %v\n", err)
|
|
||||||
response.ToErrorResponse(errcode.GetPostsFailed)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
totalRows, _ := broker.GetPostCount(&conditions)
|
|
||||||
|
|
||||||
response.ToResponseList(posts, totalRows)
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetUserCollections(c *gin.Context) {
|
|
||||||
response := app.NewResponse(c)
|
|
||||||
|
|
||||||
userID, _ := c.Get("UID")
|
|
||||||
posts, totalRows, err := broker.GetUserCollections(userID.(int64), (app.GetPage(c)-1)*app.GetPageSize(c), app.GetPageSize(c))
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
logrus.Errorf("service.GetUserCollections err: %v\n", err)
|
|
||||||
response.ToErrorResponse(errcode.GetCollectionsFailed)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
response.ToResponseList(posts, totalRows)
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetUserStars(c *gin.Context) {
|
|
||||||
response := app.NewResponse(c)
|
|
||||||
|
|
||||||
userID, _ := c.Get("UID")
|
|
||||||
posts, totalRows, err := broker.GetUserStars(userID.(int64), (app.GetPage(c)-1)*app.GetPageSize(c), app.GetPageSize(c))
|
|
||||||
if err != nil {
|
|
||||||
logrus.Errorf("service.GetUserStars err: %v\n", err)
|
|
||||||
response.ToErrorResponse(errcode.GetCollectionsFailed)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
response.ToResponseList(posts, totalRows)
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetSuggestUsers(c *gin.Context) {
|
|
||||||
keyword := c.Query("k")
|
|
||||||
response := app.NewResponse(c)
|
|
||||||
|
|
||||||
usernames, err := broker.GetSuggestUsers(keyword)
|
|
||||||
if err != nil {
|
|
||||||
logrus.Errorf("service.GetSuggestUsers err: %v\n", err)
|
|
||||||
response.ToErrorResponse(errcode.GetCollectionsFailed)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
response.ToResponse(gin.H{
|
|
||||||
"suggest": usernames,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetSuggestTags(c *gin.Context) {
|
|
||||||
keyword := c.Query("k")
|
|
||||||
response := app.NewResponse(c)
|
|
||||||
|
|
||||||
tags, err := broker.GetSuggestTags(keyword)
|
|
||||||
if err != nil {
|
|
||||||
logrus.Errorf("service.GetSuggestTags err: %v\n", err)
|
|
||||||
response.ToErrorResponse(errcode.GetCollectionsFailed)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
response.ToResponse(gin.H{
|
|
||||||
"suggest": tags,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetUserRechargeLink(c *gin.Context) {
|
|
||||||
param := broker.RechargeReq{}
|
|
||||||
response := app.NewResponse(c)
|
|
||||||
valid, errs := app.BindAndValid(c, ¶m)
|
|
||||||
if !valid {
|
|
||||||
logrus.Errorf("app.BindAndValid errs: %v", errs)
|
|
||||||
response.ToErrorResponse(errcode.InvalidParams.WithDetails(errs.Errors()...))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 下单
|
|
||||||
userID, _ := c.Get("UID")
|
|
||||||
recharge, err := broker.CreateRecharge(userID.(int64), param.Amount)
|
|
||||||
if err != nil {
|
|
||||||
logrus.Errorf("service.CreateRecharge err: %v\n", err)
|
|
||||||
response.ToErrorResponse(errcode.RechargeReqFail)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
p := alipay.TradePreCreate{}
|
|
||||||
p.OutTradeNo = fmt.Sprintf("%d", recharge.ID)
|
|
||||||
p.Subject = "PaoPao用户钱包充值"
|
|
||||||
p.TotalAmount = fmt.Sprintf("%.2f", float64(recharge.Amount)/100.0)
|
|
||||||
p.NotifyURL = "https://" + c.Request.Host + "/v1/alipay/notify"
|
|
||||||
|
|
||||||
rsp, err := alipayClient.TradePreCreate(p)
|
|
||||||
if err != nil {
|
|
||||||
logrus.Errorf("client.TradePreCreate err: %v\n", err)
|
|
||||||
response.ToErrorResponse(errcode.RechargeReqFail)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if rsp.Content.Code != alipay.CodeSuccess {
|
|
||||||
response.ToErrorResponse(errcode.RechargeReqFail)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
response.ToResponse(gin.H{
|
|
||||||
"id": recharge.ID,
|
|
||||||
"pay": rsp.Content.QRCode,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetUserRechargeResult(c *gin.Context) {
|
|
||||||
response := app.NewResponse(c)
|
|
||||||
|
|
||||||
id := c.Query("id")
|
|
||||||
userID, _ := c.Get("UID")
|
|
||||||
|
|
||||||
recharge, err := broker.GetRechargeByID(convert.StrTo(id).MustInt64())
|
|
||||||
if err != nil {
|
|
||||||
response.ToErrorResponse(errcode.GetRechargeFailed)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if recharge.UserID != userID.(int64) {
|
|
||||||
response.ToErrorResponse(errcode.GetRechargeFailed)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
response.ToResponse(gin.H{
|
|
||||||
"id": recharge.ID,
|
|
||||||
"status": recharge.TradeStatus,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func AlipayNotify(c *gin.Context) {
|
|
||||||
response := app.NewResponse(c)
|
|
||||||
c.Request.ParseForm()
|
|
||||||
|
|
||||||
_, err := alipayClient.GetTradeNotification(c.Request)
|
|
||||||
if err != nil {
|
|
||||||
logrus.Errorf("alipayClient.GetTradeNotification err: %v\n", err)
|
|
||||||
logrus.Infoln(c.Request.Form)
|
|
||||||
response.ToErrorResponse(errcode.RechargeNotifyError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
id := c.Request.Form.Get("out_trade_no")
|
|
||||||
tradeNo := c.Request.Form.Get("trade_no")
|
|
||||||
tradeStatus := c.Request.Form.Get("trade_status")
|
|
||||||
if tradeStatus == "TRADE_SUCCESS" {
|
|
||||||
// 交易支付成功
|
|
||||||
err = broker.FinishRecharge(c, convert.StrTo(id).MustInt64(), tradeNo)
|
|
||||||
if err != nil {
|
|
||||||
logrus.Errorf("service.FinishRecharge err: %v\n", err)
|
|
||||||
response.ToErrorResponse(errcode.RechargeNotifyError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
response.Ctx.String(http.StatusOK, "success")
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetUserWalletBills(c *gin.Context) {
|
|
||||||
response := app.NewResponse(c)
|
|
||||||
|
|
||||||
userID, _ := c.Get("UID")
|
|
||||||
bills, totalRows, err := broker.GetUserWalletBills(userID.(int64), (app.GetPage(c)-1)*app.GetPageSize(c), app.GetPageSize(c))
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
logrus.Errorf("service.GetUserWalletBills err: %v\n", err)
|
|
||||||
response.ToErrorResponse(errcode.GetCollectionsFailed)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
response.ToResponseList(bills, totalRows)
|
|
||||||
}
|
|
||||||
|
|
||||||
func userFrom(c *gin.Context) (*core.User, bool) {
|
|
||||||
if u, exists := c.Get("USER"); exists {
|
|
||||||
user, ok := u.(*core.User)
|
|
||||||
return user, ok
|
|
||||||
}
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
|
|
||||||
func userIdFrom(c *gin.Context) (int64, bool) {
|
|
||||||
if u, exists := c.Get("UID"); exists {
|
|
||||||
uid, ok := u.(int64)
|
|
||||||
return uid, ok
|
|
||||||
}
|
|
||||||
return -1, false
|
|
||||||
}
|
|
@ -1,17 +0,0 @@
|
|||||||
// Copyright 2022 ROC. All rights reserved.
|
|
||||||
// Use of this source code is governed by a MIT style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
//go:build !docs
|
|
||||||
// +build !docs
|
|
||||||
|
|
||||||
package routers
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
)
|
|
||||||
|
|
||||||
// registerDocs stub function for register docs asset route
|
|
||||||
func registerDocs(e *gin.Engine) {
|
|
||||||
// empty
|
|
||||||
}
|
|
@ -1,21 +0,0 @@
|
|||||||
// Copyright 2022 ROC. All rights reserved.
|
|
||||||
// Use of this source code is governed by a MIT style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
//go:build docs
|
|
||||||
// +build docs
|
|
||||||
|
|
||||||
package routers
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/alimy/cfg"
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"github.com/rocboss/paopao-ce/docs/openapi"
|
|
||||||
)
|
|
||||||
|
|
||||||
// registerDocs register docs asset route
|
|
||||||
func registerDocs(e *gin.Engine) {
|
|
||||||
cfg.Be("Docs:OpenAPI", func() {
|
|
||||||
e.StaticFS("/docs/openapi", openapi.NewFileSystem())
|
|
||||||
})
|
|
||||||
}
|
|
@ -1,351 +0,0 @@
|
|||||||
// Copyright 2022 ROC. All rights reserved.
|
|
||||||
// Use of this source code is governed by a MIT style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package routers
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/http"
|
|
||||||
"path/filepath"
|
|
||||||
|
|
||||||
"github.com/alimy/cfg"
|
|
||||||
"github.com/gin-contrib/cors"
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"github.com/rocboss/paopao-ce/internal/conf"
|
|
||||||
"github.com/rocboss/paopao-ce/internal/servants/chain"
|
|
||||||
"github.com/rocboss/paopao-ce/internal/servants/web/routers/api"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
)
|
|
||||||
|
|
||||||
func NewRouter() *gin.Engine {
|
|
||||||
e := gin.New()
|
|
||||||
e.HandleMethodNotAllowed = true
|
|
||||||
e.Use(gin.Logger())
|
|
||||||
e.Use(gin.Recovery())
|
|
||||||
|
|
||||||
// 跨域配置
|
|
||||||
corsConfig := cors.DefaultConfig()
|
|
||||||
corsConfig.AllowAllOrigins = true
|
|
||||||
corsConfig.AddAllowHeaders("Authorization")
|
|
||||||
e.Use(cors.New(corsConfig))
|
|
||||||
|
|
||||||
// 按需注册 docs、静态资源、LocalOSS 路由
|
|
||||||
{
|
|
||||||
registerDocs(e)
|
|
||||||
registerStatick(e)
|
|
||||||
|
|
||||||
cfg.Be("LocalOSS", func() {
|
|
||||||
routeLocalOSS(e)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// v1 group api
|
|
||||||
r := e.Group("/v1")
|
|
||||||
|
|
||||||
// 获取version
|
|
||||||
r.GET("/", api.Version)
|
|
||||||
|
|
||||||
// 用户登录
|
|
||||||
r.POST("/auth/login", api.Login)
|
|
||||||
|
|
||||||
// 用户注册
|
|
||||||
r.POST("/auth/register", api.Register)
|
|
||||||
|
|
||||||
// 获取验证码
|
|
||||||
r.GET("/captcha", api.GetCaptcha)
|
|
||||||
|
|
||||||
// 发送验证码
|
|
||||||
r.POST("/captcha", api.PostCaptcha)
|
|
||||||
|
|
||||||
// 无鉴权路由组
|
|
||||||
noAuthApi := r.Group("/")
|
|
||||||
{
|
|
||||||
// 获取动态详情
|
|
||||||
noAuthApi.GET("/post", api.GetPost)
|
|
||||||
|
|
||||||
// 获取动态评论
|
|
||||||
noAuthApi.GET("/post/comments", api.GetPostComments)
|
|
||||||
|
|
||||||
// 获取话题列表
|
|
||||||
noAuthApi.GET("/tags", api.GetPostTags)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 宽松鉴权路由组
|
|
||||||
looseApi := r.Group("/").Use(chain.JwtLoose())
|
|
||||||
{
|
|
||||||
// 获取广场流
|
|
||||||
looseApi.GET("/posts", api.GetPostList)
|
|
||||||
|
|
||||||
// 获取用户动态列表
|
|
||||||
looseApi.GET("/user/posts", api.GetUserPosts)
|
|
||||||
|
|
||||||
// 获取用户基本信息
|
|
||||||
looseApi.GET("/user/profile", api.GetUserProfile)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 鉴权路由组
|
|
||||||
authApi := r.Group("/").Use(chain.JWT())
|
|
||||||
privApi := r.Group("/").Use(chain.JWT()).Use(chain.Priv())
|
|
||||||
adminApi := r.Group("/").Use(chain.JWT()).Use(chain.Admin())
|
|
||||||
|
|
||||||
// 核心路由注册
|
|
||||||
routeCore(authApi, privApi, adminApi)
|
|
||||||
|
|
||||||
// 支付宝路由注册
|
|
||||||
cfg.Be("Alipay", func() {
|
|
||||||
routeAlipay(r, authApi)
|
|
||||||
})
|
|
||||||
|
|
||||||
// Relationship相关路由注册
|
|
||||||
routeRelationship(authApi)
|
|
||||||
|
|
||||||
// 默认404
|
|
||||||
e.NoRoute(func(c *gin.Context) {
|
|
||||||
c.JSON(http.StatusNotFound, gin.H{
|
|
||||||
"code": 404,
|
|
||||||
"msg": "Not Found",
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
// 默认405
|
|
||||||
e.NoMethod(func(c *gin.Context) {
|
|
||||||
c.JSON(http.StatusMethodNotAllowed, gin.H{
|
|
||||||
"code": 405,
|
|
||||||
"msg": "Method Not Allowed",
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
return e
|
|
||||||
}
|
|
||||||
|
|
||||||
func RegisterRoute(e *gin.Engine) {
|
|
||||||
// 按需注册 Web前端静态资源
|
|
||||||
cfg.Be("Frontend:EmbedWeb", func() {
|
|
||||||
registerStatick(e)
|
|
||||||
})
|
|
||||||
|
|
||||||
// 按需注册 LocalOSS 路由
|
|
||||||
cfg.Be("LocalOSS", func() {
|
|
||||||
routeLocalOSS(e)
|
|
||||||
})
|
|
||||||
|
|
||||||
// v1 group api
|
|
||||||
r := e.Group("/v1")
|
|
||||||
|
|
||||||
// 获取version
|
|
||||||
r.GET("/", api.Version)
|
|
||||||
|
|
||||||
// 用户登录
|
|
||||||
r.POST("/auth/login", api.Login)
|
|
||||||
|
|
||||||
// 用户注册
|
|
||||||
r.POST("/auth/register", api.Register)
|
|
||||||
|
|
||||||
// 获取验证码
|
|
||||||
r.GET("/captcha", api.GetCaptcha)
|
|
||||||
|
|
||||||
// 发送验证码
|
|
||||||
r.POST("/captcha", api.PostCaptcha)
|
|
||||||
|
|
||||||
// 无鉴权路由组
|
|
||||||
noAuthApi := r.Group("/")
|
|
||||||
{
|
|
||||||
// 获取动态详情
|
|
||||||
noAuthApi.GET("/post", api.GetPost)
|
|
||||||
|
|
||||||
// 获取动态评论
|
|
||||||
noAuthApi.GET("/post/comments", api.GetPostComments)
|
|
||||||
|
|
||||||
// 获取话题列表
|
|
||||||
noAuthApi.GET("/tags", api.GetPostTags)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 宽松鉴权路由组
|
|
||||||
looseApi := r.Group("/").Use(chain.JwtLoose())
|
|
||||||
{
|
|
||||||
// 获取广场流
|
|
||||||
looseApi.GET("/posts", api.GetPostList)
|
|
||||||
|
|
||||||
// 获取用户动态列表
|
|
||||||
looseApi.GET("/user/posts", api.GetUserPosts)
|
|
||||||
|
|
||||||
// 获取用户基本信息
|
|
||||||
looseApi.GET("/user/profile", api.GetUserProfile)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 鉴权路由组
|
|
||||||
authApi := r.Group("/").Use(chain.JWT())
|
|
||||||
privApi := r.Group("/").Use(chain.JWT()).Use(chain.Priv())
|
|
||||||
adminApi := r.Group("/").Use(chain.JWT()).Use(chain.Admin())
|
|
||||||
|
|
||||||
// 核心路由注册
|
|
||||||
routeCore(authApi, privApi, adminApi)
|
|
||||||
|
|
||||||
// 支付宝路由注册
|
|
||||||
cfg.Be("Alipay", func() {
|
|
||||||
routeAlipay(r, authApi)
|
|
||||||
})
|
|
||||||
|
|
||||||
// Relationship相关路由注册
|
|
||||||
routeRelationship(authApi)
|
|
||||||
}
|
|
||||||
|
|
||||||
func routeCore(authApi gin.IRoutes, privApi gin.IRoutes, adminApi gin.IRoutes) {
|
|
||||||
// 同步索引
|
|
||||||
authApi.GET("/sync/index", api.SyncSearchIndex)
|
|
||||||
|
|
||||||
// 获取当前用户信息
|
|
||||||
authApi.GET("/user/info", api.GetUserInfo)
|
|
||||||
|
|
||||||
// 获取当前用户未读消息数量
|
|
||||||
authApi.GET("/user/msgcount/unread", api.GetUnreadMsgCount)
|
|
||||||
|
|
||||||
// 获取消息列表
|
|
||||||
authApi.GET("/user/messages", api.GetMessages)
|
|
||||||
|
|
||||||
// 标记消息已读
|
|
||||||
authApi.POST("/user/message/read", api.ReadMessage)
|
|
||||||
|
|
||||||
// 发送用户私信
|
|
||||||
authApi.POST("/user/whisper", api.SendUserWhisper)
|
|
||||||
|
|
||||||
// 获取用户收藏列表
|
|
||||||
authApi.GET("/user/collections", api.GetUserCollections)
|
|
||||||
|
|
||||||
// 获取用户点赞列表
|
|
||||||
authApi.GET("/user/stars", api.GetUserStars)
|
|
||||||
|
|
||||||
// 绑定用户手机号
|
|
||||||
authApi.POST("/user/phone", api.BindUserPhone)
|
|
||||||
|
|
||||||
// 修改密码
|
|
||||||
authApi.POST("/user/password", api.ChangeUserPassword)
|
|
||||||
|
|
||||||
// 修改昵称
|
|
||||||
authApi.POST("/user/nickname", api.ChangeNickname)
|
|
||||||
|
|
||||||
// 修改头像
|
|
||||||
authApi.POST("/user/avatar", api.ChangeAvatar)
|
|
||||||
|
|
||||||
// 检索用户
|
|
||||||
authApi.GET("/suggest/users", api.GetSuggestUsers)
|
|
||||||
|
|
||||||
// 检索标签
|
|
||||||
authApi.GET("/suggest/tags", api.GetSuggestTags)
|
|
||||||
|
|
||||||
// 上传资源
|
|
||||||
privApi.POST("/attachment", api.UploadAttachment)
|
|
||||||
|
|
||||||
// 下载资源预检
|
|
||||||
privApi.GET("/attachment/precheck", api.DownloadAttachmentPrecheck)
|
|
||||||
|
|
||||||
// 下载资源
|
|
||||||
privApi.GET("/attachment", api.DownloadAttachment)
|
|
||||||
|
|
||||||
// 发布动态
|
|
||||||
privApi.POST("/post", api.CreatePost)
|
|
||||||
|
|
||||||
// 删除动态
|
|
||||||
privApi.DELETE("/post", api.DeletePost)
|
|
||||||
|
|
||||||
// 获取动态点赞状态
|
|
||||||
authApi.GET("/post/star", api.GetPostStar)
|
|
||||||
|
|
||||||
// 动态点赞操作
|
|
||||||
privApi.POST("/post/star", api.PostStar)
|
|
||||||
|
|
||||||
// 获取动态收藏状态
|
|
||||||
authApi.GET("/post/collection", api.GetPostCollection)
|
|
||||||
|
|
||||||
// 动态收藏操作
|
|
||||||
privApi.POST("/post/collection", api.PostCollection)
|
|
||||||
|
|
||||||
// 锁定动态
|
|
||||||
privApi.POST("/post/lock", api.LockPost)
|
|
||||||
|
|
||||||
// 置顶动态
|
|
||||||
privApi.POST("/post/stick", api.StickPost)
|
|
||||||
|
|
||||||
// 修改动态可见度
|
|
||||||
privApi.POST("/post/visibility", api.VisiblePost)
|
|
||||||
|
|
||||||
// 发布动态评论
|
|
||||||
privApi.POST("/post/comment", api.CreatePostComment)
|
|
||||||
|
|
||||||
// 删除动态评论
|
|
||||||
privApi.DELETE("/post/comment", api.DeletePostComment)
|
|
||||||
|
|
||||||
// 发布评论回复
|
|
||||||
privApi.POST("/post/comment/reply", api.CreatePostCommentReply)
|
|
||||||
|
|
||||||
// 删除评论回复
|
|
||||||
privApi.DELETE("/post/comment/reply", api.DeletePostCommentReply)
|
|
||||||
|
|
||||||
// 管理·禁言/解封用户
|
|
||||||
adminApi.POST("/admin/user/status", api.ChangeUserStatus)
|
|
||||||
}
|
|
||||||
|
|
||||||
// routeLocalOSS register LocalOSS route if needed
|
|
||||||
func routeLocalOSS(e *gin.Engine) {
|
|
||||||
savePath, err := filepath.Abs(conf.LocalOSSSetting.SavePath)
|
|
||||||
if err != nil {
|
|
||||||
logrus.Fatalf("get localOSS save path err: %v", err)
|
|
||||||
}
|
|
||||||
e.Static("/oss", savePath)
|
|
||||||
|
|
||||||
logrus.Infof("register LocalOSS route in /oss on save path: %s", savePath)
|
|
||||||
}
|
|
||||||
|
|
||||||
// routeAlipay register Alipay feature releated route if needed
|
|
||||||
func routeAlipay(public gin.IRoutes, authApi gin.IRoutes) {
|
|
||||||
// 支付宝回调
|
|
||||||
public.POST("/alipay/notify", api.AlipayNotify)
|
|
||||||
|
|
||||||
// 用户充值
|
|
||||||
authApi.POST("/user/recharge", api.GetUserRechargeLink)
|
|
||||||
|
|
||||||
// 获取钱包余额
|
|
||||||
authApi.GET("/user/recharge", api.GetUserRechargeResult)
|
|
||||||
|
|
||||||
// 获取用户账单
|
|
||||||
authApi.GET("/user/wallet/bills", api.GetUserWalletBills)
|
|
||||||
}
|
|
||||||
|
|
||||||
// routeRelationship register Relationship releated routes
|
|
||||||
func routeRelationship(authApi gin.IRoutes) {
|
|
||||||
cfg.In(cfg.Actions{
|
|
||||||
"Friendship": func() {
|
|
||||||
routeFriendship(authApi)
|
|
||||||
},
|
|
||||||
"Followship": func() {
|
|
||||||
routeFollowship(authApi)
|
|
||||||
},
|
|
||||||
}, func() {
|
|
||||||
// 暂时默认使用好友模式
|
|
||||||
// TODO: 后期提供一种无关系模式(既不是好友模式也不是关注者模式)作为默认的关系模式
|
|
||||||
routeFriendship(authApi)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// routeFriendship register Friendship feature releated routes
|
|
||||||
func routeFriendship(authApi gin.IRoutes) {
|
|
||||||
// 请求添加朋友
|
|
||||||
authApi.POST("/friend/requesting", api.RequestingFriend)
|
|
||||||
|
|
||||||
// 同意添加好友
|
|
||||||
authApi.POST("/friend/add", api.AddFriend)
|
|
||||||
|
|
||||||
// 拒绝添加好友
|
|
||||||
authApi.POST("/friend/reject", api.RejectFriend)
|
|
||||||
|
|
||||||
// 删除好友
|
|
||||||
authApi.POST("/friend/delete", api.DeleteFriend)
|
|
||||||
|
|
||||||
// 获取好友列表
|
|
||||||
authApi.GET("/user/contacts", api.GetContacts)
|
|
||||||
}
|
|
||||||
|
|
||||||
// routeFollowship register Followship feature releated routes
|
|
||||||
func routeFollowship(authApi gin.IRoutes) {
|
|
||||||
// TODO: register followship routes
|
|
||||||
}
|
|
@ -1,17 +0,0 @@
|
|||||||
// Copyright 2022 ROC. All rights reserved.
|
|
||||||
// Use of this source code is governed by a MIT style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
//go:build !embed
|
|
||||||
// +build !embed
|
|
||||||
|
|
||||||
package routers
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
)
|
|
||||||
|
|
||||||
// registerStatick stub function for register static asset route
|
|
||||||
func registerStatick(e *gin.Engine) {
|
|
||||||
// empty
|
|
||||||
}
|
|
@ -1,31 +0,0 @@
|
|||||||
// Copyright 2022 ROC. All rights reserved.
|
|
||||||
// Use of this source code is governed by a MIT style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
//go:build embed
|
|
||||||
// +build embed
|
|
||||||
|
|
||||||
package routers
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/http"
|
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"github.com/rocboss/paopao-ce/web"
|
|
||||||
)
|
|
||||||
|
|
||||||
// registerStatick register static assets route
|
|
||||||
func registerStatick(e *gin.Engine) {
|
|
||||||
routeStatic(e, "/", "/index.html", "/favicon.ico", "/assets/*filepath")
|
|
||||||
}
|
|
||||||
|
|
||||||
func routeStatic(e *gin.Engine, paths ...string) {
|
|
||||||
staticHandler := http.FileServer(web.NewFileSystem())
|
|
||||||
handler := func(c *gin.Context) {
|
|
||||||
staticHandler.ServeHTTP(c.Writer, c.Request)
|
|
||||||
}
|
|
||||||
for _, path := range paths {
|
|
||||||
e.GET(path, handler)
|
|
||||||
e.HEAD(path, handler)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,63 +0,0 @@
|
|||||||
// Copyright 2022 ROC. All rights reserved.
|
|
||||||
// Use of this source code is governed by a MIT style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package service
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
|
|
||||||
"github.com/Masterminds/semver/v3"
|
|
||||||
"github.com/fatih/color"
|
|
||||||
"github.com/rocboss/paopao-ce/internal/conf"
|
|
||||||
"github.com/rocboss/paopao-ce/internal/servants/web/routers"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
_ Service = (*oldWebService)(nil)
|
|
||||||
)
|
|
||||||
|
|
||||||
type oldWebService struct {
|
|
||||||
*baseHttpService
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *oldWebService) Name() string {
|
|
||||||
return "OldWebService"
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *oldWebService) Version() *semver.Version {
|
|
||||||
return semver.MustParse("v0.1.0")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *oldWebService) OnInit() error {
|
|
||||||
s.registerRoute(s, routers.RegisterRoute)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *oldWebService) String() string {
|
|
||||||
return fmt.Sprintf("listen on %s\n", color.GreenString("http://%s:%s", conf.ServerSetting.HttpIp, conf.ServerSetting.HttpPort))
|
|
||||||
}
|
|
||||||
|
|
||||||
func newOldWebService() Service {
|
|
||||||
addr := conf.ServerSetting.HttpIp + ":" + conf.ServerSetting.HttpPort
|
|
||||||
server := httpServers.from(addr, func() *httpServer {
|
|
||||||
engine := newWebEngine()
|
|
||||||
return &httpServer{
|
|
||||||
baseServer: newBaseServe(),
|
|
||||||
e: engine,
|
|
||||||
server: &http.Server{
|
|
||||||
Addr: addr,
|
|
||||||
Handler: engine,
|
|
||||||
ReadTimeout: conf.ServerSetting.GetReadTimeout(),
|
|
||||||
WriteTimeout: conf.ServerSetting.GetWriteTimeout(),
|
|
||||||
MaxHeaderBytes: 1 << 20,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
})
|
|
||||||
return &oldWebService{
|
|
||||||
baseHttpService: &baseHttpService{
|
|
||||||
server: server,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,79 +0,0 @@
|
|||||||
// Copyright 2022 ROC. All rights reserved.
|
|
||||||
// Use of this source code is governed by a MIT style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package errcode
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Error struct {
|
|
||||||
code int
|
|
||||||
msg string
|
|
||||||
details []string
|
|
||||||
}
|
|
||||||
|
|
||||||
var codes = map[int]string{}
|
|
||||||
|
|
||||||
func NewError(code int, msg string) *Error {
|
|
||||||
if _, ok := codes[code]; ok {
|
|
||||||
panic(fmt.Sprintf("错误码 %d 已经存在,请更换一个", code))
|
|
||||||
}
|
|
||||||
codes[code] = msg
|
|
||||||
return &Error{code: code, msg: msg}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *Error) Error() string {
|
|
||||||
return fmt.Sprintf("错误码: %d, 错误信息: %s", e.Code(), e.Msg())
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *Error) Code() int {
|
|
||||||
return e.code
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *Error) Msg() string {
|
|
||||||
return e.msg
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *Error) Msgf(args []any) string {
|
|
||||||
return fmt.Sprintf(e.msg, args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *Error) Details() []string {
|
|
||||||
return e.details
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *Error) WithDetails(details ...string) *Error {
|
|
||||||
newError := *e
|
|
||||||
newError.details = []string{}
|
|
||||||
newError.details = append(newError.details, details...)
|
|
||||||
|
|
||||||
return &newError
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *Error) StatusCode() int {
|
|
||||||
switch e.Code() {
|
|
||||||
case Success.Code():
|
|
||||||
return http.StatusOK
|
|
||||||
case ServerError.Code():
|
|
||||||
return http.StatusInternalServerError
|
|
||||||
case InvalidParams.Code():
|
|
||||||
return http.StatusBadRequest
|
|
||||||
case UnauthorizedAuthNotExist.Code():
|
|
||||||
fallthrough
|
|
||||||
case UnauthorizedAuthFailed.Code():
|
|
||||||
fallthrough
|
|
||||||
case UnauthorizedTokenError.Code():
|
|
||||||
fallthrough
|
|
||||||
case UnauthorizedTokenGenerate.Code():
|
|
||||||
fallthrough
|
|
||||||
case UnauthorizedTokenTimeout.Code():
|
|
||||||
return http.StatusUnauthorized
|
|
||||||
case TooManyRequests.Code():
|
|
||||||
return http.StatusTooManyRequests
|
|
||||||
}
|
|
||||||
|
|
||||||
return http.StatusInternalServerError
|
|
||||||
}
|
|
@ -1,73 +0,0 @@
|
|||||||
// Copyright 2022 ROC. All rights reserved.
|
|
||||||
// Use of this source code is governed by a MIT style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package errcode
|
|
||||||
|
|
||||||
var (
|
|
||||||
UsernameHasExisted = NewError(20001, "用户名已存在")
|
|
||||||
UsernameLengthLimit = NewError(20002, "用户名长度3~12")
|
|
||||||
UsernameCharLimit = NewError(20003, "用户名只能包含字母、数字")
|
|
||||||
PasswordLengthLimit = NewError(20004, "密码长度6~16")
|
|
||||||
UserRegisterFailed = NewError(20005, "用户注册失败")
|
|
||||||
UserHasBeenBanned = NewError(20006, "该账户已被封停")
|
|
||||||
NoPermission = NewError(20007, "无权限执行该请求")
|
|
||||||
UserHasBindOTP = NewError(20008, "当前用户已绑定二次验证")
|
|
||||||
UserOTPInvalid = NewError(20009, "二次验证码验证失败")
|
|
||||||
UserNoBindOTP = NewError(20010, "当前用户未绑定二次验证")
|
|
||||||
ErrorOldPassword = NewError(20011, "当前用户密码验证失败")
|
|
||||||
ErrorCaptchaPassword = NewError(20012, "图形验证码验证失败")
|
|
||||||
AccountNoPhoneBind = NewError(20013, "拒绝操作: 账户未绑定手机号")
|
|
||||||
TooManyLoginError = NewError(20014, "登录失败次数过多,请稍后再试")
|
|
||||||
GetPhoneCaptchaError = NewError(20015, "短信验证码获取失败")
|
|
||||||
TooManyPhoneCaptchaSend = NewError(20016, "短信验证码获取次数已达今日上限")
|
|
||||||
ExistedUserPhone = NewError(20017, "该手机号已被绑定")
|
|
||||||
ErrorPhoneCaptcha = NewError(20018, "手机验证码不正确")
|
|
||||||
MaxPhoneCaptchaUseTimes = NewError(20019, "手机验证码已达最大使用次数")
|
|
||||||
NicknameLengthLimit = NewError(20020, "昵称长度2~12")
|
|
||||||
NoExistUsername = NewError(20021, "用户不存在")
|
|
||||||
NoAdminPermission = NewError(20022, "无管理权限")
|
|
||||||
|
|
||||||
GetPostsFailed = NewError(30001, "获取动态列表失败")
|
|
||||||
CreatePostFailed = NewError(30002, "动态发布失败")
|
|
||||||
GetPostFailed = NewError(30003, "获取动态详情失败")
|
|
||||||
DeletePostFailed = NewError(30004, "动态删除失败")
|
|
||||||
LockPostFailed = NewError(30005, "动态锁定失败")
|
|
||||||
GetPostTagsFailed = NewError(30006, "获取话题列表失败")
|
|
||||||
InvalidDownloadReq = NewError(30007, "附件下载请求不合法")
|
|
||||||
DownloadReqError = NewError(30008, "附件下载请求失败")
|
|
||||||
InsuffientDownloadMoney = NewError(30009, "附件下载失败:账户资金不足")
|
|
||||||
DownloadExecFail = NewError(30010, "附件下载失败:扣费失败")
|
|
||||||
StickPostFailed = NewError(30011, "动态置顶失败")
|
|
||||||
VisblePostFailed = NewError(30012, "更新可见性失败")
|
|
||||||
|
|
||||||
GetCommentsFailed = NewError(40001, "获取评论列表失败")
|
|
||||||
CreateCommentFailed = NewError(40002, "评论发布失败")
|
|
||||||
GetCommentFailed = NewError(40003, "获取评论详情失败")
|
|
||||||
DeleteCommentFailed = NewError(40004, "评论删除失败")
|
|
||||||
CreateReplyFailed = NewError(40005, "评论回复失败")
|
|
||||||
GetReplyFailed = NewError(40006, "获取评论详情失败")
|
|
||||||
MaxCommentCount = NewError(40007, "评论数已达最大限制")
|
|
||||||
|
|
||||||
GetMessagesFailed = NewError(50001, "获取消息列表失败")
|
|
||||||
ReadMessageFailed = NewError(50002, "标记消息已读失败")
|
|
||||||
SendWhisperFailed = NewError(50003, "私信发送失败")
|
|
||||||
NoWhisperToSelf = NewError(50004, "不允许给自己发送私信")
|
|
||||||
TooManyWhisperNum = NewError(50005, "今日私信次数已达上限")
|
|
||||||
|
|
||||||
GetCollectionsFailed = NewError(60001, "获取收藏列表失败")
|
|
||||||
GetStarsFailed = NewError(60002, "获取点赞列表失败")
|
|
||||||
|
|
||||||
RechargeReqFail = NewError(70001, "充值请求失败")
|
|
||||||
RechargeNotifyError = NewError(70002, "充值回调失败")
|
|
||||||
GetRechargeFailed = NewError(70003, "充值详情获取失败")
|
|
||||||
|
|
||||||
NoRequestingFriendToSelf = NewError(80001, "不允许添加自己为好友")
|
|
||||||
NotExistFriendId = NewError(80002, "好友id不存在")
|
|
||||||
SendRequestingFriendFailed = NewError(80003, "申请添加朋友请求发送失败")
|
|
||||||
AddFriendFailed = NewError(80004, "添加好友失败")
|
|
||||||
RejectFriendFailed = NewError(80005, "拒绝好友失败")
|
|
||||||
DeleteFriendFailed = NewError(80006, "删除好友失败")
|
|
||||||
GetContactsFailed = NewError(80007, "获取联系人列表失败")
|
|
||||||
NoActionToSelf = NewError(80008, "不允许对自己操作")
|
|
||||||
)
|
|
Loading…
Reference in new issue