Skip to content

Commit 7e79629

Browse files
authored
Merge pull request #167 from Drazzilb08/dev
v1.2.1
2 parents 1c02c89 + d98e54c commit 7e79629

File tree

5 files changed

+58
-62
lines changed

5 files changed

+58
-62
lines changed

README.md

+16
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,22 @@ I do my best to keep up with everything
2323
2. 0.X.0 versions are minor changes
2424
3. X.0.0 versions are major changes
2525

26+
## Schema Validation
27+
28+
### Overview
29+
30+
Schema validation is a method to ensure that data follows a predefined structure, data types, and constraints set by a Schema document. It compares the document against the schema rules, highlighting any deviations from the expected format or content.
31+
32+
### How to use it
33+
34+
- If you haven't already, install [VSCode](https://code.visualstudio.com/docs/setup/setup-overview).
35+
- Install the [YAML extension](https://marketplace.visualstudio.com/items?itemName=redhat.vscode-yaml)
36+
- Include the following line at the top of your config file (already present if you're modifying the config sample):
37+
```yaml
38+
# yaml-language-server: $schema=https://raw.githubusercontent.com/Drazzilb08/daps/master/schemas/config-schema.json
39+
```
40+
- Once added, any invalid fields or values will be flagged as errors, and hovering over the fields will provide descriptions.
41+
2642
## Submitting Pull Requests
2743

2844
Please feel free to make a pull request if you see something that could be improved. I'm always looking for ways to make my scripts better.

VERSION

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
1.2.0
1+
1.2.1

config/config.sample.yml

+8-6
Original file line numberDiff line numberDiff line change
@@ -216,11 +216,13 @@ border_replacerr:
216216
border_width: 26
217217
# skip - This will skip border replacement until the next schedule/holiday
218218
skip: false
219-
# fix light mm2k posters so no black bar shows at the bottom
219+
# The exclusion list is ideal to fix those pesky posters that MM2K makes (or others) that don't fit the normal scheme of the black gradient at the bottom
220+
# This will omit the black border at the bottom of the poster that gets made on most posters and remove all borders
221+
# Below are a few examples of certain posters that don't fit the normal scheme
222+
# NOte it is not recommended/supported to use the exclusion list with series posters
220223
exclusion_list:
221224
# - "Fall (2022)"
222225
# - "Inglourious Basterds (2009)"
223-
# - "True Detective (2014) - Season 1"
224226
# Setting a border color of nothing will remove the border, else it will add the border color
225227
# Examples: Must include everything from double quotes to double quotes such as "#FF0000"
226228
# "#FF0000" - Red
@@ -431,13 +433,13 @@ bash_scripts:
431433
nohl_bash:
432434
source:
433435
include:
434-
-
435-
-
436+
- /data/include1
437+
- /data/include2
436438
# Exclude certain movie/series folders from being searched
437439
# NOTE: It must be exactly as the folder is listed in your file system
438440
exclude:
439-
-
440-
-
441+
- /data/exclude1
442+
- /data/exclude2
441443
jduparr:
442444
data_dir:
443445
# Silences notifications if no duplicates are found

modules/border_replacerr.py

+19-51
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616

1717
import os
1818
import json
19-
from os.path import dirname
2019
import re
2120
import logging
2221
import filecmp
@@ -112,7 +111,7 @@ def convert_to_rgb(hex_color, logger):
112111
return (255, 255, 255)
113112
return color_code
114113

115-
def fix_borders(assets_dict, script_config, border_colors, destination_dir, dry_run, logger):
114+
def fix_borders(assets_dict, script_config, border_colors, destination_dir, dry_run, logger, exclusion_list):
116115
"""
117116
Replaces the border on the posters.
118117
@@ -128,7 +127,6 @@ def fix_borders(assets_dict, script_config, border_colors, destination_dir, dry_
128127

129128
# Extracting necessary parameters from the script config
130129
border_width = script_config['border_width']
131-
exclusion_list = script_config['exclusion_list']
132130
rgb_border_colors = []
133131

134132
# Convert border colors to RGB format if available
@@ -173,6 +171,12 @@ def fix_borders(assets_dict, script_config, border_colors, destination_dir, dry_
173171
else:
174172
year = ""
175173

174+
excluded = False
175+
if exclusion_list:
176+
if f"{data['title']} {year}" in exclusion_list:
177+
excluded = True
178+
logger.debug(f"Excluding {data['title']} {year}")
179+
176180
# Prepare output directory for saving processed files
177181
if path:
178182
path_basename = os.path.basename(path)
@@ -200,7 +204,7 @@ def fix_borders(assets_dict, script_config, border_colors, destination_dir, dry_
200204
if rgb_border_color:
201205
results = replace_border(input_file, output_path, rgb_border_color, border_width, logger)
202206
else:
203-
results = remove_border(input_file, output_path, border_width, exclusion_list, logger)
207+
results = remove_border(input_file, output_path, border_width, logger, excluded)
204208
if results:
205209
if path:
206210
messages.append(f"{action} {data['title']}{year} - {file_name}")
@@ -279,75 +283,38 @@ def replace_border(input_file, output_path, border_colors, border_width, logger)
279283
logger.error(f"Error processing {input_file}")
280284
return False
281285

282-
def remove_border(input_file, output_path, border_width, exclusion_list, logger):
286+
def remove_border(input_file, output_path, border_width, logger, exclude):
283287
"""
284288
Crops the center of an image, reducing its dimensions by 50 pixels on each side.
285289
286290
Args:
287291
input_file (str): The input file.
288292
output_path (str): The output path.
289293
border_width (int): The border width.
290-
exclusion_list (list): Light posters to exclude from having a black border on the bottom
291294
Returns:
292295
bool: True if the file was saved, False otherwise.
293296
"""
294297

295-
def format_season(string):
296-
return re.sub(r'Season0*(\d+)', r'Season \1', string)
297-
298-
if exclusion_list is None:
299-
exclusion_list = []
300-
301298
# Open the image
302299
try:
303300
with Image.open(input_file) as image: # Open the image
304301
# Set the border width
305302
width, height = image.size # Get the width and height of the image
306-
# Remove top, left, and right borders, and replace bottom border with black
307-
file_name = os.path.basename(input_file)
308-
name_without_extension, extension = os.path.splitext(file_name)
309-
# Format for no asset folders
310-
parts = name_without_extension.split('_')
311-
# Check if list is greater > 2 indicating season file, if not return None
312-
if len(parts)>= 2:
313-
name_without_season, season = parts
314-
else:
315-
name_without_season = parts[0]
316-
season = None
317-
if season is not None:
318-
formatted_season = format_season(season)
319-
# Create variable to match exclusion_list format
320-
formatted_name_without_season = f"{name_without_season} - {formatted_season}"
321-
else:
322-
formatted_name_without_season = None
323303

324-
# Format for asset folders
325-
directory_path = os.path.dirname(input_file)
326-
parent_dir_name = os.path.basename(directory_path)
327-
formatted_name_without_extension = format_season(name_without_extension)
328-
# Create variable to match exclusion_list format
329-
folder_season_file_name = f"{parent_dir_name} - {formatted_name_without_extension}"
330-
331-
# Check asset folders for exclusion list match
332-
if folder_season_file_name in exclusion_list and "Season" in name_without_extension: # season file name
333-
final_image = image.crop((border_width, border_width, width - border_width, height - border_width))
334-
elif parent_dir_name in exclusion_list and "Season" not in name_without_extension: # poster/series file name
335-
final_image = image.crop((border_width, border_width, width - border_width, height - border_width))
336-
337-
# Check formatted file name against exclusion list if asset folders is false
338-
elif name_without_extension in exclusion_list: # poster/series file name
339-
final_image = image.crop((border_width, border_width, width - border_width, height - border_width))
340-
elif formatted_name_without_season in exclusion_list: # season file name
341-
final_image = image.crop((border_width, border_width, width - border_width, height - border_width))
342-
# Not an exclusion
343-
else:
304+
# Remove top, left, and right borders, and replace bottom border with black
305+
if not exclude:
344306
final_image = image.crop((border_width, border_width, width - border_width, height)) # Crop the image to remove the borders
345307
bottom_border = Image.new("RGB", (width - 2 * border_width, border_width), color='black') # Create a black image for the bottom border
346308
bottom_border_position = (0, height - border_width - border_width) # Position the bottom border 25 pixels from the bottom
347309
final_image.paste(bottom_border, bottom_border_position) # Paste the black bottom border at the specified position
310+
else:
311+
# Remove all borders
312+
final_image = image.crop((border_width, border_width, width - border_width, height - border_width)) # Crop the image to remove the borders
348313

349314
# Resize the image to 1500x1000
350315
final_image = final_image.resize((1000, 1500)).convert("RGB")
316+
317+
file_name = os.path.basename(input_file)
351318
final_path = f"{output_path}/{file_name}" # Set the output path to the parent directory
352319

353320
if os.path.isfile(final_path):
@@ -464,6 +431,7 @@ def process_files(source_dirs, destination_dir, dry_run, log_level, script_confi
464431
schedule = script_config.get('schedule', None)
465432
border_colors = script_config.get('border_colors', None)
466433
skip = script_config.get('skip', False)
434+
exclusion_list = script_config.get('exclusion_list', None)
467435

468436
# Convert single string border color to a list if necessary
469437
border_colors = [border_colors] if isinstance(border_colors, str) else border_colors
@@ -536,7 +504,7 @@ def process_files(source_dirs, destination_dir, dry_run, log_level, script_confi
536504
logger.debug(f"assets_dict:\n{json.dumps(assets_dict, indent=4)}")
537505

538506
# Fix borders for assets using specified configurations
539-
messages = fix_borders(assets_dict, script_config, border_colors, destination_dir, dry_run, logger)
507+
messages = fix_borders(assets_dict, script_config, border_colors, destination_dir, dry_run, logger, exclusion_list)
540508
logger.debug(f"messages:\n{json.dumps(messages, indent=4)}")
541509

542510
# If there are messages (indicating processed files), log each message
@@ -589,4 +557,4 @@ def main(config):
589557
logger.error(f"\n\nAn error occurred:\n", exc_info=True)
590558
logger.error(f"\n\n")
591559
finally:
592-
logger.info(create_bar(f"END {name}"))
560+
logger.info(create_bar(f"END {name}"))

schemas/config-schema.json

+14-4
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,13 @@
55
"definitions": {
66
"run": {
77
"type": "string",
8-
"pattern": "^run$"
8+
"enum": [
9+
"run"
10+
]
911
},
1012
"hourly": {
1113
"type": "string",
12-
"pattern": "^hourly\\([0-5][0-9]\\)$"
14+
"pattern": "^hourly\\((?:[01]?[0-9]|2[0-3])\\)$"
1315
},
1416
"daily": {
1517
"type": "string",
@@ -51,7 +53,7 @@
5153
"type": "null"
5254
}
5355
],
54-
"description": "A schedule of either run, hourly, daily, weekly, monthly, or cron. If null, the task will not be scheduled.\nExamples:\nrun\nhourly(30)\ndaily(12:23)\ndaily(10:18|12:23)\nweekly(monday@12:00)\nmonthly(15@12:00)\ncron(0 0 * * *)"
56+
"description": "A schedule of either run, hourly, daily, weekly, monthly, or cron. If null, the task will not be scheduled.\nExamples:\nrun\nhourly(10)\ndaily(12:23)\ndaily(10:18|12:23)\nweekly(monday@12:00)\nmonthly(15@12:00)\ncron(0 0 * * *)"
5557
},
5658
"instance": {
5759
"type": "object",
@@ -77,7 +79,12 @@
7779
},
7880
"logLevel": {
7981
"type": "string",
80-
"pattern": "^debug|info|warning|error$"
82+
"enum": [
83+
"debug",
84+
"info",
85+
"warning",
86+
"error"
87+
]
8188
},
8289
"stringOrNull": {
8390
"type": [
@@ -355,6 +362,9 @@
355362
"source_dirs": {
356363
"$ref": "#/definitions/uniqueArray"
357364
},
365+
"exclusion_list": {
366+
"$ref": "#/definitions/uniqueArray"
367+
},
358368
"destination_dir": {
359369
"type": "string"
360370
},

0 commit comments

Comments
 (0)