fix(onebot): allow negative message_id in get_{group,friend}_msg_history
message_id is a signed int32 hash (hashMessageIdInt32) and is frequently
NEGATIVE, but both history actions declared it as `f.int({min:0}).default(0)`
— so a real anchor like message_id=-497311472 was rejected at param
validation (retcode 1400, 0ms) before run() fired, and the server-side
history fetch never happened (the client then reports "未找到足够的群聊记录").
Drop the min:0 bound → `f.int().default(0)`: negatives pass, absent/present-0
still mean "fetch latest", count stays ≥0. Matches every other action, which
uses f.messageId() for signed message IDs.
Regression tests: negative group/friend anchors now reach the handler;
absent message_id still defaults to 0.
This commit is contained in:
@@ -219,8 +219,12 @@ export const actions = [
|
||||
summary: '获取群消息历史',
|
||||
readOnly: true,
|
||||
params: {
|
||||
// 原实现用 `asNumber(message_id) || 0`,present 0 也映射为 0。
|
||||
message_id: f.int({ min: 0 }).default(0),
|
||||
// message_id is a signed int32 hash (hashMessageIdInt32) and is
|
||||
// frequently NEGATIVE — a `{min:0}` validator rejects a real anchor at
|
||||
// param-validation time (retcode 1400) before run() ever fires. Use a
|
||||
// plain signed int; `.default(0)` keeps absent/present-0 → "fetch latest"
|
||||
// (matches the original `asNumber(message_id) || 0`). `count` stays ≥0.
|
||||
message_id: f.int().default(0),
|
||||
count: f.int({ min: 0 }).default(20),
|
||||
},
|
||||
run: async (p, ctx) => {
|
||||
@@ -235,7 +239,8 @@ export const actions = [
|
||||
readOnly: true,
|
||||
params: {
|
||||
user_id: f.uint(),
|
||||
message_id: f.int({ min: 0 }).default(0),
|
||||
// Signed int32 hash, frequently negative — see get_group_msg_history.
|
||||
message_id: f.int().default(0),
|
||||
count: f.int({ min: 0 }).default(20),
|
||||
},
|
||||
run: async (p, ctx) => {
|
||||
|
||||
@@ -212,6 +212,42 @@ describe('extended-actions / bot_exit', () => {
|
||||
});
|
||||
});
|
||||
|
||||
// ─── History: message_id is a signed int32 hash and is frequently NEGATIVE ───
|
||||
// Regression: get_{group,friend}_msg_history declared message_id with a
|
||||
// `{min:0}` validator, so a real (negative) anchor message_id was rejected at
|
||||
// param-validation time (retcode 1400) before the handler ran — see the
|
||||
// `message_id=-497311472 ⇒ failed (0ms)` report.
|
||||
|
||||
describe('extended-actions / history accepts negative message_id', () => {
|
||||
it('get_group_msg_history forwards a negative anchor to the handler', async () => {
|
||||
const getGroupMsgHistory = vi.fn(async () => [{ message_id: -1, message_type: 'group' }]);
|
||||
const ctx = fakeCtx(fakeBridge(), { getGroupMsgHistory } as any);
|
||||
const res = await makeHandler(ctx).handle('get_group_msg_history', {
|
||||
group_id: 100, message_id: -497311472, count: 100,
|
||||
});
|
||||
expect(res).toMatchObject({ status: 'ok', retcode: 0 });
|
||||
expect(getGroupMsgHistory).toHaveBeenCalledWith(100, -497311472, 100);
|
||||
});
|
||||
|
||||
it('get_friend_msg_history forwards a negative anchor to the handler', async () => {
|
||||
const getFriendMsgHistory = vi.fn(async () => [{ message_id: -1, message_type: 'private' }]);
|
||||
const ctx = fakeCtx(fakeBridge(), { getFriendMsgHistory } as any);
|
||||
const res = await makeHandler(ctx).handle('get_friend_msg_history', {
|
||||
user_id: 12345, message_id: -670862300, count: 100,
|
||||
});
|
||||
expect(res).toMatchObject({ status: 'ok', retcode: 0 });
|
||||
expect(getFriendMsgHistory).toHaveBeenCalledWith(12345, -670862300, 100);
|
||||
});
|
||||
|
||||
it('still defaults an absent message_id to 0 (fetch-latest semantics)', async () => {
|
||||
const getGroupMsgHistory = vi.fn(async () => []);
|
||||
const ctx = fakeCtx(fakeBridge(), { getGroupMsgHistory } as any);
|
||||
const res = await makeHandler(ctx).handle('get_group_msg_history', { group_id: 100 });
|
||||
expect(res).toMatchObject({ status: 'ok', retcode: 0 });
|
||||
expect(getGroupMsgHistory).toHaveBeenCalledWith(100, 0, 20);
|
||||
});
|
||||
});
|
||||
|
||||
// ─── Tier 1: nc_get_packet_status / nc_get_rkey ───
|
||||
|
||||
describe('extended-actions / nc_get_packet_status', () => {
|
||||
|
||||
Reference in New Issue
Block a user