147 lines
4.3 KiB
Go
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")})
|
|
}
|