Set up project files and add .gitignore to exclude local build/runtime artifacts. Made-with: Cursor
104 lines
2.6 KiB
Go
104 lines
2.6 KiB
Go
package service
|
|
|
|
import (
|
|
"context"
|
|
"log"
|
|
"strings"
|
|
|
|
"carrot_bbs/internal/pkg/openai"
|
|
)
|
|
|
|
// PostModerationRejectedError 帖子审核拒绝错误
|
|
type PostModerationRejectedError struct {
|
|
Reason string
|
|
}
|
|
|
|
func (e *PostModerationRejectedError) Error() string {
|
|
if strings.TrimSpace(e.Reason) == "" {
|
|
return "post rejected by moderation"
|
|
}
|
|
return "post rejected by moderation: " + e.Reason
|
|
}
|
|
|
|
// UserMessage 返回给前端的用户可读文案
|
|
func (e *PostModerationRejectedError) UserMessage() string {
|
|
if strings.TrimSpace(e.Reason) == "" {
|
|
return "内容未通过审核,请修改后重试"
|
|
}
|
|
return strings.TrimSpace(e.Reason)
|
|
}
|
|
|
|
// CommentModerationRejectedError 评论审核拒绝错误
|
|
type CommentModerationRejectedError struct {
|
|
Reason string
|
|
}
|
|
|
|
func (e *CommentModerationRejectedError) Error() string {
|
|
if strings.TrimSpace(e.Reason) == "" {
|
|
return "comment rejected by moderation"
|
|
}
|
|
return "comment rejected by moderation: " + e.Reason
|
|
}
|
|
|
|
// UserMessage 返回给前端的用户可读文案
|
|
func (e *CommentModerationRejectedError) UserMessage() string {
|
|
if strings.TrimSpace(e.Reason) == "" {
|
|
return "评论未通过审核,请修改后重试"
|
|
}
|
|
return strings.TrimSpace(e.Reason)
|
|
}
|
|
|
|
type PostAIService struct {
|
|
openAIClient openai.Client
|
|
}
|
|
|
|
func NewPostAIService(openAIClient openai.Client) *PostAIService {
|
|
return &PostAIService{
|
|
openAIClient: openAIClient,
|
|
}
|
|
}
|
|
|
|
func (s *PostAIService) IsEnabled() bool {
|
|
return s != nil && s.openAIClient != nil && s.openAIClient.IsEnabled()
|
|
}
|
|
|
|
// ModeratePost 审核帖子内容,返回 nil 表示通过
|
|
func (s *PostAIService) ModeratePost(ctx context.Context, title, content string, images []string) error {
|
|
if !s.IsEnabled() {
|
|
return nil
|
|
}
|
|
|
|
approved, reason, err := s.openAIClient.ModeratePost(ctx, title, content, images)
|
|
if err != nil {
|
|
if s.openAIClient.Config().StrictModeration {
|
|
return err
|
|
}
|
|
log.Printf("[WARN] AI moderation failed, fallback allow: %v", err)
|
|
return nil
|
|
}
|
|
if !approved {
|
|
return &PostModerationRejectedError{Reason: reason}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// ModerateComment 审核评论内容,返回 nil 表示通过
|
|
func (s *PostAIService) ModerateComment(ctx context.Context, content string, images []string) error {
|
|
if !s.IsEnabled() {
|
|
return nil
|
|
}
|
|
|
|
approved, reason, err := s.openAIClient.ModerateComment(ctx, content, images)
|
|
if err != nil {
|
|
if s.openAIClient.Config().StrictModeration {
|
|
return err
|
|
}
|
|
log.Printf("[WARN] AI comment moderation failed, fallback allow: %v", err)
|
|
return nil
|
|
}
|
|
if !approved {
|
|
return &CommentModerationRejectedError{Reason: reason}
|
|
}
|
|
return nil
|
|
}
|