feat: trending and categories routes

This commit is contained in:
Zomatree
2025-09-11 14:18:28 +01:00
committed by Angelo Kontaxis
parent a92152d86d
commit 5885e067a6
10 changed files with 437 additions and 148 deletions

View File

@@ -0,0 +1,47 @@
use axum::{
extract::{Query, State},
Json,
};
use revolt_database::User;
use revolt_result::{create_error, Result};
use serde::Deserialize;
use utoipa::IntoParams;
use crate::{tenor, types};
#[derive(Deserialize, IntoParams)]
pub struct CategoriesQueryParams {
#[param(example = "en_US")]
pub locale: String,
}
/// Trending GIF categories
#[utoipa::path(
get,
path = "/categories",
tag = "GIFs",
security(("User Token" = []), ("Bot Token" = [])),
params(CategoriesQueryParams),
responses(
(status = 200, description = "Categories results", body = inline(Vec<types::CategoryResponse>))
)
)]
pub async fn categories(
_user: User,
Query(params): Query<CategoriesQueryParams>,
State(tenor): State<tenor::Tenor>,
) -> Result<Json<Vec<types::CategoryResponse>>> {
tenor
.categories(&params.locale)
.await
.map_err(|_| create_error!(InternalError))
.map(|results| {
(*results)
.clone()
.tags
.into_iter()
.map(|cat| cat.into())
.collect()
})
.map(Json)
}

View File

@@ -0,0 +1,15 @@
use crate::AppState;
use axum::routing::{get, Router};
pub mod categories;
pub mod root;
pub mod search;
pub mod trending;
pub fn router() -> Router<AppState> {
Router::new()
.route("/", get(root::root))
.route("/categories", get(categories::categories))
.route("/search", get(search::search))
.route("/trending", get(trending::trending))
}

View File

@@ -0,0 +1,22 @@
use axum::Json;
use crate::types;
/// Capture crate version from Cargo
static CRATE_VERSION: &str = env!("CARGO_PKG_VERSION");
/// Root response from service
#[utoipa::path(
get,
path = "/",
tag = "Misc",
responses(
(status = 200, description = "Root response", body = inline(types::RootResponse))
)
)]
pub async fn root() -> Json<types::RootResponse<'static>> {
Json(types::RootResponse {
message: "Gifbox lives on!",
version: CRATE_VERSION,
})
}

View File

@@ -0,0 +1,51 @@
use axum::{
extract::{Query, State},
Json,
};
use revolt_database::User;
use revolt_result::{create_error, Result};
use serde::Deserialize;
use utoipa::IntoParams;
use crate::{tenor, types};
#[derive(Deserialize, IntoParams)]
pub struct SearchQueryParams {
#[param(example = "Wave")]
pub query: String,
#[param(example = "en_US")]
pub locale: String,
pub limit: Option<u32>,
pub is_category: Option<bool>,
pub position: Option<String>,
}
/// Searches for GIFs with a query
#[utoipa::path(
get,
path = "/search",
tag = "GIFs",
security(("User Token" = []), ("Bot Token" = [])),
params(SearchQueryParams),
responses(
(status = 200, description = "Search results", body = inline(types::PaginatedMediaResponse))
)
)]
pub async fn search(
_user: User,
Query(params): Query<SearchQueryParams>,
State(tenor): State<tenor::Tenor>,
) -> Result<Json<types::PaginatedMediaResponse>> {
tenor
.search(
&params.query,
&params.locale,
params.limit.unwrap_or(50),
params.is_category.unwrap_or_default(),
params.position.as_deref().unwrap_or_default(),
)
.await
.map_err(|_| create_error!(InternalError))
.map(|results| results.as_ref().clone().into())
.map(Json)
}

View File

@@ -0,0 +1,45 @@
use axum::{
extract::{Query, State},
Json,
};
use revolt_database::User;
use revolt_result::{create_error, Result};
use serde::{Deserialize};
use utoipa::{IntoParams};
use crate::{
tenor,
types,
};
#[derive(Deserialize, IntoParams)]
pub struct TrendingQueryParams {
#[param(example = "en_US")]
pub locale: String,
pub limit: Option<u32>,
pub position: Option<String>
}
/// Trending GIFs
#[utoipa::path(
get,
path = "/featured",
tag = "GIFs",
security(("User Token" = []), ("Bot Token" = [])),
params(TrendingQueryParams),
responses(
(status = 200, description = "Trending results", body = inline(types::PaginatedMediaResponse))
)
)]
pub async fn trending(
_user: User,
Query(params): Query<TrendingQueryParams>,
State(tenor): State<tenor::Tenor>,
) -> Result<Json<types::PaginatedMediaResponse>> {
tenor
.featured(&params.locale, params.limit.unwrap_or(50), params.position.as_deref().unwrap_or_default())
.await
.map_err(|_| create_error!(InternalError))
.map(|results| results.as_ref().clone().into())
.map(Json)
}