Skip to content

Update Chinese localization and refactor code for clarity#394

Merged
wess09 merged 4 commits into
masterfrom
dev
Jun 25, 2026
Merged

Update Chinese localization and refactor code for clarity#394
wess09 merged 4 commits into
masterfrom
dev

Conversation

@wess09

@wess09 wess09 commented Jun 25, 2026

Copy link
Copy Markdown
Owner

Summary by Sourcery

使用基于 scrcpy 的低延迟直播预览与控制(通过 WebSocket),并新增国服活动关卡地图。

New Features:

  • 添加基于 scrcpyws-scrcpy 的实时预览管线,采用原始 H264 传输,并在需要时自动回退到基于 ffmpeg 的截图流。
  • 引入基于 WebSocket 的实时控制通道,以及浏览器端对点击、拖拽、按键事件和移动端文本输入的处理器。
  • 为新的国服活动 event_20260625_cn 添加活动配置和地图脚本,覆盖 T/HT/SP 等关卡。

Bug Fixes:

  • 提升 WebSocket 与流媒体错误处理的健壮性,避免因数据格式错误或连接断开导致的崩溃。

Enhancements:

  • 优化视频码率和帧率(FPS)控制,在前后端实现动态缩放和基于画质的重连逻辑。
  • 重构 WebSocket 实时预览 API,加入共享工具用于解析数值、处理队列和格式化错误信息,并移除未使用的 H265 相关路径。
  • 扩展活动运行器,使其能识别新活动目录,并更新开发环境下地图提取器的默认配置。
Original summary in English

Summary by Sourcery

Implement scrcpy-based low-latency live preview and control over WebSocket and add new CN event campaign maps.

New Features:

  • Add scrcpy and ws-scrcpy based live preview pipeline with raw H264 transport and automatic fallback to ffmpeg screenshot streaming.
  • Introduce a WebSocket-based live control channel and corresponding browser-side handlers for taps, drags, key events, and mobile text input.
  • Add campaign configuration and map scripts for the new CN event event_20260625_cn, including T/HT/SP stages.

Bug Fixes:

  • Improve robustness of WebSocket and streaming error handling to avoid crashes on malformed data or disconnections.

Enhancements:

  • Refine video bitrate and FPS handling with dynamic scaling and quality-based reconnect logic in both backend and frontend.
  • Refactor WebSocket live preview API with shared helpers for parsing numbers, handling queues, and formatting error messages, and remove unused H265 path.
  • Extend campaign runner to recognize the new event folders and update dev map extractor defaults.

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@wess09 wess09 merged commit c5d8e4f into master Jun 25, 2026
7 of 8 checks passed
@sourcery-ai

sourcery-ai Bot commented Jun 25, 2026

Copy link
Copy Markdown

Reviewer's Guide

重构实时预览的后端和前端,以支持基于 scrcpy 和 ws-scrcpy 的低延迟 H264 流媒体(自适应画质和交互式设备控制),同时新增一个 CN 活动档期(20260625),并更新相关工具和元数据。

实时预览启动与推流时序图(ws_live_screenshot)

sequenceDiagram
    actor Browser
    participant WebUI as WebUIServer
    participant Scrcpy as LiveScrcpySession
    participant WsScrcpy as LiveWsScrcpySession
    participant FFmpeg as ffmpeg_screenshot_fallback

    Browser->>WebUI: WebSocket /ws/live_screenshot(mode,fps,width,bitrate_scale)
    WebUI->>WebUI: _ws_live_scrcpy(instance,fps,width,bitrate_scale)
    alt ws-scrcpy available
        WebUI->>WsScrcpy: LiveWsScrcpySession(instance,...)
        WebUI->>WsScrcpy: start_server()
        WebUI->>WsScrcpy: connect()
        WsScrcpy-->>WebUI: recv() initial
        WebUI->>WebUI: _ws_scrcpy_parse_initial(initial)
        WebUI->>WsScrcpy: send_binary(_build_ws_scrcpy_video_settings(...))
        WebUI->>WebUI: _collect_ws_scrcpy_preroll(session)
        WebUI-->>Browser: ready (mode=ws-scrcpy, format=raw_h264)
        loop video stream
            WsScrcpy-->>WebUI: recv()
            WebUI-->>Browser: send_bytes(data)
        end
    else ws-scrcpy failed
        WebUI->>Scrcpy: LiveScrcpySession.acquire(instance,fps,width,bitrate_scale)
        WebUI->>WebUI: _collect_h264_preroll(session,stop_event)
        WebUI-->>Browser: ready (mode=scrcpy, format=raw_h264)
        WebUI-->>Browser: send_bytes(preroll)
        loop raw H264
            Scrcpy-->>WebUI: read_video()
            WebUI-->>Browser: send_bytes(raw_h264)
        end
    else scrcpy unavailable or mode=screenshot
        WebUI->>FFmpeg: _ws_live_screenshot_fallback(...)
        WebUI-->>Browser: ready (mode=screenshot, mime=video/mp4)
        loop screenshots
            FFmpeg-->>WebUI: out_queue (data)
            WebUI-->>Browser: send_bytes(chunk)
        end
    end
Loading

交互式设备控制时序图(ws_live_control)

sequenceDiagram
    actor Browser
    participant WebUI as WebUIServer
    participant WsScrcpy as LiveWsScrcpySession
    participant Scrcpy as LiveScrcpySession
    participant ADB as LiveControlDevice

    Browser->>WebUI: WebSocket /ws/live_control?instance=...
    WebUI->>WebUI: get_target()
    alt ws-scrcpy session exists
        WebUI->>WsScrcpy: LiveWsScrcpySession.get(instance)
    else scrcpy session exists
        WebUI->>Scrcpy: LiveScrcpySession.get(instance)
    else fallback
        WebUI->>ADB: LiveControlDevice(instance)
    end

    loop control messages
        Browser-->>WebUI: receive_text() (JSON)
        WebUI->>WebUI: json.loads(raw)
        alt type=tap
            WebUI->>target: tap(x,y)
        else type=drag
            WebUI->>target: drag(start,end,duration_ms)
        else type=key
            WebUI->>WebUI: _key_to_android_keycode(key)
            WebUI->>target: keycode(keycode)
        else type=text
            WebUI->>target: text(text)
        else system actions (back,home,app_switch)
            WebUI->>target: keycode(CONTROL_ACTION_KEYCODES[action])
        else unknown
            WebUI-->>Browser: send_text({type:error,...})
        end
    end
Loading

File-Level Changes

Change Details Files
重构实时预览后端,以支持基于 scrcpy/ws-scrcpy 的原始 H264 流式传输(自适应参数)以及独立的控制通道。
  • 新增辅助工具,用于解析数值参数、安全队列使用以及计算动态视频流码率设置。
  • 添加 H264 NAL 解析工具和预滚帧收集逻辑,以从原始流中推导编解码器字符串和 AVCC 描述信息。
  • 实现 LiveWsScrcpySessionLiveScrcpySession 类,用于管理 ws-scrcpy 与经典 scrcpy 会话,包括生命周期、码率以及输入事件。
  • ws_live_screenshot 拆分为以 scrcpy 优先的处理管线,并在失败时回退到 ffmpeg 截图方案,同时输出更丰富的 ready/错误元数据。
  • 新增 ws_live_control WebSocket 端点,将点击/拖拽/按键/文本等操作代理到当前活动的 scrcpy/ws-scrcpy 会话或回退的 ADB 输入。
module/webui/api.py
全面改造 WebUI 实时预览客户端,以支持通过 WebCodecs 解码原始 H264、自适应画质控制以及全屏交互控制。
  • 用控制按钮和全屏切换替换编码器选择器;新增画布和隐藏文本域,用于输入与控制。
  • 添加 H264 Annex B 解析/组装逻辑、基于 WebCodecs 的解码管线,以及在 raw_h264 与分片 MP4 传输之间切换的逻辑。
  • 实现基于播放健康状况的自适应码率/fps 策略,能够在重连时更新 bitrate_scale/fps,并在 scrcpy 不可用时切换模式。
  • 引入专用的 /ws/live_control 客户端,用于排队并发送控制消息,同时绑定系统按钮、键盘输入、指针事件以及全屏生命周期。
assets/gui/js/alas-utils.js
新增 CN 活动档期 20260625,包含 普通/高难/SP 关卡,并将其接入工具链和活动解析逻辑。
  • event_20260625_cn 创建 T1–T3 和 HT1–HT3 关卡定义,以及 SP 地图配置,包含刷怪、权重和配置元数据。
  • 更新 map_extractor 默认值,使其指向新的活动目录和 KEYWORD。
  • 在活动运行路由中注册新的活动目录,覆盖普通与高难模式。
  • campaign/Readme.md 中添加该活动行,并更新新活动的本地化/参数配置(文件名已在表中列出供审查)。
campaign/event_20260625_cn/t1.py
campaign/event_20260625_cn/t2.py
campaign/event_20260625_cn/t3.py
campaign/event_20260625_cn/ht1.py
campaign/event_20260625_cn/ht2.py
campaign/event_20260625_cn/ht3.py
campaign/event_20260625_cn/sp.py
dev_tools/map_extractor.py
module/campaign/run.py
campaign/Readme.md
module/config/argument/args.json
module/config/i18n/en-US.json
module/config/i18n/ja-JP.json
module/config/i18n/zh-CN.json
module/config/i18n/zh-MIAO.json
module/config/i18n/zh-TW.json

Tips and commands

Interacting with Sourcery

  • 触发新审核: 在 Pull Request 中评论 @sourcery-ai review
  • 继续讨论: 直接回复 Sourcery 的审核评论。
  • 从审核评论生成 GitHub issue: 在审核评论下回复,请求 Sourcery 从该评论创建 issue。也可以直接回复 @sourcery-ai issue,将该评论转换为 issue。
  • 生成 Pull Request 标题: 在 Pull Request 标题中任意位置写上 @sourcery-ai,即可随时生成标题。也可以在 Pull Request 中评论 @sourcery-ai title 来(重新)生成标题。
  • 生成 Pull Request 摘要: 在 Pull Request 正文的任意位置写上 @sourcery-ai summary,即可在该位置生成 PR 摘要。也可以在 Pull Request 中评论 @sourcery-ai summary 来(重新)生成摘要。
  • 生成 Reviewer's Guide: 在 Pull Request 中评论 @sourcery-ai guide,即可随时(重新)生成审核者指南。
  • 一次性解决所有 Sourcery 评论: 在 Pull Request 中评论 @sourcery-ai resolve,即可将所有 Sourcery 评论标记为已解决。如果你已经处理完所有评论但不想再看到它们,这会非常有用。
  • 批量忽略所有 Sourcery 审核: 在 Pull Request 中评论 @sourcery-ai dismiss,即可忽略所有现有的 Sourcery 审核。若你希望以一次全新的审核开始,这尤其有用——别忘了再评论 @sourcery-ai review 来触发新的审核!

Customizing Your Experience

进入你的 dashboard 以:

  • 启用或禁用审核功能,例如 Sourcery 自动生成的 Pull Request 摘要、审核者指南等。
  • 更改审核语言。
  • 添加、移除或编辑自定义审核说明。
  • 调整其他审核设置。

Getting Help

Original review guide in English

Reviewer's Guide

Refactors the live preview backend and frontend to support scrcpy- and ws-scrcpy-based low-latency H264 streaming with adaptive quality and interactive device control, while adding a new CN event campaign (20260625) and updating associated tooling and metadata.

Sequence diagram for live preview startup and streaming (ws_live_screenshot)

sequenceDiagram
    actor Browser
    participant WebUI as WebUIServer
    participant Scrcpy as LiveScrcpySession
    participant WsScrcpy as LiveWsScrcpySession
    participant FFmpeg as ffmpeg_screenshot_fallback

    Browser->>WebUI: WebSocket /ws/live_screenshot(mode,fps,width,bitrate_scale)
    WebUI->>WebUI: _ws_live_scrcpy(instance,fps,width,bitrate_scale)
    alt ws-scrcpy available
        WebUI->>WsScrcpy: LiveWsScrcpySession(instance,...)
        WebUI->>WsScrcpy: start_server()
        WebUI->>WsScrcpy: connect()
        WsScrcpy-->>WebUI: recv() initial
        WebUI->>WebUI: _ws_scrcpy_parse_initial(initial)
        WebUI->>WsScrcpy: send_binary(_build_ws_scrcpy_video_settings(...))
        WebUI->>WebUI: _collect_ws_scrcpy_preroll(session)
        WebUI-->>Browser: ready (mode=ws-scrcpy, format=raw_h264)
        loop video stream
            WsScrcpy-->>WebUI: recv()
            WebUI-->>Browser: send_bytes(data)
        end
    else ws-scrcpy failed
        WebUI->>Scrcpy: LiveScrcpySession.acquire(instance,fps,width,bitrate_scale)
        WebUI->>WebUI: _collect_h264_preroll(session,stop_event)
        WebUI-->>Browser: ready (mode=scrcpy, format=raw_h264)
        WebUI-->>Browser: send_bytes(preroll)
        loop raw H264
            Scrcpy-->>WebUI: read_video()
            WebUI-->>Browser: send_bytes(raw_h264)
        end
    else scrcpy unavailable or mode=screenshot
        WebUI->>FFmpeg: _ws_live_screenshot_fallback(...)
        WebUI-->>Browser: ready (mode=screenshot, mime=video/mp4)
        loop screenshots
            FFmpeg-->>WebUI: out_queue (data)
            WebUI-->>Browser: send_bytes(chunk)
        end
    end
Loading

Sequence diagram for interactive device control (ws_live_control)

sequenceDiagram
    actor Browser
    participant WebUI as WebUIServer
    participant WsScrcpy as LiveWsScrcpySession
    participant Scrcpy as LiveScrcpySession
    participant ADB as LiveControlDevice

    Browser->>WebUI: WebSocket /ws/live_control?instance=...
    WebUI->>WebUI: get_target()
    alt ws-scrcpy session exists
        WebUI->>WsScrcpy: LiveWsScrcpySession.get(instance)
    else scrcpy session exists
        WebUI->>Scrcpy: LiveScrcpySession.get(instance)
    else fallback
        WebUI->>ADB: LiveControlDevice(instance)
    end

    loop control messages
        Browser-->>WebUI: receive_text() (JSON)
        WebUI->>WebUI: json.loads(raw)
        alt type=tap
            WebUI->>target: tap(x,y)
        else type=drag
            WebUI->>target: drag(start,end,duration_ms)
        else type=key
            WebUI->>WebUI: _key_to_android_keycode(key)
            WebUI->>target: keycode(keycode)
        else type=text
            WebUI->>target: text(text)
        else system actions (back,home,app_switch)
            WebUI->>target: keycode(CONTROL_ACTION_KEYCODES[action])
        else unknown
            WebUI-->>Browser: send_text({type:error,...})
        end
    end
Loading

File-Level Changes

Change Details Files
Refactor live preview backend to support scrcpy/ws-scrcpy raw H264 streaming with adaptive parameters and a separate control channel.
  • Introduce helper utilities for parsing numeric params, safe queue usage, and computing dynamic video stream bitrate settings.
  • Add H264 NAL parsing utilities and preroll collection to derive codec strings and AVCC description for raw streams.
  • Implement LiveWsScrcpySession and LiveScrcpySession classes to manage ws-scrcpy and classic scrcpy sessions, including lifecycle, bitrate, and input events.
  • Split ws_live_screenshot into a scrcpy-first pipeline with ffmpeg screenshot fallback, emitting richer ready/error metadata.
  • Add ws_live_control WebSocket endpoint to proxy tap/drag/key/text actions to the active scrcpy/ws-scrcpy session or fallback ADB input.
module/webui/api.py
Overhaul WebUI live preview client to support raw H264 via WebCodecs, adaptive quality control, and full-screen interactive control.
  • Replace codec selector with control buttons and fullscreen toggle; add canvas and hidden textarea for input and control.
  • Add H264 Annex B parsing/assembly, WebCodecs-based decoding pipeline, and logic to switch between raw_h264 and fragmented MP4 transport.
  • Implement adaptive bitrate/fps logic based on playback health, reconnecting with updated bitrate_scale/fps and switching modes when scrcpy is unavailable.
  • Introduce a dedicated /ws/live_control client, queueing and sending control messages and binding system buttons, keyboard input, pointer events, and fullscreen lifecycle.
assets/gui/js/alas-utils.js
Add new CN event campaign 20260625 with normal/hard/SP stages and wire it into tooling and campaign resolution.
  • Create T1–T3 and HT1–HT3 stage definitions and SP map for event_20260625_cn with spawn, weight, and config metadata.
  • Update map_extractor defaults to point at the new event folder and KEYWORD.
  • Register the new event folder in campaign run routing for both normal and hard modes.
  • Add the event row to campaign/Readme.md and update localization / args configs for the new event (filenames listed for review).
campaign/event_20260625_cn/t1.py
campaign/event_20260625_cn/t2.py
campaign/event_20260625_cn/t3.py
campaign/event_20260625_cn/ht1.py
campaign/event_20260625_cn/ht2.py
campaign/event_20260625_cn/ht3.py
campaign/event_20260625_cn/sp.py
dev_tools/map_extractor.py
module/campaign/run.py
campaign/Readme.md
module/config/argument/args.json
module/config/i18n/en-US.json
module/config/i18n/ja-JP.json
module/config/i18n/zh-CN.json
module/config/i18n/zh-MIAO.json
module/config/i18n/zh-TW.json

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - 我发现了 4 个安全问题,并给出了一些总体反馈:

安全问题

  • innerHTMLouterHTMLdocument.write 等方法中使用用户可控数据是一种反模式,可能导致 XSS 漏洞(链接
  • panel.innerHTML 中使用用户可控数据是一种反模式,可能导致 XSS 漏洞(链接
  • 检测到不安全的 WebSocket。所有 WebSocket 连接都应该使用安全 WebSocket (wss)。(链接
  • 检测到使用 Popen 的子进程调用且未使用静态字符串。如果这些数据可能被恶意行为者控制,则可能存在命令注入风险。请审计该调用以确保它不能被外部资源控制。你可以考虑使用 shlex.escape()。(链接

一般性评论

  • LiveScrcpySession._scrcpy_command 在调用 command_v120 之前,会临时修改全局 ScrcpyOptions.frame_rate。建议考虑通过参数传递 FPS 或克隆选项,而不是修改共享的全局状态,以避免在其他代码并发构建 scrcpy 命令时出现意料之外的副作用。
  • LiveWsScrcpySessionLiveScrcpySession 都实现了类似的坐标缩放逻辑(_scale_point/scale_point)以及触摸/拖拽/按键/文本等控制流程;建议抽取用于指针缩放和控制消息构造的共享辅助函数,以减少重复,并帮助在不同模式下保持行为一致。
  • _video_stream_params 目前接收一个 codec 参数,但并未根据它进行分支逻辑,同时 ws_live_screenshot 强制使用 codec="h264";建议要么移除未使用的 codec 参数和前端的编解码器设置,要么实现所需的编解码器特定行为,以保持 API 设计的一致性。
供 AI 代理使用的提示词
请根据以下代码评审意见进行修改:

## 总体评论
- `LiveScrcpySession._scrcpy_command` 在调用 `command_v120` 之前,会临时修改全局 `ScrcpyOptions.frame_rate`。建议考虑通过参数传递 FPS 或克隆选项,而不是修改共享的全局状态,以避免在其他代码并发构建 scrcpy 命令时出现意料之外的副作用。
- `LiveWsScrcpySession``LiveScrcpySession` 都实现了类似的坐标缩放逻辑(`_scale_point`/`scale_point`)以及触摸/拖拽/按键/文本等控制流程;建议抽取用于指针缩放和控制消息构造的共享辅助函数,以减少重复,并帮助在不同模式下保持行为一致。
- `_video_stream_params` 目前接收一个 `codec` 参数,但并未根据它进行分支逻辑,同时 `ws_live_screenshot` 强制使用 `codec="h264"`;建议要么移除未使用的 `codec` 参数和前端的编解码器设置,要么实现所需的编解码器特定行为,以保持 API 设计的一致性。

## 单独评论

### 评论 1
<location path="assets/gui/js/alas-utils.js" line_range="231-245" />
<code_context>
        panel.innerHTML = [
            '<div class="alas-live-preview-head">',
            '<span class="alas-live-preview-title">实时截图</span>',
            '<button class="alas-live-preview-control" type="button" data-live-control="back" title="返回">↩</button>',
            '<button class="alas-live-preview-control" type="button" data-live-control="home" title="主页">⌂</button>',
            '<button class="alas-live-preview-control" type="button" data-live-control="app_switch" title="后台">▣</button>',
            '<button class="alas-live-preview-control" type="button" data-live-control="keyboard" title="手机键盘">⌨</button>',
            '<button class="alas-live-preview-fullscreen" type="button" title="全屏控制">⛶</button>',
            '<button class="alas-live-preview-close" type="button" title="关闭">×</button>',
            '</div>',
            '<video class="alas-live-preview-video" muted autoplay playsinline></video>',
            '<canvas class="alas-live-preview-canvas"></canvas>',
            '<textarea class="alas-live-preview-keyboard-input" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"></textarea>',
            '<div class="alas-live-preview-status">连接中</div>'
        ].join('');
</code_context>
<issue_to_address>
**security (javascript.browser.security.insecure-document-method):**`innerHTML``outerHTML``document.write` 等方法中使用用户可控数据是一种反模式,可能导致 XSS 漏洞。

*Source: opengrep*
</issue_to_address>

### 评论 2
<location path="assets/gui/js/alas-utils.js" line_range="231-245" />
<code_context>
        panel.innerHTML = [
            '<div class="alas-live-preview-head">',
            '<span class="alas-live-preview-title">实时截图</span>',
            '<button class="alas-live-preview-control" type="button" data-live-control="back" title="返回">↩</button>',
            '<button class="alas-live-preview-control" type="button" data-live-control="home" title="主页">⌂</button>',
            '<button class="alas-live-preview-control" type="button" data-live-control="app_switch" title="后台">▣</button>',
            '<button class="alas-live-preview-control" type="button" data-live-control="keyboard" title="手机键盘">⌨</button>',
            '<button class="alas-live-preview-fullscreen" type="button" title="全屏控制">⛶</button>',
            '<button class="alas-live-preview-close" type="button" title="关闭">×</button>',
            '</div>',
            '<video class="alas-live-preview-video" muted autoplay playsinline></video>',
            '<canvas class="alas-live-preview-canvas"></canvas>',
            '<textarea class="alas-live-preview-keyboard-input" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"></textarea>',
            '<div class="alas-live-preview-status">连接中</div>'
        ].join('');
</code_context>
<issue_to_address>
**security (javascript.browser.security.insecure-innerhtml):**`panel.innerHTML` 中使用用户可控数据是一种反模式,可能导致 XSS 漏洞。

*Source: opengrep*
</issue_to_address>

### 评论 3
<location path="assets/gui/js/alas-utils.js" line_range="761" />
<code_context>
        var scheme = location.protocol === 'https:' ? 'wss://' : 'ws://';
</code_context>
<issue_to_address>
**security (javascript.lang.security.detect-insecure-websocket):** 检测到不安全的 WebSocket。所有 WebSocket 连接都应该使用安全 WebSocket (wss)。

*Source: opengrep*
</issue_to_address>

### 评论 4
<location path="module/webui/api.py" line_range="1165-1169" />
<code_context>
        proc = subprocess.Popen(
            _video_stream_command(ffmpeg, codec, target_width, target_height, fps, stream_params),
            stdin=subprocess.PIPE,
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,
            bufsize=0,
        )
</code_context>
<issue_to_address>
**security (python.lang.security.audit.dangerous-subprocess-use-audit):** 检测到使用子进程函数 `Popen` 且未使用静态字符串。如果这些数据可能被恶意行为者控制,则可能存在命令注入风险。请审计该调用以确保它不能被外部资源控制。你可以考虑使用 `shlex.escape()`*Source: opengrep*
</issue_to_address>

Sourcery 对开源项目免费——如果你觉得我们的评审有帮助,欢迎分享 ✨
帮我变得更有用!请对每个评论点 👍 或 👎,我会根据你的反馈改进后续评审。
Original comment in English

Hey - I've found 4 security issues, and left some high level feedback:

Security issues:

  • User controlled data in methods like innerHTML, outerHTML or document.write is an anti-pattern that can lead to XSS vulnerabilities (link)
  • User controlled data in a panel.innerHTML is an anti-pattern that can lead to XSS vulnerabilities (link)
  • Insecure WebSocket Detected. WebSocket Secure (wss) should be used for all WebSocket connections. (link)
  • Detected subprocess function 'Popen' without a static string. If this data can be controlled by a malicious actor, it may be an instance of command injection. Audit the use of this call to ensure it is not controllable by an external resource. You may consider using 'shlex.escape()'. (link)

General comments:

  • LiveScrcpySession._scrcpy_command temporarily mutates the global ScrcpyOptions.frame_rate before calling command_v120; consider passing the FPS via arguments or cloning options instead of changing a shared global to avoid surprising side effects if other code builds scrcpy commands concurrently.
  • LiveWsScrcpySession and LiveScrcpySession both implement similar coordinate scaling logic (_scale_point/scale_point) and touch/drag/key/text control flows; extracting shared helpers for pointer scaling and control message construction would reduce duplication and help keep behavior consistent across modes.
  • _video_stream_params currently accepts a codec parameter but does not branch on it and ws_live_screenshot forces codec="h264"; either remove the unused codec parameter and front-end codec setting or implement the required codec-specific behavior to keep the API surface coherent.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- LiveScrcpySession._scrcpy_command temporarily mutates the global ScrcpyOptions.frame_rate before calling command_v120; consider passing the FPS via arguments or cloning options instead of changing a shared global to avoid surprising side effects if other code builds scrcpy commands concurrently.
- LiveWsScrcpySession and LiveScrcpySession both implement similar coordinate scaling logic (_scale_point/scale_point) and touch/drag/key/text control flows; extracting shared helpers for pointer scaling and control message construction would reduce duplication and help keep behavior consistent across modes.
- _video_stream_params currently accepts a codec parameter but does not branch on it and ws_live_screenshot forces codec="h264"; either remove the unused codec parameter and front-end codec setting or implement the required codec-specific behavior to keep the API surface coherent.

## Individual Comments

### Comment 1
<location path="assets/gui/js/alas-utils.js" line_range="231-245" />
<code_context>
        panel.innerHTML = [
            '<div class="alas-live-preview-head">',
            '<span class="alas-live-preview-title">实时截图</span>',
            '<button class="alas-live-preview-control" type="button" data-live-control="back" title="返回">↩</button>',
            '<button class="alas-live-preview-control" type="button" data-live-control="home" title="主页">⌂</button>',
            '<button class="alas-live-preview-control" type="button" data-live-control="app_switch" title="后台">▣</button>',
            '<button class="alas-live-preview-control" type="button" data-live-control="keyboard" title="手机键盘">⌨</button>',
            '<button class="alas-live-preview-fullscreen" type="button" title="全屏控制">⛶</button>',
            '<button class="alas-live-preview-close" type="button" title="关闭">×</button>',
            '</div>',
            '<video class="alas-live-preview-video" muted autoplay playsinline></video>',
            '<canvas class="alas-live-preview-canvas"></canvas>',
            '<textarea class="alas-live-preview-keyboard-input" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"></textarea>',
            '<div class="alas-live-preview-status">连接中</div>'
        ].join('');
</code_context>
<issue_to_address>
**security (javascript.browser.security.insecure-document-method):** User controlled data in methods like `innerHTML`, `outerHTML` or `document.write` is an anti-pattern that can lead to XSS vulnerabilities

*Source: opengrep*
</issue_to_address>

### Comment 2
<location path="assets/gui/js/alas-utils.js" line_range="231-245" />
<code_context>
        panel.innerHTML = [
            '<div class="alas-live-preview-head">',
            '<span class="alas-live-preview-title">实时截图</span>',
            '<button class="alas-live-preview-control" type="button" data-live-control="back" title="返回">↩</button>',
            '<button class="alas-live-preview-control" type="button" data-live-control="home" title="主页">⌂</button>',
            '<button class="alas-live-preview-control" type="button" data-live-control="app_switch" title="后台">▣</button>',
            '<button class="alas-live-preview-control" type="button" data-live-control="keyboard" title="手机键盘">⌨</button>',
            '<button class="alas-live-preview-fullscreen" type="button" title="全屏控制">⛶</button>',
            '<button class="alas-live-preview-close" type="button" title="关闭">×</button>',
            '</div>',
            '<video class="alas-live-preview-video" muted autoplay playsinline></video>',
            '<canvas class="alas-live-preview-canvas"></canvas>',
            '<textarea class="alas-live-preview-keyboard-input" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"></textarea>',
            '<div class="alas-live-preview-status">连接中</div>'
        ].join('');
</code_context>
<issue_to_address>
**security (javascript.browser.security.insecure-innerhtml):** User controlled data in a `panel.innerHTML` is an anti-pattern that can lead to XSS vulnerabilities

*Source: opengrep*
</issue_to_address>

### Comment 3
<location path="assets/gui/js/alas-utils.js" line_range="761" />
<code_context>
        var scheme = location.protocol === 'https:' ? 'wss://' : 'ws://';
</code_context>
<issue_to_address>
**security (javascript.lang.security.detect-insecure-websocket):** Insecure WebSocket Detected. WebSocket Secure (wss) should be used for all WebSocket connections.

*Source: opengrep*
</issue_to_address>

### Comment 4
<location path="module/webui/api.py" line_range="1165-1169" />
<code_context>
        proc = subprocess.Popen(
            _video_stream_command(ffmpeg, codec, target_width, target_height, fps, stream_params),
            stdin=subprocess.PIPE,
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,
            bufsize=0,
        )
</code_context>
<issue_to_address>
**security (python.lang.security.audit.dangerous-subprocess-use-audit):** Detected subprocess function 'Popen' without a static string. If this data can be controlled by a malicious actor, it may be an instance of command injection. Audit the use of this call to ensure it is not controllable by an external resource. You may consider using 'shlex.escape()'.

*Source: opengrep*
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment on lines 231 to 245
panel.innerHTML = [
'<div class="alas-live-preview-head">',
'<span class="alas-live-preview-title">实时截图</span>',
'<select class="alas-live-preview-codec" title="编码">',
'<option value="h264">H264</option>',
'<option value="h265">H265</option>',
'</select>',
'<button class="alas-live-preview-control" type="button" data-live-control="back" title="返回">↩</button>',
'<button class="alas-live-preview-control" type="button" data-live-control="home" title="主页">⌂</button>',
'<button class="alas-live-preview-control" type="button" data-live-control="app_switch" title="后台">▣</button>',
'<button class="alas-live-preview-control" type="button" data-live-control="keyboard" title="手机键盘">⌨</button>',
'<button class="alas-live-preview-fullscreen" type="button" title="全屏控制">⛶</button>',
'<button class="alas-live-preview-close" type="button" title="关闭">×</button>',
'</div>',
'<video class="alas-live-preview-video" muted autoplay playsinline></video>',
'<canvas class="alas-live-preview-canvas"></canvas>',
'<textarea class="alas-live-preview-keyboard-input" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"></textarea>',
'<div class="alas-live-preview-status">连接中</div>'
].join('');

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security (javascript.browser.security.insecure-document-method):innerHTMLouterHTMLdocument.write 等方法中使用用户可控数据是一种反模式,可能导致 XSS 漏洞。

Source: opengrep

Original comment in English

security (javascript.browser.security.insecure-document-method): User controlled data in methods like innerHTML, outerHTML or document.write is an anti-pattern that can lead to XSS vulnerabilities

Source: opengrep

Comment on lines 231 to 245
panel.innerHTML = [
'<div class="alas-live-preview-head">',
'<span class="alas-live-preview-title">实时截图</span>',
'<select class="alas-live-preview-codec" title="编码">',
'<option value="h264">H264</option>',
'<option value="h265">H265</option>',
'</select>',
'<button class="alas-live-preview-control" type="button" data-live-control="back" title="返回">↩</button>',
'<button class="alas-live-preview-control" type="button" data-live-control="home" title="主页">⌂</button>',
'<button class="alas-live-preview-control" type="button" data-live-control="app_switch" title="后台">▣</button>',
'<button class="alas-live-preview-control" type="button" data-live-control="keyboard" title="手机键盘">⌨</button>',
'<button class="alas-live-preview-fullscreen" type="button" title="全屏控制">⛶</button>',
'<button class="alas-live-preview-close" type="button" title="关闭">×</button>',
'</div>',
'<video class="alas-live-preview-video" muted autoplay playsinline></video>',
'<canvas class="alas-live-preview-canvas"></canvas>',
'<textarea class="alas-live-preview-keyboard-input" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"></textarea>',
'<div class="alas-live-preview-status">连接中</div>'
].join('');

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security (javascript.browser.security.insecure-innerhtml):panel.innerHTML 中使用用户可控数据是一种反模式,可能导致 XSS 漏洞。

Source: opengrep

Original comment in English

security (javascript.browser.security.insecure-innerhtml): User controlled data in a panel.innerHTML is an anti-pattern that can lead to XSS vulnerabilities

Source: opengrep

@@ -334,7 +760,11 @@
function getSocketCandidates() {
var scheme = location.protocol === 'https:' ? 'wss://' : 'ws://';

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security (javascript.lang.security.detect-insecure-websocket): 检测到不安全的 WebSocket。所有 WebSocket 连接都应该使用安全 WebSocket (wss)。

Source: opengrep

Original comment in English

security (javascript.lang.security.detect-insecure-websocket): Insecure WebSocket Detected. WebSocket Secure (wss) should be used for all WebSocket connections.

Source: opengrep

Comment thread module/webui/api.py
Comment on lines 1165 to 1169
proc = subprocess.Popen(
_video_stream_command(ffmpeg, codec, target_width, target_height, fps),
_video_stream_command(ffmpeg, codec, target_width, target_height, fps, stream_params),
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security (python.lang.security.audit.dangerous-subprocess-use-audit): 检测到使用子进程函数 Popen 且未使用静态字符串。如果这些数据可能被恶意行为者控制,则可能存在命令注入风险。请审计该调用以确保它不能被外部资源控制。你可以考虑使用 shlex.escape()

Source: opengrep

Original comment in English

security (python.lang.security.audit.dangerous-subprocess-use-audit): Detected subprocess function 'Popen' without a static string. If this data can be controlled by a malicious actor, it may be an instance of command injection. Audit the use of this call to ensure it is not controllable by an external resource. You may consider using 'shlex.escape()'.

Source: opengrep

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a real-time video preview feature using H264 over WebSockets (via scrcpy/ws-scrcpy) with canvas rendering, fullscreen control, and mobile keyboard support. It also adds map scripts and configurations for the new event "美梦巡演:奇妙夜" (event_20260625_cn), alongside various localization updates and terminology standardizations across English, Japanese, and Chinese translation files. The review feedback highlights localization issues where the new event name was left in Simplified Chinese in the English, Japanese, and Traditional Chinese translation files, and points out a quotation mark typo in the Traditional Chinese translation.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

"event_20260326_cn": "The Vagabond’s Recruitment Plan",
"event_20260417_cn": "Vacation Lane – Beachside Brilliance",
"event_20260520_cn": "Alliance Before the Hagiobull",
"event_20260625_cn": "美梦巡演:奇妙夜",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The new event name is in Chinese in the English localization file. Please translate "美梦巡演:奇妙夜" to English.

"event_20260326_cn": "ワンダラー募集計画",
"event_20260417_cn": "バケーションレーン・きらめく砂浜",
"event_20260520_cn": "聖印前の同盟",
"event_20260625_cn": "美梦巡演:奇妙夜",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The new event name is in Chinese in the Japanese localization file. Please translate "美梦巡演:奇妙夜" to Japanese.

"event_20260326_cn": "漫遊者招募計劃",
"event_20260417_cn": "假日航線閃耀海濱",
"event_20260520_cn": "聖印前的同盟",
"event_20260625_cn": "美梦巡演:奇妙夜",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The event name "美梦巡演:奇妙夜" is in Simplified Chinese. In this Traditional Chinese localization file, it should be converted to "美夢巡演:奇妙夜".

Suggested change
"event_20260625_cn": "美梦巡演:奇妙夜",
"event_20260625_cn": "美夢巡演:奇妙夜",

"help": "需要同時開啟「推送大世界相關資訊」功能。\n關閉時使用智慧港區設定 —> 調試設定 —> 錯誤推送設定,需要同時開啟「錯誤推送」功能。\n開啟時使用大世界推送設定,需要分離推送內容時請開啟此功能"
},
"OpsiOnePushConfig": {
"name": "大世界推送設定",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

There appears to be a typo with the opening quotation mark. A closing quotation mark is used instead of an opening one. For consistency with Taiwanese punctuation, it's better to use and .

      "help": "「大世界資訊獨立推送」功能開啟時設定才生效。使用 Onepush 推送一條關於侵蝕1和短貓的資訊。配置方法見文檔:https://github.com/LmeSzinc/AzurLaneAutoScript/wiki/Onepush-configuration-%5BCN%5D"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant