一个人人都能部署的基于 js 的弹幕 API 服务器,支持爱优腾芒哔咪人韩巴狐乐西埋帆红弹幕直接获取,兼容弹弹play的搜索、详情查询和弹幕获取接口规范,并提供日志记录,支持vercel/netlify/edgeone/cloudflare/docker/hf等部署方式,不用提前下载弹幕,没有nas或小鸡也能一键部署。
This report summarizes scanner evidence for huangxd-/danmu_api, a JavaScript project with 3,432 GitHub stars. SynthScan examined 74,754 lines of code across 170 source files, recording 180 pattern matches distributed across 6 syntactic categories. The legacy adjusted pattern signal is 3.5 (Low 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.
Payload schema: 1.0.0 · Engine: 2.0.0 · Scoring: heuristic-density-v1 · Scan date: 2026-10-31.
Can maintainers explain intent, assumptions, and trade-offs? 131 finding(s).
Are imports declared and package/API names verified? 0 finding(s).
Are wrappers, guards, and repeated structures necessary? 168 finding(s).
Which changes need focused human review? 180 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 180 distinct pattern matches across 6 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 |
|---|---|---|---|---|
| MEDIUM⚡ | danmu_api/utils/merge-util.js | 53 | // ── 标题与结构 ────────────────────────────────────────── | COMMENT |
| MEDIUM⚡ | danmu_api/utils/merge-util.js | 58 | // ── 日期 ───────────────────────────────────────────────── | COMMENT |
| MEDIUM⚡ | danmu_api/utils/merge-util.js | 61 | // ── 集数对齐 (Episode Alignment) ───────────────────────── | COMMENT |
| MEDIUM⚡ | danmu_api/utils/merge-util.js | 1470 | // ── 类型判断 ────────────────────────────────────────────── | COMMENT |
| MEDIUM⚡ | danmu_api/utils/merge-util.js | 1476 | // ── 语言对齐 ────────────────────────────────────────────── | COMMENT |
| MEDIUM⚡ | danmu_api/utils/merge-util.js | 1482 | // ── 季度编号 & 特殊类型 ─────────────────────────────────── | COMMENT |
| MEDIUM⚡ | danmu_api/utils/merge-util.js | 1491 | // ── 季度偏移精确匹配奖励 ────────────────────────────────── | COMMENT |
| MEDIUM⚡ | danmu_api/utils/merge-util.js | 1499 | // ── 文本相似度(核心评分) ──────────────────────────────── | COMMENT |
| MEDIUM⚡ | danmu_api/utils/merge-util.js | 2274 | // ── 评分修正 ───────────────────────────────────────────────────── | COMMENT |
| MEDIUM⚡ | danmu_api/utils/merge-util.js | 2282 | // ── Probe 覆盖逻辑 ────────────────────────────────────────────── | COMMENT |
| MEDIUM⚡ | danmu_api/utils/merge-util.js | 2291 | // ── 阈值过滤 ───────────────────────────────────────────────────── | COMMENT |
| MEDIUM | danmu_api/utils/merge-util.js | 1516 | // ── 数字严格相等奖励 ────────────────────────────────────── | COMMENT |
| MEDIUM | danmu_api/utils/merge-util.js | 1520 | // ── 断层惩罚(防异构/占位区污染) ───────────────────────── | COMMENT |
| MEDIUM | danmu_api/utils/merge-util.js | 1535 | // ── 数字差分布统计(支持规律性检测) ───────────────────── | COMMENT |
| MEDIUM | danmu_api/utils/merge-util.js | 2163 | // ── 之字结构强阻断 ─────────────────────────────────────────────── | COMMENT |
| MEDIUM | danmu_api/utils/merge-util.js | 2174 | // ── 媒体类型冲突检测 ───────────────────────────────────────────── | COMMENT |
| MEDIUM | danmu_api/utils/merge-util.js | 2185 | // ── 上下文续作阻断 ─────────────────────────────────────────────── | COMMENT |
| MEDIUM | danmu_api/utils/merge-util.js | 2214 | // ── 主副别名交叉比对 ───────────────────────────────────────────── | COMMENT |
| MEDIUM | danmu_api/utils/merge-util.js | 2218 | // ── 剧场版标题阻断 ─────────────────────────────────────────────── | COMMENT |
| MEDIUM | danmu_api/utils/merge-util.js | 2240 | // ── 日期匹配校验 ───────────────────────────────────────────────── | COMMENT |
| MEDIUM | danmu_api/utils/merge-util.js | 2251 | // ── 季度标记冲突校验 ───────────────────────────────────────────── | COMMENT |
| MEDIUM | danmu_api/utils/merge-util.js | 2306 | // ── Tier 筛选:梯度过滤,保留合理竞争者 ───────────────────────────── | COMMENT |
| MEDIUM | danmu_api/utils/merge-util.js | 2640 | // ── 隔离检索 ──────────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | danmu_api/utils/merge-util.js | 2693 | // ── 跨源合集时序接管 ───────────────────────────────────────────────────── | COMMENT |
| MEDIUM | danmu_api/utils/merge-util.js | 2733 | // ── 小数集数预处理 ─────────────────────────────────────────────── | COMMENT |
| MEDIUM | danmu_api/utils/merge-util.js | 2751 | // ── 合集切片 ───────────────────────────────────────────────────── | COMMENT |
| MEDIUM | danmu_api/utils/merge-util.js | 2831 | // ── 智能对齐策略(特权映射表介入) ───────────────────────────── | COMMENT |
| MEDIUM | danmu_api/utils/merge-util.js | 2896 | // ── 执行 URL 合并 ──────────────────────────────────────── | COMMENT |
| MEDIUM | danmu_api/utils/merge-util.js | 2915 | // ── 对齐偏移计算 ───────────────────────────────────────────────── | COMMENT |
| MEDIUM | danmu_api/utils/merge-util.js | 2920 | // ── 智能对齐策略(共识差计算) ─────────────────────────────────── | COMMENT |
| MEDIUM | danmu_api/utils/merge-util.js | 3043 | // ── 执行 URL 合并 ──────────────────────────────────────── | COMMENT |
| MEDIUM | danmu_api/utils/merge-util.js | 3070 | // ── 年份关系校验:与标题匹配侧沿用同一套判定 ────────────────── | COMMENT |
| MEDIUM | danmu_api/utils/merge-util.js | 3097 | // ── 覆盖率校验 ──────────────────────────────────────────────── | COMMENT |
| MEDIUM | danmu_api/utils/merge-util.js | 3114 | // ── 别名合并 ───────────────────────────────────────────── | COMMENT |
| MEDIUM | danmu_api/utils/merge-util.js | 3135 | // ── 记录合并层级 ────────────────────────────────────── | COMMENT |
| MEDIUM | danmu_api/utils/merge-util.js | 3152 | // ── 合集进度双向写入 ────────────────────────────────────── | COMMENT |
| MEDIUM | danmu_api/utils/merge-util.js | 3205 | // ── 番外沉底排序 ────────────────────────────────────────── | COMMENT |
| MEDIUM | danmu_api/utils/merge-util.js | 3229 | // ── 重复签名检测 ────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | danmu_api/utils/merge-util.js | 3334 | // ── 前置全局计算 ──────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | danmu_api/utils/merge-util.js | 3401 | // ── Phase 1: CN Primary Isolation ────────────────────────────────── | COMMENT |
| MEDIUM | danmu_api/utils/merge-util.js | 3438 | // ── Phase 1.5: Secondary CN Self-Organization ─────────────────────── | COMMENT |
| MEDIUM | danmu_api/utils/merge-util.js | 3469 | // ── Phase 2: Standard Fallback ────────────────────────────────────── | COMMENT |
| MEDIUM | danmu_api/utils/merge-util.js | 3521 | // ── 最终整理 ───────────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | danmu_api/sources/hanjutv.js | 144 | // ── 数据规范化 ────────────────────────────────────────────── | COMMENT |
| MEDIUM | danmu_api/sources/hanjutv.js | 219 | // ── 搜索候选合并 ───────────────────────────────────────────── | COMMENT |
| MEDIUM | danmu_api/sources/hanjutv.js | 490 | // ── 搜索接口 ───────────────────────────────────────────────── | COMMENT |
| MEDIUM | danmu_api/sources/hanjutv.js | 631 | // ── 详情 & 剧集 ────────────────────────────────────────────── | COMMENT |
| MEDIUM | danmu_api/sources/hanjutv.js | 880 | // ── 番剧处理 ───────────────────────────────────────────────── | COMMENT |
| MEDIUM | danmu_api/sources/hanjutv.js | 947 | // ── 弹幕 ───────────────────────────────────────────────────── | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | danmu_api/server.js | 73 | function resolvePublicRequestProtocol(req) { | CODE |
| LOW | danmu_api/server.js | 554 | async function initializeFavoriteScheduler(mainPort) { | CODE |
| LOW | danmu_api/ui/js/apitest.js | 132 | function updateCommentDurationFieldVisibility() { | CODE |
| LOW | danmu_api/ui/js/apitest.js | 150 | function bindCommentDurationFieldVisibility() { | CODE |
| LOW | danmu_api/ui/js/apitest.js | 524 | function estimateVideoDurationFromComments(comments) { | CODE |
| LOW | danmu_api/ui/js/apitest.js | 723 | function showDanmuCallTraceFailure(trace, title, message, source) { | CODE |
| LOW | danmu_api/ui/js/apitest.js | 730 | function getDanmuCallTraceTotalSeconds(trace, fallbackSeconds) { | CODE |
| LOW⚡ | danmu_api/ui/js/apitest.js | 749 | function isCurrentDanmuFlowRequest(requestId) { | CODE |
| LOW⚡ | danmu_api/ui/js/apitest.js | 753 | function startManualBangumiRequest() { | CODE |
| LOW⚡ | danmu_api/ui/js/apitest.js | 761 | function isCurrentManualBangumiRequest(requestId) { | CODE |
| LOW⚡ | danmu_api/ui/js/apitest.js | 765 | function invalidateActiveDanmuRequest() { | CODE |
| LOW⚡ | danmu_api/ui/js/apitest.js | 769 | function setDanmuFlowButtonLoading(btn, requestId, loading) { | CODE |
| LOW | danmu_api/ui/js/apitest.js | 785 | function resetManualFavoriteButton() { | CODE |
| LOW | danmu_api/ui/js/apitest.js | 801 | function renderManualFavoriteButton() { | CODE |
| LOW | danmu_api/ui/js/apitest.js | 1029 | function toggleFavoriteScheduleWeekday() { | CODE |
| LOW | danmu_api/ui/js/apitest.js | 1035 | function openFavoriteScheduleModal(keyword) { | CODE |
| LOW | danmu_api/ui/js/apitest.js | 1052 | function closeFavoriteScheduleModal() { | CODE |
| LOW | danmu_api/ui/js/apitest.js | 1762 | function updateDanmuHeatmapTooltip(event, interactive, bars, tooltip, indicator, segs, segLen, maxTime) { | CODE |
| LOW | danmu_api/ui/js/preview.js | 234 | function renderPreviewSearchResults(query) { | CODE |
| LOW | danmu_api/ui/js/requestrecords.js | 73 | function initRequestRecordsInterface() { | CODE |
| LOW | danmu_api/ui/js/pushdanmu.js | 139 | function displayEpisodeListForPush(animeTitle, episodes, pushUrl) { | CODE |
| LOW | danmu_api/ui/js/pushdanmu.js | 181 | function jumpToEpisodeForPushDanmu() { | CODE |
| LOW | danmu_api/ui/js/systemsettings.js | 242 | function updateLocalImportedConfig(key, value) { | CODE |
| LOW | danmu_api/ui/js/systemsettings.js | 649 | async function checkDeployPlatformConfig() { | CODE |
| LOW | danmu_api/ui/js/systemsettings.js | 2130 | function handleDelegatedTouchStart(e) { | CODE |
| LOW | danmu_api/ui/js/systemsettings.js | 2199 | function handleSelectedTagsContainerDragOver(e) { | CODE |
| LOW | danmu_api/ui/js/systemsettings.js | 2205 | function handleSelectedTagsContainerDrop(e) { | CODE |
| LOW | danmu_api/ui/js/systemsettings.js | 2366 | function cleanupSelectedTagsTouchDrag() { | CODE |
| LOW | danmu_api/ui/js/systemsettings.js | 3015 | async function autoCheckBilibiliCookieStatus() { | CODE |
| LOW | danmu_api/ui/js/systemsettings.js | 3075 | function showBilibiliCookieSaveHint(text) { | CODE |
| LOW | danmu_api/ui/js/systemsettings.js | 3161 | async function verifyDandanplayConnection() { | CODE |
| LOW⚡ | danmu_api/ui/js/localdanmu.js | 9 | function localDanmuRedisUnavailable() { | CODE |
| LOW⚡ | danmu_api/ui/js/localdanmu.js | 12 | function showLocalDanmuRedisRequired() { | CODE |
| LOW⚡ | danmu_api/ui/js/localdanmu.js | 19 | function updateLocalDanmuPermission(config) { | CODE |
| LOW | danmu_api/ui/js/localdanmu.js | 37 | function checkLocalDanmuWritePermission(action, event) { | CODE |
| LOW | danmu_api/ui/js/localdanmu.js | 49 | function updateLocalDanmuTypeFields() { | CODE |
| LOW | danmu_api/ui/js/localdanmu.js | 92 | function localDanmuEpisodeFromFilename(filename) { | CODE |
| LOW | danmu_api/ui/js/localdanmu.js | 106 | function updateLocalDanmuUploadFiles() { | CODE |
| LOW | danmu_api/ui/js/localdanmu.js | 235 | function prepareLocalDanmuReupload(resource) { | CODE |
| LOW | danmu_api/apis/dandan-api.js | 77 | function shouldIncludeVideoDuration(queryFormat, includeDuration = false) { | CODE |
| LOW | danmu_api/apis/dandan-api.js | 88 | function extractDurationFromSegments(segmentResult) { | CODE |
| LOW | danmu_api/apis/dandan-api.js | 243 | function isSingleEpisodeMatchCandidate(anime, bangumiData) { | CODE |
| LOW | danmu_api/apis/dandan-api.js | 1263 | function findCrossSeasonEpisodeMap(searchData, title, year, season, episode, platform, detailStore) { | CODE |
| LOW | danmu_api/apis/dandan-api.js | 1744 | export async function extractTitleSeasonEpisode(cleanFileName) { | CODE |
| LOW | danmu_api/apis/dandan-api.js | 1960 | function findSeasonPreferenceTitle(titles, season) { | CODE |
| LOW | danmu_api/apis/dandan-api.js | 1968 | function findLegacySeasonPreferenceTitle(titles, season) { | CODE |
| LOW | danmu_api/apis/system-api.js | 169 | export async function handleRemoteMappingRefresh() { | CODE |
| LOW | danmu_api/apis/local-danmu-api.js | 19 | function invalidateLocalDanmuCache(resourceKey) { | CODE |
| LOW | danmu_api/apis/env-api.js | 10 | function syncIntegrationsAfterEnvChange(key, deployPlatform) { | CODE |
| LOW | danmu_api/apis/favorite-api.js | 57 | function removeRelatedSearchCaches(keyword) { | CODE |
| LOW | danmu_api/apis/clients/fongmi-api.js | 85 | function normalizeFongmiTitleByRegex(name) { | CODE |
| LOW | danmu_api/apis/clients/fongmi-api.js | 99 | function normalizeFongmiEpisodeByRegex(episode) { | CODE |
| LOW | danmu_api/apis/clients/fongmi-api.js | 114 | function extractFongmiEpisodeNumber(episode) { | CODE |
| LOW | danmu_api/apis/clients/fongmi-api.js | 167 | function extractFongmiSeasonNumber(episode) { | CODE |
| LOW | danmu_api/apis/clients/fongmi-api.js | 186 | function buildFongmiSearchKeywords(name) { | CODE |
| LOW | danmu_api/tests/worker-api.test.js | 1255 | async function resetRemoteTitleMappingState() { | CODE |
| LOW | danmu_api/utils/cache-util.js | 88 | function collectUniqueAnimeDetails(detailStore) { | CODE |
| LOW | danmu_api/utils/cache-util.js | 96 | function getActiveSearchCacheEntries() { | CODE |
| LOW | danmu_api/utils/cache-util.js | 219 | export function resolveAnimeByIdFromDetailStore(id, detailStore = null, source = null) { | CODE |
| LOW | danmu_api/utils/cache-util.js | 224 | export function resolveEpisodeContextById(id, detailStore = null) { | CODE |
| 59 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | danmu_api/ui/js/icons.js | 1 | // language=JavaScript | COMMENT |
| LOW | danmu_api/tests/manual/live-source-checks.js | 1 | // 手工巡检:真实数据源联网用例(不参与 node --test 自动发现,也不会在 npm test 中执行) | COMMENT |
| LOW | danmu_api/tests/manual/live-source-checks.js | 441 | // const keyword = "子夜归"; | COMMENT |
| LOW | danmu_api/tests/configs/envs.test.js | 761 | // 因此本文件不包含 ':::' 的断言。 | COMMENT |
| LOW | danmu_api/utils/merge-util.js | 1 | import { globals } from '../configs/globals.js'; | COMMENT |
| LOW | danmu_api/utils/aiyifan-util.js | 1 | import { globals } from '../configs/globals.js'; | COMMENT |
| LOW | danmu_api/sources/registry.js | 1 | // ===================== | COMMENT |
| LOW | danmu_api/sources/registry.js | 41 | COMMENT | |
| LOW | forward/forward-widget.spec.js | 241 | colorPool: '16777215,16744319,16752762,16774799,9498256,8388564,8900346,14204888,16758465', | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | danmu_api/sources/aiyifan.js | 240 | // Step 1: 搜索,拿到剧目列表 | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | danmu_api/sources/aiyifan.js | 240 | // Step 1: 搜索,拿到剧目列表 | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | danmu_api/worker.js | 63 | async function handleRequest(req, env, deployPlatform, clientIp) { | CODE |