[109] fix templates

pull/885/head
meisnate12 2 years ago
parent 8be2e69832
commit 78396323a7

@ -1 +1 @@
1.16.5-develop108 1.16.5-develop109

@ -1,6 +1,6 @@
# Configuration File # Configuration File
Plex Meta Manager uses a YAML configuration file; this file contains swettings that deterimine how Plex Meta Manaegr behaves, and the required connection details needed to connect to Plex Media Server, Radarr, Sonarr, and other third-party services via API. Plex Meta Manager uses a YAML configuration file; this file contains settings that determine how Plex Meta Manager behaves, and the required connection details needed to connect to Plex Media Server, Radarr, Sonarr, and other third-party services via API.
By default, and unless otherwise stated, Plex Meta Manager looks for the configuration file within `/config/config.yml` By default, and unless otherwise stated, Plex Meta Manager looks for the configuration file within `/config/config.yml`
@ -24,3 +24,218 @@ This table outlines the third-party services that Plex Meta Manager can make use
| [`sonarr`](sonarr) | ❌ | | [`sonarr`](sonarr) | ❌ |
| [`trakt`](trakt) | ❌ | | [`trakt`](trakt) | ❌ |
| [`mal`](myanimelist) | ❌ | | [`mal`](myanimelist) | ❌ |
# Configuration File Walkthrough
This example outlines what a "standard" config.yml file might look like when in use.
<details>
<summary>Example config.yml file</summary>
<br />
```yaml
libraries:
Movies - 4K:
metadata_path:
- file: config/Movies.yml
- git: meisnate12/MovieCharts
TV Shows:
metadata_path:
- file: config/TVShows.yml
- folder: config/TV Shows/
- git: meisnate12/ShowCharts
Animé:
metadata_path:
- file: config/Anime.yml
Music:
metadata_path:
- file: config/Music.yml
playlist_files:
- file: config/playlists.yml
- git: meisnate12/Playlists
settings:
cache: true
cache_expiration: 60
asset_directory: config/assets
asset_folders: true
asset_depth: 0
create_asset_folders: false
dimensional_asset_rename: false
download_url_assets: false
show_missing_season_assets: false
show_missing_episode_assets: false
show_asset_not_needed: true
sync_mode: append
minimum_items: 1
default_collection_order:
delete_below_minimum: true
delete_not_scheduled: false
run_again_delay: 2
missing_only_released: false
only_filter_missing: false
show_unmanaged: true
show_filtered: false
show_options: false
show_missing: true
show_missing_assets: true
save_report: true
tvdb_language: eng
ignore_ids:
ignore_imdb_ids:
item_refresh_delay: 0
playlist_sync_to_users: all
verify_ssl: true
webhooks:
error:
run_start:
run_end:
changes:
version:
plex:
url: http://192.168.1.12:32400
token: ####################
timeout: 60
clean_bundles: false
empty_trash: false
optimize: false
tmdb:
apikey: ################################
language: en
tautulli:
url: http://192.168.1.12:8181
apikey: ################################
omdb:
apikey: ########
notifiarr:
apikey: ####################################
anidb:
username: ######
password: ######
radarr:
url: http://192.168.1.12:7878
token: ################################
add_missing: false
add_existing: false
root_folder_path: S:/Movies
monitor: true
availability: announced
quality_profile: HD-1080p
tag:
search: false
radarr_path:
plex_path:
sonarr:
url: http://192.168.1.12:8989
token: ################################
add_missing: false
add_existing: false
root_folder_path: "S:/TV Shows"
monitor: all
quality_profile: HD-1080p
language_profile: English
series_type: standard
season_folder: true
tag:
search: false
cutoff_search: false
sonarr_path:
plex_path:
trakt:
client_id: ################################################################
client_secret: ################################################################
authorization:
# everything below is autofilled by the script
access_token:
token_type:
expires_in:
refresh_token:
scope: public
created_at:
mal:
client_id: ################################
client_secret: ################################################################
authorization:
# everything below is autofilled by the script
access_token:
token_type:
expires_in:
refresh_token:
```
</details>
**Expand the above to see the full config.yml file before continuing.**
<br/>
## Library Mappings (`libraries:`)
`libraries:` is used to tell PMM that the following code relates to Plex libraries. `libraries:` should only be seen once within the configuration file.
In this specific example there are four Plex libraries that are being connected to: `Movies - 4K`, `TV Shows`, `Animé` and `Music`. These names **must** match the name of the library as it appears within Plex, including any special characters such as the é within `Animé`.
Using `Movies - 4K:` as an example, `metadata_path:` instructs PMM that the next piece of code is where to look for the [Metadata Files](../../metadata/metadata) which will be covered in the next section.
<br/>
<br/>
## Metadata/YAML files (`metadata_path:` mappings)
As can be seen in the original config.yml example, there are three metadata_paths being pointed to for the TV Shows library:
```yaml
TV Shows:
metadata_path:
- file: config/TVShows.yml
- folder: config/TV Shows/
- git: meisnate12/ShowCharts
```
These path types are outlined as follows:
* `- file:` refers to a YAML file which is located within the system that PMM is being run from.
* `- folder:` refers to a directory containing YAML files which is located within the system that PMM is being run from.
* `- git:` refers to a YAML file which is hosted on the [GitHub Configs Repo](https://github.com/meisnate12/Plex-Meta-Manager-Configs) unless the user has specified a custom repository within the settings section of the config.yml file.
Within the above example, PMM will:
* First, look within the root of the PMM directory (also known as `config/`) for a metadata file named `Movies.yml`. If this file does not exist, PMM will skip the entry and move to the next one in the list.
* Then, look within the root of the PMM directory (also known as `config/`) for a directory called `TV Shows`, and then load any metadata/YAML files within that directory.
* Finally, look at the [meisnate12 folder](https://github.com/meisnate12/Plex-Meta-Manager-Configs/tree/master/meisnate12) within the GitHub Configs Repo for a file called `MovieCharts.yml` which it finds [here](https://github.com/meisnate12/Plex-Meta-Manager-Configs/blob/master/meisnate12/MovieCharts.yml).
It should be noted that whilst the user should be able to edit any metadata files which are `- file:` or `- folder:` based, they have little to no control over `- git:` metadata files **unless a copy of the YAML file is downloaded and ran locally**. In the above example, if the user downloaded the [MovieCharts.yml file](https://github.com/meisnate12/Plex-Meta-Manager-Configs/blob/master/meisnate12/MovieCharts.yml) from the [GitHub Configs Repo](https://github.com/meisnate12/Plex-Meta-Manager-Configs) and placed it in the root directory of PMM (`config/`), then the metadata_path mapping would be updated to reflect this as follows:
```yaml
Movies - 4K:
metadata_path:
- file: config/Movies.yml
- file: config/MovieCharts.yml <------ HERE
```
## Playlists (`playlist_files:` mappings)
Playlists can be seen as an extension of Libraries in that they are both handled very similarly within PMM:
```yaml
playlist_files:
- file: config/playlists.yml
- git: meisnate12/Playlists
```
As with `libraries:`, YAML files are defined to create the Playlists. It should be noted that whilst in `libraries:` when working with `playlist_files:` you call out the libraries being connected to within the Metadata/YAML file as Playlists can combine media from multiple libraries. You can view an example playlists.yml file as follows:
<details>
<summary>Example playlists.yml file</summary>
<br />
```yaml
playlists:
Marvel Cinematic Universe:
sync_to_users: all
sync_mode: sync
libraries: Movies, TV Shows
trakt_list: https://trakt.tv/users/donxy/lists/marvel-cinematic-universe?sort=rank,asc
summary: Marvel Cinematic Universe In Order
Star Wars Clone Wars Chronological Order:
sync_to_users: all
sync_mode: sync
libraries: Movies, TV Shows
trakt_list: https://trakt.tv/users/tomfin46/lists/star-wars-the-clone-wars-chronological-episode-order
```
</details>
As can be seen in the above examples, multiple libraries are being used to combine different types of media (movies and tv shows in this case) into one playlist.

@ -1,213 +0,0 @@
# Configuration File Walkthrough
This example outlines what a "standard" config.yml file might look like when in use.
<details>
<summary>Example config.yml file</summary>
<br />
```yaml
libraries:
Movies - 4K:
metadata_path:
- file: config/Movies.yml
- git: meisnate12/MovieCharts
TV Shows:
metadata_path:
- file: config/TVShows.yml
- folder: config/TV Shows/
- git: meisnate12/ShowCharts
Animé:
metadata_path:
- file: config/Anime.yml
Music:
metadata_path:
- file: config/Music.yml
playlist_files:
- file: config/playlists.yml
- git: meisnate12/Playlists
settings:
cache: true
cache_expiration: 60
asset_directory: config/assets
asset_folders: true
asset_depth: 0
create_asset_folders: false
dimensional_asset_rename: false
download_url_assets: false
show_missing_season_assets: false
show_missing_episode_assets: false
show_asset_not_needed: true
sync_mode: append
minimum_items: 1
default_collection_order:
delete_below_minimum: true
delete_not_scheduled: false
run_again_delay: 2
missing_only_released: false
only_filter_missing: false
show_unmanaged: true
show_filtered: false
show_options: false
show_missing: true
show_missing_assets: true
save_missing: true
tvdb_language: eng
ignore_ids:
ignore_imdb_ids:
item_refresh_delay: 0
playlist_sync_to_user: all
verify_ssl: true
webhooks:
error:
run_start:
run_end:
changes:
plex:
url: http://192.168.1.12:32400
token: ####################
timeout: 60
clean_bundles: false
empty_trash: false
optimize: false
tmdb:
apikey: ################################
language: en
tautulli:
url: http://192.168.1.12:8181
apikey: ################################
omdb:
apikey: ########
notifiarr:
apikey: ####################################
anidb:
username: ######
password: ######
radarr:
url: http://192.168.1.12:7878
token: ################################
add_missing: false
add_existing: false
root_folder_path: S:/Movies
monitor: true
availability: announced
quality_profile: HD-1080p
tag:
search: false
radarr_path:
plex_path:
sonarr:
url: http://192.168.1.12:8989
token: ################################
add_missing: false
add_existing: false
root_folder_path: "S:/TV Shows"
monitor: all
quality_profile: HD-1080p
language_profile: English
series_type: standard
season_folder: true
tag:
search: false
cutoff_search: false
sonarr_path:
plex_path:
trakt:
client_id: ################################################################
client_secret: ################################################################
authorization:
# everything below is autofilled by the script
access_token:
token_type:
expires_in:
refresh_token:
scope: public
created_at:
mal:
client_id: ################################
client_secret: ################################################################
authorization:
# everything below is autofilled by the script
access_token:
token_type:
expires_in:
refresh_token:
```
</details>
**Expand the above to see the full config.yml file before continuing.**
<br/>
## Library Mappings (`libraries:`)
`libraries:` is used to tell PMM that the following code relates to Plex libraries. `libraries:` should only be seen once within the configuration file.
In this specific example there are four Plex libraries that are being connected to: `Movies - 4K`, `TV Shows`, `Animé` and `Music`. These names **must** match the name of the library as it appears within Plex, including any special characters such as the é within `Animé`.
Using `Movies - 4K:` as an example, `metadata_path:` instructs PMM that the next piece of code is where to look for the [Metadata Files](../../metadata/metadata) which will be covered in the next section.
<br/>
<br/>
## Metadata/YAML files (`metadata_path:` mappings)
As can be seen in the original config.yml example, there are three metadata_paths being pointed to for the TV Shows library:
```yaml
TV Shows:
metadata_path:
- file: config/TVShows.yml
- folder: config/TV Shows/
- git: meisnate12/ShowCharts
```
These path types are outlined as follows:
* `- file:` refers to a YAML file which is located within the system that PMM is being run from.
* `- folder:` refers to a directory containing YAML files which is located within the system that PMM is being run from.
* `- git:` refers to a YAML file which is hosted on the [GitHub Configs Repo](https://github.com/meisnate12/Plex-Meta-Manager-Configs) unless the user has specified a custom repository within the settings section of the config.yml file.
Within the above example, PMM will:
* First, look within the root of the PMM directory (also known as `config/`) for a metadata file named `Movies.yml`. If this file does not exist, PMM will skip the entry and move to the next one in the list.
* Then, look within the root of the PMM directory (also known as `config/`) for a directory called `TV Shows`, and then load any metadata/YAML files within that directory.
* Finally, look at the [meisnate12 folder](https://github.com/meisnate12/Plex-Meta-Manager-Configs/tree/master/meisnate12) within the GitHub Configs Repo for a file called `MovieCharts.yml` which it finds [here](https://github.com/meisnate12/Plex-Meta-Manager-Configs/blob/master/meisnate12/MovieCharts.yml).
It should be noted that whilst the user should be able to edit any metadata files which are `- file:` or `- folder:` based, they have little to no control over `- git:` metadata files **unless a copy of the YAML file is downloaded and ran locally**. In the above example, if the user downloaded the [MovieCharts.yml file](https://github.com/meisnate12/Plex-Meta-Manager-Configs/blob/master/meisnate12/MovieCharts.yml) from the [GitHub Configs Repo](https://github.com/meisnate12/Plex-Meta-Manager-Configs) and placed it in the root directory of PMM (`config/`), then the metadata_path mapping would be updated to reflect this as follows:
```yaml
Movies - 4K:
metadata_path:
- file: config/Movies.yml
- file: config/MovieCharts.yml <------ HERE
```
## Playlists (`playlist_files:` mappings)
Playlists can be seen as an extension of Libraries in that they are both handled very similarly within PMM:
```yaml
playlist_files:
- file: config/playlists.yml
- git: meisnate12/Playlists
```
As with `libraries:`, YAML files are defined to create the Playlists. It should be noted that whilst in `libraries:` when working with `playlist_files:` you call out the libraries being connected to within the Metadata/YAML file as Playlists can combine media from multiple libraries. You can view an example playlists.yml file as follows:
<details>
<summary>Example playlists.yml file</summary>
<br />
```yaml
playlists:
Marvel Cinematic Universe:
sync_to_users: all
sync_mode: sync
libraries: Movies, TV Shows
trakt_list: https://trakt.tv/users/donxy/lists/marvel-cinematic-universe?sort=rank,asc
summary: Marvel Cinematic Universe In Order
Star Wars Clone Wars Chronological Order:
sync_to_users: all
sync_mode: sync
libraries: Movies, TV Shows
trakt_list: https://trakt.tv/users/tomfin46/lists/star-wars-the-clone-wars-chronological-episode-order
```
</details>
As can be seen in the above examples, multiple libraries are being used to combine different types of media (movies and tv shows in this case) into one playlist.

@ -136,7 +136,6 @@ libraries:
- git: PMM/overlays/streaming - git: PMM/overlays/streaming
- git: PMM/overlays/video_format - git: PMM/overlays/video_format
TV Shows: TV Shows:
missing_path: config/missing/TV_missing
metadata_path: metadata_path:
- git: PMM/award/choice - git: PMM/award/choice
- git: PMM/award/golden - git: PMM/award/golden

@ -1967,7 +1967,7 @@ class CollectionBuilder:
return smart_pair(final_years) return smart_pair(final_years)
elif (attribute in number_attributes + date_attributes + year_attributes and modifier in ["", ".not", ".gt", ".gte", ".lt", ".lte"]) \ elif (attribute in number_attributes + date_attributes + year_attributes and modifier in ["", ".not", ".gt", ".gte", ".lt", ".lte"]) \
or (attribute in plex.tag_attributes and modifier in [".count_gt", ".count_gte", ".count_lt", ".count_lte"]): or (attribute in plex.tag_attributes and modifier in [".count_gt", ".count_gte", ".count_lt", ".count_lte"]):
return util.parse(self.Type, final, data, datatype="int") return util.parse(self.Type, final, data, datatype="int", minimum=0)
elif attribute in plex.float_attributes and modifier in [".gt", ".gte", ".lt", ".lte"]: elif attribute in plex.float_attributes and modifier in [".gt", ".gte", ".lt", ".lte"]:
return util.parse(self.Type, final, data, datatype="float", minimum=0, maximum=None if attribute == "duration" else 10) return util.parse(self.Type, final, data, datatype="float", minimum=0, maximum=None if attribute == "duration" else 10)
elif attribute in plex.boolean_attributes + boolean_filters: elif attribute in plex.boolean_attributes + boolean_filters:

@ -143,23 +143,21 @@ class DataFile:
default = {} default = {}
if "default" in template: if "default" in template:
if template["default"]: if not template["default"]:
if isinstance(template["default"], dict): raise Failed(f"{self.data_type} Error: template sub-attribute default is blank")
if not isinstance(template["default"], dict):
raise Failed(f"{self.data_type} Error: template sub-attribute default is not a dictionary")
for dv in template["default"]: for dv in template["default"]:
if str(dv) not in optional: for k, v in variables.items():
if template["default"][dv] is not None: if f"<<{k}>>" in dv:
dv = dv.replace(f"<<{k}>>", str(v))
if dv not in optional:
final_value = template["default"][dv] final_value = template["default"][dv]
for key, value in variables.items(): for key, value in variables.items():
if f"<<{key}>>" in str(final_value): if f"<<{key}>>" in str(final_value):
final_value = str(final_value).replace(f"<<{key}>>", str(value)) final_value = str(final_value).replace(f"<<{key}>>", str(value))
default[dv] = final_value default[dv] = final_value
default[f"{dv}_encoded"] = requests.utils.quote(str(final_value)) default[f"{dv}_encoded"] = requests.utils.quote(str(final_value))
else:
raise Failed(f"{self.data_type} Error: template default sub-attribute {dv} is blank")
else:
raise Failed(f"{self.data_type} Error: template sub-attribute default is not a dictionary")
else:
raise Failed(f"{self.data_type} Error: template sub-attribute default is blank")
if "optional" in template: if "optional" in template:
if template["optional"]: if template["optional"]:
@ -210,26 +208,24 @@ class DataFile:
else: else:
final_data = _data final_data = _data
def scan_text(og_txt, var, var_value): def scan_text(og_txt, var, var_value):
if str(og_txt) == f"<<{var}>>": if og_txt is None:
return og_txt
elif str(og_txt) == f"<<{var}>>":
return var_value return var_value
elif f"<<{var}>>" in str(og_txt): elif f"<<{var}>>" in str(og_txt):
return str(og_txt).replace(f"<<{var}>>", str(var_value)) return str(og_txt).replace(f"<<{var}>>", str(var_value))
else:
return og_txt
for option in optional: for option in optional:
if option not in variables and f"<<{option}>>" in str(final_data): if option not in variables and f"<<{option}>>" in str(final_data):
raise Failed raise Failed
clean = False for i in range(2):
while not clean:
clean = True
for variable, variable_data in variables.items(): for variable, variable_data in variables.items():
var_data = None
if (variable == "collection_name" or variable == "playlist_name") and _method in ["radarr_tag", "item_radarr_tag", "sonarr_tag", "item_sonarr_tag"]: if (variable == "collection_name" or variable == "playlist_name") and _method in ["radarr_tag", "item_radarr_tag", "sonarr_tag", "item_sonarr_tag"]:
var_data = scan_text(final_data, variable, variable_data.replace(",", "")) final_data = scan_text(final_data, variable, variable_data.replace(",", ""))
elif variable != "name": elif variable != "name":
var_data = scan_text(final_data, variable, variable_data) final_data = scan_text(final_data, variable, variable_data)
if var_data:
final_data = var_data
clean = False
for dm, dd in default.items(): for dm, dd in default.items():
default_data = scan_text(final_data, dm, dd) default_data = scan_text(final_data, dm, dd)
if default_data: if default_data:
@ -238,9 +234,6 @@ class DataFile:
for method_name, attr_data in template.items(): for method_name, attr_data in template.items():
if method_name not in data and method_name not in ["default", "optional", "move_collection_prefix", "move_prefix"]: if method_name not in data and method_name not in ["default", "optional", "move_collection_prefix", "move_prefix"]:
if attr_data is None:
logger.error(f"Template Error: template attribute {method_name} is blank")
continue
if method_name in new_attributes: if method_name in new_attributes:
logger.warning(f"Template Warning: template attribute: {method_name} from {variables['name']} skipped") logger.warning(f"Template Warning: template attribute: {method_name} from {variables['name']} skipped")
else: else:

Loading…
Cancel
Save