Files
consume-rs/backend/src/fetch/mod.rs
T
2026-06-17 10:59:45 +02:00

40 lines
1.3 KiB
Rust

//! Product data adapters. The deal source is a user-pasted product URL — no
//! per-retailer scrapers. Adapters are generic platform readers; the first is
//! Shopify, whose storefronts expose a public `/products/{handle}.json` document.
use rust_decimal::Decimal;
mod shopify;
/// Normalised product snapshot produced by an adapter.
#[derive(Debug, Clone)]
pub struct FetchedProduct {
pub title: String,
pub price: Decimal,
pub currency: String,
pub image_url: Option<String>,
pub in_stock: Option<bool>,
pub source: &'static str,
}
/// A shared HTTP client tuned for storefront fetches.
pub fn http_client() -> reqwest::Client {
reqwest::Client::builder()
.user_agent("consumers-bot/0.1 (+self-hosted wantlist price watcher)")
.timeout(std::time::Duration::from_secs(15))
.build()
.expect("failed to build reqwest client")
}
/// Try every adapter in turn. Returns the first that recognises the URL.
pub async fn fetch_product(
client: &reqwest::Client,
url: &str,
default_currency: &str,
) -> anyhow::Result<FetchedProduct> {
if let Some(p) = shopify::fetch(client, url, default_currency).await? {
return Ok(p);
}
anyhow::bail!("no adapter could read this URL (only Shopify storefronts are supported for now)")
}