Пытаюсь сделать рассылку на 3к пользователей, отправляет только 200-300. Ошибка: const BATCH_SIZE = 30; const BATCH_DELAY = 2000; const MESSAGE_DELAY = 200; const MESSAGE_TIMEOUT = 30000; const sendMessageWithTimeout = async (telegram, chatId, text, options, retries = 3) => { for (let attempt = 1; attempt <= retries; attempt++) { try { return await Promise.race([ telegram.sendMessage(chatId, text, options), new Promise((_, reject) => setTimeout(() => reject(new Error('Message send timeout')), MESSAGE_TIMEOUT) ), ]); } catch (err) { if (err.message.includes('429') && attempt < retries) { await new Promise(res => setTimeout(res, 1000 * attempt)); continue; } throw err; } } }; module.exports = async (ctx) => { try { const userId = ctx.from.id; const message = selectMailAll.getText(userId); if (!message) { console.log(`Пользователь ${userId} попытался подтвердить рассылку без текста`); return ctx.reply(' Нет текста для рассылки.'); } const users = await User.find({ hasDialog: true }); let success = 0; let error = 0; const progressMsg = await ctx.reply(' Начинаем рассылку...'); for (let i = 0; i < users.length; i += BATCH_SIZE) { const batch = users.slice(i, i + BATCH_SIZE); console.log(`Начало батча ${i}, размер: ${batch.length}, время: ${new Date().toISOString()}`); for (const user of batch) { try { await sendMessageWithTimeout(ctx.telegram, user.telegramId, message, { parse_mode: 'HTML' }); success++; } catch (err) { error++; console.warn(` Ошибка при отправке ${user.telegramId}:`, err.message); if (err.code === 403) { console.warn(` Пользователь ${user.telegramId} заблокировал бота или не писал первым`); } await User.updateOne({ telegramId: user.telegramId }, { hasDialog: false }); } await new Promise(res => setTimeout(res, MESSAGE_DELAY)); } const percent = Math.round(((i + BATCH_SIZE) / users.length) * 100); try { await ctx.telegram.editMessageText( ctx.chat.id, progressMsg.message_id, null, ` Рассылка...\nПрогресс: ${Math.min(i + BATCH_SIZE, users.length)}/${users.length} (${percent}%)\n Успешно: ${success}\n Ошибки: ${error}` ); } catch (err) { console.warn(' Ошибка при обновлении прогресса:', err.message); } if (i + BATCH_SIZE < users.length) { await new Promise(res => setTimeout(res, BATCH_DELAY)); } } selectMailAll.clear(userId); await ctx.reply(` Рассылка завершена!\n Успешно: ${success}\n Ошибки: ${error}`); } catch (err) { console.error(' Ошибка при рассылке:', err); await ctx.reply(' Произошла критическая ошибка при рассылке.'); } }; JS const BATCH_SIZE = 30; const BATCH_DELAY = 2000; const MESSAGE_DELAY = 200; const MESSAGE_TIMEOUT = 30000; const sendMessageWithTimeout = async (telegram, chatId, text, options, retries = 3) => { for (let attempt = 1; attempt <= retries; attempt++) { try { return await Promise.race([ telegram.sendMessage(chatId, text, options), new Promise((_, reject) => setTimeout(() => reject(new Error('Message send timeout')), MESSAGE_TIMEOUT) ), ]); } catch (err) { if (err.message.includes('429') && attempt < retries) { await new Promise(res => setTimeout(res, 1000 * attempt)); continue; } throw err; } } }; module.exports = async (ctx) => { try { const userId = ctx.from.id; const message = selectMailAll.getText(userId); if (!message) { console.log(`Пользователь ${userId} попытался подтвердить рассылку без текста`); return ctx.reply(' Нет текста для рассылки.'); } const users = await User.find({ hasDialog: true }); let success = 0; let error = 0; const progressMsg = await ctx.reply(' Начинаем рассылку...'); for (let i = 0; i < users.length; i += BATCH_SIZE) { const batch = users.slice(i, i + BATCH_SIZE); console.log(`Начало батча ${i}, размер: ${batch.length}, время: ${new Date().toISOString()}`); for (const user of batch) { try { await sendMessageWithTimeout(ctx.telegram, user.telegramId, message, { parse_mode: 'HTML' }); success++; } catch (err) { error++; console.warn(` Ошибка при отправке ${user.telegramId}:`, err.message); if (err.code === 403) { console.warn(` Пользователь ${user.telegramId} заблокировал бота или не писал первым`); } await User.updateOne({ telegramId: user.telegramId }, { hasDialog: false }); } await new Promise(res => setTimeout(res, MESSAGE_DELAY)); } const percent = Math.round(((i + BATCH_SIZE) / users.length) * 100); try { await ctx.telegram.editMessageText( ctx.chat.id, progressMsg.message_id, null, ` Рассылка...\nПрогресс: ${Math.min(i + BATCH_SIZE, users.length)}/${users.length} (${percent}%)\n Успешно: ${success}\n Ошибки: ${error}` ); } catch (err) { console.warn(' Ошибка при обновлении прогресса:', err.message); } if (i + BATCH_SIZE < users.length) { await new Promise(res => setTimeout(res, BATCH_DELAY)); } } selectMailAll.clear(userId); await ctx.reply(` Рассылка завершена!\n Успешно: ${success}\n Ошибки: ${error}`); } catch (err) { console.error(' Ошибка при рассылке:', err); await ctx.reply(' Произошла критическая ошибка при рассылке.'); } };