Skip to content

Commit

Permalink
Implement GET /videos endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
Aleksbgbg committed Feb 21, 2024
1 parent 123a4f0 commit e3af34e
Show file tree
Hide file tree
Showing 5 changed files with 101 additions and 1 deletion.
1 change: 1 addition & 0 deletions backend-rs/streamfox/src/controllers.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
pub mod errors;
pub mod user;
pub mod video;
48 changes: 48 additions & 0 deletions backend-rs/streamfox/src/controllers/video.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
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)]
#[serde(rename_all = "camelCase")]
pub struct VideoResponse {
id: Id,
creator: UserResponse,
duration_secs: u32,
uploaded_at: DateTime<Utc>,
name: String,
description: String,
visibility: Visibility,
views: u64,
likes: u64,
dislikes: u64,
}

pub async fn get_videos(
State(state): State<AppState>,
) -> Result<Json<Vec<VideoResponse>>, 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(),
))
}
3 changes: 2 additions & 1 deletion backend-rs/streamfox/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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))
Expand Down
1 change: 1 addition & 0 deletions backend-rs/streamfox/src/models.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
pub mod base;
pub mod user;
pub mod video;
49 changes: 49 additions & 0 deletions backend-rs/streamfox/src/models/video.rs
Original file line number Diff line number Diff line change
@@ -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<Utc>,
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<Vec<(VideoResult, User)>, 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::<VideoResult, user::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()
}

0 comments on commit e3af34e

Please sign in to comment.