use serde::Serialize;
use crate::converter::Converter;
#[derive(Debug, Clone, Default)]
pub(crate) enum ContentExtraction {
#[default]
Full,
Selector(String),
Readable,
}
#[derive(Debug, Clone)]
pub(super) struct ConvertConfig {
pub converter: Converter,
pub extract_links: bool,
pub content: ContentExtraction,
}
#[derive(Debug, Clone)]
pub(super) struct HttpResponse {
pub body: String,
pub status_code: u16,
pub content_type: Option<String>,
pub final_url: String,
}
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
#[non_exhaustive]
pub struct ScrapeResult {
pub markdown: String,
pub metadata: Metadata,
#[serde(skip_serializing_if = "Option::is_none")]
pub links: Option<Vec<String>>,
}
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
#[non_exhaustive]
pub struct Metadata {
#[serde(skip_serializing_if = "Option::is_none")]
pub title: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub description: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub language: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub og_image: Option<String>,
pub source_url: String,
pub url: String,
pub status_code: u16,
#[serde(skip_serializing_if = "Option::is_none")]
pub content_type: Option<String>,
pub elapsed_ms: u64,
}
#[derive(Debug, Clone, thiserror::Error)]
#[non_exhaustive]
pub enum ScrapeError {
#[error("HTTP error for {url}: {message}")]
Http {
url: String,
message: String,
},
#[error("too many redirects for {url}")]
TooManyRedirects {
url: String,
},
#[error("{message}")]
Other {
message: String,
url: Option<String>,
},
}
impl ScrapeError {
#[must_use]
pub fn new(message: impl Into<String>, url: Option<String>) -> Self {
Self::Other {
message: message.into(),
url,
}
}
#[must_use]
pub fn url(&self) -> Option<&str> {
match self {
Self::Http { url, .. } | Self::TooManyRedirects { url } => Some(url),
Self::Other { url, .. } => url.as_deref(),
}
}
}
impl Serialize for ScrapeError {
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
use serde::ser::SerializeMap;
let mut map = serializer.serialize_map(None)?;
map.serialize_entry("error", &self.to_string())?;
if let Some(u) = self.url() {
map.serialize_entry("url", u)?;
}
map.end()
}
}