73 lines
3.5 KiB
JavaScript
73 lines
3.5 KiB
JavaScript
/**
|
||
* Telegram bildirim kanalı — Bot API, bağımlılık yok.
|
||
*
|
||
* KURULUM (kullanıcı/yönetici): BotFather'da bot oluşturulur, tokenı
|
||
* TELEGRAM_BOT_TOKEN env'ine girilir. Her kullanıcı uygulamadan aldığı 6 haneli
|
||
* kodu bota yazar; sunucu getUpdates ile kodu görüp chat id'yi kullanıcıya
|
||
* bağlar. Token bizde tutulmaz, sohbet kimliği kullanıcı verisinde durur.
|
||
*/
|
||
|
||
const API = () => `https://api.telegram.org/bot${process.env.TELEGRAM_BOT_TOKEN}`;
|
||
|
||
export function telegramConfigured() {
|
||
return Boolean(process.env.TELEGRAM_BOT_TOKEN);
|
||
}
|
||
|
||
let botOnbellek = { ad: null, zaman: 0 };
|
||
/** Bot kullanıcı adı (t.me/<ad>) — arayüzde bağlantı vermek için. */
|
||
export async function botAdi() {
|
||
if (!telegramConfigured()) return null;
|
||
if (botOnbellek.ad && Date.now() - botOnbellek.zaman < 3600e3) return botOnbellek.ad;
|
||
try {
|
||
const r = await fetch(`${API()}/getMe`, { signal: AbortSignal.timeout(10000) });
|
||
const d = await r.json();
|
||
if (d.ok) { botOnbellek = { ad: d.result.username, zaman: Date.now() }; return d.result.username; }
|
||
} catch { /* aşağıda null */ }
|
||
return null;
|
||
}
|
||
|
||
export async function sendTelegram(chatId, text, { parseMode = 'HTML', returnReceipt = false } = {}) {
|
||
if (!telegramConfigured() || !chatId) return false;
|
||
const r = await fetch(`${API()}/sendMessage`, {
|
||
method: 'POST',
|
||
headers: { 'Content-Type': 'application/json' },
|
||
body: JSON.stringify({ chat_id: chatId, text: String(text).slice(0, 4000), ...(parseMode === null ? {} : { parse_mode:parseMode }), disable_web_page_preview: true }),
|
||
signal: AbortSignal.timeout(15000),
|
||
});
|
||
const d = await r.json().catch(() => ({}));
|
||
if (!r.ok || d.ok !== true) throw new Error(d.description || `Telegram HTTP ${r.status}`);
|
||
if (returnReceipt) {
|
||
const messageId=d.result?.message_id,returnedChat=d.result?.chat?.id;
|
||
if (!Number.isSafeInteger(messageId) || messageId <= 0 || !Number.isSafeInteger(returnedChat) || returnedChat === 0)
|
||
throw new Error('Telegram mesaj kimliği doğrulanamadı; gönderim sonucu belirsiz.');
|
||
if (/^-?\d+$/.test(String(chatId)) && String(returnedChat) !== String(chatId))
|
||
throw new Error('Telegram kabulü hedef sohbetle eşleşmiyor; gönderim sonucu belirsiz.');
|
||
return { id:`${returnedChat}:${messageId}`, chatId:String(returnedChat), messageId };
|
||
}
|
||
return true;
|
||
}
|
||
|
||
/**
|
||
* Kullanıcının bota yazdığı 6 haneli kodu son güncellemelerde arar.
|
||
* Bulursa { chatId, ad } döner. Long-polling yok; kullanıcı "doğrula" dediğinde
|
||
* tek getUpdates çağrısı yeterli (Telegram son 24 saati tutar).
|
||
*/
|
||
export async function kodIleBagla(kod) {
|
||
if (!telegramConfigured()) throw new Error('Sunucuda TELEGRAM_BOT_TOKEN tanımlı değil');
|
||
const r = await fetch(`${API()}/getUpdates?limit=100`, { signal: AbortSignal.timeout(15000) });
|
||
const d = await r.json().catch(() => ({}));
|
||
if (!d.ok) throw new Error(d.description || 'getUpdates başarısız');
|
||
const aranan = String(kod).trim();
|
||
for (const u of [...(d.result || [])].reverse()) {
|
||
const m = u.message || u.edited_message;
|
||
if (!m?.text) continue;
|
||
if (m.text.replace(/\D/g, '').includes(aranan)) {
|
||
return { chatId: String(m.chat.id), ad: [m.chat.first_name, m.chat.last_name].filter(Boolean).join(' ') || m.chat.username || null };
|
||
}
|
||
}
|
||
return null;
|
||
}
|
||
|
||
/** HTML kaçışı — ihale adları '<' '&' içerebiliyor. */
|
||
export const tgKacir = (s) => String(s ?? '').replace(/[&<>]/g, (c) => ({ '&': '&', '<': '<', '>': '>' }[c]));
|