Files
Arkie-Library-Backend/internal/handlers/post_text.go

149 lines
3.4 KiB
Go
Raw Normal View History

2026-05-25 16:45:33 +08:00
package handlers
import (
"net/http"
"regexp"
"strings"
)
const postI18nColsSQL = `
COALESCE(p.text_zh,''), COALESCE(p.text_en,''), COALESCE(p.text_ja,''),
COALESCE(p.text_ko,''), COALESCE(p.text_vi,''), COALESCE(p.text_id,''), COALESCE(p.text_ms,'')`
const maxPostTextLen = 32768
const maxPostAttachments = 20
var postLinkRe = regexp.MustCompile(`https?://`)
type postTextI18n struct {
TextZh, TextEn, TextJa, TextKo, TextVi, TextId, TextMs string
}
type postLocalePayload struct {
Text string `json:"text"`
}
2026-05-26 11:12:22 +08:00
// requestLangCode is the normalized locale from ?lang= or Accept-Language (zh, en, ja, …).
func requestLangCode(r *http.Request) string {
raw := strings.TrimSpace(r.URL.Query().Get("lang"))
if raw == "" {
raw = r.Header.Get("Accept-Language")
}
raw = strings.TrimSpace(strings.Split(raw, ",")[0])
if raw == "" {
return "zh"
}
return translateNormalizePostLang(raw)
}
2026-05-26 17:58:16 +08:00
// textForLang returns body text stored for the post's source language only.
func (t postTextI18n) textForLang(lang string) string {
switch translateNormalizePostLang(lang) {
case "en":
return strings.TrimSpace(t.TextEn)
case "ja":
return strings.TrimSpace(t.TextJa)
case "ko":
return strings.TrimSpace(t.TextKo)
case "vi":
return strings.TrimSpace(t.TextVi)
case "id":
return strings.TrimSpace(t.TextId)
case "ms":
return strings.TrimSpace(t.TextMs)
default:
return strings.TrimSpace(t.TextZh)
}
}
func postTextI18nFromSingle(lang, text string) postTextI18n {
lang = translateNormalizePostLang(lang)
text = strings.TrimSpace(text)
var t postTextI18n
switch lang {
case "en":
t.TextEn = text
case "ja":
t.TextJa = text
case "ko":
t.TextKo = text
case "vi":
t.TextVi = text
case "id":
t.TextId = text
case "ms":
t.TextMs = text
default:
t.TextZh = text
}
return t
}
func normalizePostSourceLang(lang string) string {
lang = translateNormalizePostLang(strings.TrimSpace(lang))
switch lang {
case "zh", "en", "ja", "ko", "vi", "id", "ms":
return lang
default:
return "zh"
}
2026-05-25 16:45:33 +08:00
}
func (t postTextI18n) anyNonEmpty() bool {
return strings.TrimSpace(t.TextZh) != "" ||
strings.TrimSpace(t.TextEn) != "" ||
strings.TrimSpace(t.TextJa) != "" ||
strings.TrimSpace(t.TextKo) != "" ||
strings.TrimSpace(t.TextVi) != "" ||
strings.TrimSpace(t.TextId) != "" ||
strings.TrimSpace(t.TextMs) != ""
}
func (t postTextI18n) legacyPrimary() string {
if strings.TrimSpace(t.TextZh) != "" {
return strings.TrimSpace(t.TextZh)
}
if strings.TrimSpace(t.TextEn) != "" {
return strings.TrimSpace(t.TextEn)
}
return ""
}
func scanPostTextI18n(zh, en, ja, ko, vi, id, ms string) postTextI18n {
return postTextI18n{TextZh: zh, TextEn: en, TextJa: ja, TextKo: ko, TextVi: vi, TextId: id, TextMs: ms}
}
2026-05-25 23:43:55 +08:00
func (t postTextI18n) toLocalizations() map[string]postLocalePayload {
return map[string]postLocalePayload{
"zh": {Text: t.TextZh},
"en": {Text: t.TextEn},
"ja": {Text: t.TextJa},
"ko": {Text: t.TextKo},
"vi": {Text: t.TextVi},
"id": {Text: t.TextId},
"ms": {Text: t.TextMs},
}
}
2026-05-25 16:45:33 +08:00
func postTextHasLink(text string) bool {
return postLinkRe.MatchString(text)
}
func truncatePostTexts(t postTextI18n) postTextI18n {
tr := func(s string) string {
s = strings.TrimSpace(s)
if len(s) > maxPostTextLen {
return s[:maxPostTextLen]
}
return s
}
t.TextZh = tr(t.TextZh)
t.TextEn = tr(t.TextEn)
t.TextJa = tr(t.TextJa)
t.TextKo = tr(t.TextKo)
t.TextVi = tr(t.TextVi)
t.TextId = tr(t.TextId)
t.TextMs = tr(t.TextMs)
return t
}