{"record":{"id":"616b115045e2fe1f","repo":"tonhowtf/omniget","slug":"sem-sess-o-do-goodreads-capture-os-cookies-de-goodreads-com","errorCode":null,"errorMessage":"sem sessão do Goodreads: capture os cookies de goodreads.com na extensão, ou aponte o goodreads_library_export.csv que você já baixou","messagePattern":"sem sessão do Goodreads: capture os cookies de goodreads\\.com na extensão, ou aponte o goodreads_library_export\\.csv que você já baixou","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src-tauri/omniget-core/src/core/tools/lists/goodreads.rs","lineNumber":525,"sourceCode":"// ── Execução ────────────────────────────────────────────────────────────\n\npub async fn run(opts: &Options, p: ProgressFn) -> Result<ExportResult> {\n    if opts.dest.trim().is_empty() {\n        return Err(anyhow!(\"escolha a pasta de destino\"));\n    }\n    let dest = PathBuf::from(opts.dest.trim());\n    std::fs::create_dir_all(&dest)?;\n    let f = Fetcher::new(opts.delay_ms, opts.session_netscape.as_deref(), DOMAIN)?;\n\n    let (csv, source, waited) = match opts.csv_path.as_deref().map(str::trim) {\n        Some(path) if !path.is_empty() => (\n            std::fs::read_to_string(path).with_context(|| format!(\"não consegui ler {}\", path))?,\n            path.to_string(),\n            0,\n        ),\n        _ => {\n            if !f.has_session() {\n                return Err(anyhow!(\n                    \"sem sessão do Goodreads: capture os cookies de goodreads.com na extensão, ou aponte o goodreads_library_export.csv que você já baixou\"\n                ));\n            }\n            let (csv, secs) = trigger_and_wait(&f, opts, &p).await?;\n            let _ = std::fs::write(dest.join(\"goodreads_library_export.csv\"), &csv);\n            (csv, EXPORT_BASE.to_string(), secs)\n        }\n    };\n\n    let mut entries = parse_export_csv(&csv);\n    if entries.is_empty() {\n        return Err(anyhow!(\"o export veio sem nenhum livro\"));\n    }\n\n    // Reviews que o CSV não trouxe, buscadas na prateleira.\n    let mut enriched = 0usize;\n    if !opts.enrich_shelves.is_empty() && f.has_session() {\n        let page = f.get_text(IMPORT_URL).await.unwrap_or_default();","sourceCodeStart":507,"sourceCodeEnd":543,"githubUrl":"https://github.com/tonhowtf/omniget/blob/8600b91f4246848bac346874daa9e61c1fc5677a/src-tauri/omniget-core/src/core/tools/lists/goodreads.rs#L507-L543","documentation":"Thrown by the Goodreads export tool's run() when no local CSV path was provided and the Fetcher has no captured Goodreads session cookies (f.has_session() is false). Without cookies the tool cannot drive goodreads.com to generate and download the export, so it fails fast with instructions.","triggerScenarios":"Calling run with opts.csv_path = None and opts.session_netscape = None (or cookies that failed to load into the Fetcher), so neither a local file nor an authenticated download path is available.","commonSituations":"User never captured cookies in the extension; cookies were captured for the wrong domain; session_netscape points to an empty/missing file; user assumed the tool could download the export anonymously (Goodreads requires a logged-in session for exports).","solutions":["Capture cookies for goodreads.com in the browser extension and pass them via opts.session_netscape.","Export your library manually at goodreads.com/review/import and pass the downloaded goodreads_library_export.csv path via opts.csv_path.","Verify the session_netscape file actually contains Netscape-format cookie lines for the goodreads.com domain.","Re-capture cookies if they were captured before logging in to Goodreads (anonymous cookies don't count as a session)."],"exampleFix":"// before\nlet opts = Options { csv_path: None, session_netscape: None, .. };\ntool::run(&opts, p).await?;\n// after\nlet opts = Options {\n    csv_path: Some(\"./goodreads_library_export.csv\".into()), // or session_netscape: Some(cookies_path.into())\n    ..\n};\ntool::run(&opts, p).await?;","handlingStrategy":"validation","validationCode":"let has_local = opts.csv_path.as_deref().map(str::trim).map(|p| std::path::Path::new(p).is_file()).unwrap_or(false);\nlet has_cookies = opts.session_netscape.is_some();\nanyhow::ensure!(has_local || has_cookies, \"preciso de um CSV local ou de cookies do Goodreads\");","typeGuard":"fn can_run_goodreads(opts: &Options) -> bool {\n    opts.csv_path.as_deref().map(|p| !p.trim().is_empty()).unwrap_or(false)\n        || opts.session_netscape.is_some()\n}","tryCatchPattern":"match run(&opts, &p).await {\n    Err(e) if e.to_string().contains(\"sem sessão do Goodreads\") => {\n        eprintln!(\"abra goodreads.com, capture os cookies na extensão e tente de novo\");\n    }\n    other => other?,\n}","preventionTips":["Capture cookies in the extension while logged in to goodreads.com before first use","Keep a local goodreads_library_export.csv as a fallback (csv_path)","Validate that session_netscape points to a non-empty Netscape cookie file","Re-capture cookies after any logout or password change"],"tags":["authentication","cookies","goodreads"],"backgroundTag":"authentication-required","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"}