Commit Graph
349 Commits
Author SHA1 Message Date
DrSmoothl 0d14408b6f feat(protocol): add byte-complete packet tracing
Capture complete packet request, reply, and push payloads during temporary TRACE sessions while preserving the existing non-persistent logging boundary.

Correlate transport, parser, enrichment, drop, dispatch, timeout, and terminal outcomes with their real identifiers so exported logs can explain packet failures without relying on user descriptions.

Lock byte completeness, lazy disabled behavior, concurrency, context propagation, and truthful terminal outcomes with regression coverage.
2026-07-30 20:11:02 +08:00
DrSmoothl f0ff8da2fa feat(onebot): support moving friends between categories
Add the set_friends_category action with either an existing category ID or an exact unique category name.

Validate the current friend and category roster before applying a change, reject missing or ambiguous targets, and surface failed updates instead of reporting false success. Expose the action through the SDK types and cover validation, successful updates, repeat requests, service rejection, and registry completeness.

Closes #297
2026-07-30 10:37:16 +08:00
DrSmoothl 655226d9d7 fix(logging): harden file level configuration
Make persisted log filtering predictable across supported startup settings while rejecting configurations that could silently retain more data than intended.

Keep the first WebUI login credential available without weakening normal log thresholds, clarify the operator-facing behavior, and strengthen regression coverage across isolated environments and explicit file-output disablement.
2026-07-30 10:27:43 +08:00
DrSmoothl e5f256f4dc feat(webui): report account storage update progress
Surface account storage preparation and background history progress through the existing live connection status channel. Clearly distinguish unavailable accounts from accounts that remain fully usable during maintenance.

Show processed totals, completion percentage, estimated remaining time, and retry states in both the global notice and account overview. Preserve existing connection update filtering to avoid unnecessary refreshes.
2026-07-30 09:57:31 +08:00
DrSmoothl 25e61ce5df fix(onebot): continue storage updates after account startup
Start each account as soon as its message storage is ready, then continue older history updates without delaying normal account availability. Keep already started accounts online when maintenance needs to be retried.

Handle preparation failures, stale completions, early exits, logout, and shutdown consistently. Add lifecycle coverage for startup ordering, automatic retries, cancellation, and account availability.
2026-07-30 09:57:18 +08:00
DrSmoothl b71279dcc3 feat(core): add bounded login history queries
Expose a read-only cursor probe plus one-page group and private history methods for login backfill. Validate targets, ranges, response ordering, and page sizes before returning decoded events.

Serialize all history traffic through a process-wide gate. Automatic requests keep a two-second gap, accept at most 100 targets per kind and 20 sequence slots per session, and honor account cancellation before any queued network operation starts.

Keep the probe side-effect free by omitting read markers, and add focused tests for packet budgets, invalid responses, throttling, cancellation, and continued gate usability after failures. Refs #280.
2026-07-25 23:43:59 +08:00
H3CoF6 3517257aa6 feat(onebot): expose friend dress queries (#277)
Add a read-only action for querying QQ profile decorations from the authenticated web page.

Validate and classify page responses, expose structured errors, and cover parsing with a sanitized fixture.
2026-07-25 19:53:24 +08:00
DrSmoothl dff4b3b032 fix(friend): align remark and delete protocols
Route friend remark updates and clears through the commands used by current QQ clients. Emit the required delete flags and surface post-delete cache refresh failures.

Add byte-exact regression coverage for all affected requests.

Fixes #284.
2026-07-25 15:41:02 +08:00
DrSmoothl 87a604ecbd feat(storage): add managed storage controls
Enforce a global log quota with configurable retention and observable degradation. Add authenticated storage reporting and safe cleanup controls to the settings UI. Protect active stream transfers and isolate parallel test resources.
2026-07-24 12:58:57 +08:00
DrSmoothl 120dda1d9d fix(group-album): fetch all legacy album pages
Follow AlbumService cursors in get_group_album_list so the legacy array response contains every album instead of only the first page.

Reject missing or repeated cursors when the server reports more data, preventing silent truncation and pagination loops. Add regression coverage for multi-page aggregation and malformed cursors.

Fixes #272
2026-07-22 21:51:33 +08:00
DrSmoothl eed2e692b1 fix(onebot): expose robot status for group members
Fetch QQ's versioned robot UIN ranges, classify and persist member status, and surface is_robot from both group member actions.

Preserve unknown legacy cache entries and fail visibly when classification is unavailable.

Closes #265
2026-07-21 23:27:01 +08:00
DrSmoothl ff60221330 feat(onebot): support private window shake messages
Encode poke message segments as private window shake messages while keeping the dedicated send_poke action unchanged.

Restrict window shakes to a single ordinary private-chat segment. Reject group, temporary-session, mixed-message, and forwarded usage before identity lookup, media upload, or packet transmission.

Add full outbound request coverage, OneBot action regressions, and live private-chat verification for issue #259.

Closes #259
2026-07-21 19:28:17 +08:00
DrSmoothl feb7fcac0e feat(group-album): expose cover and upload metadata
Decode the verified album cover response field and expose normalized cover details and last-upload timestamps through both album list actions. Preserve the legacy numeric timestamp shape, retain string timestamps for the native response, return null when no cover exists, and avoid additional network requests.

Document the new output contracts in the OneBot and MCP catalogs. Add independent wire fixtures and action-level regression tests for the protocol mapping and public response shapes.

Refs #257
2026-07-20 23:37:41 +08:00
DrSmoothl 4aa2cd1693 fix(onebot): correct private message history (#256)
Use the C2C roam cursor and canonical NT sequence for bidirectional history. Persist direction-aware recall tombstones so recalled messages cannot reappear.
2026-07-20 22:25:13 +08:00
DrSmoothl 297f0428cc fix(core): correlate AI voice send receipts
Wait for the canonical self group-message event after AI voice synthesis instead of interpreting undocumented response fields as a message sequence.

Correlate receipts by exact media UUID, buffer response races, and claim each semantic message identity only once across concurrent calls and duplicate multi-process pushes. Reject missing identifiers, invalid sequences, bounded-buffer overflow, and receipt timeouts with explicit diagnostics.

Keep fetchAiVoice focused on returning the media node and add regression coverage for race ordering, unrelated events, identical concurrent audio, duplicate pushes, malformed receipts, and timeout cleanup.

Fixes #250
2026-07-20 14:02:48 +08:00
DrSmoothl 06c26dee87 fix(group-album): use native QQ album service
Replace the lossy Qzone album-list endpoint with the QQ NT AlbumService protobuf request. Preserve creator nicknames and expose native pagination for get_qun_album_list.
2026-07-20 13:03:16 +08:00
DrSmoothl 810d72fa04 feat(onebot): implement collection list retrieval
Replace the get_collection_list placeholder with authenticated, read-only collection retrieval through the existing bridge API.

Add strict binary envelope validation, bounded pagination, accurate category filtering, preserved 64-bit identifiers, and explicit ticket, transport, service, and malformed-response failures. Cap item counts, page traversal, response bytes, per-request waits, and the total operation time.

Expose the compatible response model through Core, OneBot, the SDK, and the generated MCP catalog. Cover protocol framing, cursor behavior, filtered hasMore semantics, cleanup failures, bridge ticket acquisition, and Action validation with regression tests.

Verified with the live test bot without changing native components or adding any collection write behavior.
2026-07-19 20:22:16 +08:00
DrSmoothl a9b8440731 fix(webui): disable custom pointer system by default
Default new and legacy-normalized appearance configs to native cursor and context-menu behavior while preserving explicit opt-in settings.
2026-07-19 19:33:26 +08:00
DrSmoothl 168f414cd9 feat(core): retain online device snapshots
Store the latest online-device snapshot for each Bridge lifecycle and expose it through the bridge contract as an immutable, owned value.

Distinguish a snapshot that has not yet been observed from a valid empty snapshot, replace state atomically on each QQ update, clear it during disposal, and cover lifecycle, immutability, and cleanup behavior with focused tests.
2026-07-19 19:20:14 +08:00
DrSmoothl e6a69b05a7 feat(onebot): expose group folder upload metadata
Decode the folder modifier metadata returned by group file listings and project it as last upload time, uploader ID, and uploader name for both folder listing actions.

Regenerate the MCP catalog and add protocol, bridge, OneBot projection, and action schema coverage for the new fields.

Closes #248
2026-07-19 18:34:53 +08:00
DrSmoothl 78101b3512 fix(core): send group album pagination cursors
Encode the opaque media-list cursor in the protobuf page-info field while leaving the reserved field empty. This restores subsequent-page requests without changing the OneBot action or response shape.

Add an independent wire oracle so future protocol definition drift cannot make the encoder regression test pass against itself.

Fixes #245
2026-07-19 16:28:01 +08:00
DrSmoothl d40c803ed9 feat(webui): add adaptive pointer interactions
Introduce a CSS-driven adaptive cursor that morphs for controls, text editing, dragging, resizing, busy states, and other native pointer semantics on desktop devices.

Add a themed context menu for editing, selections, links, images, and page navigation while preserving explicit native-menu escape paths. Store a default-on interaction preference through the normalized appearance model and cover its migration and opt-out behavior.
2026-07-18 23:38:43 +08:00
DrSmoothl afa4ccc5e0 feat(core): add bidirectional history pagination
Walk bounded QQ history windows in either direction while keeping all returned messages in chronological order.

Resolve short-capped forward ranges without skipping messages nearest the anchor, share the existing request throttle across group and private history, and surface incomplete fetches instead of returning silent partial results.

Refs #229
2026-07-17 17:45:03 +08:00
DrSmoothl 6492500158 fix(core): handle omitted group album success codes
Treat an absent media-list return code as the protobuf zero default while preserving failures for explicit non-zero codes.

Add a regression test that exercises the encoded response path with media data and no status field.

Refs #234
2026-07-15 17:30:29 +08:00
DrSmoothl da26d6796f feat(core): aggregate receive health by account
Track receive health for every process attached to an account while treating unarmed monitoring as compatible rather than degraded.

Report the account as healthy while any attached process remains healthy, and mark it degraded only after every attached process has been confirmed stale. Keep health ownership synchronized with process attach, migration, and detach transitions.

Fail fast when process ownership and health state diverge instead of silently presenting a healthy status. Add multi-process regression coverage for partial degradation, full degradation, and recovery.

Refs #233.
2026-07-15 16:47:26 +08:00
DrSmoothl bd9236e3fa feat(webui): expose transactional backup restore
Replace route-local restore writes with the core transaction and map preflight, rollback, and post-commit cleanup failures to precise HTTP responses. Treat only ENOENT as a missing export file and return transaction, restored, skipped, migrated, and restart facts.

Update the settings panel to describe the full sensitive configuration group, avoid restart guidance for empty plans, and reload settings after both successful and failed imports so the UI reflects committed disk state. Add HTTP regression coverage for export and restore error semantics.
2026-07-15 16:12:51 +08:00
DrSmoothl ccbee78cc7 feat(core): execute config restores as a transaction
Move restore execution into a dedicated module with explicit preflight, snapshot, stage, commit, rollback, and cleanup phases. Keep live files untouched until staging completes, roll back partial commits, and retain the transaction directory when rollback or cleanup cannot finish.

Report the transaction ID, active phase, failed files, commit state, rollback result, and recovery path without logging configuration contents. Cover every filesystem boundary with a focused fault matrix, including unreadable current files and cleanup failures.
2026-07-15 16:12:03 +08:00
DrSmoothl 2fea3ca4d9 feat(core): validate backup restores before mutation
Route selected backup entries through owner-owned config parsers before any filesystem write. Reject unsupported paths, mismatched encodings, malformed base64, lossy normalization, invalid effective overlays, and decoded payloads larger than 32 MiB.

Treat WebUI state, private keys, and every OneBot config as a single sensitive group. Skip unselected sensitive entries without inspecting their contents, preserve recognized migrations, and assign restrictive modes to credential files.
2026-07-15 16:11:44 +08:00
DrSmoothl 51eb1f733d feat(group-notice): support advanced announcement controls
Route regular and new-member announcements through their correct web endpoints. Validate option conflicts, preserve existing defaults, merge returned notice collections, and surface transport and upload failures.
2026-07-14 03:39:11 +08:00
DrSmoothl 74939da3d7 feat(webui): support environment agreement consent
Allow unattended deployments to accept the EULA and Privacy Notice through SNOWLUMA_ACCEPT_EULA and SNOWLUMA_ACCEPT_PRIVACY.

Require both values, reject invalid configuration, keep environment consent non-persistent, and log whether acceptance is complete or partial.

Document the deployment contract and add regression coverage for parsing, persistence isolation, and stored-consent compatibility.
2026-07-13 23:15:10 +08:00
DrSmoothl 03aec3b052 fix(core): verify conversation read updates
Replace message-header sequence forwarding with a server-guided read flow for group and private conversations.

Batch read reports conservatively, validate per-conversation results and cursor advancement, and fail with actionable errors when the server does not apply an update.

Add regression coverage for mixed batches, pagination, already-current sessions, malformed responses, and private sequence-domain mismatches.
2026-07-13 23:01:39 +08:00
DrSmoothl 8cd7d51d80 fix(protocol): preserve friend category metadata 2026-07-13 18:51:11 +08:00
DrSmoothl 852004291b feat(onebot): reconcile and drain network adapters
Serialize desired network plans, isolate per-adapter apply failures, restore prior bindings when possible, and report saved versus applied state. Quiesce Action and event ingress, await in-flight dispatches and transport closes, retain failed generations for retry, and propagate shutdown failures.
2026-07-10 13:49:17 +08:00
DrSmoothl 01688c7567 fix(protocol): enforce message element contracts end to end
Replace the open message bag with a validated discriminated union and preflight complete messages before uploads or sends. Return BAD_REQUEST for invalid or unsendable segments instead of dropping fields, sending partial content, or silently changing private messages.
2026-07-10 13:47:06 +08:00
DrSmoothl 9f7f34cd8f fix(core): bound merged-forward decompression
Cap long-message gunzip output at 32 MiB and fail before an oversized QQ response can exhaust process memory. Include the resource id, compressed size, and configured limit in observable errors.
2026-07-10 13:42:34 +08:00
DrSmoothl 369a82b5e4 fix(core): enforce bridge PID ownership 2026-07-10 03:05:50 +08:00
DrSmoothl 35958a7fc2 fix(onebot): use canonical group request flags 2026-07-10 02:42:07 +08:00
DrSmoothl 3c73d1d5b0 feat(onebot): reply into group temp sessions (临时会话) (#212)
send_private_msg / send_msg can now reply to a group temp-session message
by passing the source group_id. Inbound temp messages surface their
source group on sender.group_id; a reply is only made into a temp session
the bot has an inbound record of. Group temp replies route through
RoutingHead.grpTmp (field 3).
2026-07-10 02:29:18 +08:00
DrSmoothl 8fbcbd29ff feat(onebot): honour a custom per-node time in merged forward (#209)
Merged-forward nodes always stamped the current time. A custom forward can now
set each node's displayed timestamp via the OneBot `data.time` field (unix
seconds), matching the field the wire already carries per node.

parseForwardNodes reads `data.time` on custom/fake nodes and threads it onto the
node payload (the `time?` field already existed for the receive side);
buildForwardPushBody uses it for `contentHead.timestamp`, falling back to now
when absent. The value is validated to a plausible unix-seconds range — the wire
field is uint32, so a millisecond or out-of-range input is rejected (would
overflow) and defaults to now rather than corrupting the timestamp. The
message_id-reference branch (time from the quoted message) and the c2c-file
expireTime (real now) are unchanged. Nested inner nodes honour their own time.
2026-07-07 21:35:33 +08:00
DrSmoothl d9dfe513ee feat(onebot): report forced offline as notice/bot_offline
Register a handler for the StatusService.KickNT push (QQ NT's unified
forced-offline notification — kick / login-elsewhere / risk-control),
decode KickNTResponse and emit bot_offline {user_id, tag, message},
matching NapCat. Command + field layout (f4=tips_title, f3=tips_content)
RE-confirmed against wrapper.linux.node + Lagrange; not yet live-captured.
2026-07-07 15:25:35 +08:00
DrSmoothl 5f90cc9b6e fix(forward): preserve group merged-forward sender nickname (#201)
get_forward_msg returned empty sender.nickname for group merged-forward nodes.
The reporter blamed a mis-parsed group_id + a failing member-list enrichment
(0xfe7_3 0x899_AUTHORITY_FAIL), but on-target capture shows a mislabeled proto
field: the group response-head's sender display name lives in field 4, which we
had labeled `groupName`. It's populated on live pushes ("星屿" / the group card
"墨梓柒111") AND on merged-forward nodes (per-node sender name), while field 2
(`memberName`) is empty on live/forward and only set by the group-history fetch,
and the real group name is field 7. Lagrange labels field 4 `MemberName`.

Relabel ResponseGrp: field 4 `memberCard` (sender display name = card||nick),
field 7 `groupName` (the real group name); keep field 2 `memberName` for the
group-history slot. The group decoder now resolves the sender name by priority:
field-2 name → local member cache (clean nick/card split) → field-4 memberCard.
The last step is what lets a forward node from a group the bot isn't in keep its
per-node sender name with no member-list lookup, so the forward-specific fallback
and the AUTHORITY_FAIL enrichment path are no longer needed for the common case.

Verified on-target across scenarios: live message senderNick unchanged; a plain
forward, a forward from a never-joined group (placeholder uin 1094950020, four
distinct senders 金橘雪梨/Crel/503/Xiing0), and a nested forward all keep their
nicknames; no member-list call fires. group_id stays the payload's value.
2026-07-05 14:20:36 +08:00
DrSmoothl a4ab4e92b5 fix(forward): preserve group merged-forward sender nickname (#201)
get_forward_msg returned empty sender.nickname/card for group merged-forward
nodes. The reporter blamed a mis-parsed group_id + a failing member-list
enrichment (0xfe7_3 0x899_AUTHORITY_FAIL on a placeholder source group), but
on-target capture shows the sender display name IS in the payload: a
merged-forward node leaves `grp.memberName` null and instead carries the sender
name in `grp.groupName` (field 4) — QQ repurposes the group-name slot per node.
parseMsgPush only reads memberName (correct for live messages), so the name was
dropped and the code fell through to the member-list enrichment, which can't
resolve a group the bot isn't in.

Fix: in the forward-node decode, fall back to `grp.groupName` for the sender
nickname (scoped to the forward path — live-message decoding is untouched). This
also makes the AUTHORITY_FAIL enrichment fetch unnecessary for the common case.
Verified on a real forward (fromUin 1787882683 ↔ grp.groupName "墨梓柒"):
nickname now populated, no member-list call. group_id stays the payload's value
(genuinely a placeholder/source group, not a mis-parse).
2026-07-05 04:30:44 +08:00
DrSmoothl 1b968b9126 feat(file): stream group + offline file uploads from disk (phase 5)
Wire the streaming primitives into the group-file and private/offline-file
upload paths. Both now stage the source onto a local disk path
(stageSourceToDisk — hardlink/download), hash it in one streaming pass
(hashFileStreaming; the offline-file md510MCheckSum comes from the same pass via
headLimit=MD5_HEAD_LIMIT), and PUT the file through a FileChunkSource — so a file
up to the 4 GiB protocol ceiling never holds more than one 1 MiB chunk in RAM.
The old readFileSync/loadBinarySource + computeHashes + md5First10MB buffered
path is removed.

The highway session is resolved before the file handle is opened (the handle's
owner, uploadHighwayHttp, must be the next call so its finally-close always
runs); a size+mtime guard re-checks the staged file before the PUT so a source
mutated mid-send fails cleanly; and the staged temp is released in a finally on
every exit. The OIDB preflight fields, the remembered-upload cache, the ext
blobs, and the publish steps (group 0x6D9_4 / private sendC2cFile) are byte-for-
byte unchanged. Tests re-mock at the stage/hash seams and assert the streamed
FileChunkSource + cleanup for both group and c2c uploads.
2026-07-05 03:42:16 +08:00
DrSmoothl 5324e2f014 refactor(highway): introduce ChunkSource for uploadHighwayHttp (phase 1)
Prep for streaming large media uploads from disk instead of buffering the
whole file in RAM. Add a `ChunkSource` abstraction — `BufferChunkSource`
(in-memory, byte-for-byte the old path) and `FileChunkSource` (disk-backed,
reads exact-length chunks via a FileHandle, loops on short reads, throws on
unexpected EOF) — and change `uploadHighwayHttp` to consume a `ChunkSource`
instead of a `Uint8Array`. The uploader now owns the source and closes it once
in `finally` (best-effort; never masks a primary upload error).

Pure structural refactor: no streaming is wired yet. All five call sites
(pipeline runPuts, group + private file upload, personal + group avatar) wrap
their bytes in `BufferChunkSource`, so behavior is unchanged. Adds a
byte-oracle test proving FileChunkSource ≡ BufferChunkSource across block
boundaries, plus short-read/EOF/empty-input coverage.
2026-07-05 02:29:13 +08:00
Airline233andCopilot Autofix powered by AI d3eb3bae14 feat(qzone,onebot): add set_qzone_ban action for qzone blacklist management (#193)
* feat(onebot,qzone): add set_qzone_ban action for qzone blacklist management

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-07-04 14:32:40 +08:00
DrSmoothl 07c08ed74d feat(onebot): enrich group/member info fields (#197)
Round out the OneBot v11 group-profile fields the issue asked for.

Group (get_group_info / get_group_list, inherited by get_group_info_ex /
get_group_detail_info):
- group_create_time + group_memo come free from the 0xFE5_2 list
  (createdTime / announcement), verified live (createdTime=1729505343,
  announcement populated).
- group_level lives only in the 0x88D_0 detail; get_group_info fetches it
  (memoized 5min) so a joined group doesn't hit the detail every call.
  get_group_list leaves it 0 — a per-group detail fetch across the whole
  list would be far too costly.

Member (get_group_member_info / get_group_member_list):
- Add area / unfriendly / title_expire_time / card_changeable. QQ NT does
  not expose these, so they're fixed placeholders ('' / false / 0 / true),
  matching go-cqhttp / NapCat. sex/age stay unknown/0 (real values need a
  per-member profile fetch — out of scope here).

typecheck 12 packages; onebot 523 / core 472 green.
2026-07-04 13:04:32 +08:00
DrSmoothl c027161a64 fix(protocol): get_group_file_system_info returns real counts + space (#196)
file_count 恒为 0(且 used_space/limit_count/total_space 是占位/写死值)。根因:
0x6D8 view 命令分三个 subcommand(1=List, 2=Count, 3=Space),但 getCount 错发到
**subCommand 3(Space)** 且 busId=0,并从 pb<1>/pb<2> 读计数——服务端根本没返回
Count 块,于是恒 0。

真机 RE(bot 在测试群传/删文件核对):
- Count 走 **0x6D8_2 + busId=6**,响应 Count 块里 fileCount=**field 4**、maxCount(文件
  数上限,如 1500)=**field 6**(旧 pb<1>/pb<2> 全落空)。
- Space 走 **0x6D8_3**,响应 Space 块 totalSpace=**field 4**、usedSpace=**field 5**(64 位)。
- 实测:fileCount=4、limitCount=1500、usedSpace=20103729、totalSpace=10737418240。

修复:改 GetGroupFileCount 到 subCommand 2 + busId 6 + 正确 tag;新增 GetGroupFileSpace
(0x6D8_3);action 并发查两者,四个字段全返回**服务端实际值**(优于 NapCat 的写死占位)。
含 count/space 编解码回归测试。catalog regen。

typecheck 12 包;protocol 591 / onebot 521 / core 472 全绿。
2026-07-04 01:59:52 +08:00
DrSmoothl 95b5878456 feat(onebot): return new folder info from create_group_file_folder (#195)
create_group_file_folder 之前只回 data:null,拿不到新建文件夹的 folderId。现对齐
NapCat 返回结构,data 带回文件夹信息:
  { result: { retCode, retMsg }, groupItem: { folderInfo: { folderId, folderName,
    folderPath, createTime, modifyTime, createUin, modifyUin } } }

- 0x6D7_0 创建响应本就在 field 4 携带 folderInfo,SnowLuma 旧 proto 没解(只读
  retcode/retMsg/clientWording)。补上 OidbGroupFileFolderInfoResp 并让 create 的
  deserialize / bridge / action 一路把它带出来。
- 真机验证(bot 在测试群建夹→读回 folderId→删除清理):确认 folderInfo 存在,且
  **modifyUin 在 field 9 而非 Lagrange proto 标注的 field 7**——按真机 wire 修正。
- 新增两个解码回归测试(带 folderInfo / 缺 folderInfo 兜底)。catalog regen。

typecheck 12 包;protocol 587 / onebot 521 / core 472 全绿。
2026-07-04 01:25:14 +08:00
DrSmoothl 7744e24af2 fix(protocol): make set_group_search actually apply search flags (#191)
旧实现走 OIDB 0x89a_0 但 settings 发空字节 → 服务端返 ok 却 no-op;action 也只收
group_id,没有设置搜索方式的参数(报告属实)。

真机 RE 定稿(tempserver,bot 为管理员的实群逐字段扫描 + GET 读回):
- 修改命令 = 0x89a_0(全量抓包确认,与 MuteAll 同命令,靠 body 形状区分)。结构
  = {1:groupUin, 2: 只含被改字段的 GroupDetailInfo modify 子消息}。这是与 0x88D_0
  群详情 GET **不同的消息域**(mute/shutUpTime 在此=tag17,在 GET 里却是字符串),
  所以标签不能照搬 GET。
- 在 modify 子消息里逐 tag 试写、经 0x88D_0 GET 读回效果,定位:
  noFingerOpen(关键词/群指纹搜索)=tag 35,noCodeFingerOpen(群号搜索/总开关)=tag 36;
  再对照客户端「被搜索方式」三选下拉(私密/群号/群号+关键词)核实语义与 0/1 取值。
- proto-defs:settings 改为 Oidb0x89a_0SearchSettings 子消息,两 flag 用 pb_optional
  (显式存在)——否则 proto3 丢 0 值,导致关闭(=0)被静默忽略。undefined 仍省略。
- set-search/bridge/action:透传 no_finger_open / no_code_finger_open;只下发提供的
  字段(同 NapCat filter 机制、与 modify-group-ext-info 一致)。catalog regen。
- 编码测试锁定:0 值必发 tag 35/36、未提供则省略、命令为 0x89a_0。

typecheck 12 包干净;protocol 585 / onebot 521 / core 472 全绿。
2026-07-03 17:37:55 +08:00
Airline233 884db940df feat(qzone): add set_qzone_msg_right to change a feed's visibility (#186)
* feat(qzone): add set_qzone_msg_right to change a feed's visibility

Add updateQzoneMsgRight in the protocol layer, porting php-qzone's
updateRight: fetch the feed via emotion_cgi_msgdetail_v6, rebuild the
full publish-shaped payload (richval/pic_bo/con), then override
ugc_right/allow_uins and POST to emotion_cgi_update. Expose it through
QzoneApi.updateRight and the OneBot set_qzone_msg_right action, with the
same ugc_right/target_uins validation as send_qzone_msg. Covered by
protocol, core and onebot tests.

* fix(qzone): make qzoneParse more stable and fixed a test example
2026-07-02 22:38:05 +08:00