131 lines
3.2 KiB
Go
131 lines
3.2 KiB
Go
package controller
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"errors"
|
|
_ "golang.org/x/image/webp"
|
|
"image"
|
|
_ "image/gif"
|
|
_ "image/jpeg"
|
|
_ "image/png"
|
|
"io/ioutil"
|
|
"net"
|
|
"net/http"
|
|
"pikapika/main/database/comic_center"
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
var mutexCounter = -1
|
|
var busMutex *sync.Mutex
|
|
var subMutexes []*sync.Mutex
|
|
var imageHttpClient *http.Client
|
|
|
|
// imageSwitchAddress
|
|
// 图片的分流直接使用 switchAddressPattern 可以正常使用
|
|
// 通过ping发现图片的分流地址与ip一致
|
|
// 这里为了域名与官方一致改为域名分流
|
|
var imageSwitchAddresses = map[int]string{
|
|
1: "https://storage.wika" + "wika.xyz",
|
|
2: "https://s2.pica" + "comic.com",
|
|
3: "https://s3.pica" + "comic.com",
|
|
}
|
|
|
|
var imageSwitchAddress int
|
|
|
|
func init() {
|
|
busMutex = &sync.Mutex{}
|
|
for i := 0; i < 5; i++ {
|
|
subMutexes = append(subMutexes, &sync.Mutex{})
|
|
}
|
|
imageHttpClient = &http.Client{
|
|
Transport: &http.Transport{
|
|
TLSHandshakeTimeout: time.Second * 10,
|
|
ExpectContinueTimeout: time.Second * 10,
|
|
ResponseHeaderTimeout: time.Second * 10,
|
|
IdleConnTimeout: time.Second * 10,
|
|
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
|
|
return dialer.DialContext(ctx, network, addr)
|
|
},
|
|
},
|
|
}
|
|
}
|
|
|
|
// takeMutex 下载图片获取一个锁, 这样只能同时下载5张图片
|
|
func takeMutex() *sync.Mutex {
|
|
busMutex.Lock()
|
|
defer busMutex.Unlock()
|
|
mutexCounter = (mutexCounter + 1) % len(subMutexes)
|
|
return subMutexes[mutexCounter]
|
|
}
|
|
|
|
func decodeInfoFromBuff(buff []byte) (image.Image, string, error) {
|
|
buffer := bytes.NewBuffer(buff)
|
|
return image.Decode(buffer)
|
|
}
|
|
|
|
func decodeFromFile(path string) ([]byte, image.Image, string, error) {
|
|
b, e := ioutil.ReadFile(path)
|
|
if e != nil {
|
|
return nil, nil, "", e
|
|
}
|
|
i, f, e := decodeInfoFromBuff(b)
|
|
if e != nil {
|
|
return nil, nil, "", e
|
|
}
|
|
return b, i, f, e
|
|
}
|
|
|
|
// 下载图片并decode
|
|
func decodeFromUrl(fileServer string, path string) ([]byte, image.Image, string, error) {
|
|
useClient := imageHttpClient
|
|
if imageSwitchAddress == -1 {
|
|
useClient = &client.Client
|
|
}
|
|
if server, ok := imageSwitchAddresses[imageSwitchAddress]; ok {
|
|
fileServer = server
|
|
}
|
|
m := takeMutex()
|
|
m.Lock()
|
|
defer m.Unlock()
|
|
request, err := http.NewRequest("GET", fileServer+"/static/"+path, nil)
|
|
if err != nil {
|
|
return nil, nil, "", err
|
|
}
|
|
response, err := useClient.Do(request)
|
|
if err != nil {
|
|
return nil, nil, "", err
|
|
}
|
|
defer response.Body.Close()
|
|
if response.StatusCode != 200 {
|
|
return nil, nil, "", errors.New("code is not 200")
|
|
}
|
|
buff, err := ioutil.ReadAll(response.Body)
|
|
if err != nil {
|
|
return nil, nil, "", err
|
|
}
|
|
img, format, err := decodeInfoFromBuff(buff)
|
|
if err != nil {
|
|
return nil, nil, "", err
|
|
}
|
|
return buff, img, format, err
|
|
}
|
|
|
|
// decodeFromCache 仅下载使用
|
|
func decodeFromCache(fileServer string, path string) ([]byte, image.Image, string, error) {
|
|
cache := comic_center.FindRemoteImage(fileServer, path)
|
|
if cache != nil {
|
|
buff, err := ioutil.ReadFile(remotePath(cache.LocalPath))
|
|
if err != nil {
|
|
return nil, nil, "", err
|
|
}
|
|
img, format, err := decodeInfoFromBuff(buff)
|
|
if err != nil {
|
|
return nil, nil, "", err
|
|
}
|
|
return buff, img, format, err
|
|
}
|
|
return nil, nil, "", errors.New("not found")
|
|
}
|