diff --git a/VERSION b/VERSION index f9e4c315..6e1eae7e 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.19.0-develop97 +1.19.0-develop101 diff --git a/defaults/overlays/languages.yml b/defaults/overlays/languages.yml index 9296ac21..520f810b 100644 --- a/defaults/overlays/languages.yml +++ b/defaults/overlays/languages.yml @@ -558,7 +558,7 @@ overlays: template: [name: flags, name: standard] mayan: - variables: {key: myn, text: MA, weight: 8, country: mx} + variables: {key: myn, text: MYN, weight: 8, country: mx, width: 230} template: [name: flags, name: standard] inuktitut: @@ -579,6 +579,12 @@ overlays: zulu: variables: {key: zu, text: ZU, weight: 3, country: za} - template: [name: flags, name: standard] + template: [name: flags, name: standard] - + luxembourgish: + variables: {key: lb, text: LB, weight: 2, country: lu} + template: [name: flags, name: standard] + + mossi: + variables: {key: mos, text: MOS, weight: 1, country: bf, width: 230} + template: [name: flags, name: standard] diff --git a/defaults/overlays/templates.yml b/defaults/overlays/templates.yml index 89d49eb8..87f9588c 100644 --- a/defaults/overlays/templates.yml +++ b/defaults/overlays/templates.yml @@ -64,9 +64,16 @@ templates: - back_line_width - addon_offset - addon_position + conditionals: + final_use: + conditions: + - use_<>.exists: true + value: <>>> + - use_all: false + value: false builder_level: <> run_definition: - - <>>> + - <> - <>>> - <> suppress_overlays: <> diff --git a/docs/config/paths.md b/docs/config/paths.md index a2526e78..f8350501 100644 --- a/docs/config/paths.md +++ b/docs/config/paths.md @@ -138,8 +138,8 @@ Within the above example, PMM will: * First, look within the root of the PMM directory (also known as `config/`) for a metadata file named `TVShows.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 files within that directory. -* Then, look at the [PMM folder](https://github.com/meisnate12/Plex-Meta-Manager/tree/master/defaults) within the GitHub PMM Repo for a file called `tmdb.yml` which it finds [here](https://github.com/meisnate12/Plex-Meta-Manager/blob/master/defaults/chart/tmdb.yml). -* Then, look at the within the Custom Defined Repo for a file called `charts.yml`. +* Then, look in the [defaults folder](https://github.com/meisnate12/Plex-Meta-Manager/tree/master/defaults) within the local PMM folder [or docker container] for a file called `tmdb.yml` which it finds [here](https://github.com/meisnate12/Plex-Meta-Manager/blob/master/defaults/chart/tmdb.yml). +* Then, look within the Custom Defined Repo for a file called `charts.yml`. * Finally, load the metadata file located at `https://somewhere.com/PopularTV.yml` @@ -168,8 +168,8 @@ Within the above example, PMM will: * First, look within the root of the PMM directory (also known as `config/`) for a metadata file named `overlays.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 `overlay configs`, and then load any metadata files within that directory. -* Then, look at the [PMM folder](https://github.com/meisnate12/Plex-Meta-Manager/tree/master/defaults/overlays) within the GitHub PMM Repo for a file called `imdb.yml`. -* Then, look at the within the Custom Defined Repo for a file called `overlays.yml`. +* Then, look in the [defaults folder](https://github.com/meisnate12/Plex-Meta-Manager/tree/master/defaults) within the local PMM folder [or docker container] for a file called `imdb.yml`. +* Then, look within the Custom Defined Repo for a file called `overlays.yml`. * Finally, load the metadata file located at `https://somewhere.com/Overlays.yml` @@ -196,8 +196,8 @@ Within the above example, PMM will: * First, look within the root of the PMM directory (also known as `config/`) for a playlist file named `Playlists.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 `Playlists`, and then load any playlist files within that directory. -* Then, look at the [PMM folder](https://github.com/meisnate12/Plex-Meta-Manager/tree/master/defaults) within the GitHub PMM Repo for a file called `playlist.yml` which it finds [here](https://github.com/meisnate12/Plex-Meta-Manager/blob/master/defaults/playlist.yml). -* Then, look at the within the Custom Defined Repo for a file called `playlists.yml`. +* Then, look in the [defaults folder](https://github.com/meisnate12/Plex-Meta-Manager/tree/master/defaults) within the local PMM folder [or docker container] for a file called `playlist.yml` which it finds [here](https://github.com/meisnate12/Plex-Meta-Manager/blob/master/defaults/playlist.yml). +* Then, look within the Custom Defined Repo for a file called `playlists.yml`. * Finally, load the playlist file located at `https://somewhere.com/Playlists.yml` @@ -225,7 +225,7 @@ Within the above example, PMM will: * First, look within the root of the PMM directory (also known as `config/`) for a metadata file named `templates.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 `templates`, and then load any metadata files within that directory. * Then, load the metadata file located at `https://somewhere.com/templates.yml`. -* Then, look at the [PMM folder](https://github.com/meisnate12/Plex-Meta-Manager/tree/master/defaults) within the GitHub PMM Repo for a file called `templates.yml` which it finds [here](https://github.com/meisnate12/Plex-Meta-Manager/blob/master/defaults/templates.yml). +* Then, look in the [defaults folder](https://github.com/meisnate12/Plex-Meta-Manager/tree/master/defaults) within the local PMM folder [or docker container] for a file called `templates.yml` which it finds [here](https://github.com/meisnate12/Plex-Meta-Manager/blob/master/defaults/templates.yml). * Finally, look at the within the Custom Defined Repo for a file called `templates.yml`. diff --git a/docs/defaults/overlays/languages.md b/docs/defaults/overlays/languages.md index c2928476..91bc32b4 100644 --- a/docs/defaults/overlays/languages.md +++ b/docs/defaults/overlays/languages.md @@ -82,6 +82,8 @@ Supported library types: Movie & Show | Amharic | `am` | `5` | `et` | ❌ | | Sundanese | `su` | `4` | `id` | ❌ | | Zulu | `zu` | `3` | `za` | ❌ | +| Luxembourgish | `lb` | `2` | `lu` | ❌ | +| Mossi | `mos` | `1` | `bf` | ❌ | ### Square Style diff --git a/docs/defaults/overlays/ribbon.md b/docs/defaults/overlays/ribbon.md index ffde6b6d..e455127e 100644 --- a/docs/defaults/overlays/ribbon.md +++ b/docs/defaults/overlays/ribbon.md @@ -30,6 +30,7 @@ Supported Overlay Level: Movie, Show | Metacritic Must See | `metacritic` | `30` | | Commonsense Selection | `common` | `20` | | Razzies Winner | `razzie` | `10` | + ## Config The below YAML in your config.yml will create the overlays: @@ -61,6 +62,7 @@ All [Shared Overlay Variables](../overlay_variables) are available with the defa | Variable | Description & Values | |:-----------------------------|:------------------------------------------------------------------------------------------------------------------------| +| `use_all` | **Description:** Used to turn on/off all keys.
**Default:** `true`
**Values:** `true` or `false` | | `weight_<>`1 | **Description:** Controls the weight of the Overlay. Higher numbers have priority.
**Values:** Any Number | | `style` | **Description:** Controls the color of the ribbon.
**Default:** `yellow`
**Values:** `yellow, gray, black, red` | diff --git a/docs/home/environmental.md b/docs/home/environmental.md index 2a4a4750..46e2e409 100644 --- a/docs/home/environmental.md +++ b/docs/home/environmental.md @@ -11,20 +11,20 @@ Environment Variables can also be placed inside a `.env` file inside your config | Attribute | Shell Command | Environment Variable | |:------------------------------------------------------|:----------------------------------------------|:-------------------------| | [Config](#config) | `-c` or `--config` | `PMM_CONFIG` | -| [Time to Run](#time-to-run) | `-t` or `--time` | `PMM_TIME` | +| [Time to Run](#time-to-run) | `-t` or `--times` | `PMM_TIMES` | | [Run Immediately](#run-immediately) | `-r` or `--run` | `PMM_RUN` | -| [Run Tests](#run-tests) | `-rt`, `--tests`, or `--run-tests` | `PMM_TEST` | +| [Run Tests](#run-tests) | `-rt`, `--tests`, or `--run-tests` | `PMM_TESTS` | | [Debug](#debug) | `-db` or `--debug` | `PMM_DEBUG` | | [Trace](#trace) | `-tr` or `--trace` | `PMM_TRACE` | | [Log Requests](#log-requests) | `-lr` or `--log-requests` | `PMM_LOG_REQUESTS` | | [Timeout](#timeout) | `-ti` or `--timeout` | `PMM_TIMEOUT` | | [Collections Only](#collections-only) | `-co` or `--collections-only` | `PMM_COLLECTIONS_ONLY` | | [Playlists Only](#playlists-only) | `-po` or `--playlists-only` | `PMM_PLAYLISTS_ONLY` | -| [Operations Only](#operations-only) | `-op`, `--operations`, or `--operations-only` | `PMM_OPERATIONS` | -| [Overlays Only](#overlays-only) | `-ov`, `--overlays`, or `--overlays-only` | `PMM_OVERLAYS` | -| [Run Collections](#run-collections) | `-rc` or `--run-collections` | `PMM_COLLECTIONS` | -| [Run Libraries](#run-libraries) | `-rl` or `--run-libraries` | `PMM_LIBRARIES` | -| [Run Metadata Files](#run-metadata-files) | `-rm` or `--run-metadata-files` | `PMM_METADATA_FILES` | +| [Operations Only](#operations-only) | `-op`, `--operations`, or `--operations-only` | `PMM_OPERATIONS_ONLY` | +| [Overlays Only](#overlays-only) | `-ov`, `--overlays`, or `--overlays-only` | `PMM_OVERLAYS_ONLY` | +| [Run Collections](#run-collections) | `-rc` or `--run-collections` | `PMM_RUN_COLLECTIONS` | +| [Run Libraries](#run-libraries) | `-rl` or `--run-libraries` | `PMM_RUN_LIBRARIES` | +| [Run Metadata Files](#run-metadata-files) | `-rm` or `--run-metadata-files` | `PMM_RUN_METADATA_FILES` | | [Libraries First](#libraries-first) | `-lf` or `--libraries-first` | `PMM_LIBRARIES_FIRST` | | [Ignore Schedules](#ignore-schedules) | `-is` or `--ignore-schedules` | `PMM_IGNORE_SCHEDULES` | | [Ignore Ghost](#ignore-ghost) | `-ig` or `--ignore-ghost` | `PMM_IGNORE_GHOST` | @@ -99,13 +99,13 @@ Specify the time of day that Plex Meta Manager will run. Flags - -t or --time - PMM_TIME + -t or --times + PMM_TIMES Example - --time 06:00,18:00 - PMM_TIME=06:00,18:00 + --times 06:00,18:00 + PMM_TIMES=06:00,18:00 Default Value @@ -119,12 +119,12 @@ Specify the time of day that Plex Meta Manager will run. ````{tab} Local Environment ``` -python plex_meta_manager.py --time 22:00,03:00 +python plex_meta_manager.py --times 22:00,03:00 ``` ```` ````{tab} Docker Environment ``` -docker run -it -v "X:\Media\Plex Meta Manager\config:/config:rw" meisnate12/plex-meta-manager --time 22:00,03:00 +docker run -it -v "X:\Media\Plex Meta Manager\config:/config:rw" meisnate12/plex-meta-manager --times 22:00,03:00 ``` ```` @@ -175,12 +175,12 @@ Perform a debug test run immediately, bypassing the time to run flag. This will Flags -rt, --tests, or --run-tests - PMM_TEST + PMM_TESTS Example --run-tests - PMM_TEST=true + PMM_TESTS=true @@ -412,24 +412,24 @@ Only run library operations skipping collections/metadata, playlists, and overla Flags - -op or --operations - PMM_OPERATIONS + -op, --operations, or --operations-only + PMM_OPERATIONS_ONLY Example - --operations - PMM_OPERATIONS=true + --operations-only + PMM_OPERATIONS_ONLY=true ````{tab} Local Environment ``` -python plex_meta_manager.py --operations +python plex_meta_manager.py --operations-only ``` ```` ````{tab} Docker Environment ``` -docker run -it -v "X:\Media\Plex Meta Manager\config:/config:rw" meisnate12/plex-meta-manager --operations +docker run -it -v "X:\Media\Plex Meta Manager\config:/config:rw" meisnate12/plex-meta-manager --operations-only ``` ```` @@ -445,24 +445,24 @@ Only run library overlays skipping collections/metadata, playlists, and operatio Flags - -ov or --overlays - PMM_OVERLAYS + -ov, --overlays, or --overlays-only + PMM_OVERLAYS_ONLY Example - --overlays - PMM_OVERLAYS=true + --overlays-only + PMM_OVERLAYS_ONLY=true ````{tab} Local Environment ``` -python plex_meta_manager.py --overlays +python plex_meta_manager.py --overlays-only ``` ```` ````{tab} Docker Environment ``` -docker run -it -v "X:\Media\Plex Meta Manager\config:/config:rw" meisnate12/plex-meta-manager --overlays +docker run -it -v "X:\Media\Plex Meta Manager\config:/config:rw" meisnate12/plex-meta-manager --overlays-only ``` ```` @@ -479,12 +479,12 @@ Perform a collections run immediately to run only the pre-defined collections, b Flags -rc or --run-collections - PMM_COLLECTIONS + PMM_RUN_COLLECTIONS Example --run-collections "Harry Potter|Star Wars" - PMM_COLLECTIONS=Harry Potter|Star Wars + PMM_RUN_COLLECTIONS=Harry Potter|Star Wars Values @@ -516,12 +516,12 @@ Perform a libraries run immediately to run only the pre-defined libraries, bypas Flags -rl or --run-libraries - PMM_LIBRARIES + PMM_RUN_LIBRARIES Example --run-libraries "Movies - 4K|TV Shows - 4K" - PMM_LIBRARIES=Movies - 4K|TV Shows - 4K + PMM_RUN_LIBRARIES=Movies - 4K|TV Shows - 4K Values @@ -553,12 +553,12 @@ Perform a metadata files run immediately to run only the pre-defined metadata fi Flags -rm or --run-metadata-files - PMM_METADATA_FILES + PMM_RUN_METADATA_FILES Example --run-metadata-files "Movies.yml|MovieCharts" - PMM_METADATA_FILES=Movies.yml|MovieCharts + PMM_RUN_METADATA_FILES=Movies.yml|MovieCharts Available Values diff --git a/docs/metadata/filters.md b/docs/metadata/filters.md index 0f572aa6..b3122b68 100644 --- a/docs/metadata/filters.md +++ b/docs/metadata/filters.md @@ -77,6 +77,7 @@ String filters can take multiple values **only as a list**. | `folder` | Uses the item's folder to match | ❌ | ✅ | ❌ | ❌ | ✅ | ❌ | ❌ | | `filepath` | Uses the item's filepath to match | ✅ | ✅**[1](#table-annotations)** | ✅**[1](#table-annotations)** | ✅ | ✅**[1](#table-annotations)** | ✅**[1](#table-annotations)** | ✅ | | `audio_track_title` | Uses the audio track titles to match | ✅ | ✅**[1](#table-annotations)** | ✅**[1](#table-annotations)** | ✅ | ✅**[1](#table-annotations)** | ✅**[1](#table-annotations)** | ✅ | +| `subtitle_track_title` | Uses the subtitle track titles to match | ✅ | ✅**[1](#table-annotations)** | ✅**[1](#table-annotations)** | ✅ | ✅**[1](#table-annotations)** | ✅**[1](#table-annotations)** | ✅ | | `video_codec` | Uses the video codec tags to match | ✅ | ✅**[1](#table-annotations)** | ✅**[1](#table-annotations)** | ✅ | ❌ | ❌ | ❌ | | `video_profile` | Uses the video profile tags to match | ✅ | ✅**[1](#table-annotations)** | ✅**[1](#table-annotations)** | ✅ | ❌ | ❌ | ❌ | | `audio_codec` | Uses the audio codec tags to match | ✅ | ✅**[1](#table-annotations)** | ✅**[1](#table-annotations)** | ✅ | ❌ | ❌ | ❌ | diff --git a/modules/builder.py b/modules/builder.py index a880b409..e62b41ac 100644 --- a/modules/builder.py +++ b/modules/builder.py @@ -67,11 +67,11 @@ sonarr_details = [ ] album_details = ["non_item_remove_label", "item_label", "item_album_sorting"] sub_filters = [ - "filepath", "audio_track_title", "resolution", "audio_language", "subtitle_language", "has_dolby_vision", + "filepath", "audio_track_title", "subtitle_track_title", "resolution", "audio_language", "subtitle_language", "has_dolby_vision", "channels", "height", "width", "aspect", "audio_codec", "audio_profile", "video_codec", "video_profile", "versions" ] filters_by_type = { - "movie_show_season_episode_artist_album_track": ["title", "summary", "collection", "has_collection", "added", "last_played", "user_rating", "plays", "filepath", "label", "audio_track_title", "versions"], + "movie_show_season_episode_artist_album_track": ["title", "summary", "collection", "has_collection", "added", "last_played", "user_rating", "plays", "filepath", "label", "audio_track_title", "subtitle_track_title", "versions"], "movie_show_season_episode_album_track": ["year"], "movie_show_season_episode_artist_album": ["has_overlay"], "movie_show_season_episode": ["resolution", "audio_language", "subtitle_language", "has_dolby_vision", "channels", "height", "width", "aspect", "audio_codec", "audio_profile", "video_codec", "video_profile"], @@ -105,7 +105,7 @@ tmdb_filters = [ ] imdb_filters = ["imdb_keyword"] string_filters = [ - "title", "summary", "studio", "edition", "record_label", "folder", "filepath", "audio_track_title", "tmdb_title", + "title", "summary", "studio", "edition", "record_label", "folder", "filepath", "audio_track_title", "subtitle_track_title", "tmdb_title", "audio_codec", "audio_profile", "video_codec", "video_profile" ] string_modifiers = ["", ".not", ".is", ".isnot", ".begins", ".ends", ".regex"] diff --git a/modules/config.py b/modules/config.py index 5573a800..9ce652a7 100644 --- a/modules/config.py +++ b/modules/config.py @@ -124,9 +124,9 @@ class ConfigFile: self._mediastingers = None self.default_dir = default_dir self.secrets = secrets - self.read_only = attrs["read_only"] if "read_only" in attrs else False self.version = attrs["version"] if "version" in attrs else None self.branch = attrs["branch"] if "branch" in attrs else None + self.read_only = attrs["read_only"] if "read_only" in attrs else False self.no_missing = attrs["no_missing"] if "no_missing" in attrs else None self.no_report = attrs["no_report"] if "no_report" in attrs else None self.ignore_schedules = attrs["ignore_schedules"] if "ignore_schedules" in attrs else False diff --git a/modules/letterboxd.py b/modules/letterboxd.py index 89593dec..280f9236 100644 --- a/modules/letterboxd.py +++ b/modules/letterboxd.py @@ -19,7 +19,7 @@ class Letterboxd: letterboxd_ids = response.xpath("//li[contains(@class, 'poster-container') or contains(@class, 'film-detail')]/div/@data-film-id") items = [] for letterboxd_id in letterboxd_ids: - slugs = response.xpath(f"//div[@data-film-id='{letterboxd_id}']/@data-film-slug") + slugs = response.xpath(f"//div[@data-film-id='{letterboxd_id}']/@data-target-link") comments = response.xpath(f"//div[@data-film-id='{letterboxd_id}']/parent::li/div[@class='film-detail-content']/div/p/text()") ratings = response.xpath(f"//div[@data-film-id='{letterboxd_id}']/parent::li/div[@class='film-detail-content']//span[contains(@class, 'rating')]/@class") years = response.xpath(f"//div[@data-film-id='{letterboxd_id}']/parent::li/div[@class='film-detail-content']/h2/small/a/text()") diff --git a/modules/meta.py b/modules/meta.py index 7dd0eab0..d752890e 100644 --- a/modules/meta.py +++ b/modules/meta.py @@ -386,9 +386,9 @@ class DataFile: if var_key.endswith(".exists"): con_var_value = util.parse(self.data_type, var_key, var_value, datatype="bool", default=False) if con_var_value: - if var_key[:-7] not in variables or not variables[var_key[:-7]]: + if var_key[:-7] not in variables or variables[var_key[:-7]] is None: error_text = "- does not exist" - elif var_key[:-7] in variables and variables[var_key[:-7]]: + elif var_key[:-7] in variables and variables[var_key[:-7]] is not None: error_text = "- exists" con_var_value = var_key[:-7] elif var_key.endswith(".not"): @@ -1073,7 +1073,11 @@ class MetadataFile(DataFile): else: test_override.append(v) 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 + sync = False + if "sync" in self.temp_vars: + sync = util.parse("Config", "sync", self.temp_vars["sync"], parent="template_variables", datatype="bool") + elif "sync" in methods: + sync = util.parse("Config", "sync", dynamic, parent=map_name, methods=methods, default=False, datatype="bool") if "<>" in title_format: title_format = title_format.replace("<>", library.type.lower()) if "<>" in title_format: diff --git a/modules/plex.py b/modules/plex.py index 5af6161f..0aa48069 100644 --- a/modules/plex.py +++ b/modules/plex.py @@ -1594,6 +1594,10 @@ class Plex(Library): for media in item.media: for part in media.parts: values.extend([a.extendedDisplayTitle for a in part.audioStreams() if a.extendedDisplayTitle]) + elif filter_attr == "subtitle_track_title": + for media in item.media: + for part in media.parts: + values.extend([a.extendedDisplayTitle for a in part.subtitleStreams() if a.extendedDisplayTitle]) elif filter_attr in ["audio_codec", "audio_profile", "video_codec", "video_profile"]: for media in item.media: attr = getattr(media, filter_actual) diff --git a/plex_meta_manager.py b/plex_meta_manager.py index 43745a5d..714b9114 100644 --- a/plex_meta_manager.py +++ b/plex_meta_manager.py @@ -19,51 +19,65 @@ except (ModuleNotFoundError, ImportError): print("Requirements Error: Requirements are not installed") sys.exit(0) +default_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "config") +load_dotenv(os.path.join(default_dir, ".env")) + +arguments = { + "config": {"args": "c", "type": "str", "help": "Run with desired *.yml file"}, + "times": {"args": ["t", "time"], "type": "str", "default": "05:00", "help": "Times to update each day use format HH:MM (Default: 05:00) (comma-separated list)"}, + "run": {"args": "r", "type": "bool", "help": "Run without the scheduler"}, + "tests": {"args": ["rt", "test", "run-test", "run-tests"], "type": "bool", "help": "Run in debug mode with only collections that have test: true"}, + "debug": {"args": "db", "type": "bool", "help": "Run with Debug Logs Reporting to the Command Window"}, + "trace": {"args": "tr", "type": "bool", "help": "Run with extra Trace Debug Logs"}, + "log-requests": {"args": ["lr", "log-request"], "type": "bool", "help": "Run with all Requests printed"}, + "timeout": {"args": "ti", "type": "int", "default": 180, "help": "PMM Global Timeout (Default: 180)"}, + "collections-only": {"args": ["co", "collection-only"], "type": "bool", "help": "Run only collection operations"}, + "playlists-only": {"args": ["po", "playlist-only"], "type": "bool", "help": "Run only playlist operations"}, + "operations-only": {"args": ["op", "operation", "operations", "lo", "library-only", "libraries-only", "operation-only"], "type": "bool", "help": "Run only operations"}, + "overlays-only": {"args": ["ov", "overlay", "overlays", "overlay-only"], "type": "bool", "help": "Run only overlays"}, + "run-collections": {"args": ["rc", "cl", "collection", "collections", "run-collection"], "type": "str", "help": "Process only specified collections (pipe-separated list '|')"}, + "run-libraries": {"args": ["rl", "l", "library", "libraries", "run-library"], "type": "str", "help": "Process only specified libraries (pipe-separated list '|')"}, + "run-metadata-files": {"args": ["rm", "m", "metadata", "metadata-files"], "type": "str", "help": "Process only specified Metadata files (pipe-separated list '|')"}, + "libraries-first": {"args": ["lf", "library-first"], "type": "bool", "help": "Run library operations before collections"}, + "ignore-schedules": {"args": "is", "type": "bool", "help": "Run ignoring collection schedules"}, + "ignore-ghost": {"args": "ig", "type": "bool", "help": "Run ignoring ghost logging"}, + "cache-libraries": {"args": ["ca", "cache-library"], "type": "bool", "help": "Cache Library load for 1 day"}, + "delete-collections": {"args": ["dc", "delete", "delete-collection"], "type": "bool", "help": "Deletes all Collections in the Plex Library before running"}, + "delete-labels": {"args": ["dl", "delete-label"], "type": "bool", "help": "Deletes all Labels in the Plex Library before running"}, + "resume": {"args": "re", "type": "str", "help": "Resume collection run from a specific collection"}, + "no-countdown": {"args": "nc", "type": "bool", "help": "Run without displaying the countdown"}, + "no-missing": {"args": "nm", "type": "bool", "help": "Run without running the missing section"}, + "no-report": {"args": "nr", "type": "bool", "help": "Run without saving a report"}, + "read-only-config": {"args": "ro", "type": "bool", "help": "Run without writing to the config"}, + "divider": {"args": "d", "type": "str", "default": "=", "help": "Character that divides the sections (Default: '=')"}, + "width": {"args": "w", "type": "int", "default": 100, "help": "Screen Width (Default: 100)"}, +} + parser = argparse.ArgumentParser() -parser.add_argument("-db", "--debug", dest="debug", help="Run with Debug Logs Reporting to the Command Window", action="store_true", default=False) -parser.add_argument("-tr", "--trace", dest="trace", help="Run with extra Trace Debug Logs", action="store_true", default=False) -parser.add_argument("-lr", "--log-request", "--log-requests", dest="log_requests", help="Run with all Requests printed", action="store_true", default=False) -parser.add_argument("-c", "--config", dest="config", help="Run with desired *.yml file", type=str) -parser.add_argument("-t", "--time", "--times", dest="times", help="Times to update each day use format HH:MM (Default: 05:00) (comma-separated list)", default="05:00", type=str) -parser.add_argument("-ti", "--timeout", dest="timeout", help="PMM Global Timeout (Default: 180)", default=180, type=int) -parser.add_argument("-re", "--resume", dest="resume", help="Resume collection run from a specific collection", type=str) -parser.add_argument("-r", "--run", dest="run", help="Run without the scheduler", action="store_true", default=False) -parser.add_argument("-is", "--ignore-schedules", dest="ignore_schedules", help="Run ignoring collection schedules", action="store_true", default=False) -parser.add_argument("-ig", "--ignore-ghost", dest="ignore_ghost", help="Run ignoring ghost logging", action="store_true", default=False) -parser.add_argument("-rt", "--test", "--tests", "--run-test", "--run-tests", dest="test", help="Run in debug mode with only collections that have test: true", action="store_true", default=False) -parser.add_argument("-co", "--collection-only", "--collections-only", dest="collection_only", help="Run only collection operations", action="store_true", default=False) -parser.add_argument("-po", "--playlist-only", "--playlists-only", dest="playlist_only", help="Run only playlist operations", action="store_true", default=False) -parser.add_argument("-op", "--operation", "--operations", "-lo", "--library-only", "--libraries-only", "--operation-only", "--operations-only", dest="operations", help="Run only operations", action="store_true", default=False) -parser.add_argument("-ov", "--overlay", "--overlays", "--overlay-only", "--overlays-only", dest="overlays", help="Run only overlays", action="store_true", default=False) -parser.add_argument("-lf", "--library-first", "--libraries-first", dest="library_first", help="Run library operations before collections", action="store_true", default=False) -parser.add_argument("-rc", "-cl", "--collection", "--collections", "--run-collection", "--run-collections", dest="collections", help="Process only specified collections (pipe-separated list '|')", type=str) -parser.add_argument("-rl", "-l", "--library", "--libraries", "--run-library", "--run-libraries", dest="libraries", help="Process only specified libraries (pipe-separated list '|')", type=str) -parser.add_argument("-rm", "-m", "--metadata", "--metadata-files", "--run-metadata-files", dest="metadata", help="Process only specified Metadata files (pipe-separated list '|')", type=str) -parser.add_argument("-ca", "--cache-library", "--cache-libraries", dest="cache_libraries", help="Cache Library load for 1 day", action="store_true", default=False) -parser.add_argument("-dc", "--delete", "--delete-collections", dest="delete_collections", help="Deletes all Collections in the Plex Library before running", action="store_true", default=False) -parser.add_argument("-dl", "--delete-label", "--delete-labels", dest="delete_labels", help="Deletes all Labels in the Plex Library before running", action="store_true", default=False) -parser.add_argument("-nc", "--no-countdown", dest="no_countdown", help="Run without displaying the countdown", action="store_true", default=False) -parser.add_argument("-nm", "--no-missing", dest="no_missing", help="Run without running the missing section", action="store_true", default=False) -parser.add_argument("-nr", "--no-report", dest="no_report", help="Run without saving a report", action="store_true", default=False) -parser.add_argument("-ro", "--read-only-config", dest="read_only_config", help="Run without writing to the config", action="store_true", default=False) -parser.add_argument("-d", "--divider", dest="divider", help="Character that divides the sections (Default: '=')", default="=", type=str) -parser.add_argument("-w", "--width", dest="width", help="Screen Width (Default: 100)", default=100, type=int) +for arg_key, arg_data in arguments.items(): + temp_args = arg_data["args"] if isinstance(arg_data["args"], list) else [arg_data["args"]] + args = [f"--{arg_key}"] + [f"--{a}" if len(a) > 2 else f"-{a}" for a in temp_args] + kwargs = {"dest": arg_key.replace("-", "_"), "help": arg_data["help"]} + if arg_data["type"] == "bool": + kwargs["action"] = "store_true" + kwargs["default"] = False + else: + kwargs["type"] = int if arg_data["type"] == "int" else str + + if "default" in arg_data: + kwargs["default"] = arg_data["default"] + + parser.add_argument(*args, **kwargs) + args, unknown = parser.parse_known_args() -default_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "config") -load_dotenv(os.path.join(default_dir, ".env")) -static_envs = [] -test_value = None -def get_arg(env_str, default, arg_bool=False, arg_int=False): - global test_value +def get_env(env_str, default, arg_bool=False, arg_int=False): env_vars = [env_str] if not isinstance(env_str, list) else env_str final_value = None static_envs.extend(env_vars) for env_var in env_vars: env_value = os.environ.get(env_var) - if env_var == "BRANCH_NAME": - test_value = env_value if env_value is not None: final_value = env_value break @@ -84,45 +98,18 @@ def get_arg(env_str, default, arg_bool=False, arg_int=False): return str(final_value) else: return default -try: - from git import Repo, InvalidGitRepositoryError - try: - git_branch = Repo(path=".").head.ref.name # noqa - except InvalidGitRepositoryError: - git_branch = None -except ImportError: - git_branch = None -env_version = get_arg("BRANCH_NAME", "master") -is_docker = get_arg("PMM_DOCKER", False, arg_bool=True) -is_linuxserver = get_arg("PMM_LINUXSERVER", False, arg_bool=True) -config_file = get_arg("PMM_CONFIG", args.config) -times = get_arg("PMM_TIME", args.times) -run = get_arg("PMM_RUN", args.run, arg_bool=True) -test = get_arg("PMM_TEST", args.test, arg_bool=True) -ignore_schedules = get_arg("PMM_IGNORE_SCHEDULES", args.ignore_schedules, arg_bool=True) -ignore_ghost = get_arg("PMM_IGNORE_GHOST", args.ignore_ghost, arg_bool=True) -collection_only = get_arg("PMM_COLLECTIONS_ONLY", args.collection_only, arg_bool=True) -playlist_only = get_arg("PMM_PLAYLISTS_ONLY", args.playlist_only, arg_bool=True) -operations_only = get_arg(["PMM_OPERATIONS", "PMM_OPERATIONS_ONLY", "PMM_LIBRARIES_ONLY"], args.operations, arg_bool=True) -overlays_only = get_arg(["PMM_OVERLAYS", "PMM_OVERLAYS_ONLY"], args.overlays, arg_bool=True) -library_first = get_arg("PMM_LIBRARIES_FIRST", args.library_first, arg_bool=True) -collections = get_arg("PMM_COLLECTIONS", args.collections) -libraries = get_arg("PMM_LIBRARIES", args.libraries) -metadata_files = get_arg("PMM_METADATA_FILES", args.metadata) -cache_libraries = get_arg("PMM_CACHE_LIBRARIES", args.cache_libraries, arg_bool=True) -delete_collections = get_arg("PMM_DELETE_COLLECTIONS", args.delete_collections, arg_bool=True) -delete_labels = get_arg("PMM_DELETE_LABELS", args.delete_labels, arg_bool=True) -resume = get_arg("PMM_RESUME", args.resume) -no_countdown = get_arg("PMM_NO_COUNTDOWN", args.no_countdown, arg_bool=True) -no_missing = get_arg("PMM_NO_MISSING", args.no_missing, arg_bool=True) -no_report = get_arg("PMM_NO_REPORT", args.no_report, arg_bool=True) -read_only_config = get_arg("PMM_READ_ONLY_CONFIG", args.read_only_config, arg_bool=True) -divider = get_arg("PMM_DIVIDER", args.divider) -screen_width = get_arg("PMM_WIDTH", args.width, arg_int=True) -timeout = get_arg("PMM_TIMEOUT", args.timeout, arg_int=True) -debug = get_arg("PMM_DEBUG", args.debug, arg_bool=True) -trace = get_arg("PMM_TRACE", args.trace, arg_bool=True) -log_requests = get_arg("PMM_LOG_REQUESTS", args.log_requests, arg_bool=True) + + +static_envs = [] +run_args = {} +for arg_key, arg_data in arguments.items(): + temp_args = arg_data["args"] if isinstance(arg_data["args"], list) else [arg_data["args"]] + final_vars = [f"PMM_{arg_key.replace('-', '_').upper()}"] + [f"PMM_{a.replace('-', '_').upper()}" for a in temp_args if len(a) > 2] + run_args[arg_key] = get_env(final_vars, getattr(args, arg_key.replace("-", "_")), arg_bool=arg_data["type"] == "bool", arg_int=arg_data["type"] == "int") + +env_version = get_env("BRANCH_NAME", "master") +is_docker = get_env("PMM_DOCKER", False, arg_bool=True) +is_linuxserver = get_env("PMM_LINUXSERVER", False, arg_bool=True) secret_args = {} plex_url = None @@ -140,8 +127,8 @@ while i < len(unknown): i += 1 i += 1 -plex_url = get_arg("PMM_PLEX_URL", plex_url) -plex_token = get_arg("PMM_PLEX_TOKEN", plex_token) +plex_url = get_env("PMM_PLEX_URL", plex_url) +plex_token = get_env("PMM_PLEX_TOKEN", plex_token) env_secrets = [] for env_name, env_data in os.environ.items(): @@ -153,23 +140,33 @@ for _, v in secret_args.items(): if v in run_arg: run_arg = run_arg.replace(v, "(redacted)") -if collections: - collection_only = True +try: + from git import Repo, InvalidGitRepositoryError + try: + git_branch = Repo(path=".").head.ref.name # noqa + except InvalidGitRepositoryError: + git_branch = None +except ImportError: + git_branch = None + +if run_args["run-collections"]: + run_args["collections-only"] = True -if screen_width < 90 or screen_width > 300: - print(f"Argument Error: width argument invalid: {screen_width} must be an integer between 90 and 300 using the default 100") - screen_width = 100 +if run_args["width"] < 90 or run_args["width"] > 300: + print(f"Argument Error: width argument invalid: {run_args['width']} must be an integer between 90 and 300 using the default 100") + run_args["width"] = 100 -if config_file and os.path.exists(config_file): - default_dir = os.path.join(os.path.dirname(os.path.abspath(config_file))) -elif config_file and not os.path.exists(config_file): - print(f"Config Error: config not found at {os.path.abspath(config_file)}") +if run_args["config"] and os.path.exists(run_args["config"]): + default_dir = os.path.join(os.path.dirname(os.path.abspath(run_args["config"]))) +elif run_args["config"] and not os.path.exists(run_args["config"]): + print(f"Config Error: config not found at {os.path.abspath(run_args['config'])}") sys.exit(0) elif not os.path.exists(os.path.join(default_dir, "config.yml")): print(f"Config Error: config not found at {os.path.abspath(default_dir)}") sys.exit(0) -logger = MyLogger("Plex Meta Manager", default_dir, screen_width, divider[0], ignore_ghost, test or debug, trace, log_requests) +logger = MyLogger("Plex Meta Manager", default_dir, run_args["width"], run_args["divider"][0], run_args["ignore-ghost"], + run_args["tests"] or run_args["debug"], run_args["trace"], run_args["log-requests"]) from modules import util util.logger = logger @@ -189,7 +186,7 @@ old_send = requests.Session.send def new_send(*send_args, **kwargs): if kwargs.get("timeout", None) is None: - kwargs["timeout"] = timeout + kwargs["timeout"] = run_args["timeout"] return old_send(*send_args, **kwargs) requests.Session.send = new_send @@ -244,7 +241,7 @@ def start(attrs): logger.info(f" Platform: {platform.platform()}") logger.info(f" Memory: {round(psutil.virtual_memory().total / (1024.0 ** 3))} GB") if "time" in attrs and attrs["time"]: start_type = f"{attrs['time']} " - elif "test" in attrs and attrs["test"]: start_type = "Test " + elif run_args["tests"]: start_type = "Test " elif "collections" in attrs and attrs["collections"]: start_type = "Collections " elif "libraries" in attrs and attrs["libraries"]: start_type = "Libraries " else: start_type = "" @@ -252,45 +249,24 @@ def start(attrs): if "time" not in attrs: attrs["time"] = start_time.strftime("%H:%M") attrs["time_obj"] = start_time - attrs["read_only"] = read_only_config attrs["version"] = version attrs["branch"] = branch - attrs["no_missing"] = no_missing - attrs["no_report"] = no_report - attrs["collection_only"] = collection_only - attrs["playlist_only"] = playlist_only - attrs["operations_only"] = operations_only - attrs["overlays_only"] = overlays_only + attrs["config_file"] = run_args["config"] + attrs["ignore_schedules"] = run_args["ignore-schedules"] + attrs["read_only"] = run_args["read-only-config"] + attrs["no_missing"] = run_args["no-missing"] + attrs["no_report"] = run_args["no-report"] + attrs["collection_only"] = run_args["collections-only"] + attrs["playlist_only"] = run_args["playlists-only"] + attrs["operations_only"] = run_args["operations-only"] + attrs["overlays_only"] = run_args["overlays-only"] attrs["plex_url"] = plex_url attrs["plex_token"] = plex_token logger.separator(debug=True) logger.debug(f"Run Command: {run_arg}") - logger.debug(f"--config (PMM_CONFIG): {config_file}") - logger.debug(f"--time (PMM_TIME): {times}") - logger.debug(f"--run (PMM_RUN): {run}") - logger.debug(f"--run-tests (PMM_TEST): {test}") - logger.debug(f"--collections-only (PMM_COLLECTIONS_ONLY): {collection_only}") - logger.debug(f"--playlists-only (PMM_PLAYLISTS_ONLY): {playlist_only}") - logger.debug(f"--operations (PMM_OPERATIONS): {operations_only}") - logger.debug(f"--overlays (PMM_OVERLAYS): {overlays_only}") - logger.debug(f"--libraries-first (PMM_LIBRARIES_FIRST): {library_first}") - logger.debug(f"--run-collections (PMM_COLLECTIONS): {collections}") - logger.debug(f"--run-libraries (PMM_LIBRARIES): {libraries}") - logger.debug(f"--run-metadata-files (PMM_METADATA_FILES): {metadata_files}") - logger.debug(f"--ignore-schedules (PMM_IGNORE_SCHEDULES): {ignore_schedules}") - logger.debug(f"--ignore-ghost (PMM_IGNORE_GHOST): {ignore_ghost}") - logger.debug(f"--cache-libraries (PMM_CACHE_LIBRARIES): {cache_libraries}") - logger.debug(f"--delete-collections (PMM_DELETE_COLLECTIONS): {delete_collections}") - logger.debug(f"--delete-labels (PMM_DELETE_LABELS): {delete_labels}") - logger.debug(f"--resume (PMM_RESUME): {resume}") - logger.debug(f"--no-countdown (PMM_NO_COUNTDOWN): {no_countdown}") - logger.debug(f"--no-missing (PMM_NO_MISSING): {no_missing}") - logger.debug(f"--no-report (PMM_NO_REPORT): {no_report}") - logger.debug(f"--read-only-config (PMM_READ_ONLY_CONFIG): {read_only_config}") - logger.debug(f"--divider (PMM_DIVIDER): {divider}") - logger.debug(f"--width (PMM_WIDTH): {screen_width}") - logger.debug(f"--debug (PMM_DEBUG): {debug}") - logger.debug(f"--trace (PMM_TRACE): {trace}") + for akey, adata in arguments.items(): + ext = '"' if adata["type"] == "str" and run_args[akey] not in [None, "None"] else "" + logger.debug(f"--{akey} (PMM_{akey.upper()}): {ext}{run_args[akey]}{ext}") logger.debug("") if secret_args: logger.debug("PMM Secrets Read:") @@ -358,7 +334,7 @@ def run_config(config, stats): playlist_status = {} playlist_stats = {} - if (config.playlist_files or config.general["playlist_report"]) and not overlays_only and not operations_only and not collection_only and not config.requested_metadata_files: + if (config.playlist_files or config.general["playlist_report"]) and not run_args["overlays-only"] and not run_args["operations-only"] and not run_args["collections-only"] and not config.requested_metadata_files: logger.add_playlists_handler() if config.playlist_files: playlist_status, playlist_stats = run_playlists(config) @@ -383,7 +359,7 @@ def run_config(config, stats): logger.remove_playlists_handler() amount_added = 0 - if not operations_only and not overlays_only and not playlist_only: + if not run_args["operations-only"] and not run_args["overlays-only"] and not run_args["playlists-only"]: has_run_again = False for library in config.libraries: if library.run_again: @@ -424,7 +400,7 @@ def run_config(config, stats): logger.stacktrace() logger.critical(e) - if not collection_only and not overlays_only and not playlist_only: + if not run_args["collections-only"] and not run_args["overlays-only"] and not run_args["playlists-only"]: used_url = [] for library in config.libraries: if library.url not in used_url: @@ -540,7 +516,7 @@ def run_libraries(config): logger.debug(f"Optimize: {library.optimize}") logger.debug(f"Timeout: {library.timeout}") - if delete_collections and not playlist_only: + if run_args["delete-collections"] and not run_args["playlists-only"]: time_start = datetime.now() logger.info("") logger.separator(f"Deleting all Collections from the {library.name} Library", space=False, border=False) @@ -553,7 +529,7 @@ def run_libraries(config): logger.error(e) library_status[library.name]["All Collections Deleted"] = str(datetime.now() - time_start).split('.')[0] - if delete_labels and not playlist_only: + if run_args["delete-labels"] and not run_args["playlists-only"]: time_start = datetime.now() logger.info("") logger.separator(f"Deleting all Labels from All items in the {library.name} Library", space=False, border=False) @@ -579,7 +555,7 @@ def run_libraries(config): expired = None if config.Cache: list_key, expired = config.Cache.query_list_cache("library", library.mapping_name, 1) - if cache_libraries and list_key and expired is False: + if run_args["cache-libraries"] and list_key and expired is False: logger.info(f"Library: {library.mapping_name} loaded from Cache") temp_items = config.Cache.query_list_ids(list_key) @@ -587,7 +563,7 @@ def run_libraries(config): temp_items = library.cache_items() if config.Cache and list_key: config.Cache.delete_list_ids(list_key) - if config.Cache and cache_libraries: + if config.Cache and run_args["cache-libraries"]: list_key = config.Cache.update_list_cache("library", library.mapping_name, expired, 1) config.Cache.update_list_ids(list_key, [(i.ratingKey, i.guid) for i in temp_items]) if not library.is_music: @@ -598,16 +574,16 @@ def run_libraries(config): library_status[library.name]["Library Loading and Mapping"] = str(datetime.now() - time_start).split('.')[0] def run_operations_and_overlays(): - if not test and not collection_only and not playlist_only and not config.requested_metadata_files: - if not overlays_only and library.library_operation: + if not run_args["tests"] and not run_args["collections-only"] and not run_args["playlists-only"] and not config.requested_metadata_files: + if not run_args["overlays-only"] and library.library_operation: library_status[library.name]["Library Operations"] = library.Operations.run_operations() - if not operations_only and (library.overlay_files or library.remove_overlays): + if not run_args["operations-only"] and (library.overlay_files or library.remove_overlays): library_status[library.name]["Library Overlays"] = library.Overlays.run_overlays() - if library_first: + if run_args["libraries-first"]: run_operations_and_overlays() - if not operations_only and not overlays_only and not playlist_only: + if not run_args["operations-only"] and not run_args["overlays-only"] and not run_args["playlists-only"]: time_start = datetime.now() for images in library.images_files: images_name = images.get_file_name() @@ -617,7 +593,7 @@ def run_libraries(config): continue logger.info("") logger.separator(f"Running {images_name} Images File\n{images.path}") - if not test and not resume and not collection_only: + if not run_args["tests"] and not run_args["resume"] and not run_args["collections-only"]: try: images.update_metadata() except Failed as e: @@ -634,26 +610,26 @@ def run_libraries(config): continue logger.info("") logger.separator(f"Running {metadata_name} Metadata File\n{metadata.path}") - if not test and not resume and not collection_only: + if not run_args["tests"] and not run_args["resume"] and not run_args["collections-only"]: try: metadata.update_metadata() except Failed as e: library.notify(e) logger.error(e) collections_to_run = metadata.get_collections(config.requested_collections) - if resume and resume not in collections_to_run: + if run_args["resume"] and run_args["resume"] not in collections_to_run: logger.info("") - logger.warning(f"Collection: {resume} not in Metadata File: {metadata.path}") + logger.warning(f"Collection: {run_args['resume']} not in Metadata File: {metadata.path}") continue if collections_to_run: logger.info("") - logger.separator(f"{'Test ' if test else ''}Collections") + logger.separator(f"{'Test ' if run_args['tests'] else ''}Collections") logger.remove_library_handler(library.mapping_name) run_collection(config, library, metadata, collections_to_run) logger.re_add_library_handler(library.mapping_name) library_status[library.name]["Library Metadata Files"] = str(datetime.now() - time_start).split('.')[0] - if not library_first: + if not run_args["libraries-first"]: run_operations_and_overlays() logger.remove_library_handler(library.mapping_name) @@ -664,11 +640,10 @@ def run_libraries(config): return library_status def run_collection(config, library, metadata, requested_collections): - global resume logger.info("") for mapping_name, collection_attrs in requested_collections.items(): collection_start = datetime.now() - if test and ("test" not in collection_attrs or collection_attrs["test"] is not True): + if run_args["tests"] and ("test" not in collection_attrs or collection_attrs["test"] is not True): no_template_test = True if "template" in collection_attrs and collection_attrs["template"]: for data_template in util.get_list(collection_attrs["template"], split=False): @@ -683,10 +658,10 @@ def run_collection(config, library, metadata, requested_collections): if no_template_test: continue - if resume and resume != mapping_name: + if run_args["resume"] and run_args["resume"] != mapping_name: continue - elif resume == mapping_name: - resume = None + elif run_args["resume"] == mapping_name: + run_args["resume"] = None logger.info("") logger.separator(f"Resuming Collections") @@ -859,7 +834,7 @@ def run_playlists(config): for playlist_file in config.playlist_files: for mapping_name, playlist_attrs in playlist_file.playlists.items(): playlist_start = datetime.now() - if test and ("test" not in playlist_attrs or playlist_attrs["test"] is not True): + if run_args["tests"] and ("test" not in playlist_attrs or playlist_attrs["test"] is not True): no_template_test = True if "template" in playlist_attrs and playlist_attrs["template"]: for data_template in util.get_list(playlist_attrs["template"], split=False): @@ -1034,17 +1009,10 @@ def run_playlists(config): if __name__ == "__main__": try: - if run or test or collections or libraries or metadata_files or resume: - params = { - "config_file": config_file, - "ignore_schedules": ignore_schedules, - "collections": collections, - "libraries": libraries, - "metadata_files": metadata_files - } - process(params) + if run_args["run"] or run_args["tests"] or run_args["run-collections"] or run_args["run-libraries"] or run_args["run-metadata-files"] or run_args["resume"]: + process({"collections": run_args["run-collections"], "libraries": run_args["run-libraries"], "metadata_files": run_args["run-metadata-files"]}) else: - times_to_run = util.get_list(times) + times_to_run = util.get_list(run_args["times"]) valid_times = [] for time_to_run in times_to_run: try: @@ -1057,11 +1025,10 @@ if __name__ == "__main__": else: raise Failed(f"Argument Error: blank time argument") for time_to_run in valid_times: - params = {"config_file": config_file, "ignore_schedules": ignore_schedules, "time": time_to_run} - schedule.every().day.at(time_to_run).do(process, params) + schedule.every().day.at(time_to_run).do(process, {"time": time_to_run}) while True: schedule.run_pending() - if not no_countdown: + if not run_args["no-countdown"]: current_time = datetime.now().strftime("%H:%M") seconds = None og_time_str = ""