Files
seensite/src/main.rs
2025-04-05 17:07:19 -05:00

89 lines
2.1 KiB
Rust

mod config;
mod meilisearch;
mod page;
use meilisearch_sdk::client::Client as MeilisearchClient;
use rocket::fairing::{self, AdHoc};
use rocket::form::Form;
use rocket::serde::json::Json;
use rocket::{Rocket, State};
use tracing::error;
use config::Config;
struct Context {
#[allow(dead_code)]
config: Config,
client: MeilisearchClient,
}
#[derive(Debug, thiserror::Error)]
enum InitError {
#[error("Meilisearch error: {0}")]
Meilisearch(#[from] meilisearch::Error),
}
impl Context {
pub fn init(config: Config) -> Result<Self, InitError> {
let client = MeilisearchClient::try_from(&config)?;
Ok(Self { config, client })
}
}
/// Save page form
#[derive(rocket::FromForm)]
pub struct SavePageForm {
/// Page URL
url: String,
/// Page content (SingleFile HTML)
data: String,
}
/// Save a visited page in SingleFile format
#[rocket::post("/save", data = "<form>")]
async fn save_page(
form: Form<SavePageForm>,
ctx: &State<Context>,
) -> Result<Json<page::Page>, String> {
match page::save_page(&form.url, &form.data, ctx).await {
Ok(p) => Ok(Json(p)),
Err(e) => {
error!("Failed to save page: {}", e);
Err(e.to_string())
},
}
}
/// Set up Meilisearch
async fn meilisearch_setup(rocket: Rocket<rocket::Build>) -> fairing::Result {
let ctx: &Context = rocket.state().unwrap();
let client = &ctx.client;
let config = &ctx.config;
if let Err(e) =
meilisearch::ensure_index(client, &config.meilisearch.index).await
{
error!("Failed to create Meilisearch index: {}", e);
Err(rocket)
} else {
Ok(rocket)
}
}
#[rocket::launch]
async fn rocket() -> _ {
tracing_subscriber::fmt()
.with_env_filter(tracing_subscriber::EnvFilter::from_default_env())
.with_writer(std::io::stderr)
.init();
let rocket = rocket::build();
let config: Config = rocket.figment().extract().unwrap();
let ctx = Context::init(config).unwrap();
rocket
.manage(ctx)
.mount("/", rocket::routes![save_page])
.attach(AdHoc::try_on_ignite("Meilisearch Setup", meilisearch_setup))
}