SnowLuma v2.4.2 source snapshot
Dev Build / cleanup (push) Waiting to run
Dev Build / typecheck (push) Waiting to run
Publish MCP to npm / Build, test, and publish MCP (push) Waiting to run
Publish SDK to npm / Build, test, and publish SDK (push) Waiting to run
Sync action catalog to docs / sync (push) Waiting to run
Publish UI to npm / Build and publish UI (push) Waiting to run
Build and Release / preflight (push) Waiting to run

This commit is contained in:
TanTan committed 2026-11-13 09:02:00 +08:00
commit fa9c73363d
1367 files changed
+355735

No files matched your search

@@ -0,0 +1,183 @@
import { describe, expect, it } from 'vitest';
import { protobuf_encode, type pb, type uint_32, type bytes } from '@snowluma/proton';
import { IdentityService } from '@snowluma/protocol/identity-service';
import { parseMsgPush, parseMsgPushOrThrow } from '@snowluma/protocol/msg-push';
import type { PacketInfo } from '@snowluma/common/protocol-types';
import { convertEvent } from '../src/event-converter';
// Independent wire fixture: routing header 1.8.8.4.1 contains the join
// origin. The member-change body has its own operator, not the inviter.
interface ObservedOrigin {
type?: pb<1, uint_32>;
uid?: pb<3, bytes>;
}
interface ObservedJoinInfo {
origin?: pb<1, ObservedOrigin>;
}
interface ObservedGroupKey {
extra?: pb<4, ObservedJoinInfo>;
}
interface ObservedGroupRoute {
key?: pb<8, ObservedGroupKey>;
}
interface ObservedRoute {
from?: pb<1, uint_32>;
group?: pb<8, ObservedGroupRoute>;
}
interface ObservedHead {
type?: pb<1, uint_32>;
time?: pb<6, uint_32>;
}
interface ObservedBody {
content?: pb<2, bytes>;
}
interface ObservedMessage {
route?: pb<1, ObservedRoute>;
head?: pb<2, ObservedHead>;
body?: pb<3, ObservedBody>;
}
interface ObservedPush {
message?: pb<1, ObservedMessage>;
}
interface ObservedChange {
group?: pb<1, uint_32>;
member?: pb<3, string>;
operation?: pb<4, uint_32>;
operator?: pb<5, bytes>;
}
function packet(operation: number, origin?: ObservedOrigin): PacketInfo {
return {
pid: 0,
uin: '10001',
seqId: 1,
retCode: 0,
fromClient: false,
serviceCmd: 'trpc.msg.olpush.OlPushService.MsgPush',
body: protobuf_encode<ObservedPush>({
message: {
route: { from: 90001, group: { key: { extra: { origin } } } },
head: { type: 33, time: 1_700_000_000 },
body: {
content: protobuf_encode<ObservedChange>({
group: 90001,
member: 'u_member',
operation,
operator: Buffer.from('u_admin'),
}),
},
},
}),
};
}
function identity() {
const result = IdentityService.memory('10001');
for (const [uid, uin] of [
['u_member', 10002],
['u_admin', 10003],
['u_inviter', 10004],
] as const) {
result.rememberRequestIdentity({ uid, uin, source: 'group_request' });
}
return result;
}
async function notice(pkt: PacketInfo, identities = identity()) {
const events = parseMsgPush(pkt, identities);
expect(events).toHaveLength(1);
return convertEvent(
{
selfId: 10001,
imageUrlResolver: null,
mediaUrlResolver: null,
messageIdResolver: null,
mediaSegmentSink: null,
},
events[0]!,
);
}
describe('group join identities (#643)', () => {
it.each([2, 130])('keeps all three actors distinct for operation %d', async (operation) => {
expect(
await notice(packet(operation, { type: 0, uid: Buffer.from('u_inviter') })),
).toMatchObject({
notice_type: 'group_increase',
sub_type: 'approve',
group_id: 90001,
user_id: 10002,
operator_id: 10003,
invitor_id: 10004,
invitor_status: 'known',
});
});
it.each([3, 131, 0x102, 0x103])(
'does not guess the inviter from operation %d',
async (operation) => {
expect(
await notice(packet(operation, { type: 0, uid: Buffer.from('u_inviter') })),
).toMatchObject({
user_id: 10002,
operator_id: 10003,
invitor_id: 0,
invitor_status: 'unknown',
});
},
);
it('does not label a QR-code sharer as an inviter', async () => {
expect(await notice(packet(130, { type: 1, uid: Buffer.from('u_inviter') }))).toMatchObject(
{
operator_id: 10003,
invitor_id: 0,
invitor_status: 'unknown',
},
);
});
it.each([undefined, {}, { type: 0, uid: new Uint8Array() }])(
'reports missing origin as unknown',
async (origin) => {
expect(await notice(packet(130, origin))).toMatchObject({
invitor_id: 0,
invitor_status: 'unknown',
});
},
);
it('keeps an unresolved inviter unknown without substituting the administrator', async () => {
expect(
await notice(packet(130, { type: 0, uid: Buffer.from('u_unresolved') })),
).toMatchObject({
operator_id: 10003,
invitor_id: 0,
invitor_status: 'unknown',
});
});
it.each([Buffer.from([0xff]), Buffer.from('u_bad\nuid')])(
'rejects malformed inviter identities',
(uid) => {
expect(() => parseMsgPushOrThrow(packet(130, { type: 0, uid }), identity())).toThrow(
/invitation origin/,
);
},
);
it("does not reuse another account's identity cache", async () => {
identity();
expect(
await notice(
packet(130, { type: 0, uid: Buffer.from('u_inviter') }),
IdentityService.memory('20001'),
),
).toMatchObject({
invitor_id: 0,
invitor_status: 'unknown',
});
});
});