Files

96 lines
4.4 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Copyright 2026 tamakyi. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package conf
// 各项上限的内置默认值(与旧版硬编码一致)。既是未配置 [limits] 段时的兜底,
// 也是 conf.Init 后归一化(sanitizeLimits)的回退基准。
const (
defaultMaxTags = 5
defaultMaxTagLen = 5
defaultMaxBlockWords = 10
defaultMaxBlockWordLen = 10
defaultCustomAnswerLen = 200
defaultVoteOptionLen = 300
defaultQuestionContentLen = 1000
defaultAnswerContentLen = 2000
defaultFollowUpContentLen = 2000
defaultChatMessageLen = 2000
defaultChatMaxMessages = 200
defaultDailyMessageLimitMax = 999
)
// LimitsConfig 全站内容 / 数量上限([limits] 配置段)的字段集合。
//
// 收口到本段前,这些上限散落在 internal/db 与路由层硬编码,改一次要重编译且前后端数值易漂移。
// 现后端校验 / 模板注入 / 前端提示统一引用同一份值,调整只需改 app.ini 重启;
// 长度类上限一律按字符(rune)计数。
type LimitsConfig struct {
MaxTags int `ini:"max_tags"`
MaxTagLen int `ini:"max_tag_len"`
MaxBlockWords int `ini:"max_block_words"`
MaxBlockWordLen int `ini:"max_block_word_len"`
// 参与者填写的「自定义补充选项」文本最大字符数(含表单字段的「其他」)。
CustomAnswerLen int `ini:"custom_answer_len"`
// 站长创建投票时单个「选项」文本最大字符数。与 CustomAnswerLen 是两条独立规则
// (站长侧预设刻意放宽),可各自调参。
VoteOptionLen int `ini:"vote_option_len"`
// 提问正文最大字符数。旧实现靠 govalid maxlen 写死 2000 且与前端 1000 不一致,
// 现改为路由层按本值做 rune 校验。
QuestionContentLen int `ini:"question_content_len"`
// 回答正文最大字符数:箱主对提问的正式回答,以及对追问的回复(共用)。
AnswerContentLen int `ini:"answer_content_len"`
FollowUpContentLen int `ini:"followup_content_len"`
// 单条消息(发送 / 回复共用)最大字符数
ChatMessageLen int `ini:"chat_message_len"`
// 每个会话的消息条数硬顶。用户只能在 1..该值间设置 chat_max_messages,
// 新用户默认值即该硬顶(而非固定 20)。
ChatMaxMessages int `ini:"chat_max_messages"`
// 每日私信条数的「用户可设上限」(非站点强制配额):用户可设 0..该值,0 表示不限制。
DailyMessageLimitMax int `ini:"daily_message_limit_max"`
}
// Limits 保存运行时的全部上限配置。conf.Init 先 MapTo [limits] 段,再由 sanitizeLimits
// 把 <1 的值回退内置默认,因此缺段、缺键、留空(解析为 0)或填负数都不会让上限静默置零。
var Limits = LimitsConfig{
MaxTags: defaultMaxTags,
MaxTagLen: defaultMaxTagLen,
MaxBlockWords: defaultMaxBlockWords,
MaxBlockWordLen: defaultMaxBlockWordLen,
CustomAnswerLen: defaultCustomAnswerLen,
VoteOptionLen: defaultVoteOptionLen,
QuestionContentLen: defaultQuestionContentLen,
AnswerContentLen: defaultAnswerContentLen,
FollowUpContentLen: defaultFollowUpContentLen,
ChatMessageLen: defaultChatMessageLen,
ChatMaxMessages: defaultChatMaxMessages,
DailyMessageLimitMax: defaultDailyMessageLimitMax,
}
// sanitizeLimits 归一化 [limits]:所有上限最小为 1,0 / 负数一律回退内置默认,
// 避免「留空=0」把标签全拒、消息全超长等隐性灾难。
// DailyMessageLimitMax 同样要求 >=1:为 0 会让用户只能设为 0(=不限制),等于关闭每日配额功能。
func sanitizeLimits(l *LimitsConfig) {
clamp1 := func(p *int, def int) {
if *p < 1 {
*p = def
}
}
clamp1(&l.MaxTags, defaultMaxTags)
clamp1(&l.MaxTagLen, defaultMaxTagLen)
clamp1(&l.MaxBlockWords, defaultMaxBlockWords)
clamp1(&l.MaxBlockWordLen, defaultMaxBlockWordLen)
clamp1(&l.CustomAnswerLen, defaultCustomAnswerLen)
clamp1(&l.VoteOptionLen, defaultVoteOptionLen)
clamp1(&l.QuestionContentLen, defaultQuestionContentLen)
clamp1(&l.AnswerContentLen, defaultAnswerContentLen)
clamp1(&l.FollowUpContentLen, defaultFollowUpContentLen)
clamp1(&l.ChatMessageLen, defaultChatMessageLen)
clamp1(&l.ChatMaxMessages, defaultChatMaxMessages)
clamp1(&l.DailyMessageLimitMax, defaultDailyMessageLimitMax)
}