From 299f165d11f8aebf0a7ccc8967d44d484fa2f34c Mon Sep 17 00:00:00 2001 From: bullmoose20 Date: Wed, 23 Aug 2023 16:39:03 -0400 Subject: [PATCH 1/5] Update plex.py with plex db cache size information --- modules/plex.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/modules/plex.py b/modules/plex.py index 0aa48069..46c8dac2 100644 --- a/modules/plex.py +++ b/modules/plex.py @@ -445,6 +445,8 @@ class Plex(Library): logger.info(f"Running on {self.PlexServer.platform} version {self.PlexServer.platformVersion}") pp_str = f"PlexPass: {self.PlexServer.myPlexSubscription}" srv_settings = self.PlexServer.settings + db_cache = srv_settings.get("DatabaseCachesize") + logger.info(f"Plex DB cache setting = {db_cache}") uc_str = f"Unknown update channel." if srv_settings.get("butlerUpdateChannel").value == '16': uc_str = f"Public update channel." From 85830d4f762c3f62b883478f30e894a79cd1984a Mon Sep 17 00:00:00 2001 From: bullmoose20 Date: Thu, 24 Aug 2023 00:17:20 -0400 Subject: [PATCH 2/5] Update plex.py with DatabaseCacheSize --- modules/plex.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/plex.py b/modules/plex.py index 46c8dac2..c5da35de 100644 --- a/modules/plex.py +++ b/modules/plex.py @@ -445,8 +445,8 @@ class Plex(Library): logger.info(f"Running on {self.PlexServer.platform} version {self.PlexServer.platformVersion}") pp_str = f"PlexPass: {self.PlexServer.myPlexSubscription}" srv_settings = self.PlexServer.settings - db_cache = srv_settings.get("DatabaseCachesize") - logger.info(f"Plex DB cache setting = {db_cache}") + db_cache = srv_settings.get("DatabaseCacheSize").value + logger.info(f"Plex DB cache setting: {db_cache} kilobytes") uc_str = f"Unknown update channel." if srv_settings.get("butlerUpdateChannel").value == '16': uc_str = f"Public update channel." From 5d57039856fd2e6e661393272679fc2cbc1d2f01 Mon Sep 17 00:00:00 2001 From: bullmoose20 Date: Thu, 24 Aug 2023 08:42:33 -0400 Subject: [PATCH 3/5] Update plex.py to include DatabaseCacheSize attribute in Plex Configuration for PMS > 1.29 --- modules/plex.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/modules/plex.py b/modules/plex.py index c5da35de..95f668a6 100644 --- a/modules/plex.py +++ b/modules/plex.py @@ -1,4 +1,5 @@ import os, plexapi, re, requests +import distutils.version from datetime import datetime, timedelta from modules import builder, util from modules.library import Library @@ -445,8 +446,12 @@ class Plex(Library): logger.info(f"Running on {self.PlexServer.platform} version {self.PlexServer.platformVersion}") pp_str = f"PlexPass: {self.PlexServer.myPlexSubscription}" srv_settings = self.PlexServer.settings - db_cache = srv_settings.get("DatabaseCacheSize").value - logger.info(f"Plex DB cache setting: {db_cache} kilobytes") + plex_version = self.PlexServer.version + parsed_version = distutils.version.LooseVersion(plex_version) + min_version = distutils.version.LooseVersion("1.29") + if parsed_version > min_version: + db_cache = srv_settings.get("DatabaseCacheSize").value + logger.info(f"Plex DB cache setting: {db_cache} kilobytes") uc_str = f"Unknown update channel." if srv_settings.get("butlerUpdateChannel").value == '16': uc_str = f"Public update channel." From 673d057ac88c3e7446a05873211bad2e6d5ec0f1 Mon Sep 17 00:00:00 2001 From: meisnate12 Date: Thu, 24 Aug 2023 10:40:41 -0400 Subject: [PATCH 4/5] [102] allow pmm to set db cache size --- VERSION | 2 +- config/config.yml.template | 1 + docs/config/plex.md | 20 ++++++++++------- docs/home/guides/kubernetes.md | 1 + .../guides/wt/wt-02-config-bad-library.md | 1 + modules/config.py | 2 ++ modules/plex.py | 22 ++++++++++--------- 7 files changed, 30 insertions(+), 19 deletions(-) diff --git a/VERSION b/VERSION index 6e1eae7e..f1e49f37 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.19.0-develop101 +1.19.0-develop102 diff --git a/config/config.yml.template b/config/config.yml.template index 6a2d0e38..342f2c68 100644 --- a/config/config.yml.template +++ b/config/config.yml.template @@ -80,6 +80,7 @@ plex: # Can be individually specified per library as url: http://192.168.1.12:32400 token: #################### timeout: 60 + db_cache: clean_bundles: false empty_trash: false optimize: false diff --git a/docs/config/plex.md b/docs/config/plex.md index 03d88a4b..ef6a3f44 100644 --- a/docs/config/plex.md +++ b/docs/config/plex.md @@ -10,19 +10,21 @@ plex: url: http://192.168.1.12:32400 token: #################### timeout: 60 + db_cache: 4096 clean_bundles: true empty_trash: true optimize: false ``` -| Attribute | Allowed Values | Default | Required | -|:----------------|:-------------------------------------------------------------------------------------------------------------------------------|:--------|:--------:| -| `url` | Plex Server URL
Example: http://192.168.1.12:32400 | N/A | ✅ | -| `token` | Plex Server Authentication Token | N/A | ✅ | -| `timeout` | Plex Server Timeout | 60 | ❌ | -| `clean_bundles` | Runs Clean Bundles on the Server after all Metadata Files are run | false | ❌ | -| `empty_trash` | Runs Empty Trash on the Server after all Metadata Files are run | false | ❌ | -| `optimize` | Runs Optimize on the Server after all Metadata Files are run | false | ❌ | +| Attribute | Allowed Values | Default | Required | +|:----------------|:-----------------------------------------------------------------------|:--------|:--------:| +| `url` | Plex Server URL
Example: http://192.168.1.12:32400 | N/A | ✅ | +| `token` | Plex Server Authentication Token | N/A | ✅ | +| `timeout` | Plex Server Timeout | 60 | ❌ | +| `db_cache` | Plex Server Database Cache Size | None | ❌ | +| `clean_bundles` | Runs Clean Bundles on the Server after all Metadata Files are run | false | ❌ | +| `empty_trash` | Runs Empty Trash on the Server after all Metadata Files are run | false | ❌ | +| `optimize` | Runs Optimize on the Server after all Metadata Files are run | false | ❌ | * **Do Not Use the Plex Token found in Plex's Preferences.xml file** @@ -47,11 +49,13 @@ libraries: url: http://plex.boing.bong token: SOME_TOKEN timeout: 360 + db_cache: 8192 ... plex: url: http://plex.bing.bang token: SOME_TOKEN timeout: 60 + db_cache: 4096 clean_bundles: false empty_trash: false optimize: false diff --git a/docs/home/guides/kubernetes.md b/docs/home/guides/kubernetes.md index 60f88040..7bc2d471 100644 --- a/docs/home/guides/kubernetes.md +++ b/docs/home/guides/kubernetes.md @@ -159,6 +159,7 @@ data: url: http://PLEX_IP_HERE:32400 token: YOUR_TOKEN_HERE timeout: 60 + db_cache: clean_bundles: false empty_trash: false optimize: false diff --git a/docs/home/guides/wt/wt-02-config-bad-library.md b/docs/home/guides/wt/wt-02-config-bad-library.md index 4a498076..392e2cce 100644 --- a/docs/home/guides/wt/wt-02-config-bad-library.md +++ b/docs/home/guides/wt/wt-02-config-bad-library.md @@ -8,6 +8,7 @@ plex: # Can be individually specified url: http://bing.bang.boing <<< ENTER YOUR PLEX URL HERE token: XXXXXXXXXXXXXXXXXXXX <<< ENTER YOUR PLEX TOKEN HERE timeout: 60 + db_cache: clean_bundles: false empty_trash: false optimize: false diff --git a/modules/config.py b/modules/config.py index 9ce652a7..1cdcad1a 100644 --- a/modules/config.py +++ b/modules/config.py @@ -662,6 +662,7 @@ class ConfigFile: "url": check_for_attribute(self.data, "url", parent="plex", var_type="url", default_is_none=True), "token": check_for_attribute(self.data, "token", parent="plex", default_is_none=True), "timeout": check_for_attribute(self.data, "timeout", parent="plex", var_type="int", default=60), + "db_cache": check_for_attribute(self.data, "db_cache", parent="plex", var_type="int", default_is_none=True), "clean_bundles": check_for_attribute(self.data, "clean_bundles", parent="plex", var_type="bool", default=False), "empty_trash": check_for_attribute(self.data, "empty_trash", parent="plex", var_type="bool", default=False), "optimize": check_for_attribute(self.data, "optimize", parent="plex", var_type="bool", default=False) @@ -944,6 +945,7 @@ class ConfigFile: "url": check_for_attribute(lib, "url", parent="plex", var_type="url", default=self.general["plex"]["url"], req_default=True, save=False), "token": check_for_attribute(lib, "token", parent="plex", default=self.general["plex"]["token"], req_default=True, save=False), "timeout": check_for_attribute(lib, "timeout", parent="plex", var_type="int", default=self.general["plex"]["timeout"], save=False), + "db_cache": check_for_attribute(lib, "db_cache", parent="plex", var_type="int", default=self.general["plex"]["db_cache"], default_is_none=True, save=False), "clean_bundles": check_for_attribute(lib, "clean_bundles", parent="plex", var_type="bool", default=self.general["plex"]["clean_bundles"], save=False), "empty_trash": check_for_attribute(lib, "empty_trash", parent="plex", var_type="bool", default=self.general["plex"]["empty_trash"], save=False), "optimize": check_for_attribute(lib, "optimize", parent="plex", var_type="bool", default=self.general["plex"]["optimize"], save=False) diff --git a/modules/plex.py b/modules/plex.py index 95f668a6..bfb53700 100644 --- a/modules/plex.py +++ b/modules/plex.py @@ -1,5 +1,4 @@ import os, plexapi, re, requests -import distutils.version from datetime import datetime, timedelta from modules import builder, util from modules.library import Library @@ -433,9 +432,9 @@ class Plex(Library): def __init__(self, config, params): super().__init__(config, params) self.plex = params["plex"] - self.url = params["plex"]["url"] - self.token = params["plex"]["token"] - self.timeout = params["plex"]["timeout"] + self.url = self.plex["url"] + self.token = self.plex["token"] + self.timeout = self.plex["timeout"] logger.secret(self.url) logger.secret(self.token) try: @@ -446,12 +445,15 @@ class Plex(Library): logger.info(f"Running on {self.PlexServer.platform} version {self.PlexServer.platformVersion}") pp_str = f"PlexPass: {self.PlexServer.myPlexSubscription}" srv_settings = self.PlexServer.settings - plex_version = self.PlexServer.version - parsed_version = distutils.version.LooseVersion(plex_version) - min_version = distutils.version.LooseVersion("1.29") - if parsed_version > min_version: - db_cache = srv_settings.get("DatabaseCacheSize").value - logger.info(f"Plex DB cache setting: {db_cache} kilobytes") + try: + db_cache = srv_settings.get("DatabaseCacheSize") + logger.info(f"Plex DB cache setting: {db_cache.value} MB") + if self.plex["db_cache"] and self.plex["db_cache"] != db_cache.value: + db_cache.set(self.plex["db_cache"]) + self.PlexServer.settings.save() + logger.info(f"Plex DB Cache updated to {self.plex['db_cache']} MB") + except NotFound: + logger.info(f"Plex DB cache setting: Unknown") uc_str = f"Unknown update channel." if srv_settings.get("butlerUpdateChannel").value == '16': uc_str = f"Public update channel." From afe1f6e32d6cdd5f0061902802aefc93eccb290a Mon Sep 17 00:00:00 2001 From: meisnate12 Date: Thu, 24 Aug 2023 11:11:22 -0400 Subject: [PATCH 5/5] [103] add hourly and weekly ranges --- VERSION | 2 +- docs/metadata/details/schedule.md | 22 ++++++------- modules/util.py | 53 +++++++++++++++++++++++-------- 3 files changed, 51 insertions(+), 26 deletions(-) diff --git a/VERSION b/VERSION index f1e49f37..dacf95c4 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.19.0-develop102 +1.19.0-develop103 diff --git a/docs/metadata/details/schedule.md b/docs/metadata/details/schedule.md index 01c6bb47..8eee359c 100644 --- a/docs/metadata/details/schedule.md +++ b/docs/metadata/details/schedule.md @@ -10,17 +10,17 @@ These schedules do not trigger PMM to run; they control what PMM will do if it h The scheduling options are: -| Name | Description | Format | Example | -|:-------------|:-------------------------------------------------------------------------------------------------|:----------------------|:----------------------------------| -| Hourly | Update only when the script is run in that hour | hourly(Hour of Day) | `hourly(17)` | -| Daily | Update once a day | daily | `daily` | -| Weekly | Update once a week on the specified day | weekly(Day of Week) | `weekly(sunday)` | -| Monthly | Update once a month on the specified day | monthly(Day of Month) | `monthly(1)` | -| Yearly | Update once a year on the specified day | yearly(MM/DD) | `yearly(01/30)` | -| Range | Updates whenever the date is within the range | range(MM/DD-MM/DD) | `range(12/01-12/31)` | -| Never | Never updates | never | `never` | -| Non Existing | Updates if it doesn't exist | non_existing | `non_existing` | -| All | Requires that all comma separated scheduling options inside its brackets be meet in order to run | all[Options] | `all[weekly(sunday), hourly(17)]` | +| Name | Description | Format | Example | +|:-------------|:-----------------------------------------------------------------------------------------------------------|:---------------------------------------------------|:-------------------------------------------------------------| +| Hourly | Update only when the script is run in that hour or hour range | hourly(Hour of Day)
hourly(Start Hour-End Hour) | `hourly(17)`
`hourly(17-04)` | +| Daily | Update once a day | daily | `daily` | +| Weekly | Update once a week on the specified days (For multiple days use a bar-separated (|) list | weekly(Days of Week) | `weekly(sunday)`
weekly(sunday|tuesday) | +| Monthly | Update once a month on the specified day | monthly(Day of Month) | `monthly(1)` | +| Yearly | Update once a year on the specified day | yearly(MM/DD) | `yearly(01/30)` | +| Range | Updates whenever the date is within the range | range(MM/DD-MM/DD) | `range(12/01-12/31)` | +| Never | Never updates | never | `never` | +| Non Existing | Updates if it doesn't exist | non_existing | `non_existing` | +| All | Requires that all comma separated scheduling options inside its brackets be meet in order to run | all[Options] | `all[weekly(sunday), hourly(17)]` | * `daily` is the default when `schedule` is not specified. * You can run the script multiple times per day but using the `--time` command line argument detailed on the [Run Commands & Environmental Variables Page](../../home/environmental.md#time-to-run). diff --git a/modules/util.py b/modules/util.py index 0464e219..80754039 100644 --- a/modules/util.py +++ b/modules/util.py @@ -603,22 +603,47 @@ def schedule_check(attribute, data, current_time, run_hour, is_all=False): continue param = match.group(1) if run_time.startswith("hour"): - try: - if 0 <= int(param) <= 23: - schedule_str += f"\nScheduled to run on the {num2words(param, to='ordinal_num')} hour" - if run_hour == int(param): - all_check += 1 - else: - raise ValueError - except ValueError: - logger.error(f"Schedule Error: hourly {display} must be an integer between 0 and 23") + if "-" in run_time: + start, end = run_time.split("-") + try: + start = int(start) + end = int(end) + if start != end and 0 <= start <= 23 and 0 <= end <= 23: + schedule_str += f"\nScheduled to run between the {num2words(start, to='ordinal_num')} hour and the {num2words(end, to='ordinal_num')} hour" + if end > start and start <= run_hour <= end: + all_check += 1 + elif start > end and (start <= run_hour or run_hour <= end): + all_check += 1 + else: + raise ValueError + except ValueError: + logger.error(f"Schedule Error: hourly {start}-{end} each must be a different integer between 0 and 23") + else: + try: + if 0 <= int(param) <= 23: + schedule_str += f"\nScheduled to run on the {num2words(param, to='ordinal_num')} hour" + if run_hour == int(param): + all_check += 1 + else: + raise ValueError + except ValueError: + logger.error(f"Schedule Error: hourly {display} must be an integer between 0 and 23") elif run_time.startswith("week"): - if param.lower() not in days_alias: - logger.error(f"Schedule Error: weekly {display} must be a day of the week i.e. weekly(Monday)") + ok_days = param.lower().split("|") + err = None + for ok_day in ok_days: + if ok_day not in days_alias: + err = f"Schedule Error: weekly {display} must be a day of the week i.e. weekly(Monday)" + if err: + logger.error(err) continue - weekday = days_alias[param.lower()] - schedule_str += f"\nScheduled weekly on {pretty_days[weekday]}" - if weekday == current_time.weekday(): + pass_day = False + for ok_day in ok_days: + weekday = days_alias[ok_day] + schedule_str += f"\nScheduled weekly on {pretty_days[weekday]}" + if weekday == current_time.weekday(): + pass_day = True + if pass_day: all_check += 1 elif run_time.startswith("month"): try: