restructure a bit

This commit is contained in:
Aleksandr 2025-12-30 00:14:12 +03:00
parent 24b63f1a75
commit b828917b4a
14 changed files with 561 additions and 504 deletions

View file

@ -16,4 +16,6 @@ const _: () = {
use status_code::direct;
direct!(NotFound => NOT_FOUND);
direct!(InvalidImage => BAD_REQUEST);
direct!(UnexpectedFileClass => BAD_REQUEST);
};

View file

@ -25,7 +25,14 @@ pub struct Update {
impl_req!(Update => [reqs::update::Ok; reqs::update::Err]);
status_code::direct!(reqs::update::Ok => OK);
status_code::map!(reqs::update::Err => [NotFound, NoSuchBadge, NoSuchGenre, NoSuchTag]);
status_code::map!(reqs::update::Err => [
NotFound,
NoSuchBadge,
NoSuchGenre,
NoSuchTag,
UnexpectedFileClass,
InvalidImage,
]);
#[data]
pub struct Search {
@ -76,7 +83,14 @@ pub struct Create {
impl_req!(Create => [reqs::create::Ok; reqs::create::Err]);
status_code::direct!(reqs::create::Ok => CREATED);
status_code::map!(reqs::create::Err => [AlreadyTaken, NoSuchAuthor, NoSuchGenre, NoSuchTag]);
status_code::map!(reqs::create::Err => [
AlreadyTaken,
NoSuchAuthor,
NoSuchGenre,
NoSuchTag,
UnexpectedFileClass,
InvalidImage,
]);
const _: () = {
use errors::games::*;

View file

@ -11,505 +11,24 @@ use viendesu_core::{
type SessionOf<T> = Session<SessionOfService<<T as Types>::Service>>;
mod authors;
mod files;
mod games;
mod marks;
mod uploads;
mod users;
mod forum;
pub fn make<T: Types>(router: RouterScope<T>) -> RouterScope<T> {
router
.nest("/users", users)
.nest("/authors", authors)
.nest("/games", games)
.nest("/boards", boards)
.nest("/threads", threads)
.nest("/messages", messages)
.nest("/uploads", uploads)
.nest("/files", files)
.nest("/tags", tags)
.nest("/badges", badges)
.nest("/genres", genres)
}
// == Routes ==
fn genres<T: Types>(router: RouterScope<T>) -> RouterScope<T> {
use crate::requests::marks::ListGenres;
use viendesu_core::{requests::marks::list_genres, service::marks::Genres as _};
router.route(
"/",
get(
async move |mut session: SessionOf<T>, ctx: Ctx<ListGenres>| {
let ListGenres {} = ctx.request;
session.genres().list().call(list_genres::Args {}).await
},
),
)
}
fn badges<T: Types>(router: RouterScope<T>) -> RouterScope<T> {
use crate::requests::marks::{AddBadge, ListBadges};
use viendesu_core::{
requests::marks::{add_badge, list_badges},
service::marks::Badges as _,
};
router
.route(
"/",
get(
async move |mut session: SessionOf<T>, ctx: Ctx<ListBadges>| {
let ListBadges { query } = ctx.request;
session
.badges()
.list()
.call(list_badges::Args { query })
.await
},
),
)
.route(
"/",
post(async move |mut session: SessionOf<T>, ctx: Ctx<AddBadge>| {
let AddBadge { text } = ctx.request;
session
.badges()
.add()
.call(add_badge::Args { badge: text })
.await
}),
)
}
fn tags<T: Types>(router: RouterScope<T>) -> RouterScope<T> {
use crate::requests::marks::{AddTag, ListTags};
use viendesu_core::{
requests::marks::{add_tag, list_tags},
service::marks::Tags as _,
};
router
.route(
"/",
get(async move |mut session: SessionOf<T>, ctx: Ctx<ListTags>| {
let ListTags { query } = ctx.request;
session.tags().list().call(list_tags::Args { query }).await
}),
)
.route(
"/",
post(async move |mut session: SessionOf<T>, ctx: Ctx<AddTag>| {
let AddTag { text } = ctx.request;
session.tags().add().call(add_tag::Args { tag: text }).await
}),
)
}
fn users<T: Types>(router: RouterScope<T>) -> RouterScope<T> {
use crate::requests::users::{
BeginAuth, CheckAuth, ConfirmSignUp, FinishAuth, Get, SignIn, SignUp, Update,
};
use viendesu_core::{
requests::users::{
begin_auth, check_auth, confirm_sign_up, finish_auth, get, sign_in, sign_up, update,
},
service::{tabs::Tabs, users::Users},
};
fn convert_update(u: Update) -> update::Update {
update::Update {
nickname: u.nickname,
display_name: u.display_name,
bio: u.bio,
password: u.password,
role: u.role,
pfp: u.pfp,
email: u.email,
}
}
router
.route(
"/{sel}",
get(async |mut session: SessionOf<T>, mut ctx: Ctx<Get>| {
let selector: user::Selector = ctx.path().await?;
session
.users()
.get()
.call(get::Args {
user: Some(selector),
})
.await
}),
)
.route(
"/begin-auth",
post(async |mut session: SessionOf<T>, ctx: Ctx<BeginAuth>| {
session
.users()
.begin_auth()
.call(begin_auth::Args {
method: ctx.request.method,
})
.await
}),
)
.route(
"/finish-auth/{authsessid}",
post(
async |mut session: SessionOf<T>, mut ctx: Ctx<FinishAuth>| {
let auth_session: user::AuthSessionId = ctx.path().await?;
session
.users()
.finish_auth()
.call(finish_auth::Args { auth_session })
.await
},
),
)
.route(
"/check-auth",
get(async |mut session: SessionOf<T>, _ctx: Ctx<CheckAuth>| {
session.users().check_auth().call(check_auth::Args {}).await
}),
)
.route(
"/me",
get(async |mut session: SessionOf<T>, _ctx: Ctx<Get>| {
session.users().get().call(get::Args { user: None }).await
}),
)
.route(
"/sign_in",
post(async |mut session: SessionOf<T>, ctx: Ctx<SignIn>| {
session
.users()
.sign_in()
.call(sign_in::Args {
nickname: ctx.request.nickname,
password: ctx.request.password,
})
.await
}),
)
.route(
"/sign_up",
post(async |mut session: SessionOf<T>, ctx: Ctx<SignUp>| {
let SignUp {
nickname,
email,
password,
display_name,
} = ctx.request;
session
.users()
.sign_up()
.call(sign_up::Args {
nickname,
email,
display_name,
password,
})
.await
}),
)
.route(
"/{sel}",
patch(async |mut session: SessionOf<T>, mut ctx: Ctx<Update>| {
let user: user::Selector = ctx.path().await?;
session
.users()
.update()
.call(update::Args {
user: Some(user),
update: convert_update(ctx.request),
})
.await
}),
)
.route(
"/me",
patch(async |mut session: SessionOf<T>, ctx: Ctx<Update>| {
session
.users()
.update()
.call(update::Args {
user: None,
update: convert_update(ctx.request),
})
.await
}),
)
.route(
"/{user}/confirm/{token}",
post(
async |mut session: SessionOf<T>, mut ctx: Ctx<ConfirmSignUp>| {
let (user, token) = ctx.path().await?;
session
.users()
.confirm_sign_up()
.call(confirm_sign_up::Args { user, token })
.await
},
),
)
.nest("/{user}/tabs", |router| {
use crate::requests::tabs::{Delete, Insert, List, ListItems};
use viendesu_core::requests::tabs::{delete, insert, list, list_items};
router
.route(
"/",
get(async |mut session: SessionOf<T>, mut ctx: Ctx<List>| {
let user = ctx.path().await?;
let List {} = ctx.request;
session.tabs().list().call(list::Args { user }).await
}),
)
.nest("/{tab}", |router| {
router
.route(
"/{item}",
delete(async |mut session: SessionOf<T>, mut ctx: Ctx<Delete>| {
let (user, tab, item) = ctx.path().await?;
let Delete {} = ctx.request;
session
.tabs()
.delete()
.call(delete::Args { user, tab, item })
.await
}),
)
.route(
"/",
post(async |mut session: SessionOf<T>, mut ctx: Ctx<Insert>| {
let (user, tab) = ctx.path().await?;
let Insert { item } = ctx.request;
session
.tabs()
.insert()
.call(insert::Args { user, tab, item })
.await
}),
)
.route(
"/",
get(async |mut session: SessionOf<T>, mut ctx: Ctx<ListItems>| {
let (user, tab) = ctx.path().await?;
let ListItems {
resolve_marks,
start_from,
limit,
} = ctx.request;
session
.tabs()
.list_items()
.call(list_items::Args {
tab,
user,
start_from,
limit,
resolve_marks,
})
.await
}),
)
})
})
}
fn uploads<T: Types>(router: RouterScope<T>) -> RouterScope<T> {
router
}
fn files<T: Types>(router: RouterScope<T>) -> RouterScope<T> {
router
}
fn authors<T: Types>(router: RouterScope<T>) -> RouterScope<T> {
use crate::requests::authors::{Create, Get, Update};
use viendesu_core::{
requests::authors::{create, get, update},
service::authors::Authors,
types::author,
};
router
.route(
"/",
post(async |mut session: SessionOf<T>, ctx: Ctx<Create>| {
let Create {
title,
slug,
description,
owner,
} = ctx.request;
session
.authors()
.create()
.call(create::Args {
title,
slug,
description,
owner,
})
.await
}),
)
.route(
"/{selector}",
get(async |mut session: SessionOf<T>, mut ctx: Ctx<Get>| {
let author: author::Selector = ctx.path().await?;
let Get {} = ctx.request;
session.authors().get().call(get::Args { author }).await
}),
)
.route(
"/{selector}",
patch(async |mut session: SessionOf<T>, mut ctx: Ctx<Update>| {
let author: author::Selector = ctx.path().await?;
let Update {
title,
description,
pfp,
slug,
verified,
} = ctx.request;
session
.authors()
.update()
.call(update::Args {
author,
update: update::Update {
title,
description,
pfp,
slug,
verified,
},
})
.await
}),
)
}
fn games<T: Types>(router: RouterScope<T>) -> RouterScope<T> {
use crate::requests::games::{Create, Get, Search};
use viendesu_core::{
requests::games::{create, get, search},
service::games::Games,
types::{author, game},
};
router
.route(
"/",
post(async |mut session: SessionOf<T>, ctx: Ctx<Create>| {
let Create {
title,
description,
thumbnail,
tags,
genres,
author,
slug,
vndb,
release_date,
} = ctx.request;
session
.games()
.create()
.call(create::Args {
title,
description,
thumbnail,
author,
slug,
tags,
genres,
vndb,
release_date,
})
.await
}),
)
.route(
"/{game_id}",
get(async |mut session: SessionOf<T>, mut ctx: Ctx<Get>| {
let game_id: game::Id = ctx.path().await?;
let Get { resolve_marks } = ctx.request;
session
.games()
.get()
.call(get::Args {
game: game_id.into(),
resolve_marks,
})
.await
}),
)
.route(
"/{author}/{slug}",
get(async |mut session: SessionOf<T>, mut ctx: Ctx<Get>| {
let (author, slug) = ctx.path::<(author::Selector, game::Slug)>().await?;
let Get { resolve_marks } = ctx.request;
session
.games()
.get()
.call(get::Args {
resolve_marks,
game: game::Selector::FullyQualified(game::FullyQualified { author, slug }),
})
.await
}),
)
.route(
"/search",
post(async |mut session: SessionOf<T>, ctx: Ctx<Search>| {
let Search {
query,
author,
include,
exclude,
order,
sort_by,
limit,
} = ctx.request;
session
.games()
.search()
.call(search::Args {
query,
author,
include,
exclude,
order,
sort_by,
limit,
})
.await
}),
)
}
fn boards<T: Types>(router: RouterScope<T>) -> RouterScope<T> {
router
}
fn threads<T: Types>(router: RouterScope<T>) -> RouterScope<T> {
router
}
fn messages<T: Types>(router: RouterScope<T>) -> RouterScope<T> {
router
.nest("/users", users::make)
.nest("/authors", authors::make)
.nest("/games", games::make)
.nest("/forum", forum::make)
.nest("/uploads", uploads::make)
.nest("/files", files::make)
.nest("/tags", marks::tags)
.nest("/badges", marks::badges)
.nest("/genres", marks::genres)
}

View file

@ -0,0 +1,71 @@
use super::*;
use crate::requests::authors::{Create, Get, Update};
use viendesu_core::{
requests::authors::{create, get, update},
service::authors::Authors,
types::author,
};
pub fn make<T: Types>(router: RouterScope<T>) -> RouterScope<T> {
router
.route(
"/",
post(async |mut session: SessionOf<T>, ctx: Ctx<Create>| {
let Create {
title,
slug,
description,
owner,
} = ctx.request;
session
.authors()
.create()
.call(create::Args {
title,
slug,
description,
owner,
})
.await
}),
)
.route(
"/{selector}",
get(async |mut session: SessionOf<T>, mut ctx: Ctx<Get>| {
let author: author::Selector = ctx.path().await?;
let Get {} = ctx.request;
session.authors().get().call(get::Args { author }).await
}),
)
.route(
"/{selector}",
patch(async |mut session: SessionOf<T>, mut ctx: Ctx<Update>| {
let author: author::Selector = ctx.path().await?;
let Update {
title,
description,
pfp,
slug,
verified,
} = ctx.request;
session
.authors()
.update()
.call(update::Args {
author,
update: update::Update {
title,
description,
pfp,
slug,
verified,
},
})
.await
}),
)
}

View file

@ -0,0 +1,5 @@
use super::*;
pub fn make<T: Types>(router: RouterScope<T>) -> RouterScope<T> {
router
}

View file

@ -0,0 +1,20 @@
use super::*;
pub fn make<T: Types>(router: RouterScope<T>) -> RouterScope<T> {
router
.nest("/boards", boards)
.nest("/threads", threads)
.nest("/messages", messages)
}
fn boards<T: Types>(router: RouterScope<T>) -> RouterScope<T> {
router
}
fn threads<T: Types>(router: RouterScope<T>) -> RouterScope<T> {
router
}
fn messages<T: Types>(router: RouterScope<T>) -> RouterScope<T> {
router
}

View file

@ -0,0 +1,104 @@
use super::*;
use crate::requests::games::{Create, Get, Search};
use viendesu_core::{
requests::games::{create, get, search},
service::games::Games,
types::{author, game},
};
pub fn make<T: Types>(router: RouterScope<T>) -> RouterScope<T> {
router
.route(
"/",
post(async |mut session: SessionOf<T>, ctx: Ctx<Create>| {
let Create {
title,
description,
thumbnail,
tags,
genres,
author,
slug,
vndb,
release_date,
} = ctx.request;
session
.games()
.create()
.call(create::Args {
title,
description,
thumbnail,
author,
slug,
tags,
genres,
vndb,
release_date,
})
.await
}),
)
.route(
"/{game_id}",
get(async |mut session: SessionOf<T>, mut ctx: Ctx<Get>| {
let game_id: game::Id = ctx.path().await?;
let Get { resolve_marks } = ctx.request;
session
.games()
.get()
.call(get::Args {
game: game_id.into(),
resolve_marks,
})
.await
}),
)
.route(
"/{author}/{slug}",
get(async |mut session: SessionOf<T>, mut ctx: Ctx<Get>| {
let (author, slug) = ctx.path::<(author::Selector, game::Slug)>().await?;
let Get { resolve_marks } = ctx.request;
session
.games()
.get()
.call(get::Args {
resolve_marks,
game: game::Selector::FullyQualified(game::FullyQualified { author, slug }),
})
.await
}),
)
.route(
"/search",
post(async |mut session: SessionOf<T>, ctx: Ctx<Search>| {
let Search {
query,
author,
include,
exclude,
order,
sort_by,
limit,
} = ctx.request;
session
.games()
.search()
.call(search::Args {
query,
author,
include,
exclude,
order,
sort_by,
limit,
})
.await
}),
)
}

View file

@ -0,0 +1,78 @@
use super::*;
pub fn genres<T: Types>(router: RouterScope<T>) -> RouterScope<T> {
use crate::requests::marks::ListGenres;
use viendesu_core::{requests::marks::list_genres, service::marks::Genres as _};
router.route(
"/",
get(
async move |mut session: SessionOf<T>, ctx: Ctx<ListGenres>| {
let ListGenres {} = ctx.request;
session.genres().list().call(list_genres::Args {}).await
},
),
)
}
pub fn badges<T: Types>(router: RouterScope<T>) -> RouterScope<T> {
use crate::requests::marks::{AddBadge, ListBadges};
use viendesu_core::{
requests::marks::{add_badge, list_badges},
service::marks::Badges as _,
};
router
.route(
"/",
get(
async move |mut session: SessionOf<T>, ctx: Ctx<ListBadges>| {
let ListBadges { query } = ctx.request;
session
.badges()
.list()
.call(list_badges::Args { query })
.await
},
),
)
.route(
"/",
post(async move |mut session: SessionOf<T>, ctx: Ctx<AddBadge>| {
let AddBadge { text } = ctx.request;
session
.badges()
.add()
.call(add_badge::Args { badge: text })
.await
}),
)
}
pub fn tags<T: Types>(router: RouterScope<T>) -> RouterScope<T> {
use crate::requests::marks::{AddTag, ListTags};
use viendesu_core::{
requests::marks::{add_tag, list_tags},
service::marks::Tags as _,
};
router
.route(
"/",
get(async move |mut session: SessionOf<T>, ctx: Ctx<ListTags>| {
let ListTags { query } = ctx.request;
session.tags().list().call(list_tags::Args { query }).await
}),
)
.route(
"/",
post(async move |mut session: SessionOf<T>, ctx: Ctx<AddTag>| {
let AddTag { text } = ctx.request;
session.tags().add().call(add_tag::Args { tag: text }).await
}),
)
}

View file

@ -0,0 +1,5 @@
use super::*;
pub fn make<T: Types>(router: RouterScope<T>) -> RouterScope<T> {
router
}

View file

@ -0,0 +1,217 @@
use super::*;
use crate::requests::users::{
BeginAuth, CheckAuth, ConfirmSignUp, FinishAuth, Get, SignIn, SignUp, Update,
};
use viendesu_core::{
requests::users::{
begin_auth, check_auth, confirm_sign_up, finish_auth, get, sign_in, sign_up, update,
},
service::{tabs::Tabs, users::Users},
};
fn convert_update(u: Update) -> update::Update {
update::Update {
nickname: u.nickname,
display_name: u.display_name,
bio: u.bio,
password: u.password,
role: u.role,
pfp: u.pfp,
email: u.email,
}
}
pub fn make<T: Types>(router: RouterScope<T>) -> RouterScope<T> {
router
.route(
"/{sel}",
get(async |mut session: SessionOf<T>, mut ctx: Ctx<Get>| {
let selector: user::Selector = ctx.path().await?;
session
.users()
.get()
.call(get::Args {
user: Some(selector),
})
.await
}),
)
.route(
"/begin-auth",
post(async |mut session: SessionOf<T>, ctx: Ctx<BeginAuth>| {
session
.users()
.begin_auth()
.call(begin_auth::Args {
method: ctx.request.method,
})
.await
}),
)
.route(
"/finish-auth/{authsessid}",
post(
async |mut session: SessionOf<T>, mut ctx: Ctx<FinishAuth>| {
let auth_session: user::AuthSessionId = ctx.path().await?;
session
.users()
.finish_auth()
.call(finish_auth::Args { auth_session })
.await
},
),
)
.route(
"/check-auth",
get(async |mut session: SessionOf<T>, _ctx: Ctx<CheckAuth>| {
session.users().check_auth().call(check_auth::Args {}).await
}),
)
.route(
"/me",
get(async |mut session: SessionOf<T>, _ctx: Ctx<Get>| {
session.users().get().call(get::Args { user: None }).await
}),
)
.route(
"/sign_in",
post(async |mut session: SessionOf<T>, ctx: Ctx<SignIn>| {
session
.users()
.sign_in()
.call(sign_in::Args {
nickname: ctx.request.nickname,
password: ctx.request.password,
})
.await
}),
)
.route(
"/sign_up",
post(async |mut session: SessionOf<T>, ctx: Ctx<SignUp>| {
let SignUp {
nickname,
email,
password,
display_name,
} = ctx.request;
session
.users()
.sign_up()
.call(sign_up::Args {
nickname,
email,
display_name,
password,
})
.await
}),
)
.route(
"/{sel}",
patch(async |mut session: SessionOf<T>, mut ctx: Ctx<Update>| {
let user: user::Selector = ctx.path().await?;
session
.users()
.update()
.call(update::Args {
user: Some(user),
update: convert_update(ctx.request),
})
.await
}),
)
.route(
"/me",
patch(async |mut session: SessionOf<T>, ctx: Ctx<Update>| {
session
.users()
.update()
.call(update::Args {
user: None,
update: convert_update(ctx.request),
})
.await
}),
)
.route(
"/{user}/confirm/{token}",
post(
async |mut session: SessionOf<T>, mut ctx: Ctx<ConfirmSignUp>| {
let (user, token) = ctx.path().await?;
session
.users()
.confirm_sign_up()
.call(confirm_sign_up::Args { user, token })
.await
},
),
)
.nest("/{user}/tabs", |router| {
use crate::requests::tabs::{Delete, Insert, List, ListItems};
use viendesu_core::requests::tabs::{delete, insert, list, list_items};
router
.route(
"/",
get(async |mut session: SessionOf<T>, mut ctx: Ctx<List>| {
let user = ctx.path().await?;
let List {} = ctx.request;
session.tabs().list().call(list::Args { user }).await
}),
)
.nest("/{tab}", |router| {
router
.route(
"/{item}",
delete(async |mut session: SessionOf<T>, mut ctx: Ctx<Delete>| {
let (user, tab, item) = ctx.path().await?;
let Delete {} = ctx.request;
session
.tabs()
.delete()
.call(delete::Args { user, tab, item })
.await
}),
)
.route(
"/",
post(async |mut session: SessionOf<T>, mut ctx: Ctx<Insert>| {
let (user, tab) = ctx.path().await?;
let Insert { item } = ctx.request;
session
.tabs()
.insert()
.call(insert::Args { user, tab, item })
.await
}),
)
.route(
"/",
get(async |mut session: SessionOf<T>, mut ctx: Ctx<ListItems>| {
let (user, tab) = ctx.path().await?;
let ListItems {
resolve_marks,
start_from,
limit,
} = ctx.request;
session
.tabs()
.list_items()
.call(list_items::Args {
tab,
user,
start_from,
limit,
resolve_marks,
})
.await
}),
)
})
})
}