mirror of
https://codeberg.org/VnPower/PixivFE
synced 2024-12-06 19:16:23 +01:00
4cffa928b8
core/mangaseries: inline comments core/types: comment out debug statements
118 lines
3.5 KiB
Go
118 lines
3.5 KiB
Go
package core
|
|
|
|
import (
|
|
"fmt"
|
|
"net/http"
|
|
"strings"
|
|
"time"
|
|
|
|
"codeberg.org/vnpower/pixivfe/v2/audit"
|
|
"codeberg.org/vnpower/pixivfe/v2/i18n"
|
|
"codeberg.org/vnpower/pixivfe/v2/server/session"
|
|
|
|
"github.com/goccy/go-json"
|
|
)
|
|
|
|
/*
|
|
TODO: occasionally, Pixiv feels like returning an HTML response instead of the expected JSON,
|
|
causing an unmarshalling error on our end and forcing a refresh by the user
|
|
|
|
as a (super secret and hardcoded) workaround, we implement automatic retries to
|
|
eventually get the JSON response we need (usually only takes a single retry)
|
|
|
|
from qualitative testing, it seems like the interval between requests doesn't actually matter,
|
|
just the fact that we send a second request is enough
|
|
*/
|
|
|
|
const (
|
|
maxRetries = 5
|
|
retryDelay = 10 * time.Millisecond
|
|
)
|
|
|
|
type Ranking struct {
|
|
Contents []RankingContent `json:"contents"`
|
|
Mode string `json:"mode"`
|
|
Content string `json:"content"`
|
|
Page int `json:"page"`
|
|
RankTotal int `json:"rank_total"`
|
|
CurrentDate string `json:"date"`
|
|
PrevDateRaw json.RawMessage `json:"prev_date"`
|
|
NextDateRaw json.RawMessage `json:"next_date"`
|
|
PrevDate string
|
|
NextDate string
|
|
}
|
|
|
|
type RankingContent struct {
|
|
Title string `json:"title"`
|
|
Thumbnail string `json:"url"`
|
|
Thumbnails Thumbnails
|
|
Pages int `json:"illust_page_count,string"`
|
|
ArtistName string `json:"user_name"`
|
|
ArtistAvatar string `json:"profile_img"`
|
|
ID int `json:"illust_id"`
|
|
ArtistID int `json:"user_id"`
|
|
Rank int `json:"rank"`
|
|
IllustType int `json:"illust_type,string"`
|
|
XRestrict int // zero field for template
|
|
}
|
|
|
|
// see core/types.go for the Ranking struct
|
|
|
|
func GetRanking(auditor *audit.Auditor, r *http.Request, mode, content, date, page string) (Ranking, error) {
|
|
// log.Printf("GetRanking called with mode: %s, content: %s, date: %s, page: %s", mode, content, date, page)
|
|
|
|
URL := GetRankingURL(mode, content, date, page)
|
|
// log.Printf("Ranking URL: %s", URL)
|
|
|
|
var ranking Ranking
|
|
var lastErr error
|
|
|
|
for attempt := 0; attempt < maxRetries; attempt++ {
|
|
i18n.Sprintf("Attempt %d of %d", attempt+1, maxRetries)
|
|
|
|
resp, err := API_GET(r.Context(), auditor, URL, "", r.Header)
|
|
if err != nil {
|
|
i18n.Errorf("API_GET error: %v", err)
|
|
return ranking, err
|
|
}
|
|
|
|
proxiedResp, err := session.ProxyImageUrl(r, resp.Body)
|
|
if err != nil {
|
|
return ranking, err
|
|
}
|
|
|
|
err = json.Unmarshal([]byte(proxiedResp), &ranking)
|
|
if err == nil {
|
|
i18n.Sprintf("JSON unmarshalling successful on attempt %d", attempt+1)
|
|
lastErr = nil // Reset lastErr on successful unmarshalling
|
|
break
|
|
}
|
|
|
|
lastErr = err
|
|
i18n.Errorf("JSON unmarshalling error on attempt %d: %v", attempt+1, err)
|
|
|
|
if attempt < maxRetries-1 {
|
|
i18n.Sprintf("Retrying in %v", retryDelay)
|
|
time.Sleep(retryDelay)
|
|
}
|
|
}
|
|
|
|
if lastErr != nil {
|
|
// NOTE: This shouldn't happen; indicative of a different issue
|
|
i18n.Errorf("All attempts failed. Last error: %v", lastErr)
|
|
return ranking, lastErr
|
|
}
|
|
|
|
ranking.PrevDate = strings.ReplaceAll(string(ranking.PrevDateRaw[:]), "\"", "")
|
|
ranking.NextDate = strings.ReplaceAll(string(ranking.NextDateRaw[:]), "\"", "")
|
|
|
|
// Populate thumbnails
|
|
if err := ranking.PopulateThumbnails(auditor); err != nil {
|
|
return ranking, fmt.Errorf("failed to populate thumbnails for ranking: %w", err)
|
|
}
|
|
|
|
// log.Printf("GetRanking completed successfully. PrevDate: %s, NextDate: %s", ranking.PrevDate, ranking.NextDate)
|
|
|
|
return ranking, nil
|
|
}
|