Files
tamabox/.workbuddy/backup/domain-shiroko-20260906/text.go
T
tamakyi e3e59e7c69 chore: baseline snapshot before moderation-strictness feature
Repo .git was damaged (refs/ missing, index truncated, object store near-empty).
Repaired via git init (rebuilt refs), stale index preserved as .git/index.corrupt-20260910.bak,
then full worktree committed as a rollback baseline.
2026-09-10 10:56:27 +08:00

119 lines
3.4 KiB
Go

// Copyright 2022 E99p1ant. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package censor
import (
"context"
"encoding/json"
"fmt"
"strings"
)
type ForbiddenType string
const (
ForbiddenTypeSpam ForbiddenType = "spam"
ForbiddenTypeAd ForbiddenType = "ad"
ForbiddenTypePolitics ForbiddenType = "politics"
ForbiddenTypeTerrorism ForbiddenType = "terrorism"
ForbiddenTypeAbuse ForbiddenType = "abuse"
ForbiddenTypePorn ForbiddenType = "porn"
ForbiddenTypeFlood ForbiddenType = "flood"
ForbiddenTypeContraband ForbiddenType = "contraband"
ForbiddenTypeMeaningless ForbiddenType = "meaningless"
ForbiddenTypeHarmful ForbiddenType = "harmful"
)
func (f ForbiddenType) String() string {
return map[ForbiddenType]string{
ForbiddenTypeSpam: "含垃圾信息",
ForbiddenTypeAd: "广告",
ForbiddenTypePolitics: "涉政",
ForbiddenTypeTerrorism: "暴恐",
ForbiddenTypeAbuse: "辱骂",
ForbiddenTypePorn: "色情",
ForbiddenTypeFlood: "灌水",
ForbiddenTypeContraband: "违禁",
ForbiddenTypeMeaningless: "无意义",
ForbiddenTypeHarmful: "不良场景",
}[f]
}
type TextCensorResponse struct {
SourceName string `json:"source_name"`
Pass bool `json:"pass"`
ForbiddenType ForbiddenType `json:"forbidden_type"`
Hint string `json:"hint"`
Confidence float64 `json:"confidence"`
RawResponse json.RawMessage `json:"raw_response"`
}
func (r *TextCensorResponse) ToJSON() []byte {
jsonBytes, _ := json.Marshal(r)
return jsonBytes
}
func (r *TextCensorResponse) ErrorMessage() string {
errorMessage := "内容安全检查不通过"
if r.ForbiddenType != "" {
errorMessage += fmt.Sprintf(" [%s]", r.ForbiddenType.String())
}
if r.Hint != "" {
errorMessage += fmt.Sprintf(",相关标签:%q", r.Hint)
}
return errorMessage
}
type TextCensor interface {
Censor(ctx context.Context, text string) (*TextCensorResponse, error)
String() string
}
var TrustedHosts = []string{
"xhslink.com", // 小红书
"weibo.com", // 微博
"b23.tv", // Bilibili
"acfun.cn",
"aixifan.com",
"github.com",
"tama.guru",
"337845818.best",
"x.com",
"bilibili.com",
}
// RemoveTrustedURL removes the trusted URL from the text,
// in order to bypass the URL censoring.
// 仅当可信域名后紧跟路径分隔符(/ ? #)或位于字符串结尾时才视为可信,
// 避免 github.com.evil.tld 被朴素替换误判为 github.com 之子域而漏审。
func RemoveTrustedURL(str string) string {
for _, host := range TrustedHosts {
for _, protocol := range []string{"http://", "https://"} {
needle := protocol + host
var b strings.Builder
rest := str
for {
idx := strings.Index(rest, needle)
if idx < 0 {
b.WriteString(rest)
break
}
b.WriteString(rest[:idx])
after := rest[idx+len(needle):]
if len(after) == 0 || after[0] == '/' || after[0] == '?' || after[0] == '#' {
// 可信域名边界:跳过该前缀,从域名之后继续(域名本身被移除,不进入审核)。
rest = after
} else {
// 非可信域名边界(如 github.com.evil):保留前缀,从其后继续扫描。
b.WriteString(needle)
rest = after
}
}
str = b.String()
}
}
return str
}