flix_db/entity/
mod.rs

1//! Entity structs for interacting with the database
2
3pub mod content;
4pub mod info;
5#[cfg(feature = "tmdb")]
6pub mod tmdb;
7pub mod watched;
8
9#[cfg(test)]
10mod tests {
11	pub use sea_orm::DbErr;
12	use sea_orm::sqlx::error::ErrorKind;
13
14	#[derive(Debug)]
15	pub enum ErrorKindError {
16		NotRuntimeError,
17		NotSqlxError,
18		NotDatabaseError,
19	}
20
21	pub fn get_error_kind(error: DbErr) -> Result<ErrorKind, ErrorKindError> {
22		let runtime_err = match error {
23			DbErr::Conn(runtime_err) => runtime_err,
24			DbErr::Exec(runtime_err) => runtime_err,
25			DbErr::Query(runtime_err) => runtime_err,
26			_ => return Err(ErrorKindError::NotRuntimeError),
27		};
28
29		let sqlx_err = match runtime_err {
30			sea_orm::RuntimeErr::SqlxError(sqlx_err) => sqlx_err,
31			_ => return Err(ErrorKindError::NotSqlxError),
32		};
33
34		let database_err = match sqlx_err.as_ref() {
35			sea_orm::SqlxError::Database(database_err) => database_err,
36			_ => return Err(ErrorKindError::NotDatabaseError),
37		};
38
39		Ok(database_err.kind())
40	}
41
42	/// Helper macro for writing tests for `ActiveModel` structs where
43	/// toggling [sea_orm::ActiveValue] is needed
44	macro_rules! notsettable {
45		($field:ident, $value:expr $(, $($skip:ident),+)?) => {
46			if notsettable!(@skip, $field $(, $($skip),+)?) {
47				NotSet
48			} else {
49				Set($value)
50			}
51		};
52		(@skip, $field:ident $(, $skip:ident),*) => {
53			false $(|| stringify!($field) == stringify!($skip))*
54		};
55	}
56	pub(super) use notsettable;
57
58	/// Helper macro for writing tests for `ActiveModel` structs where
59	/// toggling [sea_orm::ActiveValue] is needed
60	macro_rules! noneable {
61		($field:ident, $value:expr $(, $($skip:ident),+)?) => {
62			if noneable!(@skip, $field $(, $($skip),+)?) {
63				None
64			} else {
65				Some($value)
66			}
67		};
68		(@skip, $field:ident $(, $skip:ident),*) => {
69			false $(|| stringify!($field) == stringify!($skip))*
70		};
71	}
72	pub(super) use noneable;
73
74	/// Helper macro for creating a flix library
75	macro_rules! have_library {
76		($db:expr, $id:literal) => {
77			$crate::entity::content::libraries::ActiveModel {
78				id: Set(::flix_model::id::LibraryId::from_raw($id)),
79				directory: Set(::std::path::PathBuf::new().into()),
80			}
81			.insert($db)
82			.await
83			.expect("insert");
84		};
85	}
86	pub(super) use have_library;
87
88	/// Helper macro for creating a flix collection
89	macro_rules! make_flix_collection {
90		($db:expr, $id:literal) => {
91			$crate::entity::info::collections::ActiveModel {
92				id: Set(::flix_model::id::CollectionId::from_raw($id)),
93				title: Set(::std::string::String::new()),
94				overview: Set(::std::string::String::new()),
95			}
96			.insert($db)
97			.await
98			.expect("insert");
99		};
100	}
101	pub(super) use make_flix_collection;
102	macro_rules! have_collection {
103		($db:expr, $lid:literal, $id:literal, $pid:expr) => {
104			$crate::entity::tests::make_flix_collection!($db, $id);
105			$crate::entity::content::collections::ActiveModel {
106				id: Set(::flix_model::id::CollectionId::from_raw($id)),
107				parent: Set($pid.map(::flix_model::id::CollectionId::from_raw)),
108				slug: Set(::std::string::String::new()),
109				library: Set(::flix_model::id::LibraryId::from_raw($lid)),
110				directory: Set(::std::path::PathBuf::new().into()),
111				relative_poster_path: Set(::core::option::Option::None),
112			}
113			.insert($db)
114			.await
115			.expect("insert");
116		};
117	}
118	pub(super) use have_collection;
119
120	/// Helper macro for creating a flix movie
121	macro_rules! make_flix_movie {
122		($db:expr, $id:literal) => {
123			$crate::entity::info::movies::ActiveModel {
124				id: Set(::flix_model::id::MovieId::from_raw($id)),
125				title: Set(::std::string::String::new()),
126				tagline: Set(::std::string::String::new()),
127				overview: Set(::std::string::String::new()),
128				date: Set(
129					::chrono::NaiveDate::from_yo_opt(2000, $id).expect("NaiveDate::from_yo_opt")
130				),
131			}
132			.insert($db)
133			.await
134			.expect("insert");
135		};
136	}
137	pub(super) use make_flix_movie;
138	macro_rules! have_movie {
139		($db:expr, $lid:literal, $id:literal, $pid:expr) => {
140			$crate::entity::tests::make_flix_movie!($db, $id);
141			$crate::entity::content::movies::ActiveModel {
142				id: Set(::flix_model::id::MovieId::from_raw($id)),
143				parent: Set($pid.map(::flix_model::id::CollectionId::from_raw)),
144				slug: Set(::std::string::String::new()),
145				library: Set(::flix_model::id::LibraryId::from_raw($lid)),
146				directory: Set(::std::path::PathBuf::new().into()),
147				relative_media_path: Set(::std::string::String::new()),
148				relative_poster_path: Set(::core::option::Option::None),
149			}
150			.insert($db)
151			.await
152			.expect("insert");
153		};
154	}
155	pub(super) use have_movie;
156
157	/// Helper macro for creating a flix show
158	macro_rules! make_flix_show {
159		($db:expr, $id:literal) => {
160			$crate::entity::info::shows::ActiveModel {
161				id: Set(::flix_model::id::ShowId::from_raw($id)),
162				title: Set(::std::string::String::new()),
163				tagline: Set(::std::string::String::new()),
164				overview: Set(::std::string::String::new()),
165				date: Set(
166					::chrono::NaiveDate::from_yo_opt(2000, $id).expect("NaiveDate::from_yo_opt")
167				),
168			}
169			.insert($db)
170			.await
171			.expect("insert");
172		};
173	}
174	pub(super) use make_flix_show;
175	macro_rules! have_show {
176		($db:expr, $lid:literal, $id:literal, $pid:expr) => {
177			$crate::entity::tests::make_flix_show!($db, $id);
178			$crate::entity::content::shows::ActiveModel {
179				id: Set(::flix_model::id::ShowId::from_raw($id)),
180				parent: Set($pid.map(::flix_model::id::CollectionId::from_raw)),
181				slug: Set(::std::string::String::new()),
182				library: Set(::flix_model::id::LibraryId::from_raw($lid)),
183				directory: Set(::std::path::PathBuf::new().into()),
184				relative_poster_path: Set(::core::option::Option::None),
185			}
186			.insert($db)
187			.await
188			.expect("insert");
189		};
190	}
191	pub(super) use have_show;
192
193	/// Helper macro for creating a flix season
194	macro_rules! make_flix_season {
195		($db:expr, $show:literal, $season:literal) => {
196			$crate::entity::info::seasons::ActiveModel {
197				show: Set(::flix_model::id::ShowId::from_raw($show)),
198				season: Set($season),
199				title: Set(::std::string::String::new()),
200				overview: Set(::std::string::String::new()),
201				date: Set(::chrono::NaiveDate::from_yo_opt(2000, $show + $season)
202					.expect("NaiveDate::from_yo_opt")),
203			}
204			.insert($db)
205			.await
206			.expect("insert");
207		};
208	}
209	pub(super) use make_flix_season;
210	macro_rules! have_season {
211		($db:expr, $lid:literal, $show:literal, $season:literal) => {
212			$crate::entity::tests::make_flix_season!($db, $show, $season);
213			$crate::entity::content::seasons::ActiveModel {
214				show: Set(::flix_model::id::ShowId::from_raw($show)),
215				season: Set($season),
216				slug: Set(::std::string::String::new()),
217				library: Set(::flix_model::id::LibraryId::from_raw($lid)),
218				directory: Set(::std::path::PathBuf::new().into()),
219				relative_poster_path: Set(::core::option::Option::None),
220			}
221			.insert($db)
222			.await
223			.expect("insert");
224		};
225	}
226	pub(super) use have_season;
227
228	/// Helper macro for creating a flix episode
229	macro_rules! make_flix_episode {
230		($db:expr, $show:literal, $season:literal, $episode:literal) => {
231			$crate::entity::info::episodes::ActiveModel {
232				show: Set(::flix_model::id::ShowId::from_raw($show)),
233				season: Set($season),
234				episode: Set($episode),
235				title: Set(::std::string::String::new()),
236				overview: Set(::std::string::String::new()),
237				date: Set(::chrono::NaiveDate::from_yo_opt(2000, $show + $season)
238					.expect("NaiveDate::from_yo_opt")),
239			}
240			.insert($db)
241			.await
242			.expect("insert");
243		};
244	}
245	pub(super) use make_flix_episode;
246	macro_rules! have_episode {
247		($db:expr, $lid:literal, $show:literal, $season:literal, $episode:literal) => {
248			have_episode!(@make, $db, $lid, $show, $season, $episode, 0);
249		};
250		($db:expr, $lid:literal, $show:literal, $season:literal, $episode:literal, >1) => {
251			have_episode!(@make, $db, $lid, $show, $season, $episode, 1);
252		};
253		(@make, $db:expr, $lid:literal, $show:literal, $season:literal, $episode:literal, $count:literal) => {
254			$crate::entity::tests::make_flix_episode!($db, $show, $season, $episode);
255			$crate::entity::content::episodes::ActiveModel {
256				show: Set(::flix_model::id::ShowId::from_raw($show)),
257				season: Set($season),
258				episode: Set($episode),
259				count: Set($count),
260				slug: Set(::std::string::String::new()),
261				library: Set(::flix_model::id::LibraryId::from_raw($lid)),
262				directory: Set(::std::path::PathBuf::new().into()),
263				relative_media_path: Set(::std::string::String::new()),
264				relative_poster_path: Set(::core::option::Option::None),
265			}
266			.insert($db)
267			.await
268			.expect("insert");
269		};
270	}
271	pub(super) use have_episode;
272}