[40] add album_genre, album_mood, album_style, and track_mood as dynamic collection types

pull/1207/head
meisnate12 2 years ago
parent 10d65f9db6
commit ee2d425981

@ -1 +1 @@
1.18.0-develop39 1.18.0-develop40

@ -127,7 +127,6 @@ templates:
- <<use_edition>> - <<use_edition>>
- <<allowed_libraries>> - <<allowed_libraries>>
ignore_blank_results: true ignore_blank_results: true
only_filter_missing: false
plex_all: true plex_all: true
filters: filters:
- edition: <<search>> - edition: <<search>>

@ -307,6 +307,8 @@ html_theme_options = {
("Templates", "metadata/templates"), ("Templates", "metadata/templates"),
("Filters", "metadata/filters"), ("Filters", "metadata/filters"),
("_menu", "Dynamic Collections", "metadata/dynamic", [ ("_menu", "Dynamic Collections", "metadata/dynamic", [
("Dynamic Collections", "metadata/dynamic"),
("_divider", ),
("_menu", "TMDb Dynamic Collections", "metadata/dynamic", [ ("_menu", "TMDb Dynamic Collections", "metadata/dynamic", [
("TMDb Collection", "metadata/dynamic", "#tmdb-collection"), ("TMDb Collection", "metadata/dynamic", "#tmdb-collection"),
("TMDb Popular People", "metadata/dynamic", "#tmdb-popular-people"), ("TMDb Popular People", "metadata/dynamic", "#tmdb-popular-people"),
@ -324,6 +326,7 @@ html_theme_options = {
("Writer", "metadata/dynamic", "#writer"), ("Writer", "metadata/dynamic", "#writer"),
("Producer", "metadata/dynamic", "#producer"), ("Producer", "metadata/dynamic", "#producer"),
("Genre", "metadata/dynamic", "#genre"), ("Genre", "metadata/dynamic", "#genre"),
("Album Genre", "metadata/dynamic", "#album-genre"),
("Content Rating", "metadata/dynamic", "#content-rating"), ("Content Rating", "metadata/dynamic", "#content-rating"),
("Year", "metadata/dynamic", "#year"), ("Year", "metadata/dynamic", "#year"),
("Decade", "metadata/dynamic", "#decade"), ("Decade", "metadata/dynamic", "#decade"),
@ -335,13 +338,15 @@ html_theme_options = {
("Edition", "metadata/dynamic", "#edition"), ("Edition", "metadata/dynamic", "#edition"),
("Network", "metadata/dynamic", "#network"), ("Network", "metadata/dynamic", "#network"),
("Mood", "metadata/dynamic", "#mood"), ("Mood", "metadata/dynamic", "#mood"),
("Album Mood", "metadata/dynamic", "#album-mood"),
("Track Mood", "metadata/dynamic", "#track-mood"),
("Style", "metadata/dynamic", "#style"), ("Style", "metadata/dynamic", "#style"),
("Album Style", "metadata/dynamic", "#album-style"), ("Album Style", "metadata/dynamic", "#album-style"),
]), ]),
("Number", "metadata/dynamic", "#number"), ("Number", "metadata/dynamic", "#number"),
("Custom", "metadata/dynamic", "#custom"), ("Custom", "metadata/dynamic", "#custom"),
]), ]),
("_menu", "Editing Media Metadata", "#", [ ("_menu", "Editing Media Metadata", "", [
("Editing Movie Metadata", "metadata/metadata/movie"), ("Editing Movie Metadata", "metadata/metadata/movie"),
("Editing TV Metadata", "metadata/metadata/show"), ("Editing TV Metadata", "metadata/metadata/show"),
("Editing Music Metadata", "metadata/metadata/music"), ("Editing Music Metadata", "metadata/metadata/music"),

@ -247,7 +247,7 @@ Tag search can take multiple values as a **list or a comma-separated string**.
| `album_source` | Uses the Album's Source attribute to match | &#10060; | &#10060; | &#9989; | | `album_source` | Uses the Album's Source attribute to match | &#10060; | &#10060; | &#9989; |
| `album_label` | Uses the Album's Label attribute to match | &#10060; | &#10060; | &#9989; | | `album_label` | Uses the Album's Label attribute to match | &#10060; | &#10060; | &#9989; |
| `track_mood` | Uses the Track's Mood attribute to match | &#10060; | &#10060; | &#9989; | | `track_mood` | Uses the Track's Mood attribute to match | &#10060; | &#10060; | &#9989; |
| `track_source` | Uses the Track's Style attribute to match | &#10060; | &#10060; | &#9989; | | `track_source` | Uses the Track's Source attribute to match | &#10060; | &#10060; | &#9989; |
| `track_label` | Uses the Track's Label attribute to match | &#10060; | &#10060; | &#9989; | | `track_label` | Uses the Track's Label attribute to match | &#10060; | &#10060; | &#9989; |
<sup>1</sup> You can use `current_year` to have PMM use the current years value. This can be combined with a `-#` at the end to subtract that number of years. i.e. `current-2` <sup>1</sup> You can use `current_year` to have PMM use the current years value. This can be combined with a `-#` at the end to subtract that number of years. i.e. `current-2`

@ -181,7 +181,7 @@ Tag filter can take multiple values as a **list or a comma-separated string**.
| `album_source` | Uses the Album's Source attribute to match | &#10060; | &#10060; | &#9989; | | `album_source` | Uses the Album's Source attribute to match | &#10060; | &#10060; | &#9989; |
| `album_label` | Uses the Album's Label attribute to match | &#10060; | &#10060; | &#9989; | | `album_label` | Uses the Album's Label attribute to match | &#10060; | &#10060; | &#9989; |
| `track_mood` | Uses the Track's Mood attribute to match | &#10060; | &#10060; | &#9989; | | `track_mood` | Uses the Track's Mood attribute to match | &#10060; | &#10060; | &#9989; |
| `track_source` | Uses the Track's Style attribute to match | &#10060; | &#10060; | &#9989; | | `track_source` | Uses the Track's Source attribute to match | &#10060; | &#10060; | &#9989; |
| `track_label` | Uses the Track's Label attribute to match | &#10060; | &#10060; | &#9989; | | `track_label` | Uses the Track's Label attribute to match | &#10060; | &#10060; | &#9989; |
<sup>1</sup> You can use `current_year` to have PMM use the current years value. This can be combined with a `-#` at the end to subtract that number of years. i.e. `current-2` <sup>1</sup> You can use `current_year` to have PMM use the current years value. This can be combined with a `-#` at the end to subtract that number of years. i.e. `current-2`

@ -120,6 +120,7 @@ Depending on the `type` of dynamic collection, `data` is used to specify the opt
| [`writer`](#writer) | Create a collection for each writer found in the library | &#9989; | &#9989; | &#10060; | &#10060; | &#10060; | | [`writer`](#writer) | Create a collection for each writer found in the library | &#9989; | &#9989; | &#10060; | &#10060; | &#10060; |
| [`producer`](#producer) | Create a collection for each producer found in the library | &#9989; | &#9989; | &#10060; | &#10060; | &#10060; | | [`producer`](#producer) | Create a collection for each producer found in the library | &#9989; | &#9989; | &#10060; | &#10060; | &#10060; |
| [`genre`](#genre) | Create a collection for each genre found in the library | &#10060; | &#9989; | &#9989; | &#9989; | &#9989; | | [`genre`](#genre) | Create a collection for each genre found in the library | &#10060; | &#9989; | &#9989; | &#9989; | &#9989; |
| [`album_genre`](#album-genre) | Create a collection for each album genre found in the library | &#10060; | &#10060; | &#10060; | &#9989; | &#10060; |
| [`content_rating`](#content-rating) | Create a collection for each content rating found in the library | &#10060; | &#9989; | &#9989; | &#10060; | &#9989; | | [`content_rating`](#content-rating) | Create a collection for each content rating found in the library | &#10060; | &#9989; | &#9989; | &#10060; | &#9989; |
| [`year`](#year) | Create a collection for each year found in the library | &#10060; | &#9989; | &#9989; | &#10060; | &#10060; | | [`year`](#year) | Create a collection for each year found in the library | &#10060; | &#9989; | &#9989; | &#10060; | &#10060; |
| [`decade`](#decade) | Create a collection for each decade found in the library | &#10060; | &#9989; | &#9989; | &#10060; | &#10060; | | [`decade`](#decade) | Create a collection for each decade found in the library | &#10060; | &#9989; | &#9989; | &#10060; | &#10060; |
@ -130,7 +131,9 @@ 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 | &#10060; | &#9989; | &#9989; | &#10060; | &#10060; | | [`studio`](#studio) | Create a collection for each studio found in the library | &#10060; | &#9989; | &#9989; | &#10060; | &#10060; |
| [`edition`](#edition) | Create a collection for each edition found in the library | &#10060; | &#9989; | &#10060; | &#10060; | &#10060; | | [`edition`](#edition) | Create a collection for each edition found in the library | &#10060; | &#9989; | &#10060; | &#10060; | &#10060; |
| [`network`](#network) | Create a collection for each network found in the library | &#10060; | &#10060; | &#9989; | &#10060; | &#10060; | | [`network`](#network) | Create a collection for each network found in the library | &#10060; | &#10060; | &#9989; | &#10060; | &#10060; |
| [`mood`](#mood) | Create a collection for each mood found in the library | &#10060; | &#10060; | &#10060; | &#9989; | &#10060; | | [`mood`](#mood) | Create a collection for each artist mood found in the library | &#10060; | &#10060; | &#10060; | &#9989; | &#10060; |
| [`album_mood`](#album-mood) | Create a collection for each album mood found in the library | &#10060; | &#10060; | &#10060; | &#9989; | &#10060; |
| [`track_mood`](#track-mood) | Create a collection for each track mood found in the library | &#10060; | &#10060; | &#10060; | &#9989; | &#10060; |
| [`style`](#style) | Create a collection for each artist style found in the library | &#10060; | &#10060; | &#10060; | &#9989; | &#10060; | | [`style`](#style) | Create a collection for each artist style found in the library | &#10060; | &#10060; | &#10060; | &#9989; | &#10060; |
| [`album_style`](#album-style) | Create a collection for each album style found in the library | &#10060; | &#10060; | &#10060; | &#9989; | &#10060; | | [`album_style`](#album-style) | Create a collection for each album style found in the library | &#10060; | &#10060; | &#10060; | &#9989; | &#10060; |
| [`number`](#number) | Creates a collection for each number defined | &#9989; | &#9989; | &#9989; | &#9989; | &#9989; | | [`number`](#number) | Creates a collection for each number defined | &#9989; | &#9989; | &#9989; | &#9989; | &#9989; |
@ -920,6 +923,72 @@ dynamic_collections:
template: genre collection template: genre collection
``` ```
### Album Genre
Create a collection for each album genre found in the library.
<table class="dualTable colwidths-auto align-default table">
<tr>
<th><code>type</code> Option</th>
<td><code>album_genre</code></td>
</tr>
<tr>
<th><code>data</code> Value</th>
<td>Not Used</td>
</tr>
<tr>
<th>Keys</th>
<td>Genre</td>
</tr>
<tr>
<th>Key Names</th>
<td>Genre</td>
</tr>
<tr>
<th>Default <code>title_format</code></th>
<td><code>Top &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_genre: <<value>>
```
</td>
</tr>
</table>
#### Example:
* Create dynamic collections based on each Album genre found in the library
* Amend the template to increase the limit from 10 to 20
* Exclude the "Pop" genre
* Name the collection "Top 20 [Genre] Albums"
```yaml
templates:
genre collection:
smart_filter:
limit: 100
sort_by: plays.desc
all:
album_genre: <<value>>
dynamic_collections:
Genres: # mapping name does not matter just needs to be unique
type: album_genre
exclude:
- Pop
title_format: Top 20 <<key_name>> <<library_type>>s
template: genre collection
```
### Content Rating ### Content Rating
Create a collection for each content rating found in the library. Create a collection for each content rating found in the library.
@ -1504,7 +1573,7 @@ dynamic_collections:
### Mood ### Mood
Create a collection for each mood found in the library. Create a collection for each artist mood found in the library.
<table class="dualTable colwidths-auto align-default table"> <table class="dualTable colwidths-auto align-default table">
<tr> <tr>
@ -1534,7 +1603,7 @@ Create a collection for each mood found in the library.
```yaml ```yaml
default_template: default_template:
smart_filter: smart_filter:
limit: 50 limit: 10
sort_by: plays.desc sort_by: plays.desc
any: any:
artist_mood: <<value>> artist_mood: <<value>>
@ -1546,8 +1615,135 @@ default_template:
#### Example: #### Example:
* Create a collection for the top 100 items for each mood found in the Music library * Create a collection for the top 20 artists for each mood found in the Music library
* Name the collection "Top [Mood] Tracks" * Amend the template to increase the limit from 10 to 20
* Name the collection "Top 20 [Mood] Artists"
```yaml
templates:
mood collection:
smart_filter:
limit: 20
sort_by: plays.desc
all:
artist_mood: <<value>>
dynamic_collections:
Moods: # mapping name does not matter just needs to be unique
type: mood
title_format: Top 20 <<key_name>> Artists
template: mood collection
```
### Album Mood
Create a collection for each album mood found in the library.
<table class="dualTable colwidths-auto align-default table">
<tr>
<th><code>type</code> Option</th>
<td><code>album_mood</code></td>
</tr>
<tr>
<th><code>data</code> Value</th>
<td>Not Used</td>
</tr>
<tr>
<th>Keys</th>
<td>Mood</td>
</tr>
<tr>
<th>Key Names</th>
<td>Mood</td>
</tr>
<tr>
<th>Default <code>title_format</code></th>
<td><code>Most Played &lt;&lt;value&gt;&gt; Albums</code></td>
</tr>
<tr>
<th>Default Template</th>
<td>
```yaml
default_template:
smart_filter:
limit: 10
sort_by: plays.desc
any:
album_mood: <<value>>
```
</td>
</tr>
</table>
#### Example:
* Create a collection for the top 20 albums for each mood found in the Music library
* Amend the template to increase the limit from 10 to 20
* Name the collection "Top 20 [Mood] Albums"
```yaml
templates:
mood collection:
smart_filter:
limit: 20
sort_by: plays.desc
all:
album_mood: <<value>>
dynamic_collections:
Moods: # mapping name does not matter just needs to be unique
type: album_mood
title_format: Top 20 <<key_name>> Albums
template: mood collection
```
### Track Mood
Create a collection for each track mood found in the library.
<table class="dualTable colwidths-auto align-default table">
<tr>
<th><code>type</code> Option</th>
<td><code>track_mood</code></td>
</tr>
<tr>
<th><code>data</code> Value</th>
<td>Not Used</td>
</tr>
<tr>
<th>Keys</th>
<td>Mood</td>
</tr>
<tr>
<th>Key Names</th>
<td>Mood</td>
</tr>
<tr>
<th>Default <code>title_format</code></th>
<td><code>Most Played &lt;&lt;value&gt;&gt; Tracks</code></td>
</tr>
<tr>
<th>Default Template</th>
<td>
```yaml
default_template:
smart_filter:
limit: 50
sort_by: plays.desc
any:
track_mood: <<value>>
```
</td>
</tr>
</table>
#### Example:
* Create a collection for the top 100 tracks for each mood found in the Music library
* Amend the template to increase the limit from 50 to 100
* Name the collection "Top 100 [Mood] Tracks"
```yaml ```yaml
templates: templates:
@ -1555,13 +1751,12 @@ templates:
smart_filter: smart_filter:
limit: 100 limit: 100
sort_by: plays.desc sort_by: plays.desc
type: tracks
all: all:
track_mood: <<value>> track_mood: <<value>>
dynamic_collections: dynamic_collections:
Moods: # mapping name does not matter just needs to be unique Moods: # mapping name does not matter just needs to be unique
type: mood type: track_mood
title_format: Top <<key_name>> Tracks title_format: Top 100 <<key_name>> Tracks
template: mood collection template: mood collection
``` ```
@ -1597,7 +1792,7 @@ Create a collection for each artist style found in the library.
```yaml ```yaml
default_template: default_template:
smart_filter: smart_filter:
limit: 50 limit: 10
sort_by: plays.desc sort_by: plays.desc
any: any:
artist_style: <<value>> artist_style: <<value>>
@ -1659,7 +1854,7 @@ Create a collection for each album style found in the library.
```yaml ```yaml
default_template: default_template:
smart_filter: smart_filter:
limit: 50 limit: 10
sort_by: plays.desc sort_by: plays.desc
any: any:
album_style: <<value>> album_style: <<value>>

@ -849,7 +849,7 @@ class CollectionBuilder:
elif method_name == "tvdb_description": elif method_name == "tvdb_description":
self.summaries[method_name] = self.config.TVDb.get_list_description(method_data) self.summaries[method_name] = self.config.TVDb.get_list_description(method_data)
elif method_name == "trakt_description": elif method_name == "trakt_description":
self.summaries[method_name] = self.config.Trakt.list_description(self.config.Trakt.validate_list(method_data, self.library.is_movie)[0]) self.summaries[method_name] = self.config.Trakt.list_description(self.config.Trakt.validate_list(method_data)[0])
elif method_name == "letterboxd_description": elif method_name == "letterboxd_description":
self.summaries[method_name] = self.config.Letterboxd.get_list_description(method_data, self.language) self.summaries[method_name] = self.config.Letterboxd.get_list_description(method_data, self.language)
elif method_name == "icheckmovies_description": elif method_name == "icheckmovies_description":

@ -14,7 +14,7 @@ ms_auto = [
auto = { auto = {
"Movie": ["tmdb_collection", "edition", "country", "director", "producer", "writer"] + all_auto + ms_auto, "Movie": ["tmdb_collection", "edition", "country", "director", "producer", "writer"] + all_auto + ms_auto,
"Show": ["network", "origin_country"] + all_auto + ms_auto, "Show": ["network", "origin_country"] + all_auto + ms_auto,
"Artist": ["mood", "style", "country"] + all_auto, "Artist": ["mood", "style", "country", "album_genre", "album_mood", "album_style", "track_mood"] + all_auto,
"Video": ["country", "content_rating"] + all_auto "Video": ["country", "content_rating"] + all_auto
} }
dynamic_attributes = [ dynamic_attributes = [
@ -23,7 +23,7 @@ dynamic_attributes = [
] ]
auto_type_translation = { auto_type_translation = {
"content_rating": "contentRating", "subtitle_language": "subtitleLanguage", "audio_language": "audioLanguage", "content_rating": "contentRating", "subtitle_language": "subtitleLanguage", "audio_language": "audioLanguage",
"album_style": "album.style", "edition": "editionTitle" "album_genre": "album.genre", "album_style": "album.style", "album_mood": "album.mood", "track_mood": "track.mood", "edition": "editionTitle"
} }
default_templates = { default_templates = {
"original_language": {"plex_all": True, "filters": {"original_language": "<<value>>"}}, "original_language": {"plex_all": True, "filters": {"original_language": "<<value>>"}},
@ -661,7 +661,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": "<<value>>"}}} default_template = {"smart_filter": {"limit": 50, "sort_by": "critic_rating.desc", "any": {"year": "<<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", "album_style", "country", "studio", "edition", "network", "year", "decade", "content_rating", "subtitle_language", "audio_language", "resolution"]: elif auto_type in ["genre", "mood", "style", "album_genre", "album_mood", "album_style", "track_mood", "country", "studio", "edition", "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}")
@ -682,11 +682,13 @@ class MetadataFile(DataFile):
all_keys = {str(i.title): i.title for i in tags} all_keys = {str(i.title): 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:
final_var = auto_type if auto_type.startswith("album") else f"artist_{auto_type}" final_var = auto_type if auto_type.startswith(("album", "track")) else f"artist_{auto_type}"
default_template = {"smart_filter": {"limit": 50, "sort_by": "plays.desc", "any": {final_var: "<<value>>"}}} default_template = {"smart_filter": {"limit": 50 if auto_type.startswith("track") else 10, "sort_by": "plays.desc", "any": {final_var: "<<value>>"}}}
if auto_type.startswith("album"): music_type = "<<library_type>>"
default_template["builder_level"] = "album" if auto_type.startswith(("album", "track")):
default_title_format = f"Most Played <<key_name>> {'Albums' if auto_type.startswith('album') else '<<library_type>>'}s" default_template["builder_level"] = "album" if auto_type.startswith("album") else "track"
music_type = "Album" if auto_type.startswith("album") else "Track"
default_title_format = f"Most Played <<key_name>> {music_type}s"
elif auto_type == "resolution": elif auto_type == "resolution":
default_template = {"smart_filter": {"sort_by": "title.asc", "any": {auto_type: "<<value>>"}}} default_template = {"smart_filter": {"sort_by": "title.asc", "any": {auto_type: "<<value>>"}}}
default_title_format = "<<key_name>> <<library_type>>s" default_title_format = "<<key_name>> <<library_type>>s"

Loading…
Cancel
Save