61 lines
1.7 KiB
Rust
61 lines
1.7 KiB
Rust
use axum::{
|
|
Json,
|
|
extract::{Path, State},
|
|
http::StatusCode,
|
|
response::IntoResponse,
|
|
};
|
|
use chrono::Utc;
|
|
use uuid::Uuid;
|
|
|
|
use domain::{self, DomainError};
|
|
|
|
use crate::{
|
|
dto::ScheduleResponse,
|
|
error::ApiError,
|
|
extractors::CurrentUser,
|
|
state::AppState,
|
|
};
|
|
|
|
use super::require_owner;
|
|
|
|
/// Trigger 48-hour schedule generation for a channel, starting from now.
|
|
/// Replaces any existing schedule for the same window.
|
|
pub(super) async fn generate_schedule(
|
|
State(state): State<AppState>,
|
|
CurrentUser(user): CurrentUser,
|
|
Path(channel_id): Path<Uuid>,
|
|
) -> Result<impl IntoResponse, ApiError> {
|
|
let channel = state.channel_service.find_by_id(channel_id).await?;
|
|
require_owner(&channel, user.id)?;
|
|
|
|
let schedule = state
|
|
.schedule_engine
|
|
.generate_schedule(channel_id, Utc::now())
|
|
.await?;
|
|
|
|
let _ = state.event_tx.send(domain::DomainEvent::ScheduleGenerated {
|
|
channel_id,
|
|
schedule: schedule.clone(),
|
|
});
|
|
Ok((StatusCode::CREATED, Json(ScheduleResponse::from(schedule))))
|
|
}
|
|
|
|
/// Return the currently active 48-hour schedule for a channel.
|
|
/// 404 if no schedule has been generated yet — call POST /:id/schedule first.
|
|
pub(super) async fn get_active_schedule(
|
|
State(state): State<AppState>,
|
|
CurrentUser(user): CurrentUser,
|
|
Path(channel_id): Path<Uuid>,
|
|
) -> Result<impl IntoResponse, ApiError> {
|
|
let channel = state.channel_service.find_by_id(channel_id).await?;
|
|
require_owner(&channel, user.id)?;
|
|
|
|
let schedule = state
|
|
.schedule_engine
|
|
.get_active_schedule(channel_id, Utc::now())
|
|
.await?
|
|
.ok_or(DomainError::NoActiveSchedule(channel_id))?;
|
|
|
|
Ok(Json(ScheduleResponse::from(schedule)))
|
|
}
|