fix(protocol): report rejected card deliveries
Surface delivery failures instead of reporting success for rejected image and text cards. Reject responses without a delivery result. Fixes #611
This commit is contained in:
@@ -8,7 +8,7 @@
|
||||
// reads {1:bussness_error_code, 5:ark_json}.
|
||||
// Both return a server-built ark JSON string (the share card payload).
|
||||
|
||||
import type { pb, pb_optional, uint_32 } from '@snowluma/proton';
|
||||
import type { pb, pb_optional, pb_repeated, uint_32 } from '@snowluma/proton';
|
||||
|
||||
export interface OidbBuddyRecommendArkReq {
|
||||
uin?: pb<1, uint_32>;
|
||||
@@ -67,4 +67,11 @@ export interface Oidb0xdc2_34Req {
|
||||
meta?: pb<2, Oidb0xdc2Meta>;
|
||||
}
|
||||
|
||||
export interface Oidb0xdc2_34Resp {}
|
||||
export interface Oidb0xdc2CardResult {
|
||||
errorCode?: pb<4, uint_32>;
|
||||
errorMessage?: pb<5, string>;
|
||||
}
|
||||
|
||||
export interface Oidb0xdc2_34Resp {
|
||||
results?: pb_repeated<1, Oidb0xdc2CardResult>;
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ import type {
|
||||
Oidb0xdc2_34Req,
|
||||
Oidb0xdc2_34Resp,
|
||||
} from '@snowluma/proto-defs/oidb-actions/contact-ark';
|
||||
import { invokeOidb, type OidbSender } from '../../oidb-service';
|
||||
import { invokeOidb, OidbError, type OidbSender } from '../../oidb-service';
|
||||
|
||||
const TUWEN_ARK_APPID = 100446242;
|
||||
|
||||
@@ -54,7 +54,22 @@ export namespace SendTuwenArk {
|
||||
},
|
||||
});
|
||||
|
||||
export const deserialize = (_ctx: Deps, _body: Oidb0xdc2_34Resp): void => undefined;
|
||||
export const deserialize = (_ctx: Deps, body: Oidb0xdc2_34Resp): void => {
|
||||
if (!body.results?.length) {
|
||||
throw new Error('send_tuwen_ark response has no delivery result');
|
||||
}
|
||||
|
||||
for (const result of body.results) {
|
||||
if (result.errorCode) {
|
||||
throw new OidbError(
|
||||
result.errorCode,
|
||||
result.errorMessage ?? '',
|
||||
command,
|
||||
subCommand,
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const encode = (env: OidbBase<Oidb0xdc2_34Req>): Uint8Array =>
|
||||
protobuf_encode<OidbBase<Oidb0xdc2_34Req>>(env);
|
||||
|
||||
@@ -1,19 +1,15 @@
|
||||
import { describe, expect, it, vi } from 'vitest';
|
||||
import { protobuf_encode } from '@snowluma/proton';
|
||||
import type { OidbBase } from '@snowluma/proto-defs/oidb';
|
||||
import type { Oidb0xdc2_34Resp } from '@snowluma/proto-defs/oidb-actions/contact-ark';
|
||||
import type { SendPacketResult } from '@snowluma/common/packet-sender';
|
||||
import { SendTuwenArk } from '../../../src/oidb-services/contacts/send-tuwen-ark';
|
||||
import { env, v, s, m } from '../_pb-oracle';
|
||||
|
||||
function makeSender() {
|
||||
const respEnv: OidbBase<Oidb0xdc2_34Resp> = { command: 0xdc2, subCommand: 34, body: {} };
|
||||
function makeSender(body = m(1, [...v(2, 10001), ...v(4, 0)])) {
|
||||
const r: SendPacketResult = {
|
||||
success: true,
|
||||
gotResponse: true,
|
||||
errorCode: 0,
|
||||
errorMessage: '',
|
||||
responseData: Buffer.from(protobuf_encode<OidbBase<Oidb0xdc2_34Resp>>(respEnv)),
|
||||
responseData: Buffer.from(env(0xdc2, 34, body, false), 'hex'),
|
||||
};
|
||||
return { sendRawPacket: vi.fn(async () => r) };
|
||||
}
|
||||
@@ -128,7 +124,40 @@ describe('SendTuwenArk namespace', () => {
|
||||
expect(Buffer.from(bytes).toString('hex')).toBe(env(0xdc2, 34, body, false));
|
||||
});
|
||||
|
||||
it('deserialize returns undefined (void response)', () => {
|
||||
expect(SendTuwenArk.deserialize({} as any, {})).toBeUndefined();
|
||||
it('rejects a delivery refusal even when the outer envelope succeeds', async () => {
|
||||
const sender = makeSender(
|
||||
m(1, [
|
||||
...v(1, 0),
|
||||
...v(2, 10001),
|
||||
...s(3, ''),
|
||||
...v(4, 901501),
|
||||
...s(5, 'imagent service_error:319_[oidb] rule type not match appid'),
|
||||
]),
|
||||
);
|
||||
await expect(
|
||||
SendTuwenArk.invoke(sender, {
|
||||
targetId: 10001,
|
||||
peerType: 0,
|
||||
title: 'title',
|
||||
desc: '',
|
||||
summary: '',
|
||||
jumpUrl: 'https://example.com',
|
||||
previewUrl: '',
|
||||
}),
|
||||
).rejects.toThrow(/901501.*rule type not match appid/);
|
||||
});
|
||||
|
||||
it('checks every delivery result and requires an acknowledgement', () => {
|
||||
const sender = makeSender();
|
||||
expect(() => SendTuwenArk.deserialize(sender, {})).toThrow('no delivery result');
|
||||
expect(() => SendTuwenArk.deserialize(sender, { results: [] })).toThrow(
|
||||
'no delivery result',
|
||||
);
|
||||
expect(() =>
|
||||
SendTuwenArk.deserialize(sender, {
|
||||
results: [{ errorCode: 0 }, { errorCode: 901501, errorMessage: 'refused' }],
|
||||
}),
|
||||
).toThrow('refused');
|
||||
expect(SendTuwenArk.deserialize(sender, { results: [{}] })).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user