Skip to content

Commit

Permalink
feat(api): enhance EncodableBot with additional description field (#107)
Browse files Browse the repository at this point in the history
  • Loading branch information
chikof authored Nov 10, 2024
2 parents 3741754 + f3fbffe commit 30305fa
Show file tree
Hide file tree
Showing 4 changed files with 108 additions and 51 deletions.
101 changes: 61 additions & 40 deletions src/controllers/summary.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
use crate::app::AppState;
use crate::models::{Bot, Category};
use crate::schema::bots;
use crate::task::spawn_blocking;
use crate::models::{Bot, BotCategory, Category};
use crate::schema::{bots, bots_categories, categories};
use crate::util::errors::AppResult;
use crate::views::{EncodableBot, EncodableCategory};
use axum::Json;
use diesel::prelude::*;
use diesel_async::async_connection_wrapper::AsyncConnectionWrapper;
use diesel::{BelongingToDsl, ExpressionMethods, QueryDsl, SelectableHelper};

use diesel_async::AsyncPgConnection;
use diesel_async::RunQueryDsl;
use serde_json::Value;

pub async fn summary(state: AppState) -> AppResult<Json<Value>> {
Expand All @@ -18,40 +20,59 @@ pub async fn summary(state: AppState) -> AppResult<Json<Value>> {
.map(Category::into)
.collect::<Vec<EncodableCategory>>();

spawn_blocking(move || {
let conn: &mut AsyncConnectionWrapper<_> = &mut conn.into();

let num_bots: i64 = bots::table.count().get_result(conn)?;

fn encode_bots(bot_list: Vec<Bot>) -> AppResult<Vec<EncodableBot>> {
bot_list
.into_iter()
.map(|b| Ok(EncodableBot::from_minimal(b)))
.collect()
}

let selection = Bot::as_select();

let new_bots = bots::table
.order(bots::created_at.desc())
.select(selection)
.limit(10)
.load(conn)?;

let just_updated = bots::table
.filter(bots::updated_at.ne(bots::created_at))
.order(bots::updated_at.desc())
.select(selection)
.limit(10)
.load(conn)?;

// TODO: top rated, most voted
Ok(Json(json!({
"num_bots": num_bots,
"new_bots": encode_bots(new_bots)?,
"just_updated": encode_bots(just_updated)?,
"popular_categories": popular_categories,
})))
})
.await
let num_bots: i64 = bots::table.count().get_result(&mut conn).await?;

async fn encode_bots(
conn: &mut AsyncPgConnection,
bot_list: Vec<Bot>,
) -> AppResult<Vec<EncodableBot>> {
use diesel_async::RunQueryDsl;

let cats = BotCategory::belonging_to(&bot_list)
.inner_join(categories::table)
.select((bots_categories::bot_id, categories::slug))
.load::<(String, String)>(conn)
.await?;

let encodable_bots = bot_list
.into_iter()
.map(|bot| {
let bot_id = bot.id.clone();
let cat_slugs = cats
.iter()
.filter(|(id, _)| *id == bot_id)
.map(|(_, slug)| slug.clone())
.collect::<Vec<_>>();

EncodableBot::from_with_no_desc(bot, cat_slugs)
})
.collect();

Ok(encodable_bots)
}

let selection = Bot::as_select();

let new_bots = bots::table
.order(bots::created_at.desc())
.select(selection)
.limit(10)
.load(&mut conn)
.await?;

let just_updated = bots::table
.filter(bots::updated_at.ne(bots::created_at))
.order(bots::updated_at.desc())
.select(selection)
.limit(10)
.load(&mut conn)
.await?;

// TODO: top rated, most voted
Ok(Json(json!({
"num_bots": num_bots,
"new_bots": encode_bots(&mut conn, new_bots).await?,
"just_updated": encode_bots(&mut conn, just_updated).await?,
"popular_categories": popular_categories,
})))
}
2 changes: 1 addition & 1 deletion src/models.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
pub use self::bot::Bot;
pub use self::category::Category;
pub use self::category::{BotCategory, Category};
pub use self::owners::BotOwner;
pub use self::review::BotReview;
pub use self::token::{ApiToken, CreatedApiToken};
Expand Down
2 changes: 1 addition & 1 deletion src/util/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ pub fn service_unavailable() -> BoxedAppError {
}

pub fn bot_not_found(bot: &str) -> BoxedAppError {
let detail = format!("crate `{bot}` does not exist");
let detail = format!("bot `{bot}` does not exist");
custom(StatusCode::NOT_FOUND, detail)
}

Expand Down
54 changes: 45 additions & 9 deletions src/views.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,12 +161,18 @@ pub struct OwnedBot {
pub name: String,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct EncodableBotWithDescription<T> {
#[serde(flatten)]
pub inner: T,
pub description: String,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct EncodableBot {
pub id: String,
pub name: String,
pub avatar: Option<String>,
pub description: String,
pub short_description: String,
pub supported_languages: Vec<Option<BotLanguages>>,
pub categories: Option<Vec<String>>,
Expand All @@ -179,7 +185,7 @@ pub struct EncodableBot {
}

impl EncodableBot {
pub fn from(bot: Bot, categories: Option<&[Category]>) -> Self {
pub fn from(bot: Bot, categories: Option<&[Category]>) -> EncodableBotWithDescription<Self> {
let Bot {
id,
name,
Expand All @@ -196,24 +202,54 @@ impl EncodableBot {

let category_ids = categories.map(|cats| cats.iter().map(|cat| cat.slug.clone()).collect());

EncodableBotWithDescription::<EncodableBot> {
inner: EncodableBot {
id,
name,
updated_at,
created_at,
categories: category_ids,
short_description,
supported_languages,
guild_count,
status: status.into(),
avatar,
},
description,
}
}

pub fn from_minimal(bot: Bot) -> EncodableBotWithDescription<Self> {
Self::from(bot, None)
}

pub fn from_with_no_desc(bot: Bot, categories: Vec<String>) -> Self {
let Bot {
id,
name,
updated_at,
created_at,
short_description,
supported_languages,
guild_count,
status,
avatar,
..
} = bot;

EncodableBot {
id,
name,
updated_at,
created_at,
categories: category_ids,
description,
categories: Some(categories),
short_description,
supported_languages,
guild_count,
status: status.into(),
avatar,
}
}

pub fn from_minimal(bot: Bot) -> Self {
Self::from(bot, None)
}
}

/// The serialization format for the `ApiToken` model with its token value.
Expand All @@ -238,7 +274,7 @@ impl From<CreatedApiToken> for EncodableApiTokenWithToken {

#[derive(Serialize, Deserialize, Debug)]
pub struct GoodBot {
pub bot: EncodableBot,
pub bot: EncodableBotWithDescription<EncodableBot>,
pub warnings: PublishWarnings,
}

Expand Down

0 comments on commit 30305fa

Please sign in to comment.