diff --git a/VERSION b/VERSION
index 6dc0611a..6dbe536a 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1.16.2-develop36
+1.16.2-develop37
diff --git a/docs/metadata/builders/trakt.md b/docs/metadata/builders/trakt.md
index 8d619c96..73e054c2 100644
--- a/docs/metadata/builders/trakt.md
+++ b/docs/metadata/builders/trakt.md
@@ -56,11 +56,21 @@ Finds the movies/shows in the Trakt Chart. The options are detailed below.
The `sync_mode: sync` and `collection_order: custom` Details are recommended since the lists are continuously updated and in a specific order.
-| Attribute | Description & Values |
-|:--------------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
-| `chart` | **Description:** Which Trakt chart to query
**Values:**
`trending` | Trakt's Trending [Movies](https://trakt.tv/movies/trending)/[Shows](https://trakt.tv/shows/trending) list |
`popular` | Trakt's Popular [Movies](https://trakt.tv/movies/popular)/[Shows](https://trakt.tv/shows/popular) list |
`recommended` | Trakt's Recommended [Movies](https://trakt.tv/movies/recommended)/[Shows](https://trakt.tv/shows/recommended) list |
`watched` | Trakt's Watched [Movies](https://trakt.tv/movies/watched)/[Shows](https://trakt.tv/shows/watched) list |
`collected` | Trakt's Collected [Movies](https://trakt.tv/movies/collected)/[Shows](https://trakt.tv/shows/collected) list |
|
-| `time_period` | **Description:** Time Period for the chart. Does not work with `trending` or `popular` chart types.
**Default:** `weekly`
**Values:** `daily`, `weekly`, `monthly`, `yearly`, or `all` |
-| `limit` | **Description:** Don't return more then this number
**Default:** `10`
**Values:** Number of Items to query. |
+| Attribute | Description & Values |
+|:-----------------|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| `chart` | **Description:** Which Trakt chart to query
**Values:**`trending` | Trakt's Trending [Movies](https://trakt.tv/movies/trending)/[Shows](https://trakt.tv/shows/trending) list |
`popular` | Trakt's Popular [Movies](https://trakt.tv/movies/popular)/[Shows](https://trakt.tv/shows/popular) list |
`recommended` | Trakt's Recommended [Movies](https://trakt.tv/movies/recommended)/[Shows](https://trakt.tv/shows/recommended) list |
`watched` | Trakt's Watched [Movies](https://trakt.tv/movies/watched)/[Shows](https://trakt.tv/shows/watched) list |
`collected` | Trakt's Collected [Movies](https://trakt.tv/movies/collected)/[Shows](https://trakt.tv/shows/collected) list |
|
+| `time_period` | **Description:** Time Period for the chart. Does not work with `trending` or `popular` chart types.
**Default:** `weekly`
**Values:** `daily`, `weekly`, `monthly`, `yearly`, or `all` |
+| `limit` | **Description:** Don't return more then this number
**Default:** `10`
**Values:** Number of Items to query. |
+| `query` | **Description:** Search titles and descriptions for this
**Values:** Any String. |
+| `year` | **Description:** Search for the specified years only
**Values:** 4 digit year or range of 4 digit years. i.e. `1950` or `1950-1959` |
+| `genres` | **Description:** Search for the specified genres only
**Values:** Comma separated string or list of genres
**Movie Genres:** `action`, `adventure`, `animation`, `anime`, `comedy`, `crime`, `documentary`, `drama`, `family`, `fantasy`, `history`, `holiday`, `horror`, `music`, `musical`, `mystery`, `none`, `romance`, `science-fiction`, `short`, `sporting-event`, `superhero`, `suspense`, `thriller`, `war`, `western`
**Show Genres:** `action`, `adventure`, `animation`, `anime`, `biography`, `children`, `comedy`, `crime`, `documentary`, `drama`, `family`, `fantasy`, `game-show`, `history`, `holiday`, `home-and-garden`, `horror`, `mini-series`, `music`, `musical`, `mystery`, `news`, `none`, `reality`, `romance`, `science-fiction`, `short`, `soap`, `special-interest`, `sporting-event`, `superhero`, `suspense`, `talk-show`, `thriller`, `war`, `western` |
+| `languages` | **Description:** Search for the specified languages only
**Values:** Comma separated string or list of languages
**Movie Languages:** `ab`, `af`, `ak`, `sq`, `am`, `ar`, `an`, `hy`, `as`, `av`, `ay`, `az`, `bm`, `ba`, `eu`, `be`, `bn`, `bi`, `nb`, `bs`, `bg`, `my`, `ca`, `km`, `ch`, `ce`, `ny`, `zh`, `kw`, `co`, `cr`, `hr`, `cs`, `da`, `dv`, `nl`, `dz`, `en`, `eo`, `et`, `fo`, `fj`, `fi`, `fr`, `ff`, `gd`, `gl`, `lg`, `ka`, `de`, `el`, `gn`, `gu`, `ht`, `ha`, `he`, `hi`, `hu`, `is`, `ig`, `id`, `ie`, `iu`, `ik`, `ga`, `it`, `ja`, `jv`, `kl`, `kn`, `ks`, `kk`, `rw`, `ky`, `kg`, `ko`, `ku`, `lo`, `la`, `lv`, `li`, `ln`, `lt`, `lb`, `mk`, `mg`, `ms`, `ml`, `mt`, `mi`, `mr`, `mh`, `mn`, `nv`, `ne`, `se`, `no`, `nn`, `oc`, `oj`, `or`, `om`, `os`, `pi`, `pa`, `fa`, `pl`, `pt`, `ps`, `qu`, `ro`, `rm`, `rn`, `ru`, `sm`, `sg`, `sa`, `sc`, `sr`, `sn`, `ii`, `sd`, `si`, `sk`, `sl`, `so`, `st`, `es`, `su`, `sw`, `ss`, `sv`, `tl`, `ty`, `tg`, `ta`, `tt`, `te`, `th`, `bo`, `ti`, `to`, `ts`, `tn`, `tr`, `tk`, `tw`, `ug`, `uk`, `ur`, `uz`, `vi`, `cy`, `fy`, `wo`, `xh`, `yi`, `yo`, `za`, `zu`
**Show Languages:** `ab`, `af`, `sq`, `am`, `ar`, `hy`, `eu`, `be`, `bn`, `nb`, `bs`, `bg`, `ca`, `km`, `zh`, `hr`, `cs`, `da`, `dv`, `nl`, `en`, `et`, `fi`, `fr`, `gl`, `ka`, `de`, `el`, `gu`, `he`, `hi`, `hu`, `is`, `id`, `ga`, `it`, `ja`, `kn`, `ko`, `lo`, `la`, `lv`, `lt`, `lb`, `mk`, `ms`, `ml`, `mt`, `mi`, `mr`, `ne`, `se`, `no`, `nn`, `pa`, `fa`, `pl`, `pt`, `ro`, `ru`, `sr`, `si`, `sk`, `sl`, `es`, `sv`, `tl`, `ta`, `te`, `th`, `tr`, `tw`, `uk`, `ur`, `uz`, `vi`, `cy` |
+| `countries` | **Description:** Search for the specified countries only
**Values:** Comma separated string or list of countries
**Movie Countries:** `af`, `al`, `dz`, `as`, `ad`, `ao`, `ai`, `aq`, `ag`, `ar`, `am`, `aw`, `au`, `at`, `az`, `bs`, `bh`, `bd`, `bb`, `by`, `be`, `bz`, `bj`, `bm`, `bt`, `bo`, `ba`, `bw`, `bv`, `br`, `io`, `bn`, `bg`, `bf`, `bi`, `cv`, `kh`, `cm`, `ca`, `ky`, `cf`, `td`, `cl`, `cn`, `cx`, `co`, `km`, `cg`, `cd`, `ck`, `cr`, `hr`, `cu`, `cy`, `cz`, `ci`, `dk`, `dj`, `dm`, `do`, `ec`, `eg`, `sv`, `gq`, `er`, `ee`, `sz`, `et`, `fk`, `fo`, `fj`, `fi`, `fr`, `gf`, `pf`, `tf`, `ga`, `gm`, `ge`, `de`, `gh`, `gi`, `gr`, `gl`, `gd`, `gp`, `gu`, `gt`, `gn`, `gw`, `gy`, `ht`, `va`, `hn`, `hk`, `hu`, `is`, `in`, `id`, `ir`, `iq`, `ie`, `il`, `it`, `jm`, `jp`, `jo`, `kz`, `ke`, `ki`, `kp`, `kr`, `kw`, `kg`, `la`, `lv`, `lb`, `ls`, `lr`, `ly`, `li`, `lt`, `lu`, `mo`, `mg`, `mw`, `my`, `mv`, `ml`, `mt`, `mh`, `mq`, `mr`, `mu`, `yt`, `mx`, `md`, `mc`, `mn`, `me`, `ms`, `ma`, `mz`, `mm`, `na`, `nr`, `np`, `nl`, `nc`, `nz`, `ni`, `ne`, `ng`, `nf`, `mk`, `mp`, `no`, `om`, `pk`, `pw`, `ps`, `pa`, `pg`, `py`, `pe`, `ph`, `pn`, `pl`, `pt`, `pr`, `qa`, `ro`, `ru`, `rw`, `re`, `sh`, `kn`, `lc`, `vc`, `ws`, `sm`, `st`, `sa`, `sn`, `rs`, `sc`, `sl`, `sg`, `sk`, `si`, `sb`, `so`, `za`, `ss`, `es`, `lk`, `sd`, `sr`, `se`, `ch`, `sy`, `tw`, `tj`, `tz`, `th`, `tl`, `tg`, `tk`, `to`, `tt`, `tn`, `tr`, `tm`, `tc`, `tv`, `ug`, `ua`, `ae`, `gb`, `us`, `um`, `uy`, `uz`, `vu`, `ve`, `vn`, `vg`, `vi`, `wf`, `eh`, `ye`, `zm`, `zw`
**Show Countries:** `af`, `ad`, `ar`, `am`, `au`, `at`, `bd`, `by`, `be`, `bz`, `ba`, `bw`, `br`, `io`, `bg`, `kh`, `ca`, `td`, `cl`, `cn`, `co`, `hr`, `cu`, `cy`, `cz`, `dk`, `do`, `ec`, `eg`, `ee`, `sz`, `fi`, `fr`, `ge`, `de`, `gr`, `hn`, `hk`, `hu`, `is`, `in`, `id`, `ir`, `iq`, `ie`, `il`, `it`, `jp`, `jo`, `kz`, `kp`, `kr`, `kw`, `la`, `lv`, `lb`, `lt`, `lu`, `my`, `mv`, `mt`, `mx`, `md`, `mc`, `me`, `ma`, `np`, `nl`, `nz`, `ng`, `mk`, `mp`, `no`, `pk`, `pa`, `py`, `pe`, `ph`, `pl`, `pt`, `pr`, `qa`, `ro`, `ru`, `sa`, `sn`, `rs`, `sg`, `sk`, `si`, `za`, `es`, `lk`, `se`, `ch`, `sy`, `tw`, `th`, `tg`, `tn`, `tr`, `ua`, `ae`, `gb`, `us`, `uy`, `ve`, `vn` |
+| `certifications` | **Description:** Search for the specified certifications only
**Values:** Comma separated string or list of certifications
**Movie Certifications:** `g`, `pg`, `pg-13`, `r`, `nr`
**Show Certifications:** `tv-y`, `tv-y7`, `tv-g`, `tv-pg`, `tv-14`, `tv-ma`, `nr` |
+| `runtimes` | **Description:** Search for the specified runtime range
**Values:** range of int i.e. `0-60`
**Movie Genres:**
**Show Genres:** |
+| `ratings` | **Description:** Search for the specified rating range
**Values:** range of int i.e. `80-100`
**Movie Genres:**
**Show Genres:** |
+| `networks` | **Description:** Search for the specified networks only **Only works with shows**
**Values:** Comma separated string or list of networks |
+| `status` | **Description:** Search for the specified status only **Only works with shows**
**Values:** Comma separated string or list of statuses
**Status:** `returning`, `production`, `planned`, `canceled`, `ended` |
These are the links to the trakt charts that is looked at by time period.
diff --git a/docs/metadata/filters.md b/docs/metadata/filters.md
index 8bf25940..131801f1 100644
--- a/docs/metadata/filters.md
+++ b/docs/metadata/filters.md
@@ -89,10 +89,11 @@ Boolean Filters have no modifiers.
### Attribute
-| Boolean Filters | Description | Movies | Shows | Seasons | Episodes | Artists | Albums | Track |
-|:-----------------|:----------------------------------------------------------|:-------:|:-------:|:--------:|:--------:|:--------:|:--------:|:--------:|
-| `has_collection` | Matches every item that has or does not have a collection | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
-| `has_overlay` | Matches every item that has or does not have an overlay | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
+| Boolean Filters | Description | Movies | Shows | Seasons | Episodes | Artists | Albums | Track |
+|:--------------------|:------------------------------------------------------------|:-------:|:--------:|:--------:|:--------:|:--------:|:--------:|:--------:|
+| `has_collection` | Matches every item that has or does not have a collection | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
+| `has_dolby_vision` | Matches every item that has or does not have a dolby vision | ✅ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ |
+| `has_overlay` | Matches every item that has or does not have an overlay | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
## Date Filters
diff --git a/modules/builder.py b/modules/builder.py
index 79731417..15cc2ecf 100644
--- a/modules/builder.py
+++ b/modules/builder.py
@@ -1295,7 +1295,7 @@ class CollectionBuilder:
"time_period": terms[2] if len(terms) > 2 else None
}
final_method = "trakt_chart"
- for trakt_dict in self.config.Trakt.validate_chart(final_method, trakt_dicts, self.language):
+ for trakt_dict in self.config.Trakt.validate_chart(self.Type, final_method, trakt_dicts, self.library.is_movie):
self.builders.append((method_name, trakt_dict))
def _tvdb(self, method_name, method_data):
diff --git a/modules/trakt.py b/modules/trakt.py
index 6de5d222..b0c5218d 100644
--- a/modules/trakt.py
+++ b/modules/trakt.py
@@ -18,6 +18,11 @@ sorts = [
"rank", "added", "title", "released", "runtime", "popularity",
"percentage", "votes", "random", "my_rating", "watched", "collected"
]
+status = ["returning", "production", "planned", "canceled", "ended"]
+status_translation = {
+ "returning": "returning series", "production": "in production",
+ "planned": "planned", "canceled": "canceled", "ended": "ended"
+}
periods = ["daily", "weekly", "monthly", "yearly", "all"]
id_translation = {"movie": "movie", "show": "show", "season": "show", "episode": "show", "person": "person", "list": "list"}
id_types = {
@@ -41,6 +46,62 @@ class Trakt:
if not self._save(self.authorization):
if not self._refresh():
self._authorization()
+ self._movie_genres = None
+ self._show_genres = None
+ self._movie_languages = None
+ self._show_languages = None
+ self._movie_countries = None
+ self._show_countries = None
+ self._movie_certifications = None
+ self._show_certifications = None
+
+ @property
+ def movie_genres(self):
+ if not self._movie_genres:
+ self._movie_genres = [g["slug"] for g in self._request("/genres/movies")]
+ return self._movie_genres
+
+ @property
+ def show_genres(self):
+ if not self._show_genres:
+ self._show_genres = [g["slug"] for g in self._request("/genres/shows")]
+ return self._show_genres
+
+ @property
+ def movie_languages(self):
+ if not self._movie_languages:
+ self._movie_languages = [g["code"] for g in self._request("/languages/movies")]
+ return self._movie_languages
+
+ @property
+ def show_languages(self):
+ if not self._show_languages:
+ self._show_languages = [g["code"] for g in self._request("/languages/shows")]
+ return self._show_languages
+
+ @property
+ def movie_countries(self):
+ if not self._movie_countries:
+ self._movie_countries = [g["code"] for g in self._request("/countries/movies")]
+ return self._movie_countries
+
+ @property
+ def show_countries(self):
+ if not self._show_countries:
+ self._show_countries = [g["code"] for g in self._request("/countries/shows")]
+ return self._show_countries
+
+ @property
+ def movie_certifications(self):
+ if not self._movie_certifications:
+ self._movie_certifications = [g["slug"] for g in self._request("/certifications/movies")["us"]]
+ return self._movie_certifications
+
+ @property
+ def show_certifications(self):
+ if not self._show_certifications:
+ self._show_certifications = [g["slug"] for g in self._request("/certifications/shows")["us"]]
+ return self._show_certifications
def _authorization(self):
if self.pin:
@@ -114,7 +175,7 @@ class Trakt:
return True
return False
- def _request(self, url):
+ def _request(self, url, params=None):
headers = {
"Content-Type": "application/json",
"Authorization": f"Bearer {self.authorization['access_token']}",
@@ -122,17 +183,20 @@ class Trakt:
"trakt-api-key": self.client_id
}
output_json = []
+ if params is None:
+ params = {}
pages = 1
current = 1
if self.config.trace_mode:
logger.debug(f"URL: {base_url}{url}")
while current <= pages:
if pages == 1:
- response = self.config.get(f"{base_url}{url}", headers=headers)
- if "X-Pagination-Page-Count" in response.headers and "?" not in url:
+ response = self.config.get(f"{base_url}{url}", headers=headers, params=params)
+ if "X-Pagination-Page-Count" in response.headers and not params:
pages = int(response.headers["X-Pagination-Page-Count"])
else:
- response = self.config.get(f"{base_url}{url}?page={current}", headers=headers)
+ params["page"] = current
+ response = self.config.get(f"{base_url}{url}", headers=headers, params=params)
if response.status_code == 200:
json_data = response.json()
if self.config.trace_mode:
@@ -153,9 +217,8 @@ class Trakt:
def convert(self, external_id, from_source, to_source, media_type):
path = f"/search/{from_source}/{external_id}"
- if from_source in ["tmdb", "tvdb"]:
- path = f"{path}?type={media_type}"
- lookup = self._request(path)
+ params = {"type": media_type} if from_source in ["tmdb", "tvdb"] else None
+ lookup = self._request(path, params=params)
if lookup and media_type in lookup[0] and to_source in lookup[0][media_type]["ids"]:
return lookup[0][media_type]["ids"][to_source]
raise Failed(f"Trakt Error: No {to_source.upper().replace('B', 'b')} ID found for {from_source.upper().replace('B', 'b')} ID: {external_id}")
@@ -238,16 +301,16 @@ class Trakt:
def _recommendations(self, limit, is_movie):
media_type = "Movie" if is_movie else "Show"
try:
- items = self._request(f"/recommendations/{'movies' if is_movie else 'shows'}/?limit={limit}")
+ items = self._request(f"/recommendations/{'movies' if is_movie else 'shows'}", params={"limit": limit})
except Failed:
raise Failed(f"Trakt Error: failed to fetch {media_type} Recommendations")
if len(items) == 0:
raise Failed(f"Trakt Error: no {media_type} Recommendations were found")
return self._parse(items, typeless=True, item_type="movie" if is_movie else "show")
- def _charts(self, chart_type, limit, is_movie, time_period=None):
+ def _charts(self, chart_type, is_movie, params, time_period=None):
chart_url = f"{chart_type}/{time_period}" if time_period else chart_type
- items = self._request(f"/{'movies' if is_movie else 'shows'}/{chart_url}?limit={limit}")
+ items = self._request(f"/{'movies' if is_movie else 'shows'}/{chart_url}", params=params)
return self._parse(items, typeless=chart_type == "popular", item_type="movie" if is_movie else "show")
def get_people(self, data):
@@ -268,7 +331,7 @@ class Trakt:
raise Failed(f"Trakt Error: No valid Trakt Lists in {values}")
return trakt_values
- def validate_chart(self, method_name, err_type, data, is_movie):
+ def validate_chart(self, err_type, method_name, data, is_movie):
valid_dicts = []
for trakt_dict in util.get_list(data, split=False):
if not isinstance(trakt_dict, dict):
@@ -276,12 +339,39 @@ class Trakt:
dict_methods = {dm.lower(): dm for dm in trakt_dict}
try:
if method_name == "trakt_chart":
- chart = util.parse(err_type, "chart", trakt_dict, methods=dict_methods, parent=method_name, options=["recommended", "watched", "collected", "trending", "popular"])
- limit = util.parse(err_type, "limit", trakt_dict, methods=dict_methods, parent=method_name, datatype="int", default=10)
- time_period = None
- if chart in ["recommended", "watched", "collected"] and "time_period" in dict_methods:
- time_period = util.parse(err_type, "time_period", trakt_dict, methods=dict_methods, parent=method_name, default="weekly", options=periods)
- valid_dicts.append({"chart": chart, "limit": limit, "time_period": time_period})
+ final_dict = {}
+ final_dict["chart"] = util.parse(err_type, "chart", trakt_dict, methods=dict_methods, parent=method_name, options=["recommended", "watched", "collected", "trending", "popular"])
+ final_dict["limit"] = util.parse(err_type, "limit", trakt_dict, methods=dict_methods, parent=method_name, datatype="int", default=10)
+ final_dict["time_period"] = None
+ if final_dict["chart"] in ["recommended", "watched", "collected"] and "time_period" in dict_methods:
+ final_dict["time_period"] = util.parse(err_type, "time_period", trakt_dict, methods=dict_methods, parent=method_name, default="weekly", options=periods)
+ if "query" in dict_methods:
+ final_dict["query"] = util.parse(err_type, "query", trakt_dict, methods=dict_methods, parent=method_name)
+ if "year" in dict_methods:
+ try:
+ if trakt_dict[dict_methods["year"]] and len(str(trakt_dict[dict_methods["year"]])) == 4:
+ final_dict["year"] = util.parse(err_type, "year", trakt_dict, methods=dict_methods, parent=method_name, datatype="int", minimum=1000, maximum=3000)
+ else:
+ final_dict["year"] = util.parse(err_type, "year", trakt_dict, methods=dict_methods, parent=method_name, datatype="int", minimum=1000, maximum=3000, range_split="-")
+ except Failed:
+ raise Failed(f"{err_type} Error: trakt_chart year attribute must be either a 4 digit year or a range of two 4 digit year with a '-' i.e. 1950 or 1950-1959")
+ if "runtimes" in dict_methods:
+ final_dict["runtimes"] = util.parse(err_type, "runtimes", trakt_dict, methods=dict_methods, parent=method_name, datatype="int", range_split="-")
+ if "ratings" in dict_methods:
+ final_dict["ratings"] = util.parse(err_type, "ratings", trakt_dict, methods=dict_methods, parent=method_name, datatype="int", minimum=0, maximum=100, range_split="-")
+ if "genres" in dict_methods:
+ final_dict["genres"] = util.parse(err_type, "genres", trakt_dict, methods=dict_methods, parent=method_name, datatype="list", options=self.movie_genres if is_movie else self.show_genres)
+ if "languages" in dict_methods:
+ final_dict["languages"] = util.parse(err_type, "languages", trakt_dict, methods=dict_methods, parent=method_name, datatype="list", options=self.movie_languages if is_movie else self.show_languages)
+ if "countries" in dict_methods:
+ final_dict["countries"] = util.parse(err_type, "countries", trakt_dict, methods=dict_methods, parent=method_name, datatype="list", options=self.movie_countries if is_movie else self.show_countries)
+ if "certifications" in dict_methods:
+ final_dict["certifications"] = util.parse(err_type, "certifications", trakt_dict, methods=dict_methods, parent=method_name, datatype="list", options=self.movie_certifications if is_movie else self.show_certifications)
+ if "networks" in dict_methods and not is_movie:
+ final_dict["networks"] = util.parse(err_type, "networks", trakt_dict, methods=dict_methods, parent=method_name, datatype="list")
+ if "status" in dict_methods and not is_movie:
+ final_dict["status"] = util.parse(err_type, "status", trakt_dict, methods=dict_methods, parent=method_name, datatype="list", options=status)
+ valid_dicts.append(final_dict)
else:
userlist = util.parse(err_type, "userlist", trakt_dict, methods=dict_methods, parent=method_name, options=["recommended", "watched", "collected", "watchlist"])
user = util.parse(err_type, "user", trakt_dict, methods=dict_methods, parent=method_name, default="me")
@@ -306,9 +396,15 @@ class Trakt:
logger.info(f"Processing {pretty}: {data} {media_type}{'' if data == 1 else 's'}")
return self._recommendations(data, is_movie)
elif method == "trakt_chart":
- chart_title = data["chart"] if data["time_period"] else f"{data['chart']} {data['time_period'].capitalize()}"
- logger.info(f"Processing {pretty}: {chart_title} {data['chart'].capitalize()} {media_type}{'' if data == 1 else 's'}")
- return self._charts(data["chart"], data["limit"], is_movie, time_period=data["time_period"])
+ params = {"limit": data["limit"]}
+ chart_limit = f"{data['limit']} {data['time_period'].capitalize()}" if data["time_period"] else data["limit"]
+ logger.info(f"Processing {pretty}: {chart_limit} {data['chart'].capitalize()} {media_type}{'' if data == 1 else 's'}")
+ for attr in ["query", "year", "runtimes", "ratings", "genres", "languages", "countries", "certifications", "networks", "status"]:
+ if attr in data:
+ logger.info(f"{attr:>22}: {','.join(data[attr]) if isinstance(data[attr], list) else data[attr]}")
+ values = [status_translation[v] for v in data[attr]] if attr == "status" else data[attr]
+ params[attr] = ",".join(values) if isinstance(values, list) else values
+ return self._charts(data["chart"], is_movie, params, time_period=data["time_period"])
elif method == "trakt_userlist":
logger.info(f"Processing {pretty} {media_type}s from {data['user']}'s {data['userlist'].capitalize()}")
return self._userlist(data["userlist"], data["user"], is_movie, sort_by=data["sort_by"])
diff --git a/modules/util.py b/modules/util.py
index dc46f746..9a733b64 100644
--- a/modules/util.py
+++ b/modules/util.py
@@ -420,7 +420,15 @@ def schedule_check(attribute, data, current_time, run_hour):
elif skip_collection:
raise NotScheduled(schedule_str)
-def parse(error, attribute, data, datatype=None, methods=None, parent=None, default=None, options=None, translation=None, minimum=1, maximum=None, regex=None):
+def check_int(value, datatype="int", minimum=1, maximum=None):
+ try:
+ value = int(str(value)) if datatype == "int" else float(str(value))
+ if (maximum is None and minimum <= value) or (maximum is not None and minimum <= value <= maximum):
+ return value
+ except ValueError:
+ pass
+
+def parse(error, attribute, data, datatype=None, methods=None, parent=None, default=None, options=None, translation=None, minimum=1, maximum=None, regex=None, range_split=None):
display = f"{parent + ' ' if parent else ''}{attribute} attribute"
if options is None and translation is not None:
options = [o for o in translation]
@@ -500,17 +508,21 @@ def parse(error, attribute, data, datatype=None, methods=None, parent=None, defa
else:
message = f"{display} must be either true or false"
elif datatype in ["int", "float"]:
- try:
- value = int(str(value)) if datatype == "int" else float(str(value))
- if (maximum is None and minimum <= value) or (maximum is not None and minimum <= value <= maximum):
- return value
- except ValueError:
- pass
- pre = f"{display} {value} must be {'an integer' if datatype == 'int' else 'a number'}"
- if maximum is None:
- message = f"{pre} {minimum} or greater"
+ if range_split:
+ range_values = str(value).split(range_split)
+ if len(range_values) == 2:
+ start = check_int(range_values[0])
+ end = check_int(range_values[1])
+ if start and end and start < end:
+ return f"{start}{range_split}{end}"
else:
- message = f"{pre} between {minimum} and {maximum}"
+ value = check_int(value, datatype=datatype, minimum=minimum, maximum=maximum)
+ if value:
+ return value
+ message = f"{display} {value} must {'each ' if range_split else ''}be {'an integer' if datatype == 'int' else 'a number'}"
+ message = f"{message} {minimum} or greater" if maximum is None else f"{message} between {minimum} and {maximum}"
+ if range_split:
+ message = f"{message} separated by a {range_split}"
elif (translation is not None and str(value).lower() not in translation) or \
(options is not None and translation is None and str(value).lower() not in options):
message = f"{display} {value} must be in {', '.join([str(o) for o in options])}"