初始提交:短剧库源码(含转码优化 ultrafast)
This commit is contained in:
@@ -0,0 +1,67 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
type huangdouDetailEntry struct {
|
||||
row map[string]any
|
||||
expiresAt time.Time
|
||||
}
|
||||
|
||||
type huangdouDetailCall struct {
|
||||
done chan struct{}
|
||||
row map[string]any
|
||||
err error
|
||||
}
|
||||
|
||||
func (d *Downloader) huangdouDetail(ctx context.Context, id string) (map[string]any, error) {
|
||||
if !rankingSourceID.MatchString(id) {
|
||||
return nil, errors.New("无效的黄豆剧集 ID")
|
||||
}
|
||||
d.providerMu.Lock()
|
||||
if cached, found := d.huangdouDetails[id]; found && time.Now().Before(cached.expiresAt) {
|
||||
d.providerMu.Unlock()
|
||||
return cached.row, nil
|
||||
}
|
||||
if pending := d.huangdouDetailPending[id]; pending != nil {
|
||||
d.providerMu.Unlock()
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return nil, ctx.Err()
|
||||
case <-pending.done:
|
||||
if (errors.Is(pending.err, context.Canceled) || errors.Is(pending.err, context.DeadlineExceeded)) && ctx.Err() == nil {
|
||||
return d.huangdouDetail(ctx, id)
|
||||
}
|
||||
return pending.row, pending.err
|
||||
}
|
||||
}
|
||||
if d.huangdouDetailPending == nil {
|
||||
d.huangdouDetailPending = make(map[string]*huangdouDetailCall)
|
||||
}
|
||||
call := &huangdouDetailCall{done: make(chan struct{})}
|
||||
d.huangdouDetailPending[id] = call
|
||||
d.providerMu.Unlock()
|
||||
var decoded any
|
||||
err := newHuangdouAPIClient(d).call(ctx, "/drama/detail", map[string]any{"id": id}, &decoded)
|
||||
row := huangdouDataMap(decoded)
|
||||
if err == nil && strings.TrimPrefix(mapString(row, "id", "drama_id"), "rp_") != id {
|
||||
row = nil
|
||||
err = errors.New("黄豆详情返回了其他剧集")
|
||||
}
|
||||
d.providerMu.Lock()
|
||||
if err == nil {
|
||||
if d.huangdouDetails == nil || len(d.huangdouDetails) >= 128 {
|
||||
d.huangdouDetails = make(map[string]huangdouDetailEntry)
|
||||
}
|
||||
d.huangdouDetails[id] = huangdouDetailEntry{row: row, expiresAt: time.Now().Add(dramaRefreshRetryDelay)}
|
||||
}
|
||||
call.row, call.err = row, err
|
||||
delete(d.huangdouDetailPending, id)
|
||||
close(call.done)
|
||||
d.providerMu.Unlock()
|
||||
return row, err
|
||||
}
|
||||
Reference in New Issue
Block a user