Files
mce/internal/controller/post_controller.go

90 lines
2.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.

package controller
import (
"bytes"
"crypto/rand"
"encoding/hex"
"image"
"metazone.cc/mce/internal/model"
"metazone.cc/mce/internal/service"
"github.com/chai2010/webp"
"github.com/gin-gonic/gin"
)
// PostController 帖子控制器SSR 页面 + API
type PostController struct {
postService postUseCase
shortcodeSvc *service.ShortcodeService
}
// NewPostController 构造函数
func NewPostController(ps postUseCase, scs *service.ShortcodeService) *PostController {
return &PostController{postService: ps, shortcodeSvc: scs}
}
// allowedImageExt 允许的图片扩展名
var allowedImageExt = map[string]bool{
".jpg": true, ".jpeg": true, ".png": true, ".gif": true, ".webp": true,
}
// visitorCookieName Cookie 名称
const visitorCookieName = "visitor_id"
// visitorCookieMaxAge 访客 Cookie 有效期30 天)
const visitorCookieMaxAge = 30 * 24 * 3600
// getVisitorID 获取或创建访客标识 Cookie
func (ctrl *PostController) getVisitorID(c *gin.Context) string {
if cookie, err := c.Cookie(visitorCookieName); err == nil && cookie != "" {
return cookie
}
// 生成 16 字节随机 hex32 字符)
b := make([]byte, 16)
if _, err := rand.Read(b); err != nil {
return ""
}
vid := hex.EncodeToString(b)
c.SetCookie(visitorCookieName, vid, visitorCookieMaxAge, "/", "", false, true)
return vid
}
// applyShortcode 处理帖子正文中的 shortcode 标记,替换为 HTML 占位符
func (ctrl *PostController) applyShortcode(post *model.Post) {
if ctrl.shortcodeSvc != nil {
result := ctrl.shortcodeSvc.Process(post.Body)
post.Body = result.ProcessedBody
}
}
// encodeWebPBinary 二分查找 WebP 质量,找 ≤ targetBytes 的最高质量quality 1~80
// 返回 nil 表示最低质量仍超限(几乎不可能发生),应由调用方回退原格式
func encodeWebPBinary(img image.Image, targetBytes int) []byte {
var buf bytes.Buffer
if err := webp.Encode(&buf, img, &webp.Options{Quality: 80}); err != nil {
return nil
}
if buf.Len() <= targetBytes {
return buf.Bytes()
}
low, high := 1, 80
var best []byte
for low <= high {
mid := (low + high) / 2
buf.Reset()
if err := webp.Encode(&buf, img, &webp.Options{Quality: float32(mid)}); err != nil {
return nil
}
if buf.Len() <= targetBytes {
best = make([]byte, buf.Len())
copy(best, buf.Bytes())
low = mid + 1
} else {
high = mid - 1
}
}
return best
}