commit
f470a0c31f
|
@ -71,3 +71,7 @@ trustIps: []
|
|||
trustServerNames: ["xy.test","blog.xy.test"]
|
||||
# port
|
||||
port: 8082
|
||||
# 主题 为空值为option template,没有就默认为twentyfifteen
|
||||
theme: "twentyfifteen"
|
||||
# 文档排序默认升序还是降序
|
||||
postOrder: "desc"
|
1
helper/html/a.gohtml
Normal file
1
helper/html/a.gohtml
Normal file
|
@ -0,0 +1 @@
|
|||
{{.xx}}
|
|
@ -1,9 +1,11 @@
|
|||
package html
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"github.com/dlclark/regexp2"
|
||||
"github.com/fthvgb1/wp-go/helper/slice"
|
||||
"html/template"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
@ -164,3 +166,13 @@ func UnClosedTag(s []string) []string {
|
|||
i++
|
||||
}
|
||||
}
|
||||
|
||||
func RenderedHtml(t *template.Template, data map[string]any) (r string, err error) {
|
||||
var buf bytes.Buffer
|
||||
err = t.Execute(&buf, data)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
r = buf.String()
|
||||
return
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package html
|
||||
|
||||
import (
|
||||
"html/template"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
@ -228,3 +229,46 @@ func Test_clearTag(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestRenderedHtml(t *testing.T) {
|
||||
type args struct {
|
||||
t *template.Template
|
||||
data map[string]any
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
wantR string
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "t1",
|
||||
args: args{
|
||||
t: func() *template.Template {
|
||||
tt, err := template.ParseFiles("./a.gohtml")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return tt
|
||||
}(),
|
||||
data: map[string]any{
|
||||
"xx": "oo",
|
||||
},
|
||||
},
|
||||
wantR: "oo",
|
||||
wantErr: false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
gotR, err := RenderedHtml(tt.args.t, tt.args.data)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("RenderedHtml() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
if gotR != tt.wantR {
|
||||
t.Errorf("RenderedHtml() gotR = %v, want %v", gotR, tt.wantR)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
114
helper/slice/set.go
Normal file
114
helper/slice/set.go
Normal file
|
@ -0,0 +1,114 @@
|
|||
package slice
|
||||
|
||||
func IsContained[T comparable](a T, arr []T) bool {
|
||||
for _, v := range arr {
|
||||
if a == v {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func IsContainedByFn[T any](a []T, e T, fn func(i, j T) bool) bool {
|
||||
for _, t := range a {
|
||||
if fn(e, t) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Diff return elements which in a and not in b,...
|
||||
func Diff[T comparable](a []T, b ...[]T) (r []T) {
|
||||
for _, t := range a {
|
||||
f := false
|
||||
for _, ts := range b {
|
||||
if IsContained(t, ts) {
|
||||
f = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if f {
|
||||
continue
|
||||
}
|
||||
r = append(r, t)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func DiffByFn[T any](a []T, fn func(i, j T) bool, b ...[]T) (r []T) {
|
||||
for _, t := range a {
|
||||
f := false
|
||||
for _, ts := range b {
|
||||
if IsContainedByFn(ts, t, fn) {
|
||||
f = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if f {
|
||||
continue
|
||||
}
|
||||
r = append(r, t)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func Intersect[T comparable](a []T, b ...[]T) (r []T) {
|
||||
for _, t := range a {
|
||||
f := false
|
||||
for _, ts := range b {
|
||||
if !IsContained(t, ts) {
|
||||
f = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if f {
|
||||
continue
|
||||
}
|
||||
r = append(r, t)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func IntersectByFn[T any](a []T, fn func(i, j T) bool, b ...[]T) (r []T) {
|
||||
for _, t := range a {
|
||||
f := false
|
||||
for _, ts := range b {
|
||||
if !IsContainedByFn(ts, t, fn) {
|
||||
f = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if f {
|
||||
continue
|
||||
}
|
||||
r = append(r, t)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func Unique[T comparable](a ...[]T) (r []T) {
|
||||
m := map[T]struct{}{}
|
||||
for _, ts := range a {
|
||||
for _, t := range ts {
|
||||
if _, ok := m[t]; !ok {
|
||||
m[t] = struct{}{}
|
||||
r = append(r, t)
|
||||
} else {
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func UniqueByFn[T any](fn func(T, T) bool, a ...[]T) (r []T) {
|
||||
for _, ts := range a {
|
||||
for _, t := range ts {
|
||||
if !IsContainedByFn(r, t, fn) {
|
||||
r = append(r, t)
|
||||
}
|
||||
}
|
||||
}
|
||||
return r
|
||||
}
|
211
helper/slice/set_test.go
Normal file
211
helper/slice/set_test.go
Normal file
|
@ -0,0 +1,211 @@
|
|||
package slice
|
||||
|
||||
import (
|
||||
"github.com/fthvgb1/wp-go/helper/number"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type x struct {
|
||||
int
|
||||
y string
|
||||
}
|
||||
|
||||
func y(i []int) []x {
|
||||
return Map(i, func(t int) x {
|
||||
return x{t, ""}
|
||||
})
|
||||
}
|
||||
|
||||
func TestDiff(t *testing.T) {
|
||||
type args[T int] struct {
|
||||
a []T
|
||||
b [][]T
|
||||
}
|
||||
type testCase[T int] struct {
|
||||
name string
|
||||
args args[T]
|
||||
wantR []T
|
||||
}
|
||||
tests := []testCase[int]{
|
||||
{
|
||||
name: "t1",
|
||||
args: args[int]{
|
||||
a: number.Range(1, 10, 1),
|
||||
b: [][]int{number.Range(3, 7, 1), number.Range(6, 9, 1)},
|
||||
},
|
||||
wantR: []int{1, 2, 10},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if gotR := Diff(tt.args.a, tt.args.b...); !reflect.DeepEqual(gotR, tt.wantR) {
|
||||
t.Errorf("Diff() = %v, want %v", gotR, tt.wantR)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestDiffByFn(t *testing.T) {
|
||||
|
||||
type args[T x] struct {
|
||||
a []T
|
||||
fn func(i, j T) bool
|
||||
b [][]T
|
||||
}
|
||||
type testCase[T x] struct {
|
||||
name string
|
||||
args args[T]
|
||||
wantR []T
|
||||
}
|
||||
tests := []testCase[x]{
|
||||
{
|
||||
name: "t1",
|
||||
args: args[x]{
|
||||
a: y(number.Range(1, 10, 1)),
|
||||
fn: func(i, j x) bool {
|
||||
return i.int == j.int
|
||||
},
|
||||
b: [][]x{
|
||||
y(number.Range(3, 7, 1)),
|
||||
y(number.Range(6, 9, 1)),
|
||||
},
|
||||
},
|
||||
wantR: []x{{1, ""}, {2, ""}, {10, ""}},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if gotR := DiffByFn(tt.args.a, tt.args.fn, tt.args.b...); !reflect.DeepEqual(gotR, tt.wantR) {
|
||||
t.Errorf("DiffByFn() = %v, want %v", gotR, tt.wantR)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestIntersect(t *testing.T) {
|
||||
type args[T int] struct {
|
||||
a []T
|
||||
b [][]T
|
||||
}
|
||||
type testCase[T int] struct {
|
||||
name string
|
||||
args args[T]
|
||||
wantR []T
|
||||
}
|
||||
tests := []testCase[int]{
|
||||
{
|
||||
name: "t1",
|
||||
args: args[int]{
|
||||
a: number.Range(1, 10, 1),
|
||||
b: [][]int{number.Range(3, 7, 1), number.Range(6, 9, 1)},
|
||||
},
|
||||
wantR: []int{6, 7},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if gotR := Intersect(tt.args.a, tt.args.b...); !reflect.DeepEqual(gotR, tt.wantR) {
|
||||
t.Errorf("Intersect() = %v, want %v", gotR, tt.wantR)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestIntersectByFn(t *testing.T) {
|
||||
type args[T x] struct {
|
||||
a []T
|
||||
fn func(i, j T) bool
|
||||
b [][]T
|
||||
}
|
||||
type testCase[T x] struct {
|
||||
name string
|
||||
args args[T]
|
||||
wantR []T
|
||||
}
|
||||
tests := []testCase[x]{
|
||||
{
|
||||
name: "t1",
|
||||
args: args[x]{
|
||||
a: y(number.Range(1, 10, 1)),
|
||||
fn: func(i, j x) bool {
|
||||
return i.int == j.int
|
||||
},
|
||||
b: [][]x{
|
||||
y(number.Range(3, 7, 1)),
|
||||
y(number.Range(6, 9, 1)),
|
||||
},
|
||||
},
|
||||
wantR: []x{{6, ""}, {7, ""}},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if gotR := IntersectByFn(tt.args.a, tt.args.fn, tt.args.b...); !reflect.DeepEqual(gotR, tt.wantR) {
|
||||
t.Errorf("IntersectByFn() = %v, want %v", gotR, tt.wantR)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestUnique(t *testing.T) {
|
||||
type args[T int] struct {
|
||||
a [][]T
|
||||
}
|
||||
type testCase[T int] struct {
|
||||
name string
|
||||
args args[T]
|
||||
wantR []T
|
||||
}
|
||||
tests := []testCase[int]{
|
||||
{
|
||||
name: "t1",
|
||||
args: args[int]{
|
||||
a: [][]int{
|
||||
number.Range(1, 5, 1),
|
||||
number.Range(3, 6, 1),
|
||||
number.Range(6, 15, 1),
|
||||
},
|
||||
},
|
||||
wantR: number.Range(1, 15, 1),
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if gotR := Unique(tt.args.a...); !reflect.DeepEqual(gotR, tt.wantR) {
|
||||
t.Errorf("Unique() = %v, want %v", gotR, tt.wantR)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestUniqueByFn(t *testing.T) {
|
||||
type args[T x] struct {
|
||||
fn func(T, T) bool
|
||||
a [][]T
|
||||
}
|
||||
type testCase[T x] struct {
|
||||
name string
|
||||
args args[T]
|
||||
wantR []T
|
||||
}
|
||||
tests := []testCase[x]{
|
||||
{
|
||||
name: "t1",
|
||||
args: args[x]{
|
||||
fn: func(i, j x) bool {
|
||||
return i.int == j.int
|
||||
},
|
||||
a: [][]x{y([]int{1, 1, 2, 2, 3, 3}), y([]int{2, 2, 4, 4})},
|
||||
},
|
||||
wantR: y([]int{1, 2, 3, 4}),
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if gotR := UniqueByFn(tt.args.fn, tt.args.a...); !reflect.DeepEqual(gotR, tt.wantR) {
|
||||
t.Errorf("UniqueByFn() = %v, want %v", gotR, tt.wantR)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
|
@ -1,5 +1,7 @@
|
|||
package slice
|
||||
|
||||
import "github.com/fthvgb1/wp-go/helper"
|
||||
|
||||
func Map[T, R any](arr []T, fn func(T) R) []R {
|
||||
r := make([]R, 0, len(arr))
|
||||
for _, t := range arr {
|
||||
|
@ -146,11 +148,19 @@ func Comb[T any](arr []T, m int) (r [][]T) {
|
|||
return r
|
||||
}
|
||||
|
||||
func IsContained[T comparable](a T, arr []T) bool {
|
||||
for _, v := range arr {
|
||||
if a == v {
|
||||
return true
|
||||
func GroupBy[K comparable, T, V any](a []T, fn func(T) (K, V)) map[K][]V {
|
||||
r := make(map[K][]V)
|
||||
for _, t := range a {
|
||||
k, v := fn(t)
|
||||
if _, ok := r[k]; !ok {
|
||||
r[k] = []V{v}
|
||||
} else {
|
||||
r[k] = append(r[k], v)
|
||||
}
|
||||
}
|
||||
return false
|
||||
return r
|
||||
}
|
||||
|
||||
func ToAnySlice[T any](a []T) []any {
|
||||
return Map(a, helper.ToAny[T])
|
||||
}
|
||||
|
|
|
@ -463,3 +463,67 @@ func TestFilterAndMap(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGroupBy(t *testing.T) {
|
||||
type args[T x, K int, V string] struct {
|
||||
a []T
|
||||
fn func(T) (K, V)
|
||||
}
|
||||
type testCase[T x, K int, V string] struct {
|
||||
name string
|
||||
args args[T, K, V]
|
||||
want map[K][]V
|
||||
}
|
||||
tests := []testCase[x, int, string]{
|
||||
{
|
||||
name: "t1",
|
||||
args: args[x, int, string]{
|
||||
a: Map([]int{1, 1, 2, 2, 3, 3, 4, 4, 5, 5}, func(t int) x {
|
||||
return x{t, number.ToString(t)}
|
||||
}),
|
||||
fn: func(v x) (int, string) {
|
||||
return v.int, v.y
|
||||
},
|
||||
},
|
||||
want: map[int][]string{
|
||||
1: {"1", "1"},
|
||||
2: {"2", "2"},
|
||||
3: {"3", "3"},
|
||||
4: {"4", "4"},
|
||||
5: {"5", "5"},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := GroupBy(tt.args.a, tt.args.fn); !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("GroupBy() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestToAnySlice(t *testing.T) {
|
||||
type args[T int] struct {
|
||||
a []T
|
||||
}
|
||||
type testCase[T int] struct {
|
||||
name string
|
||||
args args[T]
|
||||
want []any
|
||||
}
|
||||
tests := []testCase[int]{
|
||||
{
|
||||
name: "t1",
|
||||
args: args[int]{number.Range(1, 5, 1)},
|
||||
want: []any{1, 2, 3, 4, 5},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := ToAnySlice(tt.args.a); !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("ToAnySlice() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,6 @@ package actions
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
str "github.com/fthvgb1/wp-go/helper/strings"
|
||||
"github.com/fthvgb1/wp-go/internal/pkg/cache"
|
||||
"github.com/fthvgb1/wp-go/internal/pkg/logs"
|
||||
"github.com/fthvgb1/wp-go/internal/pkg/models"
|
||||
|
@ -30,7 +29,7 @@ func Detail(c *gin.Context) {
|
|||
archive := cache.Archives(c)
|
||||
categoryItems := cache.Categories(c)
|
||||
recentComments := cache.RecentComments(c, 5)
|
||||
var h = gin.H{
|
||||
var ginH = gin.H{
|
||||
"title": wpconfig.Options.Value("blogname"),
|
||||
"options": wpconfig.Options,
|
||||
"recentPosts": recent,
|
||||
|
@ -39,17 +38,21 @@ func Detail(c *gin.Context) {
|
|||
"recentComments": recentComments,
|
||||
}
|
||||
isApproveComment := false
|
||||
status := plugins.Ok
|
||||
defer func() {
|
||||
status := http.StatusOK
|
||||
code := http.StatusOK
|
||||
if err != nil {
|
||||
status = http.StatusInternalServerError
|
||||
code = http.StatusNotFound
|
||||
c.Error(err)
|
||||
status = plugins.Error
|
||||
return
|
||||
}
|
||||
if isApproveComment == true {
|
||||
return
|
||||
}
|
||||
c.HTML(status, str.Join(theme.GetTemplateName(), "/posts/detail.gohtml"), h)
|
||||
|
||||
t := theme.GetTemplateName()
|
||||
theme.Hook(t, code, c, ginH, plugins.Detail, status)
|
||||
}()
|
||||
id := c.Param("id")
|
||||
Id := 0
|
||||
|
@ -92,19 +95,19 @@ func Detail(c *gin.Context) {
|
|||
commentss := treeComments(comments)
|
||||
prev, next, err := cache.GetContextPost(c, post.Id, post.PostDate)
|
||||
logs.ErrPrintln(err, "get pre and next post", post.Id, post.PostDate)
|
||||
h["title"] = fmt.Sprintf("%s-%s", post.PostTitle, wpconfig.Options.Value("blogname"))
|
||||
h["post"] = post
|
||||
h["showComment"] = showComment
|
||||
h["prev"] = prev
|
||||
ginH["title"] = fmt.Sprintf("%s-%s", post.PostTitle, wpconfig.Options.Value("blogname"))
|
||||
ginH["post"] = post
|
||||
ginH["showComment"] = showComment
|
||||
ginH["prev"] = prev
|
||||
depth := wpconfig.Options.Value("thread_comments_depth")
|
||||
d, err := strconv.Atoi(depth)
|
||||
if err != nil {
|
||||
logs.ErrPrintln(err, "get comment depth")
|
||||
logs.ErrPrintln(err, "get comment depth ", depth)
|
||||
d = 5
|
||||
}
|
||||
h["comments"] = hh.formatComment(commentss, 1, d)
|
||||
h["next"] = next
|
||||
h["user"] = user
|
||||
ginH["comments"] = hh.formatComment(commentss, 1, d)
|
||||
ginH["next"] = next
|
||||
ginH["user"] = user
|
||||
}
|
||||
|
||||
type Comment struct {
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
"github.com/fthvgb1/wp-go/helper/slice"
|
||||
str "github.com/fthvgb1/wp-go/helper/strings"
|
||||
"github.com/fthvgb1/wp-go/internal/pkg/cache"
|
||||
"github.com/fthvgb1/wp-go/internal/pkg/config"
|
||||
"github.com/fthvgb1/wp-go/internal/pkg/dao"
|
||||
"github.com/fthvgb1/wp-go/internal/pkg/logs"
|
||||
"github.com/fthvgb1/wp-go/internal/pkg/models"
|
||||
|
@ -92,10 +93,17 @@ func (h *indexHandle) getSearchKey() string {
|
|||
return fmt.Sprintf("action:%s|%s|%s|%s|%s|%s|%d|%d", h.author, h.search, h.orderBy, h.order, h.category, h.categoryType, h.page, h.pageSize)
|
||||
}
|
||||
|
||||
var orders = []string{"asc", "desc"}
|
||||
|
||||
func (h *indexHandle) parseParams() (err error) {
|
||||
h.order = h.c.Query("order")
|
||||
if !slice.IsContained(h.order, []string{"asc", "desc"}) {
|
||||
|
||||
if !slice.IsContained(h.order, orders) {
|
||||
order := config.Conf.Load().PostOrder
|
||||
h.order = "asc"
|
||||
if order != "" && slice.IsContained(order, orders) {
|
||||
h.order = order
|
||||
}
|
||||
}
|
||||
year := h.c.Param("year")
|
||||
if year != "" {
|
||||
|
|
|
@ -21,34 +21,37 @@ func RecoverAndSendMail(w io.Writer) func(ctx *gin.Context) {
|
|||
return gin.CustomRecoveryWithWriter(w, func(ctx *gin.Context, err any) {
|
||||
c := ctx.Copy()
|
||||
stack := stack(4)
|
||||
go func() {
|
||||
httpRequest, _ := httputil.DumpRequest(c.Request, true)
|
||||
headers := strings.Split(string(httpRequest), "\r\n")
|
||||
for idx, header := range headers {
|
||||
current := strings.Split(header, ":")
|
||||
if current[0] == "Authorization" {
|
||||
headers[idx] = current[0] + ": *"
|
||||
if gin.Mode() == gin.ReleaseMode {
|
||||
go func() {
|
||||
httpRequest, _ := httputil.DumpRequest(c.Request, true)
|
||||
headers := strings.Split(string(httpRequest), "\r\n")
|
||||
for idx, header := range headers {
|
||||
current := strings.Split(header, ":")
|
||||
if current[0] == "Authorization" {
|
||||
headers[idx] = current[0] + ": *"
|
||||
}
|
||||
}
|
||||
}
|
||||
headersToStr := strings.Join(headers, "<br/>")
|
||||
content := `<dl><dt>err:</dt><dd>%v</dd><hr/>
|
||||
headersToStr := strings.Join(headers, "<br/>")
|
||||
content := `<dl><dt>err:</dt><dd>%v</dd><hr/>
|
||||
<dt>stack: </dt><dd>%v</dd><hr/>
|
||||
<dt>headers: </dt><dd>%s</dd></dl>
|
||||
`
|
||||
content = fmt.Sprintf(content,
|
||||
err,
|
||||
formatStack(string(stack)),
|
||||
headersToStr,
|
||||
)
|
||||
content = fmt.Sprintf(content,
|
||||
err,
|
||||
formatStack(string(stack)),
|
||||
headersToStr,
|
||||
)
|
||||
|
||||
er := mail.SendMail(
|
||||
[]string{config.Conf.Load().Mail.User},
|
||||
fmt.Sprintf("%s%s %s 发生错误", fmt.Sprintf(wpconfig.Options.Value("siteurl")), c.FullPath(), time.Now().Format(time.RFC1123Z)), content)
|
||||
er := mail.SendMail(
|
||||
[]string{config.Conf.Load().Mail.User},
|
||||
fmt.Sprintf("%s%s %s 发生错误", fmt.Sprintf(wpconfig.Options.Value("siteurl")), c.FullPath(), time.Now().Format(time.RFC1123Z)), content)
|
||||
|
||||
if er != nil {
|
||||
logs.ErrPrintln(er, "recover send mail fail", fmt.Sprintf("%v", err))
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
if er != nil {
|
||||
logs.ErrPrintln(er, "recover send mail fail", fmt.Sprintf("%v", err))
|
||||
}
|
||||
}()
|
||||
ctx.AbortWithStatus(http.StatusInternalServerError)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -38,6 +38,7 @@ type Config struct {
|
|||
TrustIps []string `yaml:"trustIps"`
|
||||
TrustServerNames []string `yaml:"trustServerNames"`
|
||||
Theme string `yaml:"theme"`
|
||||
PostOrder string `yaml:"postOrder"`
|
||||
}
|
||||
|
||||
type Mail struct {
|
||||
|
|
|
@ -2,7 +2,6 @@ package dao
|
|||
|
||||
import (
|
||||
"context"
|
||||
"github.com/fthvgb1/wp-go/helper"
|
||||
"github.com/fthvgb1/wp-go/helper/slice"
|
||||
"github.com/fthvgb1/wp-go/internal/pkg/models"
|
||||
"github.com/fthvgb1/wp-go/model"
|
||||
|
@ -48,7 +47,7 @@ func GetCommentByIds(args ...any) (map[uint64]models.Comments, error) {
|
|||
m := make(map[uint64]models.Comments)
|
||||
r, err := model.SimpleFind[models.Comments](ctx, model.SqlBuilder{
|
||||
{"comment_ID", "in", ""}, {"comment_approved", "1"},
|
||||
}, "*", slice.Map(ids, helper.ToAny[uint64]))
|
||||
}, "*", slice.ToAnySlice(ids))
|
||||
if err != nil {
|
||||
return m, err
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@ package dao
|
|||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/fthvgb1/wp-go/helper"
|
||||
"github.com/fthvgb1/wp-go/helper/maps"
|
||||
"github.com/fthvgb1/wp-go/helper/slice"
|
||||
"github.com/fthvgb1/wp-go/internal/pkg/logs"
|
||||
|
@ -19,7 +18,7 @@ func GetPostMetaByPostIds(args ...any) (r map[uint64]map[string]any, err error)
|
|||
ids := args[1].([]uint64)
|
||||
rr, err := model.Find[models.Postmeta](ctx, model.SqlBuilder{
|
||||
{"post_id", "in", ""},
|
||||
}, "*", "", nil, nil, nil, 0, slice.Map(ids, helper.ToAny[uint64]))
|
||||
}, "*", "", nil, nil, nil, 0, slice.ToAnySlice(ids))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -93,6 +92,7 @@ func thumbnail(metadata models.WpAttachmentMetadata, thumbType, host string) (r
|
|||
} else if r.Width >= 767 {
|
||||
r.Sizes = "(max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px"
|
||||
}
|
||||
r.OriginAttachmentData = metadata
|
||||
}
|
||||
return
|
||||
}
|
||||
|
|
|
@ -4,7 +4,6 @@ import (
|
|||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"github.com/fthvgb1/wp-go/helper"
|
||||
"github.com/fthvgb1/wp-go/helper/slice"
|
||||
"github.com/fthvgb1/wp-go/internal/pkg/models"
|
||||
"github.com/fthvgb1/wp-go/internal/wpconfig"
|
||||
|
@ -18,7 +17,7 @@ func GetPostsByIds(ids ...any) (m map[uint64]models.Posts, err error) {
|
|||
ctx := ids[0].(context.Context)
|
||||
m = make(map[uint64]models.Posts)
|
||||
id := ids[1].([]uint64)
|
||||
arg := slice.Map(id, helper.ToAny[uint64])
|
||||
arg := slice.ToAnySlice(id)
|
||||
rawPosts, err := model.Find[models.Posts](ctx, model.SqlBuilder{{
|
||||
"Id", "in", "",
|
||||
}}, "a.*,ifnull(d.name,'') category_name,ifnull(taxonomy,'') `taxonomy`", "", nil, model.SqlBuilder{{
|
||||
|
|
|
@ -38,12 +38,16 @@ type Posts struct {
|
|||
AttachmentMetadata WpAttachmentMetadata
|
||||
}
|
||||
|
||||
type Image struct {
|
||||
}
|
||||
|
||||
type PostThumbnail struct {
|
||||
Path string
|
||||
Width int
|
||||
Height int
|
||||
Srcset string
|
||||
Sizes string
|
||||
Path string
|
||||
Width int
|
||||
Height int
|
||||
Srcset string
|
||||
Sizes string
|
||||
OriginAttachmentData WpAttachmentMetadata
|
||||
}
|
||||
|
||||
func (w Posts) PrimaryKey() string {
|
||||
|
|
|
@ -52,6 +52,7 @@ func Hook(status int, c *gin.Context, h gin.H, scene, stats int) {
|
|||
}
|
||||
}
|
||||
} else if scene == plugins.Detail {
|
||||
h["HeaderImage"] = getHeaderImage(c)
|
||||
templ = "twentyseventeen/posts/detail.gohtml"
|
||||
}
|
||||
c.HTML(status, templ, h)
|
||||
|
|
|
@ -3,7 +3,6 @@ package model
|
|||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"github.com/fthvgb1/wp-go/helper"
|
||||
"github.com/fthvgb1/wp-go/helper/number"
|
||||
"github.com/fthvgb1/wp-go/helper/slice"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
|
@ -499,10 +498,10 @@ func TestSimplePagination(t *testing.T) {
|
|||
order: nil,
|
||||
join: nil,
|
||||
having: nil,
|
||||
in: [][]any{slice.Map[int, any](number.Range(431, 440, 1), helper.ToAny[int])},
|
||||
in: [][]any{slice.ToAnySlice(number.Range(431, 440, 1))},
|
||||
},
|
||||
wantR: func() (r []post) {
|
||||
r, err := Select[post](ctx, "select * from "+post{}.Table()+" where ID in (?,?,?,?,?)", slice.Map[int, any](number.Range(431, 435, 1), helper.ToAny[int])...)
|
||||
r, err := Select[post](ctx, "select * from "+post{}.Table()+" where ID in (?,?,?,?,?)", slice.ToAnySlice(number.Range(431, 435, 1))...)
|
||||
if err != nil && err != sql.ErrNoRows {
|
||||
panic(err)
|
||||
} else if err == sql.ErrNoRows {
|
||||
|
|
|
@ -17,6 +17,22 @@ type MultipleFsTemplate struct {
|
|||
Fs embed.FS
|
||||
}
|
||||
|
||||
func (t *MultipleFileTemplate) AppendTemplate(name string, templates ...string) *MultipleFileTemplate {
|
||||
tmpl, ok := t.Template[name]
|
||||
if ok {
|
||||
t.Template[name] = template.Must(tmpl.ParseFiles(templates...))
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
||||
func (t *MultipleFsTemplate) AppendTemplate(name string, templates ...string) *MultipleFsTemplate {
|
||||
tmpl, ok := t.Template[name]
|
||||
if ok {
|
||||
t.Template[name] = template.Must(tmpl.ParseFS(t.Fs, templates...))
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
||||
func NewFileTemplate() *MultipleFileTemplate {
|
||||
return &MultipleFileTemplate{
|
||||
Template: make(map[string]*template.Template),
|
||||
|
@ -47,9 +63,6 @@ func (t *MultipleFileTemplate) AddTemplate(mainTemplatePattern string, fnMap tem
|
|||
panic(err)
|
||||
}
|
||||
for _, mainTemplate := range mainTemplates {
|
||||
if _, ok := t.Template[mainTemplate]; ok {
|
||||
panic("exists same Template " + mainTemplate)
|
||||
}
|
||||
file := filepath.Base(mainTemplate)
|
||||
pattern := append([]string{mainTemplate}, layoutTemplatePattern...)
|
||||
t.Template[mainTemplate] = template.Must(template.New(file).Funcs(fnMap).ParseFiles(pattern...))
|
||||
|
|
Loading…
Reference in New Issue
Block a user