This commit is contained in:
@@ -0,0 +1,137 @@
|
||||
'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/);
|
||||
});
|
||||
Reference in New Issue
Block a user