refactor: merge media-server parsers, move poster sync and event payload

This commit is contained in:
2026-10-25 21:22:59 +01:00
parent 57c70afead
commit b5bfdadcd9
22 changed files with 32 additions and 77 deletions

41
Cargo.lock generated
View File

@@ -921,13 +921,11 @@ dependencies = [
"export",
"image-converter",
"importer",
"jellyfin",
"media-server",
"metadata",
"nats",
"object-storage",
"plex",
"poster-fetcher",
"poster-sync",
"presentation",
"rss 0.1.0",
"sqlite",
@@ -2852,15 +2850,6 @@ version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682"
[[package]]
name = "jellyfin"
version = "0.1.0"
dependencies = [
"domain",
"serde",
"serde_json",
]
[[package]]
name = "jni"
version = "0.22.4"
@@ -3224,6 +3213,15 @@ dependencies = [
"digest",
]
[[package]]
name = "media-server"
version = "0.1.0"
dependencies = [
"domain",
"serde",
"serde_json",
]
[[package]]
name = "memchr"
version = "2.8.0"
@@ -3909,15 +3907,6 @@ version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6"
[[package]]
name = "plex"
version = "0.1.0"
dependencies = [
"domain",
"serde",
"serde_json",
]
[[package]]
name = "png"
version = "0.18.1"
@@ -3962,16 +3951,6 @@ dependencies = [
"reqwest 0.13.3",
]
[[package]]
name = "poster-sync"
version = "0.1.0"
dependencies = [
"async-trait",
"domain",
"tokio",
"tracing",
]
[[package]]
name = "potential_utf"
version = "0.1.5"

View File

@@ -5,14 +5,13 @@ members = [
"crates/adapters/metadata",
"crates/adapters/poster-fetcher",
"crates/adapters/object-storage",
"crates/adapters/poster-sync",
"crates/adapters/rss",
"crates/adapters/sqlite",
"crates/adapters/sqlite-federation",
"crates/adapters/template-askama",
"crates/adapters/activitypub",
"crates/adapters/export",
"crates/adapters/event-payload",
"crates/event-payload",
"crates/adapters/nats",
"crates/api-types",
"crates/application",
@@ -25,8 +24,7 @@ members = [
"crates/tui",
"crates/worker",
"crates/adapters/importer",
"crates/adapters/jellyfin",
"crates/adapters/plex",
"crates/adapters/media-server",
"crates/config",
]
resolver = "2"
@@ -75,7 +73,6 @@ auth = { path = "crates/adapters/auth" }
metadata = { path = "crates/adapters/metadata" }
poster-fetcher = { path = "crates/adapters/poster-fetcher" }
object-storage = { path = "crates/adapters/object-storage" }
poster-sync = { path = "crates/adapters/poster-sync" }
event-publisher = { path = "crates/adapters/event-publisher" }
rss = { path = "crates/adapters/rss" }
export = { path = "crates/adapters/export" }
@@ -83,11 +80,10 @@ sqlite = { path = "crates/adapters/sqlite" }
sqlite-federation = { path = "crates/adapters/sqlite-federation" }
template-askama = { path = "crates/adapters/template-askama" }
activitypub = { path = "crates/adapters/activitypub" }
event-payload = { path = "crates/adapters/event-payload" }
event-payload = { path = "crates/event-payload" }
media-server = { path = "crates/adapters/media-server" }
nats = { path = "crates/adapters/nats" }
importer = { path = "crates/adapters/importer" }
jellyfin = { path = "crates/adapters/jellyfin" }
plex = { path = "crates/adapters/plex" }
image-converter = { path = "crates/adapters/image-converter" }
config = { path = "crates/config" }

View File

@@ -20,17 +20,15 @@ COPY Cargo.toml Cargo.lock ./
COPY .cargo ./.cargo
COPY crates/adapters/activitypub/Cargo.toml crates/adapters/activitypub/Cargo.toml
COPY crates/adapters/auth/Cargo.toml crates/adapters/auth/Cargo.toml
COPY crates/adapters/event-payload/Cargo.toml crates/adapters/event-payload/Cargo.toml
COPY crates/event-payload/Cargo.toml crates/event-payload/Cargo.toml
COPY crates/adapters/event-publisher/Cargo.toml crates/adapters/event-publisher/Cargo.toml
COPY crates/adapters/nats/Cargo.toml crates/adapters/nats/Cargo.toml
COPY crates/adapters/metadata/Cargo.toml crates/adapters/metadata/Cargo.toml
COPY crates/adapters/poster-fetcher/Cargo.toml crates/adapters/poster-fetcher/Cargo.toml
COPY crates/adapters/object-storage/Cargo.toml crates/adapters/object-storage/Cargo.toml
COPY crates/adapters/poster-sync/Cargo.toml crates/adapters/poster-sync/Cargo.toml
COPY crates/adapters/export/Cargo.toml crates/adapters/export/Cargo.toml
COPY crates/adapters/importer/Cargo.toml crates/adapters/importer/Cargo.toml
COPY crates/adapters/jellyfin/Cargo.toml crates/adapters/jellyfin/Cargo.toml
COPY crates/adapters/plex/Cargo.toml crates/adapters/plex/Cargo.toml
COPY crates/adapters/media-server/Cargo.toml crates/adapters/media-server/Cargo.toml
COPY crates/adapters/rss/Cargo.toml crates/adapters/rss/Cargo.toml
COPY crates/adapters/sqlite/Cargo.toml crates/adapters/sqlite/Cargo.toml
COPY crates/adapters/sqlite-federation/Cargo.toml crates/adapters/sqlite-federation/Cargo.toml

View File

@@ -104,16 +104,13 @@ adapters/
metadata — TMDB / OMDb HTTP client
poster-fetcher — downloads poster images
object-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 — 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
importer — CSV/TSV/JSON/XLSX parser and column mapper for bulk import
jellyfin — Jellyfin webhook payload parser (MediaServerParser adapter)
plex — Plex webhook payload parser (MediaServerParser adapter; requires Plex Pass)
event-payload — shared event serialization DTOs (used by all event bus adapters)
media-server — Jellyfin and Plex webhook payload parsers (MediaServerParser adapter; Plex requires Plex Pass)
event-publisher — in-memory event channel (used in tests)
nats — NATS Core / JetStream event publisher and consumer
activitypub — ActivityPub federation adapter (follow, inbox/outbox, actor); delegates to k-ap for protocol internals

View File

@@ -1,7 +1,7 @@
[package]
name = "image-converter"
version = "0.1.0"
edition = "2021"
edition.workspace = true
[dependencies]
config = { workspace = true }

View File

@@ -1,5 +1,5 @@
[package]
name = "jellyfin"
name = "media-server"
version = "0.1.0"
edition.workspace = true

View File

@@ -60,5 +60,5 @@ struct JellyfinPayload {
}
#[cfg(test)]
#[path = "tests/lib.rs"]
#[path = "tests/jellyfin.rs"]
mod tests;

View File

@@ -0,0 +1,5 @@
mod jellyfin;
mod plex;
pub use jellyfin::JellyfinParser;
pub use plex::PlexParser;

View File

@@ -70,5 +70,5 @@ struct PlexGuid {
}
#[cfg(test)]
#[path = "tests/lib.rs"]
#[path = "tests/plex.rs"]
mod tests;

View File

@@ -1,9 +0,0 @@
[package]
name = "plex"
version = "0.1.0"
edition.workspace = true
[dependencies]
domain = { workspace = true }
serde = { workspace = true }
serde_json = { workspace = true }

View File

@@ -1,7 +1,7 @@
[package]
name = "poster-fetcher"
version = "0.1.0"
edition = "2021"
edition.workspace = true
[dependencies]
config = { workspace = true }

View File

@@ -1,10 +0,0 @@
[package]
name = "poster-sync"
version = "0.1.0"
edition.workspace = true
[dependencies]
domain = { workspace = true }
async-trait = { workspace = true }
tracing = { workspace = true }
tokio = { workspace = true }

View File

@@ -6,6 +6,7 @@ pub mod event_handler;
pub mod get_movie_profile;
pub mod get_movies;
pub mod merge_duplicates;
pub mod poster_sync;
pub mod queries;
pub mod reindex_search;
pub mod request_enrichment;

View File

@@ -22,14 +22,12 @@ auth = { workspace = true }
metadata = { workspace = true }
poster-fetcher = { workspace = true }
object-storage = { workspace = true }
poster-sync = { workspace = true }
tmdb-enrichment = { workspace = true }
image-converter = { workspace = true }
export = { workspace = true }
importer = { workspace = true }
rss = { workspace = true }
jellyfin = { workspace = true }
plex = { workspace = true }
media-server = { workspace = true }
sqlite = { workspace = true }
sqlx = { workspace = true }
anyhow = { workspace = true }

View File

@@ -210,8 +210,8 @@ pub fn build_deps(
revoke_webhook_token: RevokeWebhookTokenDeps {
webhook_token: repos.webhook_token.clone(),
},
jellyfin_parser: std::sync::Arc::new(jellyfin::JellyfinParser),
plex_parser: std::sync::Arc::new(plex::PlexParser),
jellyfin_parser: std::sync::Arc::new(media_server::JellyfinParser),
plex_parser: std::sync::Arc::new(media_server::PlexParser),
},
movies: MoviesGroup {
sync_poster: SyncPosterDeps {

View File

@@ -167,7 +167,7 @@ pub async fn build_worker(config: &config::AppConfig) -> anyhow::Result<WorkerAp
// ── Event handlers ────────────────────────────────────────────────────────
let handlers: Vec<Arc<dyn EventHandler>> = {
let poster = Arc::new(poster_sync::PosterSyncHandler::new(
let poster = Arc::new(application::movies::poster_sync::PosterSyncHandler::new(
Arc::clone(&movie_command),
Arc::clone(&movie_query),
Arc::clone(&metadata),