mirror of https://gitee.com/answerdev/answer.git
Merge branch 'feat/1.1.2/notification' into test
This commit is contained in:
commit
119c7ddf6d
|
@ -1,6 +1,7 @@
|
||||||
package answercmd
|
package answercmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"time"
|
"time"
|
||||||
|
@ -39,7 +40,7 @@ var (
|
||||||
// @name Authorization
|
// @name Authorization
|
||||||
func Main() {
|
func Main() {
|
||||||
log.SetLogger(zap.NewLogger(
|
log.SetLogger(zap.NewLogger(
|
||||||
log.ParseLevel(logLevel), zap.WithName("answer"), zap.WithPath(logPath), zap.WithCallerFullPath()))
|
log.ParseLevel(logLevel), zap.WithName("answer"), zap.WithPath(logPath)))
|
||||||
Execute()
|
Execute()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,7 +60,7 @@ func runApp() {
|
||||||
fmt.Println("answer Version:", constant.Version, " Revision:", constant.Revision)
|
fmt.Println("answer Version:", constant.Version, " Revision:", constant.Revision)
|
||||||
|
|
||||||
defer cleanup()
|
defer cleanup()
|
||||||
if err := app.Run(); err != nil {
|
if err := app.Run(context.Background()); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -178,7 +178,7 @@ func initApplication(debug bool, serverConf *conf.Server, dbConf *data.Database,
|
||||||
collectionController := controller.NewCollectionController(collectionService)
|
collectionController := controller.NewCollectionController(collectionService)
|
||||||
answerActivityRepo := activity.NewAnswerActivityRepo(dataData, activityRepo, userRankRepo, notificationQueueService)
|
answerActivityRepo := activity.NewAnswerActivityRepo(dataData, activityRepo, userRankRepo, notificationQueueService)
|
||||||
answerActivityService := activity2.NewAnswerActivityService(answerActivityRepo, configService)
|
answerActivityService := activity2.NewAnswerActivityService(answerActivityRepo, configService)
|
||||||
externalNotificationService := notification.NewExternalNotificationService(userNotificationConfigRepo, followRepo, emailService, userRepo, externalNotificationQueueService)
|
externalNotificationService := notification.NewExternalNotificationService(dataData, userNotificationConfigRepo, followRepo, emailService, userRepo, externalNotificationQueueService)
|
||||||
questionService := service.NewQuestionService(questionRepo, tagCommonService, questionCommon, userCommon, userRepo, revisionService, metaService, collectionCommon, answerActivityService, emailService, notificationQueueService, externalNotificationQueueService, activityQueueService, siteInfoCommonService, externalNotificationService)
|
questionService := service.NewQuestionService(questionRepo, tagCommonService, questionCommon, userCommon, userRepo, revisionService, metaService, collectionCommon, answerActivityService, emailService, notificationQueueService, externalNotificationQueueService, activityQueueService, siteInfoCommonService, externalNotificationService)
|
||||||
answerService := service.NewAnswerService(answerRepo, questionRepo, questionCommon, userCommon, collectionCommon, userRepo, revisionService, answerActivityService, answerCommon, voteRepo, emailService, userRoleRelService, notificationQueueService, externalNotificationQueueService, activityQueueService)
|
answerService := service.NewAnswerService(answerRepo, questionRepo, questionCommon, userCommon, collectionCommon, userRepo, revisionService, answerActivityService, answerCommon, voteRepo, emailService, userRoleRelService, notificationQueueService, externalNotificationQueueService, activityQueueService)
|
||||||
questionController := controller.NewQuestionController(questionService, answerService, rankService, siteInfoCommonService, captchaService)
|
questionController := controller.NewQuestionController(questionService, answerService, rankService, siteInfoCommonService, captchaService)
|
||||||
|
|
4
go.mod
4
go.mod
|
@ -28,8 +28,8 @@ require (
|
||||||
github.com/ory/dockertest/v3 v3.9.1
|
github.com/ory/dockertest/v3 v3.9.1
|
||||||
github.com/robfig/cron/v3 v3.0.1
|
github.com/robfig/cron/v3 v3.0.1
|
||||||
github.com/scottleedavis/go-exif-remove v0.0.0-20230314195146-7e059d593405
|
github.com/scottleedavis/go-exif-remove v0.0.0-20230314195146-7e059d593405
|
||||||
github.com/segmentfault/pacman v1.0.4
|
github.com/segmentfault/pacman v1.0.5-0.20230822083413-c0075a2d401f
|
||||||
github.com/segmentfault/pacman/contrib/cache/memory v0.0.0-20221219081300-f734f4a16aa0
|
github.com/segmentfault/pacman/contrib/cache/memory v0.0.0-20230822083413-c0075a2d401f
|
||||||
github.com/segmentfault/pacman/contrib/conf/viper v0.0.0-20221018072427-a15dd1434e05
|
github.com/segmentfault/pacman/contrib/conf/viper v0.0.0-20221018072427-a15dd1434e05
|
||||||
github.com/segmentfault/pacman/contrib/i18n v0.0.0-20230516093754-b76aef1c1150
|
github.com/segmentfault/pacman/contrib/i18n v0.0.0-20230516093754-b76aef1c1150
|
||||||
github.com/segmentfault/pacman/contrib/log/zap v0.0.0-20221018072427-a15dd1434e05
|
github.com/segmentfault/pacman/contrib/log/zap v0.0.0-20221018072427-a15dd1434e05
|
||||||
|
|
14
go.sum
14
go.sum
|
@ -91,6 +91,7 @@ github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZw
|
||||||
github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk=
|
github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk=
|
||||||
github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4=
|
github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4=
|
||||||
github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
|
github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
|
||||||
|
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
|
||||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||||
|
@ -640,10 +641,14 @@ github.com/scottleedavis/go-exif-remove v0.0.0-20230314195146-7e059d593405 h1:2i
|
||||||
github.com/scottleedavis/go-exif-remove v0.0.0-20230314195146-7e059d593405/go.mod h1:rIxVzVLKlBwLxO+lC+k/I4HJfRQcemg/f/76Xmmzsec=
|
github.com/scottleedavis/go-exif-remove v0.0.0-20230314195146-7e059d593405/go.mod h1:rIxVzVLKlBwLxO+lC+k/I4HJfRQcemg/f/76Xmmzsec=
|
||||||
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
|
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
|
||||||
github.com/seccomp/libseccomp-golang v0.9.2-0.20210429002308-3879420cc921/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg=
|
github.com/seccomp/libseccomp-golang v0.9.2-0.20210429002308-3879420cc921/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg=
|
||||||
github.com/segmentfault/pacman v1.0.4 h1:6UIXuMHUeYMWe5toflV9SXZQizRny1RczjZJLj9kul0=
|
github.com/segmentfault/pacman v1.0.5-0.20230822075009-309985fb8700 h1:VqxiuNGQg86GEKxnzmJegZR2Ufr7EVXo68mdKaf+/MQ=
|
||||||
github.com/segmentfault/pacman v1.0.4/go.mod h1:5lNp5REd8QMThmBUvR3Fi9Y3AsOB4GRq7soCB4QLqOs=
|
github.com/segmentfault/pacman v1.0.5-0.20230822075009-309985fb8700/go.mod h1:5lNp5REd8QMThmBUvR3Fi9Y3AsOB4GRq7soCB4QLqOs=
|
||||||
github.com/segmentfault/pacman/contrib/cache/memory v0.0.0-20221219081300-f734f4a16aa0 h1:4x0qG7H2M3qH7Yo2BhGrVlji1iTmRAWgINY/JyENeHs=
|
github.com/segmentfault/pacman v1.0.5-0.20230822083413-c0075a2d401f h1:9f2Bjf6bdMvNyUop32wAGJCdp+Jdm/d6nKBYvFvkRo0=
|
||||||
github.com/segmentfault/pacman/contrib/cache/memory v0.0.0-20221219081300-f734f4a16aa0/go.mod h1:rmf1TCwz67dyM+AmTwSd1BxTo2AOYHj262lP93bOZbs=
|
github.com/segmentfault/pacman v1.0.5-0.20230822083413-c0075a2d401f/go.mod h1:5lNp5REd8QMThmBUvR3Fi9Y3AsOB4GRq7soCB4QLqOs=
|
||||||
|
github.com/segmentfault/pacman/contrib/cache/memory v0.0.0-20230822075009-309985fb8700 h1:VZpexPTcr7sOxxYUGa/9cneyCESfisAhCNbaEuTpcwI=
|
||||||
|
github.com/segmentfault/pacman/contrib/cache/memory v0.0.0-20230822075009-309985fb8700/go.mod h1:rmf1TCwz67dyM+AmTwSd1BxTo2AOYHj262lP93bOZbs=
|
||||||
|
github.com/segmentfault/pacman/contrib/cache/memory v0.0.0-20230822083413-c0075a2d401f h1:1KHe0uN6p798E7XJZPhZkgm/hXk5CTjisCvFMqaZSKI=
|
||||||
|
github.com/segmentfault/pacman/contrib/cache/memory v0.0.0-20230822083413-c0075a2d401f/go.mod h1:rmf1TCwz67dyM+AmTwSd1BxTo2AOYHj262lP93bOZbs=
|
||||||
github.com/segmentfault/pacman/contrib/conf/viper v0.0.0-20221018072427-a15dd1434e05 h1:BlqTgc3/MYKG6vMI2MI+6o+7P4Gy5PXlawu185wPXAk=
|
github.com/segmentfault/pacman/contrib/conf/viper v0.0.0-20221018072427-a15dd1434e05 h1:BlqTgc3/MYKG6vMI2MI+6o+7P4Gy5PXlawu185wPXAk=
|
||||||
github.com/segmentfault/pacman/contrib/conf/viper v0.0.0-20221018072427-a15dd1434e05/go.mod h1:prPjFam7MyZ5b3S9dcDOt2tMPz6kf7C9c243s9zSwPY=
|
github.com/segmentfault/pacman/contrib/conf/viper v0.0.0-20221018072427-a15dd1434e05/go.mod h1:prPjFam7MyZ5b3S9dcDOt2tMPz6kf7C9c243s9zSwPY=
|
||||||
github.com/segmentfault/pacman/contrib/i18n v0.0.0-20230516093754-b76aef1c1150 h1:OEuW1D7RGDE0CZDr0oGMw9Eiq7fAbD9C4WMrvSixamk=
|
github.com/segmentfault/pacman/contrib/i18n v0.0.0-20230516093754-b76aef1c1150 h1:OEuW1D7RGDE0CZDr0oGMw9Eiq7fAbD9C4WMrvSixamk=
|
||||||
|
@ -772,6 +777,7 @@ go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||||
go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ=
|
go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ=
|
||||||
go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
|
go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
|
||||||
go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI=
|
go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI=
|
||||||
|
go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
|
||||||
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
||||||
go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4=
|
go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4=
|
||||||
go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU=
|
go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU=
|
||||||
|
|
|
@ -3,20 +3,23 @@ package constant
|
||||||
import "time"
|
import "time"
|
||||||
|
|
||||||
const (
|
const (
|
||||||
UserStatusChangedCacheKey = "answer:user:status:"
|
UserStatusChangedCacheKey = "answer:user:status:"
|
||||||
UserStatusChangedCacheTime = 7 * 24 * time.Hour
|
UserStatusChangedCacheTime = 7 * 24 * time.Hour
|
||||||
UserTokenCacheKey = "answer:user:token:"
|
UserTokenCacheKey = "answer:user:token:"
|
||||||
UserTokenCacheTime = 7 * 24 * time.Hour
|
UserTokenCacheTime = 7 * 24 * time.Hour
|
||||||
AdminTokenCacheKey = "answer:admin:token:"
|
AdminTokenCacheKey = "answer:admin:token:"
|
||||||
AdminTokenCacheTime = 7 * 24 * time.Hour
|
AdminTokenCacheTime = 7 * 24 * time.Hour
|
||||||
UserTokenMappingCacheKey = "answer:user-token:mapping:"
|
UserTokenMappingCacheKey = "answer:user-token:mapping:"
|
||||||
SiteInfoCacheKey = "answer:site-info:"
|
SiteInfoCacheKey = "answer:site-info:"
|
||||||
SiteInfoCacheTime = 1 * time.Hour
|
SiteInfoCacheTime = 1 * time.Hour
|
||||||
ConfigID2KEYCacheKeyPrefix = "answer:config:id:"
|
ConfigID2KEYCacheKeyPrefix = "answer:config:id:"
|
||||||
ConfigKEY2ContentCacheKeyPrefix = "answer:config:key:"
|
ConfigKEY2ContentCacheKeyPrefix = "answer:config:key:"
|
||||||
ConnectorUserExternalInfoCacheKey = "answer:connector:"
|
ConnectorUserExternalInfoCacheKey = "answer:connector:"
|
||||||
ConnectorUserExternalInfoCacheTime = 10 * time.Minute
|
ConnectorUserExternalInfoCacheTime = 10 * time.Minute
|
||||||
SiteMapQuestionCacheKeyPrefix = "answer:sitemap:question:%d"
|
SiteMapQuestionCacheKeyPrefix = "answer:sitemap:question:%d"
|
||||||
SiteMapQuestionCacheTime = time.Hour
|
SiteMapQuestionCacheTime = time.Hour
|
||||||
SitemapMaxSize = 50000
|
SitemapMaxSize = 50000
|
||||||
|
NewQuestionNotificationLimitCacheKeyPrefix = "answer:new-question-notification-limit:"
|
||||||
|
NewQuestionNotificationLimitCacheTime = 7 * 24 * time.Hour
|
||||||
|
NewQuestionNotificationLimitMax = 50
|
||||||
)
|
)
|
||||||
|
|
|
@ -71,7 +71,7 @@ var migrations = []Migration{
|
||||||
NewMigration("v1.1.0-beta.2", "update question post time", updateQuestionPostTime, true),
|
NewMigration("v1.1.0-beta.2", "update question post time", updateQuestionPostTime, true),
|
||||||
NewMigration("v1.1.0", "add gravatar base url", updateCount, true),
|
NewMigration("v1.1.0", "add gravatar base url", updateCount, true),
|
||||||
NewMigration("v1.1.1", "update the length of revision content", updateTheLengthOfRevisionContent, false),
|
NewMigration("v1.1.1", "update the length of revision content", updateTheLengthOfRevisionContent, false),
|
||||||
NewMigration("v1.1.2", "add notification config", addNoticeConfig, false),
|
NewMigration("v1.1.2", "add notification config", addNoticeConfig, true),
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetMigrations() []Migration {
|
func GetMigrations() []Migration {
|
||||||
|
|
|
@ -27,15 +27,15 @@ func NewAuthRepo(data *data.Data) auth.AuthRepo {
|
||||||
|
|
||||||
// GetUserCacheInfo get user cache info
|
// GetUserCacheInfo get user cache info
|
||||||
func (ar *authRepo) GetUserCacheInfo(ctx context.Context, accessToken string) (userInfo *entity.UserCacheInfo, err error) {
|
func (ar *authRepo) GetUserCacheInfo(ctx context.Context, accessToken string) (userInfo *entity.UserCacheInfo, err error) {
|
||||||
userInfoCache, err := ar.data.Cache.GetString(ctx, constant.UserTokenCacheKey+accessToken)
|
userInfoCache, exist, err := ar.data.Cache.GetString(ctx, constant.UserTokenCacheKey+accessToken)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
|
return nil, errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
|
||||||
}
|
}
|
||||||
|
if !exist {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
userInfo = &entity.UserCacheInfo{}
|
userInfo = &entity.UserCacheInfo{}
|
||||||
err = json.Unmarshal([]byte(userInfoCache), userInfo)
|
_ = json.Unmarshal([]byte(userInfoCache), userInfo)
|
||||||
if err != nil {
|
|
||||||
return nil, errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
|
|
||||||
}
|
|
||||||
return userInfo, nil
|
return userInfo, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,15 +81,15 @@ func (ar *authRepo) SetUserStatus(ctx context.Context, userID string, userInfo *
|
||||||
|
|
||||||
// GetUserStatus get user status
|
// GetUserStatus get user status
|
||||||
func (ar *authRepo) GetUserStatus(ctx context.Context, userID string) (userInfo *entity.UserCacheInfo, err error) {
|
func (ar *authRepo) GetUserStatus(ctx context.Context, userID string) (userInfo *entity.UserCacheInfo, err error) {
|
||||||
userInfoCache, err := ar.data.Cache.GetString(ctx, constant.UserStatusChangedCacheKey+userID)
|
userInfoCache, exist, err := ar.data.Cache.GetString(ctx, constant.UserStatusChangedCacheKey+userID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
|
return nil, errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
|
||||||
}
|
}
|
||||||
|
if !exist {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
userInfo = &entity.UserCacheInfo{}
|
userInfo = &entity.UserCacheInfo{}
|
||||||
err = json.Unmarshal([]byte(userInfoCache), userInfo)
|
_ = json.Unmarshal([]byte(userInfoCache), userInfo)
|
||||||
if err != nil {
|
|
||||||
return nil, errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
|
|
||||||
}
|
|
||||||
return userInfo, nil
|
return userInfo, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,16 +104,16 @@ func (ar *authRepo) RemoveUserStatus(ctx context.Context, userID string) (err er
|
||||||
|
|
||||||
// GetAdminUserCacheInfo get admin user cache info
|
// GetAdminUserCacheInfo get admin user cache info
|
||||||
func (ar *authRepo) GetAdminUserCacheInfo(ctx context.Context, accessToken string) (userInfo *entity.UserCacheInfo, err error) {
|
func (ar *authRepo) GetAdminUserCacheInfo(ctx context.Context, accessToken string) (userInfo *entity.UserCacheInfo, err error) {
|
||||||
userInfoCache, err := ar.data.Cache.GetString(ctx, constant.AdminTokenCacheKey+accessToken)
|
userInfoCache, exist, err := ar.data.Cache.GetString(ctx, constant.AdminTokenCacheKey+accessToken)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
|
err = errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
userInfo = &entity.UserCacheInfo{}
|
if !exist {
|
||||||
err = json.Unmarshal([]byte(userInfoCache), userInfo)
|
return nil, nil
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
|
userInfo = &entity.UserCacheInfo{}
|
||||||
|
_ = json.Unmarshal([]byte(userInfoCache), userInfo)
|
||||||
return userInfo, nil
|
return userInfo, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -144,7 +144,10 @@ func (ar *authRepo) RemoveAdminUserCacheInfo(ctx context.Context, accessToken st
|
||||||
// AddUserTokenMapping add user token mapping
|
// AddUserTokenMapping add user token mapping
|
||||||
func (ar *authRepo) AddUserTokenMapping(ctx context.Context, userID, accessToken string) (err error) {
|
func (ar *authRepo) AddUserTokenMapping(ctx context.Context, userID, accessToken string) (err error) {
|
||||||
key := constant.UserTokenMappingCacheKey + userID
|
key := constant.UserTokenMappingCacheKey + userID
|
||||||
resp, _ := ar.data.Cache.GetString(ctx, key)
|
resp, _, err := ar.data.Cache.GetString(ctx, key)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
mapping := make(map[string]bool, 0)
|
mapping := make(map[string]bool, 0)
|
||||||
if len(resp) > 0 {
|
if len(resp) > 0 {
|
||||||
_ = json.Unmarshal([]byte(resp), &mapping)
|
_ = json.Unmarshal([]byte(resp), &mapping)
|
||||||
|
@ -157,7 +160,10 @@ func (ar *authRepo) AddUserTokenMapping(ctx context.Context, userID, accessToken
|
||||||
// RemoveUserTokens Log out all users under this user id
|
// RemoveUserTokens Log out all users under this user id
|
||||||
func (ar *authRepo) RemoveUserTokens(ctx context.Context, userID string, remainToken string) {
|
func (ar *authRepo) RemoveUserTokens(ctx context.Context, userID string, remainToken string) {
|
||||||
key := constant.UserTokenMappingCacheKey + userID
|
key := constant.UserTokenMappingCacheKey + userID
|
||||||
resp, _ := ar.data.Cache.GetString(ctx, key)
|
resp, _, err := ar.data.Cache.GetString(ctx, key)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
mapping := make(map[string]bool, 0)
|
mapping := make(map[string]bool, 0)
|
||||||
if len(resp) > 0 {
|
if len(resp) > 0 {
|
||||||
_ = json.Unmarshal([]byte(resp), &mapping)
|
_ = json.Unmarshal([]byte(resp), &mapping)
|
||||||
|
|
|
@ -43,19 +43,19 @@ func (cr *captchaRepo) SetActionType(ctx context.Context, unit, actionType, conf
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cr *captchaRepo) GetActionType(ctx context.Context, unit, actionType string) (actioninfo *entity.ActionRecordInfo, err error) {
|
func (cr *captchaRepo) GetActionType(ctx context.Context, unit, actionType string) (actionInfo *entity.ActionRecordInfo, err error) {
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
cacheKey := fmt.Sprintf("ActionRecord:%s@%s@%s", unit, actionType, now.Format("2006-1-02"))
|
cacheKey := fmt.Sprintf("ActionRecord:%s@%s@%s", unit, actionType, now.Format("2006-1-02"))
|
||||||
actioninfo = &entity.ActionRecordInfo{}
|
res, exist, err := cr.data.Cache.GetString(ctx, cacheKey)
|
||||||
res, err := cr.data.Cache.GetString(ctx, cacheKey)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
|
return nil, err
|
||||||
}
|
}
|
||||||
err = json.Unmarshal([]byte(res), actioninfo)
|
if !exist {
|
||||||
if err != nil {
|
return nil, nil
|
||||||
return actioninfo, nil
|
|
||||||
}
|
}
|
||||||
return actioninfo, nil
|
actionInfo = &entity.ActionRecordInfo{}
|
||||||
|
_ = json.Unmarshal([]byte(res), actionInfo)
|
||||||
|
return actionInfo, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cr *captchaRepo) DelActionType(ctx context.Context, unit, actionType string) (err error) {
|
func (cr *captchaRepo) DelActionType(ctx context.Context, unit, actionType string) (err error) {
|
||||||
|
@ -79,9 +79,12 @@ func (cr *captchaRepo) SetCaptcha(ctx context.Context, key, captcha string) (err
|
||||||
|
|
||||||
// GetCaptcha get captcha from cache
|
// GetCaptcha get captcha from cache
|
||||||
func (cr *captchaRepo) GetCaptcha(ctx context.Context, key string) (captcha string, err error) {
|
func (cr *captchaRepo) GetCaptcha(ctx context.Context, key string) (captcha string, err error) {
|
||||||
captcha, err = cr.data.Cache.GetString(ctx, key)
|
captcha, exist, err := cr.data.Cache.GetString(ctx, key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Debug(err)
|
return "", err
|
||||||
|
}
|
||||||
|
if !exist {
|
||||||
|
return "", fmt.Errorf("captcha not exist")
|
||||||
}
|
}
|
||||||
return captcha, nil
|
return captcha, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,7 @@ func NewConfigRepo(data *data.Data) config.ConfigRepo {
|
||||||
|
|
||||||
func (cr configRepo) GetConfigByID(ctx context.Context, id int) (c *entity.Config, err error) {
|
func (cr configRepo) GetConfigByID(ctx context.Context, id int) (c *entity.Config, err error) {
|
||||||
cacheKey := fmt.Sprintf("%s%d", constant.ConfigID2KEYCacheKeyPrefix, id)
|
cacheKey := fmt.Sprintf("%s%d", constant.ConfigID2KEYCacheKeyPrefix, id)
|
||||||
if cacheData, err := cr.data.Cache.GetString(ctx, cacheKey); err == nil && len(cacheData) > 0 {
|
if cacheData, exist, err := cr.data.Cache.GetString(ctx, cacheKey); err == nil && exist {
|
||||||
c = &entity.Config{}
|
c = &entity.Config{}
|
||||||
c.BuildByJSON([]byte(cacheData))
|
c.BuildByJSON([]byte(cacheData))
|
||||||
if c.ID > 0 {
|
if c.ID > 0 {
|
||||||
|
@ -54,7 +54,7 @@ func (cr configRepo) GetConfigByID(ctx context.Context, id int) (c *entity.Confi
|
||||||
|
|
||||||
func (cr configRepo) GetConfigByKey(ctx context.Context, key string) (c *entity.Config, err error) {
|
func (cr configRepo) GetConfigByKey(ctx context.Context, key string) (c *entity.Config, err error) {
|
||||||
cacheKey := constant.ConfigKEY2ContentCacheKeyPrefix + key
|
cacheKey := constant.ConfigKEY2ContentCacheKeyPrefix + key
|
||||||
if cacheData, err := cr.data.Cache.GetString(ctx, cacheKey); err == nil && len(cacheData) > 0 {
|
if cacheData, exist, err := cr.data.Cache.GetString(ctx, cacheKey); err == nil && exist {
|
||||||
c = &entity.Config{}
|
c = &entity.Config{}
|
||||||
c.BuildByJSON([]byte(cacheData))
|
c.BuildByJSON([]byte(cacheData))
|
||||||
if c.ID > 0 {
|
if c.ID > 0 {
|
||||||
|
|
|
@ -33,9 +33,12 @@ func (e *emailRepo) SetCode(ctx context.Context, code, content string, duration
|
||||||
|
|
||||||
// VerifyCode verify the code if out of date
|
// VerifyCode verify the code if out of date
|
||||||
func (e *emailRepo) VerifyCode(ctx context.Context, code string) (content string, err error) {
|
func (e *emailRepo) VerifyCode(ctx context.Context, code string) (content string, err error) {
|
||||||
content, err = e.data.Cache.GetString(ctx, code)
|
content, exist, err := e.data.Cache.GetString(ctx, code)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
|
return "", err
|
||||||
}
|
}
|
||||||
return
|
if !exist {
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
return content, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -259,8 +259,8 @@ func (qr *questionRepo) SitemapQuestions(ctx context.Context, page, pageSize int
|
||||||
|
|
||||||
// try to get sitemap data from cache
|
// try to get sitemap data from cache
|
||||||
cacheKey := fmt.Sprintf(constant.SiteMapQuestionCacheKeyPrefix, page)
|
cacheKey := fmt.Sprintf(constant.SiteMapQuestionCacheKeyPrefix, page)
|
||||||
cacheData, err := qr.data.Cache.GetString(ctx, cacheKey)
|
cacheData, exist, err := qr.data.Cache.GetString(ctx, cacheKey)
|
||||||
if err == nil && len(cacheKey) > 0 {
|
if err == nil && exist {
|
||||||
_ = json.Unmarshal([]byte(cacheData), &questionIDList)
|
_ = json.Unmarshal([]byte(cacheData), &questionIDList)
|
||||||
return questionIDList, nil
|
return questionIDList, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,6 +53,7 @@ func (sr *siteInfoRepo) GetByType(ctx context.Context, siteType string) (siteInf
|
||||||
exist, err = sr.data.DB.Context(ctx).Where(builder.Eq{"type": siteType}).Get(siteInfo)
|
exist, err = sr.data.DB.Context(ctx).Where(builder.Eq{"type": siteType}).Get(siteInfo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
|
err = errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
|
||||||
|
return nil, false, err
|
||||||
}
|
}
|
||||||
if exist {
|
if exist {
|
||||||
sr.setCache(ctx, siteType, siteInfo)
|
sr.setCache(ctx, siteType, siteInfo)
|
||||||
|
@ -61,11 +62,14 @@ func (sr *siteInfoRepo) GetByType(ctx context.Context, siteType string) (siteInf
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sr *siteInfoRepo) getCache(ctx context.Context, siteType string) (siteInfo *entity.SiteInfo) {
|
func (sr *siteInfoRepo) getCache(ctx context.Context, siteType string) (siteInfo *entity.SiteInfo) {
|
||||||
siteInfo = &entity.SiteInfo{}
|
siteInfoCache, exist, err := sr.data.Cache.GetString(ctx, constant.SiteInfoCacheKey+siteType)
|
||||||
siteInfoCache, err := sr.data.Cache.GetString(ctx, constant.SiteInfoCacheKey+siteType)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
if !exist {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
siteInfo = &entity.SiteInfo{}
|
||||||
_ = json.Unmarshal([]byte(siteInfoCache), siteInfo)
|
_ = json.Unmarshal([]byte(siteInfoCache), siteInfo)
|
||||||
return siteInfo
|
return siteInfo
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,10 +85,14 @@ func (ur *userExternalLoginRepo) SetCacheUserExternalLoginInfo(
|
||||||
// GetCacheUserExternalLoginInfo cache user info for external login
|
// GetCacheUserExternalLoginInfo cache user info for external login
|
||||||
func (ur *userExternalLoginRepo) GetCacheUserExternalLoginInfo(
|
func (ur *userExternalLoginRepo) GetCacheUserExternalLoginInfo(
|
||||||
ctx context.Context, key string) (info *schema.ExternalLoginUserInfoCache, err error) {
|
ctx context.Context, key string) (info *schema.ExternalLoginUserInfoCache, err error) {
|
||||||
res, err := ur.data.Cache.GetString(ctx, constant.ConnectorUserExternalInfoCacheKey+key)
|
res, exist, err := ur.data.Cache.GetString(ctx, constant.ConnectorUserExternalInfoCacheKey+key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return info, err
|
return info, err
|
||||||
}
|
}
|
||||||
|
if !exist {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
info = &schema.ExternalLoginUserInfoCache{}
|
||||||
_ = json.Unmarshal([]byte(res), &info)
|
_ = json.Unmarshal([]byte(res), &info)
|
||||||
return info, nil
|
return info, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -87,11 +87,12 @@ type NewCommentTemplateData struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type NewQuestionTemplateRawData struct {
|
type NewQuestionTemplateRawData struct {
|
||||||
QuestionTitle string
|
QuestionAuthorUserID string
|
||||||
QuestionID string
|
QuestionTitle string
|
||||||
UnsubscribeCode string
|
QuestionID string
|
||||||
Tags []string
|
UnsubscribeCode string
|
||||||
TagIDs []string
|
Tags []string
|
||||||
|
TagIDs []string
|
||||||
}
|
}
|
||||||
|
|
||||||
type NewQuestionTemplateData struct {
|
type NewQuestionTemplateData struct {
|
||||||
|
|
|
@ -16,12 +16,14 @@ type ExternalNotificationMsg struct {
|
||||||
NewQuestionTemplateRawData *NewQuestionTemplateRawData `json:"new_question_template_raw_data,omitempty"`
|
NewQuestionTemplateRawData *NewQuestionTemplateRawData `json:"new_question_template_raw_data,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func CreateNewQuestionNotificationMsg(questionID, questionTitle string, tags []*entity.Tag) *ExternalNotificationMsg {
|
func CreateNewQuestionNotificationMsg(
|
||||||
|
questionID, questionTitle, questionAuthorUserID string, tags []*entity.Tag) *ExternalNotificationMsg {
|
||||||
questionID = uid.DeShortID(questionID)
|
questionID = uid.DeShortID(questionID)
|
||||||
msg := &ExternalNotificationMsg{
|
msg := &ExternalNotificationMsg{
|
||||||
NewQuestionTemplateRawData: &NewQuestionTemplateRawData{
|
NewQuestionTemplateRawData: &NewQuestionTemplateRawData{
|
||||||
QuestionID: questionID,
|
QuestionAuthorUserID: questionAuthorUserID,
|
||||||
QuestionTitle: questionTitle,
|
QuestionID: questionID,
|
||||||
|
QuestionTitle: questionTitle,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tag := range tags {
|
for _, tag := range tags {
|
||||||
|
|
|
@ -111,17 +111,20 @@ func (cs *CaptchaService) ActionRecordVerifyCaptcha(
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cs *CaptchaService) ActionRecordAdd(ctx context.Context, actionType string, unit string) (int, error) {
|
func (cs *CaptchaService) ActionRecordAdd(ctx context.Context, actionType string, unit string) (int, error) {
|
||||||
var err error
|
info, err := cs.captchaRepo.GetActionType(ctx, unit, actionType)
|
||||||
info, cahceErr := cs.captchaRepo.GetActionType(ctx, unit, actionType)
|
if err != nil {
|
||||||
if cahceErr != nil {
|
|
||||||
log.Error(err)
|
log.Error(err)
|
||||||
|
return 0, err
|
||||||
}
|
}
|
||||||
info.Num++
|
amount := 1
|
||||||
err = cs.captchaRepo.SetActionType(ctx, unit, actionType, "", info.Num)
|
if info != nil {
|
||||||
|
amount = info.Num + 1
|
||||||
|
}
|
||||||
|
err = cs.captchaRepo.SetActionType(ctx, unit, actionType, "", amount)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
return info.Num, nil
|
return amount, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cs *CaptchaService) ActionRecordDel(ctx context.Context, actionType string, unit string) {
|
func (cs *CaptchaService) ActionRecordDel(ctx context.Context, actionType string, unit string) {
|
||||||
|
|
|
@ -2,6 +2,7 @@ package action
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"github.com/segmentfault/pacman/log"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/answerdev/answer/internal/entity"
|
"github.com/answerdev/answer/internal/entity"
|
||||||
|
@ -13,8 +14,14 @@ import (
|
||||||
func (cs *CaptchaService) ValidationStrategy(ctx context.Context, unit, actionType string) bool {
|
func (cs *CaptchaService) ValidationStrategy(ctx context.Context, unit, actionType string) bool {
|
||||||
info, err := cs.captchaRepo.GetActionType(ctx, unit, actionType)
|
info, err := cs.captchaRepo.GetActionType(ctx, unit, actionType)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
//No record, no processing
|
log.Error(err)
|
||||||
//
|
return false
|
||||||
|
}
|
||||||
|
if info == nil {
|
||||||
|
info = &entity.ActionRecordInfo{
|
||||||
|
LastTime: time.Now().Unix(),
|
||||||
|
Num: 1,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
switch actionType {
|
switch actionType {
|
||||||
case entity.CaptchaActionEmail:
|
case entity.CaptchaActionEmail:
|
||||||
|
|
|
@ -41,6 +41,9 @@ func (as *AuthService) GetUserCacheInfo(ctx context.Context, accessToken string)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
if userCacheInfo == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
cacheInfo, _ := as.authRepo.GetUserStatus(ctx, userCacheInfo.UserID)
|
cacheInfo, _ := as.authRepo.GetUserStatus(ctx, userCacheInfo.UserID)
|
||||||
if cacheInfo != nil {
|
if cacheInfo != nil {
|
||||||
userCacheInfo.UserStatus = cacheInfo.UserStatus
|
userCacheInfo.UserStatus = cacheInfo.UserStatus
|
||||||
|
|
|
@ -70,8 +70,8 @@ type DashboardService interface {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ds *dashboardService) Statistical(ctx context.Context) (*schema.DashboardInfo, error) {
|
func (ds *dashboardService) Statistical(ctx context.Context) (*schema.DashboardInfo, error) {
|
||||||
dashboardInfo, err := ds.getFromCache(ctx)
|
dashboardInfo := ds.getFromCache(ctx)
|
||||||
if err != nil {
|
if dashboardInfo == nil {
|
||||||
dashboardInfo = &schema.DashboardInfo{}
|
dashboardInfo = &schema.DashboardInfo{}
|
||||||
dashboardInfo.QuestionCount = ds.questionCount(ctx)
|
dashboardInfo.QuestionCount = ds.questionCount(ctx)
|
||||||
dashboardInfo.AnswerCount = ds.answerCount(ctx)
|
dashboardInfo.AnswerCount = ds.answerCount(ctx)
|
||||||
|
@ -95,16 +95,20 @@ func (ds *dashboardService) Statistical(ctx context.Context) (*schema.DashboardI
|
||||||
return dashboardInfo, nil
|
return dashboardInfo, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ds *dashboardService) getFromCache(ctx context.Context) (*schema.DashboardInfo, error) {
|
func (ds *dashboardService) getFromCache(ctx context.Context) (dashboardInfo *schema.DashboardInfo) {
|
||||||
infoStr, err := ds.data.Cache.GetString(ctx, schema.DashboardCacheKey)
|
infoStr, exist, err := ds.data.Cache.GetString(ctx, schema.DashboardCacheKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
log.Errorf("get dashboard statistical from cache failed: %s", err)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
dashboardInfo := &schema.DashboardInfo{}
|
if !exist {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
dashboardInfo = &schema.DashboardInfo{}
|
||||||
if err = json.Unmarshal([]byte(infoStr), dashboardInfo); err != nil {
|
if err = json.Unmarshal([]byte(infoStr), dashboardInfo); err != nil {
|
||||||
return nil, err
|
return nil
|
||||||
}
|
}
|
||||||
return dashboardInfo, nil
|
return dashboardInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ds *dashboardService) setCache(ctx context.Context, info *schema.DashboardInfo) {
|
func (ds *dashboardService) setCache(ctx context.Context, info *schema.DashboardInfo) {
|
||||||
|
|
|
@ -145,7 +145,7 @@ func (es *EmailService) Send(ctx context.Context, toEmailAddr, subject, body str
|
||||||
func (es *EmailService) VerifyUrlExpired(ctx context.Context, code string) (content string) {
|
func (es *EmailService) VerifyUrlExpired(ctx context.Context, code string) (content string) {
|
||||||
content, err := es.emailRepo.VerifyCode(ctx, code)
|
content, err := es.emailRepo.VerifyCode(ctx, code)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warn(err)
|
log.Error(err)
|
||||||
}
|
}
|
||||||
return content
|
return content
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@ type ExternalNotificationService struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewExternalNotificationService(
|
func NewExternalNotificationService(
|
||||||
|
data *data.Data,
|
||||||
userNotificationConfigRepo user_notification_config.UserNotificationConfigRepo,
|
userNotificationConfigRepo user_notification_config.UserNotificationConfigRepo,
|
||||||
followRepo activity_common.FollowRepo,
|
followRepo activity_common.FollowRepo,
|
||||||
emailService *export.EmailService,
|
emailService *export.EmailService,
|
||||||
|
@ -29,6 +30,7 @@ func NewExternalNotificationService(
|
||||||
notificationQueueService notice_queue.ExternalNotificationQueueService,
|
notificationQueueService notice_queue.ExternalNotificationQueueService,
|
||||||
) *ExternalNotificationService {
|
) *ExternalNotificationService {
|
||||||
n := &ExternalNotificationService{
|
n := &ExternalNotificationService{
|
||||||
|
data: data,
|
||||||
userNotificationConfigRepo: userNotificationConfigRepo,
|
userNotificationConfigRepo: userNotificationConfigRepo,
|
||||||
followRepo: followRepo,
|
followRepo: followRepo,
|
||||||
emailService: emailService,
|
emailService: emailService,
|
||||||
|
|
|
@ -78,7 +78,6 @@ func (ns *ExternalNotificationService) getNewQuestionSubscribers(ctx context.Con
|
||||||
UserID: userNotificationConfig.UserID,
|
UserID: userNotificationConfig.UserID,
|
||||||
Channels: schema.NewNotificationChannelsFormJson(userNotificationConfig.Channels),
|
Channels: schema.NewNotificationChannelsFormJson(userNotificationConfig.Channels),
|
||||||
}
|
}
|
||||||
subscribers = append(subscribers, subscribersMapping[userNotificationConfig.UserID])
|
|
||||||
}
|
}
|
||||||
log.Debugf("get %d subscribers from tags", len(subscribersMapping))
|
log.Debugf("get %d subscribers from tags", len(subscribersMapping))
|
||||||
|
|
||||||
|
@ -98,14 +97,36 @@ func (ns *ExternalNotificationService) getNewQuestionSubscribers(ctx context.Con
|
||||||
UserID: notificationConfig.UserID,
|
UserID: notificationConfig.UserID,
|
||||||
Channels: schema.NewNotificationChannelsFormJson(notificationConfig.Channels),
|
Channels: schema.NewNotificationChannelsFormJson(notificationConfig.Channels),
|
||||||
}
|
}
|
||||||
subscribers = append(subscribers, subscribersMapping[notificationConfig.UserID])
|
}
|
||||||
|
|
||||||
|
// 3. remove question owner
|
||||||
|
delete(subscribersMapping, msg.NewQuestionTemplateRawData.QuestionAuthorUserID)
|
||||||
|
for _, subscriber := range subscribersMapping {
|
||||||
|
subscribers = append(subscribers, subscriber)
|
||||||
}
|
}
|
||||||
log.Debugf("get %d subscribers from all new question config", len(subscribers))
|
log.Debugf("get %d subscribers from all new question config", len(subscribers))
|
||||||
return subscribers, nil
|
return subscribers, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ns *ExternalNotificationService) checkSendNewQuestionNotificationEmailLimit(ctx context.Context, userID string) bool {
|
func (ns *ExternalNotificationService) checkSendNewQuestionNotificationEmailLimit(ctx context.Context, userID string) bool {
|
||||||
// TODO: check if reach send limit
|
key := constant.NewQuestionNotificationLimitCacheKeyPrefix + userID
|
||||||
|
old, exist, err := ns.data.Cache.GetInt64(ctx, key)
|
||||||
|
if err != nil {
|
||||||
|
log.Error(err)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if exist && old >= constant.NewQuestionNotificationLimitMax {
|
||||||
|
log.Debugf("%s user reach new question notification limit", userID)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if !exist {
|
||||||
|
err = ns.data.Cache.SetInt64(ctx, key, 1, constant.NewQuestionNotificationLimitCacheTime)
|
||||||
|
} else {
|
||||||
|
_, err = ns.data.Cache.Increase(ctx, key, 1)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
log.Error(err)
|
||||||
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -46,13 +46,13 @@ func (ns *NotificationService) GetRedDot(ctx context.Context, req *schema.GetRed
|
||||||
redBot := &schema.RedDot{}
|
redBot := &schema.RedDot{}
|
||||||
inboxKey := fmt.Sprintf("answer_RedDot_%d_%s", schema.NotificationTypeInbox, req.UserID)
|
inboxKey := fmt.Sprintf("answer_RedDot_%d_%s", schema.NotificationTypeInbox, req.UserID)
|
||||||
achievementKey := fmt.Sprintf("answer_RedDot_%d_%s", schema.NotificationTypeAchievement, req.UserID)
|
achievementKey := fmt.Sprintf("answer_RedDot_%d_%s", schema.NotificationTypeAchievement, req.UserID)
|
||||||
inboxValue, err := ns.data.Cache.GetInt64(ctx, inboxKey)
|
inboxValue, _, err := ns.data.Cache.GetInt64(ctx, inboxKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
redBot.Inbox = 0
|
redBot.Inbox = 0
|
||||||
} else {
|
} else {
|
||||||
redBot.Inbox = inboxValue
|
redBot.Inbox = inboxValue
|
||||||
}
|
}
|
||||||
achievementValue, err := ns.data.Cache.GetInt64(ctx, achievementKey)
|
achievementValue, _, err := ns.data.Cache.GetInt64(ctx, achievementKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
redBot.Achievement = 0
|
redBot.Achievement = 0
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -333,7 +333,7 @@ func (qs *QuestionService) AddQuestion(ctx context.Context, req *schema.Question
|
||||||
})
|
})
|
||||||
|
|
||||||
qs.externalNotificationQueueService.Send(ctx,
|
qs.externalNotificationQueueService.Send(ctx,
|
||||||
schema.CreateNewQuestionNotificationMsg(question.ID, question.Title, tags))
|
schema.CreateNewQuestionNotificationMsg(question.ID, question.Title, question.UserID, tags))
|
||||||
|
|
||||||
questionInfo, err = qs.GetQuestion(ctx, question.ID, question.UserID, req.QuestionPermission)
|
questionInfo, err = qs.GetQuestion(ctx, question.ID, question.UserID, req.QuestionPermission)
|
||||||
return
|
return
|
||||||
|
|
|
@ -252,7 +252,7 @@ func (us *UserExternalLoginService) ExternalLoginBindingUserSendEmail(
|
||||||
}
|
}
|
||||||
resp = &schema.ExternalLoginBindingUserSendEmailResp{}
|
resp = &schema.ExternalLoginBindingUserSendEmailResp{}
|
||||||
externalLoginInfo, err := us.userExternalLoginRepo.GetCacheUserExternalLoginInfo(ctx, req.BindingKey)
|
externalLoginInfo, err := us.userExternalLoginRepo.GetCacheUserExternalLoginInfo(ctx, req.BindingKey)
|
||||||
if err != nil || len(externalLoginInfo.ExternalID) == 0 {
|
if err != nil || externalLoginInfo == nil {
|
||||||
return nil, errors.BadRequest(reason.UserNotFound)
|
return nil, errors.BadRequest(reason.UserNotFound)
|
||||||
}
|
}
|
||||||
if len(externalLoginInfo.Email) > 0 {
|
if len(externalLoginInfo.Email) > 0 {
|
||||||
|
@ -308,7 +308,7 @@ func (us *UserExternalLoginService) ExternalLoginBindingUserSendEmail(
|
||||||
func (us *UserExternalLoginService) ExternalLoginBindingUser(
|
func (us *UserExternalLoginService) ExternalLoginBindingUser(
|
||||||
ctx context.Context, bindingKey string, oldUserInfo *entity.User) (err error) {
|
ctx context.Context, bindingKey string, oldUserInfo *entity.User) (err error) {
|
||||||
externalLoginInfo, err := us.userExternalLoginRepo.GetCacheUserExternalLoginInfo(ctx, bindingKey)
|
externalLoginInfo, err := us.userExternalLoginRepo.GetCacheUserExternalLoginInfo(ctx, bindingKey)
|
||||||
if err != nil || len(externalLoginInfo.ExternalID) == 0 {
|
if err != nil || externalLoginInfo == nil {
|
||||||
return errors.BadRequest(reason.UserNotFound)
|
return errors.BadRequest(reason.UserNotFound)
|
||||||
}
|
}
|
||||||
return us.bindOldUser(ctx, externalLoginInfo, oldUserInfo)
|
return us.bindOldUser(ctx, externalLoginInfo, oldUserInfo)
|
||||||
|
|
|
@ -8,12 +8,14 @@ import (
|
||||||
type Cache interface {
|
type Cache interface {
|
||||||
Base
|
Base
|
||||||
|
|
||||||
GetString(ctx context.Context, key string) (string, error)
|
GetString(ctx context.Context, key string) (data string, exist bool, err error)
|
||||||
SetString(ctx context.Context, key, value string, ttl time.Duration) error
|
SetString(ctx context.Context, key, value string, ttl time.Duration) (err error)
|
||||||
GetInt64(ctx context.Context, key string) (int64, error)
|
GetInt64(ctx context.Context, key string) (data int64, exist bool, err error)
|
||||||
SetInt64(ctx context.Context, key string, value int64, ttl time.Duration) error
|
SetInt64(ctx context.Context, key string, value int64, ttl time.Duration) (err error)
|
||||||
Del(ctx context.Context, key string) error
|
Increase(ctx context.Context, key string, value int64) (data int64, err error)
|
||||||
Flush(ctx context.Context) error
|
Decrease(ctx context.Context, key string, value int64) (data int64, err error)
|
||||||
|
Del(ctx context.Context, key string) (err error)
|
||||||
|
Flush(ctx context.Context) (err error)
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
Loading…
Reference in New Issue