diff --git a/README.md b/README.md index d380b14..8aa0949 100644 --- a/README.md +++ b/README.md @@ -55,10 +55,10 @@ Open `http://localhost:3000`. The HTTP server and background worker start togeth - People as first-class entities — browse by person via `GET /api/v1/people/{id}` and full credit history via `GET /api/v1/people/{id}/credits`; index populated automatically during TMDb enrichment - RSS/Atom feed for public subscription (global and per-user) - JWT authentication via cookie (HTML) or Bearer token (REST API) -- ActivityPub federation — follow/unfollow remote users, accept/reject/remove followers, federated reviews broadcast as `Note` objects with `#MoviesDiary` + `#MovieTitle` hashtags, paginated outbox, boost/Announce tracking, NodeInfo discovery endpoint, shared inbox delivery, actor profile sync (bio, avatar, discoverable) -- Federation moderation — instance-level domain blocking (admin-managed), per-user actor blocking with `Block` activity, delivery filter excludes blocked actors and blocked-domain inboxes +- ActivityPub federation — follow/unfollow remote users, accept/reject/remove followers, federated reviews broadcast as `Note` objects with movie poster image attachment, `#MoviesDiary` + `#MovieTitle` hashtags, paginated outbox (reviews, watchlist entries, goals), boost/Announce tracking, NodeInfo discovery endpoint, shared inbox delivery, actor profile sync (bio, avatar, discoverable); account migration via `Move` activity; account deletion broadcasts `Delete` actor to followers +- Federation moderation — instance-level domain blocking (admin-managed), per-user actor blocking with `Block` / `Undo Block` activities, delivery filter excludes blocked actors and blocked-domain inboxes - Watchlist — add movies to watch later, per-user; federated watchlist entries visible for remote actors -- User profiles — display name, bio, avatar, banner, custom profile fields; editable via HTML settings page or REST API +- User profiles — display name, bio, avatar, banner, custom profile fields; editable via HTML settings page or REST API; account deletion broadcasts AP `Delete` actor activity; `alsoKnownAs` change triggers AP `Move` for account migration - Jellyfin/Plex auto-import — media server sends a webhook on playback stop, movies land in a watch queue; review and confirm with a rating to create diary entries; per-user webhook tokens with SHA-256 auth; setup UI at `/settings/integrations` - Annual Wrap-Up — Spotify Wrapped for movies: per-user and instance-wide year-in-review with stats (top directors, actors, genres, rating distribution, watch time, rewatches, budget analysis), shareable HTML page at `/wrapups/{user_id}/{year}`; admin-triggered or auto-generated in January - Goals — set a "watch N movies in YEAR" target with a progress bar; progress computed from existing reviews (backwards compatible); per-user federation toggle in settings; displayed on profile (SPA: interactive with create/edit/delete, classic HTML: read-only glassmorphic card) @@ -102,7 +102,7 @@ adapters/ image-storage — stores images (posters + user avatars) on local filesystem or S3-compatible storage poster-sync — event handler: triggers poster fetch+store on MovieDiscovered image-converter — optional background worker: converts stored images to AVIF or WebP; backfills existing images via a 24h periodic job - tmdb-enrichment — event handler: fetches full movie profile (cast, crew, genres, keywords, box office) from TMDb on MovieEnrichmentRequested; resolves IMDb IDs automatically + tmdb-enrichment — TMDb HTTP client implementing MovieEnrichmentClient and PersonEnrichmentClient; event handlers (MovieEnrichmentHandler, PersonEnrichmentHandler) live in the application layer template-askama — Askama HTML rendering rss — RSS/Atom feed generation export — CSV and JSON diary serialization diff --git a/architecture.mmd b/architecture.mmd index 3c54453..a699ff9 100644 --- a/architecture.mmd +++ b/architecture.mmd @@ -15,9 +15,9 @@ graph TB subgraph UseCases["Use Cases"] UC_AUTH["auth
login, register"] UC_DIARY["diary
log_review, get_diary,
get_activity_feed, export"] - UC_MOVIES["movies
get_movies, get_movie_profile,
enrich_movie, request_enrichment,
sync_poster, reindex_search"] + UC_MOVIES["movies
get_movies, get_movie_profile,
enrich_movie, request_enrichment,
sync_poster, reindex_search,
merge_duplicates"] UC_IMPORT["import
create_session, apply_mapping,
execute, profiles"] - UC_USERS["users
get_users, get_profile,
update_profile"] + UC_USERS["users
get_users, get_profile,
update_profile, delete_account"] UC_WATCHLIST["watchlist
add, remove, get"] UC_WRAPUP["wrapup
generate, compute,
list, delete"] UC_GOALS["goals
create, update, delete,
get, list"] @@ -26,17 +26,22 @@ graph TB UC_PERSON["person
get, get_credits"] end subgraph EventHandlers["Event Handlers"] - EH_ENRICH["EnrichmentHandler"] + EH_MOVIE["MovieEnrichmentHandler
on MovieEnrichmentRequested"] + EH_PERSON["PersonEnrichmentHandler
on PersonEnrichmentRequested"] EH_DISCOVER["MovieDiscoveryIndexer"] EH_CLEANUP["SearchCleanupHandler"] EH_REINDEX["SearchReindexHandler"] EH_WRAPUP["WrapUpEventHandler"] + EH_AP["ActivityPubEventHandler
reviews, watchlist, goals,
UserDeleted, UserAccountMoved
"] end subgraph Jobs["Periodic Jobs"] JOB_IMPORT["ImportSessionCleanup"] JOB_WATCH["WatchEventCleanup"] JOB_STALE["EnrichmentStaleness"] JOB_WRAPGEN["WrapUpAutoGenerate"] + JOB_WRAPCLEAN["WrapUpCleanup"] + JOB_SESSION["RefreshSessionCleanup"] + JOB_DEDUP["MovieDeduplication
merge duplicate movie
records (daily)
"] end WORKER_SVC["WorkerService
Semaphore(8), JoinSet,
shutdown signal
"] end @@ -54,7 +59,7 @@ graph TB M_SEARCH["SearchQuery,
SearchResults"] end subgraph Ports["Port Traits (Interfaces)"] - P_REPOS["MovieRepository
ReviewRepository
DiaryRepository
UserRepository
WatchlistRepository
WatchEventRepository
WebhookTokenRepository
ImportSessionRepository
MovieProfileRepository
WrapUpRepository
GoalRepository
UserSettingsRepository"] + P_REPOS["MovieRepository
ReviewRepository
DiaryRepository
UserRepository
WatchlistRepository
WatchEventRepository
WebhookTokenRepository
ImportSessionRepository
MovieProfileRepository
WrapUpRepository
GoalRepository
UserSettingsRepository
MovieDeduplicator"] P_SERVICES["AuthService
MetadataClient
PosterFetcherClient
ObjectStorage
EventPublisher
EventConsumer
PasswordHasher
DiaryExporter
DocumentParser"] P_SEARCH["SearchPort
SearchCommand
PersonQuery
PersonCommand"] P_FEDERATION["SocialQueryPort
LocalApContentQuery
RemoteWatchlistRepository
RemoteGoalRepository"] @@ -63,7 +68,7 @@ graph TB DS_WRAPUP["WrapUpAnalyzer
build_report, compute_*"] DS_REVIEW["ReviewHistoryAnalyzer
rating_trend"] end - EVENTS["DomainEvent enum
ReviewLogged, MovieDiscovered,
GoalCreated, GoalUpdated,
SearchReindexRequested, ...
"] + EVENTS["DomainEvent enum
ReviewLogged, MovieDiscovered,
GoalCreated, GoalUpdated,
UserDeleted, UserAccountMoved,
SearchReindexRequested, ...
"] VO["Value Objects
MovieId, UserId, Rating,
Email, Username, Password, ...
"] end