页眉随机展示图片及缓存

This commit is contained in:
xing 2023-02-01 00:58:42 +08:00
parent d9aa8cbd4e
commit 76ddae21db
13 changed files with 183 additions and 130 deletions

View File

@ -65,6 +65,9 @@ maxPostIdCacheTime: 1h
userInfoCacheTime: 24h
# 单独评论缓存时间
commentsCacheTime: 24h
# 主题的页眉图片缓存时间
themeHeaderImagCacheTime: 5m
# Gzip
gzip: false
# 提交评论url
@ -80,4 +83,6 @@ theme: "twentyfifteen"
# 文档排序默认升序还是降序
postOrder: "desc"
# 上传的目录
uploadDir: ""
uploadDir: ""
# pprof route path 为空表示不开启pprof,否则为pprof的路由
pprof: "/debug/pprof"

1
go.mod
View File

@ -11,7 +11,6 @@ require (
github.com/gin-gonic/gin v1.8.1
github.com/go-sql-driver/mysql v1.6.0
github.com/jmoiron/sqlx v1.3.5
github.com/leeqvip/gophp v1.0.0
github.com/soxfmr/gomail v0.0.0-20200806033254-80bf84e583f0
golang.org/x/crypto v0.0.0-20220924013350-4ba4fb4dd9e7
gopkg.in/yaml.v2 v2.4.0

2
go.sum
View File

@ -52,8 +52,6 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/leeqvip/gophp v1.0.0 h1:lzWOECV3vkXjzrwoOVYyrfcAfOH+9BqIZLDIwxffy8o=
github.com/leeqvip/gophp v1.0.0/go.mod h1:DRoO5E9Sk+t4/3LGPCH4QZ/arcASXk9VsqdeTXLgYC4=
github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w=
github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=

View File

@ -78,8 +78,8 @@ func SetupRouter() (*gin.Engine, func()) {
r.GET("/comments/feed", actions.CommentsFeed)
cfl, _ := middleware.FlowLimit(c.MaxRequestSleepNum, 5, c.SleepTime)
r.POST("/comment", cfl, actions.PostComment)
if gin.Mode() != gin.ReleaseMode {
pprof.Register(r, "dev/pprof")
if c.Pprof != "" {
pprof.Register(r, c.Pprof)
}
fn := func() {
reloadValidServerNameFn()

View File

@ -41,7 +41,7 @@ var newCommentCache *cache.MapCache[string, string]
var allUsernameCache *cache.VarCache[map[string]struct{}]
var allCategories *cache.VarCache[map[string]struct{}]
var headerImagesCache *cache.MapCache[string, []models.PostThumbnail]
func InitActionsCommonCache() {
c := config.Conf.Load()
@ -88,6 +88,8 @@ func InitActionsCommonCache() {
allUsernameCache = cache.NewVarCache(dao.AllUsername, c.UserInfoCacheTime)
headerImagesCache = cache.NewMapCacheByFn[string](getHeaderImages, c.ThemeHeaderImagCacheTime)
InitFeed()
}
@ -103,6 +105,7 @@ func ClearCache() {
usersNameCache.ClearExpired()
postFeedCache.ClearExpired()
newCommentCache.ClearExpired()
headerImagesCache.ClearExpired()
}
func FlushCache() {
searchPostIdsCache.Flush()
@ -116,6 +119,7 @@ func FlushCache() {
usersCache.Flush()
postFeedCache.Flush()
newCommentCache.Flush()
headerImagesCache.Flush()
}
func Archives(ctx context.Context) (r []models.PostArchive) {

78
internal/pkg/cache/headerImages.go vendored Normal file
View File

@ -0,0 +1,78 @@
package cache
import (
"context"
"fmt"
"github.com/fthvgb1/wp-go/helper/slice"
str "github.com/fthvgb1/wp-go/helper/strings"
"github.com/fthvgb1/wp-go/internal/pkg/models"
"github.com/fthvgb1/wp-go/internal/plugins"
"github.com/fthvgb1/wp-go/internal/wpconfig"
"github.com/fthvgb1/wp-go/model"
"time"
)
func GetHeaderImages(ctx context.Context, theme string) (r []models.PostThumbnail, err error) {
r, err = headerImagesCache.GetCache(ctx, theme, time.Second, ctx, theme)
return
}
func getHeaderImages(a ...any) (r []models.PostThumbnail, err error) {
ctx := a[0].(context.Context)
theme := a[1].(string)
mods, ok := wpconfig.Options.Load(fmt.Sprintf("theme_mods_%s", theme))
if ok && mods != "" {
meta, er := plugins.UnPHPSerialize[plugins.HeaderImageMeta](mods)
if er != nil {
err = er
return
}
if "random-uploaded-image" == meta.HeaderImage {
headers, er := model.Find[models.Posts](ctx, model.SqlBuilder{
{"post_type", "attachment"},
{"post_status", "inherit"},
{"meta_value", theme},
{"meta_key", "_wp_attachment_is_custom_header"},
}, "a.ID", "a.ID", nil, model.SqlBuilder{
{" a", "left join", "wp_postmeta b", "a.ID=b.post_id"},
}, nil, 0)
if er != nil {
err = er
return
}
if len(headers) > 0 {
posts, er := GetPostsByIds(ctx, slice.Map(headers, func(t models.Posts) uint64 {
return t.Id
}))
if er != nil {
err = er
return
}
r = slice.Map(posts, func(m models.Posts) models.PostThumbnail {
return thumb(m, theme)
})
}
return
}
m, er := GetPostById(ctx, uint64(meta.HeaderImagData.AttachmentId))
if er != nil {
err = er
return
}
m.Thumbnail = thumb(m, theme)
r = []models.PostThumbnail{m.Thumbnail}
}
return
}
func thumb(m models.Posts, theme string) models.PostThumbnail {
m.Thumbnail = plugins.Thumbnail(m.AttachmentMetadata, "thumbnail", "", "thumbnail", "post-thumbnail", fmt.Sprintf("%s-thumbnail-avatar", theme))
m.Thumbnail.Width = m.AttachmentMetadata.Width
m.Thumbnail.Height = m.AttachmentMetadata.Height
if m.Thumbnail.Path != "" {
if len(m.AttachmentMetadata.Sizes) > 0 {
m.Thumbnail.Srcset = str.Join(m.Thumbnail.Path, " 2000w, ", m.Thumbnail.Srcset)
}
}
return m.Thumbnail
}

View File

@ -11,36 +11,38 @@ import (
var Conf safety.Var[Config]
type Config struct {
Ssl Ssl `yaml:"ssl"`
Mysql Mysql `yaml:"mysql"`
Mail Mail `yaml:"mail"`
RecentPostCacheTime time.Duration `yaml:"recentPostCacheTime"`
CategoryCacheTime time.Duration `yaml:"categoryCacheTime"`
ArchiveCacheTime time.Duration `yaml:"archiveCacheTime"`
ContextPostCacheTime time.Duration `yaml:"contextPostCacheTime"`
RecentCommentsCacheTime time.Duration `yaml:"recentCommentsCacheTime"`
DigestCacheTime time.Duration `yaml:"digestCacheTime"`
DigestWordCount int `yaml:"digestWordCount"`
PostListCacheTime time.Duration `yaml:"postListCacheTime"`
SearchPostCacheTime time.Duration `yaml:"searchPostCacheTime"`
MonthPostCacheTime time.Duration `yaml:"monthPostCacheTime"`
PostDataCacheTime time.Duration `yaml:"postDataCacheTime"`
PostCommentsCacheTime time.Duration `yaml:"postCommentsCacheTime"`
CrontabClearCacheTime time.Duration `yaml:"crontabClearCacheTime"`
MaxRequestSleepNum int64 `yaml:"maxRequestSleepNum"`
SleepTime []time.Duration `yaml:"sleepTime"`
MaxRequestNum int64 `yaml:"maxRequestNum"`
SingleIpSearchNum int64 `yaml:"singleIpSearchNum"`
MaxPostIdCacheTime time.Duration `yaml:"maxPostIdCacheTime"`
UserInfoCacheTime time.Duration `yaml:"userInfoCacheTime"`
CommentsCacheTime time.Duration `yaml:"commentsCacheTime"`
Gzip bool `yaml:"gzip"`
PostCommentUrl string `yaml:"postCommentUrl"`
TrustIps []string `yaml:"trustIps"`
TrustServerNames []string `yaml:"trustServerNames"`
Theme string `yaml:"theme"`
PostOrder string `yaml:"postOrder"`
UploadDir string `yaml:"uploadDir"`
Ssl Ssl `yaml:"ssl"`
Mysql Mysql `yaml:"mysql"`
Mail Mail `yaml:"mail"`
RecentPostCacheTime time.Duration `yaml:"recentPostCacheTime"`
CategoryCacheTime time.Duration `yaml:"categoryCacheTime"`
ArchiveCacheTime time.Duration `yaml:"archiveCacheTime"`
ContextPostCacheTime time.Duration `yaml:"contextPostCacheTime"`
RecentCommentsCacheTime time.Duration `yaml:"recentCommentsCacheTime"`
DigestCacheTime time.Duration `yaml:"digestCacheTime"`
DigestWordCount int `yaml:"digestWordCount"`
PostListCacheTime time.Duration `yaml:"postListCacheTime"`
SearchPostCacheTime time.Duration `yaml:"searchPostCacheTime"`
MonthPostCacheTime time.Duration `yaml:"monthPostCacheTime"`
PostDataCacheTime time.Duration `yaml:"postDataCacheTime"`
PostCommentsCacheTime time.Duration `yaml:"postCommentsCacheTime"`
CrontabClearCacheTime time.Duration `yaml:"crontabClearCacheTime"`
MaxRequestSleepNum int64 `yaml:"maxRequestSleepNum"`
SleepTime []time.Duration `yaml:"sleepTime"`
MaxRequestNum int64 `yaml:"maxRequestNum"`
SingleIpSearchNum int64 `yaml:"singleIpSearchNum"`
MaxPostIdCacheTime time.Duration `yaml:"maxPostIdCacheTime"`
UserInfoCacheTime time.Duration `yaml:"userInfoCacheTime"`
CommentsCacheTime time.Duration `yaml:"commentsCacheTime"`
ThemeHeaderImagCacheTime time.Duration `yaml:"themeHeaderImagCacheTime"`
Gzip bool `yaml:"gzip"`
PostCommentUrl string `yaml:"postCommentUrl"`
TrustIps []string `yaml:"trustIps"`
TrustServerNames []string `yaml:"trustServerNames"`
Theme string `yaml:"theme"`
PostOrder string `yaml:"postOrder"`
UploadDir string `yaml:"uploadDir"`
Pprof string `yaml:"pprof"`
}
type Ssl struct {

View File

@ -14,7 +14,7 @@ func GetPostMetaByPostIds(args ...any) (r map[uint64]map[string]any, err error)
r = make(map[uint64]map[string]any)
ctx := args[0].(context.Context)
ids := args[1].([]uint64)
rr, err := model.Find[models.Postmeta](ctx, model.SqlBuilder{
rr, err := model.Find[models.PostMeta](ctx, model.SqlBuilder{
{"post_id", "in", ""},
}, "*", "", nil, nil, nil, 0, slice.ToAnySlice(ids))
if err != nil {
@ -25,7 +25,7 @@ func GetPostMetaByPostIds(args ...any) (r map[uint64]map[string]any, err error)
r[postmeta.PostId] = make(map[string]any)
}
if postmeta.MetaKey == "_wp_attachment_metadata" {
metadata, err := models.AttachmentMetadata(postmeta.MetaValue)
metadata, err := plugins.UnPHPSerialize[models.WpAttachmentMetadata](postmeta.MetaValue)
if err != nil {
logs.ErrPrintln(err, "解析postmeta失败", postmeta.MetaId, postmeta.MetaValue)
continue

View File

@ -1,52 +1,20 @@
package models
import (
"github.com/fthvgb1/wp-go/helper/maps"
"github.com/leeqvip/gophp"
)
type Postmeta struct {
type PostMeta struct {
MetaId uint64 `db:"meta_id" json:"meta_id" form:"meta_id"`
PostId uint64 `db:"post_id" json:"post_id" form:"post_id"`
MetaKey string `db:"meta_key" json:"meta_key" form:"meta_key"`
MetaValue string `db:"meta_value" json:"meta_value" form:"meta_value"`
}
func (p Postmeta) PrimaryKey() string {
func (p PostMeta) PrimaryKey() string {
return "meta_id"
}
func (p Postmeta) Table() string {
func (p PostMeta) Table() string {
return "wp_postmeta"
}
func (p Postmeta) AttachmentMetadata() (r WpAttachmentMetadata, err error) {
if p.MetaKey == "_wp_attachment_metadata" && p.MetaValue != "" {
unSerialize, er := gophp.Unserialize([]byte(p.MetaValue))
if er != nil {
err = er
return
}
info, ok := unSerialize.(map[string]any)
if ok {
r, err = maps.StrAnyMapToStruct[WpAttachmentMetadata](info)
}
}
return
}
func AttachmentMetadata(s string) (r WpAttachmentMetadata, err error) {
unSerialize, er := gophp.Unserialize([]byte(s))
if er != nil {
err = er
return
}
info, ok := unSerialize.(map[string]any)
if ok {
r, err = maps.StrAnyMapToStruct[WpAttachmentMetadata](info)
}
return
}
type WpAttachmentMetadata struct {
Width int `json:"width,omitempty"`
Height int `json:"height,omitempty"`

View File

@ -38,9 +38,6 @@ type Posts struct {
AttachmentMetadata WpAttachmentMetadata
}
type Image struct {
}
type PostThumbnail struct {
Path string
Width int

View File

@ -0,0 +1,16 @@
package plugins
import (
"github.com/elliotchance/phpserialize"
"github.com/fthvgb1/wp-go/helper/maps"
)
func UnPHPSerialize[T any](s string) (r T, err error) {
var rr map[any]any
err = phpserialize.Unmarshal([]byte(s), &rr)
if err == nil {
rx := maps.AnyAnyToStrAny(rr)
r, err = maps.StrAnyMapToStruct[T](rx)
}
return
}

View File

@ -7,6 +7,34 @@ import (
"strings"
)
type HeaderImageMeta struct {
CustomCssPostId int `json:"custom_css_post_id,omitempty"`
NavMenuLocations []string `json:"nav_menu_locations,omitempty"`
HeaderImage string `json:"header_image,omitempty"`
HeaderImagData ImageData `json:"header_image_data,omitempty"`
SidebarsWidgets Sidebars `json:"sidebars_widgets"`
}
type Sidebars struct {
Time int `json:"time,omitempty"`
Data SidebarsData `json:"data"`
}
type SidebarsData struct {
WpInactiveWidgets []string `json:"wp_inactive_widgets,omitempty"`
Sidebar1 []string `json:"sidebar-1,omitempty"`
Sidebar2 []string `json:"sidebar-2,omitempty"`
Sidebar3 []string `json:"sidebar-3,omitempty"`
}
type ImageData struct {
AttachmentId int64 `json:"attachment_id,omitempty"`
Url string `json:"url,omitempty"`
ThumbnailUrl string `json:"thumbnail_url,omitempty"`
Height int64 `json:"height,omitempty"`
Width int64 `json:"width,omitempty"`
}
func Thumbnail(metadata models.WpAttachmentMetadata, Type, host string, except ...string) (r models.PostThumbnail) {
if _, ok := metadata.Sizes[Type]; ok {
r.Path = fmt.Sprintf("%s/wp-content/uploads/%s", host, metadata.File)

View File

@ -2,8 +2,6 @@ package twentyseventeen
import (
"fmt"
"github.com/elliotchance/phpserialize"
"github.com/fthvgb1/wp-go/helper/maps"
"github.com/fthvgb1/wp-go/helper/slice"
str "github.com/fthvgb1/wp-go/helper/strings"
"github.com/fthvgb1/wp-go/internal/pkg/cache"
@ -18,21 +16,6 @@ import (
const ThemeName = "twentyseventeen"
type HeaderImageMeta struct {
CustomCssPostId int `json:"custom_css_post_id,omitempty"`
NavMenuLocations []string `json:"nav_menu_locations,omitempty"`
HeaderImage string `json:"header_image,omitempty"`
HeaderImagData ImageData `json:"header_image_data,omitempty"`
}
type ImageData struct {
AttachmentId int64 `json:"attachment_id,omitempty"`
Url string `json:"url,omitempty"`
ThumbnailUrl string `json:"thumbnail_url,omitempty"`
Height int64 `json:"height,omitempty"`
Width int64 `json:"width,omitempty"`
}
var paginate = func() plugins.PageEle {
p := plugins.TwentyFifteenPagination()
p.PrevEle = `<a class="prev page-numbers" href="%s"><svg class="icon icon-arrow-left" aria-hidden="true" role="img"> <use href="#icon-arrow-left" xlink:href="#icon-arrow-left"></use> </svg>
@ -45,8 +28,11 @@ var paginate = func() plugins.PageEle {
func Hook(status int, c *gin.Context, h gin.H, scene, stats int) {
templ := "twentyseventeen/posts/index.gohtml"
h["HeaderImage"] = getHeaderImage(c)
if stats == plugins.Empty404 {
c.HTML(status, templ, h)
}
if _, ok := plugins.IndexSceneMap[scene]; ok {
h["HeaderImage"] = getHeaderImage(c)
posts := h["posts"].([]models.Posts)
p, ok := h["pagination"]
if ok {
@ -85,7 +71,6 @@ func Hook(status int, c *gin.Context, h gin.H, scene, stats int) {
h["bodyClass"] = bodyClass(scene, d, s)
h["posts"] = postThumbnail(posts, scene)
} else if scene == plugins.Detail {
h["HeaderImage"] = getHeaderImage(c)
post := h["post"].(models.Posts)
h["bodyClass"] = bodyClass(scene, int(post.Id))
//host, _ := wpconfig.Options.Load("siteurl")
@ -139,43 +124,16 @@ func postThumbnail(posts []models.Posts, scene int) []models.Posts {
func getHeaderImage(c *gin.Context) (r models.PostThumbnail) {
r.Path = "/wp-content/themes/twentyseventeen/assets/images/header.jpg"
meta, err := getHeaderMarkup()
if err != nil {
logs.ErrPrintln(err, "解析主题背景图设置错误")
return
}
if meta.HeaderImagData.AttachmentId > 0 {
m, err := cache.GetPostById(c, uint64(meta.HeaderImagData.AttachmentId))
if err != nil {
logs.ErrPrintln(err, "获取主题背景图信息错误")
return
}
//host, _ := wpconfig.Options.Load("siteurl")
host := ""
m.Thumbnail = plugins.Thumbnail(m.AttachmentMetadata, "thumbnail", host, "thumbnail", "post-thumbnail", "twentyseventeen-thumbnail-avatar")
if m.Thumbnail.Path != "" {
r = m.Thumbnail
if len(m.AttachmentMetadata.Sizes) > 0 {
r.Srcset = str.Join(r.Path, " 2000w, ", r.Srcset)
}
}
}
r.Width = 2000
r.Height = 1200
r.Sizes = "100vw"
return
}
func getHeaderMarkup() (r HeaderImageMeta, err error) {
mods, ok := wpconfig.Options.Load("theme_mods_twentyseventeen")
var rr map[any]any
if ok {
err = phpserialize.Unmarshal([]byte(mods), &rr)
if err == nil {
rx := maps.AnyAnyToStrAny(rr)
r, err = maps.StrAnyMapToStruct[HeaderImageMeta](rx)
}
t, _ := wpconfig.Options.Load("template")
hs, err := cache.GetHeaderImages(c, t)
if err != nil {
logs.ErrPrintln(err, "获取页眉背景图失败")
} else if len(hs) > 0 && err == nil {
_, r = slice.Rand(hs)
}
r.Sizes = "100vw"
return
}