113 lines
3.1 KiB
Rust
113 lines
3.1 KiB
Rust
use std::net::{Ipv4Addr, SocketAddr};
|
|
|
|
use axum::{extract::FromRef, middleware::from_fn_with_state, Router};
|
|
|
|
use revolt_config::config;
|
|
use revolt_database::{Database, DatabaseInfo};
|
|
use revolt_ratelimits::axum as ratelimiter;
|
|
use tokio::net::TcpListener;
|
|
use utoipa::{
|
|
openapi::security::{ApiKey, ApiKeyValue, SecurityScheme},
|
|
Modify, OpenApi,
|
|
};
|
|
use utoipa_scalar::{Scalar, Servable as ScalarServable};
|
|
|
|
use crate::tenor::Tenor;
|
|
|
|
mod ratelimits;
|
|
mod routes;
|
|
mod tenor;
|
|
mod types;
|
|
|
|
#[derive(Clone, FromRef)]
|
|
struct AppState {
|
|
pub database: Database,
|
|
pub tenor: Tenor,
|
|
pub ratelimit_storage: ratelimiter::RatelimitStorage,
|
|
}
|
|
|
|
struct SecurityAddon;
|
|
|
|
impl Modify for SecurityAddon {
|
|
fn modify(&self, openapi: &mut utoipa::openapi::OpenApi) {
|
|
let components = openapi.components.get_or_insert_default();
|
|
|
|
components.add_security_scheme(
|
|
"User Token",
|
|
SecurityScheme::ApiKey(ApiKey::Header(ApiKeyValue::new(
|
|
"X-Session-Token".to_string(),
|
|
))),
|
|
);
|
|
|
|
components.add_security_scheme(
|
|
"Bot Token",
|
|
SecurityScheme::ApiKey(ApiKey::Header(ApiKeyValue::new("X-Bot-Token".to_string()))),
|
|
);
|
|
}
|
|
}
|
|
|
|
#[tokio::main]
|
|
async fn main() -> Result<(), std::io::Error> {
|
|
// Configure logging and environment
|
|
revolt_config::configure!(gifbox);
|
|
|
|
// Configure API schema
|
|
#[derive(OpenApi)]
|
|
#[openapi(
|
|
modifiers(&SecurityAddon),
|
|
paths(
|
|
routes::categories::categories,
|
|
routes::root::root,
|
|
routes::search::search,
|
|
routes::trending::trending,
|
|
),
|
|
tags(
|
|
(name = "Misc", description = "Misc routes for microservice."),
|
|
(name = "GIFs", description = "All routes for requesting GIFs from tenor.")
|
|
),
|
|
components(
|
|
schemas(
|
|
revolt_result::Error,
|
|
revolt_result::ErrorType,
|
|
types::MediaResult,
|
|
types::MediaObject,
|
|
)
|
|
),
|
|
)]
|
|
struct ApiDoc;
|
|
|
|
let config = config().await;
|
|
|
|
let database = DatabaseInfo::Auto
|
|
.connect()
|
|
.await
|
|
.expect("Unable to connect to database");
|
|
|
|
let tenor = tenor::Tenor::new(&config.api.security.tenor_key);
|
|
|
|
let ratelimit_storage = ratelimiter::RatelimitStorage::new(ratelimits::GifboxRatelimits);
|
|
|
|
let state = AppState {
|
|
database,
|
|
tenor,
|
|
ratelimit_storage,
|
|
};
|
|
|
|
// Configure Axum and router
|
|
let app = Router::new()
|
|
.merge(Scalar::with_url("/scalar", ApiDoc::openapi()))
|
|
.nest("/", routes::router())
|
|
.layer(from_fn_with_state(
|
|
state.clone(),
|
|
ratelimiter::ratelimit_middleware,
|
|
))
|
|
.with_state(state);
|
|
|
|
// Configure TCP listener and bind
|
|
tracing::info!("Listening on 0.0.0.0:14706");
|
|
tracing::info!("Play around with the API: http://localhost:14706/scalar");
|
|
let address = SocketAddr::from((Ipv4Addr::UNSPECIFIED, 14706));
|
|
let listener = TcpListener::bind(&address).await?;
|
|
axum::serve(listener, app.into_make_service()).await
|
|
}
|