This is an automated email from the ASF dual-hosted git repository. linkinstar pushed a commit to branch feat/1.4.0/badge in repository https://gitbox.apache.org/repos/asf/incubator-answer.git
commit 9b0de85ed4f5d9b77506b4698cc87850baf89691 Author: LinkinStars <[email protected]> AuthorDate: Thu Aug 8 18:09:27 2024 +0800 feat(badge): add badge event handler --- cmd/wire_gen.go | 4 +- internal/repo/badge/badge_event_rule.go | 216 +++++++++++++++++++++ internal/repo/badge/badge_repo.go | 31 ++- internal/repo/badge/badge_rule.go | 95 --------- internal/repo/badge/event_rule_mapping.go | 47 ----- internal/repo/badge/rule.go | 43 ---- internal/repo/provider.go | 1 + internal/schema/event_schema.go | 10 + .../{repo => service}/badge/badge_event_handler.go | 34 +++- internal/service/badge/badge_service.go | 19 +- internal/service/provider.go | 1 + 11 files changed, 304 insertions(+), 197 deletions(-) diff --git a/cmd/wire_gen.go b/cmd/wire_gen.go index 24cdb163..f49ef20e 100644 --- a/cmd/wire_gen.go +++ b/cmd/wire_gen.go @@ -263,7 +263,9 @@ func initApplication(debug bool, serverConf *conf.Server, dbConf *data.Database, badgeRepo := badge.NewBadgeRepo(dataData, uniqueIDRepo) badgeGroupRepo := badge_group.NewBadgeGroupRepo(dataData, uniqueIDRepo) badgeAwardRepo := badge_award.NewBadgeAwardRepo(dataData, uniqueIDRepo) - badgeService := badge2.NewBadgeService(badgeRepo, badgeGroupRepo, badgeAwardRepo) + eventRuleRepo := badge.NewEventRuleRepo(dataData) + badgeEventService := badge2.NewBadgeEventService(dataData, eventQueueService, badgeRepo, eventRuleRepo) + badgeService := badge2.NewBadgeService(badgeRepo, badgeGroupRepo, badgeAwardRepo, badgeEventService) badgeAwardService := badge_award2.NewBadgeAwardService(badgeAwardRepo, userCommon, objService, questionRepo, answerRepo) badgeController := controller.NewBadgeController(badgeService, badgeAwardService) answerAPIRouter := router.NewAnswerAPIRouter(langController, userController, commentController, reportController, voteController, tagController, followController, collectionController, questionController, answerController, searchController, revisionController, rankController, userAdminController, reasonController, themeController, siteInfoController, controllerSiteInfoController, notificationController, dashboardController, uploadController, activityController, roleController, pluginCon [...] diff --git a/internal/repo/badge/badge_event_rule.go b/internal/repo/badge/badge_event_rule.go new file mode 100644 index 00000000..8f940720 --- /dev/null +++ b/internal/repo/badge/badge_event_rule.go @@ -0,0 +1,216 @@ +/* + * 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 badge + +import ( + "context" + "github.com/apache/incubator-answer/internal/base/constant" + "github.com/apache/incubator-answer/internal/base/data" + "github.com/apache/incubator-answer/internal/base/reason" + "github.com/apache/incubator-answer/internal/entity" + "github.com/apache/incubator-answer/internal/schema" + "github.com/apache/incubator-answer/internal/service/badge" + "github.com/segmentfault/pacman/errors" + "github.com/segmentfault/pacman/log" +) + +// eventRuleRepo event rule repo +type eventRuleRepo struct { + data *data.Data + EventRuleMapping map[constant.EventType][]badge.EventRuleHandler +} + +// NewEventRuleRepo creates a new badge repository +func NewEventRuleRepo(data *data.Data) badge.EventRuleRepo { + b := &eventRuleRepo{ + data: data, + } + b.EventRuleMapping = map[constant.EventType][]badge.EventRuleHandler{ + constant.EventUserUpdate: {b.FirstUpdateUserProfile}, + constant.EventUserShare: {b.FirstSharedPost}, + constant.EventQuestionCreate: nil, + constant.EventQuestionUpdate: {b.FirstPostEdit}, + constant.EventQuestionDelete: nil, + constant.EventQuestionVote: {b.FirstVotedPost, b.ReachQuestionVote}, + constant.EventQuestionAccept: {b.FirstAcceptAnswer, b.ReachAnswerAcceptedAmount}, + constant.EventQuestionFlag: {b.FirstFlaggedPost}, + constant.EventQuestionReact: {b.FirstReactedPost}, + constant.EventAnswerCreate: nil, + constant.EventAnswerUpdate: {b.FirstPostEdit}, + constant.EventAnswerDelete: nil, + constant.EventAnswerVote: {b.FirstVotedPost, b.ReachAnswerVote}, + constant.EventAnswerFlag: {b.FirstFlaggedPost}, + constant.EventAnswerReact: {b.FirstReactedPost}, + constant.EventCommentCreate: nil, + constant.EventCommentUpdate: nil, + constant.EventCommentDelete: nil, + constant.EventCommentVote: {b.FirstVotedPost}, + constant.EventCommentFlag: {b.FirstFlaggedPost}, + } + return b +} + +// HandleEventWithRule handle event with rule +func (br *eventRuleRepo) HandleEventWithRule(ctx context.Context, msg *schema.EventMsg) ( + awards []*entity.BadgeAward) { + handlers := br.EventRuleMapping[msg.EventType] + for _, h := range handlers { + t, err := h(ctx, msg) + if err != nil { + log.Errorf("error handling badge event %+v: %v", msg, err) + } else { + awards = append(awards, t...) + } + } + return awards +} + +// FirstUpdateUserProfile first update user profile +func (br *eventRuleRepo) FirstUpdateUserProfile(ctx context.Context, + event *schema.EventMsg) (awards []*entity.BadgeAward, err error) { + b := br.getBadgeByHandler(ctx, "FirstUpdateUserProfile") + if b == nil { + return nil, nil + } + bean := &entity.User{ID: event.UserID} + exist, err := br.data.DB.Context(ctx).Get(bean) + if err != nil { + return nil, errors.InternalServer(reason.DatabaseError).WithError(err).WithStack() + } + if !exist { + return nil, nil + } + if len(bean.Bio) > 0 { + return append(awards, br.createBadgeAward(event.UserID, b.ID, "")), nil + } + return nil, nil +} + +// FirstPostEdit first post edit +func (br *eventRuleRepo) FirstPostEdit(ctx context.Context, + event *schema.EventMsg) (awards []*entity.BadgeAward, err error) { + b := br.getBadgeByHandler(ctx, "FirstPostEdit") + if b == nil { + return nil, nil + } + return append(awards, br.createBadgeAward(event.UserID, b.ID, event.GetObjectID())), nil +} + +// FirstFlaggedPost first flagged post. +func (br *eventRuleRepo) FirstFlaggedPost(ctx context.Context, + event *schema.EventMsg) (awards []*entity.BadgeAward, err error) { + b := br.getBadgeByHandler(ctx, "FirstFlaggedPost") + if b == nil { + return nil, nil + } + return append(awards, br.createBadgeAward(event.UserID, b.ID, event.GetObjectID())), nil +} + +// FirstVotedPost first voted post +func (br *eventRuleRepo) FirstVotedPost(ctx context.Context, + event *schema.EventMsg) (awards []*entity.BadgeAward, err error) { + b := br.getBadgeByHandler(ctx, "FirstVotedPost") + if b == nil { + return nil, nil + } + return append(awards, br.createBadgeAward(event.UserID, b.ID, event.GetObjectID())), nil +} + +// FirstReactedPost first reacted post +func (br *eventRuleRepo) FirstReactedPost(ctx context.Context, + event *schema.EventMsg) (awards []*entity.BadgeAward, err error) { + b := br.getBadgeByHandler(ctx, "FirstReactedPost") + if b == nil { + return nil, nil + } + return append(awards, br.createBadgeAward(event.UserID, b.ID, event.GetObjectID())), nil +} + +// FirstSharedPost first shared post +func (br *eventRuleRepo) FirstSharedPost(ctx context.Context, + event *schema.EventMsg) (awards []*entity.BadgeAward, err error) { + b := br.getBadgeByHandler(ctx, "FirstSharedPost") + if b == nil { + return nil, nil + } + return append(awards, br.createBadgeAward(event.UserID, b.ID, event.GetObjectID())), nil +} + +// FirstAcceptAnswer user first accept answer +func (br *eventRuleRepo) FirstAcceptAnswer(ctx context.Context, + event *schema.EventMsg) (awards []*entity.BadgeAward, err error) { + b := br.getBadgeByHandler(ctx, "FirstAcceptAnswer") + if b == nil { + return nil, nil + } + return append(awards, br.createBadgeAward(event.UserID, b.ID, event.GetObjectID())), nil +} + +// ReachAnswerAcceptedAmount reach answer accepted amount +func (br *eventRuleRepo) ReachAnswerAcceptedAmount(ctx context.Context, + event *schema.EventMsg) (awards []*entity.BadgeAward, err error) { + b := br.getBadgeByHandler(ctx, "ReachAnswerAcceptedAmount") + if b == nil { + return nil, nil + } + return append(awards, br.createBadgeAward(event.UserID, b.ID, event.GetObjectID())), nil +} + +// ReachAnswerVote reach answer vote +func (br *eventRuleRepo) ReachAnswerVote(ctx context.Context, + event *schema.EventMsg) (awards []*entity.BadgeAward, err error) { + b := br.getBadgeByHandler(ctx, "ReachAnswerVote") + if b == nil { + return nil, nil + } + return append(awards, br.createBadgeAward(event.UserID, b.ID, event.GetObjectID())), nil +} + +// ReachQuestionVote reach question vote +func (br *eventRuleRepo) ReachQuestionVote(ctx context.Context, + event *schema.EventMsg) (awards []*entity.BadgeAward, err error) { + b := br.getBadgeByHandler(ctx, "ReachQuestionVote") + if b == nil { + return nil, nil + } + return append(awards, br.createBadgeAward(event.UserID, b.ID, event.GetObjectID())), nil +} + +func (br *eventRuleRepo) getBadgeByHandler(ctx context.Context, handler string) (b *entity.Badge) { + b = &entity.Badge{Handler: handler} + exist, err := br.data.DB.Context(ctx).Get(b) + if err != nil { + log.Errorf("error getting badge by handler %s: %v", handler, err) + return nil + } + if !exist { + log.Errorf("badge not found by handler %s", handler) + return nil + } + return b +} + +func (br *eventRuleRepo) createBadgeAward(userID, badgeID, objectID string) (awards *entity.BadgeAward) { + return &entity.BadgeAward{ + UserID: userID, + BadgeID: badgeID, + ObjectID: objectID, + } +} diff --git a/internal/repo/badge/badge_repo.go b/internal/repo/badge/badge_repo.go index 7651f95b..5030f0da 100644 --- a/internal/repo/badge/badge_repo.go +++ b/internal/repo/badge/badge_repo.go @@ -22,9 +22,11 @@ package badge import ( "context" "github.com/apache/incubator-answer/internal/base/data" + "github.com/apache/incubator-answer/internal/base/reason" "github.com/apache/incubator-answer/internal/entity" "github.com/apache/incubator-answer/internal/service/badge" "github.com/apache/incubator-answer/internal/service/unique" + "github.com/segmentfault/pacman/errors" ) type badgeRepo struct { @@ -40,9 +42,21 @@ func NewBadgeRepo(data *data.Data, uniqueIDRepo unique.UniqueIDRepo) badge.Badge } } -func (r badgeRepo) GetByID(ctx context.Context, id string) (badge *entity.Badge, exists bool, err error) { +func (r *badgeRepo) GetByID(ctx context.Context, id string) (badge *entity.Badge, exists bool, err error) { badge = &entity.Badge{} exists, err = r.data.DB.Context(ctx).Where("id = ?", id).Get(badge) + if err != nil { + err = errors.InternalServer(reason.DatabaseError).WithError(err).WithStack() + } + return +} + +func (r *badgeRepo) GetByIDs(ctx context.Context, ids []string) (badges []*entity.Badge, err error) { + badges = make([]*entity.Badge, 0) + err = r.data.DB.Context(ctx).In("id", ids).Find(&badges) + if err != nil { + err = errors.InternalServer(reason.DatabaseError).WithError(err).WithStack() + } return } @@ -50,6 +64,9 @@ func (r badgeRepo) GetByID(ctx context.Context, id string) (badge *entity.Badge, func (r *badgeRepo) ListByLevel(ctx context.Context, level entity.BadgeLevel) (badges []*entity.Badge, err error) { badges = make([]*entity.Badge, 0) err = r.data.DB.Context(ctx).Where("level = ?", level).Find(&badges) + if err != nil { + err = errors.InternalServer(reason.DatabaseError).WithError(err).WithStack() + } return } @@ -57,6 +74,9 @@ func (r *badgeRepo) ListByLevel(ctx context.Context, level entity.BadgeLevel) (b func (r *badgeRepo) ListByGroup(ctx context.Context, groupID int64) (badges []*entity.Badge, err error) { badges = make([]*entity.Badge, 0) err = r.data.DB.Context(ctx).Where("group_id = ?", groupID).Find(&badges) + if err != nil { + err = errors.InternalServer(reason.DatabaseError).WithError(err).WithStack() + } return } @@ -64,6 +84,9 @@ func (r *badgeRepo) ListByGroup(ctx context.Context, groupID int64) (badges []*e func (r *badgeRepo) ListByLevelAndGroup(ctx context.Context, level entity.BadgeLevel, groupID int64) (badges []*entity.Badge, err error) { badges = make([]*entity.Badge, 0) err = r.data.DB.Context(ctx).Where("level = ? AND group_id = ?", level, groupID).Find(&badges) + if err != nil { + err = errors.InternalServer(reason.DatabaseError).WithError(err).WithStack() + } return } @@ -71,6 +94,9 @@ func (r *badgeRepo) ListByLevelAndGroup(ctx context.Context, level entity.BadgeL func (r *badgeRepo) ListActivated(ctx context.Context) (badges []*entity.Badge, err error) { badges = make([]*entity.Badge, 0) err = r.data.DB.Context(ctx).Where("status = ?", entity.BadgeStatusActive).Find(&badges) + if err != nil { + err = errors.InternalServer(reason.DatabaseError).WithError(err).WithStack() + } return } @@ -78,5 +104,8 @@ func (r *badgeRepo) ListActivated(ctx context.Context) (badges []*entity.Badge, func (r *badgeRepo) ListInactivated(ctx context.Context) (badges []*entity.Badge, err error) { badges = make([]*entity.Badge, 0) err = r.data.DB.Context(ctx).Where("status = ?", entity.BadgeStatusInactive).Find(&badges) + if err != nil { + err = errors.InternalServer(reason.DatabaseError).WithError(err).WithStack() + } return } diff --git a/internal/repo/badge/badge_rule.go b/internal/repo/badge/badge_rule.go deleted file mode 100644 index 3ae0b7b4..00000000 --- a/internal/repo/badge/badge_rule.go +++ /dev/null @@ -1,95 +0,0 @@ -/* - * 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 badge - -import ( - "context" - "github.com/apache/incubator-answer/internal/base/data" - "github.com/apache/incubator-answer/internal/base/reason" - "github.com/apache/incubator-answer/internal/entity" - "github.com/apache/incubator-answer/internal/service/unique" - "github.com/segmentfault/pacman/errors" -) - -// BadgeRuleRepo collection repository -type BadgeRuleRepo struct { - data *data.Data - uniqueIDRepo unique.UniqueIDRepo -} - -// FilledPersonalProfile filled personal profile -func (br *BadgeRuleRepo) FilledPersonalProfile(ctx context.Context, userID string) (reach bool, err error) { - bean := &entity.User{ID: userID} - exist, err := br.data.DB.Context(ctx).Get(bean) - if err != nil { - return false, errors.InternalServer(reason.DatabaseError).WithError(err).WithStack() - } - if !exist { - return false, nil - } - if len(bean.Bio) > 0 { - return true, nil - } - return false, nil -} - -// FirstPostEdit first post edit -func (br *BadgeRuleRepo) FirstPostEdit(ctx context.Context, userID string, objectID string) { - -} - -// FirstFlaggedPost first flagged post. -func (br *BadgeRuleRepo) FirstFlaggedPost(ctx context.Context, userID string, reportID string) { -} - -// FirstVotedPost first voted post -func (br *BadgeRuleRepo) FirstVotedPost(ctx context.Context) { - -} - -// FirstReactedPost first reacted post -func (br *BadgeRuleRepo) FirstReactedPost(ctx context.Context) { - -} - -// FirstSharedPost first shared post -func (br *BadgeRuleRepo) FirstSharedPost(ctx context.Context) { - -} - -// AskQuestionAcceptAnswer ask question accept answer -func (br *BadgeRuleRepo) AskQuestionAcceptAnswer(ctx context.Context) { - -} - -// AnswerAccepted answer accepted -func (br *BadgeRuleRepo) AnswerAccepted(ctx context.Context) { - -} - -// ReachAnswerScore reach answer score -func (br *BadgeRuleRepo) ReachAnswerScore(ctx context.Context) { - -} - -// ReachQuestionScore reach question score -func (br *BadgeRuleRepo) ReachQuestionScore(ctx context.Context) { - -} diff --git a/internal/repo/badge/event_rule_mapping.go b/internal/repo/badge/event_rule_mapping.go deleted file mode 100644 index 8f01fdef..00000000 --- a/internal/repo/badge/event_rule_mapping.go +++ /dev/null @@ -1,47 +0,0 @@ -/* - * 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 badge - -import "github.com/apache/incubator-answer/internal/base/constant" - -var ( - EventRuleMapping = map[constant.EventType][]string{ - constant.EventUserUpdate: {FilledPersonalProfile}, - constant.EventUserShare: {FirstSharedPost}, - constant.EventQuestionCreate: {""}, - constant.EventQuestionUpdate: {FirstPostEdit}, - constant.EventQuestionDelete: {""}, - constant.EventQuestionVote: {FirstVotedPost, ReachQuestionScore}, - constant.EventQuestionAccept: {AskQuestionAcceptAnswer, AnswerAccepted}, - constant.EventQuestionFlag: {FirstFlaggedPost}, - constant.EventQuestionReact: {FirstReactedPost}, - constant.EventAnswerCreate: {""}, - constant.EventAnswerUpdate: {FirstPostEdit}, - constant.EventAnswerDelete: {""}, - constant.EventAnswerVote: {FirstVotedPost, ReachAnswerScore}, - constant.EventAnswerFlag: {FirstFlaggedPost}, - constant.EventAnswerReact: {FirstReactedPost}, - constant.EventCommentCreate: {""}, - constant.EventCommentUpdate: {""}, - constant.EventCommentDelete: {""}, - constant.EventCommentVote: {FirstVotedPost}, - constant.EventCommentFlag: {FirstFlaggedPost}, - } -) diff --git a/internal/repo/badge/rule.go b/internal/repo/badge/rule.go deleted file mode 100644 index 635b30da..00000000 --- a/internal/repo/badge/rule.go +++ /dev/null @@ -1,43 +0,0 @@ -/* - * 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 badge - -const ( - // FilledPersonalProfile filled personal profile - FilledPersonalProfile = "filled_personal_profile" - // FirstPostEdit first post edit - FirstPostEdit = "first_post_edit" - // FirstFlaggedPost first flagged post. - FirstFlaggedPost = "first_flagged_post" - // FirstVotedPost first voted post - FirstVotedPost = "first_voted_post" - // FirstReactedPost first reacted post - FirstReactedPost = "first_reacted_post" - // FirstSharedPost first shared post - FirstSharedPost = "first_shared_post" - // AskQuestionAcceptAnswer ask question accept answer - AskQuestionAcceptAnswer = "ask_question_accept_answer" - // AnswerAccepted answer accepted - AnswerAccepted = "answer_accepted" - // ReachAnswerScore reach answer score - ReachAnswerScore = "reach_answer_score" - // ReachQuestionScore reach question score - ReachQuestionScore = "reach_question_score" -) diff --git a/internal/repo/provider.go b/internal/repo/provider.go index ee309e02..7f222a42 100644 --- a/internal/repo/provider.go +++ b/internal/repo/provider.go @@ -104,6 +104,7 @@ var ProviderSetRepo = wire.NewSet( plugin_config.NewPluginUserConfigRepo, review.NewReviewRepo, badge.NewBadgeRepo, + badge.NewEventRuleRepo, badge_group.NewBadgeGroupRepo, badge_award.NewBadgeAwardRepo, ) diff --git a/internal/schema/event_schema.go b/internal/schema/event_schema.go index 01f80fbb..17be9627 100644 --- a/internal/schema/event_schema.go +++ b/internal/schema/event_schema.go @@ -68,3 +68,13 @@ func (e *EventMsg) AddExtra(key, value string) *EventMsg { e.ExtraInfo[key] = value return e } + +func (e *EventMsg) GetObjectID() string { + if len(e.CommentID) > 0 { + return e.CommentID + } + if len(e.AnswerID) > 0 { + return e.AnswerID + } + return e.QuestionID +} diff --git a/internal/repo/badge/badge_event_handler.go b/internal/service/badge/badge_event_handler.go similarity index 60% rename from internal/repo/badge/badge_event_handler.go rename to internal/service/badge/badge_event_handler.go index 242778ec..587ee77d 100644 --- a/internal/repo/badge/badge_event_handler.go +++ b/internal/service/badge/badge_event_handler.go @@ -21,6 +21,8 @@ package badge import ( "context" + "github.com/apache/incubator-answer/internal/entity" + "github.com/apache/incubator-answer/internal/service/badge_award" "github.com/apache/incubator-answer/internal/service/event_queue" "github.com/segmentfault/pacman/log" @@ -31,15 +33,28 @@ import ( type BadgeEventService struct { data *data.Data eventQueueService event_queue.EventQueueService + badgeAwardRepo badge_award.BadgeAwardRepo + badgeRepo BadgeRepo + eventRuleRepo EventRuleRepo +} + +type EventRuleHandler func(ctx context.Context, event *schema.EventMsg) (awards []*entity.BadgeAward, err error) + +type EventRuleRepo interface { + HandleEventWithRule(ctx context.Context, msg *schema.EventMsg) (awards []*entity.BadgeAward) } func NewBadgeEventService( data *data.Data, eventQueueService event_queue.EventQueueService, + badgeRepo BadgeRepo, + eventRuleRepo EventRuleRepo, ) *BadgeEventService { n := &BadgeEventService{ data: data, eventQueueService: eventQueueService, + badgeRepo: badgeRepo, + eventRuleRepo: eventRuleRepo, } eventQueueService.RegisterHandler(n.Handler) return n @@ -47,11 +62,24 @@ func NewBadgeEventService( func (ns *BadgeEventService) Handler(ctx context.Context, msg *schema.EventMsg) error { log.Debugf("received badge event %+v", msg) - // TODO: Check if badge already exists - // TODO: Check rule + awards := ns.eventRuleRepo.HandleEventWithRule(ctx, msg) + if len(awards) == 0 { + return nil + } - // TODO: Distribute badge + badgeIDs := make([]string, 0) + for _, award := range awards { + badgeIDs = append(badgeIDs, award.BadgeID) + } + + badges, err := ns.badgeRepo.GetByIDs(ctx, badgeIDs) + if err != nil { + log.Errorf("error getting badges %+v: %v", badgeIDs, err) + return err + } + // TODO: award badges to user + log.Debugf("awarding badges %+v to user", badges) return nil } diff --git a/internal/service/badge/badge_service.go b/internal/service/badge/badge_service.go index 94ba5b64..16087f9c 100644 --- a/internal/service/badge/badge_service.go +++ b/internal/service/badge/badge_service.go @@ -36,6 +36,7 @@ import ( type BadgeRepo interface { GetByID(ctx context.Context, id string) (badge *entity.Badge, exists bool, err error) + GetByIDs(ctx context.Context, ids []string) (badges []*entity.Badge, err error) ListByLevel(ctx context.Context, level entity.BadgeLevel) ([]*entity.Badge, error) ListByGroup(ctx context.Context, groupID int64) ([]*entity.Badge, error) ListByLevelAndGroup(ctx context.Context, level entity.BadgeLevel, groupID int64) ([]*entity.Badge, error) @@ -44,19 +45,23 @@ type BadgeRepo interface { } type BadgeService struct { - badgeRepo BadgeRepo - badgeGroupRepo badge_group.BadgeGroupRepo - badgeAwardRepo badge_award.BadgeAwardRepo + badgeRepo BadgeRepo + badgeGroupRepo badge_group.BadgeGroupRepo + badgeAwardRepo badge_award.BadgeAwardRepo + badgeEventService *BadgeEventService } func NewBadgeService( badgeRepo BadgeRepo, badgeGroupRepo badge_group.BadgeGroupRepo, - badgeAwardRepo badge_award.BadgeAwardRepo) *BadgeService { + badgeAwardRepo badge_award.BadgeAwardRepo, + badgeEventService *BadgeEventService, +) *BadgeService { return &BadgeService{ - badgeRepo: badgeRepo, - badgeGroupRepo: badgeGroupRepo, - badgeAwardRepo: badgeAwardRepo, + badgeRepo: badgeRepo, + badgeGroupRepo: badgeGroupRepo, + badgeAwardRepo: badgeAwardRepo, + badgeEventService: badgeEventService, } } diff --git a/internal/service/provider.go b/internal/service/provider.go index bf1528b8..7a6b1340 100644 --- a/internal/service/provider.go +++ b/internal/service/provider.go @@ -123,6 +123,7 @@ var ProviderSetService = wire.NewSet( meta.NewMetaService, event_queue.NewEventQueueService, badge.NewBadgeService, + badge.NewBadgeEventService, badge_award.NewBadgeAwardService, badge_group.NewBadgeGroupService, )
