[37] #751 add trakt filters

pull/811/head
meisnate12 3 years ago
parent 8dc4988255
commit 01fe35d326

@ -1 +1 @@
1.16.2-develop36 1.16.2-develop37

@ -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. 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 | | Attribute | Description & Values |
|:--------------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| |:-----------------|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `chart` | **Description:** Which Trakt chart to query<br>**Values:**<table class="clearTable"><tr><td>`trending`</td><td>Trakt's Trending [Movies](https://trakt.tv/movies/trending)/[Shows](https://trakt.tv/shows/trending) list</td></tr><tr><td>`popular`</td><td>Trakt's Popular [Movies](https://trakt.tv/movies/popular)/[Shows](https://trakt.tv/shows/popular) list</td></tr><tr><td>`recommended`</td><td>Trakt's Recommended [Movies](https://trakt.tv/movies/recommended)/[Shows](https://trakt.tv/shows/recommended) list</td></tr><tr><td>`watched`</td><td>Trakt's Watched [Movies](https://trakt.tv/movies/watched)/[Shows](https://trakt.tv/shows/watched) list</td></tr><tr><td>`collected`</td><td>Trakt's Collected [Movies](https://trakt.tv/movies/collected)/[Shows](https://trakt.tv/shows/collected) list</td></tr></table> | | `chart` | **Description:** Which Trakt chart to query<br>**Values:**<table class="clearTable"><tr><td>`trending`</td><td>Trakt's Trending [Movies](https://trakt.tv/movies/trending)/[Shows](https://trakt.tv/shows/trending) list</td></tr><tr><td>`popular`</td><td>Trakt's Popular [Movies](https://trakt.tv/movies/popular)/[Shows](https://trakt.tv/shows/popular) list</td></tr><tr><td>`recommended`</td><td>Trakt's Recommended [Movies](https://trakt.tv/movies/recommended)/[Shows](https://trakt.tv/shows/recommended) list</td></tr><tr><td>`watched`</td><td>Trakt's Watched [Movies](https://trakt.tv/movies/watched)/[Shows](https://trakt.tv/shows/watched) list</td></tr><tr><td>`collected`</td><td>Trakt's Collected [Movies](https://trakt.tv/movies/collected)/[Shows](https://trakt.tv/shows/collected) list</td></tr></table> |
| `time_period` | **Description:** Time Period for the chart. Does not work with `trending` or `popular` chart types.<br>**Default:** `weekly`<br>**Values:** `daily`, `weekly`, `monthly`, `yearly`, or `all` | | `time_period` | **Description:** Time Period for the chart. Does not work with `trending` or `popular` chart types.<br>**Default:** `weekly`<br>**Values:** `daily`, `weekly`, `monthly`, `yearly`, or `all` |
| `limit` | **Description:** Don't return more then this number<br>**Default:** `10`<br>**Values:** Number of Items to query. | | `limit` | **Description:** Don't return more then this number<br>**Default:** `10`<br>**Values:** Number of Items to query. |
| `query` | **Description:** Search titles and descriptions for this<br>**Values:** Any String. |
| `year` | **Description:** Search for the specified years only<br>**Values:** 4 digit year or range of 4 digit years. i.e. `1950` or `1950-1959` |
| `genres` | **Description:** Search for the specified genres only<br>**Values:** Comma separated string or list of genres<br>**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`<br>**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<br>**Values:** Comma separated string or list of languages<br>**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`<br>**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<br>**Values:** Comma separated string or list of countries<br>**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`<br>**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<br>**Values:** Comma separated string or list of certifications<br>**Movie Certifications:** `g`, `pg`, `pg-13`, `r`, `nr`<br>**Show Certifications:** `tv-y`, `tv-y7`, `tv-g`, `tv-pg`, `tv-14`, `tv-ma`, `nr` |
| `runtimes` | **Description:** Search for the specified runtime range<br>**Values:** range of int i.e. `0-60`<br>**Movie Genres:** <br>**Show Genres:** |
| `ratings` | **Description:** Search for the specified rating range<br>**Values:** range of int i.e. `80-100`<br>**Movie Genres:** <br>**Show Genres:** |
| `networks` | **Description:** Search for the specified networks only **Only works with shows**<br>**Values:** Comma separated string or list of networks |
| `status` | **Description:** Search for the specified status only **Only works with shows**<br>**Values:** Comma separated string or list of statuses<br>**Status:** `returning`, `production`, `planned`, `canceled`, `ended` |
These are the links to the trakt charts that is looked at by time period. These are the links to the trakt charts that is looked at by time period.

@ -89,10 +89,11 @@ Boolean Filters have no modifiers.
### Attribute ### Attribute
| Boolean Filters | Description | Movies | Shows | Seasons | Episodes | Artists | Albums | Track | | Boolean Filters | Description | Movies | Shows | Seasons | Episodes | Artists | Albums | Track |
|:-----------------|:----------------------------------------------------------|:-------:|:-------:|:--------:|:--------:|:--------:|:--------:|:--------:| |:--------------------|:------------------------------------------------------------|:-------:|:--------:|:--------:|:--------:|:--------:|:--------:|:--------:|
| `has_collection` | Matches every item that has or does not have a collection | &#9989; | &#9989; | &#9989; | &#9989; | &#9989; | &#9989; | &#9989; | | `has_collection` | Matches every item that has or does not have a collection | &#9989; | &#9989; | &#9989; | &#9989; | &#9989; | &#9989; | &#9989; |
| `has_overlay` | Matches every item that has or does not have an overlay | &#9989; | &#9989; | &#10060; | &#10060; | &#10060; | &#10060; | &#10060; | | `has_dolby_vision` | Matches every item that has or does not have a dolby vision | &#9989; | &#10060; | &#10060; | &#9989; | &#10060; | &#10060; | &#10060; |
| `has_overlay` | Matches every item that has or does not have an overlay | &#9989; | &#9989; | &#10060; | &#10060; | &#10060; | &#10060; | &#10060; |
## Date Filters ## Date Filters

@ -1295,7 +1295,7 @@ class CollectionBuilder:
"time_period": terms[2] if len(terms) > 2 else None "time_period": terms[2] if len(terms) > 2 else None
} }
final_method = "trakt_chart" 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)) self.builders.append((method_name, trakt_dict))
def _tvdb(self, method_name, method_data): def _tvdb(self, method_name, method_data):

@ -18,6 +18,11 @@ sorts = [
"rank", "added", "title", "released", "runtime", "popularity", "rank", "added", "title", "released", "runtime", "popularity",
"percentage", "votes", "random", "my_rating", "watched", "collected" "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"] periods = ["daily", "weekly", "monthly", "yearly", "all"]
id_translation = {"movie": "movie", "show": "show", "season": "show", "episode": "show", "person": "person", "list": "list"} id_translation = {"movie": "movie", "show": "show", "season": "show", "episode": "show", "person": "person", "list": "list"}
id_types = { id_types = {
@ -41,6 +46,62 @@ class Trakt:
if not self._save(self.authorization): if not self._save(self.authorization):
if not self._refresh(): if not self._refresh():
self._authorization() 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): def _authorization(self):
if self.pin: if self.pin:
@ -114,7 +175,7 @@ class Trakt:
return True return True
return False return False
def _request(self, url): def _request(self, url, params=None):
headers = { headers = {
"Content-Type": "application/json", "Content-Type": "application/json",
"Authorization": f"Bearer {self.authorization['access_token']}", "Authorization": f"Bearer {self.authorization['access_token']}",
@ -122,17 +183,20 @@ class Trakt:
"trakt-api-key": self.client_id "trakt-api-key": self.client_id
} }
output_json = [] output_json = []
if params is None:
params = {}
pages = 1 pages = 1
current = 1 current = 1
if self.config.trace_mode: if self.config.trace_mode:
logger.debug(f"URL: {base_url}{url}") logger.debug(f"URL: {base_url}{url}")
while current <= pages: while current <= pages:
if pages == 1: if pages == 1:
response = self.config.get(f"{base_url}{url}", headers=headers) response = self.config.get(f"{base_url}{url}", headers=headers, params=params)
if "X-Pagination-Page-Count" in response.headers and "?" not in url: if "X-Pagination-Page-Count" in response.headers and not params:
pages = int(response.headers["X-Pagination-Page-Count"]) pages = int(response.headers["X-Pagination-Page-Count"])
else: 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: if response.status_code == 200:
json_data = response.json() json_data = response.json()
if self.config.trace_mode: if self.config.trace_mode:
@ -153,9 +217,8 @@ class Trakt:
def convert(self, external_id, from_source, to_source, media_type): def convert(self, external_id, from_source, to_source, media_type):
path = f"/search/{from_source}/{external_id}" path = f"/search/{from_source}/{external_id}"
if from_source in ["tmdb", "tvdb"]: params = {"type": media_type} if from_source in ["tmdb", "tvdb"] else None
path = f"{path}?type={media_type}" lookup = self._request(path, params=params)
lookup = self._request(path)
if lookup and media_type in lookup[0] and to_source in lookup[0][media_type]["ids"]: 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] 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}") 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): def _recommendations(self, limit, is_movie):
media_type = "Movie" if is_movie else "Show" media_type = "Movie" if is_movie else "Show"
try: 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: except Failed:
raise Failed(f"Trakt Error: failed to fetch {media_type} Recommendations") raise Failed(f"Trakt Error: failed to fetch {media_type} Recommendations")
if len(items) == 0: if len(items) == 0:
raise Failed(f"Trakt Error: no {media_type} Recommendations were found") 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") 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 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") return self._parse(items, typeless=chart_type == "popular", item_type="movie" if is_movie else "show")
def get_people(self, data): def get_people(self, data):
@ -268,7 +331,7 @@ class Trakt:
raise Failed(f"Trakt Error: No valid Trakt Lists in {values}") raise Failed(f"Trakt Error: No valid Trakt Lists in {values}")
return trakt_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 = [] valid_dicts = []
for trakt_dict in util.get_list(data, split=False): for trakt_dict in util.get_list(data, split=False):
if not isinstance(trakt_dict, dict): if not isinstance(trakt_dict, dict):
@ -276,12 +339,39 @@ class Trakt:
dict_methods = {dm.lower(): dm for dm in trakt_dict} dict_methods = {dm.lower(): dm for dm in trakt_dict}
try: try:
if method_name == "trakt_chart": 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"]) final_dict = {}
limit = util.parse(err_type, "limit", trakt_dict, methods=dict_methods, parent=method_name, datatype="int", default=10) final_dict["chart"] = util.parse(err_type, "chart", trakt_dict, methods=dict_methods, parent=method_name, options=["recommended", "watched", "collected", "trending", "popular"])
time_period = None final_dict["limit"] = util.parse(err_type, "limit", trakt_dict, methods=dict_methods, parent=method_name, datatype="int", default=10)
if chart in ["recommended", "watched", "collected"] and "time_period" in dict_methods: final_dict["time_period"] = None
time_period = util.parse(err_type, "time_period", trakt_dict, methods=dict_methods, parent=method_name, default="weekly", options=periods) if final_dict["chart"] in ["recommended", "watched", "collected"] and "time_period" in dict_methods:
valid_dicts.append({"chart": chart, "limit": limit, "time_period": time_period}) 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: else:
userlist = util.parse(err_type, "userlist", trakt_dict, methods=dict_methods, parent=method_name, options=["recommended", "watched", "collected", "watchlist"]) 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") 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'}") logger.info(f"Processing {pretty}: {data} {media_type}{'' if data == 1 else 's'}")
return self._recommendations(data, is_movie) return self._recommendations(data, is_movie)
elif method == "trakt_chart": elif method == "trakt_chart":
chart_title = data["chart"] if data["time_period"] else f"{data['chart']} {data['time_period'].capitalize()}" params = {"limit": data["limit"]}
logger.info(f"Processing {pretty}: {chart_title} {data['chart'].capitalize()} {media_type}{'' if data == 1 else 's'}") chart_limit = f"{data['limit']} {data['time_period'].capitalize()}" if data["time_period"] else data["limit"]
return self._charts(data["chart"], data["limit"], is_movie, time_period=data["time_period"]) 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": elif method == "trakt_userlist":
logger.info(f"Processing {pretty} {media_type}s from {data['user']}'s {data['userlist'].capitalize()}") 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"]) return self._userlist(data["userlist"], data["user"], is_movie, sort_by=data["sort_by"])

@ -420,7 +420,15 @@ def schedule_check(attribute, data, current_time, run_hour):
elif skip_collection: elif skip_collection:
raise NotScheduled(schedule_str) 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" display = f"{parent + ' ' if parent else ''}{attribute} attribute"
if options is None and translation is not None: if options is None and translation is not None:
options = [o for o in translation] options = [o for o in translation]
@ -500,17 +508,21 @@ def parse(error, attribute, data, datatype=None, methods=None, parent=None, defa
else: else:
message = f"{display} must be either true or false" message = f"{display} must be either true or false"
elif datatype in ["int", "float"]: elif datatype in ["int", "float"]:
try: if range_split:
value = int(str(value)) if datatype == "int" else float(str(value)) range_values = str(value).split(range_split)
if (maximum is None and minimum <= value) or (maximum is not None and minimum <= value <= maximum): if len(range_values) == 2:
return value start = check_int(range_values[0])
except ValueError: end = check_int(range_values[1])
pass if start and end and start < end:
pre = f"{display} {value} must be {'an integer' if datatype == 'int' else 'a number'}" return f"{start}{range_split}{end}"
if maximum is None:
message = f"{pre} {minimum} or greater"
else: 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 \ 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): (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])}" message = f"{display} {value} must be in {', '.join([str(o) for o in options])}"

Loading…
Cancel
Save