shared/
media.rs

1//! Mostly contains functions for getting the `key`/url of media stored in s3.
2
3use crate::domain::{animation::AnimationKind, audio::AudioKind};
4use serde::{Deserialize, Serialize};
5use uuid::Uuid;
6
7/// Media Kinds
8#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
9#[serde(tag = "media_kind")]
10#[serde(rename_all = "camelCase")]
11pub enum MediaGroupKind {
12    /// Media is audio
13    Audio,
14
15    /// Media is an image
16    Image,
17
18    /// Media is an animation
19    Animation,
20
21    /// Media is a pdf
22    Pdf,
23}
24
25impl MediaGroupKind {
26    /// returns `self` in a string representation.
27    #[must_use]
28    pub const fn to_str(self) -> &'static str {
29        match self {
30            Self::Audio => "audio",
31            Self::Image => "image",
32            Self::Animation => "animation",
33            Self::Pdf => "pdf",
34        }
35    }
36}
37
38/// Image size Variants
39#[derive(Debug, Copy, Clone)]
40pub enum PngImageFile {
41    /// The original image
42    Original,
43
44    /// The resized image
45    Resized,
46
47    /// A thumbnail of the image
48    Thumbnail,
49}
50
51/// Media Libraries
52#[derive(Debug, Copy, Clone, Serialize, Deserialize, Eq, PartialEq)]
53#[cfg_attr(feature = "backend", derive(sqlx::Type))]
54#[repr(i16)]
55pub enum MediaLibrary {
56    /// The default / global library
57    Global = 0,
58
59    /// The user library
60    User = 1,
61
62    /// The web library
63    Web = 2,
64}
65
66impl MediaLibrary {
67    /// returns `self` in a string representation.
68    #[must_use]
69    pub const fn to_str(self) -> &'static str {
70        match self {
71            Self::Global => "global",
72            Self::User => "user",
73            Self::Web => "web",
74        }
75    }
76}
77
78impl std::str::FromStr for MediaLibrary {
79    type Err = anyhow::Error;
80
81    fn from_str(s: &str) -> Result<Self, Self::Err> {
82        match s {
83            "global" => Ok(Self::Global),
84            "user" => Ok(Self::User),
85            "web" => Ok(Self::Web),
86            _ => Err(anyhow::anyhow!("media type not recognized")),
87        }
88    }
89}
90
91/// Kinds of media used with the web media library
92#[derive(Serialize, Deserialize, Debug, Copy, Clone)]
93pub enum MediaKind {
94    /// media is an Animation
95    Animation(AnimationKind),
96
97    /// Media is an Image
98    Image,
99
100    /// Media is audio
101    Audio(AudioKind),
102
103    ///media is a Pdf
104    Pdf,
105}
106
107/// Kinds of media files
108/// FIXME: Really awkward
109#[derive(Copy, Clone, Debug)]
110pub enum FileKind {
111    /// File for an Animated Gif
112    AnimationGif,
113
114    /// Files for a PNG Image
115    ImagePng(PngImageFile),
116
117    // Spritesheet(Image,JSON),
118    /// File for Mp3 audio
119    AudioMp3,
120
121    /// File for pdf documents
122    DocumentPdf,
123}
124
125impl FileKind {
126    /// Returns the content type of the represented file
127    #[must_use]
128    pub const fn content_type(self) -> &'static str {
129        match self {
130            Self::AnimationGif => "image/gif",
131            Self::ImagePng(_) => "image/png",
132            Self::AudioMp3 => "audio/mp3",
133            Self::DocumentPdf => "application/pdf",
134        }
135    }
136
137    #[must_use]
138    const fn suffix(self) -> &'static str {
139        match self {
140            Self::AnimationGif => "animation.gif",
141            Self::ImagePng(PngImageFile::Original) => "original.png",
142            Self::ImagePng(PngImageFile::Thumbnail) => "thumbnail.png",
143            Self::ImagePng(PngImageFile::Resized) => "resized.png",
144            Self::AudioMp3 => "audio.mp3",
145            Self::DocumentPdf => "document.pdf",
146        }
147    }
148}
149
150impl std::str::FromStr for FileKind {
151    type Err = anyhow::Error;
152
153    fn from_str(s: &str) -> Result<Self, Self::Err> {
154        match s {
155            "animation.gif" => Ok(Self::AnimationGif),
156            "original.png" => Ok(Self::ImagePng(PngImageFile::Original)),
157            "thumbnail.png" => Ok(Self::ImagePng(PngImageFile::Thumbnail)),
158            "resized.png" => Ok(Self::ImagePng(PngImageFile::Resized)),
159            "audio.mp3" => Ok(Self::AudioMp3),
160            "document.pdf" => Ok(Self::DocumentPdf),
161            _ => Err(anyhow::anyhow!("media type not recognized")),
162        }
163    }
164}
165
166/// FCM Data Message format for signalling processing completion.
167///
168/// Contains the information necessary to find the media from the GCS project.
169#[derive(Deserialize, Serialize)]
170#[allow(dead_code)]
171pub struct MediaKey {
172    /// Media library the
173    pub media_library: MediaLibrary,
174    /// The id of the media
175    pub id: Uuid,
176    /// The content type of the media.
177    /// The definitions can be found in [`content_type()`](FileKind::content_type).
178    pub content_type: String,
179}
180
181/// gives the key for some media with the given parameters
182/// this is *not* a full url, (for CDN it's missing the domain)
183#[must_use]
184pub fn media_key(library: MediaLibrary, id: Uuid, file_kind: FileKind) -> String {
185    format!(
186        "media/{}/{}/{}",
187        library.to_str(),
188        id.hyphenated(),
189        file_kind.suffix()
190    )
191}