mirror of
https://github.com/eiblog/eiblog.git
synced 2026-02-05 14:22:27 +08:00
Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c515e33e2c | ||
|
|
5b12dd625b | ||
|
|
9b918caccd | ||
|
|
2be53379e1 | ||
|
|
944e27c58a | ||
|
|
92baf970bc | ||
|
|
64a754167a | ||
|
|
af2a20c34a | ||
|
|
f28d0e77e0 | ||
|
|
9a1b4db61a |
14
CHANGELOG.md
14
CHANGELOG.md
@@ -2,6 +2,20 @@
|
||||
|
||||
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.9](https://github.com/eiblog/eiblog/compare/v2.2.8...v2.2.9) (2023-09-25)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* google analytics not work, supported ga4 measurement protocol ([9b918ca](https://github.com/eiblog/eiblog/commit/9b918caccd9fd7faff7d253693e075ccd0150c17))
|
||||
|
||||
### [2.2.8](https://github.com/eiblog/eiblog/compare/v2.2.7...v2.2.8) (2023-07-12)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **backup:** restore db and tests ([f28d0e7](https://github.com/eiblog/eiblog/commit/f28d0e77e06dd435dc13a1867f18a011e34b8f53))
|
||||
|
||||
### [2.2.7](https://github.com/eiblog/eiblog/compare/v2.2.6...v2.2.7) (2023-07-12)
|
||||
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ appname: eiblog
|
||||
database:
|
||||
driver: sqlite
|
||||
source: ./db.sqlite
|
||||
eshost:
|
||||
eshost: # http://elasticsearch:9200
|
||||
eiblogapp:
|
||||
mode:
|
||||
name: cmd-eiblog
|
||||
@@ -28,10 +28,9 @@ eiblogapp:
|
||||
publickey: wdSgxRm9rdGAlLKFcFdToBe3GT4SibmV7Y8EjJQ0r4GWXeKtxpopMAeIeoI2dTEg
|
||||
accesstoken: 50023908f39f4607957e909b495326af
|
||||
google: # 谷歌分析
|
||||
url: https://www.google-analytics.com/collect
|
||||
tid: UA-xxxxxx-1
|
||||
v: "1"
|
||||
t: pageview
|
||||
url: https://www.google-analytics.com/g/collect
|
||||
tid: G-xxxxxxxxxx
|
||||
v: "2"
|
||||
adsense: <script data-ad-client="ca-pub-5384494508691406" async src=""></script>
|
||||
qiniu: # 七牛OSS
|
||||
bucket: eiblog
|
||||
|
||||
@@ -27,6 +27,7 @@ services:
|
||||
restart: always
|
||||
backup:
|
||||
image: deepzz0/backup:latest
|
||||
#command: ./backend --restore true
|
||||
volumes:
|
||||
- ${PWD}/conf:/app/conf
|
||||
links:
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||

|
||||
|
||||
### 图片懒加载
|
||||
博客系统提供图片懒加载功能(浏览到某个位置,图片才会加载),以此来提高页面加载速度。我们可根据需要是否使用。当然由此带来的坏处就是rss不能够正确加载图片。后续看是否解决这个问题或朋友提PR。
|
||||
博客系统提供图片懒加载功能(浏览到某个位置,图片才会加载),以此来提高页面加载速度。我们可根据需要是否使用。~~当然由此带来的坏处就是rss不能够正确加载图片。后续看是否解决这个问题或朋友提PR。~~,已解决。
|
||||
|
||||
首先看下图片的`markdown`标准写法:
|
||||
```
|
||||
|
||||
5
pkg/cache/store/mongodb.go
vendored
5
pkg/cache/store/mongodb.go
vendored
@@ -326,6 +326,11 @@ func (db *mongodb) LoadArticleList(ctx context.Context, search SearchArticles) (
|
||||
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
|
||||
type counter struct {
|
||||
Name string
|
||||
|
||||
84
pkg/cache/store/mongodb_test.go
vendored
84
pkg/cache/store/mongodb_test.go
vendored
@@ -13,7 +13,7 @@ var (
|
||||
store Store
|
||||
acct *model.Account
|
||||
blogger *model.Blogger
|
||||
series *model.Series
|
||||
series *model.Serie
|
||||
article *model.Article
|
||||
)
|
||||
|
||||
@@ -25,12 +25,12 @@ func init() {
|
||||
}
|
||||
// account
|
||||
acct = &model.Account{
|
||||
Username: "deepzz",
|
||||
Password: "deepzz",
|
||||
Email: "deepzz@example.com",
|
||||
PhoneN: "12345678900",
|
||||
Address: "address",
|
||||
CreateTime: time.Now(),
|
||||
Username: "deepzz",
|
||||
Password: "deepzz",
|
||||
Email: "deepzz@example.com",
|
||||
PhoneN: "12345678900",
|
||||
Address: "address",
|
||||
CreatedAt: time.Now(),
|
||||
}
|
||||
// blogger
|
||||
blogger = &model.Blogger{
|
||||
@@ -41,11 +41,11 @@ func init() {
|
||||
Copyright: "Copyright",
|
||||
}
|
||||
// series
|
||||
series = &model.Series{
|
||||
Slug: "slug",
|
||||
Name: "series name",
|
||||
Desc: "series desc",
|
||||
CreateTime: time.Now(),
|
||||
series = &model.Serie{
|
||||
Slug: "slug",
|
||||
Name: "series name",
|
||||
Desc: "series desc",
|
||||
CreatedAt: time.Now(),
|
||||
}
|
||||
// article
|
||||
article = &model.Article{
|
||||
@@ -55,21 +55,20 @@ func init() {
|
||||
Count: 0,
|
||||
Content: "### count",
|
||||
SerieID: 0,
|
||||
Tags: "",
|
||||
Tags: nil,
|
||||
IsDraft: false,
|
||||
|
||||
UpdateTime: time.Now(),
|
||||
CreateTime: time.Now(),
|
||||
UpdatedAt: time.Now(),
|
||||
CreatedAt: time.Now(),
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadInsertAccount(t *testing.T) {
|
||||
acct2, err := store.LoadInsertAccount(context.Background(), acct)
|
||||
ok, err := store.LoadInsertAccount(context.Background(), acct)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(acct2)
|
||||
t.Log(acct == acct2)
|
||||
t.Log(ok)
|
||||
}
|
||||
|
||||
func TestUpdateAccount(t *testing.T) {
|
||||
@@ -86,12 +85,11 @@ func TestUpdateAccount(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestLoadInsertBlogger(t *testing.T) {
|
||||
blogger2, err := store.LoadInsertBlogger(context.Background(), blogger)
|
||||
ok, err := store.LoadInsertBlogger(context.Background(), blogger)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(blogger2)
|
||||
t.Log(blogger == blogger2)
|
||||
t.Log(ok)
|
||||
}
|
||||
|
||||
func TestUpdateBlogger(t *testing.T) {
|
||||
@@ -104,21 +102,21 @@ func TestUpdateBlogger(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestInsertSeries(t *testing.T) {
|
||||
err := store.InsertSeries(context.Background(), series)
|
||||
err := store.InsertSerie(context.Background(), series)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRemoveSeries(t *testing.T) {
|
||||
err := store.RemoveSeries(context.Background(), 1)
|
||||
err := store.RemoveSerie(context.Background(), 1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUpdateSeries(t *testing.T) {
|
||||
err := store.UpdateSeries(context.Background(), 2, map[string]interface{}{
|
||||
err := store.UpdateSerie(context.Background(), 2, map[string]interface{}{
|
||||
"desc": "update desc",
|
||||
})
|
||||
if err != nil {
|
||||
@@ -127,7 +125,7 @@ func TestUpdateSeries(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestLoadAllSeries(t *testing.T) {
|
||||
series, err := store.LoadAllSeries(context.Background())
|
||||
series, err := store.LoadAllSerie(context.Background())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -136,7 +134,7 @@ func TestLoadAllSeries(t *testing.T) {
|
||||
|
||||
func TestInsertArticle(t *testing.T) {
|
||||
article.ID = 12
|
||||
err := store.InsertArticle(context.Background(), article)
|
||||
err := store.InsertArticle(context.Background(), article, 10)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -150,14 +148,14 @@ func TestRemoveArticle(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDeleteArticle(t *testing.T) {
|
||||
err := store.DeleteArticle(context.Background(), 12)
|
||||
err := store.RemoveArticle(context.Background(), 12)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCleanArticles(t *testing.T) {
|
||||
err := store.CleanArticles(context.Background())
|
||||
err := store.CleanArticles(context.Background(), time.Now())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -173,33 +171,13 @@ func TestUpdateArticle(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestRecoverArticle(t *testing.T) {
|
||||
err := store.RecoverArticle(context.Background(), 12)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadAllArticle(t *testing.T) {
|
||||
articles, err := store.LoadAllArticle(context.Background())
|
||||
_, total, err := store.LoadArticleList(context.Background(), SearchArticles{
|
||||
Page: 1,
|
||||
Limit: 1000,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Logf("load all articles: %d", len(articles))
|
||||
}
|
||||
|
||||
func TestLoadTrashArticles(t *testing.T) {
|
||||
articles, err := store.LoadTrashArticles(context.Background())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Logf("load trash articles: %d", len(articles))
|
||||
}
|
||||
|
||||
func TestLoadDraftArticles(t *testing.T) {
|
||||
articles, err := store.LoadDraftArticles(context.Background())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Logf("load draft articles: %d", len(articles))
|
||||
t.Logf("load all articles: %d", total)
|
||||
}
|
||||
|
||||
8
pkg/cache/store/rdbms.go
vendored
8
pkg/cache/store/rdbms.go
vendored
@@ -3,6 +3,7 @@ package store
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"github.com/eiblog/eiblog/pkg/model"
|
||||
@@ -129,7 +130,7 @@ func (db *rdbms) InsertArticle(ctx context.Context, article *model.Article, star
|
||||
if id < startID {
|
||||
id = startID
|
||||
} else {
|
||||
id += 1
|
||||
id++
|
||||
}
|
||||
article.ID = id
|
||||
}
|
||||
@@ -190,6 +191,11 @@ func (db *rdbms) LoadArticleList(ctx context.Context, search SearchArticles) (mo
|
||||
return articles, int(count), err
|
||||
}
|
||||
|
||||
// DropDatabase drop eiblog database
|
||||
func (db *rdbms) DropDatabase(ctx context.Context) error {
|
||||
return errors.New("can not drop eiblog database in rdbms")
|
||||
}
|
||||
|
||||
// register store
|
||||
func init() {
|
||||
Register("mysql", &rdbms{})
|
||||
|
||||
3
pkg/cache/store/store.go
vendored
3
pkg/cache/store/store.go
vendored
@@ -64,6 +64,9 @@ type Store interface {
|
||||
LoadArticle(ctx context.Context, id int) (*model.Article, error)
|
||||
// LoadArticleList 查找文章列表
|
||||
LoadArticleList(ctx context.Context, search SearchArticles) (model.SortedArticles, int, error)
|
||||
|
||||
// 危险操作
|
||||
DropDatabase(ctx context.Context) error
|
||||
}
|
||||
|
||||
// Driver 存储驱动
|
||||
|
||||
@@ -69,7 +69,6 @@ type Google struct {
|
||||
URL string `yaml:"url"`
|
||||
Tid string `yaml:"tid"`
|
||||
V string `yaml:"v"`
|
||||
T string `yaml:"t"`
|
||||
AdSense string `yaml:"adsense"`
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"github.com/eiblog/eiblog/pkg/cache/store"
|
||||
"github.com/eiblog/eiblog/pkg/config"
|
||||
"github.com/eiblog/eiblog/pkg/internal"
|
||||
)
|
||||
@@ -24,7 +25,8 @@ func (s Storage) BackupData(now time.Time) error {
|
||||
case "mongodb":
|
||||
return backupFromMongoDB(now)
|
||||
default:
|
||||
return errors.New("unsupported database source backup to qiniu")
|
||||
return errors.New("unsupported source backup to qiniu: " +
|
||||
config.Conf.Database.Driver)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,7 +36,8 @@ func (s Storage) RestoreData() error {
|
||||
case "mongodb":
|
||||
return restoreToMongoDB()
|
||||
default:
|
||||
return errors.New("unsupported database source backup to qiniu")
|
||||
return errors.New("unsupported source restore from qiniu: " +
|
||||
config.Conf.Database.Driver)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,6 +98,7 @@ func backupFromMongoDB(now time.Time) error {
|
||||
}
|
||||
|
||||
func restoreToMongoDB() error {
|
||||
// backup file
|
||||
params := internal.ContentParams{
|
||||
Prefix: "blog/",
|
||||
|
||||
@@ -113,6 +117,16 @@ func restoreToMongoDB() error {
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Minute*20)
|
||||
defer cancel()
|
||||
// drop database
|
||||
store, err := store.NewStore(config.Conf.Database.Driver,
|
||||
config.Conf.Database.Source)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = store.DropDatabase(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// unarchive
|
||||
arg := fmt.Sprintf("tar xzf /tmp/eiblog.tar.gz -C /tmp")
|
||||
cmd := exec.CommandContext(ctx, "sh", "-c", arg)
|
||||
@@ -121,7 +135,11 @@ func restoreToMongoDB() error {
|
||||
return err
|
||||
}
|
||||
// restore
|
||||
arg = fmt.Sprintf("mongorestore -h %s -d eiblog /tmp/eiblog", config.Conf.Database.Source)
|
||||
u, err := url.Parse(config.Conf.Database.Source)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
arg = fmt.Sprintf("mongorestore -h %s -d eiblog /tmp/eiblog", u.Host)
|
||||
cmd = exec.CommandContext(ctx, "sh", "-c", arg)
|
||||
return cmd.Run()
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ func Start(restore bool) (err error) {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
logrus.Info("timer: RestoreData success")
|
||||
}
|
||||
// parse duration
|
||||
interval, err := ParseDuration(config.Conf.BackupApp.Interval)
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"fmt"
|
||||
htemplate "html/template"
|
||||
"io/ioutil"
|
||||
"math/rand"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -335,27 +336,34 @@ func handleDisqusCreate(c *gin.Context) {
|
||||
}
|
||||
|
||||
// handleBeaconPage 服务端推送谷歌统计
|
||||
// https://www.thyngster.com/ga4-measurement-protocol-cheatsheet/
|
||||
func handleBeaconPage(c *gin.Context) {
|
||||
ua := c.Request.UserAgent()
|
||||
|
||||
vals := c.Request.URL.Query()
|
||||
vals.Set("v", config.Conf.EiBlogApp.Google.V)
|
||||
vals.Set("tid", config.Conf.EiBlogApp.Google.Tid)
|
||||
vals.Set("t", config.Conf.EiBlogApp.Google.T)
|
||||
cookie, _ := c.Cookie("u")
|
||||
vals.Set("cid", cookie)
|
||||
|
||||
vals.Set("dl", c.Request.Referer())
|
||||
vals.Set("uip", c.ClientIP())
|
||||
vals.Set("dl", c.Request.Referer()) // document location
|
||||
vals.Set("en", "page_view") // event name
|
||||
vals.Set("sct", "1") // Session Count
|
||||
vals.Set("seg", "1") // Session Engagment
|
||||
vals.Set("_uip", c.ClientIP()) // user ip
|
||||
vals.Set("_p", fmt.Sprint(201226219+rand.Intn(499999999))) // random page load hash
|
||||
vals.Set("_ee", "1") // external event
|
||||
go func() {
|
||||
req, err := http.NewRequest("POST", config.Conf.EiBlogApp.Google.URL,
|
||||
strings.NewReader(vals.Encode()))
|
||||
url := config.Conf.EiBlogApp.Google.URL + "?" + vals.Encode()
|
||||
req, err := http.NewRequest("POST", url, nil)
|
||||
if err != nil {
|
||||
logrus.Error("HandleBeaconPage.NewRequest: ", err)
|
||||
return
|
||||
}
|
||||
req.Header.Set("User-Agent", ua)
|
||||
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||
req.Header.Set("Sec-Ch-Ua", c.GetHeader("Sec-Ch-Ua"))
|
||||
req.Header.Set("Sec-Ch-Ua-Platform", c.GetHeader("Sec-Ch-Ua-Platform"))
|
||||
req.Header.Set("Sec-Ch-Ua-Mobile", c.GetHeader("Sec-Ch-Ua-Mobile"))
|
||||
res, err := http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
logrus.Error("HandleBeaconPage.Do: ", err)
|
||||
|
||||
@@ -128,7 +128,7 @@ func QiniuContent(params ContentParams) ([]byte, error) {
|
||||
// manager
|
||||
bucketManager := storage.NewBucketManager(mac, cfg)
|
||||
// list file
|
||||
files, _, _, _, err := bucketManager.ListFiles(params.Conf.Bucket, params.Prefix, "", "", 2)
|
||||
files, _, _, _, err := bucketManager.ListFiles(params.Conf.Bucket, params.Prefix, "", "", 1)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
{{define "ana_js"}}
|
||||
!function(e,n,o){var t=e.screen,a=encodeURIComponent,r=["dt="+a(n.title),"dr="+a(n.referrer),"ul="+(o.language||o.browserLanguage),"sd="+t.colorDepth+"-bit","sr="+t.width+"x"+t.height,"_="+ +new Date],i="?"+r.join("&");e.__beacon_img=new Image,e.__beacon_img.src="/beacon.html"+i}(window,document,navigator,location);
|
||||
{{end}}
|
||||
!function(e,n,o){var t=e.screen,a=encodeURIComponent,r=["dt="+a(n.title),"dr="+a(n.referrer),"ul="+(o.language||o.browserLanguage).toLowerCase(),"sd="+t.colorDepth+"-bit","sr="+t.width+"x"+t.height,"_="+ +new Date],i="?"+r.join("&");e.__beacon_img=new Image,e.__beacon_img.src="/beacon.html"+i}(window,document,navigator,location);
|
||||
{{end}}
|
||||
|
||||
Reference in New Issue
Block a user