[36] update template reporting

pull/970/head
meisnate12 2 years ago
parent 5f742615e6
commit dbe5a51d23

@ -1 +1 @@
1.17.1-develop35 1.17.1-develop36

@ -129,7 +129,8 @@ Depending on the `type` of dynamic collection, `data` is used to specify the opt
| [`studio`](#studio) | Create a collection for each studio found in the library | ❌ | ✅ | ✅ | ❌ | ❌ | | [`studio`](#studio) | Create a collection for each studio found in the library | ❌ | ✅ | ✅ | ❌ | ❌ |
| [`network`](#network) | Create a collection for each network found in the library | ❌ | ❌ | ✅ | ❌ | ❌ | | [`network`](#network) | Create a collection for each network found in the library | ❌ | ❌ | ✅ | ❌ | ❌ |
| [`mood`](#mood) | Create a collection for each mood found in the library | ❌ | ❌ | ❌ | ✅ | ❌ | | [`mood`](#mood) | Create a collection for each mood found in the library | ❌ | ❌ | ❌ | ✅ | ❌ |
| [`style`](#style) | Create a collection for each style found in the library | ❌ | ❌ | ❌ | ✅ | ❌ | | [`style`](#style) | Create a collection for each artist style found in the library | ❌ | ❌ | ❌ | ✅ | ❌ |
| [`album_style`](#album-style) | Create a collection for each album style found in the library | ❌ | ❌ | ❌ | ✅ | ❌ |
| [`number`](#number) | Creates a collection for each number defined | ✅ | ✅ | ✅ | ✅ | ✅ | | [`number`](#number) | Creates a collection for each number defined | ✅ | ✅ | ✅ | ✅ | ✅ |
| [`custom`](#custom) | Creates a collection for each custom `key: key_name` pair defined. | ✅ | ✅ | ✅ | ✅ | ✅ | | [`custom`](#custom) | Creates a collection for each custom `key: key_name` pair defined. | ✅ | ✅ | ✅ | ✅ | ✅ |
@ -1503,7 +1504,7 @@ dynamic_collections:
### Style ### Style
Create a collection for each style found in the library. Create a collection for each artist style found in the library.
<table class="dualTable colwidths-auto align-default table"> <table class="dualTable colwidths-auto align-default table">
<tr> <tr>
@ -1545,21 +1546,83 @@ default_template:
#### Example: #### Example:
* Create a collection for the top 10 artists for each style found in the Music library
* Name the collection "Top [Style] Artists"
```yaml
templates:
style collection:
smart_filter:
limit: 10
sort_by: plays.desc
all:
artist_style: <<value>>
dynamic_collections:
Styles: # mapping name does not matter just needs to be unique
type: style
title_format: Top <<key_name>> <<library_type>>
template: style collection
```
### Album Style
Create a collection for each album style found in the library.
<table class="dualTable colwidths-auto align-default table">
<tr>
<th><code>type</code> Option</th>
<td><code>album_style</code></td>
</tr>
<tr>
<th><code>data</code> Value</th>
<td>Not Used</td>
</tr>
<tr>
<th>Keys</th>
<td>Style</td>
</tr>
<tr>
<th>Key Names</th>
<td>Style</td>
</tr>
<tr>
<th>Default <code>title_format</code></th>
<td><code>Most Played &lt;&lt;key_name&gt;&gt; Albums</code></td>
</tr>
<tr>
<th>Default Template</th>
<td>
```yaml
default_template:
smart_filter:
limit: 50
sort_by: plays.desc
any:
album_style: <<value>>
```
</td>
</tr>
</table>
#### Example:
* Create a collection for the top 10 albums for each style found in the Music library * Create a collection for the top 10 albums for each style found in the Music library
* Name the collection "Top [Style] Albums" * Name the collection "Top [Style] Albums"
```yaml ```yaml
templates: templates:
style collection: style collection:
collection_level: albums
smart_filter: smart_filter:
limit: 10 limit: 10
sort_by: plays.desc sort_by: plays.desc
type: albums
all: all:
album_style: <<value>> album_style: <<value>>
dynamic_collections: dynamic_collections:
Styles: # mapping name does not matter just needs to be unique Styles: # mapping name does not matter just needs to be unique
type: style type: album_style
title_format: Top <<key_name>> Albums title_format: Top <<key_name>> Albums
template: style collection template: style collection
``` ```

@ -112,8 +112,10 @@ There are some attributes unique to `templates`; `default`, `optional`, `conditi
Every template call is given these template variables. Every template call is given these template variables.
* Either `<<collection_name>>`, `<<playlist_name>>`, or `<<overlay_name>>` which is the name of the definition. * Either `<<collection_name>>`, `<<playlist_name>>`, or `<<overlay_name>>` which is the name of the definition.
* `<<mapping_name>>` is the original mapping name for the definition in the YAML file.
* Either `<<collection_sort>>` or `<<playlist_sort>>` which is the name of the definition after `move_prefix` is applied. * Either `<<collection_sort>>` or `<<playlist_sort>>` which is the name of the definition after `move_prefix` is applied.
* `<<library_type>>` which is the library type * `<<library_type>>` which is the library type
* `<<library_name>>` which is the name of the library
* All Template Variables can append `_encoded` to the variable name to use a URL encode version of the variable. ex. `<<collection_name_encoded>>` * All Template Variables can append `_encoded` to the variable name to use a URL encode version of the variable. ex. `<<collection_name_encoded>>`
### Conditionals ### Conditionals

@ -200,7 +200,7 @@ class CollectionBuilder:
logger.info(extra) logger.info(extra)
logger.info("") logger.info("")
logger.separator(f"Validating {self.mapping_name} Attributes", space=False, border=False) logger.separator(f"Building Definition From Templates", space=False, border=False)
if f"{self.type}_name" in methods: if f"{self.type}_name" in methods:
logger.warning(f"Config Warning: Running {self.type}_name as name") logger.warning(f"Config Warning: Running {self.type}_name as name")
@ -217,6 +217,8 @@ class CollectionBuilder:
self.data[attr] = new_attributes[attr] self.data[attr] = new_attributes[attr]
methods[attr.lower()] = attr methods[attr.lower()] = attr
logger.separator(f"Validating {self.mapping_name} Attributes", space=False, border=False)
if "name" in methods: if "name" in methods:
logger.debug("") logger.debug("")
logger.debug("Validating Method: name") logger.debug("Validating Method: name")

@ -21,7 +21,10 @@ dynamic_attributes = [
"type", "data", "exclude", "addons", "template", "template_variables", "other_template", "remove_suffix", "type", "data", "exclude", "addons", "template", "template_variables", "other_template", "remove_suffix",
"remove_prefix", "title_format", "key_name_override", "title_override", "test", "sync", "include", "other_name" "remove_prefix", "title_format", "key_name_override", "title_override", "test", "sync", "include", "other_name"
] ]
auto_type_translation = {"content_rating": "contentRating", "subtitle_language": "subtitleLanguage", "audio_language": "audioLanguage"} auto_type_translation = {
"content_rating": "contentRating", "subtitle_language": "subtitleLanguage", "audio_language": "audioLanguage",
"album_style": "album.style"
}
default_templates = { default_templates = {
"original_language": {"plex_all": True, "filters": {"original_language": "<<value>>"}}, "original_language": {"plex_all": True, "filters": {"original_language": "<<value>>"}},
"origin_country": {"plex_all": True, "filters": {"origin_country": "<<value>>"}}, "origin_country": {"plex_all": True, "filters": {"origin_country": "<<value>>"}},
@ -211,10 +214,14 @@ class DataFile:
if not isinstance(template["conditionals"], dict): if not isinstance(template["conditionals"], dict):
raise Failed(f"{self.data_type} Error: template sub-attribute conditionals is not a dictionary") raise Failed(f"{self.data_type} Error: template sub-attribute conditionals is not a dictionary")
for con_key, con_value in template["conditionals"].items(): for con_key, con_value in template["conditionals"].items():
logger.debug("")
logger.debug(f"Conditional: {con_key}")
if not isinstance(con_value, dict): if not isinstance(con_value, dict):
raise Failed(f"{self.data_type} Error: template sub-attribute conditionals is not a dictionary") raise Failed(f"{self.data_type} Error: template sub-attribute conditionals is not a dictionary")
con_key = small_var_check(con_key) final_key = small_var_check(con_key)
if con_key in variables: if final_key != con_key:
logger.debug(f"Conditional Variable: {final_key}")
if final_key in variables:
continue continue
if "conditions" not in con_value: if "conditions" not in con_value:
raise Failed(f"{self.data_type} Error: conditions sub-attribute required for conditionals") raise Failed(f"{self.data_type} Error: conditions sub-attribute required for conditionals")
@ -238,25 +245,34 @@ class DataFile:
if var_key in variables: if var_key in variables:
if (isinstance(var_value, list) and variables[var_key] not in var_value) or \ if (isinstance(var_value, list) and variables[var_key] not in var_value) or \
(not isinstance(var_value, list) and variables[var_key] != var_value): (not isinstance(var_value, list) and variables[var_key] != var_value):
logger.debug(f"Condition Failed: {variables[var_key]} {'not in' if isinstance(var_value, list) else '!='} {var_value}")
condition_passed = False condition_passed = False
break break
elif var_key in default: elif var_key in default:
if (isinstance(var_value, list) and default[var_key] not in var_value) or \ if (isinstance(var_value, list) and default[var_key] not in var_value) or \
(not isinstance(var_value, list) and default[var_key] != var_value): (not isinstance(var_value, list) and default[var_key] != var_value):
logger.debug(f"Condition Failed: {default[var_key]} {'not in' if isinstance(var_value, list) else '!='} {var_value}")
condition_passed = False condition_passed = False
break break
else:
logger.debug(f"Condition Failed: {var_key} is not a variable provided or a default")
condition_passed = False
break
if condition_passed: if condition_passed:
logger.debug(f"Conditional Variable: {final_key} = {condition['value']}")
condition_found = True condition_found = True
variables[con_key] = condition["value"] variables[final_key] = condition["value"]
variables[f"{con_key}_encoded"] = requests.utils.quote(str(condition["value"])) variables[f"{final_key}_encoded"] = requests.utils.quote(str(condition["value"]))
break break
if not condition_found: if not condition_found:
if "default" in con_value: if "default" in con_value:
variables[con_key] = con_value["default"] logger.debug(f"Conditional Variable: {final_key} = {con_value['default']}")
variables[f"{con_key}_encoded"] = requests.utils.quote(str(con_value["default"])) variables[final_key] = con_value["default"]
variables[f"{final_key}_encoded"] = requests.utils.quote(str(con_value["default"]))
else: else:
optional.append(str(con_key)) logger.debug(f"Conditional Variable: {final_key} added as optional variable")
optional.append(f"{con_key}_encoded") optional.append(str(final_key))
optional.append(f"{final_key}_encoded")
sort_name = None sort_name = None
if "move_prefix" in template or "move_collection_prefix" in template: if "move_prefix" in template or "move_collection_prefix" in template:
@ -275,6 +291,13 @@ class DataFile:
raise Failed(f"{self.data_type} Error: template sub-attribute move_prefix is blank") raise Failed(f"{self.data_type} Error: template sub-attribute move_prefix is blank")
variables[f"{self.data_type.lower()}_sort"] = sort_name if sort_name else variables[name_var] variables[f"{self.data_type.lower()}_sort"] = sort_name if sort_name else variables[name_var]
logger.debug("")
logger.debug(f"Variables: {variables}")
logger.debug("")
logger.debug(f"Defaults: {default}")
logger.debug("")
logger.debug(f"Optional: {optional}")
def check_for_var(_method, _data): def check_for_var(_method, _data):
def scan_text(og_txt, var, actual_value): def scan_text(og_txt, var, actual_value):
if og_txt is None: if og_txt is None:
@ -434,7 +457,7 @@ class MetadataFile(DataFile):
auto_list = {str(k): f"{k}s" for k in addons if str(k) not in exclude and f"{k}s" not in exclude} auto_list = {str(k): f"{k}s" for k in addons if str(k) not in exclude and f"{k}s" not in exclude}
default_template = {"smart_filter": {"limit": 50, "sort_by": "critic_rating.desc", "any": {"year": f"<<value>>"}}} default_template = {"smart_filter": {"limit": 50, "sort_by": "critic_rating.desc", "any": {"year": f"<<value>>"}}}
default_title_format = "Best <<library_type>>s of <<key_name>>" default_title_format = "Best <<library_type>>s of <<key_name>>"
elif auto_type in ["genre", "mood", "style", "country", "studio", "network", "year", "decade", "content_rating", "subtitle_language", "audio_language", "resolution"]: elif auto_type in ["genre", "mood", "style", "album_style", "country", "studio", "network", "year", "decade", "content_rating", "subtitle_language", "audio_language", "resolution"]:
search_tag = auto_type_translation[auto_type] if auto_type in auto_type_translation else auto_type search_tag = auto_type_translation[auto_type] if auto_type in auto_type_translation else auto_type
if library.is_show and auto_type in ["resolution", "subtitle_language", "audio_language"]: if library.is_show and auto_type in ["resolution", "subtitle_language", "audio_language"]:
tags = library.get_tags(f"episode.{search_tag}") tags = library.get_tags(f"episode.{search_tag}")
@ -455,8 +478,9 @@ class MetadataFile(DataFile):
all_keys = [str(i.title) for i in tags] all_keys = [str(i.title) for i in tags]
auto_list = {str(i.title): i.title for i in tags if str(i.title) not in exclude} auto_list = {str(i.title): i.title for i in tags if str(i.title) not in exclude}
if library.is_music: if library.is_music:
default_template = {"smart_filter": {"limit": 50, "sort_by": "plays.desc", "any": {f"artist_{auto_type}": f"<<value>>"}}} final_var = auto_type if auto_type.startwith("album") else f"artist_{auto_type}"
default_title_format = "Most Played <<key_name>> <<library_type>>s" default_template = {"smart_filter": {"limit": 50, "sort_by": "plays.desc", "any": {final_var: f"<<value>>"}}}
default_title_format = f"Most Played <<key_name>> {'Albums' if auto_type.startwith('album') else '<<library_type>>'}s"
elif auto_type == "resolution": elif auto_type == "resolution":
default_template = {"smart_filter": {"sort_by": "title.asc", "any": {auto_type: f"<<value>>"}}} default_template = {"smart_filter": {"sort_by": "title.asc", "any": {auto_type: f"<<value>>"}}}
default_title_format = "<<key_name>> <<library_type>>s" default_title_format = "<<key_name>> <<library_type>>s"

@ -1,5 +1,5 @@
PlexAPI==4.11.2 PlexAPI==4.11.2
tmdbapis==1.0.5 tmdbapis==1.0.6
arrapi==1.3.1 arrapi==1.3.1
lxml==4.9.1 lxml==4.9.1
requests==2.28.1 requests==2.28.1

Loading…
Cancel
Save