1mod 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
104pub type Country = TwoLetter;
106
107pub type Language = TwoLetter;
109
110#[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 #[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}