Files
movies-diary/crates/application/src/integrations/confirm.rs
Gabriel Kaszewski bb2001b9cc Add Spoiler Flag with veil, AP content-warning encoding, and full-stack plumbing
Authors can flag a review's comment as containing spoilers; the comment is
blurred behind a reveal control for every viewer except the author, omitted
from RSS, and federates as containsSpoilers plus an AP summary content
warning (ADR-0011) so Mastodon-class clients also collapse it. Flag follows
the general-edit path (ADR-0001) across domain, both DB backends, REST,
HTML templates, SPA (shadcn), TUI fixtures, and exports.
2026-10-17 21:12:56 +02:00

74 lines
2.1 KiB
Rust

use domain::{
errors::DomainError,
models::WatchEventStatus,
value_objects::{UserId, WatchEventId},
};
use crate::{
diary::commands::{LogReviewCommand, MovieInput},
integrations::{commands::ConfirmWatchEventsCommand, deps::ConfirmWatchEventsDeps},
};
pub async fn execute(
deps: &ConfirmWatchEventsDeps,
cmd: ConfirmWatchEventsCommand,
) -> Result<u32, DomainError> {
let user_id = UserId::from_uuid(cmd.user_id);
let mut confirmed = 0u32;
for c in cmd.confirmations {
let event_id = WatchEventId::from_uuid(c.watch_event_id);
let event = deps
.watch_event_query
.get_by_id(&event_id)
.await?
.ok_or_else(|| DomainError::NotFound(format!("WatchEvent {}", c.watch_event_id)))?;
if event.user_id() != &user_id {
return Err(DomainError::Forbidden("not your watch event".into()));
}
let input = if let Some(movie_id) = event.movie_id() {
MovieInput {
movie_id: Some(movie_id.value()),
external_metadata_id: None,
manual_title: None,
manual_release_year: None,
manual_director: None,
}
} else {
MovieInput {
movie_id: None,
external_metadata_id: event.external_metadata_id().map(String::from),
manual_title: Some(event.title().to_string()),
manual_release_year: event.year(),
manual_director: None,
}
};
let review_cmd = LogReviewCommand {
user_id: cmd.user_id,
input,
rating: c.rating,
comment: c.comment,
watched_at: *event.watched_at(),
watch_medium: Some(domain::value_objects::WatchMedium::MediaServer),
spoilers: false,
};
deps.review_logger.log_review(review_cmd).await?;
deps.watch_event_command
.update_status(&event_id, WatchEventStatus::Confirmed)
.await?;
confirmed += 1;
}
Ok(confirmed)
}
#[cfg(test)]
#[path = "tests/confirm.rs"]
mod tests;