11 KiB
11 KiB
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 (
attributesin the index, set via Filmy → Nastavit atribut… / context menu): arbitrarykey → valuepairs (e.g.collection_sort) that are exposed to Filmotéka filename templates throughFile.name_context. So a Kolekce template"{collection_sort} - {title}{ext}"orders the folder as01 - 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 (fieldstitle/year/rating/ext/stem/filename), e.g. a Kolekce with"{year} - {title}{ext}"yieldsDle kolekce/James Bond/1962 - Dr. No.mkvwhile every other folder (and the pool) keeps the plain filename.HardlinkManagertakescategory_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
transformnow 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í/ 90–100 %).csfd_field_valuesno longer transforms;HardlinkManagertakes acategory_transformsmap (FileManager.filmoteka_category_transforms) andapply_transform/decade_bandrun 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_schemain 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_bandfor the rating), and how each maps into the Filmotéka tree (""= output root,"Dle …"= grouping folder, none = filter-only, no folders). Replaces the hard-codedFILMOTEKA_CATEGORY_ROOTSand the fixed category list inapply_csfd_tags;HardlinkManagerroots are now derived from the schema (FileManager.filmoteka_category_roots). - Tag provenance (ČSFD vs user): each file tracks which tags came from ČSFD
(
csfd_tagsin the index).apply_csfd_tagsnow 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ályfolders 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/FilmyasTitle.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_querystrips resolution/codec/source/group, keeps the year) and fills in the first ČSFD search hit (find_csfd_url→search_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_moviegained anon_conflictpolicy (suffix/replace/skip);replaceevicts the existing same-named movie (file + index metadata) first. Filenow storestitleandcsfd_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ályis 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.!indexJSON keyed by pool-relative path.Filereads/writes the index when one is injected and otherwise keeps using per-file.!tagsidecars;FileManageruses the index for the pool. - Configurable copy-as-is folders:
copyasis_foldersin the global config (editable from the GUI) lists pool subfolders mirrored 1:1 during generation;Seriályis 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_tagsassigns Žá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.80–89 %,90–100 %). 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_movierenames the physical file in pool/Filmy to<new name>.<ext>(extension preserved), moves its metadata to the new index key, and syncstitle/filename. Refuses empty names, names with path separators, and collisions with an existing pooled file. - App startup injects
truststoreso 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_tagreferencedsubprocesswithout 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.pynow detects the Anubis challenge, solves the SHA-256 proof-of-work the way the bundled worker JS does, and replays the request through arequests.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.ItemIsTristatewas renamed toQt.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 viaQTimer.singleShotso the tree is not rebuilt inside its ownitemChangedsignal (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.pyto rewrite the category in an existing pool index (backs up.Curator.!indexfirst); 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 rokufolder and country tags underDle země původu.HardlinkManagergained 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 underDle 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.
CSFDMoviegainedcountries: list[str](replacing the singlecountry); 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-pythonnarrowed to>=3.14,<3.15(PySide6 compatibility).
Removed
- Duplicate
src/core/constants.py(hard-coded staleVERSION = "v1.0.3"). The GUI window title imported from it, so it showed the wrong version. All imports now usesrc/constants.py(version derived frompyproject.toml), which also absorbedAPP_VIEWPORT; the window title usesAPP_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_TAGSis 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). Declaredpython-dotenv,pillow,loguru(already imported by the inherited code).