Files
Curator/CHANGELOG.md
T

11 KiB
Raw Blame History

Changelog

Document all notable changes to the project, grouped by version and release date.

Format

Each version entry uses these sections (include only those that apply):

  • Added — new features
  • Changed — changes to existing functionality
  • Fixed — bug fixes
  • Removed — removed features
  • Dependencies — added, updated, or removed dependencies

Rules

  • Follow semantic versioning: MAJOR.MINOR.PATCH
  • Newest version goes at the top
  • Always update this file before bumping the version in pyproject.toml
  • Document changes as they are made, not all at once at release time

Unreleased

1.5.0 — 2026-06-16

Added

  • Free-form per-movie attributes (attributes in the index, set via Filmy → Nastavit atribut… / context menu): arbitrary key → value pairs (e.g. collection_sort) that are exposed to Filmotéka filename templates through File.name_context. So a Kolekce template "{collection_sort} - {title}{ext}" orders the folder as 01 - Dr. No.mkv, 02 - …. Empty value removes the attr.
  • Per-category filename template in the tag schema (filename_template, editable in Nastavení → Tag schéma…): the hardlink inside that category's folders is named from the template (fields title/year/rating/ext/ stem/filename), e.g. a Kolekce with "{year} - {title}{ext}" yields Dle kolekce/James Bond/1962 - Dr. No.mkv while every other folder (and the pool) keeps the plain filename. HardlinkManager takes category_filename_templates; File.name_context() supplies the fields.
  • The "Přiřadit štítky" dialog now lists all tag-schema categories (including empty user ones like Kolekce) and has a " Nový štítek…" button to create a tag value (e.g. Kolekce/James Bond) on the spot and assign it. Tag values are created on first assignment — the schema editor defines categories + rules, this dialog defines/assigns the individual values.

Changed

  • Tag schema transform now shapes only the Filmotéka folder name, not the tag value. ČSFD tags keep the exact value (rating → Hodnocení/90) while the grouping transform is applied when building folders (→ Dle hodnocení/ 90100 %). csfd_field_values no longer transforms; HardlinkManager takes a category_transforms map (FileManager.filmoteka_category_transforms) and apply_transform/decade_band run at folder-generation time.

Fixed

  • Sidebar filter tree no longer re-expands every category on each check/uncheck: the expanded/collapsed state is preserved across the rebuild (new categories still default to expanded).

1.3.0 — 2026-06-16

Added

  • Configurable tag schema (tag_schema in the global config, edited via Nastavení → Tag schéma…): a single source of truth for which tag categories exist, which ČSFD field feeds each (with an optional value transform, e.g. decade_band for the rating), and how each maps into the Filmotéka tree ("" = output root, "Dle …" = grouping folder, none = filter-only, no folders). Replaces the hard-coded FILMOTEKA_CATEGORY_ROOTS and the fixed category list in apply_csfd_tags; HardlinkManager roots are now derived from the schema (FileManager.filmoteka_category_roots).
  • Tag provenance (ČSFD vs user): each file tracks which tags came from ČSFD (csfd_tags in the index). apply_csfd_tags now regenerates only the ČSFD tags from the schema and leaves user-added tags untouched — so changing a movie's ČSFD link refreshes its ČSFD tags without wiping your own.

1.2.0 — 2026-06-16

Added

  • Fork of the former Tagger project as Curator, a movie-library manager.
  • Pool concept (single source of truth) with Filmy / Seriály folders and a configurable Filmotéka output folder, stored in the global config.
  • Multi-file "Import movies" flow: pick several videos at once and give each its own Title + ČSFD link (one row per file, more addable in the dialog); a copy/move toggle chooses whether sources are copied (default, non-destructive) or moved into pool/Filmy as Title.ext. Imported movies are indexed and, if a ČSFD link is set, enriched with tags right away.
  • Auto-find ČSFD links in the import dialog ("🔎 Najít ČSFD odkazy"): for every row without a link it cleans the filename into a query (clean_filename_to_query strips resolution/codec/source/group, keeps the year) and fills in the first ČSFD search hit (find_csfd_urlsearch_movies, reusing one Anubis session). Existing links are never overwritten; results are a suggestion the user can review before importing.
  • Import dialog now highlights in red any title that already exists in the pool (live as you type) and lets you remove a single row (✕ per row), so you can drop one file without discarding the whole batch and re-picking.
  • Conflict resolution on import: when a row is left red (name already in the pool), import asks whether to replace the existing movie(s) with the new file, keep both (numeric suffix), or cancel. FileManager.import_movie gained an on_conflict policy (suffix / replace / skip); replace evicts the existing same-named movie (file + index metadata) first.
  • File now stores title and csfd_link.
  • New PySide6 GUI reframed around the Filmotéka workflow (pool setup, import, tag filter sidebar, movie table, one-click Filmotéka generation), replacing the tkinter GUI as the entry point.
  • Seriály copy-as-is mirror: pool/Seriály is cloned 1:1 into the Filmotéka output as hardlinks (HardlinkManager.mirror_as_is), generated alongside the movie tree.
  • Unified pool metadata index (pool_index.py): the whole pool's metadata lives in a single <pool>/.Curator.!index JSON keyed by pool-relative path. File reads/writes the index when one is injected and otherwise keeps using per-file .!tag sidecars; FileManager uses the index for the pool.
  • Configurable copy-as-is folders: copyasis_folders in the global config (editable from the GUI) lists pool subfolders mirrored 1:1 during generation; Seriály is the default. Generalizes the previously hardcoded Seriály mirror.
  • Project README.md (overview, concepts, workflow, run/build instructions).
  • ČSFD scraping (csfd.py, ported from the Tagger devel branch): fetches movie data from a ČSFD link (JSON-LD + HTML parsing). File.apply_csfd_tags assigns Žánr / Rok / Země původu / Hodnocení tags and caches the fetched data (incl. directors and the first 10 actors) in the metadata. The rating is bucketed into ten-point bands (rating_band, e.g. 8089 %, 90100 %). Directors and actors are collected but intentionally not turned into tags or Filmotéka folders — there would be far too many. The GUI auto-fetches on import when a link is given and offers "Načíst tagy z ČSFD" for selected movies.
  • Rename a pooled movie from the app ("Přejmenovat…" in the Movie menu / context menu, F2): FileManager.rename_movie renames the physical file in pool/Filmy to <new name>.<ext> (extension preserved), moves its metadata to the new index key, and syncs title/filename. Refuses empty names, names with path separators, and collisions with an existing pooled file.
  • App startup injects truststore so HTTPS uses the OS certificate store — ČSFD fetching works behind corporate SSL inspection (where certifi's bundle lacks the proxy root CA).

Fixed

  • media_utils.add_video_resolution_tag referenced subprocess without importing it.
  • ČSFD parsing updated for the current site HTML: year is read from JSON-LD dateCreated, and the origin line (now bullet-separated, no commas) is tokenized so country / year / duration are extracted correctly.
  • ČSFD anti-bot wall (Anubis): ČSFD now serves a proof-of-work challenge page instead of the movie, so fetches returned a film with no genres/year ("načteno 0 tagů"). csfd.py now detects the Anubis challenge, solves the SHA-256 proof-of-work the way the bundled worker JS does, and replays the request through a requests.Session (reused across a batch so only the first fetch pays the PoW cost). Žánr / Rok / Země původu tags load again.
  • "Assign tags" dialog crashed on PySide6/Qt6 — Qt.ItemIsTristate was renamed to Qt.ItemIsAutoTristate.
  • Sidebar tag-filter checkboxes never appeared checked: every toggle triggered a table refresh that rebuilt the tree from scratch (all unchecked), wiping the click. The active filter is now kept in a separate model (_active_filter) and restored on rebuild. The count after each tag is also now filter-aware — it shows how many of the currently filtered movies carry that tag (i.e. how many would remain if it were checked), instead of always the pool-wide total. The refresh is deferred via QTimer.singleShot so the tree is not rebuilt inside its own itemChanged signal (which deleted the item Qt was still processing and crashed the app with SIGSEGV on a real click).

Changed

  • ČSFD country tag category renamed Země → Země původu. Added scripts/migrate_tag_category.py to rewrite the category in an existing pool index (backs up .Curator.!index first); run against the live pool.
  • Filmotéka tree relaid out: genre folders now sit directly at the output root (next to the copy-as-is Seriály mirror), with year tags grouped under a Dle roku folder and country tags under Dle země původu. HardlinkManager gained a category → root-folder map (category_roots, empty root = tag folders at the output root) and now restricts obsolete-link cleanup to the tag-tree's own top-level folders, so copy-as-is mirrors are never touched. The tree also groups the ČSFD rating under Dle hodnocení.
  • ČSFD origin is now parsed as multiple countries: a co-production like "USA / Velká Británie" becomes a separate Země původu tag per country (so the film is filed under each), instead of one combined tag. CSFDMovie gained countries: list[str] (replacing the single country); the csfd cache schema bumped to v2 (legacy single-country caches are split on read).
  • Movie table trimmed to Název / Štítky / Velikost — the Datum and ČSFD columns were dropped (a ČSFD link is a prerequisite, so its indicator was always the same).
  • All references to "Tagger" renamed to "Curator" (code, spec, config filenames .Curator.!gtag / .Curator.!ftag, tests).
  • requires-python narrowed to >=3.14,<3.15 (PySide6 compatibility).

Removed

  • Duplicate src/core/constants.py (hard-coded stale VERSION = "v1.0.3"). The GUI window title imported from it, so it showed the wrong version. All imports now use src/constants.py (version derived from pyproject.toml), which also absorbed APP_VIEWPORT; the window title uses APP_TITLE → "Curator vX.Y.Z".
  • Legacy Tagger predefined tags: the always-available Hodnocení ( rating) and Barva (color) categories in TagManager, and the automatic Stav/Nové tag assigned to every newly imported file. DEFAULT_TAGS is now empty; the pool is driven by ČSFD-derived tags (Žánr / Rok / Země původu).

Dependencies

  • Added pyside6 (GUI), requests + beautifulsoup4 (ČSFD scraping), truststore (OS cert store for HTTPS). Declared python-dotenv, pillow, loguru (already imported by the inherited code).