80 lines
2.3 KiB
Go
80 lines
2.3 KiB
Go
// Package logic is sensitive-word scan, penalties, and admin word CRUD.
|
|
package logic
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"time"
|
|
|
|
modentity "spark-server/internal/module/moderation/entity"
|
|
)
|
|
|
|
var ErrNotReady = errors.New("moderation: not ready")
|
|
|
|
type Repository interface {
|
|
Ready() bool
|
|
ReloadMatcher(ctx context.Context) error
|
|
ListWords(ctx context.Context, q string, category int, enabled *bool, page, size int) ([]modentity.Word, int64, error)
|
|
CreateWord(ctx context.Context, w *modentity.Word) error
|
|
UpdateWord(ctx context.Context, id int64, patch WordPatch) error
|
|
SoftDeleteWord(ctx context.Context, id int64) error
|
|
InsertHits(ctx context.Context, hits []HitRecord) error
|
|
ListHits(ctx context.Context, userID int64, category int, since, until *time.Time, page, size int) ([]HitRecord, int64, error)
|
|
LookupWord(id int64) *modentity.Word
|
|
MatcherFind(text string) ([]MatchDetail, string, bool)
|
|
}
|
|
|
|
type WordPatch func(w *modentity.Word) error
|
|
|
|
type HitRecord struct {
|
|
ID int64 `json:"id"`
|
|
UserID int64 `json:"user_id"`
|
|
ConversationID int64 `json:"conversation_id"`
|
|
WordID int64 `json:"word_id"`
|
|
Category modentity.Category `json:"category"`
|
|
Action modentity.Action `json:"action"`
|
|
Excerpt string `json:"excerpt"`
|
|
RealIP string `json:"real_ip"`
|
|
CreatedAt time.Time `json:"created_at"`
|
|
}
|
|
|
|
type MatchDetail struct {
|
|
WordID int64
|
|
Category modentity.Category
|
|
Action modentity.Action
|
|
Excerpt string
|
|
From int
|
|
To int
|
|
}
|
|
|
|
type UserModeration interface {
|
|
AssertCanSend(ctx context.Context, userID int64) error
|
|
DisableAccount(ctx context.Context, userID int64) error
|
|
ExtendSendMutedUntil(ctx context.Context, userID int64, until time.Time) error
|
|
}
|
|
|
|
type IDGen interface {
|
|
NextID() (int64, error)
|
|
}
|
|
|
|
type Service struct {
|
|
repo Repository
|
|
users UserModeration
|
|
ids IDGen
|
|
}
|
|
|
|
func NewService(repo Repository, users UserModeration, ids IDGen) *Service {
|
|
return &Service{repo: repo, users: users, ids: ids}
|
|
}
|
|
|
|
func (s *Service) Ready() bool {
|
|
return s != nil && s.repo != nil && s.repo.Ready()
|
|
}
|
|
|
|
func (s *Service) Reload(ctx context.Context) error {
|
|
if !s.Ready() {
|
|
return ErrNotReady
|
|
}
|
|
return s.repo.ReloadMatcher(ctx)
|
|
}
|