| 64 | // The user creates a bot via @BotFather and provides the token. |
| 65 | // The chat ID is obtained when the user sends their first message to the bot. |
| 66 | async function sendTelegram(text, botToken, chatId) { |
| 67 | // Telegram has a 4096 character limit per message. |
| 68 | // If the digest is longer, we split it into chunks. |
| 69 | const MAX_LEN = 4000; |
| 70 | const chunks = []; |
| 71 | let remaining = text; |
| 72 | while (remaining.length > 0) { |
| 73 | if (remaining.length <= MAX_LEN) { |
| 74 | chunks.push(remaining); |
| 75 | break; |
| 76 | } |
| 77 | // Try to split at a newline near the limit |
| 78 | let splitAt = remaining.lastIndexOf('\n', MAX_LEN); |
| 79 | if (splitAt < MAX_LEN * 0.5) splitAt = MAX_LEN; |
| 80 | chunks.push(remaining.slice(0, splitAt)); |
| 81 | remaining = remaining.slice(splitAt); |
| 82 | } |
| 83 | |
| 84 | for (const chunk of chunks) { |
| 85 | const res = await fetch( |
| 86 | `https://api.telegram.org/bot${botToken}/sendMessage`, |
| 87 | { |
| 88 | method: 'POST', |
| 89 | headers: { 'Content-Type': 'application/json' }, |
| 90 | body: JSON.stringify({ |
| 91 | chat_id: chatId, |
| 92 | text: chunk, |
| 93 | parse_mode: 'Markdown', |
| 94 | disable_web_page_preview: true |
| 95 | }) |
| 96 | } |
| 97 | ); |
| 98 | |
| 99 | if (!res.ok) { |
| 100 | const err = await res.json(); |
| 101 | // If Markdown parsing fails, retry without parse_mode |
| 102 | if (err.description && err.description.includes("can't parse")) { |
| 103 | await fetch( |
| 104 | `https://api.telegram.org/bot${botToken}/sendMessage`, |
| 105 | { |
| 106 | method: 'POST', |
| 107 | headers: { 'Content-Type': 'application/json' }, |
| 108 | body: JSON.stringify({ |
| 109 | chat_id: chatId, |
| 110 | text: chunk, |
| 111 | disable_web_page_preview: true |
| 112 | }) |
| 113 | } |
| 114 | ); |
| 115 | } else { |
| 116 | throw new Error(`Telegram API error: ${err.description}`); |
| 117 | } |
| 118 | } |
| 119 | |
| 120 | // Small delay between chunks to avoid rate limiting |
| 121 | if (chunks.length > 1) await new Promise(r => setTimeout(r, 500)); |
| 122 | } |
| 123 | } |