trakt_rs/
smo.rs

1//! Standard Media Objects
2
3mod de;
4mod ser;
5
6use compact_str::CompactString;
7use serde::{Deserialize, Serialize};
8use time::{Date, OffsetDateTime};
9use trakt_core::EmojiString;
10
11#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize)]
12#[serde(untagged)]
13pub enum Id {
14    Trakt(u64),
15    Slug(CompactString),
16    Tvdb(u64),
17    Imdb(CompactString),
18    Tmdb(u64),
19}
20
21impl From<Id> for Ids {
22    fn from(value: Id) -> Self {
23        let mut ret = Self::default();
24        match value {
25            Id::Trakt(trakt) => ret.trakt = Some(trakt),
26            Id::Slug(slug) => ret.slug = Some(slug),
27            Id::Tvdb(tvdb) => ret.tvdb = Some(tvdb),
28            Id::Imdb(imdb) => ret.imdb = Some(imdb),
29            Id::Tmdb(tmdb) => ret.tmdb = Some(tmdb),
30        }
31        ret
32    }
33}
34
35#[derive(Debug, Clone, Eq, PartialEq, Hash, Default, Serialize, Deserialize)]
36pub struct Ids {
37    #[serde(skip_serializing_if = "Option::is_none")]
38    pub trakt: Option<u64>,
39    #[serde(skip_serializing_if = "Option::is_none")]
40    pub slug: Option<CompactString>,
41    #[serde(skip_serializing_if = "Option::is_none")]
42    pub tvdb: Option<u64>,
43    #[serde(skip_serializing_if = "Option::is_none")]
44    pub imdb: Option<CompactString>,
45    #[serde(skip_serializing_if = "Option::is_none")]
46    pub tmdb: Option<u64>,
47}
48
49#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize)]
50pub struct Movie {
51    pub title: CompactString,
52    pub year: u16,
53    pub ids: Ids,
54}
55
56#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize)]
57pub struct Show {
58    pub title: CompactString,
59    pub year: u16,
60    pub ids: Ids,
61}
62
63#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize)]
64pub struct Season {
65    pub number: u16,
66    pub ids: Ids,
67}
68
69#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize)]
70pub struct Episode {
71    pub season: u16,
72    pub number: u16,
73    pub title: CompactString,
74    pub ids: Ids,
75}
76
77#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize)]
78pub struct Person {
79    pub name: CompactString,
80    pub ids: Ids,
81}
82
83#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize)]
84pub struct User {
85    pub username: CompactString,
86    pub private: bool,
87    pub name: CompactString,
88    pub vip: bool,
89    pub vip_ep: bool,
90    pub ids: Ids,
91}
92
93#[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Default, Serialize)]
94#[serde(rename_all = "lowercase")]
95pub enum Period {
96    Daily,
97    #[default]
98    Weekly,
99    Monthly,
100    Yearly,
101    All,
102}
103
104/// 2-letter country code
105pub type Country = TwoLetter;
106
107/// 2-letter language code
108pub type Language = TwoLetter;
109
110/// 2-letter Codes
111#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
112pub struct TwoLetter([u8; 2]);
113
114impl TwoLetter {
115    #[must_use]
116    pub fn new(code: &str) -> Self {
117        let mut bytes = [0; 2];
118        bytes.copy_from_slice(code.as_bytes());
119        unsafe { Self::from_bytes_unchecked(bytes) }
120    }
121
122    /// Create a `TwoLetter` from bytes without checking if the bytes are valid UTF-8
123    ///
124    /// # Arguments
125    ///
126    /// * `bytes`: Bytes to convert to a `TwoLetter`
127    ///
128    /// # Safety
129    ///
130    /// The bytes must be valid UTF-8.
131    #[must_use]
132    pub const unsafe fn from_bytes_unchecked(bytes: [u8; 2]) -> Self {
133        Self(bytes)
134    }
135
136    #[must_use]
137    pub const fn as_str(&self) -> &str {
138        unsafe { std::str::from_utf8_unchecked(&self.0) }
139    }
140}
141
142#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Default, Serialize)]
143#[serde(rename_all = "lowercase")]
144pub enum Sort {
145    #[default]
146    Newest,
147    Oldest,
148    Likes,
149    Replies,
150    Highest,
151    Lowest,
152    Plays,
153}
154
155#[derive(Debug, Clone, Eq, PartialEq, Hash, Deserialize)]
156pub struct Comment {
157    pub id: u32,
158    pub parent_id: Option<u32>,
159    #[serde(with = "time::serde::iso8601")]
160    pub created_at: OffsetDateTime,
161    #[serde(with = "time::serde::iso8601")]
162    pub updated_at: OffsetDateTime,
163    pub comment: EmojiString,
164    pub spoiler: bool,
165    pub review: bool,
166    pub replies: u32,
167    pub likes: u32,
168    pub user_stats: UserStats,
169    pub user: User,
170    pub sharing: Option<Sharing>,
171}
172
173#[derive(Debug, Clone, Eq, PartialEq, Hash, Deserialize)]
174pub struct UserStats {
175    pub rating: u8,
176    pub play_count: u32,
177    pub completed_count: u32,
178}
179
180#[derive(Debug, Clone, Eq, PartialEq, Hash, Deserialize)]
181pub struct List {
182    pub name: EmojiString,
183    pub description: EmojiString,
184    pub privacy: ListPrivacy,
185    pub share_link: String,
186    pub r#type: ListType,
187    pub display_numbers: bool,
188    pub allow_comments: bool,
189    pub sort_by: ListSortBy,
190    pub sort_how: ListSortHow,
191    #[serde(with = "time::serde::iso8601")]
192    pub created_at: OffsetDateTime,
193    #[serde(with = "time::serde::iso8601")]
194    pub updated_at: OffsetDateTime,
195    pub item_count: u64,
196    pub comment_count: u64,
197    pub likes: u64,
198    pub ids: Ids,
199    pub user: User,
200}
201
202#[derive(Debug, Clone, Eq, PartialEq, Hash, Deserialize)]
203#[serde(rename_all = "lowercase")]
204pub enum ListType {
205    Personal,
206    Official,
207    Watchlist,
208    Favorites,
209}
210
211#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Serialize, Deserialize)]
212#[serde(rename_all = "snake_case")]
213pub enum ListSortBy {
214    Rank,
215    Added,
216    Title,
217    Released,
218    Runtime,
219    Popularity,
220    Percentage,
221    Votes,
222    MyRating,
223    Random,
224    Watched,
225    Collected,
226}
227
228#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Serialize, Deserialize)]
229#[serde(rename_all = "lowercase")]
230pub enum ListSortHow {
231    Asc,
232    Desc,
233}
234
235#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Default, Serialize, Deserialize)]
236#[serde(rename_all = "lowercase")]
237pub enum ListPrivacy {
238    #[default]
239    Private,
240    Link,
241    Friends,
242    Public,
243}
244
245#[derive(Debug, Clone, PartialEq, Deserialize)]
246pub struct Ratings {
247    pub rating: f32,
248    pub votes: u32,
249    pub distribution: Distribution,
250}
251
252#[derive(Debug, Clone, Eq, PartialEq, Hash)]
253pub struct Distribution(pub [u32; 10]);
254
255#[derive(Debug, Clone, Eq, PartialEq, Hash, Deserialize)]
256pub struct Studio {
257    pub name: CompactString,
258    pub country: Country,
259    pub ids: Ids,
260}
261
262#[derive(Debug, Clone, Eq, PartialEq, Hash, Deserialize)]
263pub struct EpisodeAirEvent {
264    #[serde(with = "time::serde::iso8601")]
265    pub first_aired: OffsetDateTime,
266    pub episode: Episode,
267    pub show: Show,
268}
269
270#[derive(Debug, Clone, Eq, PartialEq, Hash, Deserialize)]
271pub struct MovieReleaseEvent {
272    #[serde(with = "crate::iso8601_date")]
273    pub release_date: Date,
274    pub movie: Movie,
275}
276
277#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Default, Serialize, Deserialize)]
278pub struct Sharing {
279    pub twitter: bool,
280    pub mastodon: bool,
281    pub tumblr: bool,
282}
283
284#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Default, Serialize)]
285#[serde(rename_all = "lowercase")]
286pub enum CommentType {
287    #[default]
288    All,
289    Reviews,
290    Shouts,
291}
292
293#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Default, Serialize)]
294#[serde(rename_all = "lowercase")]
295pub enum CommentItemType {
296    #[default]
297    All,
298    Movies,
299    Shows,
300    Seasons,
301    Episodes,
302    Lists,
303}
304
305#[derive(Debug, Clone, Eq, PartialEq, Hash, serde::Deserialize)]
306#[serde(rename_all = "lowercase")]
307#[serde(tag = "type")]
308pub enum CommentWithItem {
309    Movie {
310        movie: Box<Movie>,
311        comment: Comment,
312    },
313    Show {
314        show: Box<Show>,
315        comment: Comment,
316    },
317    Season {
318        season: Box<Season>,
319        comment: Comment,
320    },
321    Episode {
322        episode: Box<Episode>,
323        comment: Comment,
324    },
325    List {
326        list: Box<List>,
327        comment: Comment,
328    },
329}
330
331#[derive(Debug, Clone, Eq, PartialEq, Hash, Deserialize)]
332#[serde(rename_all = "lowercase")]
333#[serde(tag = "type")]
334pub enum Item {
335    Movie { movie: Box<Movie> },
336    Show { show: Box<Show> },
337    Season { season: Box<Season> },
338    Episode { episode: Box<Episode> },
339    List { list: Box<List> },
340}