diff --git a/VERSION b/VERSION index 0aa9f125..d2c54c6b 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.16.2-develop3 +1.16.2-develop4 diff --git a/config/config.yml.template b/config/config.yml.template index 6f961daf..a4b38bcb 100644 --- a/config/config.yml.template +++ b/config/config.yml.template @@ -55,6 +55,7 @@ settings: custom_repo: webhooks: # Can be individually specified per library as well error: + version: run_start: run_end: changes: diff --git a/docs/config/notifiarr.md b/docs/config/notifiarr.md index 440986ce..ea00a69d 100644 --- a/docs/config/notifiarr.md +++ b/docs/config/notifiarr.md @@ -19,6 +19,7 @@ Once you have added the apikey your config.yml you have to add `notifiarr` to an ```yaml webhooks: error: notifiarr + version: notifiarr run_start: notifiarr run_end: notifiarr collection_changes: notifiarr diff --git a/docs/config/webhooks.md b/docs/config/webhooks.md index 40a26420..0c343751 100644 --- a/docs/config/webhooks.md +++ b/docs/config/webhooks.md @@ -9,6 +9,7 @@ Below is a `webhooks` mapping example and the full set of attributes: ```yaml webhooks: error: https://www.myspecialdomain.com/pmm + version: run_start: run_end: changes: @@ -17,6 +18,7 @@ webhooks: | Attribute | Global | Library | Collection | |:----------------------------------------|:-------:|:--------:|:----------:| | [`error`](#error-notifications) | ✅ | ✅ | ❌ | +| [`version`](#version-notifications) | ✅ | ❌ | ❌ | | [`run_start`](#run-start-notifications) | ✅ | ❌ | ❌ | | [`run_end`](#run-end-notifications) | ✅ | ❌ | ❌ | | [`changes`](#changes-notifications) | ✅ | ✅ | ✅ | @@ -72,6 +74,20 @@ The Error notification will be sent whenever an error occurs. The payload that i } ``` +## Version Notifications + +The Version notification will be sent at the beginning of a run if there is a newer version available. + +### JSON Payload + +```yaml +{ + "current": str, // Current Version + "latest": str, // Latest Version + "notes": str // Sends the lateset release notes or new commits to develop since your version +} +``` + ## Run Start Notifications The Run Start notification will be sent at the beginning of every run. @@ -81,7 +97,6 @@ The Run Start notification will be sent at the beginning of every run. ```yaml { "start_time": str, // Time Run is started Format "YY-mm-dd HH:MM:SS" - "new_version": str // New Version or null if version is current } ``` @@ -96,7 +111,6 @@ The Run End notification will be sent at the end of every run with statistics. "start_time": str, // Time Run started Format "YY-mm-dd HH:MM:SS" "end_time": str, // Time Run ended Format "YY-mm-dd HH:MM:SS" "run_time": str, // Time Run took to complete Format "HH:MM" - "new_version": str, // New Version or null if version is current "collections_created": int, // Number of Collections/Playlists Created "collections_modified": int, // Number of Collections/Playlists Modified "collections_deleted": int, // Number of Collections/Playlists Removed diff --git a/modules/config.py b/modules/config.py index f1682815..2bce62db 100644 --- a/modules/config.py +++ b/modules/config.py @@ -9,6 +9,7 @@ from modules.convert import Convert from modules.flixpatrol import FlixPatrol from modules.icheckmovies import ICheckMovies from modules.imdb import IMDb +from modules.github import GitHub from modules.letterboxd import Letterboxd from modules.mal import MyAnimeList from modules.meta import PlaylistFile @@ -63,7 +64,8 @@ class ConfigFile: self.default_dir = default_dir self.read_only = attrs["read_only"] if "read_only" in attrs else False - self.new_version = attrs["new_version"] if "new_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.test_mode = attrs["test"] if "test" in attrs else False self.trace_mode = attrs["trace"] if "trace" in attrs else False self.delete_collections = attrs["delete"] if "delete" in attrs else False @@ -324,17 +326,12 @@ class ConfigFile: import urllib3 urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) - self.webhooks = { - "error": check_for_attribute(self.data, "error", parent="webhooks", var_type="list", default_is_none=True), - "run_start": check_for_attribute(self.data, "run_start", parent="webhooks", var_type="list", default_is_none=True), - "run_end": check_for_attribute(self.data, "run_end", parent="webhooks", var_type="list", default_is_none=True), - "changes": check_for_attribute(self.data, "changes", parent="webhooks", var_type="list", default_is_none=True) - } if self.general["cache"]: logger.separator() self.Cache = Cache(self.config_path, self.general["cache_expiration"]) else: self.Cache = None + self.GitHub = GitHub(self) logger.separator() @@ -354,9 +351,18 @@ class ConfigFile: else: logger.warning("notifiarr attribute not found") + self.webhooks = { + "error": check_for_attribute(self.data, "error", parent="webhooks", var_type="list", default_is_none=True), + "version": check_for_attribute(self.data, "version", parent="webhooks", var_type="list", default_is_none=True), + "run_start": check_for_attribute(self.data, "run_start", parent="webhooks", var_type="list", default_is_none=True), + "run_end": check_for_attribute(self.data, "run_end", parent="webhooks", var_type="list", default_is_none=True), + "changes": check_for_attribute(self.data, "changes", parent="webhooks", var_type="list", default_is_none=True) + } self.Webhooks = Webhooks(self, self.webhooks, notifiarr=self.NotifiarrFactory) try: - self.Webhooks.start_time_hooks(self.start_time, self.new_version) + self.Webhooks.start_time_hooks(self.start_time) + if self.version[1] != self.latest_version[1] or (self.version[2] and self.version[2] < self.latest_version[2]): + self.Webhooks.version_hooks(self.version, self.latest_version) except Failed as e: logger.stacktrace() logger.error(f"Webhooks Error: {e}") diff --git a/modules/github.py b/modules/github.py new file mode 100644 index 00000000..1772a0b9 --- /dev/null +++ b/modules/github.py @@ -0,0 +1,30 @@ +import re +from modules import util +from modules.util import Failed + +logger = util.logger + +base_url = "https://api.github.com/repos/meisnate12/Plex-Meta-Manager" + +class GitHub: + def __init__(self, config): + self.config = config + + def latest_release_notes(self): + response = self.config.get_json(f"{base_url}/releases/latest") + return response["body"] + + def get_develop_commits(self, dev_version): + master_sha = self.config.get_json(f"{base_url}/commits/master")["sha"] + response = self.config.get_json(f"{base_url}/commits?sha=develop") + commits = [] + for commit in response: + if commit["sha"] == master_sha: + break + message = commit["commit"]["message"] + match = re.match("^\\[(\\d)\\]", message) + if match and int(match.group(1)) <= dev_version: + break + commits.append(message) + return "\n".join(commits) + \ No newline at end of file diff --git a/modules/util.py b/modules/util.py index 5906fc79..084c639c 100644 --- a/modules/util.py +++ b/modules/util.py @@ -1,4 +1,4 @@ -import glob, logging, os, re, signal, sys, time +import glob, logging, os, re, requests, signal, sys, time from datetime import datetime, timedelta from pathvalidate import is_valid_filename, sanitize_filename from plexapi.audio import Album, Track @@ -92,6 +92,18 @@ def make_ordinal(n): def add_zero(number): return str(number) if len(str(number)) > 1 else f"0{number}" +def current_version(develop=False): + url = f"https://raw.githubusercontent.com/meisnate12/Plex-Meta-Manager/{'develop' if develop else 'master'}/VERSION" + try: + return parse_version(requests.get(url).content.decode().strip()) + except requests.exceptions.ConnectionError: + return None + + +def parse_version(version): + split_version = version.split("-develop") + return version, split_version[0], int(split_version[1]) if len(split_version) > 1 else 0 + def add_dict_list(keys, value, dict_map): for key in keys: if key in dict_map: diff --git a/modules/webhooks.py b/modules/webhooks.py index 12f16454..e77d94fa 100644 --- a/modules/webhooks.py +++ b/modules/webhooks.py @@ -8,6 +8,7 @@ class Webhooks: def __init__(self, config, system_webhooks, library=None, notifiarr=None): self.config = config self.error_webhooks = system_webhooks["error"] if "error" in system_webhooks else [] + self.version_webhooks = system_webhooks["version"] if "version" in system_webhooks else [] self.run_start_webhooks = system_webhooks["run_start"] if "run_start" in system_webhooks else [] self.run_end_webhooks = system_webhooks["run_end"] if "run_end" in system_webhooks else [] self.library = library @@ -44,20 +45,25 @@ class Webhooks: if response.status_code >= 400: raise Failed(f"({response.status_code} [{response.reason}])") - def start_time_hooks(self, start_time, version): + def start_time_hooks(self, start_time): if self.run_start_webhooks: - self._request(self.run_start_webhooks, { - "start_time": start_time.strftime("%Y-%m-%d %H:%M:%S"), - "new_version": version - }) + self._request(self.run_start_webhooks, {"start_time": start_time.strftime("%Y-%m-%d %H:%M:%S")}) - def end_time_hooks(self, start_time, end_time, run_time, stats, version): + def version_hooks(self, version, latest_version): + if self.version_webhooks: + notes = None + if version[1] != latest_version[1]: + notes = self.config.GitHub.latest_release_notes() + elif version[2] and version[2] < latest_version[2]: + notes = self.config.GitHub.get_develop_commits(version[2]) + self._request(self.version_webhooks, {"current": version[0], "latest": latest_version[0], "notes": notes}) + + def end_time_hooks(self, start_time, end_time, run_time, stats): if self.run_end_webhooks: self._request(self.run_end_webhooks, { "start_time": start_time.strftime("%Y-%m-%d %H:%M:%S"), "end_time": end_time.strftime("%Y-%m-%d %H:%M:%S"), "run_time": run_time, - "new_version": version, "collections_created": stats["created"], "collections_modified": stats["modified"], "collections_deleted": stats["deleted"], diff --git a/plex_meta_manager.py b/plex_meta_manager.py index 96d7a4c1..830acc60 100644 --- a/plex_meta_manager.py +++ b/plex_meta_manager.py @@ -108,22 +108,14 @@ def my_except_hook(exctype, value, tb): sys.excepthook = my_except_hook -def get_versions(presplit_version): - split_version = presplit_version.split("-develop") - return presplit_version, split_version[0], int(split_version[1]) if len(split_version) > 1 else 0 - version = ("Unknown", "Unknown", 0) with open(os.path.join(os.path.dirname(os.path.abspath(__file__)), "VERSION")) as handle: for line in handle.readlines(): line = line.strip() if len(line) > 0: - version = get_versions(line) + version = util.parse_version(line) break -version_url = f"https://raw.githubusercontent.com/meisnate12/Plex-Meta-Manager/{'develop' if version[1] else 'master'}/VERSION" -latest_version = get_versions(requests.get(version_url).content.decode().strip()) -new_version = latest_version[0] if version[1] != latest_version[1] or (version[2] and version[2] < latest_version[2]) else None - plexapi.BASE_HEADERS['X-Plex-Client-Identifier'] = "Plex-Meta-Manager" def start(attrs): @@ -137,6 +129,9 @@ def start(attrs): logger.info_center("|_| |_|\\___/_/\\_\\ |_| |_|\\___|\\__\\__,_| |_| |_|\\__,_|_| |_|\\__,_|\\__, |\\___|_| ") logger.info_center(" |___/ ") logger.info(f" Version: {version[0]}") + + 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 if new_version: logger.info(f" Newest Version: {new_version}") if "time" in attrs and attrs["time"]: start_type = f"{attrs['time']} " @@ -149,7 +144,8 @@ def start(attrs): attrs["time"] = start_time.strftime("%H:%M") attrs["time_obj"] = start_time attrs["read_only"] = read_only_config - attrs["new_version"] = new_version + attrs["version"] = version + attrs["latest_version"] = latest_version logger.separator(debug=True) logger.debug(f"--config (PMM_CONFIG): {config_file}") logger.debug(f"--time (PMM_TIME): {times}") @@ -193,7 +189,7 @@ def start(attrs): run_time = str(end_time - start_time).split('.')[0] if config: try: - config.Webhooks.end_time_hooks(start_time, end_time, run_time, stats, new_version) + config.Webhooks.end_time_hooks(start_time, end_time, run_time, stats) except Failed as e: logger.stacktrace() logger.error(f"Webhooks Error: {e}")