Skip to content

Commit

Permalink
fix: v1.0.4
Browse files Browse the repository at this point in the history
是什么,包含什么改变?:
1. 新增 enid 字段,该字段是 dedao 每本书的唯一 id,既可以用来请求到书的详情页,也可作为每一个 feed 的唯一 id;
2. atom 文件的创建时间、更新时间加以区别;
3. 优化函数注释以及打印日志;
4. main_test.go 增加单元测试函数;

如何解决的问题?:
无

本次提交影响范围:
all
  • Loading branch information
d100972 committed Jun 21, 2024
1 parent 05dc139 commit dcb18e6
Show file tree
Hide file tree
Showing 3 changed files with 125 additions and 4 deletions.
3 changes: 3 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@ go 1.20
require (
github.com/gin-gonic/gin v1.10.0
github.com/gorilla/feeds v1.2.0
github.com/stretchr/testify v1.9.0
)

require (
github.com/bytedance/sonic v1.11.6 // indirect
github.com/bytedance/sonic/loader v0.1.1 // indirect
github.com/cloudwego/base64x v0.1.4 // indirect
github.com/cloudwego/iasm v0.2.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect
github.com/go-playground/locales v0.14.1 // indirect
Expand All @@ -25,6 +27,7 @@ require (
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.2.12 // indirect
golang.org/x/arch v0.8.0 // indirect
Expand Down
28 changes: 24 additions & 4 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ type Book struct {
PublishTime string `json:"publish_time"`
Uptime string `json:"uptime"`
OtherShareSummary string `json:"other_share_summary"`
Enid string `json:"enid"`
Enid string `json:"enid"` // dedao 每本书的唯一标识
}

type Response struct {
Expand All @@ -43,13 +43,21 @@ func initLogger() *log.Logger {
}

var logger = initLogger()
var initialCreatedTime time.Time

func init() {
// 初始化时设置创建时间
initialCreatedTime = time.Now()
}

// fetchBooks 从得到获取电子书列表
func fetchBooks() ([]Book, error) {
url := "https://m.igetget.com/native/api/ebook/getBookList"
payload := `{"count": 50, "max_id": 0, "sort": "time", "since_id": 0}`

req, err := http.NewRequest("POST", url, strings.NewReader(payload))
if err != nil {
logger.Println("Error creating request:", err)
return nil, err
}

Expand All @@ -59,6 +67,7 @@ func fetchBooks() ([]Book, error) {
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
logger.Println("Error sending request:", err)
return nil, err
}
defer resp.Body.Close()
Expand All @@ -67,23 +76,32 @@ func fetchBooks() ([]Book, error) {
C Response `json:"c"`
}
if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
logger.Println("Error decoding response:", err)
return nil, err
}

return result.C.List, nil
}

// generateAtom 生成 Atom 订阅源
func generateAtom(books []Book) (string, error) {
now := time.Now()
feed := &feeds.Feed{
Title: "得到最新电子书 Atom 订阅源",
Link: &feeds.Link{Href: "https://m.igetget.com/native/ebook/#/ebook/newBookList"},
Description: "得到最新电子书更新",
Created: now,
Created: initialCreatedTime,
Updated: now,
}

// book detail url: https://www.dedao.cn/ebook/detail?id=enid
for _, book := range books {
createdTime, err := time.Parse("2006-01-02 15:04:05", book.Uptime)
if err != nil {
logger.Println("Error parsing time:", err)
continue
}

item := &feeds.Item{
Title: book.Title,
Link: &feeds.Link{Href: fmt.Sprintf("https://www.dedao.cn/ebook/detail?id=%s", book.Enid)},
Expand All @@ -96,8 +114,8 @@ func generateAtom(books []Book) (string, error) {
book.PublishTime,
),
Author: &feeds.Author{Name: book.Author},
Created: now,
Id: book.Cover,
Created: createdTime,
Id: book.Enid,
Description: book.OtherShareSummary,
}
feed.Items = append(feed.Items, item)
Expand All @@ -112,6 +130,7 @@ func generateAtom(books []Book) (string, error) {
return atom, nil
}

// saveAtomToFile 将 Atom 订阅源保存到文件
func saveAtomToFile(atom string) error {
file, err := os.Create("dedao.atom")
if err != nil {
Expand All @@ -129,6 +148,7 @@ func saveAtomToFile(atom string) error {
return nil
}

// updateAtomFile 更新 Atom 订阅源
func updateAtomFile() {
defer func() {
if r := recover(); r != nil {
Expand Down
98 changes: 98 additions & 0 deletions main_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
package main

import (
"net/http"
"net/http/httptest"
"os"
"testing"
"time"

"github.com/gin-gonic/gin"
"github.com/stretchr/testify/assert"
)

func TestFetchBooks(t *testing.T) {
books, err := fetchBooks()
if err != nil {
t.Fatalf("fetchBooks failed: %v", err)
}

if len(books) != 50 {
t.Fatalf("expected 50 books, got %d", len(books))
}
}

func TestGenerateAtom(t *testing.T) {
books := []Book{
{
Author: "Author1",
Cover: "http://example.com/cover1.jpg",
Title: "Title1",
AuthorInfo: "Author Info 1",
BookIntro: "Book Intro 1",
PublishTime: "2023-01-01",
Uptime: "2023-01-01 00:00:00",
OtherShareSummary: "Summary 1",
Enid: "enid1",
},
}

atom, err := generateAtom(books)
if err != nil {
t.Fatalf("generateAtom failed: %v", err)
}

assert.Contains(t, atom, "<title>Title1</title>")
assert.Contains(t, atom, "http://example.com/cover1.jpg")
}

func TestSaveAtomToFile(t *testing.T) {
atom := "<feed><title>Test Feed</title></feed>"
err := saveAtomToFile(atom)
if err != nil {
t.Fatalf("saveAtomToFile failed: %v", err)
}

data, err := os.ReadFile("dedao.atom")
if err != nil {
t.Fatalf("ReadFile failed: %v", err)
}

assert.Equal(t, atom, string(data))
}

func TestUpdateAtomFile(t *testing.T) {
go updateAtomFile()

time.Sleep(5 * time.Second)

data, err := os.ReadFile("dedao.atom")
if err != nil {
t.Fatalf("ReadFile failed: %v", err)
}

assert.Contains(t, string(data), "<feed xmlns=\"http://www.w3.org/2005/Atom\">")
}

func TestMainRoute(t *testing.T) {
gin.SetMode(gin.TestMode)
r := gin.Default()

r.GET("/feeds/dedao.atom", func(c *gin.Context) {
data, err := os.ReadFile("dedao.atom")
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Read Atom file failed"})
return
}

c.Header("Content-Type", "application/atom+xml; charset=utf-8")
c.Data(http.StatusOK, "application/atom+xml; charset=utf-8", data)
})

req, _ := http.NewRequest("GET", "/feeds/dedao.atom", nil)
w := httptest.NewRecorder()
r.ServeHTTP(w, req)

assert.Equal(t, http.StatusOK, w.Code)
assert.Contains(t, w.Body.String(), "<feed xmlns=\"http://www.w3.org/2005/Atom\">")
}

0 comments on commit dcb18e6

Please sign in to comment.