Merge remote-tracking branch 'meisnate12/nightly' into nightly

pull/1582/head
bullmoose20 1 year ago
commit ddf96f309a

@ -1 +1 @@
1.19.0-develop97
1.19.0-develop101

@ -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]

@ -64,9 +64,16 @@ templates:
- back_line_width
- addon_offset
- addon_position
conditionals:
final_use:
conditions:
- use_<<key>>.exists: true
value: <<use_<<key>>>>
- use_all: false
value: false
builder_level: <<builder_level>>
run_definition:
- <<use_<<key>>>>
- <<final_use>>
- <<use_<<alt>>>>
- <<allowed_libraries>>
suppress_overlays: <<suppress_overlays>>

@ -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`
</details>
@ -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`
</details>
@ -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`
</details>
@ -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`.
</details>

@ -82,6 +82,8 @@ Supported library types: Movie & Show
| Amharic | `am` | `5` | `et` | &#10060; |
| Sundanese | `su` | `4` | `id` | &#10060; |
| Zulu | `zu` | `3` | `za` | &#10060; |
| Luxembourgish | `lb` | `2` | `lu` | &#10060; |
| Mossi | `mos` | `1` | `bf` | &#10060; |
### Square Style

@ -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. <br>**Default:** `true` <br>**Values:** `true` or `false` |
| `weight_<<key>>`<sup>1</sup> | **Description:** Controls the weight of the Overlay. Higher numbers have priority.<br>**Values:** Any Number |
| `style` | **Description:** Controls the color of the ribbon. <br>**Default:** `yellow` <br>**Values:** `yellow, gray, black, red` |

@ -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.
</tr>
<tr>
<th>Flags</th>
<td><code>-t</code> or <code>--time</code></td>
<td><code>PMM_TIME</code></td>
<td><code>-t</code> or <code>--times</code></td>
<td><code>PMM_TIMES</code></td>
</tr>
<tr>
<th>Example</th>
<td><code>--time 06:00,18:00</code></td>
<td><code>PMM_TIME=06:00,18:00</code></td>
<td><code>--times 06:00,18:00</code></td>
<td><code>PMM_TIMES=06:00,18:00</code></td>
</tr>
<tr>
<th>Default Value</th>
@ -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
<tr>
<th>Flags</th>
<td><code>-rt</code>, <code>--tests</code>, or <code>--run-tests</code></td>
<td><code>PMM_TEST</code></td>
<td><code>PMM_TESTS</code></td>
</tr>
<tr>
<th>Example</th>
<td><code>--run-tests</code></td>
<td><code>PMM_TEST=true</code></td>
<td><code>PMM_TESTS=true</code></td>
</tr>
</table>
@ -412,24 +412,24 @@ Only run library operations skipping collections/metadata, playlists, and overla
</tr>
<tr>
<th>Flags</th>
<td><code>-op</code> or <code>--operations</code></td>
<td><code>PMM_OPERATIONS</code></td>
<td><code>-op</code>, <code>--operations</code>, or <code>--operations-only</code></td>
<td><code>PMM_OPERATIONS_ONLY</code></td>
</tr>
<tr>
<th>Example</th>
<td><code>--operations</code></td>
<td><code>PMM_OPERATIONS=true</code></td>
<td><code>--operations-only</code></td>
<td><code>PMM_OPERATIONS_ONLY=true</code></td>
</tr>
</table>
````{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
</tr>
<tr>
<th>Flags</th>
<td><code>-ov</code> or <code>--overlays</code></td>
<td><code>PMM_OVERLAYS</code></td>
<td><code>-ov</code>, <code>--overlays</code>, or <code>--overlays-only</code></td>
<td><code>PMM_OVERLAYS_ONLY</code></td>
</tr>
<tr>
<th>Example</th>
<td><code>--overlays</code></td>
<td><code>PMM_OVERLAYS=true</code></td>
<td><code>--overlays-only</code></td>
<td><code>PMM_OVERLAYS_ONLY=true</code></td>
</tr>
</table>
````{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
<tr>
<th>Flags</th>
<td><code>-rc</code> or <code>--run-collections</code></td>
<td><code>PMM_COLLECTIONS</code></td>
<td><code>PMM_RUN_COLLECTIONS</code></td>
</tr>
<tr>
<th>Example</th>
<td><code>--run-collections "Harry Potter|Star Wars"</code></td>
<td><code>PMM_COLLECTIONS=Harry Potter|Star Wars</code></td>
<td><code>PMM_RUN_COLLECTIONS=Harry Potter|Star Wars</code></td>
</tr>
<tr>
<th>Values</th>
@ -516,12 +516,12 @@ Perform a libraries run immediately to run only the pre-defined libraries, bypas
<tr>
<th>Flags</th>
<td><code>-rl</code> or <code>--run-libraries</code></td>
<td><code>PMM_LIBRARIES</code></td>
<td><code>PMM_RUN_LIBRARIES</code></td>
</tr>
<tr>
<th>Example</th>
<td><code>--run-libraries "Movies - 4K|TV Shows - 4K"</code></td>
<td><code>PMM_LIBRARIES=Movies - 4K|TV Shows - 4K</code></td>
<td><code>PMM_RUN_LIBRARIES=Movies - 4K|TV Shows - 4K</code></td>
</tr>
<tr>
<th>Values</th>
@ -553,12 +553,12 @@ Perform a metadata files run immediately to run only the pre-defined metadata fi
<tr>
<th>Flags</th>
<td><code>-rm</code> or <code>--run-metadata-files</code></td>
<td><code>PMM_METADATA_FILES</code></td>
<td><code>PMM_RUN_METADATA_FILES</code></td>
</tr>
<tr>
<th>Example</th>
<td><code>--run-metadata-files "Movies.yml|MovieCharts"</code></td>
<td><code>PMM_METADATA_FILES=Movies.yml|MovieCharts</code></td>
<td><code>PMM_RUN_METADATA_FILES=Movies.yml|MovieCharts</code></td>
</tr>
<tr>
<th>Available Values</th>

@ -77,6 +77,7 @@ String filters can take multiple values **only as a list**.
| `folder` | Uses the item's folder to match | &#10060; | &#9989; | &#10060; | &#10060; | &#9989; | &#10060; | &#10060; |
| `filepath` | Uses the item's filepath to match | &#9989; | &#9989;<sup>**[1](#table-annotations)**</sup> | &#9989;<sup>**[1](#table-annotations)**</sup> | &#9989; | &#9989;<sup>**[1](#table-annotations)**</sup> | &#9989;<sup>**[1](#table-annotations)**</sup> | &#9989; |
| `audio_track_title` | Uses the audio track titles to match | &#9989; | &#9989;<sup>**[1](#table-annotations)**</sup> | &#9989;<sup>**[1](#table-annotations)**</sup> | &#9989; | &#9989;<sup>**[1](#table-annotations)**</sup> | &#9989;<sup>**[1](#table-annotations)**</sup> | &#9989; |
| `subtitle_track_title` | Uses the subtitle track titles to match | &#9989; | &#9989;<sup>**[1](#table-annotations)**</sup> | &#9989;<sup>**[1](#table-annotations)**</sup> | &#9989; | &#9989;<sup>**[1](#table-annotations)**</sup> | &#9989;<sup>**[1](#table-annotations)**</sup> | &#9989; |
| `video_codec` | Uses the video codec tags to match | &#9989; | &#9989;<sup>**[1](#table-annotations)**</sup> | &#9989;<sup>**[1](#table-annotations)**</sup> | &#9989; | &#10060; | &#10060; | &#10060; |
| `video_profile` | Uses the video profile tags to match | &#9989; | &#9989;<sup>**[1](#table-annotations)**</sup> | &#9989;<sup>**[1](#table-annotations)**</sup> | &#9989; | &#10060; | &#10060; | &#10060; |
| `audio_codec` | Uses the audio codec tags to match | &#9989; | &#9989;<sup>**[1](#table-annotations)**</sup> | &#9989;<sup>**[1](#table-annotations)**</sup> | &#9989; | &#10060; | &#10060; | &#10060; |

@ -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"]

@ -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

@ -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()")

@ -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 "<<library_type>>" in title_format:
title_format = title_format.replace("<<library_type>>", library.type.lower())
if "<<library_typeU>>" in title_format:

@ -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)

@ -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 = ""

Loading…
Cancel
Save