{"record":{"id":"bd5cfe9bd057074c","repo":"tonhowtf/omniget","slug":"cole-o-link-do-v-deo-do-bilibili","errorCode":null,"errorMessage":"cole o link do vídeo do Bilibili","messagePattern":"cole o link do vídeo do Bilibili","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src-tauri/src/platforms/bilibili/danmaku/export.rs","lineNumber":78,"sourceCode":"}\n\n#[derive(Debug, Clone, Serialize)]\npub struct ExportResult {\n    pub title: String,\n    pub part: DanmakuPart,\n    /// Todas as partes que a URL tem, para a UI montar o seletor.\n    pub parts: Vec<DanmakuPart>,\n    pub fetched: usize,\n    pub kept: usize,\n    pub files: Vec<ExportFile>,\n    /// `true` quando saiu com a sessão de uma conta, não anônimo.\n    pub with_account: bool,\n}\n\npub async fn run(opts: &ExportOptions, progress: &ProgressFn) -> Result<ExportResult> {\n    let url = opts.url.trim();\n    if url.is_empty() {\n        return Err(anyhow!(\"cole o link do vídeo do Bilibili\"));\n    }\n    report(progress, ID, \"started\", 0, Some(4), None);\n\n    // Cookies anônimos (buvid3/buvid4/bili_ticket): sem eles a assinatura WBI\n    // do endpoint de danmaku é recusada em boa parte dos vídeos.\n    if let Err(e) = cookie::ensure_fresh().await {\n        tracing::warn!(\"[bili-danmaku] cookies anônimos falharam: {:?}\", e);\n    }\n    let slug = active_account_slug();\n    let with_account = slug.is_some();\n    let client = build_client(slug.as_deref())?;\n\n    report(\n        progress,\n        ID,\n        \"progress\",\n        1,\n        Some(4),","sourceCodeStart":60,"sourceCodeEnd":96,"githubUrl":"https://github.com/tonhowtf/omniget/blob/8600b91f4246848bac346874daa9e61c1fc5677a/src-tauri/src/platforms/bilibili/danmaku/export.rs#L60-L96","documentation":"export::run trims opts.url and throws 'cole o link do vídeo do Bilibili' when the result is empty. This is a required-input guard: the export pipeline needs a Bilibili video URL before it can fetch cookies and danmaku.","triggerScenarios":"Calling bilibili::danmaku::export::run with ExportOptions { url: \"\" } or a whitespace-only string; the frontend bound an empty input field.","commonSituations":"User clicked export before pasting a link; form state reset to empty string; a previous pipeline step produced an empty URL variable.","solutions":["Validate/require a non-empty URL in the UI before invoking export","Check that the field binding actually passes the user's input into ExportOptions.url","In callers, bail early with a clear message when url.trim().is_empty()"],"exampleFix":"// before\nexport::run(&ExportOptions { url: form.url, ..opts }).await?;\n// after\nanyhow::ensure!(!form.url.trim().is_empty(), \"informe o link do vídeo\");\nexport::run(&ExportOptions { url: form.url.clone(), ..opts }).await?;","handlingStrategy":"validation","validationCode":"fn url_present(url: &str) -> bool {\n    !url.trim().is_empty()\n}","typeGuard":null,"tryCatchPattern":"match export::run(&opts, &progress).await {\n    Err(e) if e.to_string().contains(\"cole o link\") => focus_url_input_and_prompt_user(),\n    Err(e) => propagate(e)?,\n    Ok(res) => use_result(res),\n}","preventionTips":["Disable the export button until the URL field is non-empty","Trim inputs at the UI boundary before constructing ExportOptions","Validate required fields in one place before calling pipeline stages"],"tags":["validation","empty-input","url","bilibili"],"backgroundTag":"empty-required-field","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"}