shared/domain/
audio.rs

1//! Types for audio files.
2
3use super::meta::AudioStyleId;
4use crate::api::endpoints::PathPart;
5use chrono::{DateTime, Utc};
6use serde::{Deserialize, Serialize};
7#[cfg(feature = "backend")]
8use sqlx::postgres::PgRow;
9
10/// Types for user audio library.
11pub mod user {
12    use macros::make_path_parts;
13    use serde::{Deserialize, Serialize};
14
15    use super::AudioId;
16    use crate::api::endpoints::PathPart;
17
18    make_path_parts!(UserAudioListPath => "/v1/user/me/audio");
19
20    /// Response for listing.
21    #[derive(Serialize, Deserialize, Debug)]
22    pub struct UserAudioListResponse {
23        /// the audio files returned.
24        pub audio_files: Vec<UserAudioResponse>,
25    }
26
27    make_path_parts!(UserAudioGetPath => "/v1/user/me/audio/{}" => AudioId);
28
29    /// Response for getting a single audio file.
30    #[derive(Serialize, Deserialize, Debug)]
31    pub struct UserAudioResponse {
32        /// The audio file's metadata.
33        pub metadata: UserAudio,
34    }
35
36    make_path_parts!(UserAudioCreatePath => "/v1/user/me/audio");
37
38    /// Over the wire representation of an audio file's metadata.
39    #[derive(Serialize, Deserialize, Debug)]
40    pub struct UserAudio {
41        /// The audio file's ID.
42        pub id: AudioId,
43        // more fields to be added
44    }
45
46    make_path_parts!(UserAudioUploadPath => "/v1/user/me/audio/{}/raw" => AudioId);
47
48    /// Request indicating the size of an image for upload.
49    #[derive(Serialize, Deserialize, Debug)]
50    pub struct UserAudioUploadRequest {
51        /// The size of the audio to be uploaded in bytes. Allows the API server to check that the file size is
52        /// within limits and as a verification at GCS that the entire file was uploaded
53        pub file_size: usize,
54    }
55
56    /// URL to upload an audio. Supports resumable uploading.
57    #[derive(Serialize, Deserialize, Debug)]
58    pub struct UserAudioUploadResponse {
59        /// The session URI used for uploading, including the query for uploader ID
60        pub session_uri: String,
61    }
62
63    make_path_parts!(UserAudioDeletePath => "/v1/user/me/audio/{}" => AudioId);
64}
65
66wrap_uuid! {
67    /// Wrapper type around [`Uuid`](Uuid), represents the ID of an audio file.
68    pub struct AudioId
69}
70
71/// Represents different kinds of audio.
72#[derive(Serialize, Deserialize, Copy, Clone, Debug)]
73#[cfg_attr(feature = "backend", derive(sqlx::Type))]
74#[repr(i16)]
75pub enum AudioKind {
76    /// Audio is an Mp3
77    Mp3 = 0,
78}
79
80/// Response for getting a single audio file.
81#[derive(Serialize, Deserialize, Debug)]
82pub struct AudioResponse {
83    /// The audio's metadata.
84    pub metadata: AudioMetadata,
85}
86
87/// Over the wire representation of an audio file's metadata.
88#[derive(Serialize, Deserialize, Debug)]
89pub struct AudioMetadata {
90    /// The audio's ID.
91    pub id: AudioId,
92
93    /// The name of the audio.
94    pub name: String,
95
96    /// The description of the audio file.
97    pub description: String,
98
99    /// Is the audio premium?
100    pub is_premium: bool,
101
102    /// When the audio should be considered published (if at all).
103    pub publish_at: Option<DateTime<Utc>>,
104
105    /// The styles associated with the audio file.
106    pub styles: Vec<AudioStyleId>,
107
108    /// What kind of audio this is.
109    pub kind: AudioKind,
110
111    /// Should the audio loop?
112    pub is_looping: bool,
113
114    /// When the audio was originally created.
115    pub created_at: DateTime<Utc>,
116
117    /// When the audio was last updated.
118    pub updated_at: Option<DateTime<Utc>>,
119}
120
121// HACK: can't get `Vec<_>` directly from the DB. See `[crate::domain::image::ImageMetadata]`
122#[cfg(feature = "backend")]
123impl<'r> sqlx::FromRow<'r, PgRow> for AudioMetadata {
124    fn from_row(row: &'r PgRow) -> Result<Self, sqlx::Error> {
125        let DbAudio {
126            id,
127            kind,
128            name,
129            description,
130            is_premium,
131            publish_at,
132            styles,
133            is_looping,
134            created_at,
135            updated_at,
136        } = DbAudio::from_row(row)?;
137
138        Ok(Self {
139            id,
140            kind,
141            name,
142            description,
143            is_premium,
144            publish_at,
145            styles: styles.into_iter().map(|(it,)| it).collect(),
146            is_looping,
147            created_at,
148            updated_at,
149        })
150    }
151}
152
153#[cfg_attr(feature = "backend", derive(sqlx::FromRow))]
154#[cfg(feature = "backend")]
155struct DbAudio {
156    pub id: AudioId,
157    pub kind: AudioKind,
158    pub name: String,
159    pub description: String,
160    pub is_premium: bool,
161    pub publish_at: Option<DateTime<Utc>>,
162    pub styles: Vec<(AudioStyleId,)>,
163    pub is_looping: bool,
164    pub created_at: DateTime<Utc>,
165    pub updated_at: Option<DateTime<Utc>>,
166}