开源、免费、跨平台的 B 站视频下载工具,支持多线程加速、音视频分离、弹幕元数据获取、自定义命名与分类等功能。Open Source, Free, Cross-Platform Bilibili Video Downloader.
This report summarizes scanner evidence for ScottSloan/Bili23-Downloader, a Python project with 8,292 GitHub stars. SynthScan examined 86,018 lines of code across 296 source files, recording 834 pattern matches distributed across 13 syntactic categories. The legacy adjusted pattern signal is 13.8 (Moderate 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? 516 finding(s).
Are imports declared and package/API names verified? 92 finding(s).
Are wrappers, guards, and repeated structures necessary? 685 finding(s).
Which changes need focused human review? 834 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 834 distinct pattern matches across 13 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⚡ | test/test_gui_smoke.py | 144 | def test_danmaku_style_dialog(self, parent): | CODE |
| LOW⚡ | test/test_gui_smoke.py | 149 | def test_subtitles_style_dialog(self, parent): | CODE |
| LOW⚡ | test/test_gui_smoke.py | 154 | def test_uses_project_scroll_area(self): | CODE |
| LOW⚡ | test/test_gui_smoke.py | 163 | def test_interactive_video_dialog(self, parent): | CODE |
| LOW | test/test_gui_smoke.py | 39 | def test_poster_item_delegate(self, parent): | CODE |
| LOW | test/test_gui_smoke.py | 89 | def test_dialog_constructed_with_parent_is_a_toplevel_window(self, app, parent, monkeypatch): | CODE |
| LOW | test/test_gui_smoke.py | 111 | def test_construction_does_not_show_the_dialog(self, app, parent, monkeypatch): | CODE |
| LOW | test/test_gui_smoke.py | 179 | def test_rule_builder_round_trip(self, parent): | CODE |
| LOW | test/test_gui_smoke.py | 189 | def test_rule_builder_degrades_on_unsupported_rule(self, parent): | CODE |
| LOW | test/test_gui_smoke.py | 204 | def test_edit_panel_load_and_dump(self, parent): | CODE |
| LOW | test/test_gui_smoke.py | 226 | def test_edit_panel_previews_every_shape(self, parent): | CODE |
| LOW | test/test_gui_smoke.py | 242 | def test_edit_panel_validation_messages(self, parent): | CODE |
| LOW | test/test_gui_smoke.py | 257 | def test_rule_builder_scrolls_when_levels_pile_up(self, parent): | CODE |
| LOW | test/test_gui_smoke.py | 281 | def test_rebuild_does_not_spawn_stray_windows(self, parent): | CODE |
| LOW | test/test_gui_smoke.py | 314 | def test_editor_does_not_overlap_at_minimum_height(self, parent, case): | CODE |
| LOW | test/test_gui_smoke.py | 369 | def test_variable_list_can_be_folded_away(self, parent): | CODE |
| LOW | test/test_gui_smoke.py | 388 | def test_fragment_move_inside_file_name(self, parent): | CODE |
| LOW | test/test_gui_smoke.py | 408 | def test_fragment_edit_view_keeps_shape_on_variable_change(self, parent): | CODE |
| LOW | test/test_gui_smoke.py | 432 | def test_fragment_edit_view_variable_choice_only_offers_recommended_variables(self, parent): | CODE |
| LOW | test/test_gui_smoke.py | 457 | def test_fragment_edit_view_variable_choice_keeps_a_foreign_current_variable(self, parent): | CODE |
| LOW | test/test_gui_smoke.py | 495 | def test_drag_reorders_the_node_list(self, parent): | CODE |
| LOW | test/test_gui_smoke.py | 534 | def test_invalid_edit_survives_switching_rows(self, parent): | CODE |
| LOW | test/test_gui_smoke.py | 556 | def test_discard_restores_the_committed_state(self, parent): | CODE |
| LOW | test/test_gui_smoke.py | 573 | def test_discard_hint_is_reserved_for_rule_errors(self, parent): | CODE |
| LOW | test/test_gui_smoke.py | 594 | def test_name_edit_shows_up_in_the_list_immediately(self, parent): | CODE |
| LOW | test/test_gui_smoke.py | 605 | def test_checking_default_clears_the_other_row(self, parent): | CODE |
| LOW | test/test_gui_smoke.py | 632 | def test_filter_hides_rows_and_blocks_dragging(self, parent): | CODE |
| LOW | test/test_gui_smoke.py | 657 | def test_adding_a_rule_clears_the_filter(self, parent): | CODE |
| LOW | test/test_gui_smoke.py | 673 | def test_item_moved_syncs_the_working_copy(self, parent): | CODE |
| LOW | test/test_gui_smoke.py | 688 | def test_switching_rows_without_editing_is_not_dirty(self, parent): | CODE |
| LOW | test/test_gui_smoke.py | 703 | def test_item_moved_is_reverted_when_the_editor_is_invalid(self, parent): | CODE |
| LOW | test/test_gui_smoke.py | 721 | def test_restore_builtin_default_touches_only_that_rule(self, parent): | CODE |
| LOW | test/test_gui_smoke.py | 743 | def test_left_column_does_not_overlap_at_minimum_size(self, parent): | CODE |
| LOW | test/test_gui_smoke.py | 760 | def test_new_rule_seed_has_a_usable_variable_for_every_type(self, parent): | CODE |
| LOW | test/test_gui_smoke.py | 786 | def test_new_rule_follows_the_selected_type(self, parent): | CODE |
| LOW | test/test_gui_smoke.py | 799 | def test_restore_is_unavailable_for_custom_rules(self, parent): | CODE |
| LOW | test/test_gui_smoke.py | 821 | def test_dirty_is_computed_not_accumulated(self, parent): | CODE |
| LOW | test/test_reparse_worker.py | 23 | def test_reports_a_real_message_instead_of_unbound_local(self): | CODE |
| LOW | test/test_config_defaults.py | 24 | def test_get_returns_the_default_object_itself(self): | CODE |
| LOW | test/test_config_defaults.py | 29 | def test_shallow_copy_does_not_protect_nested_structures(self): | CODE |
| LOW | test/test_task_completion_durability.py | 58 | def test_wait_true_is_on_disk_when_it_returns(self, task_manager): | CODE |
| LOW | test/test_task_completion_durability.py | 71 | def test_wait_true_does_not_deadlock_from_the_caller_thread(self, task_manager): | CODE |
| LOW | test/test_task_completion_durability.py | 94 | def test_timeout_does_not_raise_and_write_still_lands(self, task_manager, caplog): | CODE |
| LOW | test/test_task_completion_durability.py | 120 | def test_without_wait_there_is_no_durability_guarantee(self, task_manager): | CODE |
| LOW | test/test_task_completion_durability.py | 149 | def test_wait_false_keeps_the_old_asynchronous_contract(self, task_manager): | CODE |
| LOW | test/test_time.py | 17 | def test_millisecond_normalization(self): | CODE |
| LOW | test/test_time.py | 22 | def test_second_timestamp_below_threshold(self): | CODE |
| LOW | test/test_time.py | 34 | def test_out_of_range_timestamp(self): | CODE |
| LOW | test/test_time.py | 42 | def test_to_timestamp_strips_tzinfo_on_overflow(self): | CODE |
| LOW | test/test_search_url.py | 52 | def test_uses_type_specific_param(self): | CODE |
| LOW | test/test_search_url.py | 60 | def test_absent_and_unsupported(self): | CODE |
| LOW⚡ | test/test_search_url.py | 72 | def test_empty_keyword_removes_param(self): | CODE |
| LOW⚡ | test/test_search_url.py | 76 | def test_unsupported_url_returned_unchanged(self): | CODE |
| LOW⚡ | test/test_search_url.py | 79 | def test_preserves_other_params(self): | CODE |
| LOW | test/test_parse_worker.py | 35 | def test_the_two_sets_do_not_overlap(): | CODE |
| LOW | test/test_parse_worker.py | 39 | def test_every_parser_module_is_accounted_for(): | CODE |
| LOW | test/test_parse_worker.py | 56 | def test_classification_matches_the_parser_source(parser_type): | CODE |
| LOW | test/test_parse_worker.py | 67 | def test_unclassified_parsers_are_not_gated(parser_type): | CODE |
| LOW | test/test_parse_worker.py | 73 | def test_needs_wbi_signature_covers_exactly_the_wbi_set(): | CODE |
| LOW⚡ | test/test_naming_convention.py | 81 | def test_every_entry_carries_a_type(self, factory, type): | CODE |
| 393 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| HIGH | test/test_json.py | 171 | except module.JSONDecodeError: | CODE |
| HIGH | src/main.py | 233 | except Exception: # noqa: S110 日志系统本身正在关闭,无处可记录 | CODE |
| HIGH | src/main.py | 240 | except Exception: # noqa: S110 紧接着就是进程结束,刷不出去也无从补救 | CODE |
| HIGH | src/main.py | 264 | except Exception: # noqa: S110 日志系统已经关闭,失败时静默退回末尾的 os._exit() | CODE |
| HIGH | src/util/ffmpeg/runner.py | 274 | except (OSError, ValueError): | CODE |
| HIGH | src/util/ffmpeg/runner.py | 249 | except (OSError, ValueError): | CODE |
| HIGH | src/util/ffmpeg/runner.py | 284 | except OSError: | CODE |
| HIGH | src/util/ffmpeg/runner.py | 360 | except OSError: | CODE |
| HIGH | src/util/ffmpeg/runner.py | 185 | except OSError: | CODE |
| HIGH | src/util/ffmpeg/runner.py | 214 | except OSError: | CODE |
| HIGH | src/util/auth/server.py | 107 | except queue.Empty: | CODE |
| HIGH | src/util/auth/qrcode.py | 39 | except RuntimeError: | CODE |
| HIGH | src/util/auth/cookie_login.py | 63 | except Exception: # noqa: S110 见下方说明 | CODE |
| HIGH | src/util/auth/sms.py | 39 | except RuntimeError: | CODE |
| HIGH | src/util/parse/preview/audio_info.py | 160 | except RuntimeError: | CODE |
| HIGH | src/util/parse/preview/video_info.py | 175 | except RuntimeError: | CODE |
| HIGH | src/util/parse/additional/file/danmaku_ass.py | 236 | except (ValueError, TypeError): | CODE |
| HIGH | src/util/network/request.py | 223 | except KeyError: | CODE |
| HIGH | src/util/mcp/server.py | 205 | except OSError: | CODE |
| HIGH | src/util/mcp/stdio_bridge.py | 58 | except (AttributeError, ValueError): | CODE |
| HIGH | src/util/mcp/stdio_bridge.py | 64 | except (AttributeError, ValueError): | CODE |
| HIGH | src/util/mcp/stdio_bridge.py | 70 | except (AttributeError, ValueError): | CODE |
| HIGH | src/util/mcp/stdio_bridge.py | 437 | except KeyboardInterrupt: | CODE |
| HIGH | src/util/mcp/stdio_bridge.py | 394 | except Exception: # noqa: S110 退出路径上的尽力而为,失败没有补救手段 | CODE |
| HIGH | src/util/common/config.py | 508 | except OSError: | CODE |
| HIGH | src/util/download/downloader/merger.py | 109 | except RuntimeError: | CODE |
| HIGH | src/util/download/downloader/merger.py | 251 | except RuntimeError: | CODE |
| HIGH | src/util/download/downloader/merger.py | 261 | except RuntimeError: | CODE |
| HIGH | src/util/format/file_name.py | 133 | except (TypeError, ValueError): | CODE |
| HIGH | src/util/thread/async_.py | 17 | except ValueError: | CODE |
| HIGH | src/util/thread/async_.py | 25 | except RuntimeError: | CODE |
| HIGH | src/gui/component/parse_list/tree_view.py | 792 | except IndexError: | CODE |
| HIGH | src/gui/dialog/login.py | 164 | except RuntimeError: | CODE |
| HIGH | src/gui/dialog/login.py | 169 | except RuntimeError: | CODE |
| HIGH | src/gui/dialog/login.py | 174 | except RuntimeError: | CODE |
| HIGH | src/gui/dialog/login.py | 179 | except RuntimeError: | CODE |
| HIGH | src/gui/dialog/login.py | 184 | except RuntimeError: | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | launcher/PyStand.cpp | 880 | except Exception as e: | CODE |
| LOW | launcher/PyStand.cpp | 1042 | except Exception: | CODE |
| MEDIUM | launcher/PyStand.cpp | 863 | def PYSTAND_CONSOLE | CODE |
| MEDIUM | test/test_wbi_signature.py | 281 | def runner(): | CODE |
| LOW | test/test_wbi_signature.py | 286 | except Exception as e: | CODE |
| LOW | test/test_episode_tree.py | 179 | except Exception as exc: | CODE |
| MEDIUM | src/main.py | 494 | def stop_mcp_server(self): | CODE |
| MEDIUM | src/main.py | 603 | def warmup(): | CODE |
| LOW | src/main.py | 233 | except Exception: # noqa: S110 日志系统本身正在关闭,无处可记录 | CODE |
| LOW | src/main.py | 240 | except Exception: # noqa: S110 紧接着就是进程结束,刷不出去也无从补救 | CODE |
| LOW | src/main.py | 264 | except Exception: # noqa: S110 日志系统已经关闭,失败时静默退回末尾的 os._exit() | CODE |
| LOW | src/main.py | 500 | except Exception: | CODE |
| LOW | src/main.py | 593 | except Exception: | CODE |
| LOW | src/main.py | 611 | except Exception: | CODE |
| LOW | src/util/misc/update.py | 126 | except Exception as e: | CODE |
| LOW | src/util/misc/macos.py | 43 | except Exception: | CODE |
| LOW | src/util/ffmpeg/runner.py | 132 | except Exception as e: | CODE |
| LOW | src/util/auth/cookie_login.py | 63 | except Exception: # noqa: S110 见下方说明 | CODE |
| LOW | src/util/parse/worker.py | 115 | except Exception as e: | CODE |
| LOW | src/util/parse/worker.py | 168 | except Exception as e: | CODE |
| LOW | src/util/parse/quality.py | 76 | except Exception: | CODE |
| LOW | src/util/parse/parser/dynamic.py | 46 | except Exception as e: | CODE |
| LOW | src/util/parse/parser/festival.py | 38 | except Exception as e: | CODE |
| LOW | src/util/parse/parser/base.py | 104 | except Exception: | CODE |
| LOW | src/util/parse/preview/worker.py | 53 | except Exception as e: | CODE |
| MEDIUM | src/util/parse/preview/worker.py | 32 | def run(self): | CODE |
| LOW | src/util/parse/preview/previewer.py | 103 | except Exception as e: | CODE |
| LOW | src/util/parse/preview/previewer.py | 158 | except Exception as e: | CODE |
| LOW | src/util/parse/preview/previewer.py | 259 | except Exception as e: | CODE |
| MEDIUM | src/util/parse/preview/previewer.py | 96 | def on_init_success(self): | CODE |
| MEDIUM | src/util/parse/preview/previewer.py | 146 | def parse_info(self): | CODE |
| LOW | src/util/parse/additional/worker.py | 36 | except Exception as e: | CODE |
| MEDIUM | src/util/parse/additional/worker.py | 31 | def run(self): | CODE |
| LOW | src/util/network/request.py | 85 | except Exception: | CODE |
| LOW | src/util/network/request.py | 104 | except Exception: | CODE |
| LOW | src/util/network/request.py | 153 | except Exception as e: | CODE |
| LOW | src/util/network/request.py | 380 | except Exception as e: | CODE |
| MEDIUM | src/util/network/request.py | 374 | def run(self): | CODE |
| LOW | src/util/network/download_url.py | 196 | except Exception as e: | CODE |
| LOW | src/util/network/download_url.py | 248 | except Exception as e: | CODE |
| LOW | src/util/mcp/server.py | 429 | except Exception: | CODE |
| LOW | src/util/mcp/server.py | 436 | except Exception: | CODE |
| MEDIUM | src/util/mcp/server.py | 75 | def handle_one_request(self): | CODE |
| LOW | src/util/mcp/stdio_bridge.py | 394 | except Exception: # noqa: S110 退出路径上的尽力而为,失败没有补救手段 | CODE |
| LOW | src/util/mcp/protocol.py | 150 | except Exception: | CODE |
| LOW | src/util/mcp/__init__.py | 44 | except Exception: | CODE |
| LOW | src/util/mcp/invoke.py | 58 | except Exception as e: | CODE |
| LOW | src/util/mcp/invoke.py | 123 | except Exception: | CODE |
| MEDIUM | src/util/mcp/invoke.py | 54 | def runner(): | CODE |
| LOW | src/util/mcp/tools/download.py | 283 | except Exception: | CODE |
| LOW | src/util/mcp/tools/download.py | 433 | except Exception: | CODE |
| LOW | src/util/mcp/tools/__init__.py | 90 | except Exception as e: | CODE |
| LOW | src/util/mcp/tools/parse.py | 250 | except Exception: | CODE |
| LOW | src/util/mcp/tools/parse.py | 328 | except Exception: | CODE |
| LOW | src/util/common/config.py | 502 | except Exception: | CODE |
| LOW | src/util/common/config.py | 519 | except Exception as e: | CODE |
| LOW | src/util/common/io/file.py | 17 | except Exception as e: | CODE |
| LOW | src/util/common/io/file.py | 35 | except Exception as e: | CODE |
| LOW | src/util/common/io/directory.py | 181 | except Exception as e: | CODE |
| LOW | src/util/download/downloader/downloader.py | 376 | except Exception: | CODE |
| 56 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| CRITICAL | src/gui/interface/parse.py | 196 | self.segmented_widget.pager_widget.auto_parse_btn.clicked.connect(self.on_auto_parse) | CODE |
| CRITICAL⚡ | src/gui/dialog/download_options/media.py | 44 | self.media_info_card.video_quality_widget.choice.currentIndexChanged.connect(self.on_change_video_info_choice) | CODE |
| CRITICAL⚡ | src/gui/dialog/download_options/media.py | 45 | self.media_info_card.audio_quality_widget.choice.currentIndexChanged.connect(self.on_change_audio_info_choice) | CODE |
| CRITICAL⚡ | src/gui/dialog/download_options/media.py | 46 | self.media_info_card.video_codec_widget.choice.currentIndexChanged.connect(self.on_change_video_info_choice) | CODE |
| CRITICAL⚡ | src/gui/dialog/download_options/media.py | 48 | self.media_info_card.video_quality_widget.custom_btn.clicked.connect(self.on_adjust_video_quality_priority) | CODE |
| CRITICAL⚡ | src/gui/dialog/download_options/media.py | 49 | self.media_info_card.audio_quality_widget.custom_btn.clicked.connect(self.on_adjust_audio_quality_priority) | CODE |
| CRITICAL⚡ | src/gui/dialog/download_options/media.py | 50 | self.media_info_card.video_codec_widget.custom_btn.clicked.connect(self.on_adjust_video_codec_priority) | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | test/test_gui_smoke.py | 23 | CODE | |
| LOW | test/test_parse_wbi_gate.py | 43 | CODE | |
| LOW | test/test_codec_fallback.py | 27 | CODE | |
| LOW | test/test_i18n_context.py | 161 | CODE | |
| LOW | test/smoke_startup.py | 173 | CODE | |
| LOW | test/test_media_options.py | 33 | CODE | |
| LOW | test/test_parse_list_view.py | 24 | CODE | |
| LOW | src/main.py | 345 | CODE | |
| LOW | src/main.py | 605 | CODE | |
| LOW | src/util/auth/captcha.py | 50 | CODE | |
| LOW | src/util/common/data/__init__.py | 1 | CODE | |
| LOW | src/util/common/data/__init__.py | 1 | CODE | |
| LOW | src/util/common/data/__init__.py | 1 | CODE | |
| LOW | src/util/common/data/__init__.py | 1 | CODE | |
| LOW | src/util/common/data/__init__.py | 1 | CODE | |
| LOW | src/util/common/data/__init__.py | 1 | CODE | |
| LOW | src/util/common/data/__init__.py | 1 | CODE | |
| LOW | src/util/common/data/__init__.py | 1 | CODE | |
| LOW | src/util/common/data/__init__.py | 1 | CODE | |
| LOW | src/util/common/data/__init__.py | 1 | CODE | |
| LOW | src/util/common/data/__init__.py | 1 | CODE | |
| LOW | src/util/common/data/__init__.py | 6 | CODE | |
| LOW | src/util/common/data/__init__.py | 6 | CODE | |
| LOW | src/util/common/data/__init__.py | 6 | CODE | |
| LOW | src/util/common/data/__init__.py | 7 | CODE | |
| LOW | src/util/common/data/__init__.py | 7 | CODE | |
| LOW | src/util/common/data/__init__.py | 8 | CODE | |
| LOW | src/util/common/data/__init__.py | 8 | CODE | |
| LOW | src/util/common/data/__init__.py | 9 | CODE | |
| LOW | src/util/common/data/__init__.py | 10 | CODE | |
| LOW | src/util/common/data/__init__.py | 11 | CODE | |
| LOW | src/util/common/data/__init__.py | 12 | CODE | |
| LOW | src/util/common/data/__init__.py | 13 | CODE | |
| LOW | src/gui/component/download_list/__init__.py | 1 | CODE | |
| LOW | src/gui/component/download_list/__init__.py | 2 | CODE | |
| LOW | src/gui/component/download_list/__init__.py | 3 | CODE | |
| LOW | src/gui/component/download_list/__init__.py | 4 | CODE | |
| LOW | src/gui/component/download_list/__init__.py | 5 | CODE | |
| LOW | src/gui/component/parse_list/__init__.py | 1 | CODE | |
| LOW | src/gui/component/parse_list/__init__.py | 1 | CODE | |
| LOW | src/gui/component/parse_list/__init__.py | 1 | CODE | |
| LOW | src/gui/component/parse_list/__init__.py | 2 | CODE | |
| LOW | src/gui/component/parse_list/__init__.py | 3 | CODE | |
| LOW | src/gui/component/view_model/__init__.py | 1 | CODE | |
| LOW | src/gui/component/view_model/__init__.py | 1 | CODE | |
| LOW | src/gui/component/view_model/__init__.py | 1 | CODE | |
| LOW | src/gui/component/view_model/__init__.py | 2 | CODE | |
| LOW | src/gui/component/view_model/__init__.py | 3 | CODE | |
| LOW | src/gui/component/setting/__init__.py | 1 | CODE | |
| LOW | src/gui/component/setting/__init__.py | 1 | CODE | |
| LOW | src/gui/component/setting/__init__.py | 1 | CODE | |
| LOW | src/gui/component/setting/__init__.py | 1 | CODE | |
| LOW | src/gui/component/setting/__init__.py | 1 | CODE | |
| LOW | src/gui/component/setting/__init__.py | 1 | CODE | |
| LOW | src/gui/component/setting/__init__.py | 1 | CODE | |
| LOW | src/gui/component/setting/__init__.py | 1 | CODE | |
| LOW | src/gui/component/setting/__init__.py | 1 | CODE | |
| LOW | src/gui/component/setting/__init__.py | 1 | CODE | |
| LOW | src/gui/component/setting/__init__.py | 1 | CODE | |
| LOW | src/gui/component/setting/__init__.py | 1 | CODE | |
| 22 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | src/main.py | 359 | logger = logging.getLogger(__name__) | CODE |
| LOW | src/util/misc/update.py | 12 | logger = logging.getLogger(__name__) | CODE |
| LOW | src/util/misc/web.py | 7 | logger = logging.getLogger(__name__) | CODE |
| LOW | src/util/misc/macos.py | 4 | logger = logging.getLogger(__name__) | CODE |
| LOW | src/util/ffmpeg/runner.py | 36 | logger = logging.getLogger(__name__) | CODE |
| LOW | src/util/ffmpeg/__init__.py | 12 | logger = logging.getLogger(__name__) | CODE |
| LOW | src/util/auth/user.py | 14 | logger = logging.getLogger(__name__) | CODE |
| LOW | src/util/auth/base.py | 10 | logger = logging.getLogger(__name__) | CODE |
| LOW | src/util/parse/worker.py | 12 | logger = logging.getLogger(__name__) | CODE |
| LOW | src/util/parse/quality.py | 7 | logger = logging.getLogger(__name__) | CODE |
| LOW | src/util/parse/episode/lesson.py | 8 | logger = logging.getLogger(__name__) | CODE |
| LOW | src/util/parse/parser/dynamic.py | 16 | logger = logging.getLogger(__name__) | CODE |
| LOW | src/util/parse/parser/base.py | 20 | logger = logging.getLogger(__name__) | CODE |
| LOW | src/util/parse/preview/audio_info.py | 17 | logger = logging.getLogger(__name__) | CODE |
| LOW | src/util/parse/preview/previewer.py | 24 | logger = logging.getLogger(__name__) | CODE |
| LOW | src/util/parse/additional/worker.py | 18 | logger = logging.getLogger(__name__) | CODE |
| LOW | src/util/parse/additional/chapter.py | 11 | logger = logging.getLogger(__name__) | CODE |
| LOW | src/util/network/request.py | 18 | logger = logging.getLogger(__name__) | CODE |
| LOW | src/util/network/download_url.py | 13 | logger = logging.getLogger(__name__) | CODE |
| LOW | src/util/network/cdn.py | 11 | logger = logging.getLogger(__name__) | CODE |
| LOW | src/util/network/area.py | 7 | logger = logging.getLogger(__name__) | CODE |
| LOW | src/util/mcp/server.py | 17 | logger = logging.getLogger(__name__) | CODE |
| LOW | src/util/mcp/protocol.py | 5 | logger = logging.getLogger(__name__) | CODE |
| LOW | src/util/mcp/__init__.py | 12 | logger = logging.getLogger(__name__) | CODE |
| LOW | src/util/mcp/invoke.py | 6 | logger = logging.getLogger(__name__) | CODE |
| LOW | src/util/mcp/tools/task.py | 11 | logger = logging.getLogger(__name__) | CODE |
| LOW | src/util/mcp/tools/download.py | 18 | logger = logging.getLogger(__name__) | CODE |
| LOW | src/util/mcp/tools/__init__.py | 7 | logger = logging.getLogger(__name__) | CODE |
| LOW | src/util/mcp/tools/parse.py | 10 | logger = logging.getLogger(__name__) | CODE |
| LOW | src/util/common/_json.py | 17 | logger = logging.getLogger(__name__) | CODE |
| LOW | src/util/common/config.py | 25 | logger = logging.getLogger(__name__) | CODE |
| LOW | src/util/common/io/file.py | 8 | logger = logging.getLogger(__name__) | CODE |
| LOW | src/util/common/io/directory.py | 14 | logger = logging.getLogger(__name__) | CODE |
| LOW | src/util/download/parse/audio_info.py | 10 | logger = logging.getLogger(__name__) | CODE |
| LOW | src/util/download/downloader/downloader.py | 32 | logger = logging.getLogger(__name__) | CODE |
| LOW | src/util/download/downloader/parse_worker.py | 21 | logger = logging.getLogger(__name__) | CODE |
| LOW | src/util/download/downloader/manager.py | 10 | logger = logging.getLogger(__name__) | CODE |
| LOW | src/util/download/downloader/merger.py | 21 | logger = logging.getLogger(__name__) | CODE |
| LOW | src/util/download/task/options.py | 10 | logger = logging.getLogger(__name__) | CODE |
| LOW | src/util/download/task/db.py | 12 | logger = logging.getLogger(__name__) | CODE |
| LOW | src/util/download/task/query_worker.py | 11 | logger = logging.getLogger(__name__) | CODE |
| LOW | src/util/download/task/manager.py | 30 | logger = logging.getLogger(__name__) | CODE |
| LOW | src/util/download/task/reparse_worker.py | 18 | logger = logging.getLogger(__name__) | CODE |
| LOW | src/util/download/cover/db.py | 9 | logger = logging.getLogger(__name__) | CODE |
| LOW | src/util/download/cover/query_worker.py | 16 | logger = logging.getLogger(__name__) | CODE |
| LOW | src/util/format/rule_template.py | 31 | logger = logging.getLogger(__name__) | CODE |
| LOW | src/util/format/file_name.py | 15 | logger = logging.getLogger(__name__) | CODE |
| LOW | src/util/thread/dispatcher.py | 7 | logger = logging.getLogger(__name__) | CODE |
| LOW | src/util/thread/async_.py | 9 | logger = logging.getLogger(__name__) | CODE |
| LOW | src/util/thread/pool.py | 8 | logger = logging.getLogger(__name__) | CODE |
| LOW | src/gui/interface/main_window.py | 19 | logger = logging.getLogger(__name__) | CODE |
| LOW | src/gui/interface/setting.py | 27 | logger = logging.getLogger(__name__) | CODE |
| LOW | src/gui/interface/parse.py | 58 | logger = logging.getLogger(__name__) | CODE |
| LOW | src/gui/component/profile.py | 16 | logger = logging.getLogger(__name__) | CODE |
| LOW | src/gui/component/download_list/item_delegate.py | 21 | logger = logging.getLogger(__name__) | CODE |
| LOW | src/gui/component/setting/card.py | 28 | logger = logging.getLogger(__name__) | CODE |
| LOW | src/gui/dialog/misc/interactive_video.py | 12 | logger = logging.getLogger(__name__) | CODE |
| LOW | src/gui/dialog/misc/auto_parse.py | 14 | logger = logging.getLogger(__name__) | CODE |
| LOW | src/gui/dialog/misc/view_cover.py | 15 | logger = logging.getLogger(__name__) | CODE |
| LOW | src/gui/dialog/setting/user_agent.py | 12 | logger = logging.getLogger(__name__) | CODE |
| 1 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | pyproject.toml | 29 | # -------------------------------------------------------------------------- | COMMENT |
| MEDIUM | pyproject.toml | 31 | # -------------------------------------------------------------------------- | COMMENT |
| MEDIUM | pyproject.toml | 51 | # -------------------------------------------------------------------------- | COMMENT |
| MEDIUM | pyproject.toml | 53 | # -------------------------------------------------------------------------- | COMMENT |
| MEDIUM | test/conftest.py | 46 | # -------------------------------------------------------------------------- | COMMENT |
| MEDIUM | test/conftest.py | 48 | # -------------------------------------------------------------------------- | COMMENT |
| MEDIUM | src/util/parse/episode/list_base.py | 77 | # ------------------------------------------------------------------ | COMMENT |
| MEDIUM | src/util/parse/episode/list_base.py | 79 | # ------------------------------------------------------------------ | COMMENT |
| MEDIUM | src/util/parse/episode/list_base.py | 90 | # ------------------------------------------------------------------ | COMMENT |
| MEDIUM | src/util/parse/episode/list_base.py | 92 | # ------------------------------------------------------------------ | COMMENT |
| MEDIUM | src/util/parse/episode/list_base.py | 110 | # ------------------------------------------------------------------ | COMMENT |
| MEDIUM | src/util/parse/episode/list_base.py | 112 | # ------------------------------------------------------------------ | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | src/main.py | 292 | CODE | |
| LOW | src/util/auth/server.py | 10 | CODE | |
| LOW | src/util/auth/server.py | 90 | CODE | |
| LOW | src/util/auth/server.py | 19 | CODE | |
| LOW | src/util/auth/qrcode.py | 48 | CODE | |
| LOW | src/util/auth/cookie.py | 63 | CODE | |
| LOW | src/util/auth/cookie.py | 69 | CODE | |
| LOW | src/util/auth/cookie_login.py | 38 | CODE | |
| LOW | src/util/parse/episode/tree.py | 195 | CODE | |
| LOW | src/util/parse/episode/tree.py | 214 | CODE | |
| LOW | src/util/parse/episode/bangumi.py | 29 | CODE | |
| LOW | src/util/parse/episode/cheese.py | 28 | CODE | |
| LOW | src/util/parse/episode/video.py | 107 | CODE | |
| LOW | src/util/parse/preview/previewer.py | 60 | CODE | |
| LOW | src/util/parse/preview/previewer.py | 106 | CODE | |
| LOW | src/util/parse/additional/file/danmaku_ass.py | 186 | CODE | |
| LOW | src/util/download/downloader/downloader.py | 251 | CODE | |
| LOW | src/util/download/downloader/downloader.py | 1050 | CODE | |
| LOW | src/util/download/downloader/downloader.py | 1180 | CODE | |
| LOW | src/util/download/downloader/parse_worker.py | 136 | CODE | |
| LOW | src/util/download/downloader/merger.py | 131 | CODE | |
| LOW | src/util/download/downloader/merger.py | 276 | CODE | |
| LOW | src/util/download/task/hash_id.py | 21 | CODE | |
| LOW | src/util/format/rule_template.py | 125 | CODE | |
| LOW | src/util/format/rule_template.py | 157 | CODE | |
| LOW | src/gui/interface/parse.py | 566 | CODE | |
| LOW | src/gui/component/parse_list/tree_view.py | 240 | CODE | |
| LOW | src/gui/component/parse_list/tree_view.py | 263 | CODE | |
| LOW | src/gui/component/parse_list/tree_view.py | 491 | CODE | |
| LOW | src/gui/dialog/log.py | 112 | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | pyproject.toml | 61 | "src/util/misc/dm_pb2.py", # protoc 生成 | COMMENT |
| LOW | launcher/PyStand.h | 1 | //===================================================================== | COMMENT |
| LOW | launcher/PyStand.cpp | 1 | //===================================================================== | COMMENT |
| LOW | launcher/PyStand.cpp | 281 | // 内嵌源码解决的只是"入口脚本可以被换掉"。剩下的攻击面全在磁盘上: | COMMENT |
| LOW | launcher/PyStand.cpp | 441 | // SetDefaultDllDirectories 把范围压到 System32 加上显式登记的目录, | COMMENT |
| LOW | launcher/PyStand.cpp | 541 | _py_argv.resize(0); | COMMENT |
| LOW | launcher/PyStand.cpp | 761 | std::wstring desc = std::to_wstring((unsigned long long)(uintptr_t)_blob) | COMMENT |
| LOW | launcher/PyStand.cpp | 921 | // | COMMENT |
| LOW | test/conftest.py | 41 | # 每轮测试从干净状态开始:上一轮遗留的配置会让「首次启动」「版本迁移」这类 | COMMENT |
| LOW | test/smoke_startup.py | 61 | COMMENT | |
| LOW | src/main.py | 501 | logger.exception("停止 MCP 服务器失败") | COMMENT |
| LOW | src/main.py | 641 | COMMENT | |
| LOW | src/util/__init__.py | 1 | # 此处不要导入子模块:util 是所有工具模块的父包,任何一次 from util.x import y 都会先执行 | COMMENT |
| LOW | src/util/ffmpeg/command.py | 161 | ) | COMMENT |
| LOW | src/util/parse/episode/history.py | 81 | # 必须给出一个形态位:条目标着 NEED_PARSE_BIT 却没有任何形态位时, | COMMENT |
| LOW | src/util/network/proxy.py | 41 | COMMENT | |
| LOW | src/util/network/download_url.py | 41 | # 1. 全局 client 的 transport 带 retries = 3,遇到不回包的节点 httpx 会自己连续重试 4 次, | COMMENT |
| LOW | src/util/mcp/stdio_bridge.py | 361 | def write(self, payload): | COMMENT |
| LOW | src/util/common/config.py | 561 | if config_version < 2200: | COMMENT |
| LOW | src/util/common/data/naming_convention.py | 61 | # 混在「来源」列表里的其他类型条目 | COMMENT |
| LOW | src/util/download/downloader/downloader.py | 1521 | finally: | COMMENT |
| LOW | src/util/format/file_name.py | 201 | # series_title …)与投稿视频完全不同 —— 套用来源规则的话,这些变量在 | COMMENT |
| LOW | src/gui/component/dialog.py | 261 | # 而 Qt 的自动退出判定(QGuiApplicationPrivate::lastWindowClosed())只认这种窗口, | COMMENT |
| LOW | src/gui/component/widget/__init__.py | 1 | # 此处不要聚合导出子模块:导入任意一个子模块都会先执行本文件,聚合导出会把 flyout -> | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| HIGH⚡ | src/util/parse/additional/file/danmaku_ass.py | 113 | track.push(stime, duration_ms, text_width, speed) | STRING |
| HIGH⚡ | src/util/parse/additional/file/danmaku_ass.py | 121 | track.push(stime + duration_ms) | STRING |
| HIGH⚡ | src/util/parse/additional/file/danmaku_ass.py | 129 | track.push(stime + duration_ms) | STRING |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | src/util/parse/additional/cover.py | 35 | CODE | |
| LOW | src/util/parse/additional/subtitles.py | 197 | CODE | |
| LOW | src/util/parse/additional/danmaku.py | 93 | CODE | |
| LOW | src/util/network/request.py | 278 | CODE | |
| LOW | src/util/network/request.py | 369 | CODE | |
| LOW | src/util/download/task/hash_id.py | 21 | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | src/res/resources_rc.py | 1424 | \x00#Check if a new\ | CODE |
| LOW | src/res/resources_rc.py | 7651 | \x00\x00\x00#Check if a n\ | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | src/gui/dialog/main_window/about.py | 31 | self.sponsor_lab = BodyLabel(self.tr("If this project saved you time or solved your problem, consider buying the | CODE |