A practical Douyin downloader for both single-item and profile batch downloads, with progress display, retries, SQLite deduplication, and browser fallback support. 抖音批量下载工具,去水印,支持视频、图集、合集、音乐(原声)。
This report summarizes scanner evidence for jiji262/douyin-downloader, a Python project with 12,254 GitHub stars. SynthScan examined 39,983 lines of code across 160 source files, recording 1339 pattern matches distributed across 14 syntactic categories. The legacy adjusted pattern signal is 49.9 (High pattern signal); it is not an authorship estimate.
Use the findings to ask whether maintainers can explain intent, verify dependencies, simplify unnecessary scaffolding, and focus review effort. Risk Payload v1 adds ownership, supply-chain, over-engineering, and review-effort vectors when available. These are prompts for human verification, not probabilities, security findings, or measured maintenance costs.
Use each vector to guide manual verification of the underlying findings.
Can maintainers explain intent, assumptions, and trade-offs? 903 finding(s).
Are imports declared and package/API names verified? 103 finding(s).
Are wrappers, guards, and repeated structures necessary? 1192 finding(s).
Which changes need focused human review? 1339 finding(s).
This chart tracks the legacy adjusted pattern score across scan runs. Changes can reflect source changes, scan coverage, or detector/scoring versions; they do not measure AI adoption or prove that a team refactored code. Compare runs only when their scoring versions are compatible. The dashed line tracks the raw pattern-hit count.
Groups findings by configured severity weight. Severity is not a confidence estimate, security rating, or proof that a package is missing. Verify imports against the project's manifests and inspect each finding in its local design context.
This horizontal bar chart shows where configured pattern scores accumulate across directories. Treat the bars as locations to inspect, not as evidence of authorship or code quality. Use the file-level findings to decide whether a directory needs a focused ownership, dependency, complexity, or review check.
The scanner identified 1339 distinct pattern matches across 14 syntactic categories. Each entry below represents a discrete location in the source code where the engine recorded a detector match to inspect in context. Expand any category row to inspect the individual file paths, line numbers, code snippets, and the lexical context (CODE, COMMENT, or STRING) in which each match was detected.
Reading the findings table: The Severity column indicates the configured finding weight (CRITICAL / HIGH / MEDIUM / LOW). The Context column identifies whether the match occurred inside executable code, an inline comment, or a string literal — legacy comment-context matches receive a ×1.5 score weight. The ⚡ bolt icon marks clustered matches: three or more patterns within a 10-line window, each receiving an additional ×1.5 density multiplier under the legacy scoring model.
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | tools/cookie_fetcher.py | 229 | async def wait_for_login_confirmation(page: Any, url: str, input_func: Any = input) -> None: | CODE |
| LOW | tools/cookie_fetcher.py | 335 | def extract_ms_token_from_text(text: str) -> Optional[str]: | STRING |
| LOW | core/user_downloader.py | 193 | async def _save_homepage_screenshot( | CODE |
| LOW | core/user_downloader.py | 236 | async def _resolve_user_info_logged(self, sec_uid: str, modes: List[str]) -> Dict[str, Any]: | CODE |
| LOW | core/user_downloader.py | 520 | async def _recover_user_post_with_browser( | CODE |
| LOW | core/user_downloader.py | 676 | def _browser_recovery_unavailable_reason(self) -> Optional[str]: | CODE |
| LOW | core/user_downloader.py | 686 | def _browser_backend_missing_reason() -> str: | CODE |
| LOW | core/user_downloader.py | 701 | def _post_recovery_limit_reached( | CODE |
| LOW | core/mix_downloader.py | 22 | def derive_mix_collection_dir(mix_detail: Optional[Dict[str, Any]], mix_id: Any) -> str: | CODE |
| LOW | core/mix_downloader.py | 161 | def _stop_reason_for_empty_page( | CODE |
| LOW | core/transcript_manager.py | 50 | def resolve_api_key_with_source( | CODE |
| LOW | core/transcript_manager.py | 317 | async def _call_openai_transcription( | CODE |
| LOW | core/transcript_manager.py | 382 | def _guess_video_content_type(video_path: Path) -> str: | CODE |
| LOW | core/retry_executor.py | 70 | def _derive_url_type_for_factory(url_type: Optional[str]) -> str: | CODE |
| LOW⚡ | core/api_client.py | 2108 | async def _extract_aweme_ids_from_page(self, page) -> List[str]: | CODE |
| LOW | core/api_client.py | 686 | def _payload_from_bridge_result(self, result: Any, path: str, started: float) -> Dict[str, Any]: | CODE |
| LOW | core/api_client.py | 793 | def _bridge_answer_is_transient(result: Any, status: int) -> bool: | CODE |
| LOW | core/api_client.py | 806 | def _unavailable_paged_response(cls, *, item_keys: List[str]) -> Dict[str, Any]: | CODE |
| LOW | core/api_client.py | 818 | def _normalize_paged_response( | CODE |
| LOW | core/api_client.py | 1028 | async def _collect_user_series_as_mixes( | CODE |
| LOW | core/api_client.py | 1152 | async def _build_collect_page_params(self, max_cursor: int, count: int) -> Dict[str, Any]: | CODE |
| LOW | core/api_client.py | 1321 | def _normalize_live_room_response(raw: Dict[str, Any]) -> Optional[Dict[str, Any]]: | CODE |
| LOW | core/api_client.py | 1352 | def _extract_live_room_from_html(html: str) -> Optional[Dict[str, Any]]: | CODE |
| LOW | core/api_client.py | 1368 | async def _fetch_live_room_from_page(self, web_rid: str) -> Optional[Dict[str, Any]]: | CODE |
| LOW | core/api_client.py | 1651 | async def get_aweme_comment_replies( | CODE |
| LOW | core/api_client.py | 1710 | async def save_user_homepage_screenshot( | CODE |
| LOW | core/api_client.py | 1824 | def _emit_homepage_screenshot_request( | CODE |
| LOW | core/api_client.py | 1856 | async def collect_user_post_ids_via_browser( | CODE |
| LOW | core/api_client.py | 2082 | def pop_browser_post_aweme_items(self) -> Dict[str, Dict[str, Any]]: | CODE |
| LOW⚡ | core/api_client.py | 2149 | async def _wait_for_manual_verification(self, page, *, wait_timeout_seconds: int) -> None: | STRING |
| LOW | core/video_downloader.py | 62 | async def _collect_comments_for_existing_video(self, aweme_data: Dict[str, Any]) -> bool: | CODE |
| LOW | core/downloader_base.py | 257 | def _report_author_output_dir( | CODE |
| LOW | core/downloader_base.py | 364 | def _redownload_missing_files_enabled(self) -> bool: | CODE |
| LOW | core/downloader_base.py | 370 | async def _ensure_local_aweme_index(self) -> None: | CODE |
| LOW | core/downloader_base.py | 425 | def _mark_local_aweme_downloaded(self, aweme_id: str): | CODE |
| LOW | core/downloader_base.py | 544 | def _build_aweme_file_context( | CODE |
| LOW | core/downloader_base.py | 600 | async def _collect_comments_for_existing_aweme( | CODE |
| LOW | core/downloader_base.py | 984 | async def _download_video_with_fallback( | CODE |
| LOW | core/downloader_base.py | 1046 | async def _run_within_item_deadline( | CODE |
| LOW | core/downloader_base.py | 1062 | async def _download_first_available( | CODE |
| LOW | core/downloader_base.py | 1141 | def _build_video_url_candidates( | CODE |
| LOW | core/downloader_base.py | 1178 | def _partition_video_candidates( | CODE |
| LOW | core/downloader_base.py | 1268 | async def _maybe_promote_original_candidate( | CODE |
| LOW | core/downloader_base.py | 1313 | async def _probe_original_play_source( | CODE |
| LOW | core/downloader_base.py | 1427 | def _pick_highest_quality_play_addr(video: Dict[str, Any]) -> Optional[Dict[str, Any]]: | CODE |
| LOW | core/downloader_base.py | 1436 | def _pick_play_addr_by_quality( | CODE |
| LOW | core/downloader_base.py | 1487 | def _pick_preferred_play_addr( | CODE |
| LOW | core/downloader_base.py | 1524 | def _collect_image_url_candidates(self, aweme_data: Dict[str, Any]) -> List[List[str]]: | CODE |
| LOW | core/downloader_base.py | 1606 | def _collect_ranked_media_urls(*sources: Tuple[Any, Any, int]) -> List[str]: | CODE |
| LOW | core/downloader_base.py | 1663 | def _is_watermarked_media_url(url: str) -> bool: | CODE |
| LOW | core/user_modes/post_strategy.py | 121 | def _browser_recovery_available(self) -> bool: | CODE |
| LOW | core/user_modes/post_strategy.py | 223 | def _time_boundary_for_config(self) -> PostTimeBoundary: | CODE |
| LOW | core/user_modes/post_strategy.py | 251 | def _report_time_boundary_stop(self, page_number: int, raw_items_seen: int) -> None: | CODE |
| LOW | core/user_modes/base_strategy.py | 59 | async def fetch_page_folding_bridge_failure(fetcher: Any, *args: Any, **kwargs: Any) -> Any: | CODE |
| LOW | core/user_modes/base_strategy.py | 98 | def hard_page_failure_message(page: Dict[str, Any], detail: str) -> str: | CODE |
| LOW | core/user_modes/base_strategy.py | 173 | def _empty_page_failure_cause(cls, page: Dict[str, Any]) -> Optional[str]: | CODE |
| LOW | core/user_modes/base_strategy.py | 193 | def _raise_if_page_request_failed( | CODE |
| LOW | core/user_modes/base_strategy.py | 229 | def _media_type_filter_enabled(self) -> bool: | CODE |
| LOW | config/config_loader.py | 134 | def _is_key_explicit_in_sources(sources: List[Dict[str, Any]], section: str, key: str) -> bool: | CODE |
| LOW | config/config_loader.py | 289 | def _candidate_auto_cookie_paths(self) -> List[Path]: | CODE |
| 796 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM⚡ | core/item_reasons.py | 15 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | core/item_reasons.py | 17 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | core/item_reasons.py | 27 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | core/item_reasons.py | 29 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | core/item_reasons.py | 40 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | core/item_reasons.py | 42 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | core/item_reasons.py | 56 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | core/item_reasons.py | 58 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | core/item_reasons.py | 63 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | core/item_reasons.py | 65 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | core/item_reasons.py | 79 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | core/item_reasons.py | 81 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | core/audio_extraction.py | 23 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | core/audio_extraction.py | 25 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | core/audio_extraction.py | 76 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | core/audio_extraction.py | 78 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | core/audio_extraction.py | 222 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | core/audio_extraction.py | 224 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | core/transcript_manager.py | 194 | # ------------------------------------------------------------------ | COMMENT |
| MEDIUM | core/transcript_manager.py | 200 | # ------------------------------------------------------------------ | COMMENT |
| MEDIUM⚡ | tests/test_api_client.py | 1220 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/test_api_client.py | 1222 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/test_api_client.py | 861 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/test_api_client.py | 863 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/test_api_client.py | 1045 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/test_api_client.py | 1052 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/test_api_client.py | 1284 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/test_api_client.py | 1286 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/test_notifier_redactor_property.py | 80 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/test_notifier_redactor_property.py | 82 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/test_notifier_redactor_property.py | 131 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/test_notifier_redactor_property.py | 133 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/test_notifier_redactor_property.py | 180 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/test_notifier_redactor_property.py | 182 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/test_notifier_redactor_property.py | 216 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/test_notifier_redactor_property.py | 218 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/test_notifier_redactor_property.py | 266 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/test_notifier_redactor_property.py | 268 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/test_notifier_redactor_property.py | 51 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/test_notifier_redactor_property.py | 53 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/test_downloader_author_sec_uid.py | 44 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/test_downloader_author_sec_uid.py | 46 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/test_downloader_author_sec_uid.py | 74 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/test_downloader_author_sec_uid.py | 76 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/test_downloader_author_sec_uid.py | 350 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/test_downloader_author_sec_uid.py | 358 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/test_downloader_author_sec_uid.py | 251 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/test_downloader_author_sec_uid.py | 253 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/test_database.py | 258 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/test_database.py | 260 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/test_ms_token_manager.py | 112 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/test_ms_token_manager.py | 116 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/test_user_mode_strategies.py | 901 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/test_user_mode_strategies.py | 903 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/test_transcript_manager_audio.py | 198 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/test_transcript_manager_audio.py | 200 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/test_transcript_manager_audio.py | 313 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/test_transcript_manager_audio.py | 315 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/test_transcript_manager_audio.py | 356 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/test_transcript_manager_audio.py | 358 | # --------------------------------------------------------------------------- | COMMENT |
| 122 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| HIGH | tools/cookie_fetcher.py | 294 | if (typeof v === 'string' && v.trim()) values.push(v.trim()); | CODE |
| HIGH⚡ | core/api_client.py | 95 | style.opacity !== "0" && rect.width > 0 && rect.height > 0 && | CODE |
| HIGH⚡ | core/api_client.py | 96 | rect.bottom > 0 && rect.top < Math.max(window.innerHeight || 0, 900); | CODE |
| HIGH⚡ | core/api_client.py | 96 | rect.bottom > 0 && rect.top < Math.max(window.innerHeight || 0, 900); | CODE |
| HIGH⚡ | core/api_client.py | 115 | const text = normalize(element.innerText || element.textContent); | CODE |
| HIGH⚡ | core/api_client.py | 116 | if (!text || text.length > 1500) return null; | CODE |
| HIGH⚡ | core/api_client.py | 116 | if (!text || text.length > 1500) return null; | CODE |
| HIGH⚡ | core/api_client.py | 122 | if (!values[1] || Math.max(beforeCount, afterCount) < 2) return null; | CODE |
| HIGH⚡ | core/api_client.py | 123 | if (expectedNickname && !text.includes(expectedNickname)) return null; | CODE |
| HIGH⚡ | core/api_client.py | 130 | if (document.fonts && document.fonts.status !== "loaded") return reset(); | CODE |
| HIGH⚡ | core/api_client.py | 2114 | if (!id || seen.has(id)) return; | CODE |
| HIGH⚡ | core/api_client.py | 2116 | result.push(id); | CODE |
| HIGH⚡ | core/api_client.py | 2122 | while ((match = pattern.exec(text)) !== null) { | CODE |
| HIGH | core/api_client.py | 82 | const bodyText = normalize(document.body.innerText || document.body.textContent); | CODE |
| HIGH | core/api_client.py | 1356 | args = json.loads(call[len("self.__pace_f.push(") : -1]) | CODE |
| HIGH | tests/test_api_client.py | 453 | html = f"<script>self.__pace_f.push({json.dumps([1, flight])})</script>" | CODE |
| HIGH | tests/test_api_client.py | 1187 | """``{"aweme_list": null}`` 不是「空列表」,两者不能被归一化成同一个形状。 | STRING |
| HIGH | tests/test_mix_downloader.py | 362 | """``{"aweme_list": null}`` 走真实归一化层必须带出 ``items_missing``, | STRING |
| HIGH | tests/test_post_walk_completeness.py | 282 | """``{"aweme_list": null}`` 经归一化后 items 也是 [],但它不是可信的空列表。""" | STRING |
| HIGH | cli/login_flow.py | 51 | "\n pip install playwright && playwright install chromium" | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | tools/cookie_fetcher.py | 110 | except Exception: | CODE |
| LOW | tools/cookie_fetcher.py | 197 | except Exception as exc: | CODE |
| LOW | tools/cookie_fetcher.py | 213 | except Exception as exc: | CODE |
| LOW | tools/cookie_fetcher.py | 244 | except Exception as exc: | CODE |
| LOW | tools/cookie_fetcher.py | 250 | except Exception as exc: | CODE |
| LOW | tools/cookie_fetcher.py | 287 | except Exception: | CODE |
| LOW | tools/cookie_fetcher.py | 329 | except Exception: | STRING |
| LOW | core/music_downloader.py | 208 | except Exception as exc: | CODE |
| LOW | core/music_downloader.py | 218 | except Exception as exc: | CODE |
| LOW⚡ | core/audio_extraction.py | 159 | except Exception as exc: # imageio_ffmpeg raises RuntimeError on | CODE |
| LOW | core/audio_extraction.py | 196 | except Exception as exc: | CODE |
| LOW | core/audio_extraction.py | 347 | except Exception as exc: # pragma: no cover - defensive | CODE |
| LOW | core/audio_extraction.py | 353 | except Exception as exc: # pragma: no cover - defensive | CODE |
| LOW | core/discovery.py | 81 | except Exception: # noqa: BLE001 | CODE |
| LOW | core/user_downloader.py | 147 | except Exception as exc: # noqa: BLE001 - 任何失败都归为"解析不出账号" | CODE |
| LOW | core/user_downloader.py | 190 | except Exception as exc: | CODE |
| LOW | core/user_downloader.py | 225 | except Exception as exc: | CODE |
| LOW | core/user_downloader.py | 567 | except Exception: | CODE |
| LOW | core/user_downloader.py | 579 | except Exception as exc: | CODE |
| LOW | core/user_downloader.py | 584 | except Exception as exc: | CODE |
| LOW | core/user_downloader.py | 627 | except Exception as exc: | CODE |
| LOW | core/mix_downloader.py | 183 | except Exception as exc: | CODE |
| LOW | core/ffmpeg.py | 15 | except Exception: | CODE |
| LOW | core/transcript_manager.py | 152 | except Exception: | CODE |
| LOW | core/transcript_manager.py | 270 | except Exception as exc: | CODE |
| LOW | core/transcript_manager.py | 296 | except Exception as exc: # noqa: BLE001 — broad is correct here | CODE |
| LOW | core/live_downloader.py | 112 | except Exception as exc: | CODE |
| LOW | core/live_downloader.py | 273 | except Exception: | CODE |
| LOW | core/live_downloader.py | 278 | except Exception as exc: | CODE |
| LOW | core/live_downloader.py | 328 | except Exception as exc: | CODE |
| LOW | core/comments_collector.py | 76 | except Exception as exc: | CODE |
| LOW | core/retry_executor.py | 181 | except Exception: | CODE |
| LOW | core/retry_executor.py | 189 | except Exception: | CODE |
| LOW | core/retry_executor.py | 213 | except Exception: | CODE |
| LOW | core/retry_executor.py | 230 | except Exception: | CODE |
| LOW | core/retry_executor.py | 242 | except Exception as exc: # pragma: no cover — defensive | CODE |
| LOW | core/retry_executor.py | 259 | except Exception: | CODE |
| LOW | core/retry_executor.py | 268 | except Exception: | CODE |
| LOW | core/api_client.py | 24 | except Exception: # pragma: no cover - optional dependency | CODE |
| LOW | core/api_client.py | 509 | except Exception as exc: | CODE |
| LOW | core/api_client.py | 589 | except Exception: | CODE |
| LOW | core/api_client.py | 594 | except Exception: | CODE |
| LOW | core/api_client.py | 648 | except Exception as exc: | CODE |
| LOW | core/api_client.py | 787 | except Exception as exc: | CODE |
| LOW | core/api_client.py | 997 | except Exception: | CODE |
| LOW | core/api_client.py | 1382 | except Exception as exc: | CODE |
| LOW | core/api_client.py | 1647 | except Exception as exc: # noqa: BLE001 | CODE |
| LOW | core/api_client.py | 1706 | except Exception as e: | CODE |
| LOW | core/api_client.py | 1726 | except Exception as exc: | CODE |
| LOW | core/api_client.py | 1787 | except Exception as exc: | CODE |
| LOW | core/api_client.py | 1794 | except Exception: | CODE |
| LOW | core/api_client.py | 1808 | except Exception as exc: | CODE |
| LOW | core/api_client.py | 1852 | except Exception as exc: | CODE |
| LOW | core/api_client.py | 1869 | except Exception as exc: | CODE |
| LOW | core/api_client.py | 1940 | except Exception: | CODE |
| LOW | core/api_client.py | 1970 | except Exception as exc: | CODE |
| LOW | core/api_client.py | 1979 | except Exception: | CODE |
| LOW | core/api_client.py | 2004 | except Exception as exc: | CODE |
| LOW | core/api_client.py | 2040 | except Exception as exc: | CODE |
| LOW | core/api_client.py | 2051 | except Exception as exc: | CODE |
| 52 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| HIGH | tools/cookie_fetcher.py | 287 | except Exception: | CODE |
| HIGH | tools/cookie_fetcher.py | 329 | except Exception: | CODE |
| HIGH | tools/cookie_fetcher.py | 242 | except asyncio.CancelledError: | CODE |
| HIGH | core/audio_extraction.py | 363 | except FileNotFoundError: | CODE |
| HIGH | core/discovery.py | 81 | except Exception: # noqa: BLE001 | CODE |
| HIGH | core/live_downloader.py | 273 | except Exception: | CODE |
| HIGH | core/retry_executor.py | 181 | except Exception: | CODE |
| HIGH | core/retry_executor.py | 189 | except Exception: | CODE |
| HIGH | core/retry_executor.py | 213 | except Exception: | CODE |
| HIGH | core/retry_executor.py | 230 | except Exception: | CODE |
| HIGH | core/retry_executor.py | 259 | except Exception: | CODE |
| HIGH | core/retry_executor.py | 268 | except Exception: | CODE |
| HIGH | core/api_client.py | 2158 | except Exception: | CODE |
| HIGH | core/api_client.py | 1816 | except OSError: | CODE |
| HIGH | core/api_client.py | 1979 | except Exception: | CODE |
| HIGH | core/live_replay_downloader.py | 288 | except ProcessLookupError: | CODE |
| HIGH | cli/whisper_transcribe.py | 232 | except ImportError: | CODE |
| HIGH | control/queue_manager.py | 104 | except ValueError: | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | core/item_reasons.py | 11 | CODE | |
| LOW | core/music_downloader.py | 1 | CODE | |
| LOW | core/user_mode_registry.py | 1 | CODE | |
| LOW | core/metadata.py | 9 | CODE | |
| LOW | core/audio_extraction.py | 9 | CODE | |
| LOW | core/discovery.py | 6 | CODE | |
| LOW | core/discovery.py | 19 | CODE | |
| LOW | core/user_downloader.py | 1 | CODE | |
| LOW | core/mix_downloader.py | 1 | CODE | |
| LOW | core/ffmpeg.py | 3 | CODE | |
| LOW | core/__init__.py | 1 | CODE | |
| LOW | core/__init__.py | 1 | CODE | |
| LOW | core/__init__.py | 2 | CODE | |
| LOW | core/__init__.py | 2 | CODE | |
| LOW | core/__init__.py | 3 | CODE | |
| LOW | core/__init__.py | 4 | CODE | |
| LOW | core/__init__.py | 5 | CODE | |
| LOW | core/live_downloader.py | 17 | CODE | |
| LOW | core/comments_collector.py | 10 | CODE | |
| LOW | core/comments_collector.py | 19 | CODE | |
| LOW | core/comments_collector.py | 20 | CODE | |
| LOW | core/retry_executor.py | 29 | CODE | |
| LOW | core/api_client.py | 1 | CODE | |
| LOW | core/live_replay_downloader.py | 3 | CODE | |
| LOW | core/user_modes/post_strategy.py | 1 | CODE | |
| LOW | core/user_modes/base_strategy.py | 1 | CODE | |
| LOW | core/user_modes/base_strategy.py | 11 | CODE | |
| LOW | core/user_modes/__init__.py | 1 | CODE | |
| LOW | core/user_modes/__init__.py | 2 | CODE | |
| LOW | core/user_modes/__init__.py | 3 | CODE | |
| LOW | core/user_modes/__init__.py | 4 | CODE | |
| LOW | core/user_modes/__init__.py | 5 | CODE | |
| LOW | core/user_modes/__init__.py | 6 | CODE | |
| LOW | core/user_modes/__init__.py | 7 | CODE | |
| LOW | core/user_modes/post_time_boundary.py | 1 | CODE | |
| LOW | core/user_modes/collect_strategy.py | 1 | CODE | |
| LOW | core/user_modes/music_strategy.py | 1 | CODE | |
| LOW | core/user_modes/collect_mix_strategy.py | 1 | CODE | |
| LOW | core/user_modes/mix_strategy.py | 1 | CODE | |
| LOW | config/__init__.py | 1 | CODE | |
| LOW | config/__init__.py | 2 | CODE | |
| LOW | auth/__init__.py | 1 | CODE | |
| LOW | auth/__init__.py | 2 | CODE | |
| LOW | auth/ms_token_conf.py | 23 | CODE | |
| LOW | auth/ms_token_manager.py | 1 | CODE | |
| LOW | tests/test_notifier_redactor_property.py | 31 | CODE | |
| LOW | tests/test_downloader_author_sec_uid.py | 27 | CODE | |
| LOW | tests/test_downloader_output_dir_report.py | 9 | CODE | |
| LOW | tests/test_lvdetail_gate.py | 11 | CODE | |
| LOW | tests/test_transcript_manager_audio.py | 18 | CODE | |
| LOW | tests/test_time_window_overrides.py | 6 | CODE | |
| LOW | tests/test_manifest_author_fields.py | 22 | CODE | |
| LOW | tests/test_config_loader_save.py | 9 | CODE | |
| LOW | tests/test_comments_download_behavior.py | 3 | CODE | |
| LOW | tests/test_api_client_risk_control.py | 12 | CODE | |
| LOW | tests/test_silent_audio.py | 8 | CODE | |
| LOW | tests/test_database_top_authors.py | 30 | CODE | |
| LOW | tests/test_proxy_validator_parity.py | 30 | CODE | |
| LOW | tests/test_downloader_naming_templates.py | 11 | CODE | |
| LOW | tests/test_naming.py | 8 | CODE | |
| 23 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | tools/cookie_fetcher.py | 369 | def update_config(config_path: Path, cookies: Dict[str, str]) -> None: | STRING |
| LOW | core/audio_extraction.py | 369 | __all__ = [ | CODE |
| LOW | core/__init__.py | 7 | __all__ = [ | CODE |
| LOW | core/silent_audio.py | 110 | __all__ = ["SILENT_1S_MP3_BYTES"] | CODE |
| LOW | core/downloader_base.py | 48 | def update_step(self, step: str, detail: str = "") -> None: ... | CODE |
| LOW | core/downloader_base.py | 50 | def set_item_total(self, total: int, detail: str = "") -> None: ... | CODE |
| LOW | core/downloader_base.py | 209 | def _settle_crashed_item(self, item: Dict[str, Any], entry: Any) -> None: | CODE |
| LOW | core/user_modes/__init__.py | 9 | __all__ = [ | CODE |
| LOW | config/__init__.py | 4 | __all__ = ["ConfigLoader", "DEFAULT_CONFIG"] | CODE |
| LOW | auth/__init__.py | 4 | __all__ = ["CookieManager", "MsTokenManager"] | CODE |
| LOW | tests/test_downloader_output_dir_report.py | 27 | def update_step(self, step: str, detail: str = "") -> None: | CODE |
| LOW | tests/test_downloader_output_dir_report.py | 30 | def set_item_total(self, total: int, detail: str = "") -> None: | CODE |
| LOW | tests/test_video_downloader.py | 25 | def update_step(self, step: str, detail: str = "") -> None: | CODE |
| LOW | tests/test_video_downloader.py | 28 | def set_item_total(self, total: int, detail: str = "") -> None: | CODE |
| LOW | tests/test_user_downloader.py | 56 | def update_step(self, step: str, detail: str = "") -> None: | CODE |
| LOW | tests/test_user_downloader.py | 59 | def set_item_total(self, total: int, detail: str = "") -> None: | CODE |
| LOW | utils/__init__.py | 6 | __all__ = [ | CODE |
| LOW | utils/logger.py | 62 | def set_console_log_level(level: int) -> None: | CODE |
| LOW | storage/__init__.py | 5 | __all__ = ["Database", "FileManager", "MetadataHandler"] | CODE |
| LOW | control/__init__.py | 5 | __all__ = ["RateLimiter", "RetryHandler", "QueueManager"] | CODE |
| LOW | control/queue_manager.py | 52 | def set_max_workers(self, value: int) -> None: | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | core/downloader_factory.py | 29 | CODE | |
| LOW | core/user_downloader.py | 424 | CODE | |
| LOW | core/mix_downloader.py | 38 | CODE | |
| LOW | core/url_parser.py | 13 | CODE | |
| LOW | core/retry_executor.py | 87 | CODE | |
| LOW | core/api_client.py | 513 | CODE | |
| LOW | core/api_client.py | 1710 | CODE | |
| LOW | core/api_client.py | 1824 | CODE | |
| LOW | core/api_client.py | 1856 | CODE | |
| LOW | core/downloader_base.py | 399 | CODE | |
| LOW | core/downloader_base.py | 632 | CODE | |
| LOW | core/downloader_base.py | 1178 | CODE | |
| LOW | core/user_modes/post_strategy.py | 154 | CODE | |
| LOW | core/user_modes/base_strategy.py | 241 | CODE | |
| LOW | core/user_modes/base_strategy.py | 343 | CODE | |
| LOW | config/config_loader.py | 67 | CODE | |
| LOW | config/config_loader.py | 183 | CODE | |
| LOW | utils/notifier.py | 82 | CODE | |
| LOW | cli/main.py | 40 | CODE | |
| LOW | cli/whisper_transcribe.py | 279 | CODE | |
| LOW | storage/database.py | 73 | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW⚡ | core/audio_extraction.py | 153 | # Step 1: resolve binary path | COMMENT |
| LOW | core/audio_extraction.py | 175 | # Step 2: probe `<ffmpeg> -version` | COMMENT |
| LOW⚡ | cli/whisper_transcribe.py | 334 | # Step 1: 提取音频 | COMMENT |
| LOW⚡ | cli/whisper_transcribe.py | 342 | # Step 2: Whisper 识别 | COMMENT |
| LOW⚡ | cli/whisper_transcribe.py | 351 | # Step 3: 繁转简 | COMMENT |
| LOW⚡ | cli/whisper_transcribe.py | 359 | # Step 4: 写文件 | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW⚡ | core/audio_extraction.py | 153 | # Step 1: resolve binary path | COMMENT |
| LOW | core/audio_extraction.py | 175 | # Step 2: probe `<ffmpeg> -version` | COMMENT |
| LOW⚡ | cli/whisper_transcribe.py | 334 | # Step 1: 提取音频 | COMMENT |
| LOW⚡ | cli/whisper_transcribe.py | 342 | # Step 2: Whisper 识别 | COMMENT |
| LOW⚡ | cli/whisper_transcribe.py | 351 | # Step 3: 繁转简 | COMMENT |
| LOW⚡ | cli/whisper_transcribe.py | 359 | # Step 4: 写文件 | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | config.example.yml | 121 | # 下载完成通知(可选)。providers 支持 bark / telegram / webhook | COMMENT |
| LOW | core/api_client.py | 41 | # backoff was tried and reverted: ``_request_json`` is the chokepoint for | COMMENT |
| LOW | tests/test_notifier_redactor_property.py | 41 | COMMENT | |
| LOW | tests/test_notifier_redactor_property.py | 101 | # Skip the middle-leak assertion when the middle is unavoidably a | COMMENT |
| LOW | utils/xbogus.py | 1 | # ============================================================================== | COMMENT |
| LOW | utils/abogus.py | 861 | # start = time.time() | COMMENT |
| LOW | cli/__init__.py | 1 | # cli package — entry point is cli.main:main (see pyproject.toml). | COMMENT |
| LOW | storage/file_manager.py | 21 | _SEC_UID_ILLEGAL_RE = re.compile(r'[<>:"/\\|?*\x00-\x1f]') | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | tests/test_time_window_overrides.py | 14 | class _Stub(BaseDownloader): # pragma: no cover - thin harness | CODE |
| MEDIUM | cli/main.py | 158 | # crashing the whole batch. Keeps multi-URL CLI runs robust while | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | core/retry_executor.py | 87 | CODE | |
| LOW | storage/database.py | 371 | CODE | |
| LOW | storage/file_manager.py | 159 | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | utils/xbogus.py | 4 | # This file is part of the Douyin_TikTok_Download_API project. | COMMENT |