Files

147 lines
4.3 KiB
Go

package tools
import (
"context"
"encoding/json"
)
// read_reference — genres, languages, keyword/provider lookups,
// streaming countries and issue categories. Family: reference_page.
func handleReference(ctx context.Context, env *Env, raw json.RawMessage) *ToolResult {
o := newOp(ctx, env, "read_reference", false)
var a ReferenceArgs
if fail := o.args(raw, &a); fail != nil {
return fail
}
switch a.Action {
case "genres":
return o.refGenres(&a)
case "languages":
return o.refList("/api/v2/Search/Languages",
[]string{"iso_639_1", "name"}, []string{"english_name", "name"}, "language")
case "keywords":
return o.refKeywords(&a)
case "keyword":
return o.refKeyword(&a)
case "watch_providers":
return o.refWatchProviders(&a)
case "streaming_countries":
return o.refList("/api/v1/Identity/streamingcountry",
[]string{"code", "isoCode", "id"}, []string{"name", "code"}, "country")
case "issue_categories":
return o.refList("/api/v1/Issues/categories",
[]string{"id"}, []string{"value", "name"}, "issue_category")
default:
return o.invalid("action", "unsupported action %q", a.Action)
}
}
// refList fetches an upstream array and projects each element into a
// bounded reference record.
func (o *op) refList(path string, idKeys, nameKeys []string, cat string) *ToolResult {
raw, fail := o.call("GET", path, nil, nil)
if fail != nil {
return fail
}
items, fail := o.refArray(raw, idKeys, nameKeys, cat)
if fail != nil {
return fail
}
return o.ok(&ReferencePage{Kind: "reference_page",
Items: items, Page: singlePage(len(items), "references")})
}
func (o *op) refArray(raw []byte, idKeys, nameKeys []string, cat string) ([]Reference, *ToolResult) {
arr, fail := o.decodeArray(raw)
if fail != nil {
// Some legacy routes return scalars (e.g. a bare string list).
var strs []string
if err := json.Unmarshal(raw, &strs); err == nil && strs != nil {
items := make([]Reference, 0, len(strs))
for _, s := range strs {
items = append(items, Reference{Name: s, Category: cat})
}
return capItems(o, items), nil
}
return nil, fail
}
items := make([]Reference, 0, len(arr))
for _, m := range arr {
items = append(items, o.refOf(m, idKeys, nameKeys, nil, cat))
}
return capItems(o, items), nil
}
func (o *op) refGenres(a *ReferenceArgs) *ToolResult {
var media string
switch a.Media {
case "movie", "tv":
media = a.Media
default:
return o.invalid("media", "media must be movie or tv")
}
return o.refList("/api/v2/Search/Genres/"+media,
[]string{"id"}, []string{"name"}, "genre")
}
func (o *op) refKeywords(a *ReferenceArgs) *ToolResult {
if !nonempty(a.Query) {
return o.invalid("query", "query must contain non-whitespace text")
}
raw, fail := o.call("GET", "/api/v1/TheMovieDb/Keywords",
map[string]string{"searchTerm": a.Query}, nil)
if fail != nil {
return fail
}
items, fail := o.refArray(raw, []string{"id"}, []string{"name"}, "keyword")
if fail != nil {
return fail
}
return o.ok(&ReferencePage{Kind: "reference_page",
Items: items, Page: singlePage(len(items), "references")})
}
func (o *op) refKeyword(a *ReferenceArgs) *ToolResult {
if a.KeywordID == nil || *a.KeywordID < 1 {
return o.invalid("keyword_id", "keyword_id must be a positive integer")
}
raw, fail := o.call("GET",
"/api/v1/TheMovieDb/Keywords/"+segInt(*a.KeywordID), nil, nil)
if fail != nil {
return fail
}
m, fail := o.decodeObject(raw)
if fail != nil {
return fail
}
r := o.refOf(m, []string{"id"}, []string{"name"}, nil, "keyword")
return o.ok(&ReferencePage{Kind: "reference_page",
Items: []Reference{r}, Page: singlePage(1, "references")})
}
func (o *op) refWatchProviders(a *ReferenceArgs) *ToolResult {
var media string
switch a.Media {
case "movie", "tv":
media = a.Media
default:
return o.invalid("media", "media must be movie or tv")
}
q := map[string]string{}
if nonempty(a.Query) {
q["searchTerm"] = a.Query
}
raw, fail := o.call("GET", "/api/v1/TheMovieDb/WatchProviders/"+media, q, nil)
if fail != nil {
return fail
}
items, fail := o.refArray(raw,
[]string{"id", "provider_id", "providerId"}, []string{"name", "provider_name", "providerName"},
"watch_provider")
if fail != nil {
return fail
}
return o.ok(&ReferencePage{Kind: "reference_page",
Items: items, Page: singlePage(len(items), "references")})
}