[29] add nightly check and cached is reloaded

pull/858/head
meisnate12 3 years ago
parent d91c6bf635
commit 8d1725d397

@ -18,6 +18,7 @@ jobs:
webhook_id: ${{ secrets.DEVELOP_WEBHOOK_ID }} webhook_id: ${{ secrets.DEVELOP_WEBHOOK_ID }}
webhook_token: ${{ secrets.DEVELOP_WEBHOOK_TOKEN }} webhook_token: ${{ secrets.DEVELOP_WEBHOOK_TOKEN }}
title: Plex Meta Manager Develop Commits title: Plex Meta Manager Develop Commits
message: "@Develop Notifications"
commits: "true" commits: "true"
username: Metabot username: Metabot
avatar_url: https://raw.githubusercontent.com/meisnate12/Plex-Meta-Manager/develop/.github/pmm.png avatar_url: https://raw.githubusercontent.com/meisnate12/Plex-Meta-Manager/develop/.github/pmm.png

@ -15,9 +15,10 @@ jobs:
- name: Send Discord Commit Notification - name: Send Discord Commit Notification
uses: meisnate12/discord-notifications@master uses: meisnate12/discord-notifications@master
with: with:
webhook_id: ${{ secrets.BUILD_WEBHOOK_ID }} webhook_id: ${{ secrets.NIGHTLY_WEBHOOK_ID }}
webhook_token: ${{ secrets.BUILD_WEBHOOK_TOKEN }} webhook_token: ${{ secrets.NIGHTLY_WEBHOOK_TOKEN }}
title: Nightly Commits title: Nightly Commits
message: "@Nightly Notifications"
commits: "true" commits: "true"
username: Metabot username: Metabot
avatar_url: https://raw.githubusercontent.com/meisnate12/Plex-Meta-Manager/nightly/.github/pmm.png avatar_url: https://raw.githubusercontent.com/meisnate12/Plex-Meta-Manager/nightly/.github/pmm.png

@ -18,6 +18,6 @@ jobs:
webhook_token: ${{ secrets.RELEASE_WEBHOOK_TOKEN }} webhook_token: ${{ secrets.RELEASE_WEBHOOK_TOKEN }}
release: true release: true
title: Plex Meta Manager Release VERSION title: Plex Meta Manager Release VERSION
message: "@Master Notifications"
username: Metabot username: Metabot
avatar_url: https://raw.githubusercontent.com/meisnate12/Plex-Meta-Manager/master/.github/pmm.png avatar_url: https://raw.githubusercontent.com/meisnate12/Plex-Meta-Manager/master/.github/pmm.png
message: "@everyone"

@ -1 +1 @@
1.16.5-develop28 1.16.5-develop29

@ -53,6 +53,7 @@ The available setting attributes which can be set at each level are outlined bel
| [`playlist_sync_to_users`](#playlist-sync-to-users) | ✅ | ❌ | ✅ | | [`playlist_sync_to_users`](#playlist-sync-to-users) | ✅ | ❌ | ✅ |
| [`custom_repo`](#custom-repo) | ✅ | ❌ | ❌ | | [`custom_repo`](#custom-repo) | ✅ | ❌ | ❌ |
| [`verify_ssl`](#verify-ssl) | ✅ | ❌ | ❌ | | [`verify_ssl`](#verify-ssl) | ✅ | ❌ | ❌ |
| [`check_nightly`](#check-nightly) | ✅ | ❌ | ❌ |
## Cache ## Cache
Cache the Plex GUID and associated IDs for each library item for faster subsequent processing. The cache file is created in the same directory as the configuration file. Cache the Plex GUID and associated IDs for each library item for faster subsequent processing. The cache file is created in the same directory as the configuration file.
@ -529,6 +530,21 @@ Specify where the `repo` attribute's base is when defining `metadata_paths` and
## Verify SSL ## Verify SSL
Turn SSL Verification on or off. Turn SSL Verification on or off.
<table class="dualTable colwidths-auto align-default table">
<tr>
<th>Default Value</th>
<td><code>true</code></td>
</tr>
<tr>
<th>Allowed Values</th>
<td><code>true</code> or <code>false</code>
</td>
</tr>
</table>
## Check Nightly
Will check nightly for updates instead of develop.
<table class="dualTable colwidths-auto align-default table"> <table class="dualTable colwidths-auto align-default table">
<tr> <tr>
<th>Default Value</th> <th>Default Value</th>

@ -56,17 +56,17 @@ You can specify the Overlay Name in 3 ways.
3. Using a dictionary for more overlay location options. 3. Using a dictionary for more overlay location options.
| Attribute | Description | Required | | Attribute | Description | Required |
|:-----------|:--------------------------------------------------------------------------------------------------------------|:--------:| |:----------|:--------------------------------------------------------------------------------------------------------------|:--------:|
| `name` | Name of the overlay. Each overlay name should be unique. | &#9989; | | `name` | Name of the overlay. Each overlay name should be unique. | &#9989; |
| `url` | URL of Overlay Image Onlin. | &#10060; | | `url` | URL of Overlay Image Onlin. | &#10060; |
| `git` | Location in the [Configs Repo](https://github.com/meisnate12/Plex-Meta-Manager-Configs) of the Overlay Image. | &#10060; | | `git` | Location in the [Configs Repo](https://github.com/meisnate12/Plex-Meta-Manager-Configs) of the Overlay Image. | &#10060; |
| `repo` | Location in the [Custom Repo](../config/settings.md#custom-repo) of the Overlay Image. | &#10060; | | `repo` | Location in the [Custom Repo](../config/settings.md#custom-repo) of the Overlay Image. | &#10060; |
| `group` | Name of the Grouping for this overlay. **`priority` is required when using `group`** | &#10060; | | `group` | Name of the Grouping for this overlay. **`weight` is required when using `group`** | &#10060; |
| `priority` | Priority of this overlay in its group. **`group` is required when using `priority`** | &#10060; | | `weight` | Weight of this overlay in its group. **`group` is required when using `weight`** | &#10060; |
* If `url`, `git`, and `repo` are all not defined then PMM will look in your `config/overlays` folder for a `.png` file named the same as the `name` attribute. * If `url`, `git`, and `repo` are all not defined then PMM will look in your `config/overlays` folder for a `.png` file named the same as the `name` attribute.
* Only one overlay with the highest priority per group will be applied. * Only one overlay with the highest weight per group will be applied.
```yaml ```yaml
overlays: overlays:

@ -270,7 +270,7 @@ class CollectionBuilder:
self.suppress_overlays = [] self.suppress_overlays = []
self.overlay_group = None self.overlay_group = None
self.overlay_priority = None self.overlay_weight = None
if self.overlay: if self.overlay:
if "overlay" in methods: if "overlay" in methods:
logger.debug("") logger.debug("")
@ -282,13 +282,13 @@ class CollectionBuilder:
self.overlay = str(data[methods["overlay"]]["name"]) self.overlay = str(data[methods["overlay"]]["name"])
if "group" in data[methods["overlay"]] and data[methods["overlay"]]["group"]: if "group" in data[methods["overlay"]] and data[methods["overlay"]]["group"]:
self.overlay_group = str(data[methods["overlay"]]["group"]) self.overlay_group = str(data[methods["overlay"]]["group"])
if "priority" in data[methods["overlay"]] and data[methods["overlay"]]["priority"]: if "weight" in data[methods["overlay"]] and data[methods["overlay"]]["weight"]:
pri = util.check_num(data[methods["overlay"]]["group"]) pri = util.check_num(data[methods["overlay"]]["weight"])
if pri is None: if pri is None:
raise Failed(f"{self.Type} Error: overlay priority must be a number") raise Failed(f"{self.Type} Error: overlay weight must be a number")
self.overlay_priority = pri self.overlay_weight = pri
else: else:
raise Failed(f"{self.Type} Error: overlay group and overlay priority must be used together") raise Failed(f"{self.Type} Error: overlay group and overlay weight must be used together")
if "git" in data[methods["overlay"]] and data[methods["overlay"]]["git"]: if "git" in data[methods["overlay"]] and data[methods["overlay"]]["git"]:
url = f"{util.github_base}{data[methods['overlay']]['git']}.png" url = f"{util.github_base}{data[methods['overlay']]['git']}.png"
elif "repo" in data[methods["overlay"]] and data[methods["overlay"]]["repo"]: elif "repo" in data[methods["overlay"]] and data[methods["overlay"]]["repo"]:
@ -2151,7 +2151,7 @@ class CollectionBuilder:
def check_filters(self, item, display): def check_filters(self, item, display):
if (self.filters or self.tmdb_filters) and not self.details["only_filter_missing"]: if (self.filters or self.tmdb_filters) and not self.details["only_filter_missing"]:
logger.ghost(f"Filtering {display} {item.title}") logger.ghost(f"Filtering {display} {item.title}")
self.library.reload(item) item = self.library.reload(item)
if self.tmdb_filters and isinstance(item, (Movie, Show)): if self.tmdb_filters and isinstance(item, (Movie, Show)):
if item.ratingKey not in self.library.movie_rating_key_map and item.ratingKey not in self.library.show_rating_key_map: if item.ratingKey not in self.library.movie_rating_key_map and item.ratingKey not in self.library.show_rating_key_map:
logger.warning(f"Filter Error: No {'TMDb' if self.library.is_movie else 'TVDb'} ID found for {item.title}") logger.warning(f"Filter Error: No {'TMDb' if self.library.is_movie else 'TVDb'} ID found for {item.title}")

@ -68,7 +68,6 @@ class ConfigFile:
self.default_dir = default_dir self.default_dir = default_dir
self.read_only = attrs["read_only"] if "read_only" in attrs else False self.read_only = attrs["read_only"] if "read_only" in attrs else False
self.version = attrs["version"] if "version" in attrs else None self.version = attrs["version"] if "version" in attrs else None
self.latest_version = attrs["latest_version"] if "latest_version" in attrs else None
self.no_missing = attrs["no_missing"] if "no_missing" in attrs else None self.no_missing = attrs["no_missing"] if "no_missing" in attrs else None
self.test_mode = attrs["test"] if "test" in attrs else False self.test_mode = attrs["test"] if "test" in attrs else False
self.trace_mode = attrs["trace"] if "trace" in attrs else False self.trace_mode = attrs["trace"] if "trace" in attrs else False
@ -319,10 +318,13 @@ class ConfigFile:
"playlist_sync_to_users": check_for_attribute(self.data, "playlist_sync_to_users", parent="settings", default="all", default_is_none=True), "playlist_sync_to_users": check_for_attribute(self.data, "playlist_sync_to_users", parent="settings", default="all", default_is_none=True),
"verify_ssl": check_for_attribute(self.data, "verify_ssl", parent="settings", var_type="bool", default=True), "verify_ssl": check_for_attribute(self.data, "verify_ssl", parent="settings", var_type="bool", default=True),
"custom_repo": check_for_attribute(self.data, "custom_repo", parent="settings", default_is_none=True), "custom_repo": check_for_attribute(self.data, "custom_repo", parent="settings", default_is_none=True),
"check_nightly": check_for_attribute(self.data, "check_nightly", parent="settings", var_type="bool", default=False),
"assets_for_all": check_for_attribute(self.data, "assets_for_all", parent="settings", var_type="bool", default=False, save=False, do_print=False) "assets_for_all": check_for_attribute(self.data, "assets_for_all", parent="settings", var_type="bool", default=False, save=False, do_print=False)
} }
self.custom_repo = self.general["custom_repo"].replace("https://github.com/", "https://raw.githubusercontent.com/") if self.general["custom_repo"] else None self.custom_repo = self.general["custom_repo"].replace("https://github.com/", "https://raw.githubusercontent.com/") if self.general["custom_repo"] else None
self.latest_version = util.current_version(self.version, nightly=self.general["check_nightly"])
self.session = requests.Session() self.session = requests.Session()
if not self.general["verify_ssl"]: if not self.general["verify_ssl"]:
self.session.verify = False self.session.verify = False

@ -187,7 +187,7 @@ class Library(ABC):
new_poster.save(temp_image) new_poster.save(temp_image)
self.upload_poster(item, temp_image) self.upload_poster(item, temp_image)
self.edit_tags("label", item, add_tags=[f"{overlay_name} Overlay"]) self.edit_tags("label", item, add_tags=[f"{overlay_name} Overlay"])
self.reload(item) self.reload(item, force=True)
poster_uploaded = True poster_uploaded = True
logger.info(f"Detail: Overlay: {overlay_name} applied to {item.title}") logger.info(f"Detail: Overlay: {overlay_name} applied to {item.title}")
except (OSError, BadRequest) as e: except (OSError, BadRequest) as e:
@ -231,7 +231,7 @@ class Library(ABC):
pass pass
@abstractmethod @abstractmethod
def reload(self, item): def reload(self, item, force=False):
pass pass
@abstractmethod @abstractmethod

@ -424,7 +424,7 @@ class MetadataFile(DataFile):
person_limit = util.parse("Config", "limit", dynamic_data, parent=f"{map_name} data", methods=person_methods, datatype="int", default=25, minimum=1) if "limit" in person_methods else None person_limit = util.parse("Config", "limit", dynamic_data, parent=f"{map_name} data", methods=person_methods, datatype="int", default=25, minimum=1) if "limit" in person_methods else None
for i, item in enumerate(library.get_all(), 1): for i, item in enumerate(library.get_all(), 1):
try: try:
self.library.reload(item) item = self.library.reload(item)
for person in getattr(item, f"{auto_type}s")[:person_depth]: for person in getattr(item, f"{auto_type}s")[:person_depth]:
if person.id not in people: if person.id not in people:
people[person.id] = {"name": person.tag, "count": 0} people[person.id] = {"name": person.tag, "count": 0}

@ -68,7 +68,7 @@ class Operations:
for i, item in enumerate(items, 1): for i, item in enumerate(items, 1):
try: try:
self.library.reload(item) item = self.library.reload(item)
except Failed as e: except Failed as e:
logger.error(e) logger.error(e)
continue continue

@ -37,8 +37,8 @@ class Overlays:
if builder.overlay not in settings: if builder.overlay not in settings:
settings[builder.overlay] = { settings[builder.overlay] = {
"keys": [], "suppress": [], "group": None, "keys": [], "suppress": builder.suppress_overlays, "group": builder.overlay_group,
"priority": None, "updated": False, "image": None "weight": builder.overlay_weight, "updated": False, "image": None
} }
for method, value in builder.builders: for method, value in builder.builders:
@ -64,9 +64,6 @@ class Overlays:
if added_titles: if added_titles:
logger.debug(f"{len(added_titles)} Titles Found: {added_titles}") logger.debug(f"{len(added_titles)} Titles Found: {added_titles}")
logger.info(f"{len(added_titles) if added_titles else 'No'} Items found for {builder.overlay}") logger.info(f"{len(added_titles) if added_titles else 'No'} Items found for {builder.overlay}")
if builder.suppress_overlays:
settings[builder.overlay]["suppress"] = builder.suppress_overlays
except Failed as e: except Failed as e:
logger.error(e) logger.error(e)
@ -75,7 +72,7 @@ class Overlays:
if over_attrs["group"]: if over_attrs["group"]:
if over_attrs["group"] not in overlay_groups: if over_attrs["group"] not in overlay_groups:
overlay_groups[over_attrs["group"]] = {} overlay_groups[over_attrs["group"]] = {}
overlay_groups[over_attrs["group"]][overlay_name] = over_attrs["priority"] overlay_groups[over_attrs["group"]][overlay_name] = over_attrs["weight"]
for rk in over_attrs["keys"]: for rk in over_attrs["keys"]:
for suppress_name in over_attrs["suppress"]: for suppress_name in over_attrs["suppress"]:
if suppress_name in settings and rk in settings[suppress_name]["keys"]: if suppress_name in settings and rk in settings[suppress_name]["keys"]:
@ -254,7 +251,7 @@ class Overlays:
new_poster.save(temp, "PNG") new_poster.save(temp, "PNG")
self.library.upload_poster(item, temp) self.library.upload_poster(item, temp)
self.library.edit_tags("label", item, add_tags=["Overlay"], do_print=False) self.library.edit_tags("label", item, add_tags=["Overlay"], do_print=False)
self.library.reload(item) self.library.reload(item, force=True)
poster_compare = poster.compare if poster else item.thumb poster_compare = poster.compare if poster else item.thumb
logger.info(f"Detail: Overlays: {', '.join(over_names)} applied to {item.title}") logger.info(f"Detail: Overlays: {', '.join(over_names)} applied to {item.title}")
except (OSError, BadRequest) as e: except (OSError, BadRequest) as e:

@ -390,10 +390,6 @@ class Plex(Library):
terms = {"title=": title} terms = {"title=": title}
return self.Plex.search(libtype=libtype, **terms) return self.Plex.search(libtype=libtype, **terms)
@retry(stop_max_attempt_number=6, wait_fixed=10000, retry_on_exception=util.retry_if_not_plex)
def get_labeled_items(self, label):
return self.search(label=label)
@retry(stop_max_attempt_number=6, wait_fixed=10000, retry_on_exception=util.retry_if_not_plex) @retry(stop_max_attempt_number=6, wait_fixed=10000, retry_on_exception=util.retry_if_not_plex)
def fetchItem(self, data): def fetchItem(self, data):
return self.PlexServer.fetchItem(data) return self.PlexServer.fetchItem(data)
@ -464,18 +460,21 @@ class Plex(Library):
collection.sortUpdate(sort=data) collection.sortUpdate(sort=data)
@retry(stop_max_attempt_number=6, wait_fixed=10000, retry_on_exception=util.retry_if_not_plex) @retry(stop_max_attempt_number=6, wait_fixed=10000, retry_on_exception=util.retry_if_not_plex)
def reload(self, item, force=True): def reload(self, item, force=False):
is_full = False is_full = False
cached_item = item
if item.ratingKey in self.cached_items: if item.ratingKey in self.cached_items:
cached_item, is_full = self.cached_items[item.ratingKey] cached_item, is_full = self.cached_items[item.ratingKey]
try: try:
if not is_full: if not is_full or force:
item.reload(checkFiles=False, includeAllConcerts=False, includeBandwidths=False, includeChapters=False, cached_item.reload(checkFiles=False, includeAllConcerts=False, includeBandwidths=False,
includeChildren=False, includeConcerts=False, includeExternalMedia=False, includeExtras=False, includeChapters=False, includeChildren=False, includeConcerts=False,
includeFields=False, includeGeolocation=False, includeLoudnessRamps=False, includeMarkers=False, includeExternalMedia=False, includeExtras=False, includeFields=False,
includeOnDeck=False, includePopularLeaves=False, includeRelated=False, includeGeolocation=False, includeLoudnessRamps=False, includeMarkers=False,
includeRelatedCount=0, includeReviews=False, includeStations=False) includeOnDeck=False, includePopularLeaves=False, includeRelated=False,
includeRelatedCount=0, includeReviews=False, includeStations=False)
self.cached_items[item.ratingKey] = (item, True) self.cached_items[item.ratingKey] = (item, True)
return cached_item
except (BadRequest, NotFound) as e: except (BadRequest, NotFound) as e:
logger.stacktrace() logger.stacktrace()
raise Failed(f"Item Failed to Load: {e}") raise Failed(f"Item Failed to Load: {e}")
@ -498,7 +497,7 @@ class Plex(Library):
item.uploadArt(url=image.location) item.uploadArt(url=image.location)
else: else:
item.uploadArt(filepath=image.location) item.uploadArt(filepath=image.location)
self.reload(item) self.reload(item, force=True)
except BadRequest as e: except BadRequest as e:
item.refresh() item.refresh()
raise Failed(e) raise Failed(e)
@ -793,7 +792,7 @@ class Plex(Library):
_remove_tags = [t.lower() for t in remove_tags] if remove_tags else [] _remove_tags = [t.lower() for t in remove_tags] if remove_tags else []
_sync_tags = [t.lower() for t in sync_tags] if sync_tags else [] _sync_tags = [t.lower() for t in sync_tags] if sync_tags else []
try: try:
self.reload(obj) obj = self.reload(obj)
_item_tags = [item_tag.tag.lower() for item_tag in getattr(obj, key)] _item_tags = [item_tag.tag.lower() for item_tag in getattr(obj, key)]
except BadRequest: except BadRequest:
_item_tags = [] _item_tags = []

@ -95,14 +95,22 @@ def make_ordinal(n):
def add_zero(number): def add_zero(number):
return str(number) if len(str(number)) > 1 else f"0{number}" return str(number) if len(str(number)) > 1 else f"0{number}"
def current_version(develop=False): def current_version(version, nightly=False):
url = f"https://raw.githubusercontent.com/meisnate12/Plex-Meta-Manager/{'develop' if develop else 'master'}/VERSION" if nightly:
return get_version("nightly")
elif version[2] > 0:
new_version = get_version("develop")
return get_version("nightly") if new_version[2] < version[2] else new_version
else:
return get_version("master")
def get_version(level):
url = f"https://raw.githubusercontent.com/meisnate12/Plex-Meta-Manager/{level}/VERSION"
try: try:
return parse_version(requests.get(url).content.decode().strip()) return parse_version(requests.get(url).content.decode().strip())
except requests.exceptions.ConnectionError: except requests.exceptions.ConnectionError:
return None return None
def parse_version(version): def parse_version(version):
split_version = version.split("-develop") split_version = version.split("-develop")
return version, split_version[0], int(split_version[1]) if len(split_version) > 1 else 0 return version, split_version[0], int(split_version[1]) if len(split_version) > 1 else 0

@ -11,8 +11,8 @@ except ModuleNotFoundError:
print("Requirements Error: Requirements are not installed") print("Requirements Error: Requirements are not installed")
sys.exit(0) sys.exit(0)
if sys.version_info[0] != 3 or sys.version_info[1] < 6: if sys.version_info[0] != 3 or sys.version_info[1] < 7:
print("Version Error: Version: %s.%s.%s incompatible please use Python 3.6+" % (sys.version_info[0], sys.version_info[1], sys.version_info[2])) print("Version Error: Version: %s.%s.%s incompatible please use Python 3.7+" % (sys.version_info[0], sys.version_info[1], sys.version_info[2]))
sys.exit(0) sys.exit(0)
parser = argparse.ArgumentParser() parser = argparse.ArgumentParser()
@ -86,7 +86,6 @@ screen_width = get_arg("PMM_WIDTH", args.width, arg_int=True)
debug = get_arg("PMM_DEBUG", args.debug, arg_bool=True) debug = get_arg("PMM_DEBUG", args.debug, arg_bool=True)
trace = get_arg("PMM_TRACE", args.trace, arg_bool=True) trace = get_arg("PMM_TRACE", args.trace, arg_bool=True)
if screen_width < 90 or screen_width > 300: 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") print(f"Argument Error: width argument invalid: {screen_width} must be an integer between 90 and 300 using the default 100")
screen_width = 100 screen_width = 100
@ -150,8 +149,7 @@ def start(attrs):
logger.info_center("|_| |_|\\___/_/\\_\\ |_| |_|\\___|\\__\\__,_| |_| |_|\\__,_|_| |_|\\__,_|\\__, |\\___|_| ") logger.info_center("|_| |_|\\___/_/\\_\\ |_| |_|\\___|\\__\\__,_| |_| |_|\\__,_|_| |_|\\__,_|\\__, |\\___|_| ")
logger.info_center(" |___/ ") logger.info_center(" |___/ ")
logger.info(f" Version: {version[0]}") logger.info(f" Version: {version[0]}")
latest_version = util.current_version(version)
latest_version = util.current_version()
new_version = latest_version[0] if latest_version and (version[1] != latest_version[1] or (version[2] and version[2] < latest_version[2])) else None new_version = latest_version[0] if latest_version and (version[1] != latest_version[1] or (version[2] and version[2] < latest_version[2])) else None
if new_version: if new_version:
logger.info(f" Newest Version: {new_version}") logger.info(f" Newest Version: {new_version}")
@ -166,7 +164,6 @@ def start(attrs):
attrs["time_obj"] = start_time attrs["time_obj"] = start_time
attrs["read_only"] = read_only_config attrs["read_only"] = read_only_config
attrs["version"] = version attrs["version"] = version
attrs["latest_version"] = latest_version
attrs["no_missing"] = no_missing attrs["no_missing"] = no_missing
logger.separator(debug=True) logger.separator(debug=True)
logger.debug(f"--config (PMM_CONFIG): {config_file}") logger.debug(f"--config (PMM_CONFIG): {config_file}")

Loading…
Cancel
Save