Skip to content

Commit

Permalink
Merge pull request #170 from Kometa-Team/169-fr-enhance-logic-for-mor…
Browse files Browse the repository at this point in the history
…e-customizations-with-libraries-section
  • Loading branch information
bullmoose20 authored Jan 16, 2025
2 parents 37aebeb + 06cfbd0 commit 3f1297b
Show file tree
Hide file tree
Showing 6 changed files with 495 additions and 181 deletions.
262 changes: 182 additions & 80 deletions modules/output.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,39 +28,10 @@ def section_heading(title):
return add_border_to_ascii_art(pyfiglet.figlet_format(title))


def load_yaml_template(template_path="library_template.yml"):
"""
Load the YAML template for a library section.
"""
yaml = YAML()
with open(template_path, "r") as file:
return yaml.load(file)


def generate_library_sections_simple(
selected_libraries, template_path="templates/library_template.yml"
):
def clean_section_data(section_data, config_attribute):
"""
Generate YAML entries for selected libraries by reading the template as plain text
and replacing LIBRARYNAME with each selected library.
Cleans out temporary or irrelevant data before integrating it into the final config.
"""
library_sections = []
with open(template_path, "r") as template_file:
template_content = template_file.read()

for library in selected_libraries:
# Replace LIBRARYNAME with the actual library name
library_section = template_content.replace("LIBRARYNAME", library)
# Add indentation to ensure proper nesting under "libraries:"
indented_section = " " + library_section.strip().replace("\n", "\n ")
library_sections.append(indented_section)

# Construct the final output as a string
result = "libraries:\n" + "\n".join(library_sections)
return result


def clean_section_data(section_data, config_attribute):
clean_data = {}

for key, value in section_data.items():
Expand All @@ -77,19 +48,83 @@ def clean_section_data(section_data, config_attribute):
return clean_data


def build_libraries_section(
movie_libraries,
show_libraries,
movie_collections,
show_collections,
movie_overlays,
show_overlays,
movie_attributes,
show_attributes,
):
"""
Build the libraries section for the YAML config, ensuring that settings are
correctly applied to movies and shows. Exclude empty fields from the final output.
"""
libraries_section = {}

# Helper function to clean and add entries
def add_entry(library_name, library_type, collections, overlays, attributes):
entry = {}

# Process collections
collection_files = [
{"default": collection.replace(f"{library_type}-collection_", "")}
for collection, selected in collections.items()
if selected
]
if collection_files:
entry["collection_files"] = collection_files

# Process overlays
overlay_files = [
{"default": overlay.replace(f"{library_type}-overlay_", "")}
for overlay, selected in overlays.items()
if selected
]
if overlay_files:
entry["overlay_files"] = overlay_files

# Process attributes
for attr_key, attr_value in attributes.items():
clean_key = attr_key.replace(f"{library_type}-attribute_", "")
if attr_value not in [None, False, [], {}, ""]:
entry[clean_key] = attr_value

# Add only non-empty entries
if entry:
libraries_section[library_name] = entry

# Process movie libraries
for library_key, library_name in movie_libraries.items():
add_entry(
library_name, "mov", movie_collections, movie_overlays, movie_attributes
)

# Process show libraries
for library_key, library_name in show_libraries.items():
add_entry(library_name, "sho", show_collections, show_overlays, show_attributes)

return {"libraries": libraries_section}


def build_config(header_style="ascii"):
"""
Build the final configuration, including all sections and headers,
ensuring the libraries section is properly processed.
"""
sections = get_template_list()

config_data = {}
header_art = {}

# Process sections and generate header art
for name in sections:
item = sections[name]
# {'num': '001', 'file': '001-start.html', 'stem': '001-start', 'name': 'Start', 'raw_name': 'start', 'next': '010-plex', 'prev': '001-start'}
persistence_key = item["stem"]
config_attribute = item["raw_name"]

# Generate ASCII art or divider headers
if header_style == "ascii":
header_art[config_attribute] = section_heading(item["name"])
elif header_style == "divider":
Expand All @@ -99,39 +134,125 @@ def build_config(header_style="ascii"):
else:
header_art[config_attribute] = ""

# Retrieve settings for each section
section_data = retrieve_settings(persistence_key)

# {'mal': {'authorization': {'code_verifier': 'OEOOZwnH8RWLczgahkUbo__vabgHl7XyvWkDx0twLB4FCaxPY88C9tNXnmxzBq946vSekKbPc3WhW4SwWrq0ld5xKpm27foQx4RXfnXY25iL7Pm0WCCuYkO-iQga69jv', 'localhost_url': '', 'access_token': 'None', 'token_type': 'None', 'expires_in': 'None', 'refresh_token': 'None'}, 'client_id': 'Enter MyAnimeList Client ID', 'client_secret': 'Enter MyAnimeList Client Secret'}, 'valid': True}

if "validated" in section_data and section_data["validated"]:
# it's valid data and needs to end up in the config
# but first clear some chaff
# Clean and store data
clean_data = clean_section_data(section_data, config_attribute)
config_data[config_attribute] = clean_data

# Process libraries specifically
if "libraries" in config_data:
libraries_data = config_data["libraries"].get("libraries", "")

# If libraries_data is a dictionary, extract its values
if isinstance(libraries_data, dict):
libraries_data = libraries_data.get("libraries", "")

# Ensure libraries_data is a string before splitting
if isinstance(libraries_data, str):
selected_libraries = libraries_data.split(",")
else:
selected_libraries = []

selected_libraries = [lib.strip() for lib in selected_libraries if lib.strip()]

# Generate the YAML entries as a dictionary
library_sections = generate_library_sections_simple(selected_libraries)

# Directly replace config_data["libraries"] with the generated structure
yaml_loader = YAML(typ="safe", pure=True) # Initialize a YAML instance
config_data["libraries"] = yaml_loader.load(library_sections)

# Process playlist_files section
if "playlist_files" in config_data:
playlist_data = config_data["playlist_files"]

# Debug raw data
print("Raw config_data['playlist_files'] content (Level 1):", playlist_data)

# Adjust for possible extra nesting
if "playlist_files" in playlist_data and isinstance(
playlist_data["playlist_files"], dict
):
playlist_data = playlist_data["playlist_files"]
print("Adjusted playlist_data after extra nesting:", playlist_data)

# Extract and process libraries
libraries_value = playlist_data.get("libraries", "")
print("Extracted libraries value:", libraries_value)

libraries_list = [
lib.strip() for lib in libraries_value.split(",") if lib.strip()
]
print("Processed libraries list:", libraries_list)

# Format playlist_files data
formatted_playlist_files = {
"playlist_files": [
{
"default": "playlist",
"template_variables": {"libraries": libraries_list},
}
]
}
print("Formatted playlist_files data:", formatted_playlist_files)

# Replace in config_data
config_data["playlist_files"] = formatted_playlist_files

# Process the libraries section
if "libraries" in config_data and "libraries" in config_data["libraries"]:
nested_libraries_data = config_data["libraries"]["libraries"]

# Debugging
print("Raw nested libraries data:", nested_libraries_data)

# Separate data by prefix
movie_libraries = {
key: value
for key, value in nested_libraries_data.items()
if key.startswith("mov-library_")
}
show_libraries = {
key: value
for key, value in nested_libraries_data.items()
if key.startswith("sho-library_")
}
movie_collections = {
key: value
for key, value in nested_libraries_data.items()
if key.startswith("mov-collection_")
}
show_collections = {
key: value
for key, value in nested_libraries_data.items()
if key.startswith("sho-collection_")
}
movie_overlays = {
key: value
for key, value in nested_libraries_data.items()
if key.startswith("mov-overlay_")
}
show_overlays = {
key: value
for key, value in nested_libraries_data.items()
if key.startswith("sho-overlay_")
}
movie_attributes = {
key: value
for key, value in nested_libraries_data.items()
if key.startswith("mov-attribute_")
}
show_attributes = {
key: value
for key, value in nested_libraries_data.items()
if key.startswith("sho-attribute_")
}

# Debugging
print("Extracted Movie Libraries:", movie_libraries)
print("Extracted Show Libraries:", show_libraries)
print("Extracted Movie Collections:", movie_collections)
print("Extracted Show Collections:", show_collections)
print("Extracted Movie Overlays:", movie_overlays)
print("Extracted Show Overlays:", show_overlays)
print("Extracted Movie Attributes:", movie_attributes)
print("Extracted Show Attributes:", show_attributes)

# Build nested libraries structure
libraries_section = build_libraries_section(
movie_libraries,
show_libraries,
movie_collections,
show_collections,
movie_overlays,
show_overlays,
movie_attributes,
show_attributes,
)
config_data["libraries"] = libraries_section
print("Final Libraries Section:", libraries_section)

# Header comment for YAML file
header_comment = (
"### We highly recommend using Visual Studio Code with indent-rainbow by oderwat extension "
"and YAML by Red Hat extension. VSC will also leverage the above link to enhance Kometa yml edits."
Expand All @@ -154,19 +275,7 @@ def build_config(header_style="ascii"):

# Function to dump YAML sections
def dump_section(title, name, data):
# Convert 'true' and 'false' strings to boolean values
# this should be handled in the persistence
for key, value in data.items():
if value == "true":
data[key] = True
elif value == "false":
data[key] = False

# Remove 'valid' key if present
data = {k: v for k, v in data.items() if k != "valid"}

yaml = YAML()

data = {k: v for k, v in data.items() if k != "valid"} # Remove 'valid' key
with io.StringIO() as stream:
yaml.dump(data, stream)
return f"{title}\n{stream.getvalue().strip()}\n\n"
Expand Down Expand Up @@ -195,15 +304,8 @@ def dump_section(title, name, data):
if section_key in config_data:
section_data = config_data[section_key]
section_art = header_art[section_key]

yaml_content += dump_section(section_art, section_key, section_data)

print("\n==================================================\n")
print(f"config_data:\n{config_data}")
print("\n==================================================\n")
print(f"yaml_content:\n{yaml_content}")
print("\n==================================================\n")

validated = False
validation_error = None

Expand Down
Loading

0 comments on commit 3f1297b

Please sign in to comment.