460 lines
12 KiB
Go
460 lines
12 KiB
Go
|
package controller
|
||
|
|
||
|
import (
|
||
|
"context"
|
||
|
"encoding/json"
|
||
|
"fmt"
|
||
|
source "github.com/niuhuan/pica-go"
|
||
|
"net"
|
||
|
"net/http"
|
||
|
"net/url"
|
||
|
"pgo/pikapi/database/comic_center"
|
||
|
"pgo/pikapi/database/network_cache"
|
||
|
"pgo/pikapi/database/properties"
|
||
|
"regexp"
|
||
|
"strconv"
|
||
|
"strings"
|
||
|
"time"
|
||
|
)
|
||
|
|
||
|
func InitClient() {
|
||
|
client.Timeout = time.Second * 60
|
||
|
switchAddress, _ = properties.LoadSwitchAddress()
|
||
|
proxy, _ := properties.LoadProxy()
|
||
|
changeProxyUrl(proxy)
|
||
|
}
|
||
|
|
||
|
var client = source.Client{}
|
||
|
var dialer = &net.Dialer{
|
||
|
Timeout: 30 * time.Second,
|
||
|
KeepAlive: 30 * time.Second,
|
||
|
}
|
||
|
|
||
|
// SwitchAddress
|
||
|
// addr = "172.67.7.24:443"
|
||
|
// addr = "104.20.180.50:443"
|
||
|
// addr = "172.67.208.169:443"
|
||
|
var switchAddress = ""
|
||
|
var switchAddressPattern, _ = regexp.Compile("^.+picacomic\\.com:\\d+$")
|
||
|
|
||
|
func switchAddressContext(ctx context.Context, network, addr string) (net.Conn, error) {
|
||
|
if switchAddressPattern.MatchString(addr) && switchAddress != "" {
|
||
|
addr = switchAddress
|
||
|
}
|
||
|
return dialer.DialContext(ctx, network, addr)
|
||
|
}
|
||
|
|
||
|
func changeProxyUrl(urlStr string) bool {
|
||
|
if urlStr == "" {
|
||
|
client.Transport = &http.Transport{
|
||
|
TLSHandshakeTimeout: time.Second * 10,
|
||
|
ExpectContinueTimeout: time.Second * 10,
|
||
|
ResponseHeaderTimeout: time.Second * 10,
|
||
|
IdleConnTimeout: time.Second * 10,
|
||
|
DialContext: switchAddressContext,
|
||
|
}
|
||
|
return false
|
||
|
}
|
||
|
client.Transport = &http.Transport{
|
||
|
Proxy: func(_ *http.Request) (*url.URL, error) {
|
||
|
return url.Parse(urlStr)
|
||
|
},
|
||
|
TLSHandshakeTimeout: time.Second * 10,
|
||
|
ExpectContinueTimeout: time.Second * 10,
|
||
|
ResponseHeaderTimeout: time.Second * 10,
|
||
|
IdleConnTimeout: time.Second * 10,
|
||
|
DialContext: switchAddressContext,
|
||
|
}
|
||
|
return true
|
||
|
}
|
||
|
|
||
|
func cacheable(key string, expire time.Duration, reload func() (interface{}, error)) (string, error) {
|
||
|
// CACHE
|
||
|
cache := network_cache.LoadCache(key, expire)
|
||
|
if cache != "" {
|
||
|
return cache, nil
|
||
|
}
|
||
|
// obj
|
||
|
obj, err := reload()
|
||
|
if err != nil {
|
||
|
return "", err
|
||
|
}
|
||
|
buff, err := json.Marshal(obj)
|
||
|
// push to cache
|
||
|
if err != nil {
|
||
|
return "", err
|
||
|
}
|
||
|
// return
|
||
|
cache = string(buff)
|
||
|
network_cache.SaveCache(key, cache)
|
||
|
return cache, nil
|
||
|
}
|
||
|
|
||
|
func categories() (string, error) {
|
||
|
key := "CATEGORIES"
|
||
|
expire := time.Hour * 3
|
||
|
cache := network_cache.LoadCache(key, expire)
|
||
|
if cache != "" {
|
||
|
return cache, nil
|
||
|
}
|
||
|
categories, err := client.Categories()
|
||
|
if err != nil {
|
||
|
return "", err
|
||
|
}
|
||
|
var dbCategories []comic_center.Category
|
||
|
for _, c := range categories {
|
||
|
dbCategories = append(dbCategories, comic_center.Category{
|
||
|
ID: c.Id,
|
||
|
Title: c.Title,
|
||
|
Description: c.Description,
|
||
|
IsWeb: c.IsWeb,
|
||
|
Active: c.Active,
|
||
|
Link: c.Link,
|
||
|
ThumbOriginalName: c.Thumb.OriginalName,
|
||
|
ThumbFileServer: c.Thumb.FileServer,
|
||
|
ThumbPath: c.Thumb.Path,
|
||
|
})
|
||
|
}
|
||
|
err = comic_center.UpSetCategories(&dbCategories)
|
||
|
if err != nil {
|
||
|
return "", err
|
||
|
}
|
||
|
buff, _ := json.Marshal(&categories)
|
||
|
cache = string(buff)
|
||
|
network_cache.SaveCache(key, cache)
|
||
|
return cache, nil
|
||
|
}
|
||
|
|
||
|
func comics(params string) (string, error) {
|
||
|
var paramsStruct struct {
|
||
|
Category string `json:"category"`
|
||
|
Tag string `json:"tag"`
|
||
|
CreatorId string `json:"creatorId"`
|
||
|
ChineseTeam string `json:"chineseTeam"`
|
||
|
Sort string `json:"sort"`
|
||
|
Page int `json:"page"`
|
||
|
}
|
||
|
json.Unmarshal([]byte(params), ¶msStruct)
|
||
|
return cacheable(
|
||
|
fmt.Sprintf("COMICS$%s$%s$%s$%s$%s$%d", paramsStruct.Category, paramsStruct.Tag, paramsStruct.CreatorId, paramsStruct.ChineseTeam, paramsStruct.Sort, paramsStruct.Page),
|
||
|
time.Hour*2,
|
||
|
func() (interface{}, error) {
|
||
|
return client.Comics(paramsStruct.Category, paramsStruct.Tag, paramsStruct.CreatorId, paramsStruct.ChineseTeam, paramsStruct.Sort, paramsStruct.Page)
|
||
|
},
|
||
|
)
|
||
|
}
|
||
|
|
||
|
func searchComics(params string) (string, error) {
|
||
|
var paramsStruct struct {
|
||
|
Categories []string `json:"categories"`
|
||
|
Keyword string `json:"keyword"`
|
||
|
Sort string `json:"sort"`
|
||
|
Page int `json:"page"`
|
||
|
}
|
||
|
json.Unmarshal([]byte(params), ¶msStruct)
|
||
|
categories := paramsStruct.Categories
|
||
|
keyword := paramsStruct.Keyword
|
||
|
sort := paramsStruct.Sort
|
||
|
page := paramsStruct.Page
|
||
|
//
|
||
|
var categoriesInKey string
|
||
|
if len(categories) == 0 {
|
||
|
categoriesInKey = ""
|
||
|
} else {
|
||
|
b, _ := json.Marshal(categories)
|
||
|
categoriesInKey = string(b)
|
||
|
}
|
||
|
return cacheable(
|
||
|
fmt.Sprintf("SEARCH$%s$%s$%s$%d", categoriesInKey, keyword, sort, page),
|
||
|
time.Hour*2,
|
||
|
func() (interface{}, error) {
|
||
|
return client.SearchComics(categories, keyword, sort, page)
|
||
|
},
|
||
|
)
|
||
|
}
|
||
|
|
||
|
func randomComics() (string, error) {
|
||
|
return cacheable(
|
||
|
fmt.Sprintf("RANDOM"),
|
||
|
time.Millisecond*1,
|
||
|
func() (interface{}, error) {
|
||
|
return client.RandomComics()
|
||
|
},
|
||
|
)
|
||
|
}
|
||
|
|
||
|
func leaderboard(typeName string) (string, error) {
|
||
|
return cacheable(
|
||
|
fmt.Sprintf("LEADERBOARD$%s", typeName),
|
||
|
time.Second*200,
|
||
|
func() (interface{}, error) {
|
||
|
return client.Leaderboard(typeName)
|
||
|
},
|
||
|
)
|
||
|
}
|
||
|
|
||
|
func comicInfo(comicId string) (string, error) {
|
||
|
var err error
|
||
|
var comic *source.ComicInfo
|
||
|
// cache
|
||
|
key := fmt.Sprintf("COMIC_INFO$%s", comicId)
|
||
|
expire := time.Hour * 24 * 7
|
||
|
cache := network_cache.LoadCache(key, expire)
|
||
|
if cache != "" {
|
||
|
var co source.ComicInfo
|
||
|
err = json.Unmarshal([]byte(cache), &co)
|
||
|
if err != nil {
|
||
|
panic(err)
|
||
|
return "", err
|
||
|
}
|
||
|
comic = &co
|
||
|
} else {
|
||
|
// get
|
||
|
comic, err = client.ComicInfo(comicId)
|
||
|
if err != nil {
|
||
|
return "", err
|
||
|
}
|
||
|
var buff []byte
|
||
|
buff, err = json.Marshal(comic)
|
||
|
if err != nil {
|
||
|
return "", err
|
||
|
}
|
||
|
cache = string(buff)
|
||
|
network_cache.SaveCache(key, cache)
|
||
|
}
|
||
|
// 标记历史记录
|
||
|
view := comic_center.ComicView{}
|
||
|
view.ID = comicId
|
||
|
view.CreatedAt = comic.CreatedAt
|
||
|
view.UpdatedAt = comic.UpdatedAt
|
||
|
view.Title = comic.Title
|
||
|
view.Author = comic.Author
|
||
|
view.PagesCount = int32(comic.PagesCount)
|
||
|
view.EpsCount = int32(comic.EpsCount)
|
||
|
view.Finished = comic.Finished
|
||
|
c, _ := json.Marshal(comic.Categories)
|
||
|
view.Categories = string(c)
|
||
|
view.ThumbOriginalName = comic.Thumb.OriginalName
|
||
|
view.ThumbFileServer = comic.Thumb.FileServer
|
||
|
view.ThumbPath = comic.Thumb.Path
|
||
|
view.LikesCount = int32(comic.LikesCount)
|
||
|
view.Description = comic.Description
|
||
|
view.ChineseTeam = comic.ChineseTeam
|
||
|
t, _ := json.Marshal(comic.Tags)
|
||
|
view.Tags = string(t)
|
||
|
view.AllowDownload = comic.AllowDownload
|
||
|
view.ViewsCount = int32(comic.ViewsCount)
|
||
|
view.IsFavourite = comic.IsFavourite
|
||
|
view.IsLiked = comic.IsLiked
|
||
|
view.CommentsCount = int32(comic.CommentsCount)
|
||
|
err = comic_center.ViewComicUpdateInfo(&view)
|
||
|
if err != nil {
|
||
|
return "", err
|
||
|
}
|
||
|
// return
|
||
|
return cache, nil
|
||
|
}
|
||
|
|
||
|
func ComicInfoCleanCache(comicId string) {
|
||
|
key := fmt.Sprintf("COMIC_INFO$%s", comicId)
|
||
|
network_cache.RemoveCache(key)
|
||
|
}
|
||
|
|
||
|
func epPage(params string) (string, error) {
|
||
|
var paramsStruct struct {
|
||
|
ComicId string `json:"comicId"`
|
||
|
Page int `json:"page"`
|
||
|
}
|
||
|
json.Unmarshal([]byte(params), ¶msStruct)
|
||
|
comicId := paramsStruct.ComicId
|
||
|
page := paramsStruct.Page
|
||
|
//
|
||
|
return cacheable(
|
||
|
fmt.Sprintf("COMIC_EP_PAGE$%s$%d", comicId, page),
|
||
|
time.Hour*2,
|
||
|
func() (interface{}, error) {
|
||
|
return client.ComicEpPage(comicId, page)
|
||
|
},
|
||
|
)
|
||
|
}
|
||
|
|
||
|
func comicPicturePageWithQuality(params string) (string, error) {
|
||
|
var paramsStruct struct {
|
||
|
ComicId string `json:"comicId"`
|
||
|
EpOrder int `json:"epOrder"`
|
||
|
Page int `json:"page"`
|
||
|
Quality string `json:"quality"`
|
||
|
}
|
||
|
json.Unmarshal([]byte(params), ¶msStruct)
|
||
|
comicId := paramsStruct.ComicId
|
||
|
epOrder := paramsStruct.EpOrder
|
||
|
page := paramsStruct.Page
|
||
|
quality := paramsStruct.Quality
|
||
|
//
|
||
|
return cacheable(
|
||
|
fmt.Sprintf("COMIC_EP_PAGE$%s$%ds$%ds$%s", comicId, epOrder, page, quality),
|
||
|
time.Hour*2,
|
||
|
func() (interface{}, error) {
|
||
|
return client.ComicPicturePageWithQuality(comicId, epOrder, page, quality)
|
||
|
},
|
||
|
)
|
||
|
}
|
||
|
|
||
|
func switchLike(comicId string) (string, error) {
|
||
|
point, err := client.SwitchLike(comicId)
|
||
|
if err != nil {
|
||
|
return "", err
|
||
|
}
|
||
|
// 更新viewLog里面的favour
|
||
|
comic_center.ViewComicUpdateLike(comicId, strings.HasPrefix(*point, "un"))
|
||
|
// 删除缓存
|
||
|
ComicInfoCleanCache(comicId)
|
||
|
return *point, nil
|
||
|
}
|
||
|
|
||
|
func switchFavourite(comicId string) (string, error) {
|
||
|
point, err := client.SwitchFavourite(comicId)
|
||
|
if err != nil {
|
||
|
return "", err
|
||
|
}
|
||
|
// 更新viewLog里面的favour
|
||
|
comic_center.ViewComicUpdateFavourite(comicId, strings.HasPrefix(*point, "un"))
|
||
|
// 删除缓存
|
||
|
ComicInfoCleanCache(comicId)
|
||
|
return *point, nil
|
||
|
}
|
||
|
|
||
|
func favouriteComics(params string) (string, error) {
|
||
|
var paramsStruct struct {
|
||
|
Sort string `json:"sort"`
|
||
|
Page int `json:"page"`
|
||
|
}
|
||
|
json.Unmarshal([]byte(params), ¶msStruct)
|
||
|
sort := paramsStruct.Sort
|
||
|
page := paramsStruct.Page
|
||
|
//
|
||
|
point, err := client.FavouriteComics(sort, page)
|
||
|
if err != nil {
|
||
|
return "", err
|
||
|
}
|
||
|
str, err := json.Marshal(point)
|
||
|
if err != nil {
|
||
|
return "", err
|
||
|
}
|
||
|
return string(str), nil
|
||
|
}
|
||
|
|
||
|
func recommendation(comicId string) (string, error) {
|
||
|
return cacheable(
|
||
|
fmt.Sprintf("RECOMMENDATION$%s", comicId),
|
||
|
time.Hour*2,
|
||
|
func() (interface{}, error) {
|
||
|
return client.ComicRecommendation(comicId)
|
||
|
},
|
||
|
)
|
||
|
}
|
||
|
|
||
|
func comments(params string) (string, error) {
|
||
|
var paramsStruct struct {
|
||
|
ComicId string `json:"comicId"`
|
||
|
Page int `json:"page"`
|
||
|
}
|
||
|
json.Unmarshal([]byte(params), ¶msStruct)
|
||
|
comicId := paramsStruct.ComicId
|
||
|
page := paramsStruct.Page
|
||
|
return cacheable(
|
||
|
fmt.Sprintf("COMMENTS$%s$%d", comicId, page),
|
||
|
time.Hour*2,
|
||
|
func() (interface{}, error) {
|
||
|
return client.ComicCommentsPage(comicId, page)
|
||
|
},
|
||
|
)
|
||
|
}
|
||
|
|
||
|
func commentChildren(params string) (string, error) {
|
||
|
var paramsStruct struct {
|
||
|
CommentId string `json:"commentId"`
|
||
|
Page int `json:"page"`
|
||
|
}
|
||
|
json.Unmarshal([]byte(params), ¶msStruct)
|
||
|
commentId := paramsStruct.CommentId
|
||
|
page := paramsStruct.Page
|
||
|
return cacheable(
|
||
|
fmt.Sprintf("COMMENT_CHILDREN$%s$%d", commentId, page),
|
||
|
time.Hour*2,
|
||
|
func() (interface{}, error) {
|
||
|
return client.CommentChildren(commentId, page)
|
||
|
},
|
||
|
)
|
||
|
}
|
||
|
|
||
|
func postComment(params string) (string, error) {
|
||
|
var paramsStruct struct {
|
||
|
ComicId string `json:"comicId"`
|
||
|
Content string `json:"content"`
|
||
|
}
|
||
|
json.Unmarshal([]byte(params), ¶msStruct)
|
||
|
err := client.PostComment(paramsStruct.ComicId, paramsStruct.Content)
|
||
|
if err != nil {
|
||
|
return "", err
|
||
|
}
|
||
|
network_cache.RemoveCaches("MY_COMMENTS$%")
|
||
|
network_cache.RemoveCaches(fmt.Sprintf("COMMENTS$%s$%%", paramsStruct.ComicId))
|
||
|
return "", nil
|
||
|
}
|
||
|
|
||
|
func postChildComment(params string) (string, error) {
|
||
|
var paramsStruct struct {
|
||
|
ComicId string `json:"comicId"`
|
||
|
CommentId string `json:"commentId"`
|
||
|
Content string `json:"content"`
|
||
|
}
|
||
|
json.Unmarshal([]byte(params), ¶msStruct)
|
||
|
err := client.PostChildComment(paramsStruct.CommentId, paramsStruct.Content)
|
||
|
if err != nil {
|
||
|
return "", err
|
||
|
}
|
||
|
network_cache.RemoveCaches(fmt.Sprintf("COMMENT_CHILDREN$%s$%%", paramsStruct.CommentId))
|
||
|
network_cache.RemoveCaches("MY_COMMENTS$%")
|
||
|
network_cache.RemoveCaches(fmt.Sprintf("COMMENTS$%s$%%", paramsStruct.ComicId))
|
||
|
return "", nil
|
||
|
}
|
||
|
|
||
|
func myComments(pageStr string) (string, error) {
|
||
|
page, err := strconv.Atoi(pageStr)
|
||
|
if err != nil {
|
||
|
return "", err
|
||
|
}
|
||
|
return cacheable(
|
||
|
fmt.Sprintf("MY_COMMENTS$%d", page),
|
||
|
time.Hour*2,
|
||
|
func() (interface{}, error) {
|
||
|
return client.MyComments(page)
|
||
|
},
|
||
|
)
|
||
|
}
|
||
|
|
||
|
func games(pageStr string) (string, error) {
|
||
|
page, err := strconv.Atoi(pageStr)
|
||
|
if err != nil {
|
||
|
return "", err
|
||
|
}
|
||
|
return cacheable(
|
||
|
fmt.Sprintf("GAMES$%d", page),
|
||
|
time.Hour*2,
|
||
|
func() (interface{}, error) {
|
||
|
return client.GamePage(page)
|
||
|
},
|
||
|
)
|
||
|
}
|
||
|
|
||
|
func game(gameId string) (string, error) {
|
||
|
return cacheable(
|
||
|
fmt.Sprintf("GAME$%s", gameId),
|
||
|
time.Hour*2,
|
||
|
func() (interface{}, error) {
|
||
|
return client.GameInfo(gameId)
|
||
|
},
|
||
|
)
|
||
|
}
|