use serde::{Deserialize, Serialize};
use url::Url;
#[cfg(feature = "utoipa")]
use utoipa::ToSchema;
#[cfg(feature = "validator")]
use validator::Validate;
use crate::v1::types::{
util::{Diff, Time},
MediaId,
};
mod mime;
mod track;
pub use mime::Mime;
pub use track::*;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[cfg_attr(feature = "utoipa", derive(ToSchema))]
#[cfg_attr(feature = "validator", derive(Validate))]
pub struct Media {
pub id: MediaId,
#[cfg_attr(feature = "utoipa", schema(min_length = 1, max_length = 256))]
#[cfg_attr(feature = "validator", validate(length(min = 1, max = 256)))]
pub filename: String,
#[cfg_attr(
feature = "utoipa",
schema(required = false, min_length = 1, max_length = 8192)
)]
#[cfg_attr(feature = "validator", validate(length(min = 1, max = 8192)))]
pub alt: Option<String>,
pub source: MediaTrack,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[cfg_attr(feature = "utoipa", derive(ToSchema))]
#[cfg_attr(feature = "validator", derive(Validate))]
pub struct MediaCreate {
#[cfg_attr(
feature = "utoipa",
schema(required = false, min_length = 1, max_length = 8192)
)]
#[cfg_attr(feature = "validator", validate(length(min = 1, max = 8192)))]
pub alt: Option<String>,
#[serde(flatten)]
#[cfg_attr(feature = "validator", validate(nested))]
pub source: MediaCreateSource,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[cfg_attr(feature = "utoipa", derive(ToSchema))]
#[serde(untagged)]
pub enum MediaCreateSource {
Upload {
#[cfg_attr(
feature = "utoipa",
schema(required = false, min_length = 1, max_length = 256)
)]
filename: String,
size: u64,
},
Download {
#[cfg_attr(
feature = "utoipa",
schema(required = false, min_length = 1, max_length = 256)
)]
filename: Option<String>,
size: Option<u64>,
source_url: Url,
},
}
#[cfg(feature = "validator")]
mod val {
use super::MediaCreateSource;
use serde_json::json;
use validator::{Validate, ValidateLength, ValidationError, ValidationErrors};
impl Validate for MediaCreateSource {
fn validate(&self) -> Result<(), ValidationErrors> {
let mut v = ValidationErrors::new();
if self
.filename()
.is_none_or(|n| n.validate_length(Some(1), Some(256), None))
{
Ok(())
} else {
let mut err = ValidationError::new("length");
err.add_param("max".into(), &json!(256));
err.add_param("min".into(), &json!(1));
v.add("filename", err);
Err(v)
}
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[cfg_attr(feature = "utoipa", derive(ToSchema))]
pub struct MediaCreated {
pub media_id: MediaId,
pub upload_url: Option<Url>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[cfg_attr(feature = "utoipa", derive(ToSchema))]
#[cfg_attr(feature = "validator", derive(Validate))]
pub struct MediaPatch {
#[cfg_attr(feature = "utoipa", schema(min_length = 1, max_length = 8192))]
#[cfg_attr(feature = "validator", validate(length(min = 1, max = 8192)))]
pub alt: Option<Option<String>>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[cfg_attr(feature = "utoipa", derive(ToSchema))]
pub struct MediaRef {
pub id: MediaId,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq, Eq)]
#[cfg_attr(feature = "utoipa", derive(ToSchema))]
pub struct MediaDerived {
pub title: Option<String>,
pub artist: Option<String>,
pub album: Option<String>,
pub url: Option<Url>,
pub comment: Option<String>,
pub description: Option<String>,
pub date: Option<Time>,
}
impl Diff<Media> for MediaPatch {
fn changes(&self, other: &Media) -> bool {
self.alt.changes(&other.alt)
}
}
impl MediaCreateSource {
pub fn size(&self) -> Option<u64> {
match self {
MediaCreateSource::Upload { size, .. } => Some(*size),
MediaCreateSource::Download { size, .. } => *size,
}
}
pub fn filename(&self) -> Option<&str> {
match self {
MediaCreateSource::Upload { filename, .. } => Some(filename.as_str()),
MediaCreateSource::Download { filename, .. } => filename.as_deref(),
}
}
}