Skip to content

Commit

Permalink
Merge pull request #150 from Drazzilb08/dev
Browse files Browse the repository at this point in the history
Merge to master
  • Loading branch information
Drazzilb08 authored Apr 1, 2024
2 parents 235e5ad + 5242b30 commit 7a5ec58
Show file tree
Hide file tree
Showing 14 changed files with 111 additions and 756 deletions.
2 changes: 1 addition & 1 deletion Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ requests = "*"
tqdm = "*"
pyyaml = "*"
unidecode = "*"
qbittorrent-api = "*"
plexapi = "*"
pillow = "*"
prettytable = "*"
croniter = "*"
python-dateutil = "*"
pathvalidate = "*"

[dev-packages]

Expand Down
20 changes: 6 additions & 14 deletions Pipfile.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.0.5
1.1.2
38 changes: 2 additions & 36 deletions config/config.sample.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ schedule:
sync_gdrive:
poster_cleanarr:
poster_renamerr:
queinatorr:
renameinatorr:
unmatched_assets:
upgradinatorr:
Expand Down Expand Up @@ -69,16 +68,6 @@ instances:
# API key can be found here: https://support.plex.tv/articles/204059436-finding-an-authentication-token-x-plex-token/
url: http://localhost:32400
api: abcdefghijklmnopqrstuvwxyz1234567890
qbittorrent:
# Instance name can be whatever you want, it just needs to match the name used in other sections
qbittorrent_1:
url: http://localhost:8080
username: admin
password: adminadmin
qbittorrent_2:
url:
username:
password:

discord:
# Discord notifications:
Expand Down Expand Up @@ -110,10 +99,6 @@ discord:
# Will notify if non-hardlinked files are found/searched for
discord_webhook:
channel_id:
queinatorr:
# Will notify if a torrent/queue item has been handled
discord_webhook:
channel_id:
labelarr:
# Will notify if a label has been added/removed to a movie or series
discord_webhook:
Expand Down Expand Up @@ -396,27 +381,6 @@ nohl:
- Marvel's Spider-Man
- M*A*S*H

queinatorr:
# This script will move torrents from one category to another in qBittorrent based on
# the title of the torrent. This is useful for moving torrents from a category that are stuck
# in a queue due to a missing file or not being an upgrade for existing episode file(s).
log_level: info
dry_run: true
days_to_keep: 14 # The number of days to keep in the pre_import_category prior to moving to the post_import_category
instances:
radarr_1:
qbit_instance: qbittorrent_1
pre_import_category: movies
post_import_category: completed-movies
sonarr_1:
qbit_instance: qbittorrent_2
pre_import_category: series
post_import_category: completed-series
sonarr_anime:
qbit_instance: qbittorrent_2
pre_import_category: anime
post_import_category: completed-anime

labelarr:
# A script to sync labels between Plex and Radarr/Sonarr
# Warning: Due to the way that Plex API works, this script can take a while to run with a large library
Expand Down Expand Up @@ -467,6 +431,8 @@ bash_scripts:
-
jduparr:
data_dir:
# Silences notifications if no duplicates are found
silent: false

main:
log_level: info
1 change: 0 additions & 1 deletion main.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
"nohl",
"poster_cleanarr",
"poster_renamerr",
"queinatorr",
"renameinatorr",
"sync_gdrive",
"upgradinatorr",
Expand Down
61 changes: 4 additions & 57 deletions modules/bash_scripts.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,57 +29,28 @@ def set_cmd_args(settings, bash_script_file, logger, script_name):
if discord_check(script_name):
webhook_url, channel = get_discord_data(script_name, logger)
if settings:
script_debug = str(settings.get('debug')) if 'debug' in settings else None

source = str(settings.get('source')) if 'source' in settings else None
destination = str(settings.get('destination')) if 'destination' in settings else None
keep_backups = str(settings.get('keep_backups')) if 'keep_backups' in settings else None
compress = str(settings.get('compress')) if 'compress' in settings else None
data_dir = str(settings.get('data_dir')) if 'data_dir' in settings else None
include = list(settings.get('include')) if 'include' in settings else None
exclude = list(settings.get('exclude')) if 'exclude' in settings else None
silent = settings.get('silent') if 'silent' in settings else None

keep_essential = str(settings.get('keep_essential')) if 'keep_essential' in settings else None
keep_full = str(settings.get('keep_full')) if 'keep_full' in settings else None
force_full_Backup = str(settings.get('force_full_backup')) if 'force_full_backup' in settings else None
script_dry_run = str(settings.get('dry_run')) if 'dry_run' in settings else None
shutdown_plex = str(settings.get('shutdown_plex')) if 'shutdown_plex' in settings else None
full_backup = str(settings.get('full_backup')) if 'full_backup' in settings else None

logger.debug(f"channel: {channel}")
logger.debug(f"webhook_url: {webhook_url}")
logger.debug(f"source: {source}")
logger.debug(f"destination: {destination}")
logger.debug(f"keep_backups: {keep_backups}")
logger.debug(f"compress: {compress}")
logger.debug(f"keep_essential: {keep_essential}")
logger.debug(f"keep_full: {keep_full}")
logger.debug(f"force_full_Backup: {force_full_Backup}")
logger.debug(f"script_dry_run: {script_dry_run}")
logger.debug(f"shutdown_plex: {shutdown_plex}")
logger.debug(f"script_debug: {script_debug}")
logger.debug(f"full_backup: {full_backup}")
logger.debug(f"webhook_url: {webhook_url}")
logger.debug(f"channel: {channel}")
logger.debug(f"script_name: {script_name}")
logger.debug(f"settings: {settings}")
logger.debug(f"bash_script_file: {bash_script_file}")
logger.debug(f"include: {include}")
logger.debug(f"exclude: {exclude}")
logger.debug(f"Silent: {silent}")

if source:
cmd.append('-s')
cmd.append(shlex.quote(str(source)))
if destination:
cmd.append('-d')
cmd.append(shlex.quote(str(destination)))
if keep_backups:
cmd.append('-k')
cmd.append(shlex.quote(str(keep_backups)))

if compress:
cmd.append('-c')
cmd.append(shlex.quote(str(compress)))

if webhook_url:
cmd.append('-w')
Expand All @@ -89,34 +60,10 @@ def set_cmd_args(settings, bash_script_file, logger, script_name):
cmd.append('-C')
cmd.append(shlex.quote(str(channel)))

if keep_essential:
cmd.append('-k')
cmd.append(shlex.quote(str(keep_essential)))

if keep_full:
cmd.append('-K')
cmd.append(shlex.quote(str(keep_full)))

if force_full_Backup:
cmd.append('-F')
cmd.append(shlex.quote(str(force_full_Backup)))

if full_backup:
cmd.append('-f')
cmd.append(shlex.quote(str(full_backup)))

if script_dry_run:
cmd.append('-r')
cmd.append(shlex.quote(str(script_dry_run)))

if shutdown_plex:
if silent is not None:
cmd.append('-S')
cmd.append(shlex.quote(str(shutdown_plex)))
cmd.append(shlex.quote(str(silent)))

if script_debug:
cmd.append('-D')
cmd.append(shlex.quote(str(script_debug)))

if data_dir:
cmd.append('-D')
cmd.append(shlex.quote(str(data_dir)))
Expand Down
83 changes: 50 additions & 33 deletions modules/poster_renamerr.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
try:
from plexapi.server import PlexServer
from tqdm import tqdm
from pathvalidate import sanitize_filename, is_valid_filename
except ImportError as e:
print(f"ImportError: {e}")
print("Please install the required modules with 'pip install -r requirements.txt'")
Expand Down Expand Up @@ -94,6 +95,28 @@ def get_assets_files(source_dirs, logger):

return final_assets

def handle_series_match(asset, media_seasons_numbers, asset_season_numbers):
# Iterate through each file in the asset
files_to_remove = []
seasons_to_remove = []
for file in asset['files']:
# Check for season-related file naming
if re.search(r' - Season| - Specials', file):
if re.search(r"Season (\d+)", file):
season_number = int(re.search(r"Season (\d+)", file).group(1))
elif "Specials" in file:
season_number = 0
if season_number not in media_seasons_numbers:
files_to_remove.append(file)
continue
for file in files_to_remove:
asset['files'].remove(file)
for season in asset_season_numbers:
if season not in media_seasons_numbers:
seasons_to_remove.append(season)
for season in seasons_to_remove:
asset_season_numbers.remove(season)

def match_data(media_dict, asset_files):
"""
Matches media data to asset files
Expand Down Expand Up @@ -124,7 +147,7 @@ def match_data(media_dict, asset_files):
asset_data = asset_files[asset_type]
media_data = media_dict[asset_type]
# Iterate through each media entry of the current asset type
with tqdm(total=len(media_data), desc=f"Matching {asset_type}", unit="media", leave=True, disable=None) as pbar_inner:
with tqdm(total=len(media_data), desc=f"Matching {asset_type}", leave=True, disable=None) as pbar_inner:
for media in media_data:
matched = False
if asset_type == 'series':
Expand All @@ -136,36 +159,25 @@ def match_data(media_dict, asset_files):
matched = True # Set flag to indicate a match
asset_season_numbers = asset.get('season_numbers', None)
if asset_type == "series":
# Iterate through each file in the asset
files_to_remove = []
seasons_to_remove = []
for file in asset['files']:
# Check for season-related file naming
if re.search(r' - Season| - Specials', file):
if re.search(r"Season (\d+)", file):
season_number = int(re.search(r"Season (\d+)", file).group(1))
elif "Specials" in file:
season_number = 0
if season_number not in media_seasons_numbers:
files_to_remove.append(file)
continue
for file in files_to_remove:
asset['files'].remove(file)
for season in asset_season_numbers:
if season not in media_seasons_numbers:
seasons_to_remove.append(season)
for season in seasons_to_remove:
asset_season_numbers.remove(season)

# Store matched data in the matched dictionary
matched_dict.append({
'title': media['title'],
'year': media['year'],
'folder': media['folder'],
'files': asset['files'],
'seasons_numbers': asset_season_numbers,
})
break # Break loop after finding a match
handle_series_match(asset, media_seasons_numbers, asset_season_numbers)
break
if not matched:
for asset in asset_data:
if is_match_alternate(asset, media):
matched = True
asset_season_numbers = asset.get('season_numbers', None)
if asset_type == "series":
handle_series_match(asset, media_seasons_numbers, asset_season_numbers)
break

if matched:
matched_dict.append({
'title': media['title'],
'year': media['year'],
'folder': media['folder'],
'files': asset['files'],
'seasons_numbers': asset_season_numbers,
})

if not matched:
# If no match is found, add to unmatched dictionary
Expand Down Expand Up @@ -264,7 +276,8 @@ def rename_files(matched_assets, script_config, logger):

# Remove any OS illegal characters from the file name
if asset_type == "collections":
folder = re.sub(r'[<>:"/\\|?*]', '', folder.replace('/', ''))
if not is_valid_filename(folder):
folder = sanitize_filename(folder)

# Handle asset_folders configuration
if asset_folders:
Expand All @@ -282,7 +295,11 @@ def rename_files(matched_assets, script_config, logger):

# Check for season-related file naming
if re.search(r' - Season| - Specials', file_name):
season_number = (re.search(r"Season (\d+)", file_name).group(1) if "Season" in file_name else "00").zfill(2)
try:
season_number = (re.search(r"Season (\d+)", file_name).group(1) if "Season" in file_name else "00").zfill(2)
except AttributeError:
logger.debug(f"Error extracting season number from {file_name}")
continue
if asset_folders:
new_file_name = f"Season{season_number}{file_extension}"
else:
Expand Down
Loading

0 comments on commit 7a5ec58

Please sign in to comment.