Skip to content

Dependency Modernization and Metadata Writing Features#24

Open
ballaballaballa wants to merge 11 commits intojo1gi:masterfrom
ballaballaballa:master
Open

Dependency Modernization and Metadata Writing Features#24
ballaballaballa wants to merge 11 commits intojo1gi:masterfrom
ballaballaballa:master

Conversation

@ballaballaballa
Copy link

This PR introduces several improvements including dependency updates, EPUB metadata writing capabilities, and source file refactoring.

Summary

Dependency Modernization:

  • Migrate from blackboxprotobuf to bbpb (new PyPI package name, import name unchanged)
  • Replace deprecated appdirs with actively maintained platformdirs
  • Add minimum version constraints for all dependencies
  • Set requires-python = ">=3.9" for Python 3.9-3.13 compatibility
  • Make tomli conditional (only required for Python < 3.11)

New Features:

  • Add EPUB metadata writing support for Storytel and Nextory
  • Allow metadata writing to be triggered via command-line parameter or config file
  • Add configurable output path option

Refactoring:

  • Refactor Storytel source file for improved maintainability
  • Refactor Nextory source file for improved maintainability

Documentation:

  • Update README with correct config file paths

Changes by File

  • Dependencies (pyproject.toml, shell.nix): Updated package names and added version constraints
  • Config (grawlix/config.py): Migrated to platformdirs, added output path configuration
  • New modules: grawlix/epub_metadata.py, grawlix/epub_metadata_writers.py
  • CLI (grawlix/__main__.py, grawlix/arguments.py): Added metadata writing options
  • Sources (grawlix/sources/storytel.py, grawlix/sources/nextory.py): Refactored and added metadata support
  • Output (grawlix/output/__init__.py): Enhanced with metadata writing capabilities
  • Documentation (README.md): Updated with new features and correct paths

Testing

All changes maintain backward compatibility while adding new optional features. The migration to bbpb and platformdirs uses packages that are drop-in replacements with the same APIs.

Copy link
Owner

@jo1gi jo1gi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for your contribution and sorry for answering this late.

@@ -0,0 +1,303 @@
"""
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it makes sense for this file to be in the output directory

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file should be in the output directory

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it makes more sense for the metadata to be in the book.Metadata format and then be converted to this format when writing to the epub. That way, all sources are automatically supported.

@@ -0,0 +1,68 @@
"""
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file should be in the output directory

action="store_true",
)
# Metadata
parser.add_argument(
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason to not always add metadata to the epub?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Personally, I always want it, but I don't know with other people. I guess some want to keep it as retail. I took the safe option and followed what was implemented for audiobook-dl.

@ballaballaballa
Copy link
Author

Thank you for your contribution and sorry for answering this late.

No worries! I agree with your comments. I'm away for a couple of weeks, so can take care of it when I'm back if you don't want to fix it before that.

…now. Can be triggered with parameter or set in config.

Added option to add output path to config file.
- Fix Nextory SSL certificate error (api.nextory.se -> api.nextory.com)
- Add missing X-OS-INFO header for Nextory API compatibility
- Implement full metadata writing for Nextory (title, authors, translators, series, publisher, ISBN, language, description, release date)
- Remove debug JSON output from Nextory authentication
- Fix exit() call in epub.py that prevented metadata writing for EpubInParts

Refactoring improvements:
- Reorganize functions in nextory.py and storytel.py by execution flow
- Add section comments for better code organization (Authentication, Main download, Book path, Series path)
- Remove duplicate imports (OnlineFile in nextory.py, datetime in storytel.py)
- Remove duplicate header update in storytel.py
- Improve pagination logic in storytel.py with clearer variable names
- Optimize API calls in nextory.py (eliminate redundant call)
- Use list comprehensions for cleaner code

Documentation:
- Update README with Nextory metadata support
- Add supported sources comparison table for metadata fields
- Include Nextory configuration example
…aints

- Migrate from blackboxprotobuf to bbpb (new PyPI package name)
  - Update pyproject.toml and shell.nix dependencies
  - Import name remains 'blackboxprotobuf' (no code changes)
- Migrate from appdirs to platformdirs
  - Replace deprecated appdirs with actively maintained platformdirs
  - Update grawlix/config.py to use platformdirs.user_config_dir
  - Update dependency declarations in pyproject.toml and shell.nix
- Add minimum version constraints for all dependencies
  - Set requires-python = ">=3.9" (required by httpx and importlib.resources.files())
  - Add Python version classifiers (3.9-3.13)
  - Specify minimum versions: beautifulsoup4>=4.9.0, bbpb>=1.0.0,
    EbookLib>=0.17, httpx>=0.23.0, importlib-resources>=5.0,
    lxml>=4.6.0, platformdirs>=3.0.0, pycryptodome>=3.10.0, rich>=10.0.0
  - Make tomli conditional: only required for Python < 3.11
- Update shell.nix with correct SHA256 hash for bbpb 1.4.2
These changes ensure all dependencies meet minimum version requirements
for Python 3.9+ compatibility and replace deprecated packages with
actively maintained alternatives.
- Fix _extract_series_name to handle null series values
- Add PDF book support for Nextory (served via epub endpoint)
- Convert PDF-in-epub to merged PDF after download
- Add pypdf dependency for PDF merging
- Add Pdf output format (unused but available)
- Update metadata transformer to handle both epub and pdf formats
- Move pdf_converter.py to output/
- Move epub_metadata.py and epub_metadata_writers.py to output/metadata/
- Update imports in __main__.py
- Remove source_data/transformer pattern in favor of direct Metadata population
- Extend Metadata with new fields: original_title, translators, category, tags
- Rename identifier field to isbn for clarity
- Delete epub_metadata_writers.py (transformers no longer needed)
- Update epub_metadata.py to accept Metadata object instead of dict
- Update Storytel and Nextory sources to populate extended metadata
- Fix f-string quote syntax in ereolen.py for Python < 3.12
- Fix Storytel login signature to match new url parameter
- Fix Nextory API field names (identifier vs isbn confusion)
@ballaballaballa
Copy link
Author

I've made the changes now, so please review again when possible.

- Add rendition properties to Metadata (layout, spread, orientation)
- Extract and preserve rendition properties when merging EPUB parts
- Fix viewport meta tags for fixed-layout pages
- Use EpubItem instead of EpubHtml to preserve original content

Fix EPUB validation errors in merged output:
- Skip directory entries, mimetype, and META-INF from manifest
- Exclude nav/toc from spine for fixed-layout books

Improve CSS merging across parts:
- Keep longer version of duplicate selectors (more complete rules)
- Return None from _get_css_rule_key for invalid font-faces

Add cover detection fallback:
- Detect cover from largest image on first page when OPF lacks cover info
- Optimize lookup with dict instead of nested loops

Clean up redundant imports in epub_metadata.py
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

Comments