初始提交:短剧库源码(含转码优化 ultrafast)
This commit is contained in:
@@ -0,0 +1,109 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
func (a *UIApp) handleRankings(writer http.ResponseWriter, request *http.Request) {
|
||||
if request.Method != http.MethodGet {
|
||||
writeJSON(writer, http.StatusMethodNotAllowed, map[string]string{"error": "method not allowed"})
|
||||
return
|
||||
}
|
||||
id := request.URL.Query().Get("board")
|
||||
if id == "" {
|
||||
writeJSON(writer, http.StatusOK, map[string]any{"boards": sourceRankingBoards(request.Context())})
|
||||
return
|
||||
}
|
||||
board, found := findRankingBoard(id)
|
||||
pageText := firstNonEmpty(request.URL.Query().Get("page"), "1")
|
||||
page, err := strconv.Atoi(pageText)
|
||||
if !found || err != nil || page < 1 || page > 500 || board.Source == "huangguo" && page != 1 {
|
||||
writeJSON(writer, http.StatusBadRequest, map[string]string{"error": "榜单或页码无效"})
|
||||
return
|
||||
}
|
||||
if !requireSource(writer, request.Context(), board.Source) {
|
||||
return
|
||||
}
|
||||
ctx, cancel := context.WithTimeout(request.Context(), 40*time.Second)
|
||||
defer cancel()
|
||||
result, err := a.downloader.loadRankingPage(ctx, board, page, request.URL.Query().Get("refresh") == "1")
|
||||
if err != nil {
|
||||
if request.Context().Err() != nil {
|
||||
return
|
||||
}
|
||||
fmt.Printf("%s榜单获取失败: %v\n", board.Source, publicError(err))
|
||||
writeJSON(writer, http.StatusBadGateway, map[string]string{"error": "站点榜单暂不可用,请稍后重试"})
|
||||
return
|
||||
}
|
||||
if ctx.Err() != nil {
|
||||
return
|
||||
}
|
||||
a.acceptRankingDramas(result)
|
||||
a.mu.Lock()
|
||||
saved := a.librarySaved && !a.libraryDirty
|
||||
a.mu.Unlock()
|
||||
writeJSON(writer, http.StatusOK, struct {
|
||||
rankingPage
|
||||
Saved bool `json:"saved"`
|
||||
}{result, saved})
|
||||
}
|
||||
|
||||
func (a *UIApp) acceptRankingDramas(page rankingPage) {
|
||||
if len(page.Items) == 0 {
|
||||
return
|
||||
}
|
||||
key := page.BoardID + ":" + strconv.Itoa(page.Page)
|
||||
a.mu.Lock()
|
||||
if a.rankingApplied == nil {
|
||||
a.rankingApplied = map[string]time.Time{}
|
||||
}
|
||||
if a.rankingApplied[key].Equal(page.FetchedAt) {
|
||||
a.mu.Unlock()
|
||||
return
|
||||
}
|
||||
if len(a.rankingApplied) >= 256 {
|
||||
a.rankingApplied = map[string]time.Time{}
|
||||
}
|
||||
a.rankingApplied[key] = page.FetchedAt
|
||||
fresh := make([]Drama, 0, len(page.Items))
|
||||
for _, item := range page.Items {
|
||||
fresh = append(fresh, item.Drama)
|
||||
}
|
||||
a.normalizeDramaCovers(fresh)
|
||||
newDramas := a.newSortMetadataDramasLocked(fresh)
|
||||
if page.Stale {
|
||||
a.dramas = mergeLoadedDramas(fresh, a.dramas, nil)
|
||||
} else {
|
||||
a.dramas = mergeLoadedDramas(a.dramas, fresh, nil)
|
||||
}
|
||||
a.enqueueSortMetadataLocked(newDramas, false)
|
||||
if a.librarySources == nil {
|
||||
a.librarySources = map[string]librarySourceState{}
|
||||
}
|
||||
source := dramaProvider(fresh[0])
|
||||
state := a.librarySources[source]
|
||||
state.Count = 0
|
||||
for _, drama := range a.dramas {
|
||||
if dramaProvider(drama) == source {
|
||||
state.Count++
|
||||
}
|
||||
}
|
||||
if state.Status == "" {
|
||||
state.Status = "ready"
|
||||
}
|
||||
if page.FetchedAt.After(state.UpdatedAt) {
|
||||
state.UpdatedAt = page.FetchedAt
|
||||
}
|
||||
a.librarySources[source] = state
|
||||
if page.FetchedAt.After(a.loadedAt) {
|
||||
a.loadedAt = page.FetchedAt
|
||||
}
|
||||
a.libraryDirty = true
|
||||
a.libraryRevision++
|
||||
a.mu.Unlock()
|
||||
a.persistLibrary()
|
||||
}
|
||||
Reference in New Issue
Block a user