diff --git a/backend-rs/streamfox/src/controllers.rs b/backend-rs/streamfox/src/controllers.rs index 0db32ff..024f134 100644 --- a/backend-rs/streamfox/src/controllers.rs +++ b/backend-rs/streamfox/src/controllers.rs @@ -1,2 +1,3 @@ pub mod errors; pub mod user; +pub mod video; diff --git a/backend-rs/streamfox/src/controllers/video.rs b/backend-rs/streamfox/src/controllers/video.rs new file mode 100644 index 0000000..d2595bb --- /dev/null +++ b/backend-rs/streamfox/src/controllers/video.rs @@ -0,0 +1,47 @@ +use crate::controllers::errors::HandlerError; +use crate::controllers::user::UserResponse; +use crate::models::video; +use crate::AppState; +use axum::extract::State; +use axum::Json; +use chrono::{DateTime, Utc}; +use entity::id::Id; +use entity::video::Visibility; +use serde::Serialize; + +#[derive(Serialize)] +pub struct VideoResponse { + pub id: Id, + pub creator: UserResponse, + pub duration_secs: u32, + pub uploaded_at: DateTime, + pub name: String, + pub description: String, + pub visibility: Visibility, + pub views: u64, + pub likes: u64, + pub dislikes: u64, +} + +pub async fn get_videos( + State(state): State, +) -> Result>, HandlerError> { + Ok(Json( + video::find_all(&state.connection) + .await? + .into_iter() + .map(|(video, user)| VideoResponse { + id: video.id, + creator: user.into(), + duration_secs: video.duration_secs, + uploaded_at: video.uploaded_at, + name: video.name, + description: video.description, + visibility: video.visibility, + views: video.views, + likes: 0, + dislikes: 0, + }) + .collect(), + )) +} diff --git a/backend-rs/streamfox/src/main.rs b/backend-rs/streamfox/src/main.rs index bf1e144..f8ed993 100644 --- a/backend-rs/streamfox/src/main.rs +++ b/backend-rs/streamfox/src/main.rs @@ -5,7 +5,7 @@ mod secure; mod snowflake; use crate::config::{Config, ConfigError}; -use crate::controllers::user; +use crate::controllers::{user, video}; use crate::models::user::CreateDefaultUsersError; use crate::snowflake::SnowflakeGenerator; use axum::{routing, Router}; @@ -93,6 +93,7 @@ async fn main() -> Result<(), AppError> { .route("/auth/register", routing::post(user::register)) .route("/auth/login", routing::post(user::login)) .route("/user", routing::get(user::get_user)) + .route("/videos", routing::get(video::get_videos)) .layer( TraceLayer::new_for_http() .make_span_with(DefaultMakeSpan::new().level(Level::INFO)) diff --git a/backend-rs/streamfox/src/models.rs b/backend-rs/streamfox/src/models.rs index 3ef1b73..5f9e0f8 100644 --- a/backend-rs/streamfox/src/models.rs +++ b/backend-rs/streamfox/src/models.rs @@ -1,2 +1,3 @@ pub mod base; pub mod user; +pub mod video; diff --git a/backend-rs/streamfox/src/models/video.rs b/backend-rs/streamfox/src/models/video.rs new file mode 100644 index 0000000..35813bb --- /dev/null +++ b/backend-rs/streamfox/src/models/video.rs @@ -0,0 +1,49 @@ +use crate::models::user::User; +use chrono::{DateTime, Utc}; +use entity::id::Id; +use entity::video::Visibility; +use entity::{user, video, view}; +use sea_orm::{ + ColumnTrait, DatabaseConnection, DbErr, EntityTrait, FromQueryResult, JoinType, QuerySelect, +}; + +#[derive(FromQueryResult)] +pub struct VideoResult { + pub id: Id, + pub duration_secs: u32, + pub uploaded_at: DateTime, + pub name: String, + pub description: String, + pub visibility: Visibility, + pub views: u64, + pub likes: u64, + pub dislikes: u64, +} + +pub async fn find_all(connection: &DatabaseConnection) -> Result, DbErr> { + video::Entity::find() + .find_also_related(user::Entity) + .join_rev( + JoinType::InnerJoin, + view::Entity::belongs_to(video::Entity) + .from(view::Column::VideoId) + .to(video::Column::Id) + .into(), + ) + .column_as(view::Column::Id.count(), "views") + .group_by(video::Column::Id) + .group_by(user::Column::Id) + .into_model::() + .all(connection) + .await? + .into_iter() + .map(|(video, creator)| { + Ok(( + video, + creator + .map(Into::into) + .ok_or(DbErr::Custom("video creator was empty".into()))?, + )) + }) + .collect() +}