Skip to content

Commit

Permalink
Api: Get one movie/package/extra (#15)
Browse files Browse the repository at this point in the history
  • Loading branch information
Arthi-chaud committed Mar 9, 2024
2 parents a525578 + b779ab1 commit ce6578f
Show file tree
Hide file tree
Showing 26 changed files with 384 additions and 37 deletions.
16 changes: 13 additions & 3 deletions api/api/src/controllers/extras.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
use crate::dto::extra::NewExtra;
use crate::error_handling::{ApiError, ApiRawResult};
use crate::responses::extra_creation::ExtraCreationResponse;
use crate::error_handling::{ApiError, ApiRawResult, ApiResult};
use crate::responses::extra::{ExtraCreationResponse, ExtraResponse};
use crate::services;
use diesel::Connection;
use domain::models::artist::Artist;
use infrastructure::Database;
use rocket::response::status;
use rocket::serde::uuid::Uuid;
use rocket::{post, serde::json::Json};
use rocket_okapi::okapi::openapi3::OpenApi;
use rocket_okapi::settings::OpenApiSettings;
use rocket_okapi::{openapi, openapi_get_routes_spec};

pub fn get_routes_and_docs(settings: &OpenApiSettings) -> (Vec<rocket::Route>, OpenApi) {
openapi_get_routes_spec![settings: new_extra]
openapi_get_routes_spec![settings: new_extra, get_extra]
}

/// Create a new extra
Expand Down Expand Up @@ -75,3 +76,12 @@ async fn new_extra(
|v| Ok(status::Created::new("").body(Json(v))),
)
}

/// Get a Single extra
#[openapi(tag = "Extras")]
#[get("/<uuid>")]
async fn get_extra(db: Database, uuid: Uuid) -> ApiResult<ExtraResponse> {
db.run(move |conn| services::extra::find(&uuid, conn))
.await
.map_or_else(|e| Err(ApiError::from(e)), |v| Ok(Json(v)))
}
22 changes: 22 additions & 0 deletions api/api/src/controllers/files.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
use crate::error_handling::{ApiError, ApiResult};
use crate::services;
use domain::models::file::File;
use infrastructure::Database;
use rocket::serde::json::Json;
use rocket::serde::uuid::Uuid;
use rocket_okapi::okapi::openapi3::OpenApi;
use rocket_okapi::settings::OpenApiSettings;
use rocket_okapi::{openapi, openapi_get_routes_spec};

pub fn get_routes_and_docs(settings: &OpenApiSettings) -> (Vec<rocket::Route>, OpenApi) {
openapi_get_routes_spec![settings: get_file]
}

/// Get a Single File
#[openapi(tag = "Files")]
#[get("/<uuid>")]
async fn get_file(db: Database, uuid: Uuid) -> ApiResult<File> {
db.run(move |conn| services::file::find(&uuid, conn))
.await
.map_or_else(|e| Err(ApiError::from(e)), |v| Ok(Json(v)))
}
2 changes: 2 additions & 0 deletions api/api/src/controllers/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
pub mod artists;
pub mod extras;
pub mod files;
pub mod images;
pub mod index;
pub mod movies;
pub mod packages;
26 changes: 23 additions & 3 deletions api/api/src/controllers/movies.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
use crate::dto::movie::NewMovie;
use crate::error_handling::{ApiError, ApiRawResult};
use crate::responses::movie_creation::MovieCreationResponse;
use crate::error_handling::{ApiError, ApiRawResult, ApiResult};
use crate::responses::chapter::ChapterResponse;
use crate::responses::movie::{MovieCreationResponse, MovieResponse};
use crate::services;
use diesel::Connection;
use domain::models::artist::Artist;
use infrastructure::Database;
use rocket::response::status;
use rocket::serde::uuid::Uuid;
use rocket::{post, serde::json::Json};
use rocket_okapi::okapi::openapi3::OpenApi;
use rocket_okapi::settings::OpenApiSettings;
use rocket_okapi::{openapi, openapi_get_routes_spec};

pub fn get_routes_and_docs(settings: &OpenApiSettings) -> (Vec<rocket::Route>, OpenApi) {
openapi_get_routes_spec![settings: new_movie]
openapi_get_routes_spec![settings: new_movie, get_movie, get_movie_chapters]
}

/// Create a new movie with its chapters
Expand Down Expand Up @@ -77,3 +79,21 @@ async fn new_movie(
|v| Ok(status::Created::new("").body(Json(v))),
)
}

/// Get a Single Movie
#[openapi(tag = "Movies")]
#[get("/<slug_or_uuid>")]
async fn get_movie(db: Database, slug_or_uuid: String) -> ApiResult<MovieResponse> {
db.run(move |conn| services::movie::find(&slug_or_uuid, conn))
.await
.map_or_else(|e| Err(ApiError::from(e)), |v| Ok(Json(v)))
}

/// Get a Movie's Chapters
#[openapi(tag = "Movies")]
#[get("/<uuid>/chapters")]
async fn get_movie_chapters(db: Database, uuid: Uuid) -> ApiResult<Vec<ChapterResponse>> {
db.run(move |conn| services::chapters::find_by_movie(&uuid, conn))
.await
.map_or_else(|e| Err(ApiError::from(e)), |v| Ok(Json(v)))
}
21 changes: 21 additions & 0 deletions api/api/src/controllers/packages.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
use crate::error_handling::{ApiError, ApiResult};
use crate::responses::package::PackageResponse;
use crate::services;
use infrastructure::Database;
use rocket::serde::json::Json;
use rocket_okapi::okapi::openapi3::OpenApi;
use rocket_okapi::settings::OpenApiSettings;
use rocket_okapi::{openapi, openapi_get_routes_spec};

pub fn get_routes_and_docs(settings: &OpenApiSettings) -> (Vec<rocket::Route>, OpenApi) {
openapi_get_routes_spec![settings: get_package]
}

/// Get a Single Package
#[openapi(tag = "Package")]
#[get("/<slug_or_uuid>")]
async fn get_package(db: Database, slug_or_uuid: String) -> ApiResult<PackageResponse> {
db.run(move |conn| services::package::find(&slug_or_uuid, conn))
.await
.map_or_else(|e| Err(ApiError::from(e)), |v| Ok(Json(v)))
}
2 changes: 2 additions & 0 deletions api/api/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,10 @@ fn create_server() -> Rocket<Build> {
building_rocket, "/".to_owned(), openapi_settings,
"/artists" => controllers::artists::get_routes_and_docs(&openapi_settings),
"/extras" => controllers::extras::get_routes_and_docs(&openapi_settings),
"/files" => controllers::files::get_routes_and_docs(&openapi_settings),
"/images" => controllers::images::get_routes_and_docs(&openapi_settings),
"/movies" => controllers::movies::get_routes_and_docs(&openapi_settings),
"/packages" => controllers::packages::get_routes_and_docs(&openapi_settings),
"/swagger" => (vec![], custom_openapi_spec()),
};

Expand Down
12 changes: 12 additions & 0 deletions api/api/src/responses/chapter.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
use domain::models::chapter::Chapter;
use domain::models::image::Image;
use rocket_okapi::okapi::schemars;
use rocket_okapi::okapi::schemars::JsonSchema;
use serde::Serialize;

#[derive(Serialize, JsonSchema)]
pub struct ChapterResponse {
#[serde(flatten)]
pub chapter: Chapter,
pub thumbnail: Option<Image>,
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
use crate::swagger_examples::*;
use domain::models::{extra::Extra, file::File, image::Image, package::Package};
use rocket::serde::uuid::Uuid;
use rocket_okapi::okapi::schemars;
use rocket_okapi::okapi::schemars::JsonSchema;
use serde::{Deserialize, Serialize};

use super::artist::ArtistResponse;

#[derive(Serialize, Deserialize, JsonSchema, Debug)]
#[serde(crate = "rocket::serde")]
pub struct ExtraCreationResponse {
Expand All @@ -18,3 +21,19 @@ pub struct ExtraCreationResponse {
#[schemars(example = "example_uuid")]
pub file_id: Uuid,
}

#[derive(Serialize, JsonSchema)]
pub struct ExtraResponse {
#[serde(flatten)]
pub extra: Extra,
pub thumbnail: Option<Image>,
#[schemars(skip)]
#[serde(skip_serializing_if = "Option::is_none")]
pub package: Option<Package>,
#[schemars(skip)]
#[serde(skip_serializing_if = "Option::is_none")]
pub artist: Option<ArtistResponse>,
#[schemars(skip)]
#[serde(skip_serializing_if = "Option::is_none")]
pub file: Option<File>,
}
6 changes: 4 additions & 2 deletions api/api/src/responses/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
pub mod artist;
pub mod extra_creation;
pub mod movie_creation;
pub mod chapter;
pub mod extra;
pub mod movie;
pub mod package;
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
use crate::swagger_examples::*;
use domain::models::{file::File, image::Image, movie::Movie, package::Package};
use rocket::serde::uuid::Uuid;
use rocket_okapi::okapi::schemars;
use rocket_okapi::okapi::schemars::JsonSchema;
use serde::{Deserialize, Serialize};

use super::artist::ArtistResponse;

#[derive(Serialize, Deserialize, JsonSchema, Debug)]
#[serde(crate = "rocket::serde")]
pub struct MovieCreationResponse {
Expand All @@ -19,3 +22,19 @@ pub struct MovieCreationResponse {
pub file_id: Uuid,
pub chapters_id: Vec<Uuid>,
}

#[derive(Serialize, JsonSchema)]
pub struct MovieResponse {
#[serde(flatten)]
pub movie: Movie,
pub poster: Option<Image>,
#[schemars(skip)]
#[serde(skip_serializing_if = "Option::is_none")]
pub package: Option<Package>,
#[schemars(skip)]
#[serde(skip_serializing_if = "Option::is_none")]
pub artist: Option<ArtistResponse>,
#[schemars(skip)]
#[serde(skip_serializing_if = "Option::is_none")]
pub file: Option<File>,
}
14 changes: 14 additions & 0 deletions api/api/src/responses/package.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
use domain::models::{artist::Artist, image::Image, package::Package};
use rocket_okapi::okapi::schemars;
use rocket_okapi::okapi::schemars::JsonSchema;
use serde::Serialize;

#[derive(Serialize, JsonSchema)]
pub struct PackageResponse {
#[serde(flatten)]
pub package: Package,
pub poster: Option<Image>,
#[schemars(skip)]
#[serde(skip_serializing_if = "Option::is_none")]
pub artist: Option<Option<Artist>>,
}
21 changes: 9 additions & 12 deletions api/api/src/services/artist.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,19 +34,16 @@ pub fn find<'s>(
use domain::schema::artists::dsl::*;
use domain::schema::images::dsl::images;
let uuid_parse_result = Uuid::parse_str(slug_or_uuid);
let mut query = artists.left_join(images).into_boxed();

let (artist, image) = match uuid_parse_result {
Ok(uuid) => artists
.left_join(images)
.filter(id.eq(uuid))
.select((Artist::as_select(), Option::<Image>::as_select()))
.first(connection),
_ => artists
.left_join(images)
.filter(slug.eq(slug_or_uuid))
.select((Artist::as_select(), Option::<Image>::as_select()))
.first(connection),
}?;
if let Ok(uuid) = uuid_parse_result {
query = query.filter(id.eq(uuid));
} else {
query = query.filter(slug.eq(slug_or_uuid))
}
let (artist, image) = query
.select((Artist::as_select(), Option::<Image>::as_select()))
.first(connection)?;

Ok(ArtistResponse {
artist,
Expand Down
29 changes: 29 additions & 0 deletions api/api/src/services/chapters.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
use diesel::prelude::*;
use domain::models::{chapter::Chapter, image::Image};
use rocket::serde::uuid::Uuid;

use crate::responses::chapter::ChapterResponse;

pub fn find_by_movie(
movie_uuid: &Uuid,
connection: &mut PgConnection,
) -> Result<Vec<ChapterResponse>, diesel::result::Error> {
use domain::schema::chapters::dsl::*;
use domain::schema::images::dsl::*;

let movie_chapters: Vec<(Chapter, Option<Image>)> = chapters
.filter(movie_id.eq(movie_uuid))
.left_join(images)
.order(start_time.asc())
.get_results(connection)?;

Ok(movie_chapters
.iter()
.map(move |(chapter, thumbnail)| -> ChapterResponse {
ChapterResponse {
chapter: chapter.clone(),
thumbnail: thumbnail.clone(),
}
})
.collect())
}
30 changes: 28 additions & 2 deletions api/api/src/services/extra.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
use diesel::{prelude::*, PgConnection};
use domain::models::extra::{Extra, ExtraType};
use domain::models::{
extra::{Extra, ExtraType},
image::Image,
};
use rocket::serde::uuid::Uuid;
use slug::slugify;

use crate::responses::extra::ExtraResponse;

pub fn create<'s>(
extra_name: &'s str,
disc: Option<i16>,
Expand All @@ -29,6 +34,27 @@ pub fn create<'s>(

diesel::insert_into(extras)
.values(&creation_dto)
// .select(Extra::as_select())
.get_result::<Extra>(connection)
}

pub fn find(
uuid: &Uuid,
connection: &mut PgConnection,
) -> Result<ExtraResponse, diesel::result::Error> {
use domain::schema::extras::dsl::*;
use domain::schema::images::dsl::images;

let (extra, image) = extras
.filter(id.eq(uuid))
.left_join(images)
.select((Extra::as_select(), Option::<Image>::as_select()))
.first(connection)?;

Ok(ExtraResponse {
extra,
thumbnail: image,
artist: None,
package: None,
file: None,
})
}
7 changes: 7 additions & 0 deletions api/api/src/services/file.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use diesel::prelude::*;
use domain::models::{file::File, video_quality::VideoQuality};
use rocket::serde::uuid::Uuid;

pub fn create_or_find<'s>(
file_path: &'s str,
Expand All @@ -26,3 +27,9 @@ pub fn create_or_find<'s>(
.values(&creation_dto)
.get_result(connection)
}

pub fn find(uuid: &Uuid, connection: &mut PgConnection) -> Result<File, diesel::result::Error> {
use domain::schema::files::dsl::*;

files.filter(id.eq(uuid)).first(connection)
}
1 change: 1 addition & 0 deletions api/api/src/services/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
pub mod artist;
pub mod chapter;
pub mod chapters;
pub mod extra;
pub mod file;
pub mod image;
Expand Down
Loading

0 comments on commit ce6578f

Please sign in to comment.