138 lines
4.5 KiB
JavaScript
138 lines
4.5 KiB
JavaScript
'use strict';
|
|
|
|
const assert = require('node:assert/strict');
|
|
const test = require('node:test');
|
|
|
|
const {
|
|
TelegramNotifier,
|
|
formatLobbyMessage,
|
|
parseRecipientIds,
|
|
validateBotToken,
|
|
} = require('../lib/telegram-notifier');
|
|
|
|
class MemoryStore {
|
|
constructor(initial = null) {
|
|
this.value = initial;
|
|
}
|
|
|
|
load() {
|
|
return this.value;
|
|
}
|
|
|
|
save(value) {
|
|
this.value = JSON.parse(JSON.stringify(value));
|
|
}
|
|
}
|
|
|
|
function fakeResponse(result) {
|
|
return {
|
|
ok: true,
|
|
status: 200,
|
|
json: async () => ({ ok: true, result }),
|
|
};
|
|
}
|
|
|
|
test('validates Telegram bot tokens and numeric recipient IDs without losing precision', () => {
|
|
assert.equal(validateBotToken('123456:abcdefghijklmnopqrstuvwxyz_ABC'), '123456:abcdefghijklmnopqrstuvwxyz_ABC');
|
|
assert.deepEqual(parseRecipientIds('123456789, 4503599627370495; 123456789'), [
|
|
'123456789',
|
|
'4503599627370495',
|
|
]);
|
|
assert.throws(() => parseRecipientIds('alice'), /positive numeric/);
|
|
assert.throws(() => parseRecipientIds('4503599627370496'), /positive numeric/);
|
|
});
|
|
|
|
test('formats lobby status with real-player count and resolved member names', () => {
|
|
const text = formatLobbyMessage(
|
|
{
|
|
lobbyName: 'Duos queue',
|
|
customMapName: 'duos',
|
|
customMaxPlayers: 12,
|
|
notifyAtPlayers: 8,
|
|
leaveAtPlayers: 9,
|
|
serverRegion: 9,
|
|
},
|
|
{
|
|
phase: 'monitoring',
|
|
lobbyId: '29963550000000000',
|
|
humanCount: 2,
|
|
practicePublished: true,
|
|
members: [
|
|
{ steamId: '76561198000000001', name: 'Alice' },
|
|
{ steamId: '76561198000000002', name: 'Bob' },
|
|
],
|
|
},
|
|
);
|
|
|
|
assert.match(text, /Игроки: 2\/12/);
|
|
assert.match(text, /1\. Alice \(76561198000000001\)/);
|
|
assert.match(text, /2\. Bob \(76561198000000002\)/);
|
|
assert.match(text, /Публикация: в списке лобби/);
|
|
});
|
|
|
|
test('sends one tracker message and edits it only when lobby content changes', async () => {
|
|
const calls = [];
|
|
const fetchImpl = async (url, options) => {
|
|
const method = url.split('/').at(-1);
|
|
const payload = JSON.parse(options.body);
|
|
calls.push({ method, payload });
|
|
if (method === 'getMe') return fakeResponse({ id: 99, username: 'lobby_bot' });
|
|
if (method === 'sendMessage') return fakeResponse({ message_id: 42 });
|
|
if (method === 'editMessageText') return fakeResponse({ message_id: 42 });
|
|
throw new Error(`Unexpected method ${method}`);
|
|
};
|
|
const store = new MemoryStore();
|
|
const notifier = new TelegramNotifier({ store, fetchImpl, debounceMs: 1 });
|
|
await notifier.configure({
|
|
token: '123456:abcdefghijklmnopqrstuvwxyz_ABC',
|
|
recipientIds: ['123456789'],
|
|
});
|
|
assert.equal(notifier.publicState().configured, true);
|
|
assert.equal(notifier.publicState().token, undefined);
|
|
|
|
notifier.beginLobbySession();
|
|
const settings = { lobbyName: 'Duos', customMaxPlayers: 12 };
|
|
const first = {
|
|
phase: 'monitoring',
|
|
armed: true,
|
|
lobbyId: '123',
|
|
humanCount: 1,
|
|
members: [{ steamId: '76561198000000001', name: 'Alice' }],
|
|
};
|
|
await notifier.syncLobby(settings, first);
|
|
await notifier.syncLobby(settings, first);
|
|
const restoredNotifier = new TelegramNotifier({ store, fetchImpl, debounceMs: 1 });
|
|
await restoredNotifier.syncLobby(settings, {
|
|
...first,
|
|
humanCount: 2,
|
|
members: [...first.members, { steamId: '76561198000000002', name: 'Bob' }],
|
|
});
|
|
|
|
assert.deepEqual(calls.map((call) => call.method), ['getMe', 'sendMessage', 'editMessageText']);
|
|
assert.equal(calls[1].payload.chat_id, '123456789');
|
|
assert.equal(calls[2].payload.message_id, 42);
|
|
assert.match(calls[2].payload.text, /Игроки: 2\/12/);
|
|
assert.equal(store.value.token, '123456:abcdefghijklmnopqrstuvwxyz_ABC');
|
|
});
|
|
|
|
test('test delivery reports recipients that have not started the bot chat', async () => {
|
|
const fetchImpl = async (url) => {
|
|
const method = url.split('/').at(-1);
|
|
if (method === 'getMe') return fakeResponse({ id: 99, username: 'lobby_bot' });
|
|
return {
|
|
ok: false,
|
|
status: 403,
|
|
json: async () => ({ ok: false, error_code: 403, description: 'Forbidden: bot can\'t initiate conversation with a user' }),
|
|
};
|
|
};
|
|
const notifier = new TelegramNotifier({ store: new MemoryStore(), fetchImpl });
|
|
await notifier.configure({
|
|
token: '123456:abcdefghijklmnopqrstuvwxyz_ABC',
|
|
recipientIds: ['123456789'],
|
|
});
|
|
const result = await notifier.sendTest();
|
|
assert.equal(result.delivered, 0);
|
|
assert.equal(result.failed, 1);
|
|
assert.match(result.errors[0], /can't initiate conversation/);
|
|
});
|