feat: add shared query param helpers for jikan
This commit is contained in:
@@ -3,6 +3,8 @@ package jikan
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
@@ -15,7 +17,9 @@ func (c *Client) GetEpisodes(ctx context.Context, animeID int, page int) (Episod
|
||||
|
||||
cacheKey := fmt.Sprintf("anime:%d:episodes:%d", animeID, page)
|
||||
var result EpisodesResponse
|
||||
reqURL := fmt.Sprintf("%s/anime/%d/episodes?page=%d", c.baseURL, animeID, page)
|
||||
params := url.Values{}
|
||||
params.Set("page", strconv.Itoa(page))
|
||||
reqURL := buildRequestURL(c.baseURL, fmt.Sprintf("/anime/%d/episodes", animeID), params)
|
||||
|
||||
err := c.getWithCache(ctx, cacheKey, 12*time.Hour, reqURL, &result)
|
||||
return result, err
|
||||
|
||||
@@ -3,6 +3,8 @@ package jikan
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func (c *Client) GetAnimeStaff(ctx context.Context, id int) ([]StaffEntry, error) {
|
||||
@@ -46,7 +48,9 @@ func (c *Client) GetAnimeReviews(ctx context.Context, id int, page int) ([]Revie
|
||||
page = 1
|
||||
}
|
||||
|
||||
url := fmt.Sprintf("%s/anime/%d/reviews?page=%d", c.baseURL, id, page)
|
||||
params := url.Values{}
|
||||
params.Set("page", strconv.Itoa(page))
|
||||
url := buildRequestURL(c.baseURL, fmt.Sprintf("/anime/%d/reviews", id), params)
|
||||
cacheKey := fmt.Sprintf("anime:reviews:%d:%d", id, page)
|
||||
|
||||
var resp ReviewsResponse
|
||||
|
||||
@@ -56,10 +56,11 @@ func (c *Client) GetProducers(ctx context.Context, query string, page int, limit
|
||||
func (c *Client) fetchProducersPage(ctx context.Context, query string, page int, limit int) (ProducerListResult, error) {
|
||||
q := strings.TrimSpace(query)
|
||||
cacheKey := fmt.Sprintf("producers:%s:%d:%d", q, page, limit)
|
||||
reqURL := fmt.Sprintf("%s/producers?page=%d&limit=%d", c.baseURL, page, limit)
|
||||
if q != "" {
|
||||
reqURL += "&q=" + url.QueryEscape(q)
|
||||
}
|
||||
params := url.Values{}
|
||||
params.Set("page", strconv.Itoa(page))
|
||||
params.Set("limit", strconv.Itoa(limit))
|
||||
setQueryValue(params, "q", q)
|
||||
reqURL := buildRequestURL(c.baseURL, "/producers", params)
|
||||
|
||||
var result ProducersResponse
|
||||
if err := c.getWithCache(ctx, cacheKey, producerCacheTTL, reqURL, &result); err != nil {
|
||||
|
||||
43
integrations/jikan/query_params.go
Normal file
43
integrations/jikan/query_params.go
Normal file
@@ -0,0 +1,43 @@
|
||||
package jikan
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func buildRequestURL(baseURL, path string, params url.Values) string {
|
||||
encoded := params.Encode()
|
||||
if encoded == "" {
|
||||
return fmt.Sprintf("%s%s", baseURL, path)
|
||||
}
|
||||
|
||||
return fmt.Sprintf("%s%s?%s", baseURL, path, encoded)
|
||||
}
|
||||
|
||||
func setQueryValue(values url.Values, key, value string) {
|
||||
if value == "" {
|
||||
values.Del(key)
|
||||
return
|
||||
}
|
||||
|
||||
values.Set(key, value)
|
||||
}
|
||||
|
||||
func setPositiveIntQueryValue(values url.Values, key string, value int) {
|
||||
if value <= 0 {
|
||||
values.Del(key)
|
||||
return
|
||||
}
|
||||
|
||||
values.Set(key, strconv.Itoa(value))
|
||||
}
|
||||
|
||||
func setTrueQueryValue(values url.Values, key string, enabled bool) {
|
||||
if !enabled {
|
||||
values.Del(key)
|
||||
return
|
||||
}
|
||||
|
||||
values.Set(key, "true")
|
||||
}
|
||||
@@ -8,8 +8,7 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
// SearchAdvanced performs a filtered anime search with type, status, ordering, genre filters, and studio (producer) filters.
|
||||
func (c *Client) SearchAdvanced(ctx context.Context, query, animeType, status, orderBy, sort string, genres []int, studioID int, sfw bool, page, limit int) (SearchResult, error) {
|
||||
func normalizeSearchPagination(page, limit int) (int, int) {
|
||||
if page < 1 {
|
||||
page = 1
|
||||
}
|
||||
@@ -17,46 +16,47 @@ func (c *Client) SearchAdvanced(ctx context.Context, query, animeType, status, o
|
||||
limit = 0
|
||||
}
|
||||
|
||||
genresParam := ""
|
||||
if len(genres) > 0 {
|
||||
ids := make([]string, len(genres))
|
||||
for i, g := range genres {
|
||||
ids[i] = strconv.Itoa(g)
|
||||
}
|
||||
genresParam = strings.Join(ids, ",")
|
||||
return page, limit
|
||||
}
|
||||
|
||||
func joinGenreIDs(genres []int) string {
|
||||
if len(genres) == 0 {
|
||||
return ""
|
||||
}
|
||||
|
||||
ids := make([]string, len(genres))
|
||||
for i, g := range genres {
|
||||
ids[i] = strconv.Itoa(g)
|
||||
}
|
||||
|
||||
return strings.Join(ids, ",")
|
||||
}
|
||||
|
||||
func buildAdvancedSearchURL(baseURL, query, animeType, status, orderBy, sort, genres string, studioID int, sfw bool, page, limit int) string {
|
||||
params := url.Values{}
|
||||
params.Set("page", strconv.Itoa(page))
|
||||
setTrueQueryValue(params, "sfw", sfw)
|
||||
setQueryValue(params, "q", query)
|
||||
setQueryValue(params, "type", animeType)
|
||||
setQueryValue(params, "status", status)
|
||||
setPositiveIntQueryValue(params, "producers", studioID)
|
||||
setQueryValue(params, "order_by", orderBy)
|
||||
setQueryValue(params, "sort", sort)
|
||||
setQueryValue(params, "genres", genres)
|
||||
setPositiveIntQueryValue(params, "limit", limit)
|
||||
|
||||
return buildRequestURL(baseURL, "/anime", params)
|
||||
}
|
||||
|
||||
// SearchAdvanced performs a filtered anime search with type, status, ordering, genre filters, and studio (producer) filters.
|
||||
func (c *Client) SearchAdvanced(ctx context.Context, query, animeType, status, orderBy, sort string, genres []int, studioID int, sfw bool, page, limit int) (SearchResult, error) {
|
||||
page, limit = normalizeSearchPagination(page, limit)
|
||||
genresParam := joinGenreIDs(genres)
|
||||
|
||||
cacheKey := fmt.Sprintf("search:%s:%s:%s:%s:%s:%s:%d:%v:%d:%d", query, animeType, status, orderBy, sort, genresParam, studioID, sfw, page, limit)
|
||||
|
||||
var result SearchResponse
|
||||
reqURL := fmt.Sprintf("%s/anime?page=%d", c.baseURL, page)
|
||||
if sfw {
|
||||
reqURL += "&sfw=true"
|
||||
}
|
||||
if query != "" {
|
||||
reqURL += "&q=" + url.QueryEscape(query)
|
||||
}
|
||||
if animeType != "" {
|
||||
reqURL += "&type=" + url.QueryEscape(animeType)
|
||||
}
|
||||
if status != "" {
|
||||
reqURL += "&status=" + url.QueryEscape(status)
|
||||
}
|
||||
if studioID > 0 {
|
||||
reqURL += "&producers=" + strconv.Itoa(studioID)
|
||||
}
|
||||
if orderBy != "" {
|
||||
reqURL += "&order_by=" + url.QueryEscape(orderBy)
|
||||
}
|
||||
if sort != "" {
|
||||
reqURL += "&sort=" + url.QueryEscape(sort)
|
||||
}
|
||||
if genresParam != "" {
|
||||
reqURL += "&genres=" + genresParam
|
||||
}
|
||||
if limit > 0 {
|
||||
reqURL += fmt.Sprintf("&limit=%d", limit)
|
||||
}
|
||||
reqURL := buildAdvancedSearchURL(c.baseURL, query, animeType, status, orderBy, sort, genresParam, studioID, sfw, page, limit)
|
||||
|
||||
if err := c.getWithCache(ctx, cacheKey, shortCacheTTL, reqURL, &result); err != nil {
|
||||
return SearchResult{}, err
|
||||
@@ -76,7 +76,9 @@ func (c *Client) GetTopAnime(ctx context.Context, page int) (TopAnimeResult, err
|
||||
cacheKey := fmt.Sprintf("top:%d", page)
|
||||
|
||||
var result TopAnimeResponse
|
||||
reqURL := fmt.Sprintf("%s/top/anime?page=%d", c.baseURL, page)
|
||||
params := url.Values{}
|
||||
params.Set("page", strconv.Itoa(page))
|
||||
reqURL := buildRequestURL(c.baseURL, "/top/anime", params)
|
||||
|
||||
if err := c.getWithCache(ctx, cacheKey, shortCacheTTL, reqURL, &result); err != nil {
|
||||
return TopAnimeResult{}, err
|
||||
|
||||
@@ -5,6 +5,8 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
@@ -30,7 +32,9 @@ func (c *Client) getSeasonList(ctx context.Context, page int, season string) (To
|
||||
cacheKey := fmt.Sprintf("seasons_%s:%d", season, page)
|
||||
|
||||
var result TopAnimeResponse
|
||||
reqURL := fmt.Sprintf("%s/seasons/%s?page=%d", c.baseURL, season, page)
|
||||
params := url.Values{}
|
||||
params.Set("page", strconv.Itoa(page))
|
||||
reqURL := buildRequestURL(c.baseURL, fmt.Sprintf("/seasons/%s", season), params)
|
||||
|
||||
err := c.getWithCache(ctx, cacheKey, shortCacheTTL, reqURL, &result)
|
||||
if err != nil {
|
||||
|
||||
Reference in New Issue
Block a user