Commit Graph
13 Commits
Author SHA1 Message Date
DrSmoothl 056188d63d chore: resolve async SQLite merge conflicts
Integrate the current development branch, preserve the album comment fixes, and align the changes with repository formatting and dependency tooling.
2026-10-13 09:55:16 +08:00
手瓜一十雪 e699351f90 feat: adopt async SQLite and improve messaging and runtime diagnostics 2026-10-12 15:44:55 +08:00
DrSmoothl 7c0519f75f lint 2026-10-12 15:43:34 +08:00
DrSmoothl 063ede4c62 fix(onebot): preserve custom forward metadata
Keep custom titles and previews available when reading uploaded forwards,
including nested messages and refreshed sender names.

Reject malformed preview metadata before processing the request.

Refs #493
2026-10-04 16:03:32 +08:00
under-the-ocean 89275ae279 fix(onebot): support custom nested forward previews (#493)
Accept custom preview metadata on nested forward messages and carry it through card creation.

Refs #493
2026-10-04 15:44:06 +08:00
DrSmoothl 99bcfca15c fix(onebot): preserve historical media independently of cache limits
Preserve message history and the media information needed for reliable
forwarding. Retain available older data during upgrades and report storage
failures explicitly.

Fixes #462
2026-10-04 14:00:30 +08:00
DrSmoothl 201d10c534 fix(onebot): rebuild merged forwards for the target chat
Resending another chat's merged-forward card leaves an unopenable
bubble. Fetch the inner tree and upload it for the destination.

Fixes #437
2026-09-13 21:14:46 +08:00
DrSmoothl 6da412ab96 fix(onebot): keep real sender nick on forward nodes that cite a message id
Empty group cards were treated as a name, so get_forward_msg showed the QQ number instead of the stored nickname (#372).
2026-08-16 13:11:53 +08:00
DrSmoothl 27c527976b fix(onebot): reject ambiguous video message combinations
Prevent ordinary messages and forwarded nodes from combining video content with visible sibling segments or additional videos. Invalid combinations now fail before parsing side effects, media work, or bridge sends, while exact empty text placeholders remain compatible with a single video.

Cover group, private, temporary-session, CQ string, nested forward, cached forward, and protocol-builder paths. Preserve the existing standalone window-shake behavior and keep valid single-video messages unchanged.
2026-08-05 23:55:55 +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 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 b6107e38d8 fix(onebot): default forward node sender to self when user_id is 0/absent
A fake forward node (send_group_forward_msg / send_private_forward_msg) whose
data.user_id was "0" or omitted got rejected with "forward node user_id/uin is
required", even though the protocol端 is logged in and the core forward builder
(bridge/apis/forward.ts) already defaults a zero sender to the bot's own uin.
Upstream frameworks (AstrBot, etc.) don't manage QQ uins and legitimately send
user_id "0"; NapCat and LLBot accept it. parseForwardNodes now falls back to
ref.selfId, keeping the throw only for the not-logged-in case (selfId 0).
Verified on-target (#203).
2026-07-05 23:00:13 +08:00
DrSmoothl 9a30df9907 refactor(onebot): extract OneBot protocol translation into @snowluma/onebot
Phase 3 of the 4-package split (RoadMap #3). Moves the entire
`packages/core/src/onebot/` subtree (43 source files + 20 test files
spanning network adapters, action handlers, event converters, message
parser, message store, media store, instance + manager) into the new
`@snowluma/onebot` workspace package. The remaining `@snowluma/core`
now hosts only the api-layer (Bridge class + 13 Api classes), the
hook tooling, the WebUI server, and the runnable `index.ts`.

Why
---
- The OneBot adapter is the public-facing OneBot11 protocol surface;
  it has its own version cadence and its own consumers (third-party
  bots talking OneBot WS / HTTP). Splitting it lets that cadence move
  independently of the Api-on-ctx layer.
- The two were sharing the `packages/core/` build pipeline only
  because they happened to live in the same directory. Nothing in
  the api-layer reaches into OneBot internals.
- Mirrors NapCat / Lagrange.OneBot's repo split (their OneBot adapter
  is a separate assembly from the Core protocol library).

Layout
------
Moved via `git mv` (history preserved):
  packages/core/src/onebot/*  → @snowluma/onebot/src/<x>
  packages/core/tests/onebot/* (6 files)   → @snowluma/onebot/tests/
  packages/core/tests/{message-parser,message-store,event-pipeline,
    media-store,media-url-resolver,event-converter,
    http-server-hot-reload,http-server-content-type,
    api-handler-logging,message-id,group-msg-emoji-like,
    config,media-indexer,network-manager}.test.ts (14 files)
                                              → @snowluma/onebot/tests/

What stays in @snowluma/core
----------------------------
- `bridge/{bridge,bridge-interface,bridge-context,manager}.ts`
- `bridge/apis/*` (the 13 typed Api classes)
- `hook/*` (debugger/injector — tooling for the core protocol layer)
- `webui/*` (admin UI server — application wiring, not the OneBot
  adapter itself)
- `index.ts` (application entry that wires BridgeManager +
  OneBotManager + HookManager + WebUI together)

Changes
-------
- New package `packages/onebot/` (package.json with subpath exports
  mirroring legacy `core/src/onebot/<x>` 1:1, tsconfig.json,
  vitest.config.ts with `SNOWLUMA_LOG_LEVEL=debug` env so the action-
  dispatch logging tests see debug-level subscribers — copied verbatim
  from core's vitest.config.ts).
- @snowluma/core grows new subpath exports for the api-layer files
  OneBot's type-only imports need: `./bridge`, `./bridge-interface`,
  `./bridge-context`, `./manager`, `./apis`.
- `@snowluma/onebot` depends on `@snowluma/bridge`, `@snowluma/common`,
  `@snowluma/core`, `@snowluma/proto-defs`, `@snowluma/proton`,
  `@snowluma/websocket`.
- `@snowluma/core` depends on `@snowluma/onebot` (for index.ts +
  webui/server.ts wiring).
- 100+ import sites rewritten via sed:
  * OneBot → core: `'../bridge/bridge'` → `'@snowluma/core/bridge'`,
    `'../bridge/manager'` → `'@snowluma/core/manager'`,
    `'../bridge/bridge-interface'` → `'@snowluma/core/bridge-interface'`,
    `'@/bridge/bridge'` (vite path alias) → `'@snowluma/core/bridge'`.
  * Core → OneBot: `'./onebot/manager'` → `'@snowluma/onebot/manager'`,
    `'../onebot/config'` → `'@snowluma/onebot/config'`, etc.
  * Test relative paths: `'../../src/onebot/<x>'` → `'../src/<x>'`
    after the test file move (one level shallower).
- New `packages/onebot/src/env.d.ts` declaring `__APP_VERSION__` and
  `__BUILD_WEBUI__` (the vite-injected globals `info.ts` reads).

Workspace cycle
---------------
core ↔ onebot is allowed by pnpm workspaces. The runtime direction
is one-way: core → onebot (index.ts constructs OneBotManager,
webui/server reads OneBot config). OneBot only reaches into core for
TYPES (Bridge, BridgeInterface, BridgeManager, ClientKeyInfo,
DownloadRKeyInfo); those imports use `import type` so they compile
out at runtime and don't introduce a real cycle.

Verification
------------
- Full workspace `pnpm -r typecheck`: all 11 projects clean.
- `@snowluma/core` test suite: 302/302 pass (33 test files).
- `@snowluma/onebot` test suite: 250/250 pass (20 test files;
  pre-existing `network-manager.test.ts` native-addon failure
  unchanged — same baseline as before the split).
- Combined: 552/552 — identical pass count to the pre-Phase-3
  baseline.
- Vite build with stubbed native binary: clean, 2.84 MB bundle /
  224 KB gzip (identical envelope).
2026-05-21 08:52:00 +08:00