Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/dev' into feat/improved-series…
Browse files Browse the repository at this point in the history
…-searching + fix bug in season filtering
  • Loading branch information
washedszn committed Jul 7, 2024
2 parents 90b114c + ad655f4 commit a3ea7da
Show file tree
Hide file tree
Showing 12 changed files with 91 additions and 44 deletions.
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.2.1
1.2.2
14 changes: 13 additions & 1 deletion config/config.sample.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ instances:
api: abcdefghijklmnopqrstuvwxyz1234567890
sonarr:
# Instance name can be whatever you want, it just needs to match the name used in other sections
sonarr_1:
sonarr_1:
url: http://localhost:8989
api: abcdefghijklmnopqrstuvwxyz1234567890
sonarr_anime:
Expand Down Expand Up @@ -314,6 +314,13 @@ poster_cleanarr:
library_names:
- Movies
- Anime Movies
ignore_media:
- "Random Movie in assets you want to keep (1999)"
- "Random Series in assets you want to keep (1999)"
- "The Matrix (1999)"
- "The Lion King (1994)"
- "Friends (1994)"
- "The Simpsons (1989)"
ignore_collections:
- "Random Collection in assets you want to keep"
# If using poster_renamer with border_replacer, include the tmp folder that border_replacer uses
Expand All @@ -328,22 +335,27 @@ upgradinatorr:
radarr_1:
count: 3
tag_name: checked
ignore_tag: ignore
unattended: true
radarr_2:
count: 10
tag_name: checked
ignore_tag: ignore
unattended: true
sonarr_1:
count: 1
tag_name: checked
ignore_tag: ignore
unattended: true
sonarr_anime:
count: 1
tag_name: checked
ignore_tag: ignore
unattended: true
sonarr_3:
count: 20
tag_name: checked
ignore_tag: ignore
unattended: true

renameinatorr:
Expand Down
7 changes: 5 additions & 2 deletions modules/border_replacerr.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,17 +61,20 @@ def check_holiday(data, border_colors, logger):
# Iterate through each holiday and its corresponding schedule and color in the data
for holiday, schedule_color in data.items():
schedule = schedule_color.get('schedule', None)

# If schedule exists for the holiday
if schedule:

# Check if the schedule matches the range pattern
if re.match(pattern, schedule):

# If 'check_schedule' returns True (indicating successful execution)
if check_schedule(script_name, schedule, logger):
# Retrieve the color for the holiday from schedule_color or use default border_colors
holiday_colors = schedule_color.get('color', border_colors)

# If holiday color is string convert to list
if isinstance(holiday_colors, str):
holiday_colors = [holiday_colors]
# If holiday_colors exist, log the schedule execution and colors being used
if holiday_colors:
table = [
Expand Down
2 changes: 0 additions & 2 deletions modules/labelarr.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,6 @@ def sync_to_plex(plex, data_dict, instance_type, logger):
None
"""

logger.info(f"Syncing labels to Plex")

# Loop through each item in the data_dict
for item in data_dict:
if instance_type == "sonarr":
Expand Down
9 changes: 7 additions & 2 deletions modules/poster_cleanarr.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@

script_name = "poster_cleanarr"

def match_assets(assets_list, media_dict):
def match_assets(assets_list, media_dict, ignore_media):
"""
Match assets to media.
Expand Down Expand Up @@ -99,6 +99,9 @@ def match_assets(assets_list, media_dict):
break
# If no match is found, add the asset to unmatched assets based on media type
if not matched:
if f"{asset_data['title']} ({asset_data['year']})" in ignore_media:
print(f"{asset_data['title']} ({asset_data['year']}) is in ignore_media, skipping...")
continue
unmatched_assets.append({
'title': asset_data['title'],
'year': asset_data['year'],
Expand Down Expand Up @@ -245,6 +248,7 @@ def main(config):
library_names = script_config.get('library_names', [])
source_dirs = script_config.get('source_dirs', [])
instances = script_config.get('instances', None)
ignore_media = script_config.get('ignore_media', [])

# Log script settings for debugging purposes
table = [
Expand All @@ -256,6 +260,7 @@ def main(config):
logger.debug(f'{"Assets paths:":<20}{source_dirs}')
logger.debug(f'{"Library names:":<20}{library_names}')
logger.debug(f'{"Instances:":<20}{instances}')
logger.debug(f'{"Ignore media:":<20}{ignore_media}')
logger.debug(create_bar("-"))

source_dirs = [source_dirs] if isinstance(source_dirs, str) else source_dirs
Expand Down Expand Up @@ -321,7 +326,7 @@ def main(config):
logger.debug(f"Media:\n{json.dumps(media_dict, indent=4)}")

# Match assets with media and log the results
unmatched_dict = match_assets(assets_list, media_dict)
unmatched_dict = match_assets(assets_list, media_dict, ignore_media)
if unmatched_dict:
logger.debug(f"Unmatched:\n{json.dumps(unmatched_dict, indent=4)}")
remove_data = remove_assets(unmatched_dict, source_dirs, logger)
Expand Down
45 changes: 27 additions & 18 deletions modules/upgradinatorr.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,18 @@

script_name = "upgradinatorr"

def filter_media(media_dict, tag_id, count, season_monitored_threshold, logger):
def filter_media(media_dict, checked_tag_id, ignore_tag_id, count, season_monitored_threshold, logger):
"""
Filter media_dict to remove items that are not monitored, have the tag_id, or are not in the correct status.
Filter media_dict to remove items that are:
* not monitored
* have the checked_tag_id
* have the ignore_tag_id
* not in the correct status
Args:
media_dict (list): A list of dictionaries containing media information.
tag_id (int): The tag_id to filter out.
checked_tag_id (int): The checked_tag_id to filter out.
ignore_tag_id (int): The ignore_tag_id to filter out.
count (int): The number of items to return.
Returns:
Expand All @@ -43,14 +48,14 @@ def filter_media(media_dict, tag_id, count, season_monitored_threshold, logger):
for item in media_dict:
if filter_count == count: # Check if the desired count has been reached
break
# Check conditions: tag_id not in tags, monitored is True, and status is one of the specified statuses
if tag_id in item['tags'] or item['monitored'] == False or item['status'] not in ["continuing", "airing", "ended", "canceled", "released"]:
# Check conditions: checked_tag_id not in tags, ignore_tag_id not in tags, monitored is True, and status is one of the specified statuses
if checked_tag_id in item['tags'] or ignore_tag_id in item['tags'] or item['monitored'] == False or item['status'] not in ["continuing", "airing", "ended", "canceled", "released"]:
# Log skipped items
logger.debug(f"Skipping {item['title']} ({item['year']}), Status: {item['status']}, Monitored: {item['monitored']}, Tags: {item['tags']}")
continue # Move to the next item if conditions are not met
# Check number of monitored episodes within a season
series_monitored = False
if item['seasons']:
series_monitored = False
for i, season in enumerate(item['seasons']):
monitored_count = 0
for episode in season['episode_data']:
Expand All @@ -63,9 +68,10 @@ def filter_media(media_dict, tag_id, count, season_monitored_threshold, logger):
logger.debug(f"{item['title']}, Season {i} unmonitored. Reason: monitored percentage {monitored_percentage} less than season_monitored_threshold {season_monitored_threshold}")
if item['seasons'][i]['monitored']:
series_monitored = True
if series_monitored == False:
logger.debug(f"Skipping {item['title']} ({item['year']}), Status: {item['status']}, Monitored: {item['monitored']}, Tags: {item['tags']}")
continue
# Skip if all seasons are unmonitored
if series_monitored == False:
logger.debug(f"Skipping {item['title']} ({item['year']}), Status: {item['status']}, Monitored: {item['monitored']}, Tags: {item['tags']}")
continue
filtered_media_dict.append(item) # Append the item to the filtered list
filter_count += 1 # Increment the counter for filtered items
return filtered_media_dict # Return the filtered list of media
Expand Down Expand Up @@ -125,7 +131,8 @@ def process_instance(instance_type, instance_settings, app, logger):
total_count = 0
server_name = app.get_instance_name()
count = instance_settings.get('count', 2)
tag_name = instance_settings.get('tag_name', "checked")
checked_tag_name = instance_settings.get('tag_name', "checked")
ignore_tag_name = instance_settings.get('ignore_tag', "ignore")
unattended = instance_settings.get('unattended', False)
# default 0 means that a season will NOT be unmonitored if all episodes ARE unmonitored
season_monitored_threshold = instance_settings.get('season_monitored_threshold', 0)
Expand All @@ -136,7 +143,8 @@ def process_instance(instance_type, instance_settings, app, logger):
]
logger.debug(create_table(table))
logger.debug(f'{"Count:":<20}{count}')
logger.debug(f'{"tag_name:":<20}{tag_name}')
logger.debug(f'{"checked_tag_name:":<20}{checked_tag_name}')
logger.debug(f'{"ignore_tag_name:":<20}{checked_tag_name}')
logger.debug(f'{"unattended:":<20}{unattended}')
if instance_type == 'sonarr':
logger.debug(f'{"season_monitored_threshold:":<20}{season_monitored_threshold}')
Expand All @@ -149,16 +157,17 @@ def process_instance(instance_type, instance_settings, app, logger):
logger.debug(f"media_dict:\n{json.dumps(media_dict, indent=4)}")

# Get tag ID based on the provided tag name
tag_id = app.get_tag_id_from_name(tag_name)
checked_tag_id = app.get_tag_id_from_name(checked_tag_name)
ignore_tag_id = app.get_tag_id_from_name(ignore_tag_name)

# Filter media based on tag and count criteria
filtered_media_dict = filter_media(media_dict, tag_id, count, season_monitored_threshold, logger)
filtered_media_dict = filter_media(media_dict, checked_tag_id, ignore_tag_id, count, season_monitored_threshold, logger)
if not filtered_media_dict and unattended:
media_ids = [item['media_id'] for item in media_dict]
logger.info("All media is tagged. Removing tags...")
app.remove_tags(media_ids, tag_id)
app.remove_tags(media_ids, checked_tag_id)
media_dict = handle_starr_data(app, server_name, instance_type, include_episode=True)
filtered_media_dict = filter_media(media_dict, tag_id, count, season_monitored_threshold, logger)
filtered_media_dict = filter_media(media_dict, checked_tag_id, ignore_tag_id, count, season_monitored_threshold, logger)

# If no filtered_media and not unattended return
if not filtered_media_dict and not unattended:
Expand All @@ -171,7 +180,7 @@ def process_instance(instance_type, instance_settings, app, logger):
if media_dict:
total_count = len(media_dict)
for item in media_dict:
if tag_id in item['tags']:
if checked_tag_id in item['tags']:
tagged_count += 1
else:
untagged_count += 1
Expand Down Expand Up @@ -215,8 +224,8 @@ def process_search_response(search_response, media_id):
search_response = app.search_season(item['media_id'], season['season_number'])
process_search_response(search_response, item['media_id'])

logger.debug(f"Adding tag {tag_id} to media ID: {item['media_id']}")
app.add_tags(item['media_id'], tag_id)
logger.debug(f"Adding tag {checked_tag_id} to media ID: {item['media_id']}")
app.add_tags(item['media_id'], checked_tag_id)

sleep_time = 10 # Set the sleep time to 10 seconds
print(f"Waiting for {sleep_time} seconds to allow for search results to populate in the queue...")
Expand Down
8 changes: 8 additions & 0 deletions schemas/config-schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -464,6 +464,10 @@
"library_names": {
"$ref": "#/definitions/uniqueArray"
},
"ignore_media":
{
"type":"string"
},
"ignore_collections": {
"$ref": "#/definitions/uniqueArray"
},
Expand Down Expand Up @@ -505,6 +509,10 @@
"tag_name": {
"type": "string"
},
"ignore_tag":
{
"type": "string"
},
"unattended": {
"type": "boolean"
}
Expand Down
3 changes: 2 additions & 1 deletion scripts/rclone.sh
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ rclone sync \
--no-update-modtime \
--drive-use-trash=false \
--drive-chunk-size=512M \
--exclude=**.partial \
--check-first \
--bwlimit=80M \
--size-only \
Expand All @@ -61,4 +62,4 @@ if [ "$verbose" = false ]; then
echo
fi

exit 0
exit 0
1 change: 1 addition & 0 deletions start.sh
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ echo "Starting daps as $(whoami) running daps with UID: $PUID and GID: $PGID"

chown -R ${PUID}:${PGID} /${CONFIG_DIR} /app > /dev/null 2>&1
chmod -R 777 /${CONFIG_DIR} > /dev/null 2>&1
chmod 660 /${CONFIG_DIR}/config.yml > /dev/null 2>&1

# Run main.py as the dockeruser
exec su -s /bin/bash -c "python3 /app/main.py" dockeruser
16 changes: 6 additions & 10 deletions util/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,18 +46,14 @@ def load_config(self):
"""
# Open the YAML config file and load its contents
try:
try:
with open(self.config_path, "r") as file:
config = yaml.safe_load(file)
except FileNotFoundError:
print(f"Config file not found at {self.config_path}")
return
except yaml.parser.ParserError as e:
print(f"Error parsing config file: {e}")
return
with open(self.config_path, "r") as file:
config = yaml.safe_load(file)
except FileNotFoundError:
print(f"Config file not found at {self.config_path}")
return
except yaml.parser.ParserError as e:
print(f"Error parsing config file: {e}")
return

# Set various attributes from the loaded config
self.instances_config = config['instances'] # Instance configurations
Expand All @@ -81,4 +77,4 @@ def load_config(self):
self.sonarr_config = self.instances_config.get('sonarr', {}) # Sonarr configurations
self.qbit_config = self.instances_config.get('qbittorrent', {}) # qBittorrent configurations
self.plex_config = self.instances_config.get('plex', {}) # Plex configurations


7 changes: 3 additions & 4 deletions util/scheduler.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,9 @@ def check_schedule(script_name, schedule, logger):
start, end = start_end.split("-")
start_month, start_day = map(int, start.split("/"))
end_month, end_day = map(int, end.split("/"))
current_month, current_day = map(int, now.strftime("%m/%d").split("/"))

if start_month <= current_month <= end_month and start_day <= current_day <= end_day:
start_date = datetime(now.year, start_month, start_day)
end_date = datetime(now.year, end_month, end_day)
if start_date <= now <= end_date:
return True
elif frequency == "cron":
local_tz = tz.tzlocal()
Expand All @@ -80,7 +80,6 @@ def check_schedule(script_name, schedule, logger):
next_run_times[script_name] = next_run

logger.debug(f"Next run for {script_name}: {next_run}\n")

return True
else:
logger.debug(f"Next run time for script {script_name}: {next_run} is in the future\n")
Expand Down
21 changes: 18 additions & 3 deletions util/utility.py
Original file line number Diff line number Diff line change
Expand Up @@ -568,11 +568,20 @@ def handle_starr_data(app, server_name, instance_type, include_episode=False):
'episode_id': episode['id'],
'has_file': episode['hasFile'],
}) # Append episode data to the episode dictionary
# Check if season is complete
try:
status = season['statistics']['episodeCount'] == season['statistics']['totalEpisodeCount']
except:
status = False
try:
season_stats = season['statistics']['episodeCount']
except:
season_stats = 0
season_list.append({
'season_number': season['seasonNumber'],
'monitored': season['monitored'],
'season_pack': season['statistics']['episodeCount'] == season['statistics']['totalEpisodeCount'],
'season_has_episodes': season['statistics']['episodeCount'] > 0,
'season_pack': status,
'season_has_episodes': season_stats,
'episode_data': episode_list if include_episode else [],
}) # Append season data to the season dictionary

Expand All @@ -589,6 +598,12 @@ def handle_starr_data(app, server_name, instance_type, include_episode=False):
else:
title = item['title']
year = item['year']
# Check windows path
reg = re.match(r"^([A-Z]:\\)", item['path'])
if reg and reg.group(1):
folder = item['path'][item['path'].rfind("\\")+1:]
else:
folder = os.path.basename(os.path.normpath(item['path']))
# Construct a dictionary for each item and append it to media_dict
media_dict.append({
'title': title,
Expand All @@ -606,7 +621,7 @@ def handle_starr_data(app, server_name, instance_type, include_episode=False):
'alternate_titles': alternate_titles,
'normalized_alternate_titles': normalized_alternate_titles,
'file_id': file_id if instance_type == "radarr" else None,
'folder': os.path.basename(os.path.normpath(item['path'])),
'folder': folder,
'has_file': item['hasFile'] if instance_type == "radarr" else None,
'tags': item['tags'],
'seasons': season_list if instance_type == "sonarr" else None, # Add season_list for Sonarr items
Expand Down

0 comments on commit a3ea7da

Please sign in to comment.