use crate::enums::{ScreenshotFormat, ScreenshotOption, VisionDeficiencyType};
use crate::error::ScrapflyError;
use super::url_safe_b64_encode;
#[derive(Debug, Clone, Default)]
pub struct ScreenshotConfig {
pub url: String,
pub format: Option<ScreenshotFormat>,
pub capture: Option<String>,
pub resolution: Option<String>,
pub country: Option<String>,
pub timeout: Option<u32>,
pub rendering_wait: Option<u32>,
pub wait_for_selector: Option<String>,
pub options: Vec<ScreenshotOption>,
pub auto_scroll: bool,
pub js: Option<String>,
pub cache: bool,
pub cache_ttl: Option<u32>,
pub cache_clear: bool,
pub webhook: Option<String>,
pub vision_deficiency: Option<VisionDeficiencyType>,
}
impl ScreenshotConfig {
pub fn builder(url: impl Into<String>) -> ScreenshotConfigBuilder {
ScreenshotConfigBuilder {
cfg: ScreenshotConfig {
url: url.into(),
..Default::default()
},
}
}
pub fn to_query_pairs(&self) -> Result<Vec<(String, String)>, ScrapflyError> {
if self.url.is_empty() {
return Err(ScrapflyError::Config("url is required".into()));
}
let mut out: Vec<(String, String)> = Vec::new();
out.push(("url".into(), self.url.clone()));
if let Some(f) = self.format {
out.push(("format".into(), f.as_str().into()));
}
if let Some(c) = &self.capture {
out.push(("capture".into(), c.clone()));
}
if let Some(r) = &self.resolution {
out.push(("resolution".into(), r.clone()));
}
if let Some(c) = &self.country {
out.push(("country".into(), c.clone()));
}
if let Some(t) = self.timeout {
out.push(("timeout".into(), t.to_string()));
}
if let Some(w) = self.rendering_wait {
out.push(("rendering_wait".into(), w.to_string()));
}
if let Some(s) = &self.wait_for_selector {
out.push(("wait_for_selector".into(), s.clone()));
}
if self.auto_scroll {
out.push(("auto_scroll".into(), "true".into()));
}
if let Some(js) = &self.js {
out.push(("js".into(), url_safe_b64_encode(js)));
}
if !self.options.is_empty() {
let joined = self
.options
.iter()
.map(|o| o.as_str())
.collect::<Vec<_>>()
.join(",");
out.push(("options".into(), joined));
}
if self.cache {
out.push(("cache".into(), "true".into()));
if let Some(ttl) = self.cache_ttl {
out.push(("cache_ttl".into(), ttl.to_string()));
}
if self.cache_clear {
out.push(("cache_clear".into(), "true".into()));
}
}
if let Some(wh) = &self.webhook {
out.push(("webhook_name".into(), wh.clone()));
}
if let Some(vd) = self.vision_deficiency {
out.push(("vision_deficiency".into(), vd.as_str().into()));
}
Ok(out)
}
}
#[derive(Debug, Clone)]
pub struct ScreenshotConfigBuilder {
cfg: ScreenshotConfig,
}
impl ScreenshotConfigBuilder {
pub fn format(mut self, f: ScreenshotFormat) -> Self {
self.cfg.format = Some(f);
self
}
pub fn capture(mut self, c: impl Into<String>) -> Self {
self.cfg.capture = Some(c.into());
self
}
pub fn resolution(mut self, r: impl Into<String>) -> Self {
self.cfg.resolution = Some(r.into());
self
}
pub fn country(mut self, c: impl Into<String>) -> Self {
self.cfg.country = Some(c.into());
self
}
pub fn timeout(mut self, t: u32) -> Self {
self.cfg.timeout = Some(t);
self
}
pub fn rendering_wait(mut self, t: u32) -> Self {
self.cfg.rendering_wait = Some(t);
self
}
pub fn wait_for_selector(mut self, s: impl Into<String>) -> Self {
self.cfg.wait_for_selector = Some(s.into());
self
}
pub fn option(mut self, o: ScreenshotOption) -> Self {
self.cfg.options.push(o);
self
}
pub fn auto_scroll(mut self, v: bool) -> Self {
self.cfg.auto_scroll = v;
self
}
pub fn js(mut self, js: impl Into<String>) -> Self {
self.cfg.js = Some(js.into());
self
}
pub fn cache(mut self, v: bool) -> Self {
self.cfg.cache = v;
self
}
pub fn cache_ttl(mut self, v: u32) -> Self {
self.cfg.cache_ttl = Some(v);
self
}
pub fn cache_clear(mut self, v: bool) -> Self {
self.cfg.cache_clear = v;
self
}
pub fn webhook(mut self, v: impl Into<String>) -> Self {
self.cfg.webhook = Some(v.into());
self
}
pub fn vision_deficiency(mut self, v: VisionDeficiencyType) -> Self {
self.cfg.vision_deficiency = Some(v);
self
}
pub fn build(self) -> Result<ScreenshotConfig, ScrapflyError> {
if self.cfg.url.is_empty() {
return Err(ScrapflyError::Config("url is required".into()));
}
Ok(self.cfg)
}
}