adds range schedule and delete_not_scheduled

pull/487/head
meisnate12 3 years ago
parent d3eb57902b
commit 23c5af19e2

@ -182,6 +182,7 @@ class CollectionBuilder:
"only_filter_missing": self.library.only_filter_missing, "only_filter_missing": self.library.only_filter_missing,
"create_asset_folders": self.library.create_asset_folders, "create_asset_folders": self.library.create_asset_folders,
"delete_below_minimum": self.library.delete_below_minimum, "delete_below_minimum": self.library.delete_below_minimum,
"delete_not_scheduled": self.library.delete_not_scheduled,
"collection_creation_webhooks": self.library.collection_creation_webhooks, "collection_creation_webhooks": self.library.collection_creation_webhooks,
"collection_addition_webhooks": self.library.collection_addition_webhooks, "collection_addition_webhooks": self.library.collection_addition_webhooks,
"collection_removal_webhooks": self.library.collection_removal_webhooks, "collection_removal_webhooks": self.library.collection_removal_webhooks,
@ -337,6 +338,12 @@ class CollectionBuilder:
except Failed: except Failed:
continue continue
if "delete_not_scheduled" in methods:
logger.debug("")
logger.debug("Validating Method: delete_not_scheduled")
logger.debug(f"Value: {data[methods['delete_not_scheduled']]}")
self.details["delete_not_scheduled"] = util.parse("delete_not_scheduled", self.data, datatype="bool", methods=methods, default=False)
if "schedule" in methods: if "schedule" in methods:
logger.debug("") logger.debug("")
logger.debug("Validating Method: schedule") logger.debug("Validating Method: schedule")
@ -352,7 +359,7 @@ class CollectionBuilder:
run_time = str(schedule).lower() run_time = str(schedule).lower()
if run_time.startswith(("day", "daily")): if run_time.startswith(("day", "daily")):
skip_collection = False skip_collection = False
elif run_time.startswith(("hour", "week", "month", "year")): elif run_time.startswith(("hour", "week", "month", "year", "range")):
match = re.search("\\(([^)]+)\\)", run_time) match = re.search("\\(([^)]+)\\)", run_time)
if not match: if not match:
logger.error(f"Collection Error: failed to parse schedule: {schedule}") logger.error(f"Collection Error: failed to parse schedule: {schedule}")
@ -396,12 +403,35 @@ class CollectionBuilder:
self.schedule += f"\nScheduled yearly on {util.pretty_months[month]} {util.make_ordinal(day)}" self.schedule += f"\nScheduled yearly on {util.pretty_months[month]} {util.make_ordinal(day)}"
if self.current_time.month == month and (self.current_time.day == day or (self.current_time.day == last_day.day and day > last_day.day)): if self.current_time.month == month and (self.current_time.day == day or (self.current_time.day == last_day.day and day > last_day.day)):
skip_collection = False skip_collection = False
elif run_time.startswith("range"):
match = re.match("^(1[0-2]|0?[1-9])/(3[01]|[12][0-9]|0?[1-9])-(1[0-2]|0?[1-9])/(3[01]|[12][0-9]|0?[1-9])$", param)
if not match:
logger.error(f"Collection Error: range schedule attribute {schedule} invalid must be in the MM/DD-MM/DD format i.e. range(12/01-12/25)")
continue
month_start = int(match.group(1))
day_start = int(match.group(2))
month_end = int(match.group(3))
day_end = int(match.group(4))
check = datetime.strptime(f"{self.current_time.month}/{self.current_time.day}", "%m/%d")
start = datetime.strptime(f"{month_start}/{day_start}", "%m/%d")
end = datetime.strptime(f"{month_end}/{day_end}", "%m/%d")
self.schedule += f"\nScheduled between {util.pretty_months[month_start]} {util.make_ordinal(day_start)} and {util.pretty_months[month_end]} {util.make_ordinal(day_end)}"
if start <= check <= end if start < end else check <= end or check >= start:
skip_collection = False
else: else:
logger.error(f"Collection Error: schedule attribute {schedule} invalid") logger.error(f"Collection Error: schedule attribute {schedule} invalid")
if len(self.schedule) == 0: if len(self.schedule) == 0:
skip_collection = False skip_collection = False
if skip_collection: if skip_collection:
raise NotScheduled(f"{self.schedule}\n\nCollection {self.name} not scheduled to run") suffix = ""
if self.details["delete_not_scheduled"]:
try:
self.obj = self.library.get_collection(self.name)
self.delete_collection()
suffix = f" and was deleted"
except Failed:
suffix = f" and could not be found to delete"
raise NotScheduled(f"{self.schedule}\n\nCollection {self.name} not scheduled to run{suffix}")
self.collectionless = "plex_collectionless" in methods self.collectionless = "plex_collectionless" in methods

@ -208,6 +208,7 @@ class Config:
"create_asset_folders": check_for_attribute(self.data, "create_asset_folders", parent="settings", var_type="bool", default=False), "create_asset_folders": check_for_attribute(self.data, "create_asset_folders", parent="settings", var_type="bool", default=False),
"collection_minimum": check_for_attribute(self.data, "collection_minimum", parent="settings", var_type="int", default=1), "collection_minimum": check_for_attribute(self.data, "collection_minimum", parent="settings", var_type="int", default=1),
"delete_below_minimum": check_for_attribute(self.data, "delete_below_minimum", parent="settings", var_type="bool", default=False), "delete_below_minimum": check_for_attribute(self.data, "delete_below_minimum", parent="settings", var_type="bool", default=False),
"delete_not_scheduled": check_for_attribute(self.data, "delete_not_scheduled", parent="settings", var_type="bool", default=False),
"tvdb_language": check_for_attribute(self.data, "tvdb_language", parent="settings", default="default") "tvdb_language": check_for_attribute(self.data, "tvdb_language", parent="settings", default="default")
} }
self.webhooks = { self.webhooks = {
@ -424,6 +425,7 @@ class Config:
params["create_asset_folders"] = check_for_attribute(lib, "create_asset_folders", parent="settings", var_type="bool", default=self.general["create_asset_folders"], do_print=False, save=False) params["create_asset_folders"] = check_for_attribute(lib, "create_asset_folders", parent="settings", var_type="bool", default=self.general["create_asset_folders"], do_print=False, save=False)
params["collection_minimum"] = check_for_attribute(lib, "collection_minimum", parent="settings", var_type="int", default=self.general["collection_minimum"], do_print=False, save=False) params["collection_minimum"] = check_for_attribute(lib, "collection_minimum", parent="settings", var_type="int", default=self.general["collection_minimum"], do_print=False, save=False)
params["delete_below_minimum"] = check_for_attribute(lib, "delete_below_minimum", parent="settings", var_type="bool", default=self.general["delete_below_minimum"], do_print=False, save=False) params["delete_below_minimum"] = check_for_attribute(lib, "delete_below_minimum", parent="settings", var_type="bool", default=self.general["delete_below_minimum"], do_print=False, save=False)
params["delete_not_scheduled"] = check_for_attribute(lib, "delete_not_scheduled", parent="settings", var_type="bool", default=self.general["delete_not_scheduled"], do_print=False, save=False)
params["delete_unmanaged_collections"] = check_for_attribute(lib, "delete_unmanaged_collections", parent="settings", var_type="bool", default=False, do_print=False, save=False) params["delete_unmanaged_collections"] = check_for_attribute(lib, "delete_unmanaged_collections", parent="settings", var_type="bool", default=False, do_print=False, save=False)
params["delete_collections_with_less"] = check_for_attribute(lib, "delete_collections_with_less", parent="settings", var_type="int", default_is_none=True, do_print=False, save=False) params["delete_collections_with_less"] = check_for_attribute(lib, "delete_collections_with_less", parent="settings", var_type="int", default_is_none=True, do_print=False, save=False)
params["error_webhooks"] = check_for_attribute(lib, "error", parent="webhooks", var_type="list", default=self.webhooks["error"], do_print=False, save=False, default_is_none=True) params["error_webhooks"] = check_for_attribute(lib, "error", parent="webhooks", var_type="list", default=self.webhooks["error"], do_print=False, save=False, default_is_none=True)

@ -44,6 +44,7 @@ class Library(ABC):
self.sync_mode = params["sync_mode"] self.sync_mode = params["sync_mode"]
self.collection_minimum = params["collection_minimum"] self.collection_minimum = params["collection_minimum"]
self.delete_below_minimum = params["delete_below_minimum"] self.delete_below_minimum = params["delete_below_minimum"]
self.delete_not_scheduled = params["delete_not_scheduled"]
self.missing_only_released = params["missing_only_released"] self.missing_only_released = params["missing_only_released"]
self.show_unmanaged = params["show_unmanaged"] self.show_unmanaged = params["show_unmanaged"]
self.show_filtered = params["show_filtered"] self.show_filtered = params["show_filtered"]

@ -200,7 +200,10 @@ def separator(text=None, space=True, border=True, debug=False):
if text: if text:
text_list = text.split("\n") text_list = text.split("\n")
for t in text_list: for t in text_list:
logger.info(f"|{sep}{centered(t, sep=sep)}{sep}|") if debug:
logger.debug(f"|{sep}{centered(t, sep=sep)}{sep}|")
else:
logger.info(f"|{sep}{centered(t, sep=sep)}{sep}|")
if border and debug: if border and debug:
logger.debug(border_text) logger.debug(border_text)
elif border: elif border:

@ -51,21 +51,21 @@ def get_arg(env_str, default, arg_bool=False, arg_int=False):
else: else:
return default return default
test = get_arg("PMM_TEST", args.test, arg_bool=True) config_file = get_arg("PMM_CONFIG", args.config)
debug = get_arg("PMM_DEBUG", args.debug, arg_bool=True) times = get_arg("PMM_TIME", args.times)
trace = get_arg("PMM_TRACE", args.trace, arg_bool=True)
run = get_arg("PMM_RUN", args.run, arg_bool=True) run = get_arg("PMM_RUN", args.run, arg_bool=True)
no_countdown = get_arg("PMM_NO_COUNTDOWN", args.no_countdown, arg_bool=True) test = get_arg("PMM_TEST", args.test, arg_bool=True)
no_missing = get_arg("PMM_NO_MISSING", args.no_missing, arg_bool=True)
library_only = get_arg("PMM_LIBRARIES_ONLY", args.library_only, arg_bool=True)
collection_only = get_arg("PMM_COLLECTIONS_ONLY", args.collection_only, arg_bool=True) collection_only = get_arg("PMM_COLLECTIONS_ONLY", args.collection_only, arg_bool=True)
library_only = get_arg("PMM_LIBRARIES_ONLY", args.library_only, arg_bool=True)
collections = get_arg("PMM_COLLECTIONS", args.collections) collections = get_arg("PMM_COLLECTIONS", args.collections)
libraries = get_arg("PMM_LIBRARIES", args.libraries) libraries = get_arg("PMM_LIBRARIES", args.libraries)
resume = get_arg("PMM_RESUME", args.resume) resume = get_arg("PMM_RESUME", args.resume)
times = get_arg("PMM_TIME", args.times) 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)
divider = get_arg("PMM_DIVIDER", args.divider) divider = get_arg("PMM_DIVIDER", args.divider)
screen_width = get_arg("PMM_WIDTH", args.width, arg_int=True) screen_width = get_arg("PMM_WIDTH", args.width, arg_int=True)
config_file = get_arg("PMM_CONFIG", args.config) debug = get_arg("PMM_DEBUG", args.debug, arg_bool=True)
trace = get_arg("PMM_TRACE", args.trace, arg_bool=True)
stats = {} stats = {}
util.separating_character = divider[0] util.separating_character = divider[0]
@ -137,6 +137,23 @@ def start(attrs):
if "time" not in attrs: if "time" not in attrs:
attrs["time"] = start_time.strftime("%H:%M") attrs["time"] = start_time.strftime("%H:%M")
attrs["time_obj"] = start_time attrs["time_obj"] = start_time
util.separator(debug=True)
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"--libraries-only (PMM_LIBRARIES_ONLY): {library_only}")
logger.debug(f"--run-collections (PMM_COLLECTIONS): {collections}")
logger.debug(f"--run-libraries (PMM_LIBRARIES): {libraries}")
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"--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}")
logger.debug("")
util.separator(f"Starting {start_type}Run") util.separator(f"Starting {start_type}Run")
config = None config = None
global stats global stats
@ -193,6 +210,7 @@ def update_libraries(config):
logger.debug(f"Sync Mode: {library.sync_mode}") logger.debug(f"Sync Mode: {library.sync_mode}")
logger.debug(f"Collection Minimum: {library.collection_minimum}") logger.debug(f"Collection Minimum: {library.collection_minimum}")
logger.debug(f"Delete Below Minimum: {library.delete_below_minimum}") logger.debug(f"Delete Below Minimum: {library.delete_below_minimum}")
logger.debug(f"Delete Not Scheduled: {library.delete_not_scheduled}")
logger.debug(f"Missing Only Released: {library.missing_only_released}") logger.debug(f"Missing Only Released: {library.missing_only_released}")
logger.debug(f"Only Filter Missing: {library.only_filter_missing}") logger.debug(f"Only Filter Missing: {library.only_filter_missing}")
logger.debug(f"Show Unmanaged: {library.show_unmanaged}") logger.debug(f"Show Unmanaged: {library.show_unmanaged}")

Loading…
Cancel
Save