import {test,after} from 'node:test'; import assert from 'node:assert/strict'; import {mkdtempSync,rmSync} from 'node:fs'; import {join} from 'node:path'; import {tmpdir} from 'node:os'; import {createTelegramLinker} from '../server/telegram-link.mjs'; import {kodIleBagla} from '../server/telegram.mjs'; const directory=mkdtempSync(join(tmpdir(),'telegram-link-')); process.env.IHALEIST_USER_DATA_DIR=directory; const store=await import('../server/user-store.mjs'); after(()=>rmSync(directory,{recursive:true,force:true})); const found={chatId:'123',ad:'Test'}; test('server challenge belongs to its account, expires, rotates and is consumed once',async()=>{ let time=1000000;const linker=createTelegramLinker(store,()=>time),email='link@example.test'; const first=linker.issue(email);assert.match(first.kod,/^[a-f0-9]{48}$/); assert.ok(!JSON.stringify(store.getData(email,'telegram')).includes(first.kod)); await assert.rejects(linker.link('other@example.test',first.kod,async()=>found),{status:400,kod:'TELEGRAM_CHALLENGE_INVALID'}); const second=linker.issue(email);assert.notEqual(second.kod,first.kod); await assert.rejects(linker.link(email,first.kod,async()=>found),{status:400,kod:'TELEGRAM_CHALLENGE_INVALID'}); time=second.expiresAt; await assert.rejects(linker.link(email,second.kod,async()=>found),{status:400,kod:'TELEGRAM_CHALLENGE_INVALID'}); const current=linker.issue(email); assert.deepEqual(await linker.link(email,current.kod,async()=>found),found); await assert.rejects(linker.link(email,current.kod,async()=>found),{status:400,kod:'TELEGRAM_CHALLENGE_INVALID'}); assert.equal(store.getData(email,'telegram').chatId,'123'); assert.throws(()=>linker.issue(email),{status:409}); }); test('disconnect or expiration during provider lookup cannot restore a removed link',async()=>{ let time=1000000;const linker=createTelegramLinker(store,()=>time),email='disconnect@example.test'; const challenge=linker.issue(email); await assert.rejects(linker.link(email,challenge.kod,async()=>{store.setData(email,'telegram',null);return found;}),{status:400,kod:'TELEGRAM_CHALLENGE_INVALID'}); assert.equal(store.getData(email,'telegram'),null); const next=linker.issue(email); await assert.rejects(linker.link(email,next.kod,async()=>{time=next.expiresAt;return found;}),{status:400,kod:'TELEGRAM_CHALLENGE_INVALID'}); }); test('matching accepts only a fresh exact code from a private non-bot sender',async()=>{ const oldFetch=globalThis.fetch,oldToken=process.env.TELEGRAM_BOT_TOKEN; process.env.TELEGRAM_BOT_TOKEN='synthetic-token'; const code='a'.repeat(48),window={issuedAt:1000000,expiresAt:1600000,now:1100000}; const good={text:code,date:1050,chat:{id:123,type:'private',first_name:'QA'},from:{id:123,is_bot:false}}; let updates=[]; globalThis.fetch=async()=>({ok:true,json:async()=>({ok:true,result:updates})}); try { for(const message of [{...good,text:'prefix '+code},{...good,text:code+' suffix'},{...good,date:999}, {...good,date:1101},{...good,chat:{id:123,type:'group'}},{...good,from:{id:123,is_bot:true}}, {...good,from:{id:999,is_bot:false}}]) { updates=[{message}];assert.equal(await kodIleBagla(code,window),null); } updates=[{edited_message:good}];assert.equal(await kodIleBagla(code,window),null); updates=[{message:good}];assert.equal((await kodIleBagla(code,window)).chatId,'123'); updates=[{message:{...good,text:'/start '+code}}];assert.equal((await kodIleBagla(code,window)).ad,'QA'); } finally {globalThis.fetch=oldFetch;if(oldToken===undefined)delete process.env.TELEGRAM_BOT_TOKEN;else process.env.TELEGRAM_BOT_TOKEN=oldToken;} }); test('provider errors and malformed updates are not treated as code-not-found results',async()=>{ const oldFetch=globalThis.fetch,oldToken=process.env.TELEGRAM_BOT_TOKEN; process.env.TELEGRAM_BOT_TOKEN='synthetic-token'; const window={issuedAt:1000000,expiresAt:1600000,now:1100000}; try { for(const [ok,body] of [[false,{ok:true,result:[]}],[true,{ok:true}],[true,{ok:true,result:{}}],[true,{ok:'true',result:[]}]]){ globalThis.fetch=async()=>({ok,json:async()=>body}); await assert.rejects(kodIleBagla('a'.repeat(48),window),/yanıtı doğrulanamadı/); } }finally{globalThis.fetch=oldFetch;if(oldToken===undefined)delete process.env.TELEGRAM_BOT_TOKEN;else process.env.TELEGRAM_BOT_TOKEN=oldToken;} });