From d9aa8cbd4e288c35239a646b81afb3fc7487cb4f Mon Sep 17 00:00:00 2001 From: xing Date: Tue, 31 Jan 2023 14:25:25 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E5=AE=8C=E5=96=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- helper/slice/slice.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/helper/slice/slice.go b/helper/slice/slice.go index 0cb7366..0a74454 100644 --- a/helper/slice/slice.go +++ b/helper/slice/slice.go @@ -225,6 +225,12 @@ func Pop[T any](a *[]T) T { // Rand 随机取一个元素 func Rand[T any](a []T) (int, T) { + var r T + if len(a) < 1 { + return -1, r + } else if len(a) == 1 { + return 0, a[0] + } i := number.Rand(0, len(a)-1) return i, a[i] } From 76ddae21db34a68cac07829cd6919f746c2d79c0 Mon Sep 17 00:00:00 2001 From: xing Date: Wed, 1 Feb 2023 00:58:42 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E9=A1=B5=E7=9C=89=E9=9A=8F=E6=9C=BA?= =?UTF-8?q?=E5=B1=95=E7=A4=BA=E5=9B=BE=E7=89=87=E5=8F=8A=E7=BC=93=E5=AD=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config.example.yaml | 7 +- go.mod | 1 - go.sum | 2 - internal/cmd/route/route.go | 4 +- internal/pkg/cache/cache.go | 6 +- internal/pkg/cache/headerImages.go | 78 +++++++++++++++++++ internal/pkg/config/config.go | 62 ++++++++------- internal/pkg/dao/postmeta.go | 4 +- internal/pkg/models/wp_postmeta.go | 38 +-------- internal/pkg/models/wp_posts.go | 3 - internal/plugins/phpserialize.go | 16 ++++ internal/plugins/thumbnail.go | 28 +++++++ .../theme/twentyseventeen/twentyseventeen.go | 64 +++------------ 13 files changed, 183 insertions(+), 130 deletions(-) create mode 100644 internal/pkg/cache/headerImages.go create mode 100644 internal/plugins/phpserialize.go diff --git a/config.example.yaml b/config.example.yaml index c39c68d..e0618be 100644 --- a/config.example.yaml +++ b/config.example.yaml @@ -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: "" \ No newline at end of file +uploadDir: "" +# pprof route path 为空表示不开启pprof,否则为pprof的路由 +pprof: "/debug/pprof" \ No newline at end of file diff --git a/go.mod b/go.mod index 0d0215e..8958307 100644 --- a/go.mod +++ b/go.mod @@ -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 diff --git a/go.sum b/go.sum index ae8787e..8ad4c55 100644 --- a/go.sum +++ b/go.sum @@ -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= diff --git a/internal/cmd/route/route.go b/internal/cmd/route/route.go index 9da364f..2763e11 100644 --- a/internal/cmd/route/route.go +++ b/internal/cmd/route/route.go @@ -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() diff --git a/internal/pkg/cache/cache.go b/internal/pkg/cache/cache.go index 52c4182..11f6f7f 100644 --- a/internal/pkg/cache/cache.go +++ b/internal/pkg/cache/cache.go @@ -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) { diff --git a/internal/pkg/cache/headerImages.go b/internal/pkg/cache/headerImages.go new file mode 100644 index 0000000..5341a48 --- /dev/null +++ b/internal/pkg/cache/headerImages.go @@ -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 +} diff --git a/internal/pkg/config/config.go b/internal/pkg/config/config.go index b957ec5..ea0d070 100644 --- a/internal/pkg/config/config.go +++ b/internal/pkg/config/config.go @@ -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 { diff --git a/internal/pkg/dao/postmeta.go b/internal/pkg/dao/postmeta.go index ec92134..ceb567c 100644 --- a/internal/pkg/dao/postmeta.go +++ b/internal/pkg/dao/postmeta.go @@ -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 diff --git a/internal/pkg/models/wp_postmeta.go b/internal/pkg/models/wp_postmeta.go index 2d1b358..b31bb72 100644 --- a/internal/pkg/models/wp_postmeta.go +++ b/internal/pkg/models/wp_postmeta.go @@ -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"` diff --git a/internal/pkg/models/wp_posts.go b/internal/pkg/models/wp_posts.go index 150ab59..df3df27 100644 --- a/internal/pkg/models/wp_posts.go +++ b/internal/pkg/models/wp_posts.go @@ -38,9 +38,6 @@ type Posts struct { AttachmentMetadata WpAttachmentMetadata } -type Image struct { -} - type PostThumbnail struct { Path string Width int diff --git a/internal/plugins/phpserialize.go b/internal/plugins/phpserialize.go new file mode 100644 index 0000000..c1cd45c --- /dev/null +++ b/internal/plugins/phpserialize.go @@ -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 +} diff --git a/internal/plugins/thumbnail.go b/internal/plugins/thumbnail.go index a124589..6046fbf 100644 --- a/internal/plugins/thumbnail.go +++ b/internal/plugins/thumbnail.go @@ -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) diff --git a/internal/theme/twentyseventeen/twentyseventeen.go b/internal/theme/twentyseventeen/twentyseventeen.go index 48e934e..972ab9d 100644 --- a/internal/theme/twentyseventeen/twentyseventeen.go +++ b/internal/theme/twentyseventeen/twentyseventeen.go @@ -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 = `