Commit Graph

72 Commits

Author SHA1 Message Date
66bd138927 refactor(person): EnrichPersonDeps + GetPersonDeps, PersonEnrichmentHandler 2026-06-11 22:05:38 +02:00
b29f3020e6 refactor(integrations): IngestWatchEventDeps, scoped Arc deps, WatchEventCleanupJob 2026-06-11 22:01:15 +02:00
b5ff43d9dc refactor(import): scoped Arc deps, ImportSessionCleanupJob 2026-06-11 21:49:15 +02:00
b552c1d156 refactor(watchlist): WatchlistAddDeps, scoped Arc deps 2026-06-11 21:40:48 +02:00
f006ba00a8 refactor(goals): scoped Arc deps instead of AppContext 2026-06-11 21:36:11 +02:00
2b295e10ba refactor(search): scoped Arc dep instead of AppContext 2026-06-11 21:32:19 +02:00
8ac87a3735 refactor: split jobs.rs into per-context modules 2026-06-11 14:44:23 +02:00
822f3f9d9c api: refresh + logout endpoints, update login response 2026-06-11 14:37:09 +02:00
c05087a6c7 fmt 2026-06-11 13:51:33 +02:00
9b932cde8e feat: wire person enrichment handler, update API DTOs 2026-06-11 13:40:16 +02:00
5dc90724d3 feat: JSON import + mapping presets in SPA
- Accept .json files in import upload, send format to backend
- Backend endpoint PUT /import/sessions/{id}/profile/{profile_id}
- Load saved presets on mapping step, auto-apply and skip to preview
- Save current mapping as preset on confirm step
- Delete presets from mapping step
2026-06-11 12:58:08 +02:00
f10b114e83 feat: expose search param on user profile API endpoint 2026-06-11 12:37:20 +02:00
05d062f4e0 fmt
All checks were successful
CI / Check / Test (push) Successful in 15m57s
2026-06-09 02:31:02 +02:00
70b3ca0f5c refactor: split domain models, move presentation logic out of app layer
Some checks failed
CI / Check / Test (push) Failing after 47s
Split domain/models/mod.rs (630 lines) into focused files:
movie.rs, review.rs, user.rs, stats.rs, enrichment.rs, feed.rs.

Move URL/date formatting from application use cases to
presentation mappers — use cases now return raw domain data.

Delete watchlist/get_page.rs (was pure presentation logic),
replace with presentation/mappers/watchlist.rs.

Document signature conventions in CONTRIBUTING.md.
2026-06-09 02:29:11 +02:00
30a6200b5b remove wrapup video rendering (ffmpeg)
All checks were successful
CI / Check / Test (push) Successful in 15m34s
SPA handles wrapup visuals client-side; server-side
renderer was dead code pulling in ffmpeg + image crates.
2026-06-09 00:36:44 +02:00
a7a11dde08 refactor: split monolithic handlers + testing into domain-grouped modules
Some checks failed
CI / Check / Test (push) Has been cancelled
handlers/api.rs (1706 LOC) + html.rs (1735 LOC) → 12 domain files:
auth, diary, movies, users, search, watchlist, goals, social,
integrations, helpers + existing import/webhook/wrapup/images/rss.

domain/testing.rs (1309 LOC) → testing/ module:
in_memory, fakes, noops, panics, wrapup.

Update README + architecture.mmd with goals feature.
2026-06-08 23:59:23 +02:00
fff5f4af2f feat: goals — "watch N movies in YEAR" with progress bar
Domain: Goal entity, UserSettings (federation toggle), RemoteGoalEntry.
Ports: GoalRepository, UserSettingsRepository, RemoteGoalRepository.
Adapters: sqlite + postgres repos, migrations, AP content query extensions.
Application: CRUD use cases (create/update/delete/get/list), settings use cases.
API: 7 endpoints (/goals CRUD, /users/{id}/goals, /settings) with utoipa docs.
Federation: GoalObject (Note + goal discriminator), outbound broadcast with
per-user toggle, inbound GoalObjectHandler in CompositeObjectHandler.
SPA: API client + hooks, GoalCard (shadcn Card+Progress+DropdownMenu),
GoalSheet (Drawer), profile integration (editable own, read-only others),
federation toggle in settings (Switch).
Classic HTML: glassmorphic goal card on profile, Frutiger Aero styling.
Progress computed from existing reviews — backwards compatible.
2026-06-08 22:37:52 +02:00
bd7dc648c4 feat: search reindex, worker improvements, person IDs, user display names
- add admin POST /api/v1/admin/reindex-search endpoint + event-driven handler
- backfill persons from movie_cast/movie_crew into persons table
- paginate person list_page/backfill_from_credits_batch to cap memory
- concurrent worker event dispatch with semaphore (max 8)
- graceful worker shutdown (drain in-flight tasks on SIGINT)
- always ack events, log handler errors as warnings (no infinite retry)
- NATS ack_wait 600s, AtomicBool guard against concurrent reindex
- add username/display_name to UserSummaryDto and users list
- add person_id to CastMemberDto/CrewMemberDto via get_movie_profile use case
- add movie_id to wrapup MovieRef, person_id to wrapup PersonStat
- thread tmdb_person_id through wrapup cast pipeline
- add is_federated to FeedEntryDto
- cap orphaned persons query with LIMIT 500
- add SPA link to classic site footer
2026-06-04 14:43:28 +02:00
15dc0e526b feat: expose display_name, also_known_as, profile fields in GET /profile 2026-06-04 02:58:12 +02:00
cf2f4a1b4f feat: watchlist add accepts title/year/imdb for movies not in DB 2026-06-04 02:47:55 +02:00
e7cdbf9ca7 fix: user profile URLs, typed returns for following/followers
- avatar_url/banner_url now use full base_url + /images/ prefix
- get_user_following/followers return Result<Json<_>, ApiError>
- add ap_to_domain helper for anyhow→DomainError conversion
2026-06-04 02:40:04 +02:00
837b7866af feat: include avatar_url and banner_url in UserProfileResponse 2026-06-04 02:37:16 +02:00
c4908b7765 feat: API endpoints for any user's following/followers 2026-06-04 02:34:01 +02:00
b1d667d3cb fix: user profile returns social counts when viewing own profile 2026-06-04 02:18:28 +02:00
bf73d4a695 feat: CORS, role in auth, banner_url, diary sort, cleanup
- CORS layer on API routes via CORS_ORIGINS env var
- role field in login + profile responses
- banner_url in profile response
- diary sort_by: rating_desc/rating_asc/date_asc/date_desc
- UserRole::as_str() to deduplicate role mapping
- typed DTOs for import preview (replace ad-hoc JSON)
- warn on invalid CORS origins
2026-06-04 02:06:51 +02:00
7b9b0f9ffe feat: API preview endpoint for import sessions 2026-06-04 01:59:09 +02:00
7d6f874ae7 feat: activity feed accepts sort_by param 2026-06-04 01:35:45 +02:00
004243dcbb fix: use embed=true for serde bool compat
Some checks failed
CI / Check / Test (push) Failing after 6m35s
2026-06-03 10:17:43 +02:00
c798b851dc fmt
Some checks failed
CI / Check / Test (push) Has been cancelled
2026-06-03 10:14:53 +02:00
3f6e01ed65 feat: add embed snippet to profile settings 2026-06-03 10:09:38 +02:00
19642175eb feat: wire embed param to EmbedProfileTemplate 2026-06-03 10:08:51 +02:00
f262417971 refactor: rename ImageStorage → ObjectStorage
Some checks failed
CI / Check / Test (push) Failing after 46s
2026-06-03 01:33:08 +02:00
d94ccbe057 refactor: store typed WrapUpReport in domain, serialize in adapters
Some checks failed
CI / Check / Test (push) Failing after 45s
2026-06-03 01:25:16 +02:00
857896f057 feat: add video download link to wrapup HTML page
Some checks failed
CI / Check / Test (push) Failing after 41s
2026-06-03 01:06:11 +02:00
241063c914 feat: wrapup date validation, delete endpoint, failed record cleanup
Some checks failed
CI / Check / Test (push) Failing after 41s
2026-06-03 00:54:08 +02:00
bb503f3ce8 feat: AdminApiUser extractor for Bearer-token admin endpoints
Some checks failed
CI / Check / Test (push) Has been cancelled
2026-06-03 00:00:45 +02:00
bf0350c87a fmt
Some checks failed
CI / Check / Test (push) Failing after 6m39s
2026-06-02 23:50:20 +02:00
1e063b6580 feat: streaming video download via ImageStorage::get_stream
Some checks failed
CI / Check / Test (push) Failing after 41s
2026-06-02 23:45:31 +02:00
21c33b169e feat: gate wrapup generate behind admin role 2026-06-02 23:14:06 +02:00
490bd97a40 feat: wire video renderer pipeline + download endpoint
Some checks failed
CI / Check / Test (push) Failing after 41s
2026-06-02 22:34:55 +02:00
f00a2cbbb8 feat: HTML wrap-up page with Askama template 2026-06-02 22:28:28 +02:00
5a15bea3d4 feat: wrap-up REST API endpoints 2026-06-02 22:17:11 +02:00
c878c0358f fix: add 403 response to confirm/dismiss OpenAPI annotations
Some checks failed
CI / Check / Test (push) Failing after 6m22s
2026-06-02 21:06:22 +02:00
4067dedb28 refactor: add DomainError::Forbidden + centralize error-to-HTTP mapping
Ownership checks (delete_review, confirm/dismiss watch events) now
return Forbidden instead of Unauthorized. Presentation layer maps
DomainError→StatusCode via domain_error_response helper, replacing
verbose per-handler match arms.
2026-06-02 21:00:22 +02:00
62fd6682c6 refactor: extract view-model mappers from presentation handlers
Some checks failed
CI / Check / Test (push) Has been cancelled
Move mapping logic (domain→DTO/template structs) into mappers/ module.
Handlers now call mapper fns instead of inline conversions.
2026-06-02 20:43:33 +02:00
ac7edd6953 WIP: federation + integrations
Some checks failed
CI / Check / Test (push) Failing after 5m56s
2026-06-02 19:50:19 +02:00
dcc9244d4e refactor: group use cases into DDD bounded contexts
Flat use_cases/ (44 files) + monolithic commands.rs/queries.rs
split into diary/, movies/, watchlist/, import/, auth/, users/,
integrations/, search/, person/, federation/ — each with own
commands.rs, queries.rs, and use case modules.

Inline tests extracted to sibling tests/ dirs.
2026-06-02 19:49:09 +02:00
aadad3cfb0 feat: Jellyfin/Plex auto-import via watch queue
Some checks failed
CI / Check / Test (push) Failing after 6m5s
Webhook ingestion from media servers — movies land in a pending
watch queue, user rates and confirms to create diary entries.

- domain: WatchEvent, WebhookToken models, MediaServerParser port
- adapters: jellyfin + plex parser crates, SQLite + Postgres repos
- application: ingest/confirm/dismiss/cleanup use cases, token mgmt
- presentation: webhook endpoints (bearer + query param auth),
  watch queue + integrations settings HTML pages, OpenAPI docs
- worker: WatchEventCleanupJob (daily, 30d retention)

Movie resolution deferred to confirm — single canonical path
through log_review for enrichment, poster fetch, federation.
2026-06-02 17:34:16 +02:00
c3b89f6dc6 refactor: extract business logic from handlers to application layer
Some checks failed
CI / Check / Test (push) Has been cancelled
CI / Release build (push) Has been cancelled
Move domain logic out of 7 handlers into use cases:
- activity feed: FollowingFilter construction
- user profile: social counts + pending followers
- users list: parallel local+remote actor loading
- watchlist page: local-vs-remote branching
- sync_poster: movie lookup + validation
- get_profile: avatar URL construction
- post_register: register+login orchestration

Add SocialQueryPort.{count_following,count_accepted_followers,
get_pending_followers} to AppContext behind federation feature gate.
2026-05-29 11:41:16 +02:00
2355f89bed refactor: fix all clippy warnings properly
- UserProfile struct groups display_name/bio/avatar/banner/also_known_as/profile_fields
- User::from_persistence takes UserProfile (6 args, was 11)
- PersistedReview struct for Review::from_persistence (1 arg, was 8)
- WatchlistApInput struct for watchlist_to_ap_object (1 arg, was 8)
- ActivityPubDeps struct for activitypub::wire (1 arg, was 11)
- FederationRepos type alias for wire() return types
- FeedSortBy: impl std::str::FromStr instead of inherent from_str
- postgres users.rs: row_to_user takes &PgRow like sqlite
- collapse nested ifs in multipart handlers
- type alias for complex return types (image-converter, worker)
- tui: allow large_enum_variant at crate level (pre-existing, unrelated)
2026-05-29 11:19:02 +02:00