mirror of
https://github.com/eiblog/eiblog.git
synced 2026-02-17 11:52:27 +08:00
refactor: refactor eiblog
This commit is contained in:
4
.github/workflows/release.yml
vendored
4
.github/workflows/release.yml
vendored
@@ -33,7 +33,7 @@ jobs:
|
|||||||
uses: docker/build-push-action@v3
|
uses: docker/build-push-action@v3
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
file: ./build/package/eiblog.Dockerfile
|
file: ./build/package/eiblog/Dockerfile
|
||||||
platforms: linux/amd64,linux/arm64,linux/arm/v7
|
platforms: linux/amd64,linux/arm64,linux/arm/v7
|
||||||
push: true
|
push: true
|
||||||
tags: |
|
tags: |
|
||||||
@@ -44,7 +44,7 @@ jobs:
|
|||||||
uses: docker/build-push-action@v3
|
uses: docker/build-push-action@v3
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
file: ./build/package/backup.Dockerfile
|
file: ./build/package/backup/Dockerfile
|
||||||
platforms: linux/amd64,linux/arm64,linux/arm/v7
|
platforms: linux/amd64,linux/arm64,linux/arm/v7
|
||||||
push: true
|
push: true
|
||||||
tags: |
|
tags: |
|
||||||
|
|||||||
5
.gitignore
vendored
5
.gitignore
vendored
@@ -7,7 +7,6 @@
|
|||||||
*.DS_Store
|
*.DS_Store
|
||||||
*.tar.gz
|
*.tar.gz
|
||||||
*.db
|
*.db
|
||||||
backend
|
|
||||||
|
|
||||||
# Test binary, built with `go test -c`
|
# Test binary, built with `go test -c`
|
||||||
*.test
|
*.test
|
||||||
@@ -18,5 +17,7 @@ backend
|
|||||||
# Dependency directories (remove the comment below to include it)
|
# Dependency directories (remove the comment below to include it)
|
||||||
# vendor/
|
# vendor/
|
||||||
bin
|
bin
|
||||||
assets/*.*
|
assets/*.xml
|
||||||
|
assets/*.txt
|
||||||
db.sqlite
|
db.sqlite
|
||||||
|
cmd/*/backend
|
||||||
4
Makefile
4
Makefile
@@ -22,10 +22,6 @@ backup:
|
|||||||
dist:
|
dist:
|
||||||
@scripts/dist_tar.sh $(tag)
|
@scripts/dist_tar.sh $(tag)
|
||||||
|
|
||||||
# clean
|
|
||||||
clean:
|
|
||||||
@rm -rf bin && rm -f *.tar.gz && rm -f backend
|
|
||||||
|
|
||||||
# protoc
|
# protoc
|
||||||
protoc:
|
protoc:
|
||||||
@cd pkg/proto && make protoc
|
@cd pkg/proto && make protoc
|
||||||
|
|||||||
67
cmd/backup/config/config.go
Normal file
67
cmd/backup/config/config.go
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/eiblog/eiblog/pkg/config"
|
||||||
|
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
|
"gopkg.in/yaml.v3"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Config config
|
||||||
|
type Config struct {
|
||||||
|
config.APIMode
|
||||||
|
|
||||||
|
Database config.Database // 数据库配置
|
||||||
|
BackupTo string // 备份到, default: qiniu
|
||||||
|
Interval string // 备份周期, default: 7d
|
||||||
|
Validity int // 备份保留时间, default: 60
|
||||||
|
Qiniu config.Qiniu // 七牛OSS配置
|
||||||
|
}
|
||||||
|
|
||||||
|
// Conf 配置
|
||||||
|
var Conf Config
|
||||||
|
|
||||||
|
// load config file
|
||||||
|
func init() {
|
||||||
|
// run mode
|
||||||
|
mode := config.RunMode(os.Getenv("RUN_MODE"))
|
||||||
|
if !mode.IsRunMode() {
|
||||||
|
panic("config: unsupported env RUN_MODE" + mode)
|
||||||
|
}
|
||||||
|
logrus.Infof("Run mode:%s", mode)
|
||||||
|
|
||||||
|
// 加载配置文件
|
||||||
|
dir, err := config.WalkWorkDir()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
path := filepath.Join(dir, "etc", "app.yml")
|
||||||
|
data, err := os.ReadFile(path)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
err = yaml.Unmarshal(data, &Conf)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
Conf.RunMode = mode
|
||||||
|
|
||||||
|
// read env
|
||||||
|
readDatabaseEnv()
|
||||||
|
}
|
||||||
|
|
||||||
|
func readDatabaseEnv() {
|
||||||
|
key := strings.ToUpper(Conf.Name) + "_DB_DRIVER"
|
||||||
|
if d := os.Getenv(key); d != "" {
|
||||||
|
Conf.Database.Driver = d
|
||||||
|
}
|
||||||
|
key = strings.ToUpper(Conf.Name) + "_DB_SOURCE"
|
||||||
|
if s := os.Getenv(key); s != "" {
|
||||||
|
Conf.Database.Source = s
|
||||||
|
}
|
||||||
|
}
|
||||||
60
cmd/backup/docs/docs.go
Normal file
60
cmd/backup/docs/docs.go
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
// Package docs Code generated by swaggo/swag. DO NOT EDIT
|
||||||
|
package docs
|
||||||
|
|
||||||
|
import "github.com/swaggo/swag"
|
||||||
|
|
||||||
|
const docTemplate = `{
|
||||||
|
"schemes": {{ marshal .Schemes }},
|
||||||
|
"swagger": "2.0",
|
||||||
|
"info": {
|
||||||
|
"description": "{{escape .Description}}",
|
||||||
|
"title": "{{.Title}}",
|
||||||
|
"contact": {},
|
||||||
|
"version": "{{.Version}}"
|
||||||
|
},
|
||||||
|
"host": "{{.Host}}",
|
||||||
|
"basePath": "{{.BasePath}}",
|
||||||
|
"paths": {
|
||||||
|
"/ping": {
|
||||||
|
"get": {
|
||||||
|
"description": "ping",
|
||||||
|
"consumes": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"ping"
|
||||||
|
],
|
||||||
|
"summary": "ping",
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "it's ok",
|
||||||
|
"schema": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}`
|
||||||
|
|
||||||
|
// SwaggerInfo holds exported Swagger Info so clients can modify it
|
||||||
|
var SwaggerInfo = &swag.Spec{
|
||||||
|
Version: "1.0",
|
||||||
|
Host: "",
|
||||||
|
BasePath: "",
|
||||||
|
Schemes: []string{},
|
||||||
|
Title: "backup API",
|
||||||
|
Description: "This is a backup server.",
|
||||||
|
InfoInstanceName: "swagger",
|
||||||
|
SwaggerTemplate: docTemplate,
|
||||||
|
LeftDelim: "{{",
|
||||||
|
RightDelim: "}}",
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
swag.Register(SwaggerInfo.InstanceName(), SwaggerInfo)
|
||||||
|
}
|
||||||
34
cmd/backup/docs/swagger.json
Normal file
34
cmd/backup/docs/swagger.json
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
{
|
||||||
|
"swagger": "2.0",
|
||||||
|
"info": {
|
||||||
|
"description": "This is a backup server.",
|
||||||
|
"title": "backup API",
|
||||||
|
"contact": {},
|
||||||
|
"version": "1.0"
|
||||||
|
},
|
||||||
|
"paths": {
|
||||||
|
"/ping": {
|
||||||
|
"get": {
|
||||||
|
"description": "ping",
|
||||||
|
"consumes": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"ping"
|
||||||
|
],
|
||||||
|
"summary": "ping",
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "it's ok",
|
||||||
|
"schema": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
22
cmd/backup/docs/swagger.yaml
Normal file
22
cmd/backup/docs/swagger.yaml
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
info:
|
||||||
|
contact: {}
|
||||||
|
description: This is a backup server.
|
||||||
|
title: backup API
|
||||||
|
version: "1.0"
|
||||||
|
paths:
|
||||||
|
/ping:
|
||||||
|
get:
|
||||||
|
consumes:
|
||||||
|
- application/json
|
||||||
|
description: ping
|
||||||
|
produces:
|
||||||
|
- application/json
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: it's ok
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
summary: ping
|
||||||
|
tags:
|
||||||
|
- ping
|
||||||
|
swagger: "2.0"
|
||||||
14
cmd/backup/etc/app.yml
Normal file
14
cmd/backup/etc/app.yml
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
apimode:
|
||||||
|
name: cmd-backup
|
||||||
|
listen: 0.0.0.0:9000
|
||||||
|
database: # 数据库配置
|
||||||
|
driver: sqlite
|
||||||
|
source: ./db.sqlite
|
||||||
|
backupto: qiniu # 备份到, default: qiniu
|
||||||
|
interval: 7d # 备份周期, default: 7d
|
||||||
|
validity: 60 # 备份保留时间, default: 60
|
||||||
|
qiniu: # 七牛OSS
|
||||||
|
bucket: eiblog
|
||||||
|
domain: st.deepzz.com
|
||||||
|
accesskey: MB6AXl_Sj_mmFsL-Lt59Dml2Vmy2o8XMmiCbbSeC
|
||||||
|
secretkey: BIrMy0fsZ0_SHNceNXk3eDuo7WmVYzj2-zrmd5Tf
|
||||||
17
cmd/backup/handler/internal/internal.go
Normal file
17
cmd/backup/handler/internal/internal.go
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
package internal
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/eiblog/eiblog/cmd/backup/config"
|
||||||
|
"github.com/eiblog/eiblog/pkg/third/qiniu"
|
||||||
|
)
|
||||||
|
|
||||||
|
// QiniuClient 七牛客户端
|
||||||
|
var QiniuClient *qiniu.QiniuClient
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
var err error
|
||||||
|
QiniuClient, err = qiniu.NewQiniuClient(config.Conf.Qiniu)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
// Package ping provides ...
|
|
||||||
package ping
|
package ping
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -13,6 +12,13 @@ func RegisterRoutes(group gin.IRoutes) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// handlePing ping
|
// handlePing ping
|
||||||
|
// @Summary ping
|
||||||
|
// @Description ping
|
||||||
|
// @Tags ping
|
||||||
|
// @Accept json
|
||||||
|
// @Produce json
|
||||||
|
// @Success 200 {string} string "it's ok"
|
||||||
|
// @Router /ping [get]
|
||||||
func handlePing(c *gin.Context) {
|
func handlePing(c *gin.Context) {
|
||||||
c.String(http.StatusOK, "it's ok")
|
c.String(http.StatusOK, "it's ok")
|
||||||
}
|
}
|
||||||
@@ -1,8 +1,7 @@
|
|||||||
// Package swag provides ...
|
|
||||||
package swag
|
package swag
|
||||||
|
|
||||||
import (
|
import (
|
||||||
_ "github.com/eiblog/eiblog/pkg/core/eiblog/docs" // docs
|
_ "github.com/eiblog/eiblog/cmd/eiblog/docs" // docs
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
swaggerFiles "github.com/swaggo/files"
|
swaggerFiles "github.com/swaggo/files"
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
// Package qiniu provides ...
|
|
||||||
package qiniu
|
package qiniu
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -11,16 +10,17 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/eiblog/eiblog/pkg/cache/store"
|
"github.com/eiblog/eiblog/cmd/backup/config"
|
||||||
"github.com/eiblog/eiblog/pkg/config"
|
"github.com/eiblog/eiblog/cmd/backup/handler/internal"
|
||||||
"github.com/eiblog/eiblog/pkg/internal"
|
"github.com/eiblog/eiblog/pkg/connector/db"
|
||||||
|
"github.com/eiblog/eiblog/pkg/third/qiniu"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Storage qiniu storage
|
// BackupRestorer qiniu backup restorer
|
||||||
type Storage struct{}
|
type BackupRestorer struct{}
|
||||||
|
|
||||||
// BackupData implements timer.Storage
|
// Backup implements timer.BackupRestorer
|
||||||
func (s Storage) BackupData(now time.Time) error {
|
func (s BackupRestorer) Backup(now time.Time) error {
|
||||||
switch config.Conf.Database.Driver {
|
switch config.Conf.Database.Driver {
|
||||||
case "mongodb":
|
case "mongodb":
|
||||||
return backupFromMongoDB(now)
|
return backupFromMongoDB(now)
|
||||||
@@ -30,8 +30,8 @@ func (s Storage) BackupData(now time.Time) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// RestoreData implements timer.Storage
|
// Restore implements timer.BackupRestorer
|
||||||
func (s Storage) RestoreData() error {
|
func (s BackupRestorer) Restore() error {
|
||||||
switch config.Conf.Database.Driver {
|
switch config.Conf.Database.Driver {
|
||||||
case "mongodb":
|
case "mongodb":
|
||||||
return restoreToMongoDB()
|
return restoreToMongoDB()
|
||||||
@@ -74,37 +74,31 @@ func backupFromMongoDB(now time.Time) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
uploadParams := internal.UploadParams{
|
uploadParams := qiniu.UploadParams{
|
||||||
Name: filepath.Join("blog", name), // blog/eiblog-xx.tar.gz
|
Name: filepath.Join("blog", name), // blog/eiblog-xx.tar.gz
|
||||||
Size: s.Size(),
|
Size: s.Size(),
|
||||||
Data: f,
|
Data: f,
|
||||||
NoCompletePath: true,
|
NoCompletePath: true,
|
||||||
|
|
||||||
Conf: config.Conf.BackupApp.Qiniu,
|
|
||||||
}
|
}
|
||||||
_, err = internal.QiniuUpload(uploadParams)
|
_, err = internal.QiniuClient.Upload(uploadParams)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// after days delete
|
// after days delete
|
||||||
deleteParams := internal.DeleteParams{
|
deleteParams := qiniu.DeleteParams{
|
||||||
Name: filepath.Join("blog", name), // blog/eiblog-xx.tar.gz
|
Name: filepath.Join("blog", name), // blog/eiblog-xx.tar.gz
|
||||||
Days: config.Conf.BackupApp.Validity,
|
Days: config.Conf.Validity,
|
||||||
NoCompletePath: true,
|
NoCompletePath: true,
|
||||||
|
|
||||||
Conf: config.Conf.BackupApp.Qiniu,
|
|
||||||
}
|
}
|
||||||
return internal.QiniuDelete(deleteParams)
|
return internal.QiniuClient.Delete(deleteParams)
|
||||||
}
|
}
|
||||||
|
|
||||||
func restoreToMongoDB() error {
|
func restoreToMongoDB() error {
|
||||||
// backup file
|
// backup file
|
||||||
params := internal.ContentParams{
|
params := qiniu.ContentParams{
|
||||||
Prefix: "blog/",
|
Prefix: "blog/",
|
||||||
|
|
||||||
Conf: config.Conf.BackupApp.Qiniu,
|
|
||||||
}
|
}
|
||||||
raw, err := internal.QiniuContent(params)
|
raw, err := internal.QiniuClient.Content(params)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -118,17 +112,16 @@ func restoreToMongoDB() error {
|
|||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Minute*20)
|
ctx, cancel := context.WithTimeout(context.Background(), time.Minute*20)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
// drop database
|
// drop database
|
||||||
store, err := store.NewStore(config.Conf.Database.Driver,
|
mdb, err := db.NewMDB(config.Conf.Database)
|
||||||
config.Conf.Database.Source)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
err = store.DropDatabase(ctx)
|
err = mdb.Drop(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// unarchive
|
// unarchive
|
||||||
arg := fmt.Sprintf("tar xzf /tmp/eiblog.tar.gz -C /tmp")
|
arg := "tar xzf /tmp/eiblog.tar.gz -C /tmp"
|
||||||
cmd := exec.CommandContext(ctx, "sh", "-c", arg)
|
cmd := exec.CommandContext(ctx, "sh", "-c", arg)
|
||||||
err = cmd.Run()
|
err = cmd.Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
// Package timer provides ...
|
|
||||||
package timer
|
package timer
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -6,41 +5,48 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/eiblog/eiblog/pkg/config"
|
"github.com/eiblog/eiblog/cmd/backup/config"
|
||||||
"github.com/eiblog/eiblog/pkg/core/backup/timer/qiniu"
|
"github.com/eiblog/eiblog/cmd/backup/handler/timer/qiniu"
|
||||||
|
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// BackupRestorer 备份恢复器
|
||||||
|
type BackupRestorer interface {
|
||||||
|
Backup(now time.Time) error
|
||||||
|
Restore() error
|
||||||
|
}
|
||||||
|
|
||||||
// Start to backup with ticker
|
// Start to backup with ticker
|
||||||
func Start(restore bool) (err error) {
|
func Start(restore bool) (err error) {
|
||||||
var storage Storage
|
var storage BackupRestorer
|
||||||
|
|
||||||
// backup instance
|
// backup instance
|
||||||
switch config.Conf.BackupApp.BackupTo {
|
switch config.Conf.BackupTo {
|
||||||
case "qiniu":
|
case "qiniu":
|
||||||
storage = qiniu.Storage{}
|
storage = qiniu.BackupRestorer{}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return errors.New("timer: unknown backup to driver: " +
|
return errors.New("timer: unknown backup to driver: " +
|
||||||
config.Conf.BackupApp.BackupTo)
|
config.Conf.BackupTo)
|
||||||
}
|
}
|
||||||
if restore {
|
if restore {
|
||||||
err = storage.RestoreData()
|
err = storage.Restore()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
logrus.Info("timer: RestoreData success")
|
logrus.Info("timer: Restore success")
|
||||||
}
|
}
|
||||||
// parse duration
|
// parse duration
|
||||||
interval, err := ParseDuration(config.Conf.BackupApp.Interval)
|
interval, err := ParseDuration(config.Conf.Interval)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
t := time.NewTicker(interval)
|
t := time.NewTicker(interval)
|
||||||
for now := range t.C {
|
for now := range t.C {
|
||||||
err = storage.BackupData(now)
|
err = storage.Backup(now)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Error("timer: Start.BackupData: ", now.Format(time.RFC3339), err)
|
logrus.Error("timer: Start.Backup: ", now.Format(time.RFC3339), err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@@ -63,12 +69,5 @@ func ParseDuration(d string) (time.Duration, error) {
|
|||||||
}
|
}
|
||||||
return time.Duration(di) * time.Hour * 24, nil
|
return time.Duration(di) * time.Hour * 24, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0, errors.New("timer: unsupported duration:" + d)
|
return 0, errors.New("timer: unsupported duration:" + d)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Storage backup backend
|
|
||||||
type Storage interface {
|
|
||||||
BackupData(now time.Time) error
|
|
||||||
RestoreData() error
|
|
||||||
}
|
|
||||||
@@ -3,16 +3,20 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/eiblog/eiblog/pkg/config"
|
"github.com/eiblog/eiblog/cmd/backup/config"
|
||||||
"github.com/eiblog/eiblog/pkg/core/backup/ping"
|
"github.com/eiblog/eiblog/cmd/backup/handler/ping"
|
||||||
"github.com/eiblog/eiblog/pkg/core/backup/swag"
|
"github.com/eiblog/eiblog/cmd/backup/handler/swag"
|
||||||
"github.com/eiblog/eiblog/pkg/core/backup/timer"
|
"github.com/eiblog/eiblog/cmd/backup/handler/timer"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// @title backup API
|
||||||
|
// @version 1.0
|
||||||
|
// @description This is a backup server.
|
||||||
|
|
||||||
var restore bool
|
var restore bool
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@@ -20,15 +24,15 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
fmt.Println("Hi, it's App " + config.Conf.BackupApp.Name)
|
logrus.Info("Hi, it's App " + config.Conf.Name)
|
||||||
flag.Parse()
|
|
||||||
|
|
||||||
|
flag.Parse()
|
||||||
endRun := make(chan error, 1)
|
endRun := make(chan error, 1)
|
||||||
|
|
||||||
runCommand(restore, endRun)
|
runCommand(restore, endRun)
|
||||||
|
|
||||||
runHTTPServer(endRun)
|
runHTTPServer(endRun)
|
||||||
fmt.Println(<-endRun)
|
logrus.Fatal(<-endRun)
|
||||||
}
|
}
|
||||||
|
|
||||||
func runCommand(restore bool, endRun chan error) {
|
func runCommand(restore bool, endRun chan error) {
|
||||||
@@ -38,11 +42,7 @@ func runCommand(restore bool, endRun chan error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func runHTTPServer(endRun chan error) {
|
func runHTTPServer(endRun chan error) {
|
||||||
if !config.Conf.BackupApp.EnableHTTP {
|
if config.Conf.RunMode.IsReleaseMode() {
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if config.Conf.RunMode == config.ModeProd {
|
|
||||||
gin.SetMode(gin.ReleaseMode)
|
gin.SetMode(gin.ReleaseMode)
|
||||||
}
|
}
|
||||||
e := gin.Default()
|
e := gin.Default()
|
||||||
@@ -54,9 +54,8 @@ func runHTTPServer(endRun chan error) {
|
|||||||
ping.RegisterRoutes(e)
|
ping.RegisterRoutes(e)
|
||||||
|
|
||||||
// start
|
// start
|
||||||
address := fmt.Sprintf(":%d", config.Conf.BackupApp.HTTPPort)
|
|
||||||
go func() {
|
go func() {
|
||||||
endRun <- e.Run(address)
|
endRun <- e.Run(config.Conf.Listen)
|
||||||
}()
|
}()
|
||||||
fmt.Println("HTTP server running on: " + address)
|
logrus.Info("HTTP server running on: " + config.Conf.Listen)
|
||||||
}
|
}
|
||||||
|
|||||||
82
cmd/eiblog/config/config.go
Normal file
82
cmd/eiblog/config/config.go
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/eiblog/eiblog/pkg/config"
|
||||||
|
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
|
"gopkg.in/yaml.v3"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// Conf 配置
|
||||||
|
Conf Config
|
||||||
|
// WorkDir 工作目录
|
||||||
|
WorkDir string
|
||||||
|
)
|
||||||
|
|
||||||
|
// Config config
|
||||||
|
type Config struct {
|
||||||
|
config.APIMode
|
||||||
|
// 静态资源版本, 每次更改了 js/css 都需要提高该值
|
||||||
|
StaticVersion int
|
||||||
|
// 数据库配置
|
||||||
|
Database config.Database
|
||||||
|
// 热词, 手动指定, 用于搜索
|
||||||
|
HotWords []string
|
||||||
|
// Elasticsearch 配置
|
||||||
|
ESHost string
|
||||||
|
|
||||||
|
General config.General
|
||||||
|
Disqus config.Disqus
|
||||||
|
Google config.Google
|
||||||
|
Qiniu config.Qiniu
|
||||||
|
Twitter config.Twitter
|
||||||
|
FeedRPC config.FeedRPC
|
||||||
|
Account config.Account
|
||||||
|
}
|
||||||
|
|
||||||
|
// init 初始化配置
|
||||||
|
func init() {
|
||||||
|
// run mode
|
||||||
|
mode := config.RunMode(os.Getenv("RUN_MODE"))
|
||||||
|
if !mode.IsRunMode() {
|
||||||
|
panic("config: unsupported env RUN_MODE" + mode)
|
||||||
|
}
|
||||||
|
logrus.Infof("Run mode:%s", mode)
|
||||||
|
|
||||||
|
// 加载配置文件
|
||||||
|
var err error
|
||||||
|
WorkDir, err = config.WalkWorkDir()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
path := filepath.Join(WorkDir, "etc", "app.yml")
|
||||||
|
data, err := os.ReadFile(path)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
err = yaml.Unmarshal(data, &Conf)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
Conf.RunMode = mode
|
||||||
|
|
||||||
|
// 读取环境变量配置
|
||||||
|
readDatabaseEnv()
|
||||||
|
}
|
||||||
|
|
||||||
|
func readDatabaseEnv() {
|
||||||
|
key := strings.ToUpper(Conf.Name) + "_DB_DRIVER"
|
||||||
|
if d := os.Getenv(key); d != "" {
|
||||||
|
Conf.Database.Driver = d
|
||||||
|
}
|
||||||
|
key = strings.ToUpper(Conf.Name) + "_DB_SOURCE"
|
||||||
|
if s := os.Getenv(key); s != "" {
|
||||||
|
Conf.Database.Source = s
|
||||||
|
}
|
||||||
|
}
|
||||||
36
cmd/eiblog/docs/docs.go
Normal file
36
cmd/eiblog/docs/docs.go
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
// Package docs Code generated by swaggo/swag. DO NOT EDIT
|
||||||
|
package docs
|
||||||
|
|
||||||
|
import "github.com/swaggo/swag"
|
||||||
|
|
||||||
|
const docTemplate = `{
|
||||||
|
"schemes": {{ marshal .Schemes }},
|
||||||
|
"swagger": "2.0",
|
||||||
|
"info": {
|
||||||
|
"description": "{{escape .Description}}",
|
||||||
|
"title": "{{.Title}}",
|
||||||
|
"contact": {},
|
||||||
|
"version": "{{.Version}}"
|
||||||
|
},
|
||||||
|
"host": "{{.Host}}",
|
||||||
|
"basePath": "{{.BasePath}}",
|
||||||
|
"paths": {}
|
||||||
|
}`
|
||||||
|
|
||||||
|
// SwaggerInfo holds exported Swagger Info so clients can modify it
|
||||||
|
var SwaggerInfo = &swag.Spec{
|
||||||
|
Version: "",
|
||||||
|
Host: "",
|
||||||
|
BasePath: "",
|
||||||
|
Schemes: []string{},
|
||||||
|
Title: "",
|
||||||
|
Description: "",
|
||||||
|
InfoInstanceName: "swagger",
|
||||||
|
SwaggerTemplate: docTemplate,
|
||||||
|
LeftDelim: "{{",
|
||||||
|
RightDelim: "}}",
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
swag.Register(SwaggerInfo.InstanceName(), SwaggerInfo)
|
||||||
|
}
|
||||||
7
cmd/eiblog/docs/swagger.json
Normal file
7
cmd/eiblog/docs/swagger.json
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"swagger": "2.0",
|
||||||
|
"info": {
|
||||||
|
"contact": {}
|
||||||
|
},
|
||||||
|
"paths": {}
|
||||||
|
}
|
||||||
4
cmd/eiblog/docs/swagger.yaml
Normal file
4
cmd/eiblog/docs/swagger.yaml
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
info:
|
||||||
|
contact: {}
|
||||||
|
paths: {}
|
||||||
|
swagger: "2.0"
|
||||||
49
cmd/eiblog/etc/app.yml
Normal file
49
cmd/eiblog/etc/app.yml
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
apimode:
|
||||||
|
name: cmd-eiblog
|
||||||
|
listen: 0.0.0.0:9000
|
||||||
|
host: example.com
|
||||||
|
database: # 数据库配置
|
||||||
|
driver: sqlite
|
||||||
|
source: ./db.sqlite
|
||||||
|
hotwords: # 热搜词
|
||||||
|
- docker
|
||||||
|
- mongodb
|
||||||
|
- curl
|
||||||
|
- dns
|
||||||
|
staticversion: 1
|
||||||
|
eshost: # http://elasticsearch:9200
|
||||||
|
general: # 常规配置
|
||||||
|
pagenum: 10 # 首页展示文章数量
|
||||||
|
pagesize: 20 # 管理界面
|
||||||
|
descprefix: "Desc:" # 文章描述前缀
|
||||||
|
identifier: <!--more--> # 截取预览标识
|
||||||
|
length: 400 # 自动截取预览, 字符数
|
||||||
|
timezone: Asia/Shanghai # 时区
|
||||||
|
disqus: # 评论相关
|
||||||
|
shortname: xxxxxx
|
||||||
|
publickey: wdSgxRm9rdGAlLKFcFdToBe3GT4SibmV7Y8EjJQ0r4GWXeKtxpopMAeIeoI2dTEg
|
||||||
|
accesstoken: 50023908f39f4607957e909b495326af
|
||||||
|
google: # 谷歌分析
|
||||||
|
url: https://www.google-analytics.com/g/collect
|
||||||
|
tid: G-xxxxxxxxxx
|
||||||
|
v: "2"
|
||||||
|
adsense: <script async src="https://pagead2.googlesyndication.com/xxx" crossorigin="anonymous"></script>
|
||||||
|
qiniu: # 七牛OSS
|
||||||
|
bucket: eiblog
|
||||||
|
domain: st.deepzz.com
|
||||||
|
accesskey: MB6AXl_Sj_mmFsL-Lt59Dml2Vmy2o8XMmiCbbSeC
|
||||||
|
secretkey: BIrMy0fsZ0_SHNceNXk3eDuo7WmVYzj2-zrmd5Tf
|
||||||
|
twitter: # twitter card
|
||||||
|
card: summary
|
||||||
|
site: deepzz02
|
||||||
|
image: st.deepzz.com/static/img/avatar.jpg
|
||||||
|
address: twitter.com/deepzz02
|
||||||
|
feedrpc: # rss ping
|
||||||
|
feedrurl: https://deepzz.superfeedr.com/
|
||||||
|
pingrpc:
|
||||||
|
- http://ping.baidu.com/ping/RPC2
|
||||||
|
- http://rpc.pingomatic.com/
|
||||||
|
# 数据初始化操作,可到博客后台修改
|
||||||
|
account:
|
||||||
|
username: deepzz # *后台登录用户名
|
||||||
|
password: deepzz # *登录明文密码
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
// Package admin provides ...
|
|
||||||
package admin
|
package admin
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -10,11 +9,10 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/eiblog/eiblog/pkg/cache"
|
"github.com/eiblog/eiblog/cmd/eiblog/handler/internal"
|
||||||
"github.com/eiblog/eiblog/pkg/config"
|
"github.com/eiblog/eiblog/pkg/middleware"
|
||||||
"github.com/eiblog/eiblog/pkg/core/eiblog"
|
|
||||||
"github.com/eiblog/eiblog/pkg/internal"
|
|
||||||
"github.com/eiblog/eiblog/pkg/model"
|
"github.com/eiblog/eiblog/pkg/model"
|
||||||
|
"github.com/eiblog/eiblog/pkg/third/qiniu"
|
||||||
"github.com/eiblog/eiblog/tools"
|
"github.com/eiblog/eiblog/tools"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
@@ -60,20 +58,20 @@ func handleAcctLogin(c *gin.Context) {
|
|||||||
c.Redirect(http.StatusFound, "/admin/login")
|
c.Redirect(http.StatusFound, "/admin/login")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if cache.Ei.Account.Username != user ||
|
if internal.Ei.Account.Username != user ||
|
||||||
cache.Ei.Account.Password != tools.EncryptPasswd(user, pwd) {
|
internal.Ei.Account.Password != tools.EncryptPasswd(user, pwd) {
|
||||||
logrus.Warnf("账号或密码错误 %s, %s", user, pwd)
|
logrus.Warnf("账号或密码错误 %s, %s", user, pwd)
|
||||||
c.Redirect(http.StatusFound, "/admin/login")
|
c.Redirect(http.StatusFound, "/admin/login")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// 登录成功
|
// 登录成功
|
||||||
eiblog.SetLogin(c, user)
|
middleware.SetLogin(c, user)
|
||||||
|
|
||||||
cache.Ei.Account.LoginIP = c.ClientIP()
|
internal.Ei.Account.LoginIP = c.ClientIP()
|
||||||
cache.Ei.Account.LoginAt = time.Now()
|
internal.Ei.Account.LoginAt = time.Now()
|
||||||
cache.Ei.UpdateAccount(context.Background(), user, map[string]interface{}{
|
internal.Ei.UpdateAccount(context.Background(), user, map[string]interface{}{
|
||||||
"login_ip": cache.Ei.Account.LoginIP,
|
"login_ip": internal.Ei.Account.LoginIP,
|
||||||
"login_at": cache.Ei.Account.LoginAt,
|
"login_at": internal.Ei.Account.LoginAt,
|
||||||
})
|
})
|
||||||
c.Redirect(http.StatusFound, "/admin/profile")
|
c.Redirect(http.StatusFound, "/admin/profile")
|
||||||
}
|
}
|
||||||
@@ -91,7 +89,7 @@ func handleAPIBlogger(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err := cache.Ei.UpdateBlogger(context.Background(), map[string]interface{}{
|
err := internal.Ei.UpdateBlogger(context.Background(), map[string]interface{}{
|
||||||
"blog_name": bn,
|
"blog_name": bn,
|
||||||
"b_title": bt,
|
"b_title": bt,
|
||||||
"bei_an": ba,
|
"bei_an": ba,
|
||||||
@@ -104,14 +102,14 @@ func handleAPIBlogger(c *gin.Context) {
|
|||||||
responseNotice(c, NoticeNotice, err.Error(), "")
|
responseNotice(c, NoticeNotice, err.Error(), "")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
cache.Ei.Blogger.BlogName = bn
|
internal.Ei.Blogger.BlogName = bn
|
||||||
cache.Ei.Blogger.BTitle = bt
|
internal.Ei.Blogger.BTitle = bt
|
||||||
cache.Ei.Blogger.BeiAn = ba
|
internal.Ei.Blogger.BeiAn = ba
|
||||||
cache.Ei.Blogger.SubTitle = st
|
internal.Ei.Blogger.SubTitle = st
|
||||||
cache.Ei.Blogger.SeriesSay = ss
|
internal.Ei.Blogger.SeriesSay = ss
|
||||||
cache.Ei.Blogger.ArchivesSay = as
|
internal.Ei.Blogger.ArchivesSay = as
|
||||||
cache.PagesCh <- cache.PageSeries
|
internal.PagesCh <- internal.PageSeries
|
||||||
cache.PagesCh <- cache.PageArchive
|
internal.PagesCh <- internal.PageArchive
|
||||||
responseNotice(c, NoticeSuccess, "更新成功", "")
|
responseNotice(c, NoticeSuccess, "更新成功", "")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -126,7 +124,7 @@ func handleAPIAccount(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err := cache.Ei.UpdateAccount(context.Background(), cache.Ei.Account.Username,
|
err := internal.Ei.UpdateAccount(context.Background(), internal.Ei.Account.Username,
|
||||||
map[string]interface{}{
|
map[string]interface{}{
|
||||||
"email": e,
|
"email": e,
|
||||||
"phone_n": pn,
|
"phone_n": pn,
|
||||||
@@ -137,9 +135,9 @@ func handleAPIAccount(c *gin.Context) {
|
|||||||
responseNotice(c, NoticeNotice, err.Error(), "")
|
responseNotice(c, NoticeNotice, err.Error(), "")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
cache.Ei.Account.Email = e
|
internal.Ei.Account.Email = e
|
||||||
cache.Ei.Account.PhoneN = pn
|
internal.Ei.Account.PhoneN = pn
|
||||||
cache.Ei.Account.Address = ad
|
internal.Ei.Account.Address = ad
|
||||||
responseNotice(c, NoticeSuccess, "更新成功", "")
|
responseNotice(c, NoticeSuccess, "更新成功", "")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -156,13 +154,13 @@ func handleAPIPassword(c *gin.Context) {
|
|||||||
responseNotice(c, NoticeNotice, "密码格式错误", "")
|
responseNotice(c, NoticeNotice, "密码格式错误", "")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if cache.Ei.Account.Password != tools.EncryptPasswd(cache.Ei.Account.Username, od) {
|
if internal.Ei.Account.Password != tools.EncryptPasswd(internal.Ei.Account.Username, od) {
|
||||||
responseNotice(c, NoticeNotice, "原始密码不正确", "")
|
responseNotice(c, NoticeNotice, "原始密码不正确", "")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
newPwd := tools.EncryptPasswd(cache.Ei.Account.Username, nw)
|
newPwd := tools.EncryptPasswd(internal.Ei.Account.Username, nw)
|
||||||
|
|
||||||
err := cache.Ei.UpdateAccount(context.Background(), cache.Ei.Account.Username,
|
err := internal.Ei.UpdateAccount(context.Background(), internal.Ei.Account.Username,
|
||||||
map[string]interface{}{
|
map[string]interface{}{
|
||||||
"password": newPwd,
|
"password": newPwd,
|
||||||
})
|
})
|
||||||
@@ -171,7 +169,7 @@ func handleAPIPassword(c *gin.Context) {
|
|||||||
responseNotice(c, NoticeNotice, err.Error(), "")
|
responseNotice(c, NoticeNotice, err.Error(), "")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
cache.Ei.Account.Password = newPwd
|
internal.Ei.Account.Password = newPwd
|
||||||
responseNotice(c, NoticeSuccess, "更新成功", "")
|
responseNotice(c, NoticeSuccess, "更新成功", "")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -183,7 +181,7 @@ func handleDraftDelete(c *gin.Context) {
|
|||||||
responseNotice(c, NoticeNotice, "参数错误", "")
|
responseNotice(c, NoticeNotice, "参数错误", "")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
err = cache.Ei.RemoveArticle(context.Background(), id)
|
err = internal.Ei.RemoveArticle(context.Background(), id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Error("handleDraftDelete.RemoveArticle: ", err)
|
logrus.Error("handleDraftDelete.RemoveArticle: ", err)
|
||||||
responseNotice(c, NoticeNotice, "删除失败", "")
|
responseNotice(c, NoticeNotice, "删除失败", "")
|
||||||
@@ -198,11 +196,11 @@ func handleAPIPostDelete(c *gin.Context) {
|
|||||||
var ids []int
|
var ids []int
|
||||||
for _, v := range c.PostFormArray("cid[]") {
|
for _, v := range c.PostFormArray("cid[]") {
|
||||||
id, err := strconv.Atoi(v)
|
id, err := strconv.Atoi(v)
|
||||||
if err != nil || id < config.Conf.EiBlogApp.General.StartID {
|
if err != nil || id < internal.ArticleStartID {
|
||||||
responseNotice(c, NoticeNotice, "参数错误", "")
|
responseNotice(c, NoticeNotice, "参数错误", "")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
err = cache.Ei.DelArticle(id)
|
err = internal.Ei.DelArticle(id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Error("handleAPIPostDelete.DelArticle: ", err)
|
logrus.Error("handleAPIPostDelete.DelArticle: ", err)
|
||||||
|
|
||||||
@@ -212,7 +210,7 @@ func handleAPIPostDelete(c *gin.Context) {
|
|||||||
ids = append(ids, id)
|
ids = append(ids, id)
|
||||||
}
|
}
|
||||||
// elasticsearch
|
// elasticsearch
|
||||||
err := internal.ElasticDelIndex(ids)
|
err := internal.ESClient.ElasticDelIndex(ids)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Error("handleAPIPostDelete.ElasticDelIndex: ", err)
|
logrus.Error("handleAPIPostDelete.ElasticDelIndex: ", err)
|
||||||
}
|
}
|
||||||
@@ -271,7 +269,7 @@ func handleAPIPostCreate(c *gin.Context) {
|
|||||||
Content: text,
|
Content: text,
|
||||||
Slug: slug,
|
Slug: slug,
|
||||||
IsDraft: do != "publish",
|
IsDraft: do != "publish",
|
||||||
Author: cache.Ei.Account.Username,
|
Author: internal.Ei.Account.Username,
|
||||||
SerieID: serieid,
|
SerieID: serieid,
|
||||||
Tags: tags,
|
Tags: tags,
|
||||||
CreatedAt: date,
|
CreatedAt: date,
|
||||||
@@ -279,7 +277,7 @@ func handleAPIPostCreate(c *gin.Context) {
|
|||||||
cid, err = strconv.Atoi(c.PostForm("cid"))
|
cid, err = strconv.Atoi(c.PostForm("cid"))
|
||||||
// 新文章
|
// 新文章
|
||||||
if err != nil || cid < 1 {
|
if err != nil || cid < 1 {
|
||||||
err = cache.Ei.AddArticle(article)
|
err = internal.Ei.AddArticle(article)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Error("handleAPIPostCreate.AddArticle: ", err)
|
logrus.Error("handleAPIPostCreate.AddArticle: ", err)
|
||||||
return
|
return
|
||||||
@@ -289,20 +287,20 @@ func handleAPIPostCreate(c *gin.Context) {
|
|||||||
|
|
||||||
if !article.IsDraft {
|
if !article.IsDraft {
|
||||||
// disqus
|
// disqus
|
||||||
internal.ThreadCreate(article, cache.Ei.Blogger.BTitle)
|
internal.DisqusClient.ThreadCreate(article, internal.Ei.Blogger.BTitle)
|
||||||
// 异步执行,快
|
// 异步执行,快
|
||||||
go func() {
|
go func() {
|
||||||
// elastic
|
// elastic
|
||||||
internal.ElasticAddIndex(article)
|
internal.ESClient.ElasticAddIndex(article)
|
||||||
// rss
|
// rss
|
||||||
internal.PingFunc(cache.Ei.Blogger.BTitle, slug)
|
internal.Pinger.PingFunc(internal.Ei.Blogger.BTitle, slug)
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// 旧文章
|
// 旧文章
|
||||||
article.ID = cid
|
article.ID = cid
|
||||||
artc, _ := cache.Ei.FindArticleByID(article.ID) // cache
|
artc, _ := internal.Ei.FindArticleByID(article.ID) // cache
|
||||||
if artc != nil {
|
if artc != nil {
|
||||||
article.IsDraft = false
|
article.IsDraft = false
|
||||||
article.Count = artc.Count
|
article.Count = artc.Count
|
||||||
@@ -312,7 +310,7 @@ func handleAPIPostCreate(c *gin.Context) {
|
|||||||
article.UpdatedAt = time.Now()
|
article.UpdatedAt = time.Now()
|
||||||
}
|
}
|
||||||
// 数据库更新
|
// 数据库更新
|
||||||
err = cache.Ei.UpdateArticle(context.Background(), article.ID, map[string]interface{}{
|
err = internal.Ei.UpdateArticle(context.Background(), article.ID, map[string]interface{}{
|
||||||
"title": article.Title,
|
"title": article.Title,
|
||||||
"content": article.Content,
|
"content": article.Content,
|
||||||
"serie_id": article.SerieID,
|
"serie_id": article.SerieID,
|
||||||
@@ -326,17 +324,17 @@ func handleAPIPostCreate(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
if !article.IsDraft {
|
if !article.IsDraft {
|
||||||
cache.Ei.RepArticle(artc, article)
|
internal.Ei.RepArticle(artc, article)
|
||||||
// disqus
|
// disqus
|
||||||
if artc == nil {
|
if artc == nil {
|
||||||
internal.ThreadCreate(article, cache.Ei.Blogger.BTitle)
|
internal.DisqusClient.ThreadCreate(article, internal.Ei.Blogger.BTitle)
|
||||||
}
|
}
|
||||||
// 异步执行,快
|
// 异步执行,快
|
||||||
go func() {
|
go func() {
|
||||||
// elastic
|
// elastic
|
||||||
internal.ElasticAddIndex(article)
|
internal.ESClient.ElasticAddIndex(article)
|
||||||
// rss
|
// rss
|
||||||
internal.PingFunc(cache.Ei.Blogger.BTitle, slug)
|
internal.Pinger.PingFunc(internal.Ei.Blogger.BTitle, slug)
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -349,7 +347,7 @@ func handleAPISerieDelete(c *gin.Context) {
|
|||||||
responseNotice(c, NoticeNotice, err.Error(), "")
|
responseNotice(c, NoticeNotice, err.Error(), "")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
err = cache.Ei.DelSerie(id)
|
err = internal.Ei.DelSerie(id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
responseNotice(c, NoticeNotice, err.Error(), "")
|
responseNotice(c, NoticeNotice, err.Error(), "")
|
||||||
return
|
return
|
||||||
@@ -376,7 +374,7 @@ func handleAPISerieCreate(c *gin.Context) {
|
|||||||
mid, err := strconv.Atoi(c.PostForm("mid"))
|
mid, err := strconv.Atoi(c.PostForm("mid"))
|
||||||
if err == nil && mid > 0 {
|
if err == nil && mid > 0 {
|
||||||
var serie *model.Serie
|
var serie *model.Serie
|
||||||
for _, v := range cache.Ei.Series {
|
for _, v := range internal.Ei.Series {
|
||||||
if v.ID == mid {
|
if v.ID == mid {
|
||||||
serie = v
|
serie = v
|
||||||
break
|
break
|
||||||
@@ -386,7 +384,7 @@ func handleAPISerieCreate(c *gin.Context) {
|
|||||||
responseNotice(c, NoticeNotice, "专题不存在", "")
|
responseNotice(c, NoticeNotice, "专题不存在", "")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
err = cache.Ei.UpdateSerie(context.Background(), mid, map[string]interface{}{
|
err = internal.Ei.UpdateSerie(context.Background(), mid, map[string]interface{}{
|
||||||
"slug": slug,
|
"slug": slug,
|
||||||
"name": name,
|
"name": name,
|
||||||
"desc": desc,
|
"desc": desc,
|
||||||
@@ -399,9 +397,9 @@ func handleAPISerieCreate(c *gin.Context) {
|
|||||||
serie.Slug = slug
|
serie.Slug = slug
|
||||||
serie.Name = name
|
serie.Name = name
|
||||||
serie.Desc = desc
|
serie.Desc = desc
|
||||||
cache.PagesCh <- cache.PageSeries
|
internal.PagesCh <- internal.PageSeries
|
||||||
} else {
|
} else {
|
||||||
err = cache.Ei.AddSerie(&model.Serie{
|
err = internal.Ei.AddSerie(&model.Serie{
|
||||||
Slug: slug,
|
Slug: slug,
|
||||||
Name: name,
|
Name: name,
|
||||||
Desc: desc,
|
Desc: desc,
|
||||||
@@ -424,7 +422,7 @@ func handleAPITrashDelete(c *gin.Context) {
|
|||||||
responseNotice(c, NoticeNotice, "参数错误", "")
|
responseNotice(c, NoticeNotice, "参数错误", "")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
err = cache.Ei.RemoveArticle(context.Background(), id)
|
err = internal.Ei.RemoveArticle(context.Background(), id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
responseNotice(c, NoticeNotice, err.Error(), "")
|
responseNotice(c, NoticeNotice, err.Error(), "")
|
||||||
return
|
return
|
||||||
@@ -442,7 +440,7 @@ func handleAPITrashRecover(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
|
|
||||||
}
|
}
|
||||||
err = cache.Ei.UpdateArticle(context.Background(), id, map[string]interface{}{
|
err = internal.Ei.UpdateArticle(context.Background(), id, map[string]interface{}{
|
||||||
"deleted_at": time.Time{},
|
"deleted_at": time.Time{},
|
||||||
"is_draft": true,
|
"is_draft": true,
|
||||||
})
|
})
|
||||||
@@ -473,14 +471,12 @@ func handleAPIQiniuUpload(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
filename := strings.ToLower(header.Filename)
|
filename := strings.ToLower(header.Filename)
|
||||||
|
|
||||||
params := internal.UploadParams{
|
params := qiniu.UploadParams{
|
||||||
Name: filename,
|
Name: filename,
|
||||||
Size: s.Size(),
|
Size: s.Size(),
|
||||||
Data: file,
|
Data: file,
|
||||||
|
|
||||||
Conf: config.Conf.EiBlogApp.Qiniu,
|
|
||||||
}
|
}
|
||||||
url, err := internal.QiniuUpload(params)
|
url, err := internal.QiniuClient.Upload(params)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Error("handleAPIQiniuUpload.QiniuUpload: ", err)
|
logrus.Error("handleAPIQiniuUpload.QiniuUpload: ", err)
|
||||||
c.String(http.StatusBadRequest, err.Error())
|
c.String(http.StatusBadRequest, err.Error())
|
||||||
@@ -505,12 +501,10 @@ func handleAPIQiniuDelete(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
params := internal.DeleteParams{
|
params := qiniu.DeleteParams{
|
||||||
Name: name,
|
Name: name,
|
||||||
|
|
||||||
Conf: config.Conf.EiBlogApp.Qiniu,
|
|
||||||
}
|
}
|
||||||
err := internal.QiniuDelete(params)
|
err := internal.QiniuClient.Delete(params)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Error("handleAPIQiniuDelete.QiniuDelete: ", err)
|
logrus.Error("handleAPIQiniuDelete.QiniuDelete: ", err)
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
// Package file provides ...
|
|
||||||
package file
|
package file
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
// Package file provides ...
|
|
||||||
package file
|
package file
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -7,8 +6,8 @@ import (
|
|||||||
"text/template"
|
"text/template"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/eiblog/eiblog/pkg/cache"
|
"github.com/eiblog/eiblog/cmd/eiblog/config"
|
||||||
"github.com/eiblog/eiblog/pkg/config"
|
"github.com/eiblog/eiblog/cmd/eiblog/handler/internal"
|
||||||
"github.com/eiblog/eiblog/tools"
|
"github.com/eiblog/eiblog/tools"
|
||||||
|
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
@@ -43,12 +42,12 @@ func timerFeed() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
_, _, articles := cache.Ei.PageArticleFE(1, 20)
|
_, _, articles := internal.Ei.PageArticleFE(1, 20)
|
||||||
params := map[string]interface{}{
|
params := map[string]interface{}{
|
||||||
"Title": cache.Ei.Blogger.BTitle,
|
"Title": internal.Ei.Blogger.BTitle,
|
||||||
"SubTitle": cache.Ei.Blogger.SubTitle,
|
"SubTitle": internal.Ei.Blogger.SubTitle,
|
||||||
"Host": config.Conf.EiBlogApp.Host,
|
"Host": config.Conf.Host,
|
||||||
"FeedrURL": config.Conf.EiBlogApp.FeedRPC.FeedrURL,
|
"FeedrURL": config.Conf.FeedRPC.FeedrURL,
|
||||||
"BuildDate": now.Format(time.RFC1123Z),
|
"BuildDate": now.Format(time.RFC1123Z),
|
||||||
"Articles": articles,
|
"Articles": articles,
|
||||||
}
|
}
|
||||||
@@ -75,8 +74,8 @@ func timerSitemap() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
params := map[string]interface{}{
|
params := map[string]interface{}{
|
||||||
"Articles": cache.Ei.Articles,
|
"Articles": internal.Ei.Articles,
|
||||||
"Host": config.Conf.EiBlogApp.Host,
|
"Host": config.Conf.Host,
|
||||||
}
|
}
|
||||||
f, err := os.OpenFile("assets/sitemap.xml", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666)
|
f, err := os.OpenFile("assets/sitemap.xml", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -100,9 +99,9 @@ func generateOpensearch() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
params := map[string]string{
|
params := map[string]string{
|
||||||
"BTitle": cache.Ei.Blogger.BTitle,
|
"BTitle": internal.Ei.Blogger.BTitle,
|
||||||
"SubTitle": cache.Ei.Blogger.SubTitle,
|
"SubTitle": internal.Ei.Blogger.SubTitle,
|
||||||
"Host": config.Conf.EiBlogApp.Host,
|
"Host": config.Conf.Host,
|
||||||
}
|
}
|
||||||
f, err := os.OpenFile("assets/opensearch.xml", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666)
|
f, err := os.OpenFile("assets/opensearch.xml", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -125,7 +124,7 @@ func generateRobots() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
params := map[string]string{
|
params := map[string]string{
|
||||||
"Host": config.Conf.EiBlogApp.Host,
|
"Host": config.Conf.Host,
|
||||||
}
|
}
|
||||||
f, err := os.OpenFile("assets/robots.txt", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666)
|
f, err := os.OpenFile("assets/robots.txt", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -148,7 +147,7 @@ func generateCrossdomain() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
params := map[string]string{
|
params := map[string]string{
|
||||||
"Host": config.Conf.EiBlogApp.Host,
|
"Host": config.Conf.Host,
|
||||||
}
|
}
|
||||||
f, err := os.OpenFile("assets/crossdomain.xml", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666)
|
f, err := os.OpenFile("assets/crossdomain.xml", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
// Package cache provides ...
|
// Package internal provides ...
|
||||||
package cache
|
package internal
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
@@ -11,10 +11,8 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/eiblog/eiblog/pkg/cache/render"
|
"github.com/eiblog/eiblog/cmd/eiblog/config"
|
||||||
"github.com/eiblog/eiblog/pkg/cache/store"
|
"github.com/eiblog/eiblog/cmd/eiblog/handler/internal/store"
|
||||||
"github.com/eiblog/eiblog/pkg/config"
|
|
||||||
"github.com/eiblog/eiblog/pkg/internal"
|
|
||||||
"github.com/eiblog/eiblog/pkg/model"
|
"github.com/eiblog/eiblog/pkg/model"
|
||||||
"github.com/eiblog/eiblog/tools"
|
"github.com/eiblog/eiblog/tools"
|
||||||
|
|
||||||
@@ -42,7 +40,7 @@ func init() {
|
|||||||
// init timezone
|
// init timezone
|
||||||
var err error
|
var err error
|
||||||
tools.TimeLocation, err = time.LoadLocation(
|
tools.TimeLocation, err = time.LoadLocation(
|
||||||
config.Conf.EiBlogApp.General.Timezone)
|
config.Conf.General.Timezone)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
@@ -113,7 +111,7 @@ func (c *Cache) RepArticle(oldArticle, newArticle *model.Article) {
|
|||||||
defer c.lock.Unlock()
|
defer c.lock.Unlock()
|
||||||
|
|
||||||
c.ArticlesMap[newArticle.Slug] = newArticle
|
c.ArticlesMap[newArticle.Slug] = newArticle
|
||||||
render.GenerateExcerptMarkdown(newArticle)
|
GenerateExcerptMarkdown(newArticle)
|
||||||
if newArticle.ID < ArticleStartID {
|
if newArticle.ID < ArticleStartID {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -273,7 +271,7 @@ func (c *Cache) refreshCache(article *model.Article, del bool) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
// 添加文章
|
// 添加文章
|
||||||
defer render.GenerateExcerptMarkdown(article)
|
defer GenerateExcerptMarkdown(article)
|
||||||
|
|
||||||
c.ArticlesMap[article.Slug] = article
|
c.ArticlesMap[article.Slug] = article
|
||||||
c.Articles = append([]*model.Article{article}, c.Articles...)
|
c.Articles = append([]*model.Article{article}, c.Articles...)
|
||||||
@@ -404,13 +402,12 @@ func (c *Cache) redelArticle(article *model.Article) {
|
|||||||
|
|
||||||
// loadOrInit 读取数据或初始化
|
// loadOrInit 读取数据或初始化
|
||||||
func (c *Cache) loadOrInit() error {
|
func (c *Cache) loadOrInit() error {
|
||||||
blogapp := config.Conf.EiBlogApp
|
|
||||||
// blogger
|
// blogger
|
||||||
blogger := &model.Blogger{
|
blogger := &model.Blogger{
|
||||||
BlogName: strings.Title(blogapp.Account.Username),
|
BlogName: strings.Title(config.Conf.Account.Username),
|
||||||
SubTitle: "Rome was not built in one day.",
|
SubTitle: "Rome was not built in one day.",
|
||||||
BeiAn: "蜀ICP备xxxxxxxx号-1",
|
BeiAn: "蜀ICP备xxxxxxxx号-1",
|
||||||
BTitle: fmt.Sprintf("%s's Blog", strings.Title(blogapp.Account.Username)),
|
BTitle: fmt.Sprintf("%s's Blog", strings.Title(config.Conf.Account.Username)),
|
||||||
Copyright: `本站使用「<a href="//creativecommons.org/licenses/by/4.0/">署名 4.0 国际</a>」创作共享协议,转载请注明作者及原网址。`,
|
Copyright: `本站使用「<a href="//creativecommons.org/licenses/by/4.0/">署名 4.0 国际</a>」创作共享协议,转载请注明作者及原网址。`,
|
||||||
}
|
}
|
||||||
created, err := c.LoadInsertBlogger(context.Background(), blogger)
|
created, err := c.LoadInsertBlogger(context.Background(), blogger)
|
||||||
@@ -421,7 +418,7 @@ func (c *Cache) loadOrInit() error {
|
|||||||
if created { // init articles: about blogroll
|
if created { // init articles: about blogroll
|
||||||
about := &model.Article{
|
about := &model.Article{
|
||||||
ID: 1, // 固定ID
|
ID: 1, // 固定ID
|
||||||
Author: blogapp.Account.Username,
|
Author: config.Conf.Account.Username,
|
||||||
Title: "关于",
|
Title: "关于",
|
||||||
Slug: "about",
|
Slug: "about",
|
||||||
CreatedAt: time.Time{}.AddDate(0, 0, 1),
|
CreatedAt: time.Time{}.AddDate(0, 0, 1),
|
||||||
@@ -431,10 +428,10 @@ func (c *Cache) loadOrInit() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// 推送到 disqus
|
// 推送到 disqus
|
||||||
go internal.ThreadCreate(about, blogger.BTitle)
|
go DisqusClient.ThreadCreate(about, blogger.BTitle)
|
||||||
blogroll := &model.Article{
|
blogroll := &model.Article{
|
||||||
ID: 2, // 固定ID
|
ID: 2, // 固定ID
|
||||||
Author: blogapp.Account.Username,
|
Author: config.Conf.Account.Username,
|
||||||
Title: "友情链接",
|
Title: "友情链接",
|
||||||
Slug: "blogroll",
|
Slug: "blogroll",
|
||||||
CreatedAt: time.Time{}.AddDate(0, 0, 7),
|
CreatedAt: time.Time{}.AddDate(0, 0, 7),
|
||||||
@@ -445,11 +442,11 @@ func (c *Cache) loadOrInit() error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// account
|
// account
|
||||||
pwd := tools.EncryptPasswd(blogapp.Account.Username,
|
pwd := tools.EncryptPasswd(config.Conf.Account.Username,
|
||||||
blogapp.Account.Password)
|
config.Conf.Account.Password)
|
||||||
|
|
||||||
account := &model.Account{
|
account := &model.Account{
|
||||||
Username: blogapp.Account.Username,
|
Username: config.Conf.Account.Username,
|
||||||
Password: pwd,
|
Password: pwd,
|
||||||
}
|
}
|
||||||
_, err = c.LoadInsertAccount(context.Background(), account)
|
_, err = c.LoadInsertAccount(context.Background(), account)
|
||||||
@@ -475,7 +472,7 @@ func (c *Cache) loadOrInit() error {
|
|||||||
}
|
}
|
||||||
for i, v := range articles {
|
for i, v := range articles {
|
||||||
// 渲染页面
|
// 渲染页面
|
||||||
render.GenerateExcerptMarkdown(v)
|
GenerateExcerptMarkdown(v)
|
||||||
|
|
||||||
c.ArticlesMap[v.Slug] = v
|
c.ArticlesMap[v.Slug] = v
|
||||||
// 分析文章
|
// 分析文章
|
||||||
@@ -520,7 +517,7 @@ func (c *Cache) regeneratePages() {
|
|||||||
}
|
}
|
||||||
buf.WriteString("\n")
|
buf.WriteString("\n")
|
||||||
}
|
}
|
||||||
c.PageSeries = string(render.PageRender(buf.Bytes()))
|
c.PageSeries = string(PageRender(buf.Bytes()))
|
||||||
case PageArchive:
|
case PageArchive:
|
||||||
sort.Sort(c.Archives)
|
sort.Sort(c.Archives)
|
||||||
buf := bytes.Buffer{}
|
buf := bytes.Buffer{}
|
||||||
@@ -553,7 +550,7 @@ func (c *Cache) regeneratePages() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
c.PageArchives = string(render.PageRender(buf.Bytes()))
|
c.PageArchives = string(PageRender(buf.Bytes()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -576,7 +573,7 @@ func (c *Cache) timerDisqus() {
|
|||||||
ticker := time.NewTicker(5 * time.Hour)
|
ticker := time.NewTicker(5 * time.Hour)
|
||||||
|
|
||||||
for range ticker.C {
|
for range ticker.C {
|
||||||
err := internal.PostsCount(c.ArticlesMap)
|
err := DisqusClient.PostsCount(c.ArticlesMap)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Error("cache.timerDisqus.PostsCount: ", err)
|
logrus.Error("cache.timerDisqus.PostsCount: ", err)
|
||||||
}
|
}
|
||||||
38
cmd/eiblog/handler/internal/internal.go
Normal file
38
cmd/eiblog/handler/internal/internal.go
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
package internal
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/eiblog/eiblog/cmd/eiblog/config"
|
||||||
|
"github.com/eiblog/eiblog/pkg/third/disqus"
|
||||||
|
"github.com/eiblog/eiblog/pkg/third/es"
|
||||||
|
"github.com/eiblog/eiblog/pkg/third/pinger"
|
||||||
|
"github.com/eiblog/eiblog/pkg/third/qiniu"
|
||||||
|
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
ESClient *es.ESClient
|
||||||
|
DisqusClient *disqus.DisqusClient
|
||||||
|
QiniuClient *qiniu.QiniuClient
|
||||||
|
Pinger *pinger.Pinger
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
var err error
|
||||||
|
ESClient, err = es.NewESClient(config.Conf.ESHost)
|
||||||
|
if err != nil {
|
||||||
|
logrus.Fatal("init es client: ", err)
|
||||||
|
}
|
||||||
|
DisqusClient, err = disqus.NewDisqusClient(config.Conf.Host, config.Conf.Disqus)
|
||||||
|
if err != nil {
|
||||||
|
logrus.Fatal("init disqus client: ", err)
|
||||||
|
}
|
||||||
|
QiniuClient, err = qiniu.NewQiniuClient(config.Conf.Qiniu)
|
||||||
|
if err != nil {
|
||||||
|
logrus.Fatal("init qiniu client: ", err)
|
||||||
|
}
|
||||||
|
Pinger, err = pinger.NewPinger(config.Conf.Host, config.Conf.FeedRPC)
|
||||||
|
if err != nil {
|
||||||
|
logrus.Fatal("init pinger: ", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,11 +1,10 @@
|
|||||||
// Package render provides ...
|
package internal
|
||||||
package render
|
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/eiblog/eiblog/pkg/config"
|
"github.com/eiblog/eiblog/cmd/eiblog/config"
|
||||||
"github.com/eiblog/eiblog/pkg/model"
|
"github.com/eiblog/eiblog/pkg/model"
|
||||||
"github.com/eiblog/eiblog/tools"
|
"github.com/eiblog/eiblog/tools"
|
||||||
|
|
||||||
@@ -37,7 +36,7 @@ const (
|
|||||||
|
|
||||||
var (
|
var (
|
||||||
// 渲染markdown操作和截取摘要操作
|
// 渲染markdown操作和截取摘要操作
|
||||||
regIdentifier = regexp.MustCompile(config.Conf.EiBlogApp.General.Identifier)
|
regIdentifier = regexp.MustCompile(config.Conf.General.Identifier)
|
||||||
// header
|
// header
|
||||||
regHeader = regexp.MustCompile("</nav></div>")
|
regHeader = regexp.MustCompile("</nav></div>")
|
||||||
)
|
)
|
||||||
@@ -50,11 +49,9 @@ func PageRender(md []byte) []byte {
|
|||||||
|
|
||||||
// GenerateExcerptMarkdown 生成预览和描述
|
// GenerateExcerptMarkdown 生成预览和描述
|
||||||
func GenerateExcerptMarkdown(article *model.Article) {
|
func GenerateExcerptMarkdown(article *model.Article) {
|
||||||
blogapp := config.Conf.EiBlogApp
|
if strings.HasPrefix(article.Content, config.Conf.General.DescPrefix) {
|
||||||
|
|
||||||
if strings.HasPrefix(article.Content, blogapp.General.DescPrefix) {
|
|
||||||
index := strings.Index(article.Content, "\r\n")
|
index := strings.Index(article.Content, "\r\n")
|
||||||
prefix := article.Content[len(blogapp.General.DescPrefix):index]
|
prefix := article.Content[len(config.Conf.General.DescPrefix):index]
|
||||||
|
|
||||||
article.Desc = tools.IgnoreHTMLTag(prefix)
|
article.Desc = tools.IgnoreHTMLTag(prefix)
|
||||||
article.Content = article.Content[index:]
|
article.Content = article.Content[index:]
|
||||||
@@ -77,7 +74,7 @@ func GenerateExcerptMarkdown(article *model.Article) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
uc := []rune(article.Content)
|
uc := []rune(article.Content)
|
||||||
length := blogapp.General.Length
|
length := config.Conf.General.Length
|
||||||
if len(uc) < length {
|
if len(uc) < length {
|
||||||
length = len(uc)
|
length = len(uc)
|
||||||
}
|
}
|
||||||
@@ -326,11 +326,6 @@ func (db *mongodb) LoadArticleList(ctx context.Context, search SearchArticles) (
|
|||||||
return articles, int(count), nil
|
return articles, int(count), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// DropDatabase drop eiblog database
|
|
||||||
func (db *mongodb) DropDatabase(ctx context.Context) error {
|
|
||||||
return db.Database(mongoDBName).Drop(ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
// counter counter
|
// counter counter
|
||||||
type counter struct {
|
type counter struct {
|
||||||
Name string
|
Name string
|
||||||
@@ -64,9 +64,6 @@ type Store interface {
|
|||||||
LoadArticle(ctx context.Context, id int) (*model.Article, error)
|
LoadArticle(ctx context.Context, id int) (*model.Article, error)
|
||||||
// LoadArticleList 查找文章列表
|
// LoadArticleList 查找文章列表
|
||||||
LoadArticleList(ctx context.Context, search SearchArticles) (model.SortedArticles, int, error)
|
LoadArticleList(ctx context.Context, search SearchArticles) (model.SortedArticles, int, error)
|
||||||
|
|
||||||
// 危险操作
|
|
||||||
DropDatabase(ctx context.Context) error
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Driver 存储驱动
|
// Driver 存储驱动
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
// Package page provides ...
|
|
||||||
package page
|
package page
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -10,20 +9,20 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"github.com/eiblog/eiblog/pkg/cache"
|
"github.com/eiblog/eiblog/cmd/eiblog/config"
|
||||||
"github.com/eiblog/eiblog/pkg/cache/store"
|
"github.com/eiblog/eiblog/cmd/eiblog/handler/internal"
|
||||||
"github.com/eiblog/eiblog/pkg/config"
|
"github.com/eiblog/eiblog/cmd/eiblog/handler/internal/store"
|
||||||
"github.com/eiblog/eiblog/pkg/core/eiblog"
|
"github.com/eiblog/eiblog/pkg/middleware"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
// baseBEParams 基础参数
|
// baseBEParams 基础参数
|
||||||
func baseBEParams(c *gin.Context) gin.H {
|
func baseBEParams(_ *gin.Context) gin.H {
|
||||||
return gin.H{
|
return gin.H{
|
||||||
"Author": cache.Ei.Account.Username,
|
"Author": internal.Ei.Account.Username,
|
||||||
"Qiniu": config.Conf.EiBlogApp.Qiniu,
|
"Qiniu": config.Conf.Qiniu,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -31,22 +30,22 @@ func baseBEParams(c *gin.Context) gin.H {
|
|||||||
func handleLoginPage(c *gin.Context) {
|
func handleLoginPage(c *gin.Context) {
|
||||||
logout := c.Query("logout")
|
logout := c.Query("logout")
|
||||||
if logout == "true" {
|
if logout == "true" {
|
||||||
eiblog.SetLogout(c)
|
middleware.SetLogout(c)
|
||||||
} else if eiblog.IsLogined(c) {
|
} else if middleware.IsLogined(c) {
|
||||||
c.Redirect(http.StatusFound, "/admin/profile")
|
c.Redirect(http.StatusFound, "/admin/profile")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
params := gin.H{"BTitle": cache.Ei.Blogger.BTitle}
|
params := gin.H{"BTitle": internal.Ei.Blogger.BTitle}
|
||||||
renderHTMLAdminLayout(c, "login.html", params)
|
renderHTMLAdminLayout(c, "login.html", params)
|
||||||
}
|
}
|
||||||
|
|
||||||
// handleAdminProfile 个人配置
|
// handleAdminProfile 个人配置
|
||||||
func handleAdminProfile(c *gin.Context) {
|
func handleAdminProfile(c *gin.Context) {
|
||||||
params := baseBEParams(c)
|
params := baseBEParams(c)
|
||||||
params["Title"] = "个人配置 | " + cache.Ei.Blogger.BTitle
|
params["Title"] = "个人配置 | " + internal.Ei.Blogger.BTitle
|
||||||
params["Path"] = c.Request.URL.Path
|
params["Path"] = c.Request.URL.Path
|
||||||
params["Console"] = true
|
params["Console"] = true
|
||||||
params["Ei"] = cache.Ei
|
params["Ei"] = internal.Ei
|
||||||
renderHTMLAdminLayout(c, "admin-profile", params)
|
renderHTMLAdminLayout(c, "admin-profile", params)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -61,20 +60,20 @@ func handleAdminPost(c *gin.Context) {
|
|||||||
params := baseBEParams(c)
|
params := baseBEParams(c)
|
||||||
id, err := strconv.Atoi(c.Query("cid"))
|
id, err := strconv.Atoi(c.Query("cid"))
|
||||||
if err == nil && id > 0 {
|
if err == nil && id > 0 {
|
||||||
article, _ := cache.Ei.LoadArticle(context.Background(), id)
|
article, _ := internal.Ei.LoadArticle(context.Background(), id)
|
||||||
if article != nil {
|
if article != nil {
|
||||||
params["Title"] = "编辑文章 | " + cache.Ei.Blogger.BTitle
|
params["Title"] = "编辑文章 | " + internal.Ei.Blogger.BTitle
|
||||||
params["Edit"] = article
|
params["Edit"] = article
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if params["Title"] == nil {
|
if params["Title"] == nil {
|
||||||
params["Title"] = "撰写文章 | " + cache.Ei.Blogger.BTitle
|
params["Title"] = "撰写文章 | " + internal.Ei.Blogger.BTitle
|
||||||
}
|
}
|
||||||
params["Path"] = c.Request.URL.Path
|
params["Path"] = c.Request.URL.Path
|
||||||
params["Domain"] = config.Conf.EiBlogApp.Host
|
params["Domain"] = config.Conf.Host
|
||||||
params["Series"] = cache.Ei.Series
|
params["Series"] = internal.Ei.Series
|
||||||
var tags []T
|
var tags []T
|
||||||
for tag := range cache.Ei.TagArticles {
|
for tag := range internal.Ei.TagArticles {
|
||||||
tags = append(tags, T{tag, tag})
|
tags = append(tags, T{tag, tag})
|
||||||
}
|
}
|
||||||
str, _ := json.Marshal(tags)
|
str, _ := json.Marshal(tags)
|
||||||
@@ -97,15 +96,15 @@ func handleAdminPosts(c *gin.Context) {
|
|||||||
vals := c.Request.URL.Query()
|
vals := c.Request.URL.Query()
|
||||||
|
|
||||||
params := baseBEParams(c)
|
params := baseBEParams(c)
|
||||||
params["Title"] = "文章管理 | " + cache.Ei.Blogger.BTitle
|
params["Title"] = "文章管理 | " + internal.Ei.Blogger.BTitle
|
||||||
params["Manage"] = true
|
params["Manage"] = true
|
||||||
params["Path"] = c.Request.URL.Path
|
params["Path"] = c.Request.URL.Path
|
||||||
params["Series"] = cache.Ei.Series
|
params["Series"] = internal.Ei.Series
|
||||||
params["Serie"] = se
|
params["Serie"] = se
|
||||||
params["KW"] = kw
|
params["KW"] = kw
|
||||||
var max int
|
var max int
|
||||||
params["List"], max = cache.Ei.PageArticleBE(se, kw, false, false,
|
params["List"], max = internal.Ei.PageArticleBE(se, kw, false, false,
|
||||||
pg, config.Conf.EiBlogApp.General.PageSize)
|
pg, config.Conf.General.PageSize)
|
||||||
if pg < max {
|
if pg < max {
|
||||||
vals.Set("page", fmt.Sprint(pg+1))
|
vals.Set("page", fmt.Sprint(pg+1))
|
||||||
params["Next"] = vals.Encode()
|
params["Next"] = vals.Encode()
|
||||||
@@ -126,10 +125,10 @@ func handleAdminPosts(c *gin.Context) {
|
|||||||
// handleAdminSeries 专题列表
|
// handleAdminSeries 专题列表
|
||||||
func handleAdminSeries(c *gin.Context) {
|
func handleAdminSeries(c *gin.Context) {
|
||||||
params := baseBEParams(c)
|
params := baseBEParams(c)
|
||||||
params["Title"] = "专题管理 | " + cache.Ei.Blogger.BTitle
|
params["Title"] = "专题管理 | " + internal.Ei.Blogger.BTitle
|
||||||
params["Manage"] = true
|
params["Manage"] = true
|
||||||
params["Path"] = c.Request.URL.Path
|
params["Path"] = c.Request.URL.Path
|
||||||
params["List"] = cache.Ei.Series
|
params["List"] = internal.Ei.Series
|
||||||
renderHTMLAdminLayout(c, "admin-series", params)
|
renderHTMLAdminLayout(c, "admin-series", params)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -138,11 +137,11 @@ func handleAdminSerie(c *gin.Context) {
|
|||||||
params := baseBEParams(c)
|
params := baseBEParams(c)
|
||||||
|
|
||||||
id, err := strconv.Atoi(c.Query("mid"))
|
id, err := strconv.Atoi(c.Query("mid"))
|
||||||
params["Title"] = "新增专题 | " + cache.Ei.Blogger.BTitle
|
params["Title"] = "新增专题 | " + internal.Ei.Blogger.BTitle
|
||||||
if err == nil && id > 0 {
|
if err == nil && id > 0 {
|
||||||
for _, v := range cache.Ei.Series {
|
for _, v := range internal.Ei.Series {
|
||||||
if v.ID == id {
|
if v.ID == id {
|
||||||
params["Title"] = "编辑专题 | " + cache.Ei.Blogger.BTitle
|
params["Title"] = "编辑专题 | " + internal.Ei.Blogger.BTitle
|
||||||
params["Edit"] = v
|
params["Edit"] = v
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -156,10 +155,10 @@ func handleAdminSerie(c *gin.Context) {
|
|||||||
// handleAdminTags 标签列表
|
// handleAdminTags 标签列表
|
||||||
func handleAdminTags(c *gin.Context) {
|
func handleAdminTags(c *gin.Context) {
|
||||||
params := baseBEParams(c)
|
params := baseBEParams(c)
|
||||||
params["Title"] = "标签管理 | " + cache.Ei.Blogger.BTitle
|
params["Title"] = "标签管理 | " + internal.Ei.Blogger.BTitle
|
||||||
params["Manage"] = true
|
params["Manage"] = true
|
||||||
params["Path"] = c.Request.URL.Path
|
params["Path"] = c.Request.URL.Path
|
||||||
params["List"] = cache.Ei.TagArticles
|
params["List"] = internal.Ei.TagArticles
|
||||||
renderHTMLAdminLayout(c, "admin-tags", params)
|
renderHTMLAdminLayout(c, "admin-tags", params)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -170,7 +169,7 @@ func handleDraftDelete(c *gin.Context) {
|
|||||||
c.JSON(http.StatusBadRequest, gin.H{"error": "参数错误"})
|
c.JSON(http.StatusBadRequest, gin.H{"error": "参数错误"})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
err = cache.Ei.RemoveArticle(context.Background(), id)
|
err = internal.Ei.RemoveArticle(context.Background(), id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(http.StatusBadRequest, gin.H{"error": "删除错误"})
|
c.JSON(http.StatusBadRequest, gin.H{"error": "删除错误"})
|
||||||
return
|
return
|
||||||
@@ -182,7 +181,7 @@ func handleDraftDelete(c *gin.Context) {
|
|||||||
func handleAdminDraft(c *gin.Context) {
|
func handleAdminDraft(c *gin.Context) {
|
||||||
params := baseBEParams(c)
|
params := baseBEParams(c)
|
||||||
|
|
||||||
params["Title"] = "草稿箱 | " + cache.Ei.Blogger.BTitle
|
params["Title"] = "草稿箱 | " + internal.Ei.Blogger.BTitle
|
||||||
params["Manage"] = true
|
params["Manage"] = true
|
||||||
params["Path"] = c.Request.URL.Path
|
params["Path"] = c.Request.URL.Path
|
||||||
var err error
|
var err error
|
||||||
@@ -191,7 +190,7 @@ func handleAdminDraft(c *gin.Context) {
|
|||||||
Limit: 9999,
|
Limit: 9999,
|
||||||
Fields: map[string]interface{}{store.SearchArticleDraft: true},
|
Fields: map[string]interface{}{store.SearchArticleDraft: true},
|
||||||
}
|
}
|
||||||
params["List"], _, err = cache.Ei.LoadArticleList(context.Background(), search)
|
params["List"], _, err = internal.Ei.LoadArticleList(context.Background(), search)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Error("handleDraft.LoadDraftArticles: ", err)
|
logrus.Error("handleDraft.LoadDraftArticles: ", err)
|
||||||
c.Status(http.StatusBadRequest)
|
c.Status(http.StatusBadRequest)
|
||||||
@@ -204,7 +203,7 @@ func handleAdminDraft(c *gin.Context) {
|
|||||||
// handleAdminTrash 回收箱页
|
// handleAdminTrash 回收箱页
|
||||||
func handleAdminTrash(c *gin.Context) {
|
func handleAdminTrash(c *gin.Context) {
|
||||||
params := baseBEParams(c)
|
params := baseBEParams(c)
|
||||||
params["Title"] = "回收箱 | " + cache.Ei.Blogger.BTitle
|
params["Title"] = "回收箱 | " + internal.Ei.Blogger.BTitle
|
||||||
params["Manage"] = true
|
params["Manage"] = true
|
||||||
params["Path"] = c.Request.URL.Path
|
params["Path"] = c.Request.URL.Path
|
||||||
var err error
|
var err error
|
||||||
@@ -213,7 +212,7 @@ func handleAdminTrash(c *gin.Context) {
|
|||||||
Limit: 9999,
|
Limit: 9999,
|
||||||
Fields: map[string]interface{}{store.SearchArticleTrash: true},
|
Fields: map[string]interface{}{store.SearchArticleTrash: true},
|
||||||
}
|
}
|
||||||
params["List"], _, err = cache.Ei.LoadArticleList(context.Background(), search)
|
params["List"], _, err = internal.Ei.LoadArticleList(context.Background(), search)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Error("handleTrash.LoadArticleList: ", err)
|
logrus.Error("handleTrash.LoadArticleList: ", err)
|
||||||
}
|
}
|
||||||
@@ -223,7 +222,7 @@ func handleAdminTrash(c *gin.Context) {
|
|||||||
// handleAdminGeneral 基本设置
|
// handleAdminGeneral 基本设置
|
||||||
func handleAdminGeneral(c *gin.Context) {
|
func handleAdminGeneral(c *gin.Context) {
|
||||||
params := baseBEParams(c)
|
params := baseBEParams(c)
|
||||||
params["Title"] = "基本设置 | " + cache.Ei.Blogger.BTitle
|
params["Title"] = "基本设置 | " + internal.Ei.Blogger.BTitle
|
||||||
params["Setting"] = true
|
params["Setting"] = true
|
||||||
params["Path"] = c.Request.URL.Path
|
params["Path"] = c.Request.URL.Path
|
||||||
renderHTMLAdminLayout(c, "admin-general", params)
|
renderHTMLAdminLayout(c, "admin-general", params)
|
||||||
@@ -232,7 +231,7 @@ func handleAdminGeneral(c *gin.Context) {
|
|||||||
// handleAdminDiscussion 阅读设置
|
// handleAdminDiscussion 阅读设置
|
||||||
func handleAdminDiscussion(c *gin.Context) {
|
func handleAdminDiscussion(c *gin.Context) {
|
||||||
params := baseBEParams(c)
|
params := baseBEParams(c)
|
||||||
params["Title"] = "阅读设置 | " + cache.Ei.Blogger.BTitle
|
params["Title"] = "阅读设置 | " + internal.Ei.Blogger.BTitle
|
||||||
params["Setting"] = true
|
params["Setting"] = true
|
||||||
params["Path"] = c.Request.URL.Path
|
params["Path"] = c.Request.URL.Path
|
||||||
renderHTMLAdminLayout(c, "admin-discussion", params)
|
renderHTMLAdminLayout(c, "admin-discussion", params)
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
// Package page provides ...
|
|
||||||
package page
|
package page
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -13,9 +12,9 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/eiblog/eiblog/pkg/cache"
|
"github.com/eiblog/eiblog/cmd/eiblog/config"
|
||||||
"github.com/eiblog/eiblog/pkg/config"
|
"github.com/eiblog/eiblog/cmd/eiblog/handler/internal"
|
||||||
"github.com/eiblog/eiblog/pkg/internal"
|
"github.com/eiblog/eiblog/pkg/third/disqus"
|
||||||
"github.com/eiblog/eiblog/tools"
|
"github.com/eiblog/eiblog/tools"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
@@ -28,20 +27,20 @@ func baseFEParams(c *gin.Context) gin.H {
|
|||||||
|
|
||||||
cookie, err := c.Request.Cookie("v")
|
cookie, err := c.Request.Cookie("v")
|
||||||
if err != nil || cookie.Value !=
|
if err != nil || cookie.Value !=
|
||||||
fmt.Sprint(config.Conf.EiBlogApp.StaticVersion) {
|
fmt.Sprint(config.Conf.StaticVersion) {
|
||||||
version = config.Conf.EiBlogApp.StaticVersion
|
version = config.Conf.StaticVersion
|
||||||
}
|
}
|
||||||
return gin.H{
|
return gin.H{
|
||||||
"BlogName": cache.Ei.Blogger.BlogName,
|
"BlogName": internal.Ei.Blogger.BlogName,
|
||||||
"SubTitle": cache.Ei.Blogger.SubTitle,
|
"SubTitle": internal.Ei.Blogger.SubTitle,
|
||||||
"BTitle": cache.Ei.Blogger.BTitle,
|
"BTitle": internal.Ei.Blogger.BTitle,
|
||||||
"BeiAn": cache.Ei.Blogger.BeiAn,
|
"BeiAn": internal.Ei.Blogger.BeiAn,
|
||||||
"Domain": config.Conf.EiBlogApp.Host,
|
"Domain": config.Conf.Host,
|
||||||
"CopyYear": time.Now().Year(),
|
"CopyYear": time.Now().Year(),
|
||||||
"Twitter": config.Conf.EiBlogApp.Twitter,
|
"Twitter": config.Conf.Twitter,
|
||||||
"Qiniu": config.Conf.EiBlogApp.Qiniu,
|
"Qiniu": config.Conf.Qiniu,
|
||||||
"Disqus": config.Conf.EiBlogApp.Disqus,
|
"Disqus": config.Conf.Disqus,
|
||||||
"AdSense": config.Conf.EiBlogApp.Google.AdSense,
|
"AdSense": config.Conf.Google.AdSense,
|
||||||
"Version": version,
|
"Version": version,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -59,16 +58,16 @@ func handleNotFound(c *gin.Context) {
|
|||||||
// handleHomePage 首页
|
// handleHomePage 首页
|
||||||
func handleHomePage(c *gin.Context) {
|
func handleHomePage(c *gin.Context) {
|
||||||
params := baseFEParams(c)
|
params := baseFEParams(c)
|
||||||
params["Title"] = cache.Ei.Blogger.BTitle + " | " + cache.Ei.Blogger.SubTitle
|
params["Title"] = internal.Ei.Blogger.BTitle + " | " + internal.Ei.Blogger.SubTitle
|
||||||
params["Description"] = "博客首页," + cache.Ei.Blogger.SubTitle
|
params["Description"] = "博客首页," + internal.Ei.Blogger.SubTitle
|
||||||
params["Path"] = c.Request.URL.Path
|
params["Path"] = c.Request.URL.Path
|
||||||
params["CurrentPage"] = "blog-home"
|
params["CurrentPage"] = "blog-home"
|
||||||
pn, err := strconv.Atoi(c.Query("pn"))
|
pn, err := strconv.Atoi(c.Query("pn"))
|
||||||
if err != nil || pn < 1 {
|
if err != nil || pn < 1 {
|
||||||
pn = 1
|
pn = 1
|
||||||
}
|
}
|
||||||
params["Prev"], params["Next"], params["List"] = cache.Ei.PageArticleFE(pn,
|
params["Prev"], params["Next"], params["List"] = internal.Ei.PageArticleFE(pn,
|
||||||
config.Conf.EiBlogApp.General.PageNum)
|
config.Conf.General.PageNum)
|
||||||
|
|
||||||
renderHTMLHomeLayout(c, "home", params)
|
renderHTMLHomeLayout(c, "home", params)
|
||||||
}
|
}
|
||||||
@@ -76,13 +75,13 @@ func handleHomePage(c *gin.Context) {
|
|||||||
// handleArticlePage 文章页
|
// handleArticlePage 文章页
|
||||||
func handleArticlePage(c *gin.Context) {
|
func handleArticlePage(c *gin.Context) {
|
||||||
slug := c.Param("slug")
|
slug := c.Param("slug")
|
||||||
if !strings.HasSuffix(slug, ".html") || cache.Ei.ArticlesMap[slug[:len(slug)-5]] == nil {
|
if !strings.HasSuffix(slug, ".html") || internal.Ei.ArticlesMap[slug[:len(slug)-5]] == nil {
|
||||||
handleNotFound(c)
|
handleNotFound(c)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
article := cache.Ei.ArticlesMap[slug[:len(slug)-5]]
|
article := internal.Ei.ArticlesMap[slug[:len(slug)-5]]
|
||||||
params := baseFEParams(c)
|
params := baseFEParams(c)
|
||||||
params["Title"] = article.Title + " | " + cache.Ei.Blogger.BTitle
|
params["Title"] = article.Title + " | " + internal.Ei.Blogger.BTitle
|
||||||
params["Path"] = c.Request.URL.Path
|
params["Path"] = c.Request.URL.Path
|
||||||
params["CurrentPage"] = "post-" + article.Slug
|
params["CurrentPage"] = "post-" + article.Slug
|
||||||
params["Article"] = article
|
params["Article"] = article
|
||||||
@@ -91,21 +90,21 @@ func handleArticlePage(c *gin.Context) {
|
|||||||
switch slug {
|
switch slug {
|
||||||
case "blogroll.html":
|
case "blogroll.html":
|
||||||
name = "blogroll"
|
name = "blogroll"
|
||||||
params["Description"] = "友情连接," + cache.Ei.Blogger.SubTitle
|
params["Description"] = "友情连接," + internal.Ei.Blogger.SubTitle
|
||||||
case "about.html":
|
case "about.html":
|
||||||
name = "about"
|
name = "about"
|
||||||
params["Description"] = "关于作者," + cache.Ei.Blogger.SubTitle
|
params["Description"] = "关于作者," + internal.Ei.Blogger.SubTitle
|
||||||
default:
|
default:
|
||||||
params["Description"] = article.Desc + "," + cache.Ei.Blogger.SubTitle
|
params["Description"] = article.Desc + "," + internal.Ei.Blogger.SubTitle
|
||||||
name = "article"
|
name = "article"
|
||||||
params["Copyright"] = cache.Ei.Blogger.Copyright
|
params["Copyright"] = internal.Ei.Blogger.Copyright
|
||||||
if !article.UpdatedAt.IsZero() {
|
if !article.UpdatedAt.IsZero() {
|
||||||
params["Days"] = int(time.Now().Sub(article.UpdatedAt).Hours()) / 24
|
params["Days"] = int(time.Since(article.UpdatedAt).Hours()) / 24
|
||||||
} else {
|
} else {
|
||||||
params["Days"] = int(time.Now().Sub(article.CreatedAt).Hours()) / 24
|
params["Days"] = int(time.Since(article.CreatedAt).Hours()) / 24
|
||||||
}
|
}
|
||||||
if article.SerieID > 0 {
|
if article.SerieID > 0 {
|
||||||
for _, series := range cache.Ei.Series {
|
for _, series := range internal.Ei.Series {
|
||||||
if series.ID == article.SerieID {
|
if series.ID == article.SerieID {
|
||||||
params["Serie"] = series
|
params["Serie"] = series
|
||||||
}
|
}
|
||||||
@@ -118,30 +117,30 @@ func handleArticlePage(c *gin.Context) {
|
|||||||
// handleSeriesPage 专题页
|
// handleSeriesPage 专题页
|
||||||
func handleSeriesPage(c *gin.Context) {
|
func handleSeriesPage(c *gin.Context) {
|
||||||
params := baseFEParams(c)
|
params := baseFEParams(c)
|
||||||
params["Title"] = "专题 | " + cache.Ei.Blogger.BTitle
|
params["Title"] = "专题 | " + internal.Ei.Blogger.BTitle
|
||||||
params["Description"] = "专题列表," + cache.Ei.Blogger.SubTitle
|
params["Description"] = "专题列表," + internal.Ei.Blogger.SubTitle
|
||||||
params["Path"] = c.Request.URL.Path
|
params["Path"] = c.Request.URL.Path
|
||||||
params["CurrentPage"] = "series"
|
params["CurrentPage"] = "series"
|
||||||
params["Article"] = cache.Ei.PageSeries
|
params["Article"] = internal.Ei.PageSeries
|
||||||
renderHTMLHomeLayout(c, "series", params)
|
renderHTMLHomeLayout(c, "series", params)
|
||||||
}
|
}
|
||||||
|
|
||||||
// handleArchivePage 归档页
|
// handleArchivePage 归档页
|
||||||
func handleArchivePage(c *gin.Context) {
|
func handleArchivePage(c *gin.Context) {
|
||||||
params := baseFEParams(c)
|
params := baseFEParams(c)
|
||||||
params["Title"] = "归档 | " + cache.Ei.Blogger.BTitle
|
params["Title"] = "归档 | " + internal.Ei.Blogger.BTitle
|
||||||
params["Description"] = "博客归档," + cache.Ei.Blogger.SubTitle
|
params["Description"] = "博客归档," + internal.Ei.Blogger.SubTitle
|
||||||
params["Path"] = c.Request.URL.Path
|
params["Path"] = c.Request.URL.Path
|
||||||
params["CurrentPage"] = "archives"
|
params["CurrentPage"] = "archives"
|
||||||
params["Article"] = cache.Ei.PageArchives
|
params["Article"] = internal.Ei.PageArchives
|
||||||
renderHTMLHomeLayout(c, "archives", params)
|
renderHTMLHomeLayout(c, "archives", params)
|
||||||
}
|
}
|
||||||
|
|
||||||
// handleSearchPage 搜索页
|
// handleSearchPage 搜索页
|
||||||
func handleSearchPage(c *gin.Context) {
|
func handleSearchPage(c *gin.Context) {
|
||||||
params := baseFEParams(c)
|
params := baseFEParams(c)
|
||||||
params["Title"] = "站内搜索 | " + cache.Ei.Blogger.BTitle
|
params["Title"] = "站内搜索 | " + internal.Ei.Blogger.BTitle
|
||||||
params["Description"] = "站内搜索," + cache.Ei.Blogger.SubTitle
|
params["Description"] = "站内搜索," + internal.Ei.Blogger.SubTitle
|
||||||
params["Path"] = ""
|
params["Path"] = ""
|
||||||
params["CurrentPage"] = "search-post"
|
params["CurrentPage"] = "search-post"
|
||||||
|
|
||||||
@@ -154,29 +153,29 @@ func handleSearchPage(c *gin.Context) {
|
|||||||
params["Word"] = q
|
params["Word"] = q
|
||||||
|
|
||||||
vals := c.Request.URL.Query()
|
vals := c.Request.URL.Query()
|
||||||
result, err := internal.ElasticSearch(q, config.Conf.EiBlogApp.General.PageNum, start-1)
|
result, err := internal.ESClient.ElasticSearch(q, config.Conf.General.PageNum, start-1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Error("HandleSearchPage.ElasticSearch: ", err)
|
logrus.Error("HandleSearchPage.ElasticSearch: ", err)
|
||||||
} else {
|
} else {
|
||||||
result.Took /= 1000
|
result.Took /= 1000
|
||||||
for i, v := range result.Hits.Hits {
|
for i, v := range result.Hits.Hits {
|
||||||
article := cache.Ei.ArticlesMap[v.Source.Slug]
|
article := internal.Ei.ArticlesMap[v.Source.Slug]
|
||||||
if len(v.Highlight.Content) == 0 && article != nil {
|
if len(v.Highlight.Content) == 0 && article != nil {
|
||||||
result.Hits.Hits[i].Highlight.Content = []string{article.Excerpt}
|
result.Hits.Hits[i].Highlight.Content = []string{article.Excerpt}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
params["SearchResult"] = result
|
params["SearchResult"] = result
|
||||||
if num := start - config.Conf.EiBlogApp.General.PageNum; num > 0 {
|
if num := start - config.Conf.General.PageNum; num > 0 {
|
||||||
vals.Set("start", fmt.Sprint(num))
|
vals.Set("start", fmt.Sprint(num))
|
||||||
params["Prev"] = vals.Encode()
|
params["Prev"] = vals.Encode()
|
||||||
}
|
}
|
||||||
if num := start + config.Conf.EiBlogApp.General.PageNum; result.Hits.Total >= num {
|
if num := start + config.Conf.General.PageNum; result.Hits.Total >= num {
|
||||||
vals.Set("start", fmt.Sprint(num))
|
vals.Set("start", fmt.Sprint(num))
|
||||||
params["Next"] = vals.Encode()
|
params["Next"] = vals.Encode()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
params["HotWords"] = config.Conf.EiBlogApp.HotWords
|
params["HotWords"] = config.Conf.HotWords
|
||||||
}
|
}
|
||||||
renderHTMLHomeLayout(c, "search", params)
|
renderHTMLHomeLayout(c, "search", params)
|
||||||
}
|
}
|
||||||
@@ -200,11 +199,11 @@ func handleDisqusList(c *gin.Context) {
|
|||||||
|
|
||||||
slug := c.Param("slug")
|
slug := c.Param("slug")
|
||||||
cursor := c.Query("cursor")
|
cursor := c.Query("cursor")
|
||||||
artc := cache.Ei.ArticlesMap[slug]
|
artc := internal.Ei.ArticlesMap[slug]
|
||||||
if artc != nil {
|
if artc != nil {
|
||||||
dcs.Data.Thread = artc.Thread
|
dcs.Data.Thread = artc.Thread
|
||||||
}
|
}
|
||||||
postsList, err := internal.PostsList(artc, cursor)
|
postsList, err := internal.DisqusClient.PostsList(artc, cursor)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Error("hadnleDisqusList.PostsList: ", err)
|
logrus.Error("hadnleDisqusList.PostsList: ", err)
|
||||||
dcs.ErrNo = 0
|
dcs.ErrNo = 0
|
||||||
@@ -236,10 +235,10 @@ func handleDisqusList(c *gin.Context) {
|
|||||||
if artc != nil && artc.Thread == "" {
|
if artc != nil && artc.Thread == "" {
|
||||||
if dcs.Data.Thread != "" {
|
if dcs.Data.Thread != "" {
|
||||||
artc.Thread = dcs.Data.Thread
|
artc.Thread = dcs.Data.Thread
|
||||||
} else if internal.ThreadDetails(artc) == nil {
|
} else if internal.DisqusClient.ThreadDetails(artc) == nil {
|
||||||
dcs.Data.Thread = artc.Thread
|
dcs.Data.Thread = artc.Thread
|
||||||
}
|
}
|
||||||
cache.Ei.UpdateArticle(context.Background(), artc.ID,
|
internal.Ei.UpdateArticle(context.Background(), artc.ID,
|
||||||
map[string]interface{}{
|
map[string]interface{}{
|
||||||
"thread": artc.Thread,
|
"thread": artc.Thread,
|
||||||
})
|
})
|
||||||
@@ -253,9 +252,9 @@ func handleDisqusPage(c *gin.Context) {
|
|||||||
c.String(http.StatusOK, "出错啦。。。")
|
c.String(http.StatusOK, "出错啦。。。")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
article := cache.Ei.ArticlesMap[array[0]]
|
article := internal.Ei.ArticlesMap[array[0]]
|
||||||
params := gin.H{
|
params := gin.H{
|
||||||
"Title": "发表评论 | " + cache.Ei.Blogger.BTitle,
|
"Title": "发表评论 | " + internal.Ei.Blogger.BTitle,
|
||||||
"ATitle": article.Title,
|
"ATitle": article.Title,
|
||||||
"Thread": array[1],
|
"Thread": array[1],
|
||||||
"Slug": article.Slug,
|
"Slug": article.Slug,
|
||||||
@@ -300,7 +299,7 @@ func handleDisqusCreate(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
logrus.Infof("email: %s comments: %s", email, thread)
|
logrus.Infof("email: %s comments: %s", email, thread)
|
||||||
|
|
||||||
comment := internal.PostComment{
|
comment := disqus.PostComment{
|
||||||
Message: msg,
|
Message: msg,
|
||||||
Parent: c.PostForm("parent"),
|
Parent: c.PostForm("parent"),
|
||||||
Thread: thread,
|
Thread: thread,
|
||||||
@@ -309,14 +308,14 @@ func handleDisqusCreate(c *gin.Context) {
|
|||||||
Identifier: identifier,
|
Identifier: identifier,
|
||||||
IPAddress: c.ClientIP(),
|
IPAddress: c.ClientIP(),
|
||||||
}
|
}
|
||||||
postDetail, err := internal.PostCreate(&comment)
|
postDetail, err := internal.DisqusClient.PostCreate(&comment)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Error("handleDisqusCreate.PostCreate: ", err)
|
logrus.Error("handleDisqusCreate.PostCreate: ", err)
|
||||||
resp.ErrNo = 1
|
resp.ErrNo = 1
|
||||||
resp.ErrMsg = "提交评论失败,请重试"
|
resp.ErrMsg = "提交评论失败,请重试"
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
err = internal.PostApprove(postDetail.Response.ID)
|
err = internal.DisqusClient.PostApprove(postDetail.Response.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Error("handleDisqusCreate.PostApprove: ", err)
|
logrus.Error("handleDisqusCreate.PostApprove: ", err)
|
||||||
resp.ErrNo = 1
|
resp.ErrNo = 1
|
||||||
@@ -341,8 +340,8 @@ func handleBeaconPage(c *gin.Context) {
|
|||||||
ua := c.Request.UserAgent()
|
ua := c.Request.UserAgent()
|
||||||
|
|
||||||
vals := c.Request.URL.Query()
|
vals := c.Request.URL.Query()
|
||||||
vals.Set("v", config.Conf.EiBlogApp.Google.V)
|
vals.Set("v", config.Conf.Google.V)
|
||||||
vals.Set("tid", config.Conf.EiBlogApp.Google.Tid)
|
vals.Set("tid", config.Conf.Google.Tid)
|
||||||
cookie, _ := c.Cookie("u")
|
cookie, _ := c.Cookie("u")
|
||||||
vals.Set("cid", cookie)
|
vals.Set("cid", cookie)
|
||||||
|
|
||||||
@@ -354,7 +353,7 @@ func handleBeaconPage(c *gin.Context) {
|
|||||||
vals.Set("_p", fmt.Sprint(201226219+rand.Intn(499999999))) // random page load hash
|
vals.Set("_p", fmt.Sprint(201226219+rand.Intn(499999999))) // random page load hash
|
||||||
vals.Set("_ee", "1") // external event
|
vals.Set("_ee", "1") // external event
|
||||||
go func() {
|
go func() {
|
||||||
url := config.Conf.EiBlogApp.Google.URL + "?" + vals.Encode()
|
url := config.Conf.Google.URL + "?" + vals.Encode()
|
||||||
req, err := http.NewRequest("POST", url, nil)
|
req, err := http.NewRequest("POST", url, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Error("HandleBeaconPage.NewRequest: ", err)
|
logrus.Error("HandleBeaconPage.NewRequest: ", err)
|
||||||
@@ -1,12 +1,12 @@
|
|||||||
// Package page provides ...
|
|
||||||
package page
|
package page
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io/fs"
|
"io/fs"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
"text/template"
|
"text/template"
|
||||||
|
|
||||||
"github.com/eiblog/eiblog/pkg/config"
|
"github.com/eiblog/eiblog/cmd/eiblog/config"
|
||||||
"github.com/eiblog/eiblog/tools"
|
"github.com/eiblog/eiblog/tools"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
@@ -20,7 +20,7 @@ func init() {
|
|||||||
root := filepath.Join(config.WorkDir, "website")
|
root := filepath.Join(config.WorkDir, "website")
|
||||||
files := tools.ReadDirFiles(root, func(fi fs.DirEntry) bool {
|
files := tools.ReadDirFiles(root, func(fi fs.DirEntry) bool {
|
||||||
name := fi.Name()
|
name := fi.Name()
|
||||||
if name == ".DS_Store" {
|
if strings.HasPrefix(name, ".") {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// should not read template dir
|
// should not read template dir
|
||||||
@@ -1,8 +1,7 @@
|
|||||||
// Package swag provides ...
|
|
||||||
package swag
|
package swag
|
||||||
|
|
||||||
import (
|
import (
|
||||||
_ "github.com/eiblog/eiblog/pkg/core/backup/docs" // docs
|
_ "github.com/eiblog/eiblog/cmd/eiblog/docs" // docs
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
swaggerFiles "github.com/swaggo/files"
|
swaggerFiles "github.com/swaggo/files"
|
||||||
@@ -2,52 +2,48 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
"github.com/eiblog/eiblog/pkg/config"
|
"github.com/eiblog/eiblog/cmd/eiblog/config"
|
||||||
"github.com/eiblog/eiblog/pkg/core/eiblog"
|
"github.com/eiblog/eiblog/cmd/eiblog/handler/admin"
|
||||||
"github.com/eiblog/eiblog/pkg/core/eiblog/admin"
|
"github.com/eiblog/eiblog/cmd/eiblog/handler/file"
|
||||||
"github.com/eiblog/eiblog/pkg/core/eiblog/file"
|
"github.com/eiblog/eiblog/cmd/eiblog/handler/page"
|
||||||
"github.com/eiblog/eiblog/pkg/core/eiblog/page"
|
"github.com/eiblog/eiblog/cmd/eiblog/handler/swag"
|
||||||
"github.com/eiblog/eiblog/pkg/core/eiblog/swag"
|
|
||||||
"github.com/eiblog/eiblog/pkg/mid"
|
"github.com/eiblog/eiblog/pkg/middleware"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
fmt.Println("Hi, it's App " + config.Conf.EiBlogApp.Name)
|
logrus.Info("Hi, it's App " + config.Conf.Name)
|
||||||
|
|
||||||
endRun := make(chan error, 1)
|
endRun := make(chan error, 1)
|
||||||
|
|
||||||
runHTTPServer(endRun)
|
runHTTPServer(endRun)
|
||||||
fmt.Println(<-endRun)
|
logrus.Fatal(<-endRun)
|
||||||
}
|
}
|
||||||
|
|
||||||
func runHTTPServer(endRun chan error) {
|
func runHTTPServer(endRun chan error) {
|
||||||
if !config.Conf.EiBlogApp.EnableHTTP {
|
if config.Conf.RunMode.IsReleaseMode() {
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if config.Conf.RunMode == config.ModeProd {
|
|
||||||
gin.SetMode(gin.ReleaseMode)
|
gin.SetMode(gin.ReleaseMode)
|
||||||
}
|
}
|
||||||
e := gin.Default()
|
e := gin.Default()
|
||||||
// middleware
|
// middleware
|
||||||
e.Use(mid.UserMiddleware())
|
e.Use(middleware.UserMiddleware())
|
||||||
e.Use(mid.SessionMiddleware(mid.SessionOpts{
|
e.Use(middleware.SessionMiddleware(
|
||||||
Name: "su",
|
middleware.SessionOpts{
|
||||||
Secure: config.Conf.RunMode == config.ModeProd,
|
Name: "su",
|
||||||
Secret: []byte("ZGlzvcmUoMTAsICI="),
|
Secure: config.Conf.RunMode.IsReleaseMode(),
|
||||||
}))
|
Secret: []byte("ZGlzvcmUoMTAsICI="),
|
||||||
|
}))
|
||||||
|
|
||||||
// swag
|
// swag
|
||||||
swag.RegisterRoutes(e)
|
swag.RegisterRoutes(e)
|
||||||
|
|
||||||
// static files, page
|
// static files, page
|
||||||
root := filepath.Join(config.WorkDir, "assets")
|
e.Static("/static", filepath.Join(config.WorkDir, "assets"))
|
||||||
e.Static("/static", root)
|
|
||||||
|
|
||||||
// static files
|
// static files
|
||||||
file.RegisterRoutes(e)
|
file.RegisterRoutes(e)
|
||||||
@@ -57,16 +53,15 @@ func runHTTPServer(endRun chan error) {
|
|||||||
admin.RegisterRoutes(e)
|
admin.RegisterRoutes(e)
|
||||||
|
|
||||||
// admin router
|
// admin router
|
||||||
group := e.Group("/admin", eiblog.AuthFilter)
|
group := e.Group("/admin", middleware.AuthFilter)
|
||||||
{
|
{
|
||||||
page.RegisterRoutesAuthz(group)
|
page.RegisterRoutesAuthz(group)
|
||||||
admin.RegisterRoutesAuthz(group)
|
admin.RegisterRoutesAuthz(group)
|
||||||
}
|
}
|
||||||
|
|
||||||
// start
|
// start
|
||||||
address := fmt.Sprintf(":%d", config.Conf.EiBlogApp.HTTPPort)
|
|
||||||
go func() {
|
go func() {
|
||||||
endRun <- e.Run(address)
|
endRun <- e.Run(config.Conf.Listen)
|
||||||
}()
|
}()
|
||||||
fmt.Println("HTTP server running on: " + address)
|
logrus.Info("HTTP server running on: " + config.Conf.Listen)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
version: '3'
|
|
||||||
services:
|
services:
|
||||||
mongodb:
|
mongodb:
|
||||||
image: mongo:3.2
|
image: mongo:3.2
|
||||||
@@ -10,6 +9,7 @@ services:
|
|||||||
volumes:
|
volumes:
|
||||||
- ${PWD}/esdata:/usr/share/elasticsearch/data
|
- ${PWD}/esdata:/usr/share/elasticsearch/data
|
||||||
restart: always
|
restart: always
|
||||||
|
|
||||||
eiblog:
|
eiblog:
|
||||||
image: deepzz0/eiblog:latest
|
image: deepzz0/eiblog:latest
|
||||||
volumes:
|
volumes:
|
||||||
@@ -25,6 +25,7 @@ services:
|
|||||||
ports:
|
ports:
|
||||||
- 127.0.0.1:9000:9000
|
- 127.0.0.1:9000:9000
|
||||||
restart: always
|
restart: always
|
||||||
|
|
||||||
backup:
|
backup:
|
||||||
image: deepzz0/backup:latest
|
image: deepzz0/backup:latest
|
||||||
#command: ./backend --restore true
|
#command: ./backend --restore true
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
Configuration file templates or default configs.
|
|
||||||
|
|
||||||
Put your confd or consul-template template files here.
|
|
||||||
66
conf/app.yml
66
conf/app.yml
@@ -1,66 +0,0 @@
|
|||||||
appname: eiblog
|
|
||||||
database:
|
|
||||||
driver: sqlite
|
|
||||||
source: ./db.sqlite
|
|
||||||
eshost: # http://elasticsearch:9200
|
|
||||||
eiblogapp:
|
|
||||||
mode:
|
|
||||||
name: cmd-eiblog
|
|
||||||
enablehttp: true
|
|
||||||
httpport: 9000
|
|
||||||
host: example.com
|
|
||||||
staticversion: 1 # 静态文件版本
|
|
||||||
hotwords: # 热搜词
|
|
||||||
- docker
|
|
||||||
- mongodb
|
|
||||||
- curl
|
|
||||||
- dns
|
|
||||||
general: # 常规配置
|
|
||||||
pagenum: 10 # 首页展示文章数量
|
|
||||||
pagesize: 20 # 管理界面
|
|
||||||
startid: 11 # 起始ID,预留id不时之需, 不用管
|
|
||||||
descprefix: "Desc:" # 文章描述前缀
|
|
||||||
identifier: <!--more--> # 截取预览标识
|
|
||||||
length: 400 # 自动截取预览, 字符数
|
|
||||||
timezone: Asia/Shanghai # 时区
|
|
||||||
disqus: # 评论相关
|
|
||||||
shortname: xxxxxx
|
|
||||||
publickey: wdSgxRm9rdGAlLKFcFdToBe3GT4SibmV7Y8EjJQ0r4GWXeKtxpopMAeIeoI2dTEg
|
|
||||||
accesstoken: 50023908f39f4607957e909b495326af
|
|
||||||
google: # 谷歌分析
|
|
||||||
url: https://www.google-analytics.com/g/collect
|
|
||||||
tid: G-xxxxxxxxxx
|
|
||||||
v: "2"
|
|
||||||
adsense: <script async src="https://pagead2.googlesyndication.com/xxx" crossorigin="anonymous"></script>
|
|
||||||
qiniu: # 七牛OSS
|
|
||||||
bucket: eiblog
|
|
||||||
domain: st.deepzz.com
|
|
||||||
accesskey: MB6AXl_Sj_mmFsL-Lt59Dml2Vmy2o8XMmiCbbSeC
|
|
||||||
secretkey: BIrMy0fsZ0_SHNceNXk3eDuo7WmVYzj2-zrmd5Tf
|
|
||||||
twitter: # twitter card
|
|
||||||
card: summary
|
|
||||||
site: deepzz02
|
|
||||||
image: st.deepzz.com/static/img/avatar.jpg
|
|
||||||
address: twitter.com/deepzz02
|
|
||||||
feedrpc: # rss ping
|
|
||||||
feedrurl: https://deepzz.superfeedr.com/
|
|
||||||
pingrpc:
|
|
||||||
- http://ping.baidu.com/ping/RPC2
|
|
||||||
- http://rpc.pingomatic.com/
|
|
||||||
# 数据初始化操作,可到博客后台修改
|
|
||||||
account:
|
|
||||||
username: deepzz # *后台登录用户名
|
|
||||||
password: deepzz # *登录明文密码
|
|
||||||
backupapp:
|
|
||||||
mode:
|
|
||||||
name: cmd-backup
|
|
||||||
enablehttp: true
|
|
||||||
httpport: 9001
|
|
||||||
backupto: qiniu # 备份到七牛云
|
|
||||||
interval: 7d # 多久备份一次
|
|
||||||
validity: 60 # 保存时长days
|
|
||||||
qiniu: # 七牛OSS
|
|
||||||
bucket: backup
|
|
||||||
domain: st.deepzz.com
|
|
||||||
accesskey: MB6AXl_Sj_mmFsL-Lt59Dml2Vmy2o8XMmiCbbSeC
|
|
||||||
secretkey: BIrMy0fsZ0_SHNceNXk3eDuo7WmVYzj2-zrmd5Tf
|
|
||||||
6
go.mod
6
go.mod
@@ -10,9 +10,9 @@ require (
|
|||||||
github.com/qiniu/go-sdk/v7 v7.11.0
|
github.com/qiniu/go-sdk/v7 v7.11.0
|
||||||
github.com/satori/go.uuid v1.2.0
|
github.com/satori/go.uuid v1.2.0
|
||||||
github.com/sirupsen/logrus v1.9.3
|
github.com/sirupsen/logrus v1.9.3
|
||||||
github.com/swaggo/files v0.0.0-20190704085106-630677cd5c14
|
github.com/swaggo/files v1.0.1
|
||||||
github.com/swaggo/gin-swagger v1.3.3
|
github.com/swaggo/gin-swagger v1.6.0
|
||||||
github.com/swaggo/swag v1.7.4
|
github.com/swaggo/swag v1.16.4
|
||||||
go.mongodb.org/mongo-driver v1.5.4
|
go.mongodb.org/mongo-driver v1.5.4
|
||||||
gopkg.in/yaml.v3 v3.0.1
|
gopkg.in/yaml.v3 v3.0.1
|
||||||
gorm.io/driver/clickhouse v0.4.2
|
gorm.io/driver/clickhouse v0.4.2
|
||||||
|
|||||||
89
go.sum
89
go.sum
@@ -36,6 +36,7 @@ github.com/boj/redistore v0.0.0-20180917114910-cd5dcc76aeff/go.mod h1:+RTT1BOk5P
|
|||||||
github.com/bradfitz/gomemcache v0.0.0-20190913173617-a41fca850d0b/go.mod h1:H0wQNHz2YrLsuXOZozoeDmnHXkNCRmMW0gwFWDfEZDA=
|
github.com/bradfitz/gomemcache v0.0.0-20190913173617-a41fca850d0b/go.mod h1:H0wQNHz2YrLsuXOZozoeDmnHXkNCRmMW0gwFWDfEZDA=
|
||||||
github.com/bradleypeabody/gorilla-sessions-memcache v0.0.0-20181103040241-659414f458e1/go.mod h1:dkChI7Tbtx7H1Tj7TqGSZMOeGpMP5gLHtjroHd4agiI=
|
github.com/bradleypeabody/gorilla-sessions-memcache v0.0.0-20181103040241-659414f458e1/go.mod h1:dkChI7Tbtx7H1Tj7TqGSZMOeGpMP5gLHtjroHd4agiI=
|
||||||
github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM=
|
github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM=
|
||||||
|
github.com/bytedance/sonic v1.8.0/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U=
|
||||||
github.com/bytedance/sonic v1.9.1 h1:6iJ6NqdoxCDr6mbY8h18oSO+cShGSMRGCEo7F2h0x8s=
|
github.com/bytedance/sonic v1.9.1 h1:6iJ6NqdoxCDr6mbY8h18oSO+cShGSMRGCEo7F2h0x8s=
|
||||||
github.com/bytedance/sonic v1.9.1/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U=
|
github.com/bytedance/sonic v1.9.1/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U=
|
||||||
github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY=
|
github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY=
|
||||||
@@ -55,14 +56,15 @@ github.com/eiblog/blackfriday v0.0.0-20161010144836-c0ec111761ae/go.mod h1:HzHqT
|
|||||||
github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU=
|
github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU=
|
||||||
github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA=
|
github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA=
|
||||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||||
github.com/gin-contrib/gzip v0.0.3 h1:etUaeesHhEORpZMp18zoOhepboiWnFtXrBZxszWUn4k=
|
github.com/gin-contrib/gzip v0.0.6 h1:NjcunTcGAj5CO1gn4N8jHOSIeRFHIbn51z6K+xaN4d4=
|
||||||
github.com/gin-contrib/gzip v0.0.3/go.mod h1:YxxswVZIqOvcHEQpsSn+QF5guQtO1dCfy0shBPy4jFc=
|
github.com/gin-contrib/gzip v0.0.6/go.mod h1:QOJlmV2xmayAjkNS2Y8NQsMneuRShOU/kjovCXNuzzk=
|
||||||
github.com/gin-contrib/sessions v0.0.4 h1:gq4fNa1Zmp564iHP5G6EBuktilEos8VKhe2sza1KMgo=
|
github.com/gin-contrib/sessions v0.0.4 h1:gq4fNa1Zmp564iHP5G6EBuktilEos8VKhe2sza1KMgo=
|
||||||
github.com/gin-contrib/sessions v0.0.4/go.mod h1:pQ3sIyviBBGcxgyR8mkeJuXbeV3h3NYmhJADQTq5+Vo=
|
github.com/gin-contrib/sessions v0.0.4/go.mod h1:pQ3sIyviBBGcxgyR8mkeJuXbeV3h3NYmhJADQTq5+Vo=
|
||||||
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
|
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
|
||||||
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
|
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
|
||||||
github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M=
|
|
||||||
github.com/gin-gonic/gin v1.7.4/go.mod h1:jD2toBW3GZUr5UMcdrwQA10I7RuaFOl/SGeDjXkfUtY=
|
github.com/gin-gonic/gin v1.7.4/go.mod h1:jD2toBW3GZUr5UMcdrwQA10I7RuaFOl/SGeDjXkfUtY=
|
||||||
|
github.com/gin-gonic/gin v1.8.1/go.mod h1:ji8BvRH1azfM+SYow9zQ6SZMvR8qOMZHmsCuWR9tTTk=
|
||||||
|
github.com/gin-gonic/gin v1.9.0/go.mod h1:W1Me9+hsUSyj3CePGrd1/QrKJMSJ1Tu/0hFEH89961k=
|
||||||
github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg=
|
github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg=
|
||||||
github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU=
|
github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU=
|
||||||
github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q=
|
github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q=
|
||||||
@@ -74,13 +76,13 @@ github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiU
|
|||||||
github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
|
github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
|
||||||
github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY=
|
github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY=
|
||||||
github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
|
github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
|
||||||
github.com/go-openapi/jsonreference v0.19.5 h1:1WJP/wi4OjB4iV8KVbH73rQaoialJrqv8gitZLxGLtM=
|
github.com/go-openapi/jsonreference v0.19.6 h1:UBIxjkht+AWIgYzCDSv2GN+E/togfwXUJFRTWhl2Jjs=
|
||||||
github.com/go-openapi/jsonreference v0.19.5/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg=
|
github.com/go-openapi/jsonreference v0.19.6/go.mod h1:diGHMEHg2IqXZGKxqyvWdfWU/aim5Dprw5bqpKkTvns=
|
||||||
github.com/go-openapi/spec v0.20.3 h1:uH9RQ6vdyPSs2pSy9fL8QPspDF2AMIMPtmK5coSSjtQ=
|
github.com/go-openapi/spec v0.20.4 h1:O8hJrt0UMnhHcluhIdUgCLRWyM2x7QkBXRvOs7m+O1M=
|
||||||
github.com/go-openapi/spec v0.20.3/go.mod h1:gG4F8wdEDN+YPBMVnzE85Rbhf+Th2DTvA9nFPQ5AYEg=
|
github.com/go-openapi/spec v0.20.4/go.mod h1:faYFR1CvsJZ0mNsmsphTMSoRrNV3TEDoAM7FOEWeq8I=
|
||||||
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
|
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
|
||||||
github.com/go-openapi/swag v0.19.14 h1:gm3vOOXfiuw5i9p5N9xJvfjvuofpyvLA9Wr6QfK5Fng=
|
github.com/go-openapi/swag v0.19.15 h1:D2NRCBzS9/pEY3gP9Nl8aDqGUcPFrwG2p+CNFrLyrCM=
|
||||||
github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
|
github.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
|
||||||
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||||
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
|
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
|
||||||
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||||
@@ -92,9 +94,10 @@ github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+
|
|||||||
github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA=
|
github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA=
|
||||||
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
|
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
|
||||||
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
|
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
|
||||||
github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI=
|
|
||||||
github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4=
|
github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4=
|
||||||
github.com/go-playground/validator/v10 v10.8.0/go.mod h1:9JhgTzTaE31GZDpH/HSvHiRJrJ3iKAgqqH0Bl/Ocjdk=
|
github.com/go-playground/validator/v10 v10.8.0/go.mod h1:9JhgTzTaE31GZDpH/HSvHiRJrJ3iKAgqqH0Bl/Ocjdk=
|
||||||
|
github.com/go-playground/validator/v10 v10.10.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos=
|
||||||
|
github.com/go-playground/validator/v10 v10.11.2/go.mod h1:NieE624vt4SCTJtD87arVLvdmjPAeV8BQlHtMnw9D7s=
|
||||||
github.com/go-playground/validator/v10 v10.14.0 h1:vgvQWe3XCz3gIeFDm/HnTIbj6UGmg/+t63MyGU2n5js=
|
github.com/go-playground/validator/v10 v10.14.0 h1:vgvQWe3XCz3gIeFDm/HnTIbj6UGmg/+t63MyGU2n5js=
|
||||||
github.com/go-playground/validator/v10 v10.14.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU=
|
github.com/go-playground/validator/v10 v10.14.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU=
|
||||||
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
||||||
@@ -127,9 +130,10 @@ github.com/gobuffalo/packd v0.1.0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWe
|
|||||||
github.com/gobuffalo/packr/v2 v2.0.9/go.mod h1:emmyGweYTm6Kdper+iywB6YK5YzuKchGtJQZ0Odn4pQ=
|
github.com/gobuffalo/packr/v2 v2.0.9/go.mod h1:emmyGweYTm6Kdper+iywB6YK5YzuKchGtJQZ0Odn4pQ=
|
||||||
github.com/gobuffalo/packr/v2 v2.2.0/go.mod h1:CaAwI0GPIAv+5wKLtv8Afwl+Cm78K/I/VCm/3ptBN+0=
|
github.com/gobuffalo/packr/v2 v2.2.0/go.mod h1:CaAwI0GPIAv+5wKLtv8Afwl+Cm78K/I/VCm/3ptBN+0=
|
||||||
github.com/gobuffalo/syncx v0.0.0-20190224160051-33c29581e754/go.mod h1:HhnNqWY95UYwwW3uSASeV7vtgYkT2t16hJgV3AEPUpw=
|
github.com/gobuffalo/syncx v0.0.0-20190224160051-33c29581e754/go.mod h1:HhnNqWY95UYwwW3uSASeV7vtgYkT2t16hJgV3AEPUpw=
|
||||||
|
github.com/goccy/go-json v0.9.7/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
||||||
|
github.com/goccy/go-json v0.10.0/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
||||||
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
|
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
|
||||||
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
||||||
github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
|
||||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||||
github.com/golang-jwt/jwt/v4 v4.4.3/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
|
github.com/golang-jwt/jwt/v4 v4.4.3/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
|
||||||
github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg=
|
github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg=
|
||||||
@@ -233,6 +237,8 @@ github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJ
|
|||||||
github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE=
|
github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE=
|
||||||
github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0=
|
github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0=
|
||||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||||
|
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
|
||||||
|
github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||||
github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
|
github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
|
||||||
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||||
github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
||||||
@@ -257,6 +263,8 @@ github.com/paulmach/orb v0.7.1/go.mod h1:FWRlTgl88VI1RBx/MkrwWDRhQ96ctqMCh8boXhm
|
|||||||
github.com/paulmach/protoscan v0.2.1/go.mod h1:SpcSwydNLrxUGSDvXvO0P7g7AuhJ7lcKfDlhJCDw2gY=
|
github.com/paulmach/protoscan v0.2.1/go.mod h1:SpcSwydNLrxUGSDvXvO0P7g7AuhJ7lcKfDlhJCDw2gY=
|
||||||
github.com/pelletier/go-toml v1.7.0 h1:7utD74fnzVc/cpcyy8sjrlFr5vYpypUixARcHIMIGuI=
|
github.com/pelletier/go-toml v1.7.0 h1:7utD74fnzVc/cpcyy8sjrlFr5vYpypUixARcHIMIGuI=
|
||||||
github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE=
|
github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE=
|
||||||
|
github.com/pelletier/go-toml/v2 v2.0.1/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo=
|
||||||
|
github.com/pelletier/go-toml/v2 v2.0.6/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek=
|
||||||
github.com/pelletier/go-toml/v2 v2.0.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZR9tGQ=
|
github.com/pelletier/go-toml/v2 v2.0.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZR9tGQ=
|
||||||
github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4=
|
github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4=
|
||||||
github.com/pierrec/lz4 v2.0.5+incompatible h1:2xWsjqPFWcplujydGg4WmhC/6fZqK42wMM8aXeqhl0I=
|
github.com/pierrec/lz4 v2.0.5+incompatible h1:2xWsjqPFWcplujydGg4WmhC/6fZqK42wMM8aXeqhl0I=
|
||||||
@@ -289,7 +297,6 @@ github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdh
|
|||||||
github.com/shirou/gopsutil v2.19.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
|
github.com/shirou/gopsutil v2.19.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
|
||||||
github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
|
github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
|
||||||
github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4/go.mod h1:qsXQc7+bwAM3Q1u/4XEfrquwF8Lw7D7y5cD8CuHnfIc=
|
github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4/go.mod h1:qsXQc7+bwAM3Q1u/4XEfrquwF8Lw7D7y5cD8CuHnfIc=
|
||||||
github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
|
|
||||||
github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8=
|
github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8=
|
||||||
github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
|
github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
|
||||||
github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
|
github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
|
||||||
@@ -318,21 +325,25 @@ github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o
|
|||||||
github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||||
github.com/swaggo/files v0.0.0-20190704085106-630677cd5c14 h1:PyYN9JH5jY9j6av01SpfRMb+1DWg/i3MbGOKPxJ2wjM=
|
github.com/swaggo/files v1.0.1 h1:J1bVJ4XHZNq0I46UU90611i9/YzdrF7x92oX1ig5IdE=
|
||||||
github.com/swaggo/files v0.0.0-20190704085106-630677cd5c14/go.mod h1:gxQT6pBGRuIGunNf/+tSOB5OHvguWi8Tbt82WOkf35E=
|
github.com/swaggo/files v1.0.1/go.mod h1:0qXmMNH6sXNf+73t65aKeB+ApmgxdnkQzVTAj2uaMUg=
|
||||||
github.com/swaggo/gin-swagger v1.3.3 h1:XHyYmeNVFG5PbyWHG4jXtxOm2P4kiZapDCWsyDDiQ/I=
|
github.com/swaggo/gin-swagger v1.6.0 h1:y8sxvQ3E20/RCyrXeFfg60r6H0Z+SwpTjMYsMm+zy8M=
|
||||||
github.com/swaggo/gin-swagger v1.3.3/go.mod h1:ymsZuGpbbu+S7ZoQ49QPpZoDBj6uqhb8WizgQPVgWl0=
|
github.com/swaggo/gin-swagger v1.6.0/go.mod h1:BG00cCEy294xtVpyIAHG6+e2Qzj/xKlRdOqDkvq0uzo=
|
||||||
github.com/swaggo/swag v1.7.4 h1:up+ixy8yOqJKiFcuhMgkuYuF4xnevuhnFAXXF8OSfNg=
|
github.com/swaggo/swag v1.8.12/go.mod h1:lNfm6Gg+oAq3zRJQNEMBE66LIJKM44mxFqhEEgy2its=
|
||||||
github.com/swaggo/swag v1.7.4/go.mod h1:zD8h6h4SPv7t3l+4BKdRquqW1ASWjKZgT6Qv9z3kNqI=
|
github.com/swaggo/swag v1.16.4 h1:clWJtd9LStiG3VeijiCfOVODP6VpHtKdQy9ELFG3s1A=
|
||||||
|
github.com/swaggo/swag v1.16.4/go.mod h1:VBsHJRsDvfYvqoiMKnsdwhNV9LEMHgEDZcyVYX0sxPg=
|
||||||
github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4=
|
github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4=
|
||||||
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
|
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
|
||||||
github.com/tklauser/go-sysconf v0.3.10/go.mod h1:C8XykCvCb+Gn0oNCWPIlcb0RuglQTYaQ2hGm7jmxEFk=
|
github.com/tklauser/go-sysconf v0.3.10/go.mod h1:C8XykCvCb+Gn0oNCWPIlcb0RuglQTYaQ2hGm7jmxEFk=
|
||||||
github.com/tklauser/numcpus v0.4.0/go.mod h1:1+UI3pD8NW14VMwdgJNJ1ESk2UnwhAnz5hMwiKKqXCQ=
|
github.com/tklauser/numcpus v0.4.0/go.mod h1:1+UI3pD8NW14VMwdgJNJ1ESk2UnwhAnz5hMwiKKqXCQ=
|
||||||
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
|
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
|
||||||
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
|
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
|
||||||
github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo=
|
|
||||||
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
|
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
|
||||||
|
github.com/ugorji/go v1.2.7 h1:qYhyWUUd6WbiM+C6JZAUkIJt/1WrjzNHY9+KCIjVqTo=
|
||||||
|
github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M=
|
||||||
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
|
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
|
||||||
|
github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY=
|
||||||
|
github.com/ugorji/go/codec v1.2.9/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
|
||||||
github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU=
|
github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU=
|
||||||
github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
|
github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
|
||||||
github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
|
github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
|
||||||
@@ -365,35 +376,41 @@ golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPh
|
|||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
|
golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU=
|
||||||
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
|
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
|
||||||
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
|
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
|
||||||
golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0=
|
golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0=
|
||||||
golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
|
golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
|
||||||
golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
|
|
||||||
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
|
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
|
||||||
|
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
||||||
|
golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
|
||||||
|
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
|
||||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||||
golang.org/x/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8=
|
|
||||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||||
|
golang.org/x/mod v0.9.0 h1:KENHtAZL2y3NLMYZeHY9DW8HW8V+kQyJsY/V9JlKvCs=
|
||||||
|
golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
|
||||||
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||||
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
|
||||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
|
golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM=
|
||||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||||
|
golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws=
|
||||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||||
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||||
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
|
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
|
||||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||||
golang.org/x/net v0.14.0 h1:BONx9s002vGdD9umnlX1Po8vOZmrgH34qlHcD1MfK14=
|
|
||||||
golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
|
golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
|
||||||
|
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
||||||
|
golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs=
|
||||||
|
golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
|
||||||
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20190412183630-56d357773e84/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190412183630-56d357773e84/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
@@ -415,10 +432,11 @@ golang.org/x/sys v0.0.0-20191220220014-0732a990476f/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210420072515-93ed5bcd2bfe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20211020174200-9d6173849985/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20211020174200-9d6173849985/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220429233432-b5fbb4746d32/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220429233432-b5fbb4746d32/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
@@ -426,19 +444,26 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||||||
golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
|
|
||||||
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
|
golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
|
||||||
|
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
|
golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ=
|
||||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||||
golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
|
golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
|
||||||
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
||||||
golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU=
|
golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU=
|
||||||
golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
|
golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
|
||||||
|
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
|
||||||
|
golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
@@ -446,12 +471,14 @@ golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
|||||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
|
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
|
||||||
|
golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||||
golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||||
golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
|
|
||||||
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||||
|
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||||
|
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20190329151228-23e29df326fe/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
golang.org/x/tools v0.0.0-20190329151228-23e29df326fe/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||||
golang.org/x/tools v0.0.0-20190416151739-9c9e1878f421/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
golang.org/x/tools v0.0.0-20190416151739-9c9e1878f421/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||||
@@ -460,10 +487,10 @@ golang.org/x/tools v0.0.0-20190531172133-b3315ee88b7d/go.mod h1:/rFqwRUd4F7ZHNgw
|
|||||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
|
|
||||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||||
golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM=
|
|
||||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||||
|
golang.org/x/tools v0.7.0 h1:W4OVu8VVOaIO0yzWMNdepAulS7YfoS3Zabrm8DOXXU4=
|
||||||
|
golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s=
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
@@ -471,6 +498,8 @@ golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1N
|
|||||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||||
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||||
|
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||||
|
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||||
google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
|
google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
|
||||||
google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
@@ -488,6 +517,7 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
|||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gorm.io/driver/clickhouse v0.4.2 h1:vt7WkXX0u5SeCDyR4w/Jz0ce25/tYqgoP3UUERgMZmY=
|
gorm.io/driver/clickhouse v0.4.2 h1:vt7WkXX0u5SeCDyR4w/Jz0ce25/tYqgoP3UUERgMZmY=
|
||||||
@@ -506,3 +536,4 @@ gorm.io/gorm v1.25.2-0.20230610234218-206613868439/go.mod h1:L4uxeKpfBml98NYqVqw
|
|||||||
gorm.io/gorm v1.25.5 h1:zR9lOiiYf09VNh5Q1gphfyia1JpiClIWG9hQaxB/mls=
|
gorm.io/gorm v1.25.5 h1:zR9lOiiYf09VNh5Q1gphfyia1JpiClIWG9hQaxB/mls=
|
||||||
gorm.io/gorm v1.25.5/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
|
gorm.io/gorm v1.25.5/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
|
||||||
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
|
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
|
||||||
|
sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8=
|
||||||
|
|||||||
@@ -4,172 +4,51 @@ package config
|
|||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"gopkg.in/yaml.v3"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
// RunMode 列表
|
||||||
// Conf config instance
|
const (
|
||||||
Conf Config
|
RunModeDev RunMode = "dev" // 开发环境
|
||||||
|
RunModeProd RunMode = "pro" // 生产环境
|
||||||
// ModeDev run mode as development
|
|
||||||
ModeDev = "dev"
|
|
||||||
// ModeProd run mode as production
|
|
||||||
ModeProd = "prod"
|
|
||||||
// WorkDir workspace dir
|
|
||||||
WorkDir string
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Mode run mode
|
// RunMode 运行模式
|
||||||
type Mode struct {
|
type RunMode string
|
||||||
Name string `yaml:"name"`
|
|
||||||
EnableHTTP bool `yaml:"enablehttp"`
|
// IsReleaseMode 是否
|
||||||
HTTPPort int `yaml:"httpport"`
|
func (mode RunMode) IsReleaseMode() bool {
|
||||||
EnableGRPC bool `yaml:"enablegrpc"`
|
return mode == RunModeProd
|
||||||
GRPCPort int `yaml:"grpcport"`
|
|
||||||
Host string `yaml:"host"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Database sql database
|
// IsDevMode 是否时开发模式
|
||||||
type Database struct {
|
func (mode RunMode) IsDevMode() bool {
|
||||||
Driver string `yaml:"driver"`
|
return mode == RunModeDev
|
||||||
Source string `yaml:"source"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// General common
|
// IsRunMode 是否是runmode
|
||||||
type General struct {
|
func (mode RunMode) IsRunMode() bool {
|
||||||
PageNum int `yaml:"pagenum"` // 前台每页文章数量
|
return mode == RunModeDev || mode == RunModeProd
|
||||||
PageSize int `yaml:"pagesize"` // 后台每页文章数量
|
|
||||||
StartID int `yaml:"startid"` // 文章启始ID
|
|
||||||
DescPrefix string `yaml:"descprefix"` // 文章描述前缀
|
|
||||||
Identifier string `yaml:"identifier"` // 文章截取标识
|
|
||||||
Length int `yaml:"length"` // 文章预览长度
|
|
||||||
Timezone string `yaml:"timezone"` // 时区
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Disqus comments
|
// WalkWorkDir walk work dir
|
||||||
type Disqus struct {
|
func WalkWorkDir() (string, error) {
|
||||||
ShortName string `yaml:"shortname"`
|
gopath := os.Getenv("GOPATH")
|
||||||
PublicKey string `yaml:"publickey"`
|
workDir, err := os.Getwd()
|
||||||
AccessToken string `yaml:"accesstoken"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Twitter card
|
|
||||||
type Twitter struct {
|
|
||||||
Card string `yaml:"card"`
|
|
||||||
Site string `yaml:"site"`
|
|
||||||
Image string `yaml:"image"`
|
|
||||||
Address string `yaml:"address"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Google analytics
|
|
||||||
type Google struct {
|
|
||||||
URL string `yaml:"url"`
|
|
||||||
Tid string `yaml:"tid"`
|
|
||||||
V string `yaml:"v"`
|
|
||||||
AdSense string `yaml:"adsense"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Qiniu oss
|
|
||||||
type Qiniu struct {
|
|
||||||
Bucket string `yaml:"bucket"`
|
|
||||||
Domain string `yaml:"domain"`
|
|
||||||
AccessKey string `yaml:"accesskey"`
|
|
||||||
SecretKey string `yaml:"secretkey"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// FeedRPC feedr
|
|
||||||
type FeedRPC struct {
|
|
||||||
FeedrURL string `yaml:"feedrurl"`
|
|
||||||
PingRPC []string `yaml:"pingrpc"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Account info
|
|
||||||
type Account struct {
|
|
||||||
Username string `yaml:"username"` // *
|
|
||||||
Password string `yaml:"password"` // *
|
|
||||||
Email string `yaml:"email"`
|
|
||||||
PhoneNumber string `yaml:"phonenumber"`
|
|
||||||
Address string `yaml:"address"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Blogger info
|
|
||||||
type Blogger struct {
|
|
||||||
BlogName string `yaml:"blogname"`
|
|
||||||
SubTitle string `yaml:"subtitle"`
|
|
||||||
BeiAn string `yaml:"beian"`
|
|
||||||
BTitle string `yaml:"btitle"`
|
|
||||||
Copyright string `yaml:"copyright"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// EiBlogApp config
|
|
||||||
type EiBlogApp struct {
|
|
||||||
Mode
|
|
||||||
|
|
||||||
StaticVersion int `yaml:"staticversion"`
|
|
||||||
HotWords []string `yaml:"hotwords"`
|
|
||||||
General General `yaml:"general"`
|
|
||||||
Disqus Disqus `yaml:"disqus"`
|
|
||||||
Google Google `yaml:"google"`
|
|
||||||
Qiniu Qiniu `yaml:"qiniu"`
|
|
||||||
Twitter Twitter `yaml:"twitter"`
|
|
||||||
FeedRPC FeedRPC `yaml:"feedrpc"`
|
|
||||||
Account Account `yaml:"account"`
|
|
||||||
Blogger Blogger `yaml:"blogger"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// BackupApp config
|
|
||||||
type BackupApp struct {
|
|
||||||
Mode
|
|
||||||
|
|
||||||
BackupTo string `yaml:"backupto"`
|
|
||||||
Interval string `yaml:"interval"` // circle backup, default: 7d
|
|
||||||
Validity int `yaml:"validity"` // storage days, default: 60
|
|
||||||
Qiniu Qiniu `yaml:"qiniu"` // qiniu config
|
|
||||||
}
|
|
||||||
|
|
||||||
// Config app config
|
|
||||||
type Config struct {
|
|
||||||
RunMode string `yaml:"runmode"`
|
|
||||||
AppName string `yaml:"appname"`
|
|
||||||
Database Database `yaml:"database"`
|
|
||||||
ESHost string `yaml:"eshost"`
|
|
||||||
EiBlogApp EiBlogApp `yaml:"eiblogapp"`
|
|
||||||
BackupApp BackupApp `yaml:"backupapp"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// load config file
|
|
||||||
func init() {
|
|
||||||
// compatibility linux and windows
|
|
||||||
var err error
|
|
||||||
WorkDir = workDir()
|
|
||||||
path := filepath.Join(WorkDir, "conf", "app.yml")
|
|
||||||
|
|
||||||
data, err := os.ReadFile(path)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
return "", err
|
||||||
}
|
}
|
||||||
err = yaml.Unmarshal(data, &Conf)
|
// find work dir, try 3 times
|
||||||
if err != nil {
|
for gopath != workDir && workDir != "/" {
|
||||||
panic(err)
|
dir := filepath.Join(workDir, "etc")
|
||||||
}
|
|
||||||
// read run mode from env
|
|
||||||
Conf.RunMode = ModeDev
|
|
||||||
if runmode := os.Getenv("RUN_MODE"); runmode == ModeProd {
|
|
||||||
Conf.RunMode = runmode
|
|
||||||
}
|
|
||||||
// read env
|
|
||||||
readDBEnv()
|
|
||||||
}
|
|
||||||
|
|
||||||
func readDBEnv() {
|
_, err := os.Stat(dir)
|
||||||
key := strings.ToUpper(Conf.AppName) + "_DB_DRIVER"
|
if err == nil {
|
||||||
if d := os.Getenv(key); d != "" {
|
break
|
||||||
Conf.Database.Driver = d
|
}
|
||||||
}
|
if !os.IsNotExist(err) {
|
||||||
key = strings.ToUpper(Conf.AppName) + "_DB_SOURCE"
|
return "", err
|
||||||
if s := os.Getenv(key); s != "" {
|
}
|
||||||
Conf.Database.Source = s
|
workDir = filepath.Dir(workDir)
|
||||||
}
|
}
|
||||||
|
return workDir, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,29 +0,0 @@
|
|||||||
// +build !prod
|
|
||||||
|
|
||||||
// Package config provides ...
|
|
||||||
package config
|
|
||||||
|
|
||||||
import (
|
|
||||||
"os"
|
|
||||||
"path"
|
|
||||||
"path/filepath"
|
|
||||||
)
|
|
||||||
|
|
||||||
// workDir recognize workspace dir
|
|
||||||
var workDir = func() string {
|
|
||||||
wd, err := os.Getwd()
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
for wd != "" {
|
|
||||||
name := filepath.Join(wd, "conf")
|
|
||||||
_, err := os.Stat(name)
|
|
||||||
if err != nil {
|
|
||||||
dir, _ := path.Split(wd)
|
|
||||||
wd = path.Clean(dir)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
return wd
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
124
pkg/config/enums.go
Normal file
124
pkg/config/enums.go
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
// APIMode 应用配置
|
||||||
|
type APIMode struct {
|
||||||
|
// 运行模式,可根据不同模式做相关判断,如日志打印等
|
||||||
|
RunMode RunMode
|
||||||
|
|
||||||
|
// 服务名称,如 eiblog, backup
|
||||||
|
Name string
|
||||||
|
// 监听地址,如 0.0.0.0:9000
|
||||||
|
Listen string
|
||||||
|
// 所属域名,如 deepzz.com
|
||||||
|
Host string
|
||||||
|
// 一般的应用都会有个密钥,可以用这个字段
|
||||||
|
Secret string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Database 数据库配置
|
||||||
|
type Database struct {
|
||||||
|
// 数据库驱动,如 sqlite, mysql, postgres 等
|
||||||
|
Driver string
|
||||||
|
// 数据库连接字符串,如
|
||||||
|
// sqlite:./db.sqlite
|
||||||
|
// mysql:root:123456@tcp(127.0.0.1:3306)/eiblog?charset=utf8mb4&parseTime=True&loc=Local
|
||||||
|
Source string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Disqus 评论配置
|
||||||
|
type Disqus struct {
|
||||||
|
// 短名称,如 deepzz
|
||||||
|
ShortName string
|
||||||
|
// 公共密钥 wdSgxRm9rdGAlLKFcFdToBe3GT4SibmV7Y8EjJQ0r4GWXeKtxpopMAeIeoI2dTEg
|
||||||
|
PublicKey string
|
||||||
|
// 访问令牌, 需自行创建
|
||||||
|
AccessToken string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Twitter 社交配置
|
||||||
|
type Twitter struct {
|
||||||
|
// 卡片, 可选 summary, summary_large_image, player
|
||||||
|
Card string
|
||||||
|
// id号, 如 deepzz02
|
||||||
|
Site string
|
||||||
|
// 图片, 如 st.deepzz.cn/static/img/avatar.jpg
|
||||||
|
Image string
|
||||||
|
// 地址, 如 twitter.com/deepzz02
|
||||||
|
Address string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Google 分析配置
|
||||||
|
type Google struct {
|
||||||
|
// url, 如 https://www.google-analytics.com/g/collect
|
||||||
|
URL string
|
||||||
|
// tid, 如 G-S085VRC5PF
|
||||||
|
Tid string
|
||||||
|
// v, 如 "2"
|
||||||
|
V string
|
||||||
|
// 如果开启广发, 配置 <script async src="xxx" crossorigin="anonymous"></script>
|
||||||
|
AdSense string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Qiniu 对象存储配置
|
||||||
|
type Qiniu struct {
|
||||||
|
// bucket, 如 eiblog
|
||||||
|
Bucket string
|
||||||
|
// domain, 如 st.deepzz.cn
|
||||||
|
Domain string
|
||||||
|
// accesskey, 如 1234567890
|
||||||
|
AccessKey string
|
||||||
|
// secretkey, 如 1234567890
|
||||||
|
SecretKey string
|
||||||
|
}
|
||||||
|
|
||||||
|
// FeedRPC 订阅配置
|
||||||
|
type FeedRPC struct {
|
||||||
|
// feedrurl, 如 https://deepzz.superfeedr.com/
|
||||||
|
FeedrURL string
|
||||||
|
// pingrpc, 如 http://ping.baidu.com/ping/RPC2, http://rpc.pingomatic.com/
|
||||||
|
PingRPC []string
|
||||||
|
}
|
||||||
|
|
||||||
|
// General 博客通用配置
|
||||||
|
type General struct {
|
||||||
|
// 前台每页文章数量, 一般配置为 10
|
||||||
|
PageNum int
|
||||||
|
// 后台每页文章数量, 一般配置为 20
|
||||||
|
PageSize int
|
||||||
|
// 文章描述前缀, 一般配置为 Desc:
|
||||||
|
DescPrefix string
|
||||||
|
// 文章截取标识, 一般配置为 <!--more-->
|
||||||
|
Identifier string
|
||||||
|
// 文章预览长度, 一般配置为 400
|
||||||
|
Length int
|
||||||
|
// 时区, 一般配置为 Asia/Shanghai
|
||||||
|
Timezone string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Account 账户配置
|
||||||
|
type Account struct {
|
||||||
|
// *必须配置, 后台登录用户名
|
||||||
|
Username string
|
||||||
|
// *必须配置, 后台登录密码。登录后请后台立即修改
|
||||||
|
Password string
|
||||||
|
// 邮箱, 用于显示
|
||||||
|
Email string
|
||||||
|
// 手机号, 用于显示
|
||||||
|
PhoneNumber string
|
||||||
|
// 地址, 用于显示
|
||||||
|
Address string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Blogger 博客配置, 无需配置,程序默认初始化,可在后台更改
|
||||||
|
type Blogger struct {
|
||||||
|
// 博客名称, 如 deepzz
|
||||||
|
BlogName string
|
||||||
|
// 格言, 如 Rome was not built in one day.
|
||||||
|
SubTitle string
|
||||||
|
// 备案号, 不填则不显示在网站底部, 如 蜀ICP备xxxxxxxx号-1
|
||||||
|
BeiAn string
|
||||||
|
// 标题, 如 deepzz's Blog
|
||||||
|
BTitle string
|
||||||
|
// 版权, 如 本站使用「<a href="//creativecommons.org/licenses/by/4.0/">署名 4.0 国际</a>」创作共享协议,转载请注明作者及原网址。
|
||||||
|
Copyright string // 版权
|
||||||
|
}
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
// +build prod
|
|
||||||
|
|
||||||
// Package config provides ...
|
|
||||||
package config
|
|
||||||
|
|
||||||
// workDir production use current dir
|
|
||||||
var workDir = func() string { return "" }
|
|
||||||
46
pkg/connector/db/db.go
Normal file
46
pkg/connector/db/db.go
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
package db
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"net/url"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/eiblog/eiblog/pkg/config"
|
||||||
|
|
||||||
|
"go.mongodb.org/mongo-driver/mongo"
|
||||||
|
"go.mongodb.org/mongo-driver/mongo/options"
|
||||||
|
"go.mongodb.org/mongo-driver/mongo/readpref"
|
||||||
|
)
|
||||||
|
|
||||||
|
// NewMDB new mongodb
|
||||||
|
// https://docs.mongodb.com/manual/reference/connection-string/
|
||||||
|
// mongodb://db0.example.com,db1.example.com,db2.example.com/dbname?replicaSet=myRepl&w=majority&wtimeoutMS=5000
|
||||||
|
func NewMDB(opts config.Database) (*mongo.Database, error) {
|
||||||
|
if opts.Driver != "mongodb" {
|
||||||
|
return nil, errors.New("db: driver must be mongodb, but " + opts.Driver)
|
||||||
|
}
|
||||||
|
u, err := url.Parse(opts.Source)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.New("db: " + err.Error())
|
||||||
|
}
|
||||||
|
database := u.Path
|
||||||
|
if database == "" {
|
||||||
|
return nil, errors.New("db: please specify a database")
|
||||||
|
}
|
||||||
|
database = database[1:]
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), time.Second*2)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
// remove database
|
||||||
|
u.Path = ""
|
||||||
|
client, err := mongo.Connect(ctx, options.Client().ApplyURI(u.String()))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
err = client.Ping(ctx, readpref.Primary())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return client.Database(database), nil
|
||||||
|
}
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
// Package backup provides ...
|
|
||||||
package backup
|
|
||||||
|
|
||||||
// @title APP Demo API
|
|
||||||
// @version 1.0
|
|
||||||
// @description This is a sample server celler server.
|
|
||||||
|
|
||||||
// @BasePath /api
|
|
||||||
@@ -1,80 +0,0 @@
|
|||||||
// Package docs GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
|
|
||||||
// This file was generated by swaggo/swag
|
|
||||||
package docs
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding/json"
|
|
||||||
"strings"
|
|
||||||
"text/template"
|
|
||||||
|
|
||||||
"github.com/swaggo/swag"
|
|
||||||
)
|
|
||||||
|
|
||||||
var doc = `{
|
|
||||||
"schemes": {{ marshal .Schemes }},
|
|
||||||
"swagger": "2.0",
|
|
||||||
"info": {
|
|
||||||
"description": "{{escape .Description}}",
|
|
||||||
"title": "{{.Title}}",
|
|
||||||
"contact": {},
|
|
||||||
"version": "{{.Version}}"
|
|
||||||
},
|
|
||||||
"host": "{{.Host}}",
|
|
||||||
"basePath": "{{.BasePath}}",
|
|
||||||
"paths": {}
|
|
||||||
}`
|
|
||||||
|
|
||||||
type swaggerInfo struct {
|
|
||||||
Version string
|
|
||||||
Host string
|
|
||||||
BasePath string
|
|
||||||
Schemes []string
|
|
||||||
Title string
|
|
||||||
Description string
|
|
||||||
}
|
|
||||||
|
|
||||||
// SwaggerInfo holds exported Swagger Info so clients can modify it
|
|
||||||
var SwaggerInfo = swaggerInfo{
|
|
||||||
Version: "1.0",
|
|
||||||
Host: "",
|
|
||||||
BasePath: "/api",
|
|
||||||
Schemes: []string{},
|
|
||||||
Title: "APP Demo API",
|
|
||||||
Description: "This is a sample server celler server.",
|
|
||||||
}
|
|
||||||
|
|
||||||
type s struct{}
|
|
||||||
|
|
||||||
func (s *s) ReadDoc() string {
|
|
||||||
sInfo := SwaggerInfo
|
|
||||||
sInfo.Description = strings.Replace(sInfo.Description, "\n", "\\n", -1)
|
|
||||||
|
|
||||||
t, err := template.New("swagger_info").Funcs(template.FuncMap{
|
|
||||||
"marshal": func(v interface{}) string {
|
|
||||||
a, _ := json.Marshal(v)
|
|
||||||
return string(a)
|
|
||||||
},
|
|
||||||
"escape": func(v interface{}) string {
|
|
||||||
// escape tabs
|
|
||||||
str := strings.Replace(v.(string), "\t", "\\t", -1)
|
|
||||||
// replace " with \", and if that results in \\", replace that with \\\"
|
|
||||||
str = strings.Replace(str, "\"", "\\\"", -1)
|
|
||||||
return strings.Replace(str, "\\\\\"", "\\\\\\\"", -1)
|
|
||||||
},
|
|
||||||
}).Parse(doc)
|
|
||||||
if err != nil {
|
|
||||||
return doc
|
|
||||||
}
|
|
||||||
|
|
||||||
var tpl bytes.Buffer
|
|
||||||
if err := t.Execute(&tpl, sInfo); err != nil {
|
|
||||||
return doc
|
|
||||||
}
|
|
||||||
|
|
||||||
return tpl.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
swag.Register(swag.Name, &s{})
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
{
|
|
||||||
"swagger": "2.0",
|
|
||||||
"info": {
|
|
||||||
"description": "This is a sample server celler server.",
|
|
||||||
"title": "APP Demo API",
|
|
||||||
"contact": {},
|
|
||||||
"version": "1.0"
|
|
||||||
},
|
|
||||||
"basePath": "/api",
|
|
||||||
"paths": {}
|
|
||||||
}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
basePath: /api
|
|
||||||
info:
|
|
||||||
contact: {}
|
|
||||||
description: This is a sample server celler server.
|
|
||||||
title: APP Demo API
|
|
||||||
version: "1.0"
|
|
||||||
paths: {}
|
|
||||||
swagger: "2.0"
|
|
||||||
@@ -1,56 +0,0 @@
|
|||||||
// Package eiblog provides ...
|
|
||||||
package eiblog
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/http"
|
|
||||||
|
|
||||||
"github.com/gin-contrib/sessions"
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
)
|
|
||||||
|
|
||||||
// @title APP Demo API
|
|
||||||
// @version 1.0
|
|
||||||
// @description This is a sample server celler server.
|
|
||||||
|
|
||||||
// @BasePath /api
|
|
||||||
|
|
||||||
// AuthFilter auth filter
|
|
||||||
func AuthFilter(c *gin.Context) {
|
|
||||||
if !IsLogined(c) {
|
|
||||||
c.Abort()
|
|
||||||
c.Status(http.StatusUnauthorized)
|
|
||||||
c.Redirect(http.StatusFound, "/admin/login")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
c.Next()
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetLogin login user
|
|
||||||
func SetLogin(c *gin.Context, username string) {
|
|
||||||
session := sessions.Default(c)
|
|
||||||
session.Set("username", username)
|
|
||||||
session.Save()
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetLogout logout user
|
|
||||||
func SetLogout(c *gin.Context) {
|
|
||||||
session := sessions.Default(c)
|
|
||||||
session.Delete("username")
|
|
||||||
session.Save()
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsLogined account logined
|
|
||||||
func IsLogined(c *gin.Context) bool {
|
|
||||||
return GetUsername(c) != ""
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetUsername get logined account
|
|
||||||
func GetUsername(c *gin.Context) string {
|
|
||||||
session := sessions.Default(c)
|
|
||||||
username := session.Get("username")
|
|
||||||
if username == nil {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
return username.(string)
|
|
||||||
}
|
|
||||||
@@ -1,80 +0,0 @@
|
|||||||
// Package docs GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
|
|
||||||
// This file was generated by swaggo/swag
|
|
||||||
package docs
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding/json"
|
|
||||||
"strings"
|
|
||||||
"text/template"
|
|
||||||
|
|
||||||
"github.com/swaggo/swag"
|
|
||||||
)
|
|
||||||
|
|
||||||
var doc = `{
|
|
||||||
"schemes": {{ marshal .Schemes }},
|
|
||||||
"swagger": "2.0",
|
|
||||||
"info": {
|
|
||||||
"description": "{{escape .Description}}",
|
|
||||||
"title": "{{.Title}}",
|
|
||||||
"contact": {},
|
|
||||||
"version": "{{.Version}}"
|
|
||||||
},
|
|
||||||
"host": "{{.Host}}",
|
|
||||||
"basePath": "{{.BasePath}}",
|
|
||||||
"paths": {}
|
|
||||||
}`
|
|
||||||
|
|
||||||
type swaggerInfo struct {
|
|
||||||
Version string
|
|
||||||
Host string
|
|
||||||
BasePath string
|
|
||||||
Schemes []string
|
|
||||||
Title string
|
|
||||||
Description string
|
|
||||||
}
|
|
||||||
|
|
||||||
// SwaggerInfo holds exported Swagger Info so clients can modify it
|
|
||||||
var SwaggerInfo = swaggerInfo{
|
|
||||||
Version: "1.0",
|
|
||||||
Host: "",
|
|
||||||
BasePath: "/api",
|
|
||||||
Schemes: []string{},
|
|
||||||
Title: "APP Demo API",
|
|
||||||
Description: "This is a sample server celler server.",
|
|
||||||
}
|
|
||||||
|
|
||||||
type s struct{}
|
|
||||||
|
|
||||||
func (s *s) ReadDoc() string {
|
|
||||||
sInfo := SwaggerInfo
|
|
||||||
sInfo.Description = strings.Replace(sInfo.Description, "\n", "\\n", -1)
|
|
||||||
|
|
||||||
t, err := template.New("swagger_info").Funcs(template.FuncMap{
|
|
||||||
"marshal": func(v interface{}) string {
|
|
||||||
a, _ := json.Marshal(v)
|
|
||||||
return string(a)
|
|
||||||
},
|
|
||||||
"escape": func(v interface{}) string {
|
|
||||||
// escape tabs
|
|
||||||
str := strings.Replace(v.(string), "\t", "\\t", -1)
|
|
||||||
// replace " with \", and if that results in \\", replace that with \\\"
|
|
||||||
str = strings.Replace(str, "\"", "\\\"", -1)
|
|
||||||
return strings.Replace(str, "\\\\\"", "\\\\\\\"", -1)
|
|
||||||
},
|
|
||||||
}).Parse(doc)
|
|
||||||
if err != nil {
|
|
||||||
return doc
|
|
||||||
}
|
|
||||||
|
|
||||||
var tpl bytes.Buffer
|
|
||||||
if err := t.Execute(&tpl, sInfo); err != nil {
|
|
||||||
return doc
|
|
||||||
}
|
|
||||||
|
|
||||||
return tpl.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
swag.Register(swag.Name, &s{})
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
{
|
|
||||||
"swagger": "2.0",
|
|
||||||
"info": {
|
|
||||||
"description": "This is a sample server celler server.",
|
|
||||||
"title": "APP Demo API",
|
|
||||||
"contact": {},
|
|
||||||
"version": "1.0"
|
|
||||||
},
|
|
||||||
"basePath": "/api",
|
|
||||||
"paths": {}
|
|
||||||
}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
basePath: /api
|
|
||||||
info:
|
|
||||||
contact: {}
|
|
||||||
description: This is a sample server celler server.
|
|
||||||
title: APP Demo API
|
|
||||||
version: "1.0"
|
|
||||||
paths: {}
|
|
||||||
swagger: "2.0"
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
# Changelog
|
|
||||||
|
|
||||||
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
|
||||||
|
|
||||||
### [2.2.17](https://github.com/eiblog/eiblog/compare/v2.2.16...v2.2.17) (2025-04-22)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* backup file auto delete ([0fe849a](https://github.com/eiblog/eiblog/commit/0fe849ae67de36f2d249e3306ac7d098bc057070))
|
|
||||||
@@ -1,139 +0,0 @@
|
|||||||
// Package internal provides ...
|
|
||||||
package internal
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"crypto/tls"
|
|
||||||
"fmt"
|
|
||||||
"net"
|
|
||||||
"net/http"
|
|
||||||
"net/url"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
var httpClient = &http.Client{
|
|
||||||
Transport: &http.Transport{
|
|
||||||
Proxy: http.ProxyFromEnvironment,
|
|
||||||
DialContext: (&net.Dialer{
|
|
||||||
Timeout: 30 * time.Second,
|
|
||||||
KeepAlive: 30 * time.Second,
|
|
||||||
DualStack: true,
|
|
||||||
}).DialContext,
|
|
||||||
ForceAttemptHTTP2: true,
|
|
||||||
MaxIdleConns: 100,
|
|
||||||
IdleConnTimeout: 90 * time.Second,
|
|
||||||
TLSHandshakeTimeout: 10 * time.Second,
|
|
||||||
ExpectContinueTimeout: 1 * time.Second,
|
|
||||||
TLSClientConfig: &tls.Config{
|
|
||||||
InsecureSkipVerify: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func newRequest(method, rawurl string, data interface{}) (*http.Request, error) {
|
|
||||||
u, err := url.Parse(rawurl)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
originHost := u.Host
|
|
||||||
// 获取主机IP
|
|
||||||
host, port, err := net.SplitHostPort(u.Host)
|
|
||||||
if err != nil {
|
|
||||||
addrErr := err.(*net.AddrError)
|
|
||||||
if addrErr.Err != "missing port in address" {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
// set default value
|
|
||||||
host = originHost
|
|
||||||
switch u.Scheme {
|
|
||||||
case "http":
|
|
||||||
port = "80"
|
|
||||||
case "https":
|
|
||||||
port = "443"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ips, err := net.LookupHost(host)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if len(ips) == 0 {
|
|
||||||
return nil, fmt.Errorf("http: not found ip(%s)", u.Host)
|
|
||||||
}
|
|
||||||
host = net.JoinHostPort(ips[0], port)
|
|
||||||
u.Host = host
|
|
||||||
// 创建HTTP Request
|
|
||||||
var req *http.Request
|
|
||||||
switch raw := data.(type) {
|
|
||||||
case url.Values:
|
|
||||||
req, err = http.NewRequest(method, u.String(),
|
|
||||||
strings.NewReader(raw.Encode()))
|
|
||||||
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
|
||||||
case []byte:
|
|
||||||
req, err = http.NewRequest(method, u.String(),
|
|
||||||
bytes.NewReader(raw))
|
|
||||||
case nil:
|
|
||||||
req, err = http.NewRequest(method, u.String(), nil)
|
|
||||||
default:
|
|
||||||
return nil, fmt.Errorf("http: unsupported data type: %T", data)
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
// 设置Host
|
|
||||||
req.Host = originHost
|
|
||||||
return req, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// httpHead HTTP HEAD请求
|
|
||||||
func httpHead(rawurl string) (*http.Response, error) {
|
|
||||||
req, err := newRequest(http.MethodHead, rawurl, nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return httpClient.Do(req)
|
|
||||||
}
|
|
||||||
|
|
||||||
// httpGet HTTP GET请求
|
|
||||||
func httpGet(rawurl string) (*http.Response, error) {
|
|
||||||
req, err := newRequest(http.MethodGet, rawurl, nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
// 发起请求
|
|
||||||
return httpClient.Do(req)
|
|
||||||
}
|
|
||||||
|
|
||||||
// httpPost HTTP POST请求, 自动识别是否是form
|
|
||||||
func httpPost(rawurl string, data interface{}) (*http.Response, error) {
|
|
||||||
req, err := newRequest(http.MethodPost, rawurl, data)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
// 发起请求
|
|
||||||
return httpClient.Do(req)
|
|
||||||
}
|
|
||||||
|
|
||||||
// httpPostHeader HTTP POST请求,自定义Header
|
|
||||||
func httpPostHeader(rawurl string, data interface{},
|
|
||||||
header http.Header) (*http.Response, error) {
|
|
||||||
|
|
||||||
req, err := newRequest(http.MethodPost, rawurl, data)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
// set header
|
|
||||||
req.Header = header
|
|
||||||
// 发起请求
|
|
||||||
return httpClient.Do(req)
|
|
||||||
}
|
|
||||||
|
|
||||||
// httpPut HTTP PUT请求
|
|
||||||
func httpPut(rawurl string, data interface{}) (*http.Response, error) {
|
|
||||||
req, err := newRequest(http.MethodPut, rawurl, data)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
// 发起请求
|
|
||||||
return httpClient.Do(req)
|
|
||||||
}
|
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
// Package mid provides ...
|
|
||||||
package mid
|
|
||||||
|
|
||||||
import (
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
)
|
|
||||||
|
|
||||||
// LangOpts 语言选项
|
|
||||||
type LangOpts struct {
|
|
||||||
CookieName string
|
|
||||||
Default string
|
|
||||||
Supported []string
|
|
||||||
}
|
|
||||||
|
|
||||||
// isExist language
|
|
||||||
func (opts LangOpts) isExist(l string) bool {
|
|
||||||
for _, v := range opts.Supported {
|
|
||||||
if v == l {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// LangMiddleware set language
|
|
||||||
func LangMiddleware(opts LangOpts) gin.HandlerFunc {
|
|
||||||
return func(c *gin.Context) {
|
|
||||||
lang, err := c.Cookie(opts.CookieName)
|
|
||||||
// found cookie
|
|
||||||
if err == nil {
|
|
||||||
c.Set(opts.CookieName, lang)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// set cookie
|
|
||||||
al := strings.ToLower(c.GetHeader("Accept-Language"))
|
|
||||||
if al != "" {
|
|
||||||
// choose default if not supported
|
|
||||||
lang = opts.Default
|
|
||||||
|
|
||||||
langs := strings.Split(al, ",")
|
|
||||||
for _, v := range langs {
|
|
||||||
if opts.isExist(v) {
|
|
||||||
lang = v
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
lang = opts.Default
|
|
||||||
}
|
|
||||||
c.SetCookie(opts.CookieName, lang, 86400*365, "/", "", false, false)
|
|
||||||
c.Set(opts.CookieName, lang)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
// Package mid provides ...
|
|
||||||
package mid
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/gin-contrib/sessions"
|
|
||||||
"github.com/gin-contrib/sessions/cookie"
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
)
|
|
||||||
|
|
||||||
// SessionOpts 设置选项
|
|
||||||
type SessionOpts struct {
|
|
||||||
Name string
|
|
||||||
Secure bool // required
|
|
||||||
Secret []byte // required
|
|
||||||
// redis store
|
|
||||||
RedisAddr string
|
|
||||||
RedisPwd string
|
|
||||||
}
|
|
||||||
|
|
||||||
// SessionMiddleware session中间件
|
|
||||||
func SessionMiddleware(opts SessionOpts) gin.HandlerFunc {
|
|
||||||
store := cookie.NewStore(opts.Secret)
|
|
||||||
store.Options(sessions.Options{
|
|
||||||
MaxAge: 86400 * 30,
|
|
||||||
Path: "/",
|
|
||||||
Secure: opts.Secure,
|
|
||||||
HttpOnly: true,
|
|
||||||
})
|
|
||||||
name := "SESSIONID"
|
|
||||||
if opts.Name != "" {
|
|
||||||
name = opts.Name
|
|
||||||
}
|
|
||||||
return sessions.Sessions(name, store)
|
|
||||||
}
|
|
||||||
18
pkg/mid/u.go
18
pkg/mid/u.go
@@ -1,18 +0,0 @@
|
|||||||
// Package mid provides ...
|
|
||||||
package mid
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
uuid "github.com/satori/go.uuid"
|
|
||||||
)
|
|
||||||
|
|
||||||
// UserMiddleware 用户cookie标记
|
|
||||||
func UserMiddleware() gin.HandlerFunc {
|
|
||||||
return func(c *gin.Context) {
|
|
||||||
cookie, err := c.Cookie("u")
|
|
||||||
if err != nil || cookie == "" {
|
|
||||||
u1 := uuid.NewV4().String()
|
|
||||||
c.SetCookie("u", u1, 86400*730, "/", "", true, true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
88
pkg/middleware/session.go
Normal file
88
pkg/middleware/session.go
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
package middleware
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/gin-contrib/sessions"
|
||||||
|
"github.com/gin-contrib/sessions/cookie"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
uuid "github.com/satori/go.uuid"
|
||||||
|
)
|
||||||
|
|
||||||
|
// SessionOpts 设置选项
|
||||||
|
type SessionOpts struct {
|
||||||
|
Name string
|
||||||
|
Secure bool // required
|
||||||
|
Secret []byte // required
|
||||||
|
// redis store
|
||||||
|
RedisAddr string
|
||||||
|
RedisPwd string
|
||||||
|
}
|
||||||
|
|
||||||
|
// SessionMiddleware session中间件
|
||||||
|
func SessionMiddleware(opts SessionOpts) gin.HandlerFunc {
|
||||||
|
store := cookie.NewStore(opts.Secret)
|
||||||
|
store.Options(sessions.Options{
|
||||||
|
MaxAge: 86400 * 30,
|
||||||
|
Path: "/",
|
||||||
|
Secure: opts.Secure,
|
||||||
|
HttpOnly: true,
|
||||||
|
})
|
||||||
|
name := "SESSIONID"
|
||||||
|
if opts.Name != "" {
|
||||||
|
name = opts.Name
|
||||||
|
}
|
||||||
|
return sessions.Sessions(name, store)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UserMiddleware 用户cookie标记
|
||||||
|
func UserMiddleware() gin.HandlerFunc {
|
||||||
|
return func(c *gin.Context) {
|
||||||
|
cookie, err := c.Cookie("u")
|
||||||
|
if err != nil || cookie == "" {
|
||||||
|
u1 := uuid.NewV4().String()
|
||||||
|
c.SetCookie("u", u1, 86400*730, "/", "", true, true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AuthFilter auth filter
|
||||||
|
func AuthFilter(c *gin.Context) {
|
||||||
|
if !IsLogined(c) {
|
||||||
|
c.Abort()
|
||||||
|
c.Status(http.StatusUnauthorized)
|
||||||
|
c.Redirect(http.StatusFound, "/admin/login")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Next()
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLogin login user
|
||||||
|
func SetLogin(c *gin.Context, username string) {
|
||||||
|
session := sessions.Default(c)
|
||||||
|
session.Set("username", username)
|
||||||
|
session.Save()
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLogout logout user
|
||||||
|
func SetLogout(c *gin.Context) {
|
||||||
|
session := sessions.Default(c)
|
||||||
|
session.Delete("username")
|
||||||
|
session.Save()
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsLogined account logined
|
||||||
|
func IsLogined(c *gin.Context) bool {
|
||||||
|
return GetUsername(c) != ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetUsername get logined account
|
||||||
|
func GetUsername(c *gin.Context) string {
|
||||||
|
session := sessions.Default(c)
|
||||||
|
username := session.Get("username")
|
||||||
|
if username == nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return username.(string)
|
||||||
|
}
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
// Package internal provides ...
|
package disqus
|
||||||
package internal
|
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
@@ -26,13 +25,19 @@ const (
|
|||||||
disqusAPIKey = "E8Uh5l5fHZ6gD8U3KycjAIAk46f68Zw7C6eW8WSjZvCLXebZ7p0r1yrYDrLilk2F"
|
disqusAPIKey = "E8Uh5l5fHZ6gD8U3KycjAIAk46f68Zw7C6eW8WSjZvCLXebZ7p0r1yrYDrLilk2F"
|
||||||
)
|
)
|
||||||
|
|
||||||
func checkDisqusConfig() error {
|
// DisqusClient disqus client
|
||||||
if config.Conf.EiBlogApp.Disqus.ShortName != "" &&
|
type DisqusClient struct {
|
||||||
config.Conf.EiBlogApp.Disqus.PublicKey != "" &&
|
Host string
|
||||||
config.Conf.EiBlogApp.Disqus.AccessToken != "" {
|
|
||||||
return nil
|
Conf config.Disqus
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewDisqusClient new disqus client
|
||||||
|
func NewDisqusClient(host string, conf config.Disqus) (*DisqusClient, error) {
|
||||||
|
if conf.ShortName == "" || conf.PublicKey == "" || conf.AccessToken == "" {
|
||||||
|
return nil, errors.New("disqus: config incompleted")
|
||||||
}
|
}
|
||||||
return errors.New("disqus: config incompleted")
|
return &DisqusClient{Host: host, Conf: conf}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// postsCountResp 评论数量响应
|
// postsCountResp 评论数量响应
|
||||||
@@ -46,14 +51,10 @@ type postsCountResp struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// PostsCount 获取文章评论数量
|
// PostsCount 获取文章评论数量
|
||||||
func PostsCount(articles map[string]*model.Article) error {
|
func (cli *DisqusClient) PostsCount(articles map[string]*model.Article) error {
|
||||||
if err := checkDisqusConfig(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
vals := url.Values{}
|
vals := url.Values{}
|
||||||
vals.Set("api_key", config.Conf.EiBlogApp.Disqus.PublicKey)
|
vals.Set("api_key", cli.Conf.PublicKey)
|
||||||
vals.Set("forum", config.Conf.EiBlogApp.Disqus.ShortName)
|
vals.Set("forum", cli.Conf.ShortName)
|
||||||
// batch get
|
// batch get
|
||||||
var count, index int
|
var count, index int
|
||||||
for _, article := range articles {
|
for _, article := range articles {
|
||||||
@@ -65,7 +66,7 @@ func PostsCount(articles map[string]*model.Article) error {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
count = 0
|
count = 0
|
||||||
resp, err := httpGet(apiPostsCount + "?" + vals.Encode())
|
resp, err := http.DefaultClient.Get(apiPostsCount + "?" + vals.Encode())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -127,20 +128,16 @@ type postDetail struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// PostsList 评论列表
|
// PostsList 评论列表
|
||||||
func PostsList(article *model.Article, cursor string) (*PostsListResp, error) {
|
func (cli *DisqusClient) PostsList(article *model.Article, cursor string) (*PostsListResp, error) {
|
||||||
if err := checkDisqusConfig(); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
vals := url.Values{}
|
vals := url.Values{}
|
||||||
vals.Set("api_key", disqusAPIKey)
|
vals.Set("api_key", disqusAPIKey)
|
||||||
vals.Set("forum", config.Conf.EiBlogApp.Disqus.ShortName)
|
vals.Set("forum", cli.Conf.ShortName)
|
||||||
vals.Set("thread:ident", "post-"+article.Slug)
|
vals.Set("thread:ident", "post-"+article.Slug)
|
||||||
vals.Set("cursor", cursor)
|
vals.Set("cursor", cursor)
|
||||||
vals.Set("order", "popular")
|
vals.Set("order", "popular")
|
||||||
vals.Set("limit", "50")
|
vals.Set("limit", "50")
|
||||||
|
|
||||||
resp, err := httpGet(apiPostsList + "?" + vals.Encode())
|
resp, err := http.DefaultClient.Get(apiPostsList + "?" + vals.Encode())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -181,10 +178,7 @@ type PostCreateResp struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// PostCreate 评论文章
|
// PostCreate 评论文章
|
||||||
func PostCreate(pc *PostComment) (*PostCreateResp, error) {
|
func (cli *DisqusClient) PostCreate(pc *PostComment) (*PostCreateResp, error) {
|
||||||
if err := checkDisqusConfig(); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
vals := url.Values{}
|
vals := url.Values{}
|
||||||
vals.Set("api_key", disqusAPIKey)
|
vals.Set("api_key", disqusAPIKey)
|
||||||
vals.Set("message", pc.Message)
|
vals.Set("message", pc.Message)
|
||||||
@@ -194,8 +188,14 @@ func PostCreate(pc *PostComment) (*PostCreateResp, error) {
|
|||||||
vals.Set("author_name", pc.AuthorName)
|
vals.Set("author_name", pc.AuthorName)
|
||||||
// vals.Set("state", "approved")
|
// vals.Set("state", "approved")
|
||||||
|
|
||||||
header := http.Header{"Referer": {"https://disqus.com"}}
|
req, err := http.NewRequest(http.MethodPost, apiPostCreate, strings.NewReader(vals.Encode()))
|
||||||
resp, err := httpPostHeader(apiPostCreate, vals, header)
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||||
|
req.Header.Set("Referer", "https://disqus.com")
|
||||||
|
|
||||||
|
resp, err := http.DefaultClient.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -225,18 +225,19 @@ type approvedResp struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// PostApprove 批准评论
|
// PostApprove 批准评论
|
||||||
func PostApprove(post string) error {
|
func (cli *DisqusClient) PostApprove(post string) error {
|
||||||
if err := checkDisqusConfig(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
vals := url.Values{}
|
vals := url.Values{}
|
||||||
vals.Set("api_key", config.Conf.EiBlogApp.Disqus.PublicKey)
|
vals.Set("api_key", disqusAPIKey)
|
||||||
vals.Set("access_token", config.Conf.EiBlogApp.Disqus.AccessToken)
|
vals.Set("access_token", cli.Conf.AccessToken)
|
||||||
vals.Set("post", post)
|
vals.Set("post", post)
|
||||||
|
|
||||||
header := http.Header{"Referer": {"https://disqus.com"}}
|
req, err := http.NewRequest(http.MethodPost, apiPostApprove, strings.NewReader(vals.Encode()))
|
||||||
resp, err := httpPostHeader(apiPostApprove, vals, header)
|
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||||
|
req.Header.Set("Referer", "https://disqus.com")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
resp, err := http.DefaultClient.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -264,26 +265,28 @@ type threadCreateResp struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ThreadCreate 创建thread
|
// ThreadCreate 创建thread
|
||||||
func ThreadCreate(article *model.Article, btitle string) error {
|
func (cli *DisqusClient) ThreadCreate(article *model.Article, btitle string) error {
|
||||||
if err := checkDisqusConfig(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
vals := url.Values{}
|
vals := url.Values{}
|
||||||
vals.Set("api_key", config.Conf.EiBlogApp.Disqus.PublicKey)
|
vals.Set("api_key", disqusAPIKey)
|
||||||
vals.Set("access_token", config.Conf.EiBlogApp.Disqus.AccessToken)
|
vals.Set("access_token", cli.Conf.AccessToken)
|
||||||
vals.Set("forum", config.Conf.EiBlogApp.Disqus.ShortName)
|
vals.Set("forum", cli.Conf.ShortName)
|
||||||
vals.Set("title", article.Title+" | "+btitle)
|
vals.Set("title", article.Title+" | "+btitle)
|
||||||
vals.Set("identifier", "post-"+article.Slug)
|
vals.Set("identifier", "post-"+article.Slug)
|
||||||
|
|
||||||
urlPath := fmt.Sprintf("https://%s/post/%s.html", config.Conf.EiBlogApp.Host, article.Slug)
|
urlPath := fmt.Sprintf("https://%s/post/%s.html", cli.Host, article.Slug)
|
||||||
vals.Set("url", urlPath)
|
vals.Set("url", urlPath)
|
||||||
|
|
||||||
resp, err := httpPost(apiThreadCreate, vals)
|
req, err := http.NewRequest(http.MethodPost, apiThreadCreate, strings.NewReader(vals.Encode()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||||
|
req.Header.Set("Referer", "https://disqus.com")
|
||||||
|
|
||||||
|
resp, err := http.DefaultClient.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
b, err := io.ReadAll(resp.Body)
|
b, err := io.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -311,18 +314,14 @@ type threadDetailsResp struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ThreadDetails thread详细
|
// ThreadDetails thread详细
|
||||||
func ThreadDetails(article *model.Article) error {
|
func (cli *DisqusClient) ThreadDetails(article *model.Article) error {
|
||||||
if err := checkDisqusConfig(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
vals := url.Values{}
|
vals := url.Values{}
|
||||||
vals.Set("api_key", config.Conf.EiBlogApp.Disqus.PublicKey)
|
vals.Set("api_key", disqusAPIKey)
|
||||||
vals.Set("access_token", config.Conf.EiBlogApp.Disqus.AccessToken)
|
vals.Set("access_token", cli.Conf.AccessToken)
|
||||||
vals.Set("forum", config.Conf.EiBlogApp.Disqus.ShortName)
|
vals.Set("forum", cli.Conf.ShortName)
|
||||||
vals.Set("thread:ident", "post-"+article.Slug)
|
vals.Set("thread:ident", "post-"+article.Slug)
|
||||||
|
|
||||||
resp, err := httpGet(apiThreadDetails + "?" + vals.Encode())
|
resp, err := http.DefaultClient.Get(apiThreadDetails + "?" + vals.Encode())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
// Package internal provides ...
|
package es
|
||||||
package internal
|
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
@@ -12,7 +11,6 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/eiblog/eiblog/pkg/config"
|
|
||||||
"github.com/eiblog/eiblog/pkg/model"
|
"github.com/eiblog/eiblog/pkg/model"
|
||||||
"github.com/eiblog/eiblog/tools"
|
"github.com/eiblog/eiblog/tools"
|
||||||
|
|
||||||
@@ -29,30 +27,26 @@ const (
|
|||||||
ElasticType = "article"
|
ElasticType = "article"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
// ESClient es client
|
||||||
if checkESConfig() != nil {
|
type ESClient struct {
|
||||||
return
|
Host string
|
||||||
}
|
|
||||||
|
|
||||||
mappings := fmt.Sprintf(`{"mappings":{"%s":{"properties":{"content":{"analyzer":"ik_syno","search_analyzer":"ik_syno","term_vector":"with_positions_offsets","type":"string"},"date":{"index":"not_analyzed","type":"date"},"slug":{"type":"string"},"tag":{"index":"not_analyzed","type":"string"},"title":{"analyzer":"ik_syno","search_analyzer":"ik_syno","term_vector":"with_positions_offsets","type":"string"}}}}}`, "article")
|
|
||||||
err := createIndexAndMappings(ElasticIndex, ElasticType, []byte(mappings))
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkESConfig() error {
|
// NewESClient new es client
|
||||||
if config.Conf.ESHost == "" {
|
func NewESClient(host string) (*ESClient, error) {
|
||||||
return errors.New("es: elasticsearch not config")
|
if host == "" {
|
||||||
|
return nil, errors.New("es: elasticsearch host is empty")
|
||||||
}
|
}
|
||||||
return nil
|
es := &ESClient{Host: host}
|
||||||
|
err := es.createIndexAndMappings(ElasticIndex, ElasticType)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return es, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ElasticSearch 搜索文章
|
// ElasticSearch 搜索文章
|
||||||
func ElasticSearch(query string, size, from int) (*SearchIndexResult, error) {
|
func (cli *ESClient) ElasticSearch(query string, size, from int) (*SearchIndexResult, error) {
|
||||||
if err := checkESConfig(); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
// 分析查询
|
// 分析查询
|
||||||
var (
|
var (
|
||||||
regTerm = regexp.MustCompile(`(tag|slug|date):`)
|
regTerm = regexp.MustCompile(`(tag|slug|date):`)
|
||||||
@@ -100,17 +94,13 @@ func ElasticSearch(query string, size, from int) (*SearchIndexResult, error) {
|
|||||||
// 判断是否为空,判断搜索方式
|
// 判断是否为空,判断搜索方式
|
||||||
dsl := fmt.Sprintf("{"+SearchFilter+"}", strings.Join(filter, ","))
|
dsl := fmt.Sprintf("{"+SearchFilter+"}", strings.Join(filter, ","))
|
||||||
if kw != "" {
|
if kw != "" {
|
||||||
dsl = strings.Replace(strings.Replace(`{"highlight":{"fields":{"content":{},"title":{}},"post_tags":["\u003c/b\u003e"],"pre_tags":["\u003cb\u003e"]},"query":{"dis_max":{"queries":[{"match":{"title":{"boost":4,"minimum_should_match":"50%","query":"$1"}}},{"match":{"content":{"boost":4,"minimum_should_match":"75%","query":"$1"}}},{"match":{"tag":{"boost":2,"minimum_should_match":"100%","query":"$1"}}},{"match":{"slug":{"boost":1,"minimum_should_match":"100%","query":"$1"}}}],"tie_breaker":0.3}},$2}`, "$1", kw, -1), "$2", fmt.Sprintf(SearchFilter, strings.Join(filter, ",")), -1)
|
dsl = strings.ReplaceAll(strings.ReplaceAll(`{"highlight":{"fields":{"content":{},"title":{}},"post_tags":["\u003c/b\u003e"],"pre_tags":["\u003cb\u003e"]},"query":{"dis_max":{"queries":[{"match":{"title":{"boost":4,"minimum_should_match":"50%","query":"$1"}}},{"match":{"content":{"boost":4,"minimum_should_match":"75%","query":"$1"}}},{"match":{"tag":{"boost":2,"minimum_should_match":"100%","query":"$1"}}},{"match":{"slug":{"boost":1,"minimum_should_match":"100%","query":"$1"}}}],"tie_breaker":0.3}},$2}`, "$1", kw), "$2", fmt.Sprintf(SearchFilter, strings.Join(filter, ",")))
|
||||||
}
|
}
|
||||||
return indexQueryDSL(ElasticIndex, ElasticType, size, from, []byte(dsl))
|
return cli.indexQueryDSL(ElasticIndex, ElasticType, size, from, []byte(dsl))
|
||||||
}
|
}
|
||||||
|
|
||||||
// ElasticAddIndex 添加或更新索引
|
// ElasticAddIndex 添加或更新索引
|
||||||
func ElasticAddIndex(article *model.Article) error {
|
func (cli *ESClient) ElasticAddIndex(article *model.Article) error {
|
||||||
if err := checkESConfig(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
img := tools.PickFirstImage(article.Content)
|
img := tools.PickFirstImage(article.Content)
|
||||||
mapping := map[string]interface{}{
|
mapping := map[string]interface{}{
|
||||||
"title": article.Title,
|
"title": article.Title,
|
||||||
@@ -121,20 +111,16 @@ func ElasticAddIndex(article *model.Article) error {
|
|||||||
"date": article.CreatedAt,
|
"date": article.CreatedAt,
|
||||||
}
|
}
|
||||||
data, _ := json.Marshal(mapping)
|
data, _ := json.Marshal(mapping)
|
||||||
return indexOrUpdateDocument(ElasticIndex, ElasticType, article.ID, data)
|
return cli.indexOrUpdateDocument(ElasticIndex, ElasticType, article.ID, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ElasticDelIndex 删除索引
|
// ElasticDelIndex 删除索引
|
||||||
func ElasticDelIndex(ids []int) error {
|
func (cli *ESClient) ElasticDelIndex(ids []int) error {
|
||||||
if err := checkESConfig(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
var target []string
|
var target []string
|
||||||
for _, id := range ids {
|
for _, id := range ids {
|
||||||
target = append(target, fmt.Sprint(id))
|
target = append(target, fmt.Sprint(id))
|
||||||
}
|
}
|
||||||
return deleteIndexDocument(ElasticIndex, ElasticType, target)
|
return cli.deleteIndexDocument(ElasticIndex, ElasticType, target)
|
||||||
}
|
}
|
||||||
|
|
||||||
// indicesCreateResult 索引创建结果
|
// indicesCreateResult 索引创建结果
|
||||||
@@ -143,9 +129,11 @@ type indicesCreateResult struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// createIndexAndMappings 创建索引和映射关系
|
// createIndexAndMappings 创建索引和映射关系
|
||||||
func createIndexAndMappings(index, typ string, mappings []byte) error {
|
func (cli *ESClient) createIndexAndMappings(index, typ string) error {
|
||||||
rawurl := fmt.Sprintf("%s/%s/%s", config.Conf.ESHost, index, typ)
|
mappings := fmt.Sprintf(`{"mappings":{"%s":{"properties":{"content":{"analyzer":"ik_syno","search_analyzer":"ik_syno","term_vector":"with_positions_offsets","type":"string"},"date":{"index":"not_analyzed","type":"date"},"slug":{"type":"string"},"tag":{"index":"not_analyzed","type":"string"},"title":{"analyzer":"ik_syno","search_analyzer":"ik_syno","term_vector":"with_positions_offsets","type":"string"}}}}}`, typ)
|
||||||
resp, err := httpHead(rawurl)
|
|
||||||
|
rawurl := fmt.Sprintf("%s/%s/%s", cli.Host, index, typ)
|
||||||
|
resp, err := http.DefaultClient.Head(rawurl)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -154,8 +142,13 @@ func createIndexAndMappings(index, typ string, mappings []byte) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
rawurl = fmt.Sprintf("%s/%s", config.Conf.ESHost, index)
|
rawurl = fmt.Sprintf("%s/%s", cli.Host, index)
|
||||||
resp, err = httpPut(rawurl, mappings)
|
req, err := http.NewRequest(http.MethodPut, rawurl, bytes.NewReader([]byte(mappings)))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
req.Header.Set("Content-Type", "application/json")
|
||||||
|
resp, err = http.DefaultClient.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -176,9 +169,15 @@ func createIndexAndMappings(index, typ string, mappings []byte) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// indexOrUpdateDocument 创建或更新索引
|
// indexOrUpdateDocument 创建或更新索引
|
||||||
func indexOrUpdateDocument(index, typ string, id int, doc []byte) (err error) {
|
func (cli *ESClient) indexOrUpdateDocument(index, typ string, id int, doc []byte) (err error) {
|
||||||
rawurl := fmt.Sprintf("%s/%s/%s/%d", config.Conf.ESHost, index, typ, id)
|
rawurl := fmt.Sprintf("%s/%s/%s/%d", cli.Host, index, typ, id)
|
||||||
resp, err := httpPut(rawurl, doc)
|
|
||||||
|
req, err := http.NewRequest(http.MethodPut, rawurl, bytes.NewReader(doc))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
req.Header.Set("Content-Type", "application/json")
|
||||||
|
resp, err := http.DefaultClient.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -205,7 +204,7 @@ type deleteIndexResult struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// deleteIndexDocument 删除文档
|
// deleteIndexDocument 删除文档
|
||||||
func deleteIndexDocument(index, typ string, ids []string) error {
|
func (cli *ESClient) deleteIndexDocument(index, typ string, ids []string) error {
|
||||||
buf := bytes.Buffer{}
|
buf := bytes.Buffer{}
|
||||||
for _, id := range ids {
|
for _, id := range ids {
|
||||||
dd := deleteIndexReq{Index: index, Type: typ, ID: id}
|
dd := deleteIndexReq{Index: index, Type: typ, ID: id}
|
||||||
@@ -214,8 +213,13 @@ func deleteIndexDocument(index, typ string, ids []string) error {
|
|||||||
buf.Write(b)
|
buf.Write(b)
|
||||||
buf.WriteByte('\n')
|
buf.WriteByte('\n')
|
||||||
}
|
}
|
||||||
rawurl := fmt.Sprintf("%s/_bulk", config.Conf.ESHost)
|
rawurl := fmt.Sprintf("%s/_bulk", cli.Host)
|
||||||
resp, err := httpPost(rawurl, buf.Bytes())
|
req, err := http.NewRequest(http.MethodPost, rawurl, bytes.NewReader(buf.Bytes()))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
req.Header.Set("Content-Type", "application/json")
|
||||||
|
resp, err := http.DefaultClient.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -264,10 +268,10 @@ type SearchIndexResult struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// indexQueryDSL 语句查询文档
|
// indexQueryDSL 语句查询文档
|
||||||
func indexQueryDSL(index, typ string, size, from int, dsl []byte) (*SearchIndexResult, error) {
|
func (c *ESClient) indexQueryDSL(index, typ string, size, from int, dsl []byte) (*SearchIndexResult, error) {
|
||||||
rawurl := fmt.Sprintf("%s/%s/%s/_search?size=%d&from=%d", config.Conf.ESHost,
|
rawurl := fmt.Sprintf("%s/%s/%s/_search?size=%d&from=%d", c.Host,
|
||||||
index, typ, size, from)
|
index, typ, size, from)
|
||||||
resp, err := httpPost(rawurl, dsl)
|
resp, err := http.Post(rawurl, "application/json", bytes.NewReader(dsl))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
// Package internal provides ...
|
package pinger
|
||||||
package internal
|
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
@@ -14,29 +13,50 @@ import (
|
|||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
// feedrPingFunc http://<your-hub-name>.superfeedr.com/
|
// Pinger pinger
|
||||||
var feedrPingFunc = func(btitle, slug string) error {
|
type Pinger struct {
|
||||||
feedrHost := config.Conf.EiBlogApp.FeedRPC.FeedrURL
|
Host string
|
||||||
if feedrHost == "" {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
|
Conf config.FeedRPC
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewPinger new pinger
|
||||||
|
func NewPinger(host string, conf config.FeedRPC) (*Pinger, error) {
|
||||||
|
if conf.FeedrURL == "" {
|
||||||
|
return nil, fmt.Errorf("feedr url is empty")
|
||||||
|
}
|
||||||
|
return &Pinger{Host: host, Conf: conf}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// PingFunc ping blog article to SE
|
||||||
|
func (p *Pinger) PingFunc(btitle, slug string) {
|
||||||
|
err := p.feedrPingFunc(btitle, slug)
|
||||||
|
if err != nil {
|
||||||
|
logrus.Error("pinger: PingFunc feedr: ", err)
|
||||||
|
}
|
||||||
|
err = p.rpcPingFunc(btitle, slug)
|
||||||
|
if err != nil {
|
||||||
|
logrus.Error("pinger: PingFunc: rpc: ", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// feedrPingFunc http://<your-hub-name>.superfeedr.com/
|
||||||
|
func (p *Pinger) feedrPingFunc(btitle, slug string) error {
|
||||||
vals := url.Values{}
|
vals := url.Values{}
|
||||||
vals.Set("hub.mode", "publish")
|
vals.Set("hub.mode", "publish")
|
||||||
vals.Add("hub.url", fmt.Sprintf("https://%s/post/%s.html",
|
vals.Add("hub.url", fmt.Sprintf("https://%s/post/%s.html", p.Host, slug))
|
||||||
config.Conf.BackupApp.Host, slug))
|
resp, err := http.DefaultClient.PostForm(p.Conf.FeedrURL, vals)
|
||||||
resp, err := httpPost(feedrHost, vals)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
data, err := io.ReadAll(resp.Body)
|
data, err := io.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if resp.StatusCode != 204 {
|
if resp.StatusCode != 204 {
|
||||||
return fmt.Errorf("pinger: status code: %d, %s",
|
return fmt.Errorf("pinger: status code: %d, %s", resp.StatusCode, string(data))
|
||||||
resp.StatusCode, string(data))
|
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -61,16 +81,13 @@ type rpcValue struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// rpcPingFunc ping rpc
|
// rpcPingFunc ping rpc
|
||||||
var rpcPingFunc = func(btitle, slug string) error {
|
func (p *Pinger) rpcPingFunc(btitle, slug string) error {
|
||||||
if len(config.Conf.EiBlogApp.FeedRPC.PingRPC) == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
param := rpcPingParam{MethodName: "weblogUpdates.extendedPing"}
|
param := rpcPingParam{MethodName: "weblogUpdates.extendedPing"}
|
||||||
param.Params.Param = [4]rpcValue{
|
param.Params.Param = [4]rpcValue{
|
||||||
0: rpcValue{Value: btitle},
|
0: {Value: btitle},
|
||||||
1: rpcValue{Value: "https://" + config.Conf.EiBlogApp.Host},
|
1: {Value: "https://" + p.Host},
|
||||||
2: rpcValue{Value: fmt.Sprintf("https://%s/post/%s.html", config.Conf.EiBlogApp.Host, slug)},
|
2: {Value: fmt.Sprintf("https://%s/post/%s.html", p.Host, slug)},
|
||||||
3: rpcValue{Value: "https://" + config.Conf.EiBlogApp.Host + "/rss.html"},
|
3: {Value: "https://" + p.Host + "/rss.html"},
|
||||||
}
|
}
|
||||||
buf := bytes.Buffer{}
|
buf := bytes.Buffer{}
|
||||||
buf.WriteString(xml.Header)
|
buf.WriteString(xml.Header)
|
||||||
@@ -81,13 +98,15 @@ var rpcPingFunc = func(btitle, slug string) error {
|
|||||||
data := buf.Bytes()
|
data := buf.Bytes()
|
||||||
header := http.Header{}
|
header := http.Header{}
|
||||||
header.Set("Content-Type", "text/xml")
|
header.Set("Content-Type", "text/xml")
|
||||||
for _, addr := range config.Conf.EiBlogApp.FeedRPC.PingRPC {
|
|
||||||
resp, err := httpPostHeader(addr, data, header)
|
for _, addr := range p.Conf.PingRPC {
|
||||||
|
resp, err := http.DefaultClient.Post(addr, "text/xml", bytes.NewReader(data))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Error("rpcPingFunc.httpPostHeader: ", err)
|
logrus.Error("rpcPingFunc.httpPostHeader: ", err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
data, err := io.ReadAll(resp.Body)
|
data, err := io.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Error("rpcPingFunc.ReadAll: ", err)
|
logrus.Error("rpcPingFunc.ReadAll: ", err)
|
||||||
@@ -99,15 +118,3 @@ var rpcPingFunc = func(btitle, slug string) error {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// PingFunc ping blog article to SE
|
|
||||||
func PingFunc(btitle, slug string) {
|
|
||||||
err := feedrPingFunc(btitle, slug)
|
|
||||||
if err != nil {
|
|
||||||
logrus.Error("pinger: PingFunc feedr: ", err)
|
|
||||||
}
|
|
||||||
err = rpcPingFunc(btitle, slug)
|
|
||||||
if err != nil {
|
|
||||||
logrus.Error("pinger: PingFunc: rpc: ", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
// Package internal provides ...
|
package qiniu
|
||||||
package internal
|
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
@@ -15,39 +14,49 @@ import (
|
|||||||
"github.com/qiniu/go-sdk/v7/storage"
|
"github.com/qiniu/go-sdk/v7/storage"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// QiniuClient qiniu client
|
||||||
|
type QiniuClient struct {
|
||||||
|
Conf config.Qiniu
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewQiniuClient new qiniu client
|
||||||
|
func NewQiniuClient(conf config.Qiniu) (*QiniuClient, error) {
|
||||||
|
if conf.AccessKey == "" ||
|
||||||
|
conf.SecretKey == "" ||
|
||||||
|
conf.Bucket == "" ||
|
||||||
|
conf.Domain == "" {
|
||||||
|
return nil, errors.New("qiniu config error")
|
||||||
|
}
|
||||||
|
return &QiniuClient{Conf: conf}, nil
|
||||||
|
}
|
||||||
|
|
||||||
// UploadParams upload params
|
// UploadParams upload params
|
||||||
type UploadParams struct {
|
type UploadParams struct {
|
||||||
Name string
|
Name string
|
||||||
Size int64
|
Size int64
|
||||||
Data io.Reader
|
Data io.Reader
|
||||||
NoCompletePath bool
|
NoCompletePath bool
|
||||||
|
|
||||||
Conf config.Qiniu
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// QiniuUpload 上传文件
|
// Upload 上传文件
|
||||||
func QiniuUpload(params UploadParams) (string, error) {
|
func (cli *QiniuClient) Upload(params UploadParams) (string, error) {
|
||||||
if params.Conf.AccessKey == "" ||
|
|
||||||
params.Conf.SecretKey == "" {
|
|
||||||
return "", errors.New("qiniu config error")
|
|
||||||
}
|
|
||||||
key := params.Name
|
key := params.Name
|
||||||
if !params.NoCompletePath {
|
if !params.NoCompletePath {
|
||||||
key = filepath.Base(params.Name)
|
key = filepath.Base(params.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
mac := qbox.NewMac(params.Conf.AccessKey,
|
mac := qbox.NewMac(cli.Conf.AccessKey,
|
||||||
params.Conf.SecretKey)
|
cli.Conf.SecretKey)
|
||||||
// 设置上传策略
|
// 设置上传策略
|
||||||
putPolicy := &storage.PutPolicy{
|
putPolicy := &storage.PutPolicy{
|
||||||
Scope: params.Conf.Bucket,
|
Scope: cli.Conf.Bucket,
|
||||||
Expires: 3600,
|
Expires: 3600,
|
||||||
InsertOnly: 1,
|
InsertOnly: 1,
|
||||||
}
|
}
|
||||||
// 上传token
|
// 上传token
|
||||||
uploadToken := putPolicy.UploadToken(mac)
|
uploadToken := putPolicy.UploadToken(mac)
|
||||||
// 上传配置
|
// 上传配置
|
||||||
region, err := storage.GetRegion(params.Conf.AccessKey, params.Conf.Bucket)
|
region, err := storage.GetRegion(cli.Conf.AccessKey, cli.Conf.Bucket)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
@@ -65,7 +74,7 @@ func QiniuUpload(params UploadParams) (string, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
url := "https://" + params.Conf.Domain + "/" + key
|
url := "https://" + cli.Conf.Domain + "/" + key
|
||||||
return url, nil
|
return url, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,21 +83,19 @@ type DeleteParams struct {
|
|||||||
Name string
|
Name string
|
||||||
Days int
|
Days int
|
||||||
NoCompletePath bool
|
NoCompletePath bool
|
||||||
|
|
||||||
Conf config.Qiniu
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// QiniuDelete 删除文件
|
// QiniuDelete 删除文件
|
||||||
func QiniuDelete(params DeleteParams) error {
|
func (cli *QiniuClient) Delete(params DeleteParams) error {
|
||||||
key := params.Name
|
key := params.Name
|
||||||
if !params.NoCompletePath {
|
if !params.NoCompletePath {
|
||||||
key = completeQiniuKey(params.Name)
|
key = completeQiniuKey(params.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
mac := qbox.NewMac(params.Conf.AccessKey,
|
mac := qbox.NewMac(cli.Conf.AccessKey,
|
||||||
params.Conf.SecretKey)
|
cli.Conf.SecretKey)
|
||||||
// 上传配置
|
// 上传配置
|
||||||
region, err := storage.GetRegion(params.Conf.AccessKey, params.Conf.Bucket)
|
region, err := storage.GetRegion(cli.Conf.AccessKey, cli.Conf.Bucket)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -100,24 +107,22 @@ func QiniuDelete(params DeleteParams) error {
|
|||||||
bucketManager := storage.NewBucketManager(mac, cfg)
|
bucketManager := storage.NewBucketManager(mac, cfg)
|
||||||
// Delete
|
// Delete
|
||||||
if params.Days > 0 {
|
if params.Days > 0 {
|
||||||
return bucketManager.DeleteAfterDays(params.Conf.Bucket, key, params.Days)
|
return bucketManager.DeleteAfterDays(cli.Conf.Bucket, key, params.Days)
|
||||||
}
|
}
|
||||||
return bucketManager.Delete(params.Conf.Bucket, key)
|
return bucketManager.Delete(cli.Conf.Bucket, key)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ContentParams list params
|
// ContentParams list params
|
||||||
type ContentParams struct {
|
type ContentParams struct {
|
||||||
Prefix string
|
Prefix string
|
||||||
|
|
||||||
Conf config.Qiniu
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// QiniuContent 获取文件列表
|
// Content 获取文件内容
|
||||||
func QiniuContent(params ContentParams) ([]byte, error) {
|
func (cli *QiniuClient) Content(params ContentParams) ([]byte, error) {
|
||||||
mac := qbox.NewMac(params.Conf.AccessKey,
|
mac := qbox.NewMac(cli.Conf.AccessKey,
|
||||||
params.Conf.SecretKey)
|
cli.Conf.SecretKey)
|
||||||
// region
|
// region
|
||||||
region, err := storage.GetRegion(params.Conf.AccessKey, params.Conf.Bucket)
|
region, err := storage.GetRegion(cli.Conf.AccessKey, cli.Conf.Bucket)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -128,7 +133,7 @@ func QiniuContent(params ContentParams) ([]byte, error) {
|
|||||||
// manager
|
// manager
|
||||||
bucketManager := storage.NewBucketManager(mac, cfg)
|
bucketManager := storage.NewBucketManager(mac, cfg)
|
||||||
// list file
|
// list file
|
||||||
files, _, _, _, err := bucketManager.ListFiles(params.Conf.Bucket, params.Prefix, "", "", 1)
|
files, _, _, _, err := bucketManager.ListFiles(cli.Conf.Bucket, params.Prefix, "", "", 1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -136,7 +141,7 @@ func QiniuContent(params ContentParams) ([]byte, error) {
|
|||||||
return nil, errors.New("no file")
|
return nil, errors.New("no file")
|
||||||
}
|
}
|
||||||
deadline := time.Now().Add(time.Second * 60).Unix()
|
deadline := time.Now().Add(time.Second * 60).Unix()
|
||||||
url := storage.MakePrivateURLv2(mac, "https://"+params.Conf.Domain, files[0].Key, deadline)
|
url := storage.MakePrivateURLv2(mac, "https://"+cli.Conf.Domain, files[0].Key, deadline)
|
||||||
resp, err := http.Get(url)
|
resp, err := http.Get(url)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -151,27 +156,16 @@ func completeQiniuKey(name string) string {
|
|||||||
ext := filepath.Ext(name)
|
ext := filepath.Ext(name)
|
||||||
|
|
||||||
switch ext {
|
switch ext {
|
||||||
case ".bmp", ".png", ".jpg",
|
case ".bmp", ".png", ".jpg", ".gif", ".ico", ".jpeg":
|
||||||
".gif", ".ico", ".jpeg":
|
|
||||||
|
|
||||||
name = "blog/img/" + name
|
name = "blog/img/" + name
|
||||||
case ".mov", ".mp4":
|
case ".mov", ".mp4":
|
||||||
name = "blog/video/" + name
|
name = "blog/video/" + name
|
||||||
case ".go", ".js", ".css",
|
case ".go", ".js", ".css", ".cpp", ".php", ".rb", ".java",
|
||||||
".cpp", ".php", ".rb",
|
".py", ".sql", ".lua", ".html", ".sh", ".xml", ".cs":
|
||||||
".java", ".py", ".sql",
|
|
||||||
".lua", ".html", ".sh",
|
|
||||||
".xml", ".cs":
|
|
||||||
|
|
||||||
name = "blog/code/" + name
|
name = "blog/code/" + name
|
||||||
case ".txt", ".md", ".ini",
|
case ".txt", ".md", ".ini", ".yaml", ".yml", ".doc", ".ppt", ".pdf":
|
||||||
".yaml", ".yml", ".doc",
|
|
||||||
".ppt", ".pdf":
|
|
||||||
|
|
||||||
name = "blog/document/" + name
|
name = "blog/document/" + name
|
||||||
case ".zip", ".rar", ".tar",
|
case ".zip", ".rar", ".tar", ".gz":
|
||||||
".gz":
|
|
||||||
|
|
||||||
name = "blog/archive/" + name
|
name = "blog/archive/" + name
|
||||||
default:
|
default:
|
||||||
name = "blog/other/" + name
|
name = "blog/other/" + name
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
// Package internal provides ...
|
package qiniu
|
||||||
package internal
|
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
@@ -10,6 +9,16 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestQiniuUpload(t *testing.T) {
|
func TestQiniuUpload(t *testing.T) {
|
||||||
|
cli, err := NewQiniuClient(config.Qiniu{
|
||||||
|
AccessKey: os.Getenv("QINIU_ACCESSKEY"),
|
||||||
|
SecretKey: os.Getenv("QINIU_SECRETKEY"),
|
||||||
|
Bucket: os.Getenv("QINIU_BUCKET"),
|
||||||
|
Domain: os.Getenv("QINIU_DOMAIN"),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("NewQiniuClient error = %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
f, _ := os.Open("qiniu_test.go")
|
f, _ := os.Open("qiniu_test.go")
|
||||||
fi, _ := f.Stat()
|
fi, _ := f.Stat()
|
||||||
@@ -27,17 +36,11 @@ func TestQiniuUpload(t *testing.T) {
|
|||||||
Name: "test-" + time.Now().Format("200601021504059999") + ".go",
|
Name: "test-" + time.Now().Format("200601021504059999") + ".go",
|
||||||
Size: fi.Size(),
|
Size: fi.Size(),
|
||||||
Data: f,
|
Data: f,
|
||||||
Conf: config.Qiniu{
|
|
||||||
AccessKey: os.Getenv("QINIU_ACCESSKEY"),
|
|
||||||
SecretKey: os.Getenv("QINIU_SECRETKEY"),
|
|
||||||
Bucket: os.Getenv("QINIU_BUCKET"),
|
|
||||||
Domain: "bu.st.deepzz.com",
|
|
||||||
},
|
|
||||||
}}, false},
|
}}, false},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
got, err := QiniuUpload(tt.args.params)
|
got, err := cli.Upload(tt.args.params)
|
||||||
if (err != nil) != tt.wantErr {
|
if (err != nil) != tt.wantErr {
|
||||||
t.Errorf("QiniuUpload() error = %v, wantErr %v", err, tt.wantErr)
|
t.Errorf("QiniuUpload() error = %v, wantErr %v", err, tt.wantErr)
|
||||||
return
|
return
|
||||||
@@ -48,15 +51,21 @@ func TestQiniuUpload(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestQiniuContent(t *testing.T) {
|
func TestQiniuContent(t *testing.T) {
|
||||||
params := ContentParams{
|
cli, err := NewQiniuClient(config.Qiniu{
|
||||||
Conf: config.Qiniu{
|
AccessKey: os.Getenv("QINIU_ACCESSKEY"),
|
||||||
AccessKey: os.Getenv("QINIU_ACCESSKEY"),
|
SecretKey: os.Getenv("QINIU_SECRETKEY"),
|
||||||
SecretKey: os.Getenv("QINIU_SECRETKEY"),
|
Bucket: os.Getenv("QINIU_BUCKET"),
|
||||||
Bucket: os.Getenv("QINIU_BUCKET"),
|
Domain: os.Getenv("QINIU_DOMAIN"),
|
||||||
Domain: "bu.st.deepzz.com",
|
})
|
||||||
},
|
if err != nil {
|
||||||
|
t.Errorf("NewQiniuClient error = %v", err)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
_, err := QiniuContent(params)
|
|
||||||
|
params := ContentParams{
|
||||||
|
Prefix: "blog/",
|
||||||
|
}
|
||||||
|
_, err = cli.Content(params)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("QiniuList error = %v", err)
|
t.Errorf("QiniuList error = %v", err)
|
||||||
}
|
}
|
||||||
@@ -5,7 +5,7 @@ set -e
|
|||||||
_tag="$1"
|
_tag="$1"
|
||||||
_arch=$(go env GOARCH)
|
_arch=$(go env GOARCH)
|
||||||
|
|
||||||
for file in pkg/core/*; do
|
for file in cmd/*; do
|
||||||
app="$(basename $file)";
|
app="$(basename $file)";
|
||||||
# tar platform
|
# tar platform
|
||||||
for os in linux darwin windows; do
|
for os in linux darwin windows; do
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
#!/usr/bin/env sh
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
for file in pkg/core/*; do
|
for file in cmd/*; do
|
||||||
if test -d $file; then
|
if test -d $file; then
|
||||||
cd $file && swag init -g api.go;
|
cd $file && swag init -g main.go;
|
||||||
cd -;
|
cd -;
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|||||||
Reference in New Issue
Block a user