mirror of https://gitee.com/answerdev/answer.git
refactor(answer): refactor accept answer activity
This commit is contained in:
parent
47661dc8a3
commit
7f58fbdad1
|
@ -45,7 +45,6 @@ import (
|
|||
"github.com/answerdev/answer/internal/service"
|
||||
"github.com/answerdev/answer/internal/service/action"
|
||||
activity2 "github.com/answerdev/answer/internal/service/activity"
|
||||
activity_common2 "github.com/answerdev/answer/internal/service/activity_common"
|
||||
"github.com/answerdev/answer/internal/service/activity_queue"
|
||||
"github.com/answerdev/answer/internal/service/answer_common"
|
||||
auth2 "github.com/answerdev/answer/internal/service/auth"
|
||||
|
@ -172,7 +171,7 @@ func initApplication(debug bool, serverConf *conf.Server, dbConf *data.Database,
|
|||
collectionService := service.NewCollectionService(collectionRepo, collectionGroupRepo, questionCommon)
|
||||
collectionController := controller.NewCollectionController(collectionService)
|
||||
answerActivityRepo := activity.NewAnswerActivityRepo(dataData, activityRepo, userRankRepo, notificationQueueService)
|
||||
answerActivityService := activity2.NewAnswerActivityService(answerActivityRepo)
|
||||
answerActivityService := activity2.NewAnswerActivityService(answerActivityRepo, configService)
|
||||
questionService := service.NewQuestionService(questionRepo, tagCommonService, questionCommon, userCommon, userRepo, revisionService, metaService, collectionCommon, answerActivityService, emailService, notificationQueueService, activityQueueService, siteInfoCommonService)
|
||||
answerService := service.NewAnswerService(answerRepo, questionRepo, questionCommon, userCommon, collectionCommon, userRepo, revisionService, answerActivityService, answerCommon, voteRepo, emailService, userRoleRelService, notificationQueueService, activityQueueService)
|
||||
questionController := controller.NewQuestionController(questionService, answerService, rankService, siteInfoCommonService)
|
||||
|
@ -205,11 +204,10 @@ func initApplication(debug bool, serverConf *conf.Server, dbConf *data.Database,
|
|||
dashboardController := controller.NewDashboardController(dashboardService)
|
||||
uploaderService := uploader.NewUploaderService(serviceConf, siteInfoCommonService)
|
||||
uploadController := controller.NewUploadController(uploaderService)
|
||||
activityCommon := activity_common2.NewActivityCommon(activityRepo, activityQueueService)
|
||||
activityActivityRepo := activity.NewActivityRepo(dataData, configService)
|
||||
commentCommonService := comment_common.NewCommentCommonService(commentCommonRepo)
|
||||
activityService := activity2.NewActivityService(activityActivityRepo, userCommon, activityCommon, tagCommonService, objService, commentCommonService, revisionService, metaService, configService)
|
||||
activityController := controller.NewActivityController(activityCommon, activityService)
|
||||
activityService := activity2.NewActivityService(activityActivityRepo, userCommon, tagCommonService, objService, commentCommonService, revisionService, metaService, configService)
|
||||
activityController := controller.NewActivityController(activityService)
|
||||
roleController := controller_admin.NewRoleController(roleService)
|
||||
pluginConfigRepo := plugin_config.NewPluginConfigRepo(dataData)
|
||||
pluginCommonService := plugin_common.NewPluginCommonService(pluginConfigRepo, configService)
|
||||
|
|
|
@ -5,22 +5,19 @@ import (
|
|||
"github.com/answerdev/answer/internal/base/middleware"
|
||||
"github.com/answerdev/answer/internal/schema"
|
||||
"github.com/answerdev/answer/internal/service/activity"
|
||||
"github.com/answerdev/answer/internal/service/activity_common"
|
||||
"github.com/answerdev/answer/internal/service/role"
|
||||
"github.com/answerdev/answer/pkg/uid"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type ActivityController struct {
|
||||
activityCommonService *activity_common.ActivityCommon
|
||||
activityService *activity.ActivityService
|
||||
activityService *activity.ActivityService
|
||||
}
|
||||
|
||||
// NewActivityController new activity controller.
|
||||
func NewActivityController(
|
||||
activityCommonService *activity_common.ActivityCommon,
|
||||
activityService *activity.ActivityService) *ActivityController {
|
||||
return &ActivityController{activityCommonService: activityCommonService, activityService: activityService}
|
||||
return &ActivityController{activityService: activityService}
|
||||
}
|
||||
|
||||
// GetObjectTimeline get object timeline
|
||||
|
|
|
@ -2,7 +2,10 @@ package activity
|
|||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/segmentfault/pacman/log"
|
||||
"time"
|
||||
"xorm.io/builder"
|
||||
|
||||
"github.com/answerdev/answer/internal/base/constant"
|
||||
"github.com/answerdev/answer/internal/base/data"
|
||||
|
@ -18,10 +21,6 @@ import (
|
|||
"xorm.io/xorm"
|
||||
)
|
||||
|
||||
var (
|
||||
acceptActionList = []string{constant.ActAccept, constant.ActAccepted}
|
||||
)
|
||||
|
||||
// AnswerActivityRepo answer accepted
|
||||
type AnswerActivityRepo struct {
|
||||
data *data.Data
|
||||
|
@ -45,91 +44,273 @@ func NewAnswerActivityRepo(
|
|||
}
|
||||
}
|
||||
|
||||
// AcceptAnswer accept other answer
|
||||
func (ar *AnswerActivityRepo) AcceptAnswer(ctx context.Context,
|
||||
answerObjID, questionObjID, questionUserID, answerUserID string, isSelf bool,
|
||||
) (err error) {
|
||||
addActivityList := make([]*entity.Activity, 0)
|
||||
for _, action := range acceptActionList {
|
||||
// get accept answer need add rank amount
|
||||
activityType, deltaRank, hasRank, e := ar.activityRepo.GetActivityTypeByObjID(ctx, answerObjID, action)
|
||||
if e != nil {
|
||||
return errors.InternalServer(reason.DatabaseError).WithError(e).WithStack()
|
||||
}
|
||||
addActivity := &entity.Activity{
|
||||
ObjectID: answerObjID,
|
||||
OriginalObjectID: questionObjID,
|
||||
ActivityType: activityType,
|
||||
Rank: deltaRank,
|
||||
HasRank: hasRank,
|
||||
}
|
||||
if action == constant.ActAccept {
|
||||
addActivity.UserID = questionUserID
|
||||
addActivity.TriggerUserID = converter.StringToInt64(answerUserID)
|
||||
addActivity.OriginalObjectID = questionObjID // if activity is 'accept' means this question is accept the answer.
|
||||
} else {
|
||||
addActivity.UserID = answerUserID
|
||||
addActivity.TriggerUserID = converter.StringToInt64(answerUserID)
|
||||
addActivity.OriginalObjectID = answerObjID // if activity is 'accepted' means this answer was accepted.
|
||||
}
|
||||
if isSelf {
|
||||
addActivity.Rank = 0
|
||||
addActivity.HasRank = 0
|
||||
}
|
||||
addActivityList = append(addActivityList, addActivity)
|
||||
func (ar *AnswerActivityRepo) SaveAcceptAnswerActivity(ctx context.Context, op *schema.AcceptAnswerOperationInfo) (
|
||||
err error) {
|
||||
// pre check
|
||||
noNeedToDo, err := ar.activityPreCheck(ctx, op)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if noNeedToDo {
|
||||
return nil
|
||||
}
|
||||
|
||||
// save activity
|
||||
_, err = ar.data.DB.Transaction(func(session *xorm.Session) (result any, err error) {
|
||||
session = session.Context(ctx)
|
||||
for _, addActivity := range addActivityList {
|
||||
existsActivity, exists, e := ar.activityRepo.GetActivity(
|
||||
ctx, session, answerObjID, addActivity.UserID, addActivity.ActivityType)
|
||||
if e != nil {
|
||||
return nil, errors.InternalServer(reason.DatabaseError).WithError(e).WithStack()
|
||||
}
|
||||
if exists && existsActivity.Cancelled == entity.ActivityAvailable {
|
||||
continue
|
||||
}
|
||||
|
||||
// trigger user rank and send notification
|
||||
if addActivity.Rank != 0 {
|
||||
reachStandard, e := ar.userRankRepo.TriggerUserRank(
|
||||
ctx, session, addActivity.UserID, addActivity.Rank, addActivity.ActivityType)
|
||||
if e != nil {
|
||||
return nil, errors.InternalServer(reason.DatabaseError).WithError(e).WithStack()
|
||||
}
|
||||
if reachStandard {
|
||||
addActivity.Rank = 0
|
||||
}
|
||||
}
|
||||
userInfoMapping, err := ar.acquireUserInfo(session, op.GetUserIDs())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if exists {
|
||||
if _, e = session.Where("id = ?", existsActivity.ID).Cols("`cancelled`").
|
||||
Update(&entity.Activity{Cancelled: entity.ActivityAvailable}); e != nil {
|
||||
return nil, errors.InternalServer(reason.DatabaseError).WithError(e).WithStack()
|
||||
}
|
||||
} else {
|
||||
if _, e = session.Insert(addActivity); e != nil {
|
||||
return nil, errors.InternalServer(reason.DatabaseError).WithError(e).WithStack()
|
||||
}
|
||||
}
|
||||
err = ar.saveActivitiesAvailable(session, op)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = ar.changeUserRank(ctx, session, op, userInfoMapping)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return nil, nil
|
||||
})
|
||||
if err != nil {
|
||||
return errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
|
||||
}
|
||||
|
||||
// notification
|
||||
ar.sendAcceptAnswerNotification(ctx, op)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ar *AnswerActivityRepo) SaveCancelAcceptAnswerActivity(ctx context.Context, op *schema.AcceptAnswerOperationInfo) (
|
||||
err error) {
|
||||
// pre check
|
||||
activities, err := ar.getExistActivity(ctx, op)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, act := range addActivityList {
|
||||
var userIDs []string
|
||||
for _, act := range activities {
|
||||
if act.Cancelled == entity.ActivityCancelled {
|
||||
continue
|
||||
}
|
||||
userIDs = append(userIDs, act.UserID)
|
||||
}
|
||||
if len(userIDs) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// save activity
|
||||
_, err = ar.data.DB.Transaction(func(session *xorm.Session) (result any, err error) {
|
||||
session = session.Context(ctx)
|
||||
|
||||
userInfoMapping, err := ar.acquireUserInfo(session, userIDs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = ar.cancelActivities(session, activities)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = ar.rollbackUserRank(ctx, session, activities, userInfoMapping)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return nil, nil
|
||||
})
|
||||
if err != nil {
|
||||
return errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
|
||||
}
|
||||
|
||||
// notification
|
||||
ar.sendCancelAcceptAnswerNotification(ctx, op)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ar *AnswerActivityRepo) activityPreCheck(ctx context.Context, op *schema.AcceptAnswerOperationInfo) (
|
||||
noNeedToDo bool, err error) {
|
||||
activities, err := ar.getExistActivity(ctx, op)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
done := 0
|
||||
for _, act := range activities {
|
||||
if act.Cancelled == entity.ActivityAvailable {
|
||||
done++
|
||||
}
|
||||
}
|
||||
return done == len(op.Activities), nil
|
||||
}
|
||||
|
||||
func (ar *AnswerActivityRepo) acquireUserInfo(session *xorm.Session, userIDs []string) (map[string]*entity.User, error) {
|
||||
us := make([]*entity.User, 0)
|
||||
err := session.In("id", userIDs).ForUpdate().Find(&us)
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
users := make(map[string]*entity.User, 0)
|
||||
for _, u := range us {
|
||||
users[u.ID] = u
|
||||
}
|
||||
return users, nil
|
||||
}
|
||||
|
||||
// saveActivitiesAvailable save activities
|
||||
// If activity not exist it will be created or else will be updated
|
||||
// If this activity is already exist, set activity rank to 0
|
||||
// So after this function, the activity rank will be correct for update user rank
|
||||
func (ar *AnswerActivityRepo) saveActivitiesAvailable(session *xorm.Session, op *schema.AcceptAnswerOperationInfo) (
|
||||
err error) {
|
||||
for _, act := range op.Activities {
|
||||
existsActivity := &entity.Activity{}
|
||||
exist, err := session.
|
||||
Where(builder.Eq{"object_id": op.AnswerObjectID}).
|
||||
And(builder.Eq{"user_id": act.ActivityUserID}).
|
||||
And(builder.Eq{"trigger_user_id": act.TriggerUserID}).
|
||||
And(builder.Eq{"activity_type": act.ActivityType}).
|
||||
Get(existsActivity)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if exist && existsActivity.Cancelled == entity.ActivityAvailable {
|
||||
act.Rank = 0
|
||||
continue
|
||||
}
|
||||
if exist {
|
||||
if _, err = session.Where("id = ?", existsActivity.ID).Cols("`cancelled`").
|
||||
Update(&entity.Activity{Cancelled: entity.ActivityAvailable}); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
insertActivity := entity.Activity{
|
||||
ObjectID: op.AnswerObjectID,
|
||||
OriginalObjectID: act.OriginalObjectID,
|
||||
UserID: act.ActivityUserID,
|
||||
TriggerUserID: converter.StringToInt64(act.TriggerUserID),
|
||||
ActivityType: act.ActivityType,
|
||||
Rank: act.Rank,
|
||||
HasRank: act.HasRank(),
|
||||
Cancelled: entity.ActivityAvailable,
|
||||
}
|
||||
_, err = session.Insert(&insertActivity)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// cancelActivities cancel activities
|
||||
// If this activity is already cancelled, set activity rank to 0
|
||||
// So after this function, the activity rank will be correct for update user rank
|
||||
func (ar *AnswerActivityRepo) cancelActivities(session *xorm.Session, activities []*entity.Activity) (err error) {
|
||||
for _, act := range activities {
|
||||
t := &entity.Activity{}
|
||||
exist, err := session.ID(act.ID).Get(t)
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
return err
|
||||
}
|
||||
if !exist {
|
||||
log.Error(fmt.Errorf("%s activity not exist", act.ID))
|
||||
return fmt.Errorf("%s activity not exist", act.ID)
|
||||
}
|
||||
// If this activity is already cancelled, set activity rank to 0
|
||||
if t.Cancelled == entity.ActivityCancelled {
|
||||
act.Rank = 0
|
||||
}
|
||||
if _, err = session.ID(act.ID).Cols("cancelled", "cancelled_at").
|
||||
Update(&entity.Activity{
|
||||
Cancelled: entity.ActivityCancelled,
|
||||
CancelledAt: time.Now(),
|
||||
}); err != nil {
|
||||
log.Error(err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ar *AnswerActivityRepo) changeUserRank(ctx context.Context, session *xorm.Session,
|
||||
op *schema.AcceptAnswerOperationInfo,
|
||||
userInfoMapping map[string]*entity.User) (err error) {
|
||||
for _, act := range op.Activities {
|
||||
if act.Rank == 0 {
|
||||
continue
|
||||
}
|
||||
user := userInfoMapping[act.ActivityUserID]
|
||||
if user == nil {
|
||||
continue
|
||||
}
|
||||
if err = ar.userRankRepo.ChangeUserRank(ctx, session,
|
||||
act.ActivityUserID, user.Rank, act.Rank); err != nil {
|
||||
log.Error(err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ar *AnswerActivityRepo) rollbackUserRank(ctx context.Context, session *xorm.Session,
|
||||
activities []*entity.Activity,
|
||||
userInfoMapping map[string]*entity.User) (err error) {
|
||||
for _, act := range activities {
|
||||
if act.Rank == 0 {
|
||||
continue
|
||||
}
|
||||
user := userInfoMapping[act.UserID]
|
||||
if user == nil {
|
||||
continue
|
||||
}
|
||||
if err = ar.userRankRepo.ChangeUserRank(ctx, session,
|
||||
act.UserID, user.Rank, -act.Rank); err != nil {
|
||||
log.Error(err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ar *AnswerActivityRepo) getExistActivity(ctx context.Context, op *schema.AcceptAnswerOperationInfo) ([]*entity.Activity, error) {
|
||||
var activities []*entity.Activity
|
||||
for _, action := range op.Activities {
|
||||
t := &entity.Activity{}
|
||||
exist, err := ar.data.DB.Context(ctx).
|
||||
Where(builder.Eq{"user_id": action.ActivityUserID}).
|
||||
And(builder.Eq{"trigger_user_id": action.TriggerUserID}).
|
||||
And(builder.Eq{"activity_type": action.ActivityType}).
|
||||
And(builder.Eq{"object_id": op.AnswerObjectID}).
|
||||
Get(t)
|
||||
if err != nil {
|
||||
return nil, errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
|
||||
}
|
||||
if exist {
|
||||
activities = append(activities, t)
|
||||
}
|
||||
}
|
||||
return activities, nil
|
||||
}
|
||||
|
||||
func (ar *AnswerActivityRepo) sendAcceptAnswerNotification(
|
||||
ctx context.Context, op *schema.AcceptAnswerOperationInfo) {
|
||||
for _, act := range op.Activities {
|
||||
msg := &schema.NotificationMsg{
|
||||
Type: schema.NotificationTypeAchievement,
|
||||
ObjectID: act.ObjectID,
|
||||
ReceiverUserID: act.UserID,
|
||||
ObjectID: op.AnswerObjectID,
|
||||
ReceiverUserID: act.ActivityUserID,
|
||||
}
|
||||
if act.UserID == questionUserID {
|
||||
msg.TriggerUserID = answerUserID
|
||||
if act.ActivityUserID == op.QuestionUserID {
|
||||
msg.TriggerUserID = op.AnswerUserID
|
||||
msg.ObjectType = constant.AnswerObjectType
|
||||
} else {
|
||||
msg.TriggerUserID = questionUserID
|
||||
msg.TriggerUserID = op.QuestionUserID
|
||||
msg.ObjectType = constant.AnswerObjectType
|
||||
}
|
||||
if msg.TriggerUserID != msg.ReceiverUserID {
|
||||
|
@ -137,98 +318,38 @@ func (ar *AnswerActivityRepo) AcceptAnswer(ctx context.Context,
|
|||
}
|
||||
}
|
||||
|
||||
for _, act := range addActivityList {
|
||||
for _, act := range op.Activities {
|
||||
msg := &schema.NotificationMsg{
|
||||
ReceiverUserID: act.UserID,
|
||||
ReceiverUserID: act.ActivityUserID,
|
||||
Type: schema.NotificationTypeInbox,
|
||||
ObjectID: act.ObjectID,
|
||||
ObjectID: op.AnswerObjectID,
|
||||
}
|
||||
if act.UserID != questionUserID {
|
||||
msg.TriggerUserID = questionUserID
|
||||
if act.ActivityUserID != op.QuestionUserID {
|
||||
msg.TriggerUserID = op.QuestionUserID
|
||||
msg.ObjectType = constant.AnswerObjectType
|
||||
msg.NotificationAction = constant.NotificationAcceptAnswer
|
||||
ar.notificationQueueService.Send(ctx, msg)
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// CancelAcceptAnswer accept other answer
|
||||
func (ar *AnswerActivityRepo) CancelAcceptAnswer(ctx context.Context,
|
||||
answerObjID, questionObjID, questionUserID, answerUserID string,
|
||||
) (err error) {
|
||||
addActivityList := make([]*entity.Activity, 0)
|
||||
for _, action := range acceptActionList {
|
||||
// get accept answer need add rank amount
|
||||
activityType, deltaRank, hasRank, e := ar.activityRepo.GetActivityTypeByObjID(ctx, answerObjID, action)
|
||||
if e != nil {
|
||||
return errors.InternalServer(reason.DatabaseError).WithError(e).WithStack()
|
||||
}
|
||||
addActivity := &entity.Activity{
|
||||
ObjectID: answerObjID,
|
||||
ActivityType: activityType,
|
||||
Rank: -deltaRank,
|
||||
HasRank: hasRank,
|
||||
}
|
||||
if action == constant.ActAccept {
|
||||
addActivity.UserID = questionUserID
|
||||
addActivity.OriginalObjectID = questionObjID
|
||||
} else {
|
||||
addActivity.UserID = answerUserID
|
||||
addActivity.OriginalObjectID = answerObjID
|
||||
}
|
||||
addActivityList = append(addActivityList, addActivity)
|
||||
}
|
||||
|
||||
_, err = ar.data.DB.Transaction(func(session *xorm.Session) (result any, err error) {
|
||||
session = session.Context(ctx)
|
||||
for _, addActivity := range addActivityList {
|
||||
existsActivity, exists, e := ar.activityRepo.GetActivity(
|
||||
ctx, session, answerObjID, addActivity.UserID, addActivity.ActivityType)
|
||||
if e != nil {
|
||||
return nil, errors.InternalServer(reason.DatabaseError).WithError(e).WithStack()
|
||||
}
|
||||
if exists && existsActivity.Cancelled == entity.ActivityCancelled {
|
||||
continue
|
||||
}
|
||||
if !exists {
|
||||
continue
|
||||
}
|
||||
|
||||
if existsActivity.Rank != 0 {
|
||||
_, e = ar.userRankRepo.TriggerUserRank(
|
||||
ctx, session, addActivity.UserID, addActivity.Rank, addActivity.ActivityType)
|
||||
if e != nil {
|
||||
return nil, errors.InternalServer(reason.DatabaseError).WithError(e).WithStack()
|
||||
}
|
||||
}
|
||||
|
||||
if _, e := session.Where("id = ?", existsActivity.ID).Cols("cancelled", "cancelled_at").
|
||||
Update(&entity.Activity{Cancelled: entity.ActivityCancelled, CancelledAt: time.Now()}); e != nil {
|
||||
return nil, errors.InternalServer(reason.DatabaseError).WithError(e).WithStack()
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, act := range addActivityList {
|
||||
func (ar *AnswerActivityRepo) sendCancelAcceptAnswerNotification(
|
||||
ctx context.Context, op *schema.AcceptAnswerOperationInfo) {
|
||||
for _, act := range op.Activities {
|
||||
msg := &schema.NotificationMsg{
|
||||
ReceiverUserID: act.UserID,
|
||||
ReceiverUserID: act.ActivityUserID,
|
||||
Type: schema.NotificationTypeAchievement,
|
||||
ObjectID: act.ObjectID,
|
||||
ObjectID: op.AnswerObjectID,
|
||||
}
|
||||
if act.UserID == questionUserID {
|
||||
msg.TriggerUserID = answerUserID
|
||||
if act.ActivityUserID == op.QuestionObjectID {
|
||||
msg.TriggerUserID = op.AnswerObjectID
|
||||
msg.ObjectType = constant.QuestionObjectType
|
||||
} else {
|
||||
msg.TriggerUserID = questionUserID
|
||||
msg.TriggerUserID = op.QuestionObjectID
|
||||
msg.ObjectType = constant.AnswerObjectType
|
||||
}
|
||||
if msg.TriggerUserID != msg.ReceiverUserID {
|
||||
ar.notificationQueueService.Send(ctx, msg)
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
package schema
|
||||
|
||||
// AcceptAnswerOperationInfo accept answer operation info
|
||||
type AcceptAnswerOperationInfo struct {
|
||||
QuestionObjectID string
|
||||
QuestionUserID string
|
||||
AnswerObjectID string
|
||||
AnswerUserID string
|
||||
|
||||
// vote activity info
|
||||
Activities []*AcceptAnswerActivity
|
||||
}
|
||||
|
||||
// AcceptAnswerActivity accept answer activity
|
||||
type AcceptAnswerActivity struct {
|
||||
ActivityType int
|
||||
ActivityUserID string
|
||||
TriggerUserID string
|
||||
OriginalObjectID string
|
||||
Rank int
|
||||
}
|
||||
|
||||
func (v *AcceptAnswerActivity) HasRank() int {
|
||||
if v.Rank != 0 {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (a *AcceptAnswerOperationInfo) GetUserIDs() (userIDs []string) {
|
||||
for _, act := range a.Activities {
|
||||
userIDs = append(userIDs, act.ActivityUserID)
|
||||
}
|
||||
return userIDs
|
||||
}
|
|
@ -10,7 +10,6 @@ import (
|
|||
"github.com/answerdev/answer/internal/base/handler"
|
||||
"github.com/answerdev/answer/internal/entity"
|
||||
"github.com/answerdev/answer/internal/schema"
|
||||
"github.com/answerdev/answer/internal/service/activity_common"
|
||||
"github.com/answerdev/answer/internal/service/comment_common"
|
||||
"github.com/answerdev/answer/internal/service/config"
|
||||
"github.com/answerdev/answer/internal/service/meta"
|
||||
|
@ -31,22 +30,20 @@ type ActivityRepo interface {
|
|||
|
||||
// ActivityService activity service
|
||||
type ActivityService struct {
|
||||
activityRepo ActivityRepo
|
||||
userCommon *usercommon.UserCommon
|
||||
activityCommonService *activity_common.ActivityCommon
|
||||
tagCommonService *tag_common.TagCommonService
|
||||
objectInfoService *object_info.ObjService
|
||||
commentCommonService *comment_common.CommentCommonService
|
||||
revisionService *revision_common.RevisionService
|
||||
metaService *meta.MetaService
|
||||
configService *config.ConfigService
|
||||
activityRepo ActivityRepo
|
||||
userCommon *usercommon.UserCommon
|
||||
tagCommonService *tag_common.TagCommonService
|
||||
objectInfoService *object_info.ObjService
|
||||
commentCommonService *comment_common.CommentCommonService
|
||||
revisionService *revision_common.RevisionService
|
||||
metaService *meta.MetaService
|
||||
configService *config.ConfigService
|
||||
}
|
||||
|
||||
// NewActivityService new activity service
|
||||
func NewActivityService(
|
||||
activityRepo ActivityRepo,
|
||||
userCommon *usercommon.UserCommon,
|
||||
activityCommonService *activity_common.ActivityCommon,
|
||||
tagCommonService *tag_common.TagCommonService,
|
||||
objectInfoService *object_info.ObjService,
|
||||
commentCommonService *comment_common.CommentCommonService,
|
||||
|
@ -55,15 +52,14 @@ func NewActivityService(
|
|||
configService *config.ConfigService,
|
||||
) *ActivityService {
|
||||
return &ActivityService{
|
||||
objectInfoService: objectInfoService,
|
||||
activityRepo: activityRepo,
|
||||
userCommon: userCommon,
|
||||
activityCommonService: activityCommonService,
|
||||
tagCommonService: tagCommonService,
|
||||
commentCommonService: commentCommonService,
|
||||
revisionService: revisionService,
|
||||
metaService: metaService,
|
||||
configService: configService,
|
||||
objectInfoService: objectInfoService,
|
||||
activityRepo: activityRepo,
|
||||
userCommon: userCommon,
|
||||
tagCommonService: tagCommonService,
|
||||
commentCommonService: commentCommonService,
|
||||
revisionService: revisionService,
|
||||
metaService: metaService,
|
||||
configService: configService,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,38 +0,0 @@
|
|||
package activity
|
||||
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
// AnswerActivityRepo answer activity
|
||||
type AnswerActivityRepo interface {
|
||||
AcceptAnswer(ctx context.Context,
|
||||
answerObjID, questionObjID, questionUserID, answerUserID string, isSelf bool) (err error)
|
||||
CancelAcceptAnswer(ctx context.Context,
|
||||
answerObjID, questionObjID, questionUserID, answerUserID string) (err error)
|
||||
}
|
||||
|
||||
// AnswerActivityService user service
|
||||
type AnswerActivityService struct {
|
||||
answerActivityRepo AnswerActivityRepo
|
||||
}
|
||||
|
||||
// NewAnswerActivityService new comment service
|
||||
func NewAnswerActivityService(
|
||||
answerActivityRepo AnswerActivityRepo) *AnswerActivityService {
|
||||
return &AnswerActivityService{
|
||||
answerActivityRepo: answerActivityRepo,
|
||||
}
|
||||
}
|
||||
|
||||
// AcceptAnswer accept answer change activity
|
||||
func (as *AnswerActivityService) AcceptAnswer(ctx context.Context,
|
||||
answerObjID, questionObjID, questionUserID, answerUserID string, isSelf bool) (err error) {
|
||||
return as.answerActivityRepo.AcceptAnswer(ctx, answerObjID, questionObjID, questionUserID, answerUserID, isSelf)
|
||||
}
|
||||
|
||||
// CancelAcceptAnswer cancel accept answer change activity
|
||||
func (as *AnswerActivityService) CancelAcceptAnswer(ctx context.Context,
|
||||
answerObjID, questionObjID, questionUserID, answerUserID string) (err error) {
|
||||
return as.answerActivityRepo.CancelAcceptAnswer(ctx, answerObjID, questionObjID, questionUserID, answerUserID)
|
||||
}
|
|
@ -0,0 +1,92 @@
|
|||
package activity
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/answerdev/answer/internal/schema"
|
||||
"github.com/answerdev/answer/internal/service/activity_type"
|
||||
"github.com/answerdev/answer/internal/service/config"
|
||||
"github.com/segmentfault/pacman/log"
|
||||
)
|
||||
|
||||
// AnswerActivityRepo answer activity
|
||||
type AnswerActivityRepo interface {
|
||||
SaveAcceptAnswerActivity(ctx context.Context, op *schema.AcceptAnswerOperationInfo) (err error)
|
||||
SaveCancelAcceptAnswerActivity(ctx context.Context, op *schema.AcceptAnswerOperationInfo) (err error)
|
||||
}
|
||||
|
||||
// AnswerActivityService answer activity service
|
||||
type AnswerActivityService struct {
|
||||
answerActivityRepo AnswerActivityRepo
|
||||
configService *config.ConfigService
|
||||
}
|
||||
|
||||
// NewAnswerActivityService new comment service
|
||||
func NewAnswerActivityService(
|
||||
answerActivityRepo AnswerActivityRepo,
|
||||
configService *config.ConfigService,
|
||||
) *AnswerActivityService {
|
||||
return &AnswerActivityService{
|
||||
answerActivityRepo: answerActivityRepo,
|
||||
configService: configService,
|
||||
}
|
||||
}
|
||||
|
||||
// AcceptAnswer accept answer change activity
|
||||
func (as *AnswerActivityService) AcceptAnswer(ctx context.Context,
|
||||
answerObjID, questionObjID, questionUserID, answerUserID string, isSelf bool) (err error) {
|
||||
operationInfo := as.createAcceptAnswerOperationInfo(ctx,
|
||||
answerObjID, questionObjID, questionUserID, answerUserID, isSelf)
|
||||
return as.answerActivityRepo.SaveAcceptAnswerActivity(ctx, operationInfo)
|
||||
}
|
||||
|
||||
// CancelAcceptAnswer cancel accept answer change activity
|
||||
func (as *AnswerActivityService) CancelAcceptAnswer(ctx context.Context,
|
||||
answerObjID, questionObjID, questionUserID, answerUserID string) (err error) {
|
||||
operationInfo := as.createAcceptAnswerOperationInfo(ctx,
|
||||
answerObjID, questionObjID, questionUserID, answerUserID, false)
|
||||
return as.answerActivityRepo.SaveCancelAcceptAnswerActivity(ctx, operationInfo)
|
||||
}
|
||||
|
||||
func (as *AnswerActivityService) createAcceptAnswerOperationInfo(ctx context.Context,
|
||||
answerObjID, questionObjID, questionUserID, answerUserID string, isSelf bool) *schema.AcceptAnswerOperationInfo {
|
||||
operationInfo := &schema.AcceptAnswerOperationInfo{
|
||||
QuestionObjectID: questionObjID,
|
||||
QuestionUserID: questionUserID,
|
||||
AnswerObjectID: answerObjID,
|
||||
AnswerUserID: answerUserID,
|
||||
}
|
||||
operationInfo.Activities = as.getActivities(ctx, operationInfo)
|
||||
if isSelf {
|
||||
for _, activity := range operationInfo.Activities {
|
||||
activity.Rank = 0
|
||||
}
|
||||
}
|
||||
return operationInfo
|
||||
}
|
||||
|
||||
func (as *AnswerActivityService) getActivities(ctx context.Context, op *schema.AcceptAnswerOperationInfo) (
|
||||
activities []*schema.AcceptAnswerActivity) {
|
||||
activities = make([]*schema.AcceptAnswerActivity, 0)
|
||||
|
||||
for _, action := range []string{activity_type.AnswerAccept, activity_type.AnswerAccepted} {
|
||||
t := &schema.AcceptAnswerActivity{}
|
||||
cfg, err := as.configService.GetConfigByKey(ctx, action)
|
||||
if err != nil {
|
||||
log.Warnf("get config by key error: %v", err)
|
||||
continue
|
||||
}
|
||||
t.ActivityType, t.Rank = cfg.ID, cfg.GetIntValue()
|
||||
|
||||
if action == activity_type.AnswerAccept {
|
||||
t.ActivityUserID = op.QuestionUserID
|
||||
t.TriggerUserID = op.AnswerUserID
|
||||
t.OriginalObjectID = op.QuestionObjectID // if activity is 'accept' means this question is accept the answer.
|
||||
} else {
|
||||
t.ActivityUserID = op.AnswerUserID
|
||||
t.TriggerUserID = op.AnswerUserID
|
||||
t.OriginalObjectID = op.AnswerObjectID // if activity is 'accepted' means this answer was accepted.
|
||||
}
|
||||
activities = append(activities, t)
|
||||
}
|
||||
return activities
|
||||
}
|
Loading…
Reference in New Issue