{"record":{"id":"0275f2d4069f700b","repo":"tonhowtf/omniget","slug":"cole-um-link-do-calameo-com","errorCode":null,"errorMessage":"cole um link do calameo.com","messagePattern":"cole um link do calameo\\.com","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"src-tauri/omniget-core/src/core/tools/calameo.rs","lineNumber":32,"sourceCode":"    pub pages: usize,\n    pub folder: String,\n    pub format: String,\n}\n\npub fn page_prefix(html: &str) -> Option<String> {\n    let re = regex::Regex::new(r#\"<meta[^>]*property=\"og:image\"[^>]*content=\"([^\"]+)\"\"#).ok()?;\n    let img = re.captures(html)?[1].to_string();\n    let re2 = regex::Regex::new(r\"^(.*?/)p?1\\.(svgz|jpg|jpeg|png)\").ok()?;\n    re2.captures(&img).map(|c| c[1].to_string())\n}\n\npub async fn download(\n    url: &str,\n    dest_dir: &str,\n    progress: super::ProgressFn,\n) -> anyhow::Result<CalameoResult> {\n    if !url.contains(\"calameo.com\") {\n        return Err(anyhow!(\"cole um link do calameo.com\"));\n    }\n    let client = super::client()?;\n    let html = client\n        .get(url)\n        .send()\n        .await?\n        .error_for_status()?\n        .text()\n        .await?;\n    let prefix = page_prefix(&html)\n        .ok_or_else(|| anyhow!(\"nao achei as paginas desse documento (privado ou layout novo)\"))?;\n    let title = super::slides::og_title(&html).unwrap_or_else(|| \"calameo\".to_string());\n    let folder = PathBuf::from(dest_dir).join(super::sanitize_name(&title));\n    std::fs::create_dir_all(&folder)?;\n    let id = format!(\"calameo:{}\", url);\n    let mut n = 0usize;\n    let mut format = \"svg\".to_string();\n    for page in 1..=2000usize {","sourceCodeStart":14,"sourceCodeEnd":50,"githubUrl":"https://github.com/tonhowtf/omniget/blob/8600b91f4246848bac346874daa9e61c1fc5677a/src-tauri/omniget-core/src/core/tools/calameo.rs#L14-L50","documentation":"calameo::download performs a cheap substring check on the provided URL and rejects anything that does not contain 'calameo.com' before making any network request. It is a guard against passing documents from other services or malformed input to the Calameo downloader.","triggerScenarios":"Calling download(url, dest_dir, progress) with a URL from another provider (issuu, scribd), a bare document ID, an empty string, or a typo'd domain (e.g. 'calameo.org').","commonSituations":"Mixing up URL strings in a batch-download script; user pasting an embedded-viewer URL on a different host; clipboard missing part of the URL.","solutions":["Pass the full public Calameo URL, e.g. https://www.calameo.com/read/0056...— including the calameo.com host","Normalize the input before calling download (prepend https://www.calameo.com/... if you only have an ID and know the path format)","Route non-calameo URLs to the appropriate tool instead of calameo::download"],"exampleFix":"// before\ncalameo::download(\"005678901abcdef2345\", &dest, progress).await?;\n// after\ncalameo::download(\"https://www.calameo.com/read/005678901abcdef2345\", &dest, progress).await?;","handlingStrategy":"validation","validationCode":"let url = url.trim();\nif !url.starts_with(\"http\") || !url.contains(\"calameo.com\") {\n    anyhow::bail!(\"expected a calameo.com URL\");\n}","typeGuard":"fn is_calameo_url(url: &str) -> bool { url.contains(\"calameo.com\") }","tryCatchPattern":null,"preventionTips":["Normalize URLs (trim, add scheme) before dispatching to a downloader tool","Route by domain: build a small matcher that picks the right tool per host","Validate URLs at input boundaries (paste handlers, batch files) rather than at download time"],"tags":["calameo","url-validation","rust"],"backgroundTag":"invalid-url","analyzedSha":"8600b91f4246848bac346874daa9e61c1fc5677a","analyzedAt":"2026-09-12T14:29:19.317Z","contentChangedAt":"2026-09-12T14:29:19.317Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}