aliyun sensor server
This commit is contained in:
@@ -18,7 +18,7 @@ import (
|
||||
"github.com/tamakyi/TamaBox/internal/i18n"
|
||||
"github.com/tamakyi/TamaBox/internal/imagecheck"
|
||||
"github.com/tamakyi/TamaBox/internal/mail"
|
||||
"github.com/tamakyi/TamaBox/internal/security/censor"
|
||||
"github.com/tamakyi/TamaBox/internal/security/moderation"
|
||||
"github.com/tamakyi/TamaBox/internal/shared"
|
||||
"github.com/tamakyi/TamaBox/internal/storage"
|
||||
)
|
||||
@@ -27,10 +27,18 @@ const (
|
||||
MaxMessageImageSize = 5 * 1024 * 1024 // 5MB
|
||||
)
|
||||
|
||||
// ConversationPage 私聊会话页(GET 入口)。审核拦截后的就地重渲染由 renderConversation 统一处理。
|
||||
func ConversationPage(ctx context.Context) {
|
||||
domain := ctx.Param("domain")
|
||||
token := ctx.Param("token")
|
||||
renderConversation(ctx, ctx.Param("domain"), ctx.Param("token"), "", nil)
|
||||
}
|
||||
|
||||
// renderConversation 渲染私聊会话页,并可选地回填审核拦截提示与已输入内容。
|
||||
//
|
||||
// prefillContent 非空时回填到消息输入框:审核拦截(以及其它服务端校验失败)后保留用户已输入内容,
|
||||
// 避免 Redirect 重渲染导致输入丢失。modErr 非空时作为错误提示展示(与提问链路 ctx.SetError
|
||||
// 一致的就地重渲染,而非 flash + Redirect),提示通过 templates/base/alert 渲染。
|
||||
// 函数内部在所有出口都会发起 Redirect 或 Success 渲染,调用方在调用后应直接 return。
|
||||
func renderConversation(ctx context.Context, domain, token, prefillContent string, modErr error) {
|
||||
pageUser, err := db.Users.GetByDomain(ctx.Request().Context(), domain)
|
||||
if err != nil {
|
||||
ctx.Redirect("/")
|
||||
@@ -119,8 +127,19 @@ func ConversationPage(ctx context.Context) {
|
||||
// 单条消息字数上限,供发送 / 回复 textarea 的 maxlength 与后端校验同源
|
||||
// (conf.Limits.ChatMessageLen,[limits] 配置段)
|
||||
ctx.Data["ChatMessageLimit"] = conf.Limits.ChatMessageLen
|
||||
ctx.Data["CanSend"] = !conv.IsClosed && !conv.IsDeletedByOwner &&
|
||||
canSend := !conv.IsClosed && !conv.IsDeletedByOwner &&
|
||||
((isOwner && conv.MessageCount < conv.MaxMessages) || (isAsker && conv.MessageCount < conv.MaxMessages && !isBlocked))
|
||||
ctx.Data["CanSend"] = canSend
|
||||
|
||||
// 回填审核拦截时已输入内容(仅当对话仍可发送,避免关闭/删除场景下回填到隐藏输入框)。
|
||||
if canSend {
|
||||
ctx.Data["Content"] = prefillContent
|
||||
}
|
||||
// 审核拦截等错误提示:就地通过 base/alert 渲染,不再走 flash + Redirect(否则内容丢失且无提示)。
|
||||
if modErr != nil {
|
||||
ctx.Data["HasError"] = true
|
||||
ctx.Data["Error"] = modErr.Error()
|
||||
}
|
||||
ctx.Success("chat/conversation")
|
||||
}
|
||||
|
||||
@@ -254,18 +273,12 @@ func SendMessage(ctx context.Context, cache cache.Cache) {
|
||||
}
|
||||
|
||||
// 内容安全检测(仅文本)
|
||||
// 统一守卫:与提问 / 投票共用同一份档位判定,箱主的「审核严格度」决定放行与否。
|
||||
if content != "" {
|
||||
censorResponse, err := censor.Text(ctx.Request().Context(), content)
|
||||
if err != nil {
|
||||
// 审核源全部不可用:fail-closed,拒绝发送而非免审放行。
|
||||
logrus.WithContext(ctx.Request().Context()).WithError(err).Error("Failed to censor text")
|
||||
ctx.SetErrorFlash(i18n.T(ctx.Lang(), "censor.unavailable"))
|
||||
ctx.Redirect(fmt.Sprintf("/_/%s/chat/%s", domain, token))
|
||||
return
|
||||
}
|
||||
if !censorResponse.Pass {
|
||||
ctx.SetErrorFlash(censorResponse.ErrorMessage())
|
||||
ctx.Redirect(fmt.Sprintf("/_/%s/chat/%s", domain, token))
|
||||
if _, err := moderation.Check(ctx.Request().Context(), moderation.StrictnessFor(pageUser.ModerationStrictness), ctx.Lang(), content); err != nil {
|
||||
// 审核拦截:就地重渲染会话页,回填已输入内容并展示拦截原因。
|
||||
// 不复用 SetErrorFlash + Redirect:那会导致输入框内容在刷新后丢失(用户已确认的无提示+内容消失问题)。
|
||||
renderConversation(ctx, domain, token, content, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user