This commit is contained in:
awei
2025-03-03 17:43:50 +08:00
commit 113756eaae
1497 changed files with 127997 additions and 0 deletions

View File

@@ -0,0 +1,283 @@
package eventhandler
import (
"bbs-go/internal/models"
"bbs-go/internal/models/constants"
"bbs-go/internal/pkg/common"
"bbs-go/internal/pkg/event"
"bbs-go/internal/pkg/msg"
"bbs-go/internal/services"
"log/slog"
"reflect"
"github.com/spf13/cast"
)
func init() {
event.RegHandler(reflect.TypeOf(event.CommentCreateEvent{}), handleCommentCreate)
}
func handleCommentCreate(i interface{}) {
e := i.(event.CommentCreateEvent)
comment := services.CommentService.Get(e.CommentId)
// 发送消息
handleMsg(comment)
}
// 处理评论消息
func handleMsg(comment *models.Comment) {
commentMsg := getCommentMsg(comment)
handleEntityMsg(comment, commentMsg)
handleQuoteMsg(comment, commentMsg)
handleReplyMsg(comment, commentMsg)
}
// 给被回复的实体对象作者发送消息
func handleEntityMsg(comment *models.Comment, commentMsg *CommentMsg) {
var (
from = comment.UserId
to = commentMsg.rootEntityUserId()
)
if from == to {
return
}
if to <= 0 {
slog.Warn("消息发送失败", slog.Any("to", to))
return
}
// 如果回复的评论作者就是帖子作者,那么只给回复作者发消息即可,这里就不再给帖子作者发消息了
if commentMsg.ParentComment != nil && commentMsg.ParentComment.UserId == to {
return
}
// 同上
if commentMsg.QuoteComment != nil && commentMsg.QuoteComment.UserId == to {
return
}
services.MessageService.SendMsg(from, to,
commentMsg.msgType(),
commentMsg.msgTitle(),
commentMsg.msgContent(),
commentMsg.msgRepliedContent(),
&msg.CommentExtraData{
EntityType: commentMsg.EntityType,
EntityId: commentMsg.EntityId,
QuoteId: comment.QuoteId,
RootEntityType: commentMsg.rootEntityType(),
RootEntityId: cast.ToString(commentMsg.rootEntityId()),
})
}
func handleReplyMsg(comment *models.Comment, commentMsg *CommentMsg) {
if commentMsg.ParentComment == nil {
return
}
var (
from = comment.UserId
to = commentMsg.ParentComment.UserId
)
if from == to {
return
}
// 如果回复的评论作者就是被引用消息的作者作者,那么只发引用消息即可
if commentMsg.QuoteComment != nil && commentMsg.QuoteComment.UserId == to {
return
}
var (
title = commentMsg.msgTitle()
content = commentMsg.msgContent()
repliedContent = common.GetSummary(commentMsg.ParentComment.ContentType, commentMsg.ParentComment.Content)
)
services.MessageService.SendMsg(from, to, msg.TypeCommentReply, title, content, repliedContent,
&msg.CommentExtraData{
EntityType: comment.EntityType,
EntityId: comment.EntityId,
QuoteId: comment.QuoteId,
RootEntityType: commentMsg.rootEntityType(),
RootEntityId: cast.ToString(commentMsg.rootEntityId()),
})
}
// handleQuoteMsg 给被引用人发送消息
func handleQuoteMsg(comment *models.Comment, commentMsg *CommentMsg) {
if commentMsg.QuoteComment == nil {
return
}
var (
from = comment.UserId
to = commentMsg.QuoteComment.UserId
title = commentMsg.msgTitle()
content = commentMsg.msgContent()
repliedContent = common.GetSummary(commentMsg.QuoteComment.ContentType, commentMsg.QuoteComment.Content)
)
if from == to {
return
}
services.MessageService.SendMsg(from, to, msg.TypeCommentReply, title, content, repliedContent,
&msg.CommentExtraData{
EntityType: comment.EntityType,
EntityId: comment.EntityId,
QuoteId: comment.QuoteId,
RootEntityType: commentMsg.rootEntityType(),
RootEntityId: cast.ToString(commentMsg.rootEntityId()),
})
}
func getCommentMsg(comment *models.Comment) *CommentMsg {
if comment.EntityType == constants.EntityTopic { // 帖子
topic := services.TopicService.Get(comment.EntityId)
if topic != nil && topic.Status == constants.StatusOk {
return &CommentMsg{
Comment: comment,
EntityType: comment.EntityType,
EntityId: comment.EntityId,
Entity: topic,
}
}
} else if comment.EntityType == constants.EntityArticle { // 文章
article := services.ArticleService.Get(comment.EntityId)
if article != nil && article.Status == constants.StatusOk {
return &CommentMsg{
Comment: comment,
EntityType: comment.EntityType,
EntityId: comment.EntityId,
Entity: article,
}
}
} else if comment.EntityType == constants.EntityComment { // 二级评论
parentComment := services.CommentService.Get(comment.EntityId)
if parentComment == nil || parentComment.Status != constants.StatusOk {
return nil
}
ret := &CommentMsg{
Comment: comment,
EntityType: parentComment.EntityType, // 二级评论时,取一级评论的
EntityId: parentComment.EntityId, // 二级评论时,取一级评论的
ParentComment: parentComment, // 一级评论
}
if parentComment.EntityType == constants.EntityTopic {
topic := services.TopicService.Get(parentComment.EntityId)
if topic != nil && topic.Status == constants.StatusOk {
ret.Entity = topic
}
} else if parentComment.EntityType == constants.EntityArticle {
article := services.ArticleService.Get(parentComment.EntityId)
if article != nil && article.Status == constants.StatusOk {
ret.Entity = article
}
} else {
return nil
}
if comment.QuoteId > 0 { // 三级评论
quoteComment := services.CommentService.Get(comment.QuoteId)
if quoteComment != nil && quoteComment.Status == constants.StatusOk {
ret.QuoteComment = quoteComment
}
}
return ret
}
return nil
}
type CommentMsg struct {
EntityType string // 实体类型
EntityId int64 // 实体ID
Entity interface{} // 被评论实体
Comment *models.Comment // 当前评论
ParentComment *models.Comment // 上一级评论(二级评论的时候有值)
QuoteComment *models.Comment // 引用评论
}
// msgType 消息类型
func (c *CommentMsg) msgType() msg.Type {
if c.EntityType == constants.EntityTopic {
return msg.TypeTopicComment
} else if c.EntityType == constants.EntityArticle {
return msg.TypeArticleComment
} else if c.EntityType == constants.EntityComment {
return msg.TypeCommentReply
}
return msg.TypeTopicComment
}
// msgTitle 消息标题
func (c *CommentMsg) msgTitle() string {
if c.EntityType == constants.EntityTopic {
return "回复了你的话题"
} else if c.EntityType == constants.EntityArticle {
return "回复了你的文章"
} else if c.EntityType == constants.EntityComment {
return "回复了你的评论"
}
return ""
}
// msgContent 回复内容
func (c *CommentMsg) msgContent() string {
return common.GetSummary(c.Comment.ContentType, c.Comment.Content)
}
// msgRepliedContent 被回复的内容
func (c *CommentMsg) msgRepliedContent() string {
if c.EntityType == constants.EntityArticle {
article := c.Entity.(*models.Article)
return "《" + article.Title + "》"
} else if c.EntityType == constants.EntityTopic {
topic := c.Entity.(*models.Topic)
return "《" + topic.GetTitle() + "》"
}
return ""
}
func (c *CommentMsg) rootEntityUserId() int64 {
if c.ParentComment != nil { // 二级评论
if c.ParentComment.EntityType == constants.EntityTopic {
topic := c.Entity.(*models.Topic)
return topic.UserId
} else if c.ParentComment.EntityType == constants.EntityArticle {
article := c.Entity.(*models.Article)
return article.UserId
}
} else {
if c.Comment.EntityType == constants.EntityTopic {
topic := c.Entity.(*models.Topic)
return topic.UserId
} else if c.Comment.EntityType == constants.EntityArticle {
article := c.Entity.(*models.Article)
return article.UserId
}
}
return 0
}
func (c *CommentMsg) rootEntityType() string {
if c.ParentComment != nil { // 二级评论
return c.ParentComment.EntityType
} else {
return c.Comment.EntityType
}
}
func (c *CommentMsg) rootEntityId() int64 {
if c.ParentComment != nil { // 二级评论
return c.ParentComment.EntityId
} else {
return c.Comment.EntityId
}
}

View File

@@ -0,0 +1,33 @@
package eventhandler
import (
"bbs-go/internal/models"
"bbs-go/internal/models/constants"
"bbs-go/internal/pkg/event"
"bbs-go/internal/services"
"reflect"
)
func init() {
event.RegHandler(reflect.TypeOf(event.FollowEvent{}), handleFollowEvent)
}
func handleFollowEvent(i interface{}) {
e := i.(event.FollowEvent)
// 将该用户下的帖子添加到信息流
services.TopicService.ScanByUser(e.OtherId, func(topics []models.Topic) {
for _, topic := range topics {
if topic.Status != constants.StatusOk {
continue
}
_ = services.UserFeedService.Create(&models.UserFeed{
UserId: e.UserId,
DataType: constants.EntityTopic,
DataId: topic.Id,
AuthorId: topic.UserId,
CreateTime: topic.CreateTime,
})
}
})
}

View File

@@ -0,0 +1,36 @@
package eventhandler
import (
"bbs-go/internal/models"
"bbs-go/internal/models/constants"
"bbs-go/internal/pkg/bbsurls"
"bbs-go/internal/pkg/event"
"bbs-go/internal/pkg/seo"
"bbs-go/internal/services"
"log/slog"
"reflect"
)
func init() {
event.RegHandler(reflect.TypeOf(event.TopicCreateEvent{}), handleTopicCreateEvent)
}
func handleTopicCreateEvent(i interface{}) {
e := i.(event.TopicCreateEvent)
services.UserFollowService.ScanFans(e.UserId, func(fansId int64) {
slog.With(slog.Any("topicId", e.TopicId), slog.Any("userId", e.UserId), slog.Any("fansId", fansId)).Info("用户关注,处理帖子")
if err := services.UserFeedService.Create(&models.UserFeed{
UserId: fansId,
DataId: e.TopicId,
DataType: constants.EntityTopic,
AuthorId: e.UserId,
CreateTime: e.CreateTime,
}); err != nil {
slog.Error(err.Error(), slog.Any("err", err))
}
})
// 百度链接推送
seo.Push(bbsurls.TopicUrl(e.TopicId))
}

View File

@@ -0,0 +1,53 @@
package eventhandler
import (
"bbs-go/internal/models/constants"
"bbs-go/internal/pkg/event"
"bbs-go/internal/pkg/msg"
"bbs-go/internal/repositories"
"bbs-go/internal/services"
"reflect"
"github.com/mlogclub/simple/sqls"
)
func init() {
event.RegHandler(reflect.TypeOf(event.TopicDeleteEvent{}), handleTopicDeleteEvent)
}
func handleTopicDeleteEvent(i interface{}) {
e := i.(event.TopicDeleteEvent)
// 处理userFeed
services.UserFeedService.DeleteByDataId(e.TopicId, constants.EntityTopic)
// 发送消息
sendTopicDeleteMsg(e.TopicId, e.DeleteUserId)
// 操作日志
services.OperateLogService.AddOperateLog(e.DeleteUserId, constants.OpTypeDelete, constants.EntityTopic,
e.TopicId, "", nil)
}
// sendTopicDeleteMsg 话题被删除消息
func sendTopicDeleteMsg(topicId, deleteUserId int64) {
topic := repositories.TopicRepository.Get(sqls.DB(), topicId)
if topic == nil {
return
}
if topic.UserId == deleteUserId {
return
}
var (
from int64 = 0
to = topic.UserId
title = "你的话题被删除"
quoteContent = "《" + topic.GetTitle() + "》"
)
services.MessageService.SendMsg(from, to, msg.TypeTopicDelete, title, "", quoteContent,
&msg.TopicDeleteExtraData{
TopicId: topicId,
DeleteUserId: deleteUserId,
},
)
}

View File

@@ -0,0 +1,39 @@
package eventhandler
import (
"bbs-go/internal/models/constants"
"bbs-go/internal/pkg/event"
"bbs-go/internal/pkg/msg"
"bbs-go/internal/services"
"reflect"
)
func init() {
event.RegHandler(reflect.TypeOf(event.TopicRecommendEvent{}), handleTopicRecommend)
}
func handleTopicRecommend(i interface{}) {
e := i.(event.TopicRecommendEvent)
if e.Recommend {
sendTopicRecommendMsg(e.TopicId)
}
}
// sendTopicRecommendMsg 话题被设为推荐
func sendTopicRecommendMsg(topicId int64) {
topic := services.TopicService.Get(topicId)
if topic == nil || topic.Status != constants.StatusOk {
return
}
var (
from int64 = 0
to = topic.UserId
title = "你的话题被设为推荐"
quoteContent = "《" + topic.GetTitle() + "》"
)
services.MessageService.SendMsg(from, to, msg.TypeTopicRecommend, title, "", quoteContent,
&msg.TopicRecommendExtraData{
TopicId: topicId,
})
}

View File

@@ -0,0 +1,18 @@
package eventhandler
import (
"bbs-go/internal/pkg/event"
"bbs-go/internal/services"
"reflect"
)
func init() {
event.RegHandler(reflect.TypeOf(event.UnFollowEvent{}), handleUnFollowEvent)
}
func handleUnFollowEvent(i interface{}) {
e := i.(event.UnFollowEvent)
// 清理该用户下的信息流
services.UserFeedService.DeleteByUser(e.UserId, e.OtherId)
}

View File

@@ -0,0 +1,45 @@
package eventhandler
import (
"bbs-go/internal/models/constants"
"bbs-go/internal/pkg/event"
"bbs-go/internal/pkg/msg"
"bbs-go/internal/services"
"reflect"
)
func init() {
event.RegHandler(reflect.TypeOf(event.UserFavoriteEvent{}), handleUserFavorite)
}
func handleUserFavorite(i interface{}) {
e := i.(event.UserFavoriteEvent)
if e.EntityType == constants.EntityTopic {
sendTopicFavoriteMsg(e.EntityId, e.UserId)
} else if e.EntityType == constants.EntityArticle {
// TODO
}
}
// sendTopicFavoriteMsg 话题被收藏
func sendTopicFavoriteMsg(topicId, favoriteUserId int64) {
topic := services.TopicService.Get(topicId)
if topic == nil || topic.Status != constants.StatusOk {
return
}
if topic.UserId == favoriteUserId {
return
}
var (
from = favoriteUserId
to = topic.UserId
title = "收藏了你的话题"
quoteContent = "《" + topic.GetTitle() + "》"
)
services.MessageService.SendMsg(from, to, msg.TypeTopicFavorite, title, "", quoteContent,
&msg.TopicFavoriteExtraData{
TopicId: topicId,
FavoriteUserId: favoriteUserId,
})
}

View File

@@ -0,0 +1,53 @@
package eventhandler
import (
"bbs-go/internal/models/constants"
"bbs-go/internal/pkg/event"
"bbs-go/internal/pkg/msg"
"bbs-go/internal/services"
"reflect"
)
func init() {
event.RegHandler(reflect.TypeOf(event.UserLikeEvent{}), handleUserLike)
event.RegHandler(reflect.TypeOf(event.UserUnLikeEvent{}), handleUserUnLike)
}
func handleUserLike(i interface{}) {
e := i.(event.UserLikeEvent)
if e.EntityType == constants.EntityTopic {
sendTopicLikeMsg(e.EntityId, e.UserId)
} else if e.EntityType == constants.EntityComment {
// TODO
}
}
func handleUserUnLike(i interface{}) {
e := i.(event.UserUnLikeEvent)
if e.EntityType == constants.EntityTopic {
// TODO
}
}
// sendTopicLikeMsg 话题收到点赞
func sendTopicLikeMsg(topicId, likeUserId int64) {
topic := services.TopicService.Get(topicId)
if topic == nil || topic.Status != constants.StatusOk {
return
}
if topic.UserId == likeUserId {
return
}
var (
from = likeUserId
to = topic.UserId
title = "点赞了你的话题"
quoteContent = "《" + topic.GetTitle() + "》"
)
services.MessageService.SendMsg(from, to, msg.TypeTopicLike, title, "", quoteContent,
&msg.TopicLikeExtraData{
TopicId: topicId,
LikeUserId: likeUserId,
})
}