| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| |
| package comment |
| |
| import ( |
| "context" |
| |
| "github.com/apache/answer/internal/service/event_queue" |
| "github.com/apache/answer/internal/service/review" |
| |
| "time" |
| |
| "github.com/apache/answer/internal/base/constant" |
| "github.com/apache/answer/internal/base/pager" |
| "github.com/apache/answer/internal/base/reason" |
| "github.com/apache/answer/internal/entity" |
| "github.com/apache/answer/internal/schema" |
| "github.com/apache/answer/internal/service/activity_common" |
| "github.com/apache/answer/internal/service/activity_queue" |
| "github.com/apache/answer/internal/service/comment_common" |
| "github.com/apache/answer/internal/service/export" |
| "github.com/apache/answer/internal/service/notice_queue" |
| "github.com/apache/answer/internal/service/object_info" |
| "github.com/apache/answer/internal/service/permission" |
| usercommon "github.com/apache/answer/internal/service/user_common" |
| "github.com/apache/answer/pkg/htmltext" |
| "github.com/apache/answer/pkg/token" |
| "github.com/apache/answer/pkg/uid" |
| "github.com/jinzhu/copier" |
| "github.com/segmentfault/pacman/errors" |
| "github.com/segmentfault/pacman/log" |
| ) |
| |
| // CommentRepo comment repository |
| type CommentRepo interface { |
| AddComment(ctx context.Context, comment *entity.Comment) (err error) |
| RemoveComment(ctx context.Context, commentID string) (err error) |
| UpdateCommentContent(ctx context.Context, commentID string, original string, parsedText string) (err error) |
| UpdateCommentStatus(ctx context.Context, commentID string, status int) (err error) |
| GetComment(ctx context.Context, commentID string) (comment *entity.Comment, exist bool, err error) |
| GetCommentPage(ctx context.Context, commentQuery *CommentQuery) ( |
| comments []*entity.Comment, total int64, err error) |
| } |
| |
| type CommentQuery struct { |
| pager.PageCond |
| // object id |
| ObjectID string |
| // query condition |
| QueryCond string |
| // user id |
| UserID string |
| } |
| |
| func (c *CommentQuery) GetOrderBy() string { |
| if c.QueryCond == "vote" { |
| return "vote_count DESC,created_at ASC" |
| } |
| if c.QueryCond == "created_at" { |
| return "created_at DESC" |
| } |
| return "created_at ASC" |
| } |
| |
| // CommentService user service |
| type CommentService struct { |
| commentRepo CommentRepo |
| commentCommonRepo comment_common.CommentCommonRepo |
| userCommon *usercommon.UserCommon |
| voteCommon activity_common.VoteRepo |
| objectInfoService *object_info.ObjService |
| emailService *export.EmailService |
| userRepo usercommon.UserRepo |
| notificationQueueService notice_queue.NotificationQueueService |
| externalNotificationQueueService notice_queue.ExternalNotificationQueueService |
| activityQueueService activity_queue.ActivityQueueService |
| eventQueueService event_queue.EventQueueService |
| reviewService *review.ReviewService |
| } |
| |
| // NewCommentService new comment service |
| func NewCommentService( |
| commentRepo CommentRepo, |
| commentCommonRepo comment_common.CommentCommonRepo, |
| userCommon *usercommon.UserCommon, |
| objectInfoService *object_info.ObjService, |
| voteCommon activity_common.VoteRepo, |
| emailService *export.EmailService, |
| userRepo usercommon.UserRepo, |
| notificationQueueService notice_queue.NotificationQueueService, |
| externalNotificationQueueService notice_queue.ExternalNotificationQueueService, |
| activityQueueService activity_queue.ActivityQueueService, |
| eventQueueService event_queue.EventQueueService, |
| reviewService *review.ReviewService, |
| ) *CommentService { |
| return &CommentService{ |
| commentRepo: commentRepo, |
| commentCommonRepo: commentCommonRepo, |
| userCommon: userCommon, |
| voteCommon: voteCommon, |
| objectInfoService: objectInfoService, |
| emailService: emailService, |
| userRepo: userRepo, |
| notificationQueueService: notificationQueueService, |
| externalNotificationQueueService: externalNotificationQueueService, |
| activityQueueService: activityQueueService, |
| eventQueueService: eventQueueService, |
| reviewService: reviewService, |
| } |
| } |
| |
| // AddComment add comment |
| func (cs *CommentService) AddComment(ctx context.Context, req *schema.AddCommentReq) ( |
| resp *schema.GetCommentResp, err error) { |
| comment := &entity.Comment{} |
| _ = copier.Copy(comment, req) |
| comment.Status = entity.CommentStatusAvailable |
| |
| objInfo, err := cs.objectInfoService.GetInfo(ctx, req.ObjectID) |
| if err != nil { |
| return nil, err |
| } |
| if objInfo.IsDeleted() { |
| return nil, errors.BadRequest(reason.NewObjectAlreadyDeleted) |
| } |
| objInfo.ObjectID = uid.DeShortID(objInfo.ObjectID) |
| objInfo.QuestionID = uid.DeShortID(objInfo.QuestionID) |
| objInfo.AnswerID = uid.DeShortID(objInfo.AnswerID) |
| if objInfo.ObjectType == constant.QuestionObjectType || objInfo.ObjectType == constant.AnswerObjectType { |
| comment.QuestionID = objInfo.QuestionID |
| } |
| |
| if len(req.ReplyCommentID) > 0 { |
| replyComment, exist, err := cs.commentCommonRepo.GetComment(ctx, req.ReplyCommentID) |
| if err != nil { |
| return nil, err |
| } |
| if !exist { |
| return nil, errors.BadRequest(reason.CommentNotFound) |
| } |
| comment.SetReplyUserID(replyComment.UserID) |
| comment.SetReplyCommentID(replyComment.ID) |
| } else { |
| comment.SetReplyUserID("") |
| comment.SetReplyCommentID("") |
| } |
| |
| err = cs.commentRepo.AddComment(ctx, comment) |
| if err != nil { |
| return nil, err |
| } |
| |
| comment.Status = cs.reviewService.AddCommentReview(ctx, comment, req.IP, req.UserAgent) |
| if err := cs.commentRepo.UpdateCommentStatus(ctx, comment.ID, comment.Status); err != nil { |
| return nil, err |
| } |
| |
| resp = &schema.GetCommentResp{} |
| resp.SetFromComment(comment) |
| resp.MemberActions = permission.GetCommentPermission(ctx, req.UserID, resp.UserID, |
| time.Now(), req.CanEdit, req.CanDelete) |
| |
| if comment.Status == entity.CommentStatusAvailable { |
| commentResp, err := cs.addCommentNotification(ctx, req, resp, comment, objInfo) |
| if err != nil { |
| return commentResp, err |
| } |
| } |
| |
| // get user info |
| userInfo, exist, err := cs.userCommon.GetUserBasicInfoByID(ctx, resp.UserID) |
| if err != nil { |
| return nil, err |
| } |
| if exist { |
| resp.Username = userInfo.Username |
| resp.UserDisplayName = userInfo.DisplayName |
| resp.UserAvatar = userInfo.Avatar |
| resp.UserStatus = userInfo.Status |
| } |
| |
| activityMsg := &schema.ActivityMsg{ |
| UserID: comment.UserID, |
| ObjectID: comment.ID, |
| OriginalObjectID: req.ObjectID, |
| ActivityTypeKey: constant.ActQuestionCommented, |
| } |
| var event *schema.EventMsg |
| switch objInfo.ObjectType { |
| case constant.QuestionObjectType: |
| activityMsg.ActivityTypeKey = constant.ActQuestionCommented |
| event = schema.NewEvent(constant.EventCommentCreate, req.UserID).TID(comment.ID). |
| CID(comment.ID, comment.UserID).QID(objInfo.QuestionID, objInfo.ObjectCreatorUserID) |
| case constant.AnswerObjectType: |
| activityMsg.ActivityTypeKey = constant.ActAnswerCommented |
| event = schema.NewEvent(constant.EventCommentCreate, req.UserID).TID(comment.ID). |
| CID(comment.ID, comment.UserID).AID(objInfo.AnswerID, objInfo.ObjectCreatorUserID) |
| } |
| cs.activityQueueService.Send(ctx, activityMsg) |
| cs.eventQueueService.Send(ctx, event) |
| return resp, nil |
| } |
| |
| func (cs *CommentService) addCommentNotification( |
| ctx context.Context, req *schema.AddCommentReq, resp *schema.GetCommentResp, |
| comment *entity.Comment, objInfo *schema.SimpleObjectInfo) (*schema.GetCommentResp, error) { |
| // The priority of the notification |
| // 1. reply to user |
| // 2. comment mention to user |
| // 3. answer or question was commented |
| alreadyNotifiedUserID := make(map[string]bool) |
| |
| // get reply user info |
| if len(resp.ReplyUserID) > 0 && resp.ReplyUserID != req.UserID { |
| replyUser, exist, err := cs.userCommon.GetUserBasicInfoByID(ctx, resp.ReplyUserID) |
| if err != nil { |
| return nil, err |
| } |
| if exist { |
| resp.ReplyUsername = replyUser.Username |
| resp.ReplyUserDisplayName = replyUser.DisplayName |
| resp.ReplyUserStatus = replyUser.Status |
| } |
| cs.notificationCommentReply(ctx, replyUser.ID, comment.ID, req.UserID, |
| objInfo.QuestionID, objInfo.Title, htmltext.FetchExcerpt(comment.ParsedText, "...", 240)) |
| alreadyNotifiedUserID[replyUser.ID] = true |
| return nil, nil |
| } |
| |
| if len(req.MentionUsernameList) > 0 { |
| alreadyNotifiedUserIDs := cs.notificationMention( |
| ctx, req.MentionUsernameList, comment.ID, req.UserID, alreadyNotifiedUserID) |
| for _, userID := range alreadyNotifiedUserIDs { |
| alreadyNotifiedUserID[userID] = true |
| } |
| return nil, nil |
| } |
| |
| if objInfo.ObjectType == constant.QuestionObjectType && !alreadyNotifiedUserID[objInfo.ObjectCreatorUserID] { |
| cs.notificationQuestionComment(ctx, objInfo.ObjectCreatorUserID, |
| objInfo.QuestionID, objInfo.Title, comment.ID, req.UserID, htmltext.FetchExcerpt(comment.ParsedText, "...", 240)) |
| } else if objInfo.ObjectType == constant.AnswerObjectType && !alreadyNotifiedUserID[objInfo.ObjectCreatorUserID] { |
| cs.notificationAnswerComment(ctx, objInfo.QuestionID, objInfo.Title, objInfo.AnswerID, |
| objInfo.ObjectCreatorUserID, comment.ID, req.UserID, htmltext.FetchExcerpt(comment.ParsedText, "...", 240)) |
| } |
| return nil, nil |
| } |
| |
| // RemoveComment delete comment |
| func (cs *CommentService) RemoveComment(ctx context.Context, req *schema.RemoveCommentReq) (err error) { |
| err = cs.commentRepo.RemoveComment(ctx, req.CommentID) |
| if err != nil { |
| return err |
| } |
| cs.eventQueueService.Send(ctx, schema.NewEvent(constant.EventCommentDelete, req.UserID). |
| TID(req.CommentID).CID(req.CommentID, req.UserID)) |
| return nil |
| } |
| |
| // UpdateComment update comment |
| func (cs *CommentService) UpdateComment(ctx context.Context, req *schema.UpdateCommentReq) ( |
| resp *schema.UpdateCommentResp, err error) { |
| old, exist, err := cs.commentCommonRepo.GetComment(ctx, req.CommentID) |
| if err != nil { |
| return nil, err |
| } |
| if !exist { |
| return nil, errors.BadRequest(reason.CommentNotFound) |
| } |
| // user can't edit the comment that was posted by others except admin |
| if !req.IsAdmin && req.UserID != old.UserID { |
| return nil, errors.BadRequest(reason.CommentNotFound) |
| } |
| |
| // user can edit the comment that was posted by himself before deadline. |
| // admin can edit it at any time |
| if !req.IsAdmin && (time.Now().After(old.CreatedAt.Add(constant.CommentEditDeadline))) { |
| return nil, errors.BadRequest(reason.CommentCannotEditAfterDeadline) |
| } |
| |
| if err = cs.commentRepo.UpdateCommentContent(ctx, old.ID, req.OriginalText, req.ParsedText); err != nil { |
| return nil, err |
| } |
| resp = &schema.UpdateCommentResp{ |
| CommentID: old.ID, |
| OriginalText: req.OriginalText, |
| ParsedText: req.ParsedText, |
| } |
| cs.eventQueueService.Send(ctx, schema.NewEvent(constant.EventCommentUpdate, req.UserID).TID(old.ID). |
| CID(old.ID, old.UserID)) |
| return resp, nil |
| } |
| |
| // GetComment get comment one |
| func (cs *CommentService) GetComment(ctx context.Context, req *schema.GetCommentReq) (resp *schema.GetCommentResp, err error) { |
| comment, exist, err := cs.commentCommonRepo.GetComment(ctx, req.ID) |
| if err != nil { |
| return |
| } |
| if !exist { |
| return nil, errors.BadRequest(reason.CommentNotFound) |
| } |
| |
| resp = &schema.GetCommentResp{ |
| CommentID: comment.ID, |
| CreatedAt: comment.CreatedAt.Unix(), |
| UserID: comment.UserID, |
| ReplyUserID: comment.GetReplyUserID(), |
| ReplyCommentID: comment.GetReplyCommentID(), |
| ObjectID: comment.ObjectID, |
| VoteCount: comment.VoteCount, |
| OriginalText: comment.OriginalText, |
| ParsedText: comment.ParsedText, |
| } |
| |
| // get comment user info |
| if len(resp.UserID) > 0 { |
| commentUser, exist, err := cs.userCommon.GetUserBasicInfoByID(ctx, resp.UserID) |
| if err != nil { |
| return nil, err |
| } |
| if exist { |
| resp.Username = commentUser.Username |
| resp.UserDisplayName = commentUser.DisplayName |
| resp.UserAvatar = commentUser.Avatar |
| resp.UserStatus = commentUser.Status |
| } |
| } |
| |
| // get reply user info |
| if len(resp.ReplyUserID) > 0 { |
| replyUser, exist, err := cs.userCommon.GetUserBasicInfoByID(ctx, resp.ReplyUserID) |
| if err != nil { |
| return nil, err |
| } |
| if exist { |
| resp.ReplyUsername = replyUser.Username |
| resp.ReplyUserDisplayName = replyUser.DisplayName |
| resp.ReplyUserStatus = replyUser.Status |
| } |
| } |
| |
| // check if current user vote this comment |
| resp.IsVote = cs.checkIsVote(ctx, req.UserID, resp.CommentID) |
| |
| resp.MemberActions = permission.GetCommentPermission(ctx, req.UserID, resp.UserID, |
| comment.CreatedAt, req.CanEdit, req.CanDelete) |
| return resp, nil |
| } |
| |
| // GetCommentWithPage get comment list page |
| func (cs *CommentService) GetCommentWithPage(ctx context.Context, req *schema.GetCommentWithPageReq) ( |
| pageModel *pager.PageModel, err error) { |
| dto := &CommentQuery{ |
| PageCond: pager.PageCond{Page: req.Page, PageSize: req.PageSize}, |
| ObjectID: req.ObjectID, |
| QueryCond: req.QueryCond, |
| } |
| commentList, total, err := cs.commentRepo.GetCommentPage(ctx, dto) |
| if err != nil { |
| return nil, err |
| } |
| resp := make([]*schema.GetCommentResp, 0) |
| for _, comment := range commentList { |
| commentResp, err := cs.convertCommentEntity2Resp(ctx, req, comment) |
| if err != nil { |
| return nil, err |
| } |
| resp = append(resp, commentResp) |
| } |
| |
| // if user request the specific comment, add it if not exist. |
| if len(req.CommentID) > 0 { |
| commentExist := false |
| for _, t := range resp { |
| if t.CommentID == req.CommentID { |
| commentExist = true |
| break |
| } |
| } |
| if !commentExist { |
| comment, exist, err := cs.commentCommonRepo.GetComment(ctx, req.CommentID) |
| if err != nil { |
| return nil, err |
| } |
| if exist && comment.ObjectID == req.ObjectID { |
| commentResp, err := cs.convertCommentEntity2Resp(ctx, req, comment) |
| if err != nil { |
| return nil, err |
| } |
| resp = append(resp, commentResp) |
| } |
| } |
| } |
| return pager.NewPageModel(total, resp), nil |
| } |
| |
| func (cs *CommentService) convertCommentEntity2Resp(ctx context.Context, req *schema.GetCommentWithPageReq, |
| comment *entity.Comment) (commentResp *schema.GetCommentResp, err error) { |
| commentResp = &schema.GetCommentResp{ |
| CommentID: comment.ID, |
| CreatedAt: comment.CreatedAt.Unix(), |
| UserID: comment.UserID, |
| ReplyUserID: comment.GetReplyUserID(), |
| ReplyCommentID: comment.GetReplyCommentID(), |
| ObjectID: comment.ObjectID, |
| VoteCount: comment.VoteCount, |
| OriginalText: comment.OriginalText, |
| ParsedText: comment.ParsedText, |
| } |
| |
| // get comment user info |
| if len(commentResp.UserID) > 0 { |
| commentUser, exist, err := cs.userCommon.GetUserBasicInfoByID(ctx, commentResp.UserID) |
| if err != nil { |
| return nil, err |
| } |
| if exist { |
| commentResp.Username = commentUser.Username |
| commentResp.UserDisplayName = commentUser.DisplayName |
| commentResp.UserAvatar = commentUser.Avatar |
| commentResp.UserStatus = commentUser.Status |
| } |
| } |
| |
| // get reply user info |
| if len(commentResp.ReplyUserID) > 0 { |
| replyUser, exist, err := cs.userCommon.GetUserBasicInfoByID(ctx, commentResp.ReplyUserID) |
| if err != nil { |
| return nil, err |
| } |
| if exist { |
| commentResp.ReplyUsername = replyUser.Username |
| commentResp.ReplyUserDisplayName = replyUser.DisplayName |
| commentResp.ReplyUserStatus = replyUser.Status |
| } |
| } |
| |
| // check if current user vote this comment |
| commentResp.IsVote = cs.checkIsVote(ctx, req.UserID, commentResp.CommentID) |
| |
| commentResp.MemberActions = permission.GetCommentPermission(ctx, |
| req.UserID, commentResp.UserID, comment.CreatedAt, req.CanEdit, req.CanDelete) |
| return commentResp, nil |
| } |
| |
| func (cs *CommentService) checkIsVote(ctx context.Context, userID, commentID string) (isVote bool) { |
| status := cs.voteCommon.GetVoteStatus(ctx, commentID, userID) |
| return len(status) > 0 |
| } |
| |
| // GetCommentPersonalWithPage get personal comment list page |
| func (cs *CommentService) GetCommentPersonalWithPage(ctx context.Context, req *schema.GetCommentPersonalWithPageReq) ( |
| pageModel *pager.PageModel, err error) { |
| if len(req.Username) > 0 { |
| userInfo, exist, err := cs.userCommon.GetUserBasicInfoByUserName(ctx, req.Username) |
| if err != nil { |
| return nil, err |
| } |
| if !exist { |
| return nil, errors.BadRequest(reason.UserNotFound) |
| } |
| req.UserID = userInfo.ID |
| } |
| if len(req.UserID) == 0 { |
| return nil, errors.BadRequest(reason.UserNotFound) |
| } |
| |
| dto := &CommentQuery{ |
| PageCond: pager.PageCond{Page: req.Page, PageSize: req.PageSize}, |
| UserID: req.UserID, |
| QueryCond: "created_at", |
| } |
| commentList, total, err := cs.commentRepo.GetCommentPage(ctx, dto) |
| if err != nil { |
| return nil, err |
| } |
| resp := make([]*schema.GetCommentPersonalWithPageResp, 0) |
| for _, comment := range commentList { |
| commentResp := &schema.GetCommentPersonalWithPageResp{ |
| CommentID: comment.ID, |
| CreatedAt: comment.CreatedAt.Unix(), |
| ObjectID: comment.ObjectID, |
| Content: comment.ParsedText, // todo trim |
| } |
| if len(comment.ObjectID) > 0 { |
| objInfo, err := cs.objectInfoService.GetInfo(ctx, comment.ObjectID) |
| if err != nil { |
| log.Error(err) |
| } else { |
| commentResp.ObjectType = objInfo.ObjectType |
| commentResp.Title = objInfo.Title |
| commentResp.UrlTitle = htmltext.UrlTitle(objInfo.Title) |
| commentResp.QuestionID = objInfo.QuestionID |
| commentResp.AnswerID = objInfo.AnswerID |
| if objInfo.QuestionStatus == entity.QuestionStatusDeleted { |
| commentResp.Title = "Deleted question" |
| } |
| } |
| } |
| resp = append(resp, commentResp) |
| } |
| return pager.NewPageModel(total, resp), nil |
| } |
| |
| func (cs *CommentService) notificationQuestionComment(ctx context.Context, questionUserID, |
| questionID, questionTitle, commentID, commentUserID, commentSummary string) { |
| if questionUserID == commentUserID { |
| return |
| } |
| // send internal notification |
| msg := &schema.NotificationMsg{ |
| ReceiverUserID: questionUserID, |
| TriggerUserID: commentUserID, |
| Type: schema.NotificationTypeInbox, |
| ObjectID: commentID, |
| } |
| msg.ObjectType = constant.CommentObjectType |
| msg.NotificationAction = constant.NotificationCommentQuestion |
| cs.notificationQueueService.Send(ctx, msg) |
| |
| // send external notification |
| receiverUserInfo, exist, err := cs.userRepo.GetByUserID(ctx, questionUserID) |
| if err != nil { |
| log.Error(err) |
| return |
| } |
| if !exist { |
| log.Warnf("user %s not found", questionUserID) |
| return |
| } |
| |
| externalNotificationMsg := &schema.ExternalNotificationMsg{ |
| ReceiverUserID: receiverUserInfo.ID, |
| ReceiverEmail: receiverUserInfo.EMail, |
| ReceiverLang: receiverUserInfo.Language, |
| } |
| rawData := &schema.NewCommentTemplateRawData{ |
| QuestionTitle: questionTitle, |
| QuestionID: questionID, |
| CommentID: commentID, |
| CommentSummary: commentSummary, |
| UnsubscribeCode: token.GenerateToken(), |
| } |
| commentUser, _, _ := cs.userCommon.GetUserBasicInfoByID(ctx, commentUserID) |
| if commentUser != nil { |
| rawData.CommentUserDisplayName = commentUser.DisplayName |
| } |
| externalNotificationMsg.NewCommentTemplateRawData = rawData |
| cs.externalNotificationQueueService.Send(ctx, externalNotificationMsg) |
| } |
| |
| func (cs *CommentService) notificationAnswerComment(ctx context.Context, |
| questionID, questionTitle, answerID, answerUserID, commentID, commentUserID, commentSummary string) { |
| if answerUserID == commentUserID { |
| return |
| } |
| |
| // Send internal notification. |
| msg := &schema.NotificationMsg{ |
| ReceiverUserID: answerUserID, |
| TriggerUserID: commentUserID, |
| Type: schema.NotificationTypeInbox, |
| ObjectID: commentID, |
| } |
| msg.ObjectType = constant.CommentObjectType |
| msg.NotificationAction = constant.NotificationCommentAnswer |
| cs.notificationQueueService.Send(ctx, msg) |
| |
| // Send external notification. |
| receiverUserInfo, exist, err := cs.userRepo.GetByUserID(ctx, answerUserID) |
| if err != nil { |
| log.Error(err) |
| return |
| } |
| if !exist { |
| log.Warnf("user %s not found", answerUserID) |
| return |
| } |
| externalNotificationMsg := &schema.ExternalNotificationMsg{ |
| ReceiverUserID: receiverUserInfo.ID, |
| ReceiverEmail: receiverUserInfo.EMail, |
| ReceiverLang: receiverUserInfo.Language, |
| } |
| rawData := &schema.NewCommentTemplateRawData{ |
| QuestionTitle: questionTitle, |
| QuestionID: questionID, |
| AnswerID: answerID, |
| CommentID: commentID, |
| CommentSummary: commentSummary, |
| UnsubscribeCode: token.GenerateToken(), |
| } |
| commentUser, _, _ := cs.userCommon.GetUserBasicInfoByID(ctx, commentUserID) |
| if commentUser != nil { |
| rawData.CommentUserDisplayName = commentUser.DisplayName |
| } |
| externalNotificationMsg.NewCommentTemplateRawData = rawData |
| cs.externalNotificationQueueService.Send(ctx, externalNotificationMsg) |
| } |
| |
| func (cs *CommentService) notificationCommentReply(ctx context.Context, replyUserID, commentID, commentUserID, |
| questionID, questionTitle, commentSummary string) { |
| msg := &schema.NotificationMsg{ |
| ReceiverUserID: replyUserID, |
| TriggerUserID: commentUserID, |
| Type: schema.NotificationTypeInbox, |
| ObjectID: commentID, |
| } |
| msg.ObjectType = constant.CommentObjectType |
| msg.NotificationAction = constant.NotificationReplyToYou |
| cs.notificationQueueService.Send(ctx, msg) |
| |
| // Send external notification. |
| receiverUserInfo, exist, err := cs.userRepo.GetByUserID(ctx, replyUserID) |
| if err != nil { |
| log.Error(err) |
| return |
| } |
| if !exist { |
| log.Warnf("user %s not found", replyUserID) |
| return |
| } |
| externalNotificationMsg := &schema.ExternalNotificationMsg{ |
| ReceiverUserID: receiverUserInfo.ID, |
| ReceiverEmail: receiverUserInfo.EMail, |
| ReceiverLang: receiverUserInfo.Language, |
| } |
| rawData := &schema.NewCommentTemplateRawData{ |
| QuestionTitle: questionTitle, |
| QuestionID: questionID, |
| CommentID: commentID, |
| CommentSummary: commentSummary, |
| UnsubscribeCode: token.GenerateToken(), |
| } |
| commentUser, _, _ := cs.userCommon.GetUserBasicInfoByID(ctx, commentUserID) |
| if commentUser != nil { |
| rawData.CommentUserDisplayName = commentUser.DisplayName |
| } |
| externalNotificationMsg.NewCommentTemplateRawData = rawData |
| cs.externalNotificationQueueService.Send(ctx, externalNotificationMsg) |
| } |
| |
| func (cs *CommentService) notificationMention( |
| ctx context.Context, mentionUsernameList []string, commentID, commentUserID string, |
| alreadyNotifiedUserID map[string]bool) (alreadyNotifiedUserIDs []string) { |
| for _, username := range mentionUsernameList { |
| userInfo, exist, err := cs.userCommon.GetUserBasicInfoByUserName(ctx, username) |
| if err != nil { |
| log.Error(err) |
| continue |
| } |
| if exist && !alreadyNotifiedUserID[userInfo.ID] { |
| msg := &schema.NotificationMsg{ |
| ReceiverUserID: userInfo.ID, |
| TriggerUserID: commentUserID, |
| Type: schema.NotificationTypeInbox, |
| ObjectID: commentID, |
| } |
| msg.ObjectType = constant.CommentObjectType |
| msg.NotificationAction = constant.NotificationMentionYou |
| cs.notificationQueueService.Send(ctx, msg) |
| alreadyNotifiedUserIDs = append(alreadyNotifiedUserIDs, userInfo.ID) |
| } |
| } |
| return alreadyNotifiedUserIDs |
| } |