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

View File

@@ -0,0 +1,30 @@
package spam
import (
"bbs-go/internal/models"
"bbs-go/internal/pkg/errs"
"bbs-go/internal/services"
"github.com/dchest/captcha"
)
type CaptchaStrategy struct{}
func (CaptchaStrategy) Name() string {
return "CaptchaStrategy"
}
func (CaptchaStrategy) CheckTopic(user *models.User, form models.CreateTopicForm) error {
if services.SysConfigService.GetConfig().TopicCaptcha && !captcha.VerifyString(form.CaptchaId, form.CaptchaCode) {
return errs.CaptchaError
}
return nil
}
func (CaptchaStrategy) CheckArticle(user *models.User, form models.CreateArticleForm) error {
return nil
}
func (CaptchaStrategy) CheckComment(user *models.User, form models.CreateCommentForm) error {
return nil
}

View File

@@ -0,0 +1,34 @@
package spam
import (
"bbs-go/internal/models"
"bbs-go/internal/pkg/errs"
"bbs-go/internal/services"
)
type EmailVerifyStrategy struct{}
func (EmailVerifyStrategy) Name() string {
return "EmailVerifyStrategy"
}
func (EmailVerifyStrategy) CheckTopic(user *models.User, form models.CreateTopicForm) error {
if services.SysConfigService.IsCreateTopicEmailVerified() && !user.EmailVerified {
return errs.EmailNotVerified
}
return nil
}
func (EmailVerifyStrategy) CheckArticle(user *models.User, form models.CreateArticleForm) error {
if services.SysConfigService.IsCreateArticleEmailVerified() && !user.EmailVerified {
return errs.EmailNotVerified
}
return nil
}
func (EmailVerifyStrategy) CheckComment(user *models.User, form models.CreateCommentForm) error {
if services.SysConfigService.IsCreateCommentEmailVerified() && !user.EmailVerified {
return errs.EmailNotVerified
}
return nil
}

View File

@@ -0,0 +1,105 @@
package spam
import (
"bbs-go/internal/models"
"bbs-go/internal/repositories"
"errors"
"time"
"github.com/mlogclub/simple/common/dates"
"github.com/mlogclub/simple/sqls"
)
// PostFrequencyStrategy 发表频率限制
type PostFrequencyStrategy struct{}
func (PostFrequencyStrategy) Name() string {
return "PostFrequencyStrategy"
}
func (PostFrequencyStrategy) CheckTopic(user *models.User, topic models.CreateTopicForm) error {
// 注册时间超过24小时
if user.CreateTime < dates.Timestamp(time.Now().Add(-time.Hour*24)) {
return nil
}
var (
maxCountInTenMinutes int64 = 1 // 十分钟内最高发帖数量
maxCountInOneHour int64 = 2 // 一小时内最高发帖量
maxCountInOneDay int64 = 3 // 一天内最高发帖量
)
if repositories.TopicRepository.Count(sqls.DB(), sqls.NewCnd().Eq("user_id", user.Id).
Gt("create_time", dates.Timestamp(time.Now().Add(-time.Hour*24)))) >= maxCountInOneDay {
return errors.New("发表太快了,请休息一会儿")
}
if repositories.TopicRepository.Count(sqls.DB(), sqls.NewCnd().Eq("user_id", user.Id).
Gt("create_time", dates.Timestamp(time.Now().Add(-time.Hour)))) >= maxCountInOneHour {
return errors.New("发表太快了,请休息一会儿")
}
if repositories.TopicRepository.Count(sqls.DB(), sqls.NewCnd().Eq("user_id", user.Id).
Gt("create_time", dates.Timestamp(time.Now().Add(-time.Minute*10)))) >= maxCountInTenMinutes {
return errors.New("发表太快了,请休息一会儿")
}
return nil
}
func (s PostFrequencyStrategy) CheckArticle(user *models.User, form models.CreateArticleForm) error {
// 注册时间超过24小时
if user.CreateTime < dates.Timestamp(time.Now().Add(-time.Hour*24)) {
return nil
}
var (
maxCountInTenMinutes int64 = 1 // 十分钟内最高发帖数量
maxCountInOneHour int64 = 2 // 一小时内最高发帖量
maxCountInOneDay int64 = 3 // 一天内最高发帖量
)
if repositories.ArticleRepository.Count(sqls.DB(), sqls.NewCnd().Eq("user_id", user.Id).
Gt("create_time", dates.Timestamp(time.Now().Add(-time.Hour*24)))) >= maxCountInOneDay {
return errors.New("发表太快了,请休息一会儿")
}
if repositories.ArticleRepository.Count(sqls.DB(), sqls.NewCnd().Eq("user_id", user.Id).
Gt("create_time", dates.Timestamp(time.Now().Add(-time.Hour)))) >= maxCountInOneHour {
return errors.New("发表太快了,请休息一会儿")
}
if repositories.ArticleRepository.Count(sqls.DB(), sqls.NewCnd().Eq("user_id", user.Id).
Gt("create_time", dates.Timestamp(time.Now().Add(-time.Minute*10)))) >= maxCountInTenMinutes {
return errors.New("发表太快了,请休息一会儿")
}
return nil
}
func (s PostFrequencyStrategy) CheckComment(user *models.User, form models.CreateCommentForm) error {
// 注册时间超过24小时
if user.CreateTime < dates.Timestamp(time.Now().Add(-time.Hour*24)) {
return nil
}
var (
maxCountInTenMinutes int64 = 1 // 十分钟内最高发帖数量
maxCountInOneHour int64 = 1 // 一小时内最高发帖量
maxCountInOneDay int64 = 1 // 一天内最高发帖量
)
if repositories.CommentRepository.Count(sqls.DB(), sqls.NewCnd().Eq("user_id", user.Id).
Gt("create_time", dates.Timestamp(time.Now().Add(-time.Hour*24)))) >= maxCountInOneDay {
return errors.New("发表太快了,请休息一会儿")
}
if repositories.CommentRepository.Count(sqls.DB(), sqls.NewCnd().Eq("user_id", user.Id).
Gt("create_time", dates.Timestamp(time.Now().Add(-time.Hour)))) >= maxCountInOneHour {
return errors.New("发表太快了,请休息一会儿")
}
if repositories.CommentRepository.Count(sqls.DB(), sqls.NewCnd().Eq("user_id", user.Id).
Gt("create_time", dates.Timestamp(time.Now().Add(-time.Minute*10)))) >= maxCountInTenMinutes {
return errors.New("发表太快了,请休息一会儿")
}
return nil
}

View File

@@ -0,0 +1,53 @@
package spam
import (
"bbs-go/internal/models"
"log/slog"
)
var strategies []Strategy
func init() {
strategies = append(strategies, &EmailVerifyStrategy{})
strategies = append(strategies, &CaptchaStrategy{})
// strategies = append(strategies, &PostFrequencyStrategy{})
}
func CheckTopic(user *models.User, form models.CreateTopicForm) error {
if len(strategies) == 0 {
return nil
}
for _, strategy := range strategies {
if err := strategy.CheckTopic(user, form); err != nil {
slog.Warn("[Topic]命中策略", slog.Any("strategy", strategy.Name()), slog.Any("userId", user.Id))
return err
}
}
return nil
}
func CheckArticle(user *models.User, form models.CreateArticleForm) error {
if len(strategies) == 0 {
return nil
}
for _, strategy := range strategies {
if err := strategy.CheckArticle(user, form); err != nil {
slog.Warn("[Article]命中策略", slog.Any("strategy", strategy.Name()), slog.Any("userId", user.Id))
return err
}
}
return nil
}
func CheckComment(user *models.User, form models.CreateCommentForm) error {
if len(strategies) == 0 {
return nil
}
for _, strategy := range strategies {
if err := strategy.CheckComment(user, form); err != nil {
slog.Warn("[Comment]命中策略", slog.Any("strategy", strategy.Name()), slog.Any("userId", user.Id))
return err
}
}
return nil
}

View File

@@ -0,0 +1,14 @@
package spam
import "bbs-go/internal/models"
type Strategy interface {
// Name 策略名称
Name() string
// CheckTopic 检查话题
CheckTopic(user *models.User, form models.CreateTopicForm) error
// CheckArticle 检查文章
CheckArticle(user *models.User, form models.CreateArticleForm) error
// CheckComment 检查评论
CheckComment(user *models.User, form models.CreateCommentForm) error
}