[18] add origin_country filter and dynamic collection

pull/790/head
meisnate12 3 years ago
parent 022cf7668a
commit 709d95e286

@ -1 +1 @@
1.16.0-develop17
1.16.0-develop18

@ -24,7 +24,7 @@ dynamic_collections:
By default, the collections generated will be named for the thing being used to create them; things like genres, countries, actors or even Trakt List Names.
There are many attributes that can change the titles, including `title_format`, `remove_suffix`, `remove_prefix`, `pre_format_override`, and `post_format_override` all detailed below.
There are many attributes that can change the titles, including `title_format`, `remove_suffix`, `remove_prefix`, `key_name_override`, and `title_override` all detailed below.
## Dynamic Keys & Key Names
@ -52,7 +52,7 @@ dynamic_collections:
- Horror
```
* Using the `pre_format_override` attribute to change the formatting of "France" to "French" so that a collection can be named "French Cinema" instead of simply "France"
* Using the `key_name_override` attribute to change the formatting of "France" to "French" so that a collection can be named "French Cinema" instead of simply "France"
* This particular example also uses the `title_format` attribute to manipulate the naming convention of the collections.
```yaml
@ -60,7 +60,7 @@ dynamic_collections:
Countries: # mapping name does not matter, just needs to be unique
type: country
title_format: <<country>> Cinema
pre_format_override:
key_name_override:
France: French
```
@ -81,23 +81,23 @@ dynamic_collections:
## Attributes
| Attribute | Description | Required |
|:------------------------------------------------|:-------------------------------------------------------------------------------------------------------------------------------|:-----------------:|
| [`type`](#type--data) | Type of Dynamic Collection to be created. | &#9989; |
| [`data`](#type--data) | Data to determine how dynamic collections with a certain `type` are created. | Depends on `type` |
| [`exclude`](#exclude) | Exclude this list of keys from being created into collections. | &#10060; |
| [`addons`](#addons) | Defines how multiple keys can be combined under a parent key. | &#10060; |
| [`template`](#template) | Name of the template to use for these dynamic collections. | &#10060; |
| [`template_variables`](#template-variables) | Defines how template variables can be defined by key. | &#10060; |
| [`remove_suffix`](#remove-prefixsuffix) | Removes the defined suffixes from the key before it's used in the collection title. | &#10060; |
| [`remove_prefix`](#remove-prefixsuffix) | Removes the defined prefixes from the key before it's used in the collection title. | &#10060; |
| [`title_format`](#title-format) | This is the format for the collection titles. | &#10060; |
| [`pre_format_override`](#pre-format-override) | Defines how titles can be overridden before they are formatted into collection titles. | &#10060; |
| [`post_format_override`](#post-format-override) | Defines how collection titles can be overridden ignoring title formatting. | &#10060; |
| [`test`](#test) | Will add `test: true` to all collections for test runs. | &#10060; |
| [`sync`](#sync) | Will remove dynamic collections that are no longer in the creation list. | &#10060; |
| [`include`](#include) | Define a list of keys to be made into collections. | &#10060; |
| [`other_name`](#other-name) | Used in combination with `include`. When defined, all keys not in `include` or `addons` will be combined into this collection. | &#10060; |
| Attribute | Description | Required |
|:--------------------------------------------|:-------------------------------------------------------------------------------------------------------------------------------|:-----------------:|
| [`type`](#type--data) | Type of Dynamic Collection to be created. | &#9989; |
| [`data`](#type--data) | Data to determine how dynamic collections with a certain `type` are created. | Depends on `type` |
| [`exclude`](#exclude) | Exclude this list of keys from being created into collections. | &#10060; |
| [`addons`](#addons) | Defines how multiple keys can be combined under a parent key. | &#10060; |
| [`template`](#template) | Name of the template to use for these dynamic collections. | &#10060; |
| [`template_variables`](#template-variables) | Defines how template variables can be defined by key. | &#10060; |
| [`remove_suffix`](#remove-prefixsuffix) | Removes the defined suffixes from the key before it's used in the collection title. | &#10060; |
| [`remove_prefix`](#remove-prefixsuffix) | Removes the defined prefixes from the key before it's used in the collection title. | &#10060; |
| [`title_format`](#title-format) | This is the format for the collection titles. | &#10060; |
| [`key_name_override`](#key-name-override) | Defines how key names can be overridden before they are formatted into collection titles. | &#10060; |
| [`title_override`](#title-override) | Defines how collection titles can be overridden ignoring title formatting. | &#10060; |
| [`test`](#test) | Will add `test: true` to all collections for test runs. | &#10060; |
| [`sync`](#sync) | Will remove dynamic collections that are no longer in the creation list. | &#10060; |
| [`include`](#include) | Define a list of keys to be made into collections. | &#10060; |
| [`other_name`](#other-name) | Used in combination with `include`. When defined, all keys not in `include` or `addons` will be combined into this collection. | &#10060; |
## Type & Data
@ -110,6 +110,7 @@ Depending on the `type` of dynamic collection, `data` is used to specify the opt
| [`tmdb_collection`](#tmdb-collection) | Create a collection for each TMDb Collection associated with an item in the library | &#10060; | &#9989; | &#10060; | &#10060; | &#10060; |
| [`tmdb_popular_people`](#tmdb-popular-people) | Create a collection for each actor found on [TMDb's Popular People List](https://www.themoviedb.org/person) | &#9989; | &#9989; | &#9989; | &#10060; | &#10060; |
| [`original_language`](#original-language) | Create a collection for each TMDb original language associated with an item in the library | &#10060; | &#9989; | &#9989; | &#10060; | &#10060; |
| [`origin_country`](#origin-country) | Create a collection for each TMDb origin country associated with an item in the library | &#10060; | &#10060; | &#9989; | &#10060; | &#10060; |
| [`trakt_user_lists`](#trakt-user-lists) | Create a collection for each list from specific trakt users | &#9989; | &#9989; | &#9989; | &#10060; | &#10060; |
| [`trakt_liked_lists`](#trakt-liked-lists) | Create a collection for each list the authenticated trakt user likes | &#10060; | &#9989; | &#9989; | &#10060; | &#10060; |
| [`trakt_people_list`](#trakt-people-lists) | Create a collection for each actor found in the trakt list | &#9989; | &#9989; | &#9989; | &#10060; | &#10060; |
@ -143,7 +144,7 @@ Create collections based on the TMDb Collections associated with items in the li
<td>TMDb Collection ID</td>
</tr>
<tr>
<th>Titles</th>
<th>Key Names</th>
<td>TMDb Collection Title</td>
</tr>
<tr>
@ -191,7 +192,7 @@ Create collections based on each actor found on [TMDb's Popular People List](htt
<td>TMDb Person ID</td>
</tr>
<tr>
<th>Titles</th>
<th>Key Names</th>
<td>TMDb Person Name</td>
</tr>
<tr>
@ -241,7 +242,7 @@ Create collections based on the TMDb original language associated with items in
<td><a href="https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes">ISO 639-1 Code</a></td>
</tr>
<tr>
<th>Titles</th>
<th>Key Names</th>
<td>ISO Language Name</td>
</tr>
<tr>
@ -271,6 +272,53 @@ dynamic_collections:
type: original_language
```
### Origin Country
Create collections based on the TMDb origin country associated with items in the library.
<table class="dualTable colwidths-auto align-default table">
<tr>
<th><code>type</code> Option</th>
<td><code>origin_country</code></td>
</tr>
<tr>
<th><code>data</code> Value</th>
<td>Not Used</td>
</tr>
<tr>
<th>Keys</th>
<td><a href="https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2">ISO 3166-1 alpha-2 country code</a></td>
</tr>
<tr>
<th>Key Names</th>
<td>ISO Country Name</td>
</tr>
<tr>
<th>Default <code>title_format</code></th>
<td><code>&lt;&lt;title&gt;&gt; &lt;&lt;library_type&gt;&gt;s</code></td>
</tr>
<tr>
<th>Default Template</th>
<td>
```yaml
default_template:
plex_all: true
filters:
origin_country: <<origin_country>>
```
</td>
</tr>
</table>
#### Example: Create collection for every TMDb Origin Country found in the library.
```yaml
dynamic_collections:
TMDb Countries: # This name is the mapping name
type: origin_country
```
### Trakt User Lists
@ -292,7 +340,7 @@ Create collections for each of the Trakt lists for the specified users. Use `me`
<td>Trakt List URL</td>
</tr>
<tr>
<th>Titles</th>
<th>Key Names</th>
<td>Trakt List Title</td>
</tr>
<tr>
@ -343,7 +391,7 @@ Create collections for each of the Trakt lists that the authenticated user has l
<td>Trakt List URL</td>
</tr>
<tr>
<th>Titles</th>
<th>Key Names</th>
<td>Trakt List Title</td>
</tr>
<tr>
@ -391,7 +439,7 @@ Create collections for each of the people found within Trakt lists that the user
<td>TMDb Person ID</td>
</tr>
<tr>
<th>Titles</th>
<th>Key Names</th>
<td>TMDb Person Name</td>
</tr>
<tr>
@ -463,7 +511,7 @@ Create a collection for each actor found in the library.
<td>TMDb Person ID</td>
</tr>
<tr>
<th>Titles</th>
<th>Key Names</th>
<td>TMDb Person Name</td>
</tr>
<tr>
@ -490,6 +538,33 @@ default_template:
* `minimum` determines the minimum number of times the actor must appear within `depth` for the collection to be created.
* `limit` determines the number of actor collection to max out at. (i.e. if to make collections for the top 25 actors)
#### Example:
* Create a collection for the top 25 actors who appear in the top 5 billing credits of movies
```yaml
dynamic_collections:
Top Actors: # mapping name does not matter just needs to be unique
type: actor
data:
depth: 5
limit: 25
```
#### Example:
* Create a collection for actors who appear in the top 5 billing credits of movies
* Only create the collection if they are in the top 5 billing credits of at least 20 movies
```yaml
dynamic_collections:
Actors: # mapping name does not matter just needs to be unique
type: actor
data:
depth: 5
minimum: 20
```
### Director
Create a collection for each director found in the library.
@ -530,7 +605,7 @@ Create a collection for each director found in the library.
<td>TMDb Person ID</td>
</tr>
<tr>
<th>Titles</th>
<th>Key Names</th>
<td>TMDb Person Name</td>
</tr>
<tr>
@ -557,6 +632,33 @@ default_template:
* `minimum` determines the minimum number of times the director must appear within `depth` for the collection to be created.
* `limit` determines the number of director collection to max out at. (i.e. if to make collections for the top 25 directors)
#### Example:
* Create a collection for the top 5 directors who appear in the top director credit of movies
```yaml
dynamic_collections:
Top Directors: # mapping name does not matter just needs to be unique
type: director
data:
depth: 1
limit: 5
```
#### Example:
* Create a collection for directors who appear in the top director credits of movies
* Only create the collection if they are in the top director credits of at least 10 movies
```yaml
dynamic_collections:
Directors: # mapping name does not matter just needs to be unique
type: director
data:
depth: 1
minimum: 10
```
### Writer
Create a collection for each writer found in the library.
@ -597,7 +699,7 @@ Create a collection for each writer found in the library.
<td>TMDb Person ID</td>
</tr>
<tr>
<th>Titles</th>
<th>Key Names</th>
<td>TMDb Person Name</td>
</tr>
<tr>
@ -624,6 +726,33 @@ default_template:
* `minimum` determines the minimum number of times the writer must appear within `depth` for the collection to be created.
* `limit` determines the number of writer collection to max out at. (i.e. if to make collections for the top 25 writers)
#### Example:
* Create a collection for the top 5 writers who appear in the top writer credit of movies
```yaml
dynamic_collections:
Top Writers: # mapping name does not matter just needs to be unique
type: writer
data:
depth: 1
limit: 5
```
#### Example:
* Create a collection for writers who appear in the top writer credits of movies
* Only create the collection if they are in the top writer credits of at least 10 movies
```yaml
dynamic_collections:
Writers: # mapping name does not matter just needs to be unique
type: writer
data:
depth: 1
minimum: 10
```
### Producer
Create a collection for each producer found in the library.
@ -664,7 +793,7 @@ Create a collection for each producer found in the library.
<td>TMDb Person ID</td>
</tr>
<tr>
<th>Titles</th>
<th>Key Names</th>
<td>TMDb Person Name</td>
</tr>
<tr>
@ -693,29 +822,29 @@ default_template:
#### Example:
* Create a collection for the top 25 actors who appear in the top 5 billing credits of movies
* Create a collection for the top 5 producers who appear in the top producer credit of movies
```yaml
dynamic_collections:
Top Actors: # mapping name does not matter just needs to be unique
type: actor
Top Producers: # mapping name does not matter just needs to be unique
type: producer
data:
depth: 5
limit: 25
depth: 1
limit: 5
```
#### Example:
* Create a collection for actors who appear in the top 5 billing credits of movies
* Only create the collection if they are in the top 5 billing credits of at least 20 movies
* Create a collection for producers who appear in the top producer credits of movies
* Only create the collection if they are in the top producer credits of at least 10 movies
```yaml
dynamic_collections:
Actors: # mapping name does not matter just needs to be unique
type: actor
Producers: # mapping name does not matter just needs to be unique
type: producers
data:
depth: 5
minimum: 20
depth: 1
minimum: 10
```
### Genre
@ -736,7 +865,7 @@ Create a collection for each genre found in the library.
<td>Genre</td>
</tr>
<tr>
<th>Titles</th>
<th>Key Names</th>
<td>Genre</td>
</tr>
<tr>
@ -802,7 +931,7 @@ Create a collection for each year found in the library.
<td>Year</td>
</tr>
<tr>
<th>Titles</th>
<th>Key Names</th>
<td>Year</td>
</tr>
<tr>
@ -861,7 +990,7 @@ Create a collection for each decade found in the library
<td>Decade</td>
</tr>
<tr>
<th>Titles</th>
<th>Key Names</th>
<td>Decade</td>
</tr>
<tr>
@ -896,7 +1025,7 @@ dynamic_collections:
Decades: # mapping name does not matter just needs to be unique
type: decade
title_format: Top <<key_name>> <<library_type>>s
post_format_override:
title_override:
2020: Top 2020 Movies (so far)
```
@ -918,7 +1047,7 @@ Create a collection for each country found in the library
<td>Country</td>
</tr>
<tr>
<th>Titles</th>
<th>Key Names</th>
<td>Country</td>
</tr>
<tr>
@ -946,14 +1075,14 @@ default_template:
* Create a collection for the top movies from each country found in the library
* Name the collection Top [Country] Cinema
* The `pre_format_override` attribute is used here in combination with the `title_format` to change the collection name from "France" which would be the default title, to "Top French Cinema"
* The `key_name_override` attribute is used here in combination with the `title_format` to change the collection name from "France" which would be the default title, to "Top French Cinema"
```yaml
dynamic_collections:
Countries: # mapping name does not matter just needs to be unique
type: country
title_format: Top <<key_name>> Cinema
pre_format_override:
key_name_override:
France: French
Germany: German
India: Indian
@ -977,7 +1106,7 @@ Create a collection for each network found in the library.
<td>Network</td>
</tr>
<tr>
<th>Titles</th>
<th>Key Names</th>
<td>Network</td>
</tr>
<tr>
@ -1038,7 +1167,7 @@ Create a collection for each mood found in the library.
<td>Mood</td>
</tr>
<tr>
<th>Titles</th>
<th>Key Names</th>
<td>Mood</td>
</tr>
<tr>
@ -1101,7 +1230,7 @@ Create a collection for each style found in the library.
<td>Style</td>
</tr>
<tr>
<th>Titles</th>
<th>Key Names</th>
<td>Style</td>
</tr>
<tr>
@ -1252,11 +1381,11 @@ dynamic_collections:
title_format: Top 50 <<key_name>> <<library_type>>s
```
## Pre Format Override
## Key Name Override
Defines how titles can be overridden before they are formatted into collection titles.
Defines how key names can be overridden before they are formatted into collection titles.
This example uses the `pre_format_override` attribute to change the formatting of "France" to "French" so that a collection can be named "French Cinema" instead of simply "France"
This example uses the `key_name_override` attribute to change the formatting of "France" to "French" so that a collection can be named "French Cinema" instead of simply "France"
* This particular example also uses the `title_format` attribute to manipulate the naming convention of the collections.
```yaml
@ -1264,22 +1393,22 @@ dynamic_collections:
Countries: # mapping name does not matter, just needs to be unique
type: country
title_format: <<key_name>> Cinema
pre_format_override:
key_name_override:
France: French
```
## Post Format Override
## Title Override
Defines how collection titles can be overridden ignoring title formatting.
Here's an example using `post_format_override` that will override the TMDb Star Wars collection which has an TMDb ID of `10` with `Star Wars Universe.
Here's an example using `title_override` that will override the TMDb Star Wars collection which has an TMDb ID of `10` with `Star Wars Universe.
```yaml
dynamic_collections:
TMDb Collections: # mapping name does not matter, just needs to be unique
type: tmdb_collections
remove_suffix: "Collection"
post_format_override:
title_override:
10: Star Wars Universe
```

@ -11,6 +11,7 @@ You can use the `plex_all: true` builder to filter from your entire library.
**Filters can be very slow. Try to build or narrow your items using [Plex Search](builders/plex.md#plex-search) if possible.**
## String Filters
String filters can be used with either no modifier or with `.not`, `.is`, `.isnot`, `.begins`, `.ends`, or `.regex`.
String filters can take multiple values **only as a list**.
@ -39,12 +40,11 @@ String filters can take multiple values **only as a list**.
| `audio_track_title` | Uses the audio track titles to match | &#9989; | &#10060; | &#10060; | &#9989; | &#10060; | &#10060; | &#9989; |
## Tag Filters
Tag filters can be used with either no modifier or with `.not`.
Tag filters can take multiple values as a **list or a comma-separated string**.
The `original_language` and `tmdb_genre` filters will also filter out movies/shows from being added to Radarr/Sonarr.
### Modifier
| Tag Modifier | Description |
@ -58,28 +58,33 @@ The `original_language` and `tmdb_genre` filters will also filter out movies/sho
### Attribute
| Tag Filters | Description | Movies | Shows | Seasons | Episodes | Artists | Albums | Track |
|:--------------------|:------------------------------------------------------------------------------------------------------------------------------------------------------|:--------:|:--------:|:--------:|:--------:|:--------:|:--------:|:--------:|
| `actor` | Uses the actor tags to match | &#9989; | &#9989; | &#10060; | &#9989; | &#10060; | &#10060; | &#10060; |
| `collection` | Uses the collection tags to match | &#9989; | &#9989; | &#9989; | &#9989; | &#9989; | &#9989; | &#9989; |
| `content_rating` | Uses the content rating tags to match | &#9989; | &#9989; | &#10060; | &#9989; | &#10060; | &#10060; | &#10060; |
| `network` | Uses the network tags to match | &#10060; | &#9989; | &#10060; | &#10060; | &#10060; | &#10060; | &#10060; |
| `country` | Uses the country tags to match | &#9989; | &#10060; | &#10060; | &#10060; | &#9989; | &#10060; | &#10060; |
| `director` | Uses the director tags to match | &#9989; | &#10060; | &#10060; | &#9989; | &#10060; | &#10060; | &#10060; |
| `genre` | Uses the genre tags to match | &#9989; | &#9989; | &#10060; | &#10060; | &#9989; | &#9989; | &#10060; |
| `tmdb_genre` | Uses the genre from TMDb to match | &#9989; | &#9989; | &#10060; | &#10060; | &#10060; | &#10060; | &#10060; |
| `label` | Uses the label tags to match | &#9989; | &#9989; | &#10060; | &#10060; | &#10060; | &#9989; | &#10060; |
| `producer` | Uses the actor tags to match | &#9989; | &#10060; | &#10060; | &#9989; | &#10060; | &#10060; | &#10060; |
| `year` | Uses the year tag to match | &#9989; | &#9989; | &#9989; | &#9989; | &#10060; | &#9989; | &#9989; |
| `writer` | Uses the writer tags to match | &#9989; | &#10060; | &#10060; | &#9989; | &#10060; | &#10060; | &#10060; |
| `resolution` | Uses the resolution tag to match | &#9989; | &#10060; | &#10060; | &#9989; | &#10060; | &#10060; | &#10060; |
| `audio_language` | Uses the audio language tags to match | &#9989; | &#10060; | &#10060; | &#9989; | &#10060; | &#10060; | &#10060; |
| `subtitle_language` | Uses the subtitle language tags to match | &#9989; | &#10060; | &#10060; | &#9989; | &#10060; | &#10060; | &#10060; |
| `original_language` | Uses TMDb original language [ISO 639-1 codes](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) to match<br>Example: `original_language: en, ko` | &#10060; | &#9989; | &#10060; | &#10060; | &#10060; | &#10060; | &#10060; |
| `tmdb_status` | Uses TMDb Status to match<br>**Values:** `returning`, `planned`, `production`, `ended`, `canceled`, `pilot` | &#10060; | &#9989; | &#10060; | &#10060; | &#10060; | &#10060; | &#10060; |
| `tmdb_type` | Uses TMDb Type to match<br>**Values:** `documentary`, `news`, `production`, `miniseries`, `reality`, `scripted`, `talk_show`, `video` | &#10060; | &#9989; | &#10060; | &#10060; | &#10060; | &#10060; | &#10060; |
| Tag Filters | Description | Movies | Shows | Seasons | Episodes | Artists | Albums | Track |
|:--------------------------------|:------------------------------------------------------------------------------------------------------------------------------------------------------|:--------:|:--------:|:--------:|:--------:|:--------:|:--------:|:--------:|
| `actor` | Uses the actor tags to match | &#9989; | &#9989; | &#10060; | &#9989; | &#10060; | &#10060; | &#10060; |
| `collection` | Uses the collection tags to match | &#9989; | &#9989; | &#9989; | &#9989; | &#9989; | &#9989; | &#9989; |
| `content_rating` | Uses the content rating tags to match | &#9989; | &#9989; | &#10060; | &#9989; | &#10060; | &#10060; | &#10060; |
| `network` | Uses the network tags to match | &#10060; | &#9989; | &#10060; | &#10060; | &#10060; | &#10060; | &#10060; |
| `country` | Uses the country tags to match | &#9989; | &#10060; | &#10060; | &#10060; | &#9989; | &#10060; | &#10060; |
| `director` | Uses the director tags to match | &#9989; | &#10060; | &#10060; | &#9989; | &#10060; | &#10060; | &#10060; |
| `genre` | Uses the genre tags to match | &#9989; | &#9989; | &#10060; | &#10060; | &#9989; | &#9989; | &#10060; |
| `tmdb_genre`<sup>1</sup> | Uses the genre from TMDb to match | &#9989; | &#9989; | &#10060; | &#10060; | &#10060; | &#10060; | &#10060; |
| `tmdb_keyword`<sup>1</sup> | Uses the keyword from TMDb to match | &#9989; | &#9989; | &#10060; | &#10060; | &#10060; | &#10060; | &#10060; |
| `label` | Uses the label tags to match | &#9989; | &#9989; | &#10060; | &#10060; | &#10060; | &#9989; | &#10060; |
| `producer` | Uses the actor tags to match | &#9989; | &#10060; | &#10060; | &#9989; | &#10060; | &#10060; | &#10060; |
| `year` | Uses the year tag to match | &#9989; | &#9989; | &#9989; | &#9989; | &#10060; | &#9989; | &#9989; |
| `writer` | Uses the writer tags to match | &#9989; | &#10060; | &#10060; | &#9989; | &#10060; | &#10060; | &#10060; |
| `resolution` | Uses the resolution tag to match | &#9989; | &#10060; | &#10060; | &#9989; | &#10060; | &#10060; | &#10060; |
| `audio_language` | Uses the audio language tags to match | &#9989; | &#10060; | &#10060; | &#9989; | &#10060; | &#10060; | &#10060; |
| `subtitle_language` | Uses the subtitle language tags to match | &#9989; | &#10060; | &#10060; | &#9989; | &#10060; | &#10060; | &#10060; |
| `original_language`<sup>1</sup> | Uses TMDb original language [ISO 639-1 codes](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) to match<br>Example: `original_language: en, ko` | &#10060; | &#9989; | &#10060; | &#10060; | &#10060; | &#10060; | &#10060; |
| `origin_country`<sup>1</sup> | Uses TMDb origin country [ISO 3166-1 alpha-2 codes](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) to match<br>Example: `origin_country: us` | &#10060; | &#9989; | &#10060; | &#10060; | &#10060; | &#10060; | &#10060; |
| `tmdb_status`<sup>1</sup> | Uses TMDb Status to match<br>**Values:** `returning`, `planned`, `production`, `ended`, `canceled`, `pilot` | &#10060; | &#9989; | &#10060; | &#10060; | &#10060; | &#10060; | &#10060; |
| `tmdb_type`<sup>1</sup> | Uses TMDb Type to match<br>**Values:** `documentary`, `news`, `production`, `miniseries`, `reality`, `scripted`, `talk_show`, `video` | &#10060; | &#9989; | &#10060; | &#10060; | &#10060; | &#10060; | &#10060; |
<sup>1</sup> Also filters out missing movies/shows from being added to Radarr/Sonarr. These Values also cannot use the `count` modifiers.
## Boolean Filters
Boolean Filters have no modifiers.
### Attribute
@ -90,12 +95,11 @@ Boolean Filters have no modifiers.
| `has_overlay` | Matches every item that has or does not have an overlay | &#9989; | &#9989; | &#10060; | &#10060; | &#10060; | &#10060; | &#10060; |
## Date Filters
Date filters can be used with either no modifier or with `.not`, `.before`, `.after`, or `.regex`.
Date filters can **NOT** take multiple values.
The `first_episode_aired` and `last_episode_aired` filters will also filter out movies/shows from being added to Radarr/Sonarr.
### Modifier
| Date Modifier | Description | Format |
@ -108,21 +112,22 @@ The `first_episode_aired` and `last_episode_aired` filters will also filter out
### Attribute
| Date Filters | Description | Movies | Shows | Seasons | Episodes | Artists | Albums | Track |
|:----------------------|:----------------------------------------------------------------|:--------:|:-------:|:--------:|:--------:|:--------:|:--------:|:--------:|
| `release` | Uses the release date attribute (originally available) to match | &#9989; | &#9989; | &#10060; | &#9989; | &#10060; | &#9989; | &#10060; |
| `added` | Uses the date added attribute to match | &#9989; | &#9989; | &#9989; | &#9989; | &#9989; | &#9989; | &#9989; |
| `last_played` | Uses the date last played attribute to match | &#9989; | &#9989; | &#9989; | &#9989; | &#9989; | &#9989; | &#9989; |
| `first_episode_aired` | Uses the first episode aired date to match | &#10060; | &#9989; | &#10060; | &#10060; | &#10060; | &#10060; | &#10060; |
| `last_episode_aired` | Uses the last episode aired date to match | &#10060; | &#9989; | &#10060; | &#10060; | &#10060; | &#10060; | &#10060; |
| Date Filters | Description | Movies | Shows | Seasons | Episodes | Artists | Albums | Track |
|:----------------------------------|:----------------------------------------------------------------|:--------:|:-------:|:--------:|:--------:|:--------:|:--------:|:--------:|
| `release` | Uses the release date attribute (originally available) to match | &#9989; | &#9989; | &#10060; | &#9989; | &#10060; | &#9989; | &#10060; |
| `added` | Uses the date added attribute to match | &#9989; | &#9989; | &#9989; | &#9989; | &#9989; | &#9989; | &#9989; |
| `last_played` | Uses the date last played attribute to match | &#9989; | &#9989; | &#9989; | &#9989; | &#9989; | &#9989; | &#9989; |
| `first_episode_aired`<sup>1</sup> | Uses the first episode aired date to match | &#10060; | &#9989; | &#10060; | &#10060; | &#10060; | &#10060; | &#10060; |
| `last_episode_aired`<sup>1</sup> | Uses the last episode aired date to match | &#10060; | &#9989; | &#10060; | &#10060; | &#10060; | &#10060; | &#10060; |
<sup>1</sup> Also filters out missing movies/shows from being added to Radarr/Sonarr.
## Number Filters
Number filters must use `.gt`, `.gte`, `.lt`, or `.lte` as a modifier.
Number filters can **NOT** take multiple values.
The `tmdb_vote_count` and `tmdb_year` filters will also filter out movies/shows from being added to Radarr/Sonarr.
### Modifier
| Number Modifier | Description | Format |
@ -134,18 +139,21 @@ The `tmdb_vote_count` and `tmdb_year` filters will also filter out movies/shows
### Attribute
| Number Filters | Description | Movies | Shows | Seasons | Episodes | Artists | Albums | Track |
|:------------------|:---------------------------------------------------------------------|:-------:|:-------:|:--------:|:--------:|:--------:|:--------:|:--------:|
| `year` | Uses the year attribute to match<br>minimum: `1` | &#9989; | &#9989; | &#9989; | &#9989; | &#10060; | &#9989; | &#9989; |
| `tmdb_year` | Uses the year on TMDb to match<br>minimum: `1` | &#9989; | &#9989; | &#10060; | &#10060; | &#10060; | &#10060; | &#10060; |
| `critic_rating` | Uses the critic rating attribute to match<br>`0.0` - `10.0` | &#9989; | &#9989; | &#10060; | &#9989; | &#10060; | &#9989; | &#10060; |
| `audience_rating` | Uses the audience rating attribute to match<br> `0.0` - `10.0` | &#9989; | &#9989; | &#10060; | &#9989; | &#10060; | &#10060; | &#10060; |
| `user_rating` | Uses the user rating attribute to match<br>`0.0` - `10.0` | &#9989; | &#9989; | &#9989; | &#9989; | &#9989; | &#9989; | &#9989; |
| `tmdb_vote_count` | Uses the tmdb vote count to match<br>minimum: `1` | &#9989; | &#9989; | &#10060; | &#10060; | &#10060; | &#10060; | &#10060; |
| `plays` | Uses the plays attribute to match<br>minimum: `1` | &#9989; | &#9989; | &#9989; | &#9989; | &#9989; | &#9989; | &#9989; |
| `duration` | Uses the duration attribute to match using minutes<br>minimum: `0.0` | &#9989; | &#9989; | &#10060; | &#9989; | &#10060; | &#10060; | &#9989; |
| Number Filters | Description | Movies | Shows | Seasons | Episodes | Artists | Albums | Track |
|:------------------------------|:---------------------------------------------------------------------|:-------:|:-------:|:--------:|:--------:|:--------:|:--------:|:--------:|
| `year` | Uses the year attribute to match<br>minimum: `1` | &#9989; | &#9989; | &#9989; | &#9989; | &#10060; | &#9989; | &#9989; |
| `tmdb_year`<sup>1</sup> | Uses the year on TMDb to match<br>minimum: `1` | &#9989; | &#9989; | &#10060; | &#10060; | &#10060; | &#10060; | &#10060; |
| `critic_rating` | Uses the critic rating attribute to match<br>`0.0` - `10.0` | &#9989; | &#9989; | &#10060; | &#9989; | &#10060; | &#9989; | &#10060; |
| `audience_rating` | Uses the audience rating attribute to match<br> `0.0` - `10.0` | &#9989; | &#9989; | &#10060; | &#9989; | &#10060; | &#10060; | &#10060; |
| `user_rating` | Uses the user rating attribute to match<br>`0.0` - `10.0` | &#9989; | &#9989; | &#9989; | &#9989; | &#9989; | &#9989; | &#9989; |
| `tmdb_vote_count`<sup>1</sup> | Uses the tmdb vote count to match<br>minimum: `1` | &#9989; | &#9989; | &#10060; | &#10060; | &#10060; | &#10060; | &#10060; |
| `plays` | Uses the plays attribute to match<br>minimum: `1` | &#9989; | &#9989; | &#9989; | &#9989; | &#9989; | &#9989; | &#9989; |
| `duration` | Uses the duration attribute to match using minutes<br>minimum: `0.0` | &#9989; | &#9989; | &#10060; | &#9989; | &#10060; | &#10060; | &#9989; |
<sup>1</sup> Also filters out missing movies/shows from being added to Radarr/Sonarr.
## Special Filters
Special Filters each have their own set of rules for how they're used.
### Attribute

@ -132,7 +132,7 @@ filters_by_type = {
"movie_show": ["studio", "original_language", "has_overlay", "tmdb_vote_count", "tmdb_year", "tmdb_genre", "tmdb_title", "tmdb_keyword"],
"movie_episode": ["director", "producer", "writer", "resolution", "audio_language", "subtitle_language", "has_dolby_vision"],
"movie_artist": ["country"],
"show": ["tmdb_status", "tmdb_type", "network", "first_episode_aired", "last_episode_aired"],
"show": ["tmdb_status", "tmdb_type", "origin_country", "network", "first_episode_aired", "last_episode_aired"],
"album": ["record_label"]
}
filters = {
@ -144,11 +144,14 @@ filters = {
"album": [item for check, sub in filters_by_type.items() for item in sub if "album" in check],
"track": [item for check, sub in filters_by_type.items() for item in sub if "track" in check]
}
tmdb_filters = ["original_language", "tmdb_vote_count", "tmdb_year", "tmdb_keyword", "tmdb_genre", "first_episode_aired", "last_episode_aired", "tmdb_status", "tmdb_type", "tmdb_title"]
tmdb_filters = [
"original_language", "origin_country", "tmdb_vote_count", "tmdb_year", "tmdb_keyword", "tmdb_genre",
"first_episode_aired", "last_episode_aired", "tmdb_status", "tmdb_type", "tmdb_title"
]
string_filters = ["title", "summary", "studio", "record_label", "filepath", "audio_track_title", "tmdb_title"]
string_modifiers = ["", ".not", ".is", ".isnot", ".begins", ".ends", ".regex"]
tag_filters = [
"actor", "collection", "content_rating", "country", "director", "network", "genre", "label", "producer", "year",
"actor", "collection", "content_rating", "country", "director", "network", "genre", "label", "producer", "year", "origin_country",
"writer", "original_language", "resolution", "audio_language", "subtitle_language", "tmdb_keyword", "tmdb_genre", "tmdb_status", "tmdb_type"
]
tag_modifiers = ["", ".not", ".count_gt", ".count_gte", ".count_lt", ".count_lte"]
@ -1716,7 +1719,7 @@ class CollectionBuilder:
return valid_regex
elif attribute in plex.string_attributes + string_filters and modifier in ["", ".not", ".is", ".isnot", ".begins", ".ends"]:
return smart_pair(util.get_list(data, split=False))
elif attribute in ["original_language", "tmdb_keyword"]:
elif attribute in ["original_language", "origin_country", "tmdb_keyword"]:
return util.get_list(data, lower=True)
elif attribute in ["filepath", "tmdb_genre"]:
return util.get_list(data)
@ -1909,6 +1912,8 @@ class CollectionBuilder:
check_value = discover_types[item.type]
elif filter_attr == "original_language":
check_value = item.original_language.iso_639_1
else:
raise Failed
if (modifier == ".not" and check_value in filter_data) or (modifier == "" and check_value not in filter_data):
return False
elif filter_attr in ["first_episode_aired", "last_episode_aired"]:
@ -1927,13 +1932,15 @@ class CollectionBuilder:
attr = item.release_date.year if is_movie else item.first_air_date.year
if util.is_number_filter(attr, modifier, filter_data):
return False
elif filter_attr == "tmdb_genre":
attrs = [g.name for g in item.genres]
if (not list(set(filter_data) & set(attrs)) and modifier == "") \
or (list(set(filter_data) & set(attrs)) and modifier == ".not"):
return False
elif filter_attr == "tmdb_keyword":
attrs = [k.name for k in item.keywords]
elif filter_attr in ["tmdb_genre", "tmdb_keyword", "origin_country"]:
if filter_attr == "tmdb_genre":
attrs = [g.name for g in item.genres]
elif filter_attr == "tmdb_keyword":
attrs = [k.name for k in item.keywords]
elif filter_attr == "origin_country":
attrs = [c.iso_3166_1 for c in item.origin_countries]
else:
raise Failed
if (not list(set(filter_data) & set(attrs)) and modifier == "") \
or (list(set(filter_data) & set(attrs)) and modifier == ".not"):
return False

@ -14,7 +14,7 @@ all_auto = ["genre"]
ms_auto = ["actor", "year", "original_language", "tmdb_popular_people", "trakt_user_lists", "trakt_liked_lists", "trakt_people_list"]
auto = {
"Movie": ["tmdb_collection", "decade", "country", "director", "producer", "writer"] + all_auto + ms_auto,
"Show": ["network"] + all_auto + ms_auto,
"Show": ["network", "origin_country"] + all_auto + ms_auto,
"Artist": ["mood", "style", "country"] + all_auto,
"Video": ["country"] + all_auto
}
@ -24,6 +24,7 @@ default_templates = {
"producer": {"tmdb_person": f"<<producer>>", "plex_search": {"all": {"producer": "tmdb"}}},
"writer": {"tmdb_person": f"<<writer>>", "plex_search": {"all": {"writer": "tmdb"}}},
"original_language": {"plex_all": True, "filters": {"original_language": "<<original_language>>"}},
"origin_country": {"plex_all": True, "filters": {"origin_country": "<<origin_country>>"}},
"tmdb_collection": {"tmdb_collection_details": "<<tmdb_collection>>"},
"trakt_user_lists": {"trakt_list_details": "<<trakt_user_lists>>"},
"trakt_liked_lists": {"trakt_list_details": "<<trakt_liked_lists>>"},
@ -308,6 +309,19 @@ class MetadataFile(DataFile):
auto_list[tmdb_item.original_language.iso_639_1] = tmdb_item.original_language.english_name
logger.exorcise()
default_title_format = "<<key_name>> <<library_type>>s"
elif auto_type == "origin_country":
if not all_items:
all_items = library.get_all()
for i, item in enumerate(all_items, 1):
logger.ghost(f"Processing: {i}/{len(all_items)} {item.title}")
tmdb_id, tvdb_id, imdb_id = library.get_ids(item)
tmdb_item = config.TMDb.get_item(item, tmdb_id, tvdb_id, imdb_id, is_movie=library.type == "Movie")
if tmdb_item and tmdb_item.origin_countries:
for country in tmdb_item.origin_countries:
if country.iso_3166_1 not in exclude and country.name not in exclude:
auto_list[country.iso_3166_1] = country.name
logger.exorcise()
default_title_format = "<<key_name>> <<library_type>>s"
elif auto_type in ["actor", "director", "writer", "producer"]:
people = {}
if "data" in methods:
@ -372,8 +386,12 @@ class MetadataFile(DataFile):
if "<<key_name>>" not in title_format and "<<title>>" not in title_format:
logger.error(f"Config Error: <<key_name>> not in title_format: {title_format} using default: {default_title_format}")
title_format = default_title_format
post_format_override = util.parse("Config", "post_format_override", dynamic, parent=map_name, methods=methods, datatype="dict") if "post_format_override" in methods else {}
pre_format_override = util.parse("Config", "pre_format_override", dynamic, parent=map_name, methods=methods, datatype="dict") if "pre_format_override" in methods else {}
if "post_format_override" in methods:
methods["title_override"] = methods.pop("post_format_override")
if "pre_format_override" in methods:
methods["key_name_override"] = methods.pop("pre_format_override")
title_override = util.parse("Config", "title_override", dynamic, parent=map_name, methods=methods, datatype="dict") if "title_override" in methods else {}
key_name_override = util.parse("Config", "key_name_override", dynamic, parent=map_name, methods=methods, datatype="dict") if "key_name_override" in methods else {}
test = util.parse("Config", "test", dynamic, parent=map_name, methods=methods, default=False, datatype="bool") if "test" in methods else False
sync = util.parse("Config", "sync", dynamic, parent=map_name, methods=methods, default=False, datatype="bool") if "sync" in methods else False
if "<<library_type>>" in title_format:
@ -403,8 +421,8 @@ class MetadataFile(DataFile):
logger.debug(f"Remove Prefix: {remove_prefix}")
logger.debug(f"Remove Suffix: {remove_suffix}")
logger.debug(f"Title Format: {title_format}")
logger.debug(f"Pre Format Override: {pre_format_override}")
logger.debug(f"Post Format Override: {post_format_override}")
logger.debug(f"Key Name Override: {key_name_override}")
logger.debug(f"Title Override: {title_override}")
logger.debug(f"Test: {test}")
logger.debug(f"Sync: {sync}")
logger.debug(f"Include: {include}")
@ -422,11 +440,11 @@ class MetadataFile(DataFile):
for k, v in template_variables.items():
if key in v:
template_call[k] = v[key]
if key in post_format_override:
collection_title = post_format_override[key]
if key in title_override:
collection_title = title_override[key]
else:
if key in pre_format_override:
value = pre_format_override[key]
if key in key_name_override:
value = key_name_override[key]
else:
for prefix in remove_prefix:
if value.startswith(prefix):

@ -737,7 +737,7 @@ def library_operations(config, library):
logger.info("")
logger.info(f"Metadata Backup Path: {library.metadata_backup['path']}")
logger.info("")
meta = {"metadata": {}}
meta = {}
if os.path.exists(library.metadata_backup["path"]):
try:
meta, _, _ = yaml.util.load_yaml_guess_indent(open(library.metadata_backup["path"]))
@ -749,6 +749,8 @@ def library_operations(config, library):
i += 1
os.rename(library.metadata_backup["path"], f"{filename}{i}{file_extension}")
logger.error(f"Backup failed to load saving copy to {filename}{i}{file_extension}")
if "metadata" not in meta:
meta["metadata"] = {}
items = library.get_all(load=True)
titles = [i.title for i in items]
for i, item in enumerate(items, 1):

Loading…
Cancel
Save