104 lines
3.7 KiB
JavaScript
104 lines
3.7 KiB
JavaScript
// Lightweight Telegram sender
|
|
// Sends messages via Telegram Bot API: https://api.telegram.org/bot<token>/sendMessage
|
|
// Requires env: TELEGRAM_BOT_TOKEN, TELEGRAM_CHAT_ID (single or comma/semicolon separated)
|
|
|
|
import dotenv from 'dotenv'
|
|
dotenv.config()
|
|
|
|
let _fetch = null
|
|
|
|
async function getFetch() {
|
|
if (typeof globalThis.fetch === 'function') return globalThis.fetch
|
|
if (_fetch) return _fetch
|
|
try {
|
|
const mod = await import('node-fetch')
|
|
_fetch = mod.default
|
|
return _fetch
|
|
} catch (e) {
|
|
throw new Error('fetch is not available and node-fetch is not installed. Please install node-fetch or use Node 18+.')
|
|
}
|
|
}
|
|
|
|
function ensureArray(v) {
|
|
if (!v) return []
|
|
if (Array.isArray(v)) return v
|
|
if (typeof v === 'string') return v.split(/[;,]/).map(s => s.trim()).filter(Boolean)
|
|
return [String(v)]
|
|
}
|
|
|
|
export async function sendTelegramMessage({ text, parseMode = 'HTML', disableWebPagePreview = true, chatIds = null, replyMarkup = null }) {
|
|
const token = process.env.TELEGRAM_BOT_TOKEN || ''
|
|
const rawChatIds = chatIds || process.env.TELEGRAM_CHAT_ID || ''
|
|
const ids = ensureArray(rawChatIds)
|
|
|
|
if (!token || ids.length === 0) {
|
|
throw new Error('Telegram configuration missing: TELEGRAM_BOT_TOKEN and TELEGRAM_CHAT_ID are required')
|
|
}
|
|
|
|
const fetchImpl = await getFetch()
|
|
const base = `https://api.telegram.org/bot${token}`
|
|
|
|
const payloadBase = {
|
|
text: String(text || ''),
|
|
parse_mode: parseMode || undefined,
|
|
disable_web_page_preview: Boolean(disableWebPagePreview),
|
|
}
|
|
if (replyMarkup) payloadBase.reply_markup = replyMarkup
|
|
|
|
const results = []
|
|
for (const chat_id of ids) {
|
|
const res = await fetchImpl(`${base}/sendMessage`, {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ ...payloadBase, chat_id }),
|
|
})
|
|
let data
|
|
try {
|
|
data = await res.json()
|
|
} catch (e) {
|
|
throw new Error(`Telegram response parse error: HTTP ${res.status}`)
|
|
}
|
|
if (!res.ok || !data?.ok) {
|
|
const errMsg = data?.description || JSON.stringify(data)
|
|
throw new Error(`Telegram send failed: ${errMsg}`)
|
|
}
|
|
results.push(data)
|
|
}
|
|
return results
|
|
}
|
|
|
|
async function apiCall(method, body) {
|
|
const token = process.env.TELEGRAM_BOT_TOKEN || ''
|
|
if (!token) throw new Error('TELEGRAM_BOT_TOKEN missing')
|
|
const fetchImpl = await getFetch()
|
|
const base = `https://api.telegram.org/bot${token}`
|
|
const res = await fetchImpl(`${base}/${method}`, {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify(body),
|
|
})
|
|
let data
|
|
try { data = await res.json() } catch (e) { throw new Error(`Telegram ${method} parse error: HTTP ${res.status}`) }
|
|
if (!res.ok || !data?.ok) {
|
|
throw new Error(`Telegram ${method} failed: ${data?.description || JSON.stringify(data)}`)
|
|
}
|
|
return data
|
|
}
|
|
|
|
export async function answerCallbackQuery({ callbackQueryId, text = '', showAlert = false }) {
|
|
return apiCall('answerCallbackQuery', { callback_query_id: callbackQueryId, text, show_alert: showAlert })
|
|
}
|
|
|
|
export async function editMessageText({ chatId, messageId, text, parseMode = 'HTML', replyMarkup = null, disableWebPagePreview = true }) {
|
|
const body = { chat_id: chatId, message_id: messageId, text, parse_mode: parseMode, disable_web_page_preview: disableWebPagePreview }
|
|
if (replyMarkup) body.reply_markup = replyMarkup
|
|
return apiCall('editMessageText', body)
|
|
}
|
|
|
|
export async function editMessageReplyMarkup({ chatId, messageId, replyMarkup }) {
|
|
return apiCall('editMessageReplyMarkup', { chat_id: chatId, message_id: messageId, reply_markup: replyMarkup })
|
|
}
|
|
|
|
export async function getUpdates({ offset = 0, timeout = 30 }) {
|
|
return apiCall('getUpdates', { offset, timeout, allowed_updates: ['message', 'callback_query'] })
|
|
}
|