Commit Graph
7 Commits
Author SHA1 Message Date
DrSmoothl 7c0519f75f lint 2026-10-12 15:43:34 +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 4ba2b27398 fix(onebot): keep synthetic sequences out of history
Distinguish QQ-authoritative message sequences from local message IDs so group files and reply placeholders cannot become history anchors or be reused by protocol actions.

Filter QQ null roam records and migrate previously stored synthetic rows.

Fixes #254
2026-07-20 15:33:28 +08:00
DrSmoothl fadc7ce316 feat(onebot): expose bidirectional message history
Add reverse_order to group and private history actions, preserve latest-page behavior without an anchor, and keep local fallback results chronologically ordered.

Key self-sent private messages and reply targets by the conversation peer, reject cross-conversation anchors, and include request context when a server fetch falls back to local history.

Refs #229
2026-07-17 17:45:30 +08:00
DrSmoothl 5e73d69663 fix(test): add groupName to GroupMessage test fixtures (#212 CI)
core's typecheck covers its own tests (protocol/onebot typecheck src
only), so the newly-required GroupMessage.groupName field failed the
Dev Build typecheck on test fixtures that construct group_message
events. Add groupName to every such fixture across core/onebot/protocol
tests.
2026-07-09 19:18:09 +08:00
DrSmoothl e160837f8b feat(onebot): tiered reply backfill + quoted-file recovery for get_msg (#128)
Harvests the sound ideas from PR #128 while KEEPING origSeqs[0] as the c2c
reply sequence (on-target capture in #114/#124 proved origSeqs[0] == the quoted
message's head.sequence; pbReserve.friendSequence is a small unrelated counter
that makes reply.id miss). The PR's friendSequence override is intentionally
NOT taken.

- rich-body-decoder: enrich the reply element with replySenderUin/replyTime and
  the quoted message's own decoded elements (SrcMsg.elems, field 5); recover a
  c2c quoted FILE from sourceMsg (field 9 -> RichText.notOnlineFile) when elems
  carried none, so a quoted file survives into get_msg (#124).
- backfillReplyTarget: tiered fallback — Tier 0 local store, Tier 1 server fetch
  (correct seq = origSeqs[0]), Tier 2 reconstruct from the embedded quoted
  elements (no round-trip), Tier 3 minimal '[引用消息]' placeholder so get_msg
  never returns 'message not found'.
- to-segment: per-element try/catch (logged, not silent) so one bad element
  doesn't drop the whole message.
- actions/message: log get_msg misses.
- tests: fix request-actions getGroupInviteCardSequence mock (gap from #125);
  cover backfill Tier 2 (reconstruct) + Tier 3 (placeholder); flip the stale
  c2c reply test to assert origSeqs[0] (was asserting the disproven
  friendSequence).

Validated on-target (Docker): get_msg on group reply, private text reply, and a
private quoted FILE all return correct content (file with name/size/id); full
onebot + protocol suites green.
2026-06-22 21:25:05 +08:00
DrSmoothl 28633f3c62 feat(onebot): back-fill a quoted message from the server when not stored
When an incoming reply quotes a message SnowLuma's store doesn't have (e.g. one
from before it was running, or never observed), the receive pipeline now fetches
just that message from the server and persists it before dispatch — so a
consumer's get_msg on the quote resolves instead of returning "message not
found". Works for both group and private (c2c).

- core: MessageApi.getGroupMessageBySeq / getC2cMessageBySeq — fetch a single
  message over a 1-wide [seq,seq] range, through the shared history throttle
  gate (same rate-limit as the bulk history APIs — no flood / kick risk).
- onebot: backfillReplyTarget — on a group/friend reply whose target isn't in
  the store, fetch (group SsoGetGroupMsg / c2c SsoGetC2cMsg, uid resolved for
  c2c) and persist under the EXACT id the reply resolves to, so get_msg hits
  regardless of who sent the quoted message (a bot self-sent c2c message
  converts with user_id=self but is keyed under the peer session). Awaited
  before dispatch so the consumer sees it; best-effort — a back-fill failure
  never blocks delivery of the live message.
- tests: gating (already-stored / no-reply / nothing-on-server) + keying
  (group, c2c, c2c self-sent under peer session).

Only fires on a store miss, so the common path (no reply, or quote already
stored) stays zero-cost.
2026-06-15 13:53:04 +08:00