import { test } from 'node:test'; import assert from 'node:assert/strict'; import { MatrixEvent, Room } from 'matrix-js-sdk'; import { describeRoomBridge, getBridgedUserNetwork, getRoomBridges, parseBridgeEvent, } from './bridge'; const bridgeEvent = (type: string, stateKey: string, content: Record) => new MatrixEvent({ type, state_key: stateKey, content, room_id: '!r:x', sender: '@discordbot:x' }); // Shape of what mautrix-discord 0.7.7 sends for a guild channel. const discordContent = { bridgebot: '@discordbot:matrix.lotusguild.org', protocol: { id: 'discordgo', displayname: 'Discord' }, channel: { id: '1565159372122882070', displayname: '#general', external_url: 'https://discord.com/channels/1/1565159372122882070', }, network: { id: '1', displayname: 'Lotus Guild' }, }; const roomWithState = (events: MatrixEvent[]): Room => ({ getLiveTimeline: () => ({ getState: () => ({ getStateEvents: (type: string) => events.filter((e) => e.getType() === type), }), }), }) as unknown as Room; test('Discord ghosts are recognised; the bridge bot and lookalikes are not', () => { assert.equal( getBridgedUserNetwork('@discord_123456789012345678:matrix.lotusguild.org'), 'discord', ); assert.equal(getBridgedUserNetwork('@discordbot:matrix.lotusguild.org'), undefined); assert.equal(getBridgedUserNetwork('@discord_fan:matrix.lotusguild.org'), undefined); assert.equal(getBridgedUserNetwork('@discord-relay:matrix.lotusguild.org'), undefined); assert.equal(getBridgedUserNetwork('@jared:matrix.lotusguild.org'), undefined); }); test('parseBridgeEvent reads a mautrix-discord m.bridge event', () => { assert.deepEqual(parseBridgeEvent(bridgeEvent('m.bridge', 'k', discordContent)), { network: 'discord', channelName: '#general', networkName: 'Lotus Guild', externalUrl: 'https://discord.com/channels/1/1565159372122882070', }); }); test('parseBridgeEvent ignores unknown protocols and empty content', () => { assert.equal( parseBridgeEvent(bridgeEvent('m.bridge', 'k', { protocol: { id: 'telegram' } })), undefined, ); assert.equal(parseBridgeEvent(bridgeEvent('m.bridge', 'k', {})), undefined); }); test('only http(s) channel links are kept', () => { const content = { ...discordContent, channel: { displayname: '#x', external_url: ['javascript', 'alert(1)'].join(':') }, }; assert.equal(parseBridgeEvent(bridgeEvent('m.bridge', 'k', content))?.externalUrl, undefined); }); test('getRoomBridges merges m.bridge with its unstable copy, one entry per channel', () => { const room = roomWithState([ bridgeEvent('m.bridge', 'fi.mau.discord://discord/1/2', discordContent), bridgeEvent('uk.half-shot.bridge', 'fi.mau.discord://discord/1/2', discordContent), ]); assert.equal(getRoomBridges(room).length, 1); assert.equal(getRoomBridges(roomWithState([])).length, 0); }); test('describeRoomBridge degrades gracefully without names', () => { assert.equal( describeRoomBridge({ network: 'discord', channelName: '#general', networkName: 'Lotus Guild' }), 'Bridged to #general in Lotus Guild on Discord', ); assert.equal(describeRoomBridge({ network: 'discord' }), 'Bridged to Discord'); });