Feat: refreshcache

pull/31/head
zijiren233 1 year ago
parent b5151fa2fc
commit 12bcae22f5

@ -0,0 +1,48 @@
package refreshcache
import (
"sync"
"time"
)
type RefreshCache[T any] struct {
lock sync.RWMutex
last time.Time
maxAge time.Duration
refreshFunc func() (T, error)
data T
}
func NewRefreshCache[T any](refreshFunc func() (T, error), maxAge time.Duration) *RefreshCache[T] {
if refreshFunc == nil {
panic("refreshFunc cannot be nil")
}
if maxAge <= 0 {
panic("maxAge must be positive")
}
return &RefreshCache[T]{
refreshFunc: refreshFunc,
maxAge: maxAge,
}
}
func (r *RefreshCache[T]) Get() (data T, err error) {
r.lock.RLock()
if time.Since(r.last) < r.maxAge {
r.lock.RUnlock()
return r.data, nil
}
r.lock.RUnlock()
r.lock.Lock()
defer r.lock.Unlock()
if time.Since(r.last) < r.maxAge {
return r.data, nil
}
defer func() {
if err == nil {
r.data = data
r.last = time.Now()
}
}()
return r.refreshFunc()
}

@ -3,58 +3,46 @@ package bilibili
import (
"errors"
"net/http"
"sync"
"time"
json "github.com/json-iterator/go"
"github.com/synctv-org/synctv/utils"
refreshcache "github.com/synctv-org/synctv/utils/refreshCache"
)
var (
bLock sync.RWMutex
b3, b4 string
bLastUpdateTime time.Time
)
type buvid struct {
b3, b4 string
}
var buvidCache = refreshcache.NewRefreshCache[buvid](func() (buvid, error) {
b3, b4, err := newBuvid()
if err != nil {
return buvid{}, err
}
return buvid{
b3: b3,
b4: b4,
}, nil
}, time.Hour)
func getBuvidCookies() ([]*http.Cookie, error) {
b3, b4, err := getBuvid()
buvid, err := buvidCache.Get()
if err != nil {
return nil, err
}
return []*http.Cookie{
{
Name: "buvid3",
Value: b3,
Value: buvid.b3,
},
{
Name: "buvid4",
Value: b4,
Value: buvid.b4,
},
}, nil
}
func getBuvid() (string, string, error) {
bLock.RLock()
if time.Since(bLastUpdateTime) < time.Hour {
bLock.RUnlock()
return b3, b4, nil
}
bLock.RUnlock()
bLock.Lock()
defer bLock.Unlock()
if time.Since(bLastUpdateTime) < time.Hour {
return b3, b4, nil
}
var err error
b3, b4, err = newBuvid()
if err != nil {
return "", "", err
}
bLastUpdateTime = time.Now()
return b3, b4, nil
}
type buvid struct {
type spiResp struct {
Code int `json:"code"`
Data struct {
B3 string `json:"b_3"`
@ -75,7 +63,7 @@ func newBuvid() (string, string, error) {
return "", "", err
}
defer resp.Body.Close()
var b buvid
var b spiResp
err = json.NewDecoder(resp.Body).Decode(&b)
if err != nil {
return "", "", err

@ -8,11 +8,11 @@ import (
"sort"
"strconv"
"strings"
"sync"
"time"
json "github.com/json-iterator/go"
"github.com/synctv-org/synctv/utils"
refreshcache "github.com/synctv-org/synctv/utils/refreshCache"
)
var (
@ -22,17 +22,25 @@ var (
61, 26, 17, 0, 1, 60, 51, 30, 4, 22, 25, 54, 21, 56, 59, 6, 63, 57, 62, 11,
36, 20, 34, 44, 52,
}
lock sync.RWMutex
imgKey, subKey string
lastUpdateTime time.Time
wbiCache = refreshcache.NewRefreshCache[key](func() (key, error) {
imgKey, subKey, err := getWbiKeys()
if err != nil {
return key{}, err
}
return key{imgKey, subKey}, nil
}, time.Minute*10)
)
type key struct {
imgKey, subKey string
}
func signAndGenerateURL(urlStr string) (string, error) {
urlObj, err := url.Parse(urlStr)
if err != nil {
return "", err
}
imgKey, subKey, err := getWbiKeysCached()
key, err := wbiCache.Get()
if err != nil {
return "", err
}
@ -41,7 +49,7 @@ func signAndGenerateURL(urlStr string) (string, error) {
for k, v := range query {
params[k] = v[0]
}
newParams := encWbi(params, imgKey, subKey)
newParams := encWbi(params, key.imgKey, key.subKey)
for k, v := range newParams {
query.Set(k, v)
}
@ -94,27 +102,6 @@ func sanitizeString(s string) string {
return s
}
func getWbiKeysCached() (string, string, error) {
lock.RLock()
if time.Since(lastUpdateTime).Minutes() < 10 {
defer lock.RUnlock()
return imgKey, subKey, nil
}
lock.RUnlock()
lock.Lock()
defer lock.Unlock()
if time.Since(lastUpdateTime).Minutes() < 10 {
return imgKey, subKey, nil
}
var err error
imgKey, subKey, err = getWbiKeys()
if err != nil {
return "", "", err
}
lastUpdateTime = time.Now()
return imgKey, subKey, nil
}
func getWbiKeys() (string, string, error) {
req, err := http.NewRequest(http.MethodGet, "https://api.bilibili.com/x/web-interface/nav", nil)
if err != nil {

Loading…
Cancel
Save