grammy-broadcast 2.0.2 → 2.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -21
- package/Readme.md +603 -603
- package/dist/index.d.mts +0 -0
- package/dist/index.d.ts +0 -0
- package/dist/index.js +0 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +0 -0
- package/dist/index.mjs.map +1 -1
- package/package.json +33 -33
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/middleware.ts","../src/utils.ts","../src/broadcast.queue.ts","../src/initChats.queue.ts","../src/storage.ts","../src/storage/redis.storage.ts","../src/storage/memory.storage.ts","../src/storage/file.storage.ts","../src/index.ts"],"sourcesContent":["import {Composer, Context, InlineKeyboard} from \"grammy\";\r\nimport {BroadcastOptions} from \"./types\";\r\nimport {buildProgressText} from \"./utils\";\r\n\r\nexport function getMiddleware(options: BroadcastOptions) {\r\n const middleware = new Composer();\r\n\r\n\r\n let broadcastMiddleware: Composer<Context>;\r\n if (options.sudoUsers?.length) {\r\n broadcastMiddleware = middleware.filter((ctx) => {\r\n if (ctx.from?.id) {\r\n return options.sudoUsers.includes(ctx.from.id)\r\n }\r\n return false;\r\n })\r\n } else if (typeof options.hasPermission === 'function') {\r\n broadcastMiddleware = middleware.filter(options.hasPermission)\r\n } else {\r\n broadcastMiddleware = middleware;\r\n }\r\n broadcastMiddleware.command([options.cmds.broadcast, options.cmds.copy, options.cmds.forward], async (ctx) => {\r\n let [command, ...args] = ctx.message!.text.substring(1).split(' ');\r\n let type: string;\r\n let filter: string;\r\n if (command === options.cmds.broadcast) {\r\n if (args.length < 1) {\r\n return ctx.reply(`Usage: /${options.cmds.broadcast} <type> [filter]\r\n\r\n\\`type\\` should be copy or forward\r\n\\`filter\\` is anything that want to passed to getBroadcastChats\r\n`, {\r\n parse_mode: \"Markdown\",\r\n })\r\n }\r\n type = args[0];\r\n filter = args.slice(1).join(' ')\r\n } else if (command === options.cmds.copy) {\r\n type = 'copy';\r\n filter = args.join(' ')\r\n } else if (command === options.cmds.forward) {\r\n type = 'forward';\r\n filter = args.join(' ')\r\n }\r\n\r\n if (!['copy', 'forward'].includes(type)) {\r\n return ctx.reply(`Invalid type ${type}`)\r\n }\r\n\r\n let brdId = Math.random().toString(36).substring(7);\r\n if (!ctx.message!.reply_to_message) {\r\n return ctx.reply('Reply to a message')\r\n }\r\n await options.storage.hset(options.keyPrefix + 'info:' + brdId, {\r\n type: type,\r\n chatFilter: filter,\r\n message_ids: ctx.message!.reply_to_message?.message_id.toString(),\r\n chat_id: ctx.chat.id.toString(),\r\n user_id: ctx.from!.id.toString(),\r\n id: brdId,\r\n error: '0',\r\n sent: '0',\r\n botId: ctx.me.id.toString(),\r\n total: '-1'\r\n });\r\n return ctx.reply(`\r\nReady to broadcast!\r\ncurrently 1 message is in queue\r\nfor send multi message in this broadcast reply this command to another message\r\n<code>/${options.cmds.addmsg} ${brdId}</code>\r\n`, {\r\n parse_mode: \"HTML\",\r\n reply_markup: new InlineKeyboard()\r\n .text('Preview', 'brd:preview:' + brdId)\r\n .text('Pin', `brd:pin:${brdId}`)\r\n .row()\r\n .text('Start', 'brd:start:' + brdId)\r\n .text('Cancel', 'brd:stop:' + brdId)\r\n })\r\n })\r\n\r\n broadcastMiddleware.command(options.cmds.addmsg, async (ctx) => {\r\n let args = ctx.message!.text.split(' ').slice(1);\r\n if (args.length < 1) {\r\n return ctx.reply(`Usage: /${options.cmds.addmsg} <id>`)\r\n }\r\n let brdId = args[0];\r\n if (!ctx.message!.reply_to_message) {\r\n return ctx.reply('Reply to a message')\r\n }\r\n let newMsgId = ctx.message!.reply_to_message?.message_id;\r\n let messageIds = await options.storage.hget(options.keyPrefix + 'info:' + brdId, 'message_ids');\r\n if (!messageIds) {\r\n return ctx.reply('Broadcast not found');\r\n }\r\n let currentIds = messageIds.split('_').map((e: string) => Number.parseInt(e));\r\n if (Math.max(newMsgId, ...currentIds) !== newMsgId) {\r\n return ctx.reply('Message should be newer than previous messages')\r\n }\r\n if (currentIds.includes(newMsgId)) {\r\n return ctx.reply('Message already in queue')\r\n }\r\n currentIds.push(newMsgId);\r\n\r\n await options.storage.hset(options.keyPrefix + 'info:' + brdId, 'message_ids', currentIds.join('_'));\r\n let isPin = await options.storage.hget(options.keyPrefix + 'info:' + brdId, 'pin');\r\n return ctx.reply(`Message added to queue\r\n\r\nMessages Count ${currentIds.length}`, {\r\n reply_markup: new InlineKeyboard()\r\n .text('Preview', 'brd:preview:' + brdId)\r\n .text(`Pin${isPin ? ' ✅' : ''}`, `brd:pin:${brdId}`)\r\n .row()\r\n .text('Start', 'brd:start:' + brdId)\r\n .text('Cancel', 'brd:stop:' + brdId)\r\n })\r\n });\r\n\r\n\r\n broadcastMiddleware.callbackQuery(/brd:progress:(\\w+)/, async (ctx) => {\r\n let info = await options.storage.hgetall(options.keyPrefix + 'info:' + ctx.match[1]);\r\n return ctx.answerCallbackQuery(\r\n {\r\n text: buildProgressText(+info.error, +info.sent, +info.total),\r\n show_alert: true\r\n }\r\n )\r\n\r\n });\r\n broadcastMiddleware.callbackQuery(/brd:pause:(\\w+)/, async (ctx) => {\r\n await options.storage.hset(options.keyPrefix + 'info:' + ctx.match[1], 'paused', '1');\r\n return ctx.editMessageText('Broadcast paused!', {\r\n reply_markup: new InlineKeyboard()\r\n\r\n .text('Resume', 'brd:resume:' + ctx.match[1])\r\n .text('Stop', 'brd:stop:' + ctx.match[1])\r\n });\r\n\r\n });\r\n broadcastMiddleware.callbackQuery(/brd:resume:(\\w+)/, async (ctx) => {\r\n await options.storage.hdel(options.keyPrefix + 'info:' + ctx.match[1], 'paused');\r\n return ctx.editMessageText(\r\n \"Lets begin...\", {\r\n reply_markup: new InlineKeyboard()\r\n .text('Pause', 'brd:pause:' + ctx.match[1])\r\n .text('Stop', 'brd:stop:' + ctx.match[1])\r\n });\r\n });\r\n broadcastMiddleware.callbackQuery(/brd:pin:(\\w+)/, async (ctx) => {\r\n let brdId = ctx.match[1];\r\n let isPin = await options.storage.hget(options.keyPrefix + 'info:' + brdId, 'pin');\r\n if (isPin) {\r\n await options.storage.hdel(options.keyPrefix + 'info:' + brdId, 'pin');\r\n } else {\r\n await options.storage.hset(options.keyPrefix + 'info:' + brdId, 'pin', '1');\r\n }\r\n return ctx.editMessageReplyMarkup({\r\n reply_markup: new InlineKeyboard()\r\n .text('Preview', 'brd:preview:' + brdId)\r\n .text(`Pin${(!isPin) ? ' ✅' : ''}`, `brd:pin:${brdId}`)\r\n .row()\r\n .text('Start', 'brd:start:' + brdId)\r\n .text('Cancel', 'brd:stop:' + brdId)\r\n\r\n })\r\n });\r\n broadcastMiddleware.callbackQuery(/brd:preview:(\\w+)/, async (ctx) => {\r\n let info = await options.storage.hgetall(options.keyPrefix + 'info:' + ctx.match[1]);\r\n if (!info.message_ids) {\r\n return;\r\n }\r\n let messageIds = info.message_ids.split('_').map((e: string) => Number.parseInt(e));\r\n if (info.type === 'copy') {\r\n let msgs = await ctx.copyMessages(info.chat_id, messageIds)\r\n if (info.pin) {\r\n await ctx.pinChatMessage(msgs.pop().message_id)\r\n }\r\n } else if (info.type === 'forward') {\r\n let msgs = await ctx.forwardMessages(info.chat_id, messageIds)\r\n if (info.pin) {\r\n await ctx.pinChatMessage(msgs.pop().message_id)\r\n }\r\n }\r\n });\r\n broadcastMiddleware.callbackQuery(/brd:start:(\\w+)/, async (ctx) => {\r\n let id = ctx.match[1];\r\n await options.storage.rpush(options.keyPrefix + 'list', id);\r\n return ctx.editMessageText(`Broadcast added to queue it takes some time to start...`, {\r\n reply_markup: new InlineKeyboard()\r\n .text('Pause', 'brd:pause:' + id)\r\n .text('Stop', 'brd:stop:' + id)\r\n });\r\n });\r\n broadcastMiddleware.callbackQuery(/brd:stop:(\\w+)/, async (ctx) => {\r\n return ctx.editMessageReplyMarkup({\r\n reply_markup: new InlineKeyboard().text('Sure?')\r\n .row()\r\n .text('Yes', 'brd:stop_confirm:' + ctx.match[1])\r\n .text('No', `brd:stop_cancel:${ctx.match[1]}`)\r\n });\r\n });\r\n broadcastMiddleware.callbackQuery(/brd:stop_cancel/, async (ctx) => {\r\n return ctx.editMessageReplyMarkup(\r\n {\r\n reply_markup: new InlineKeyboard()\r\n .text('Pause', 'brd:pause:' + ctx.match[1])\r\n }\r\n )\r\n });\r\n broadcastMiddleware.callbackQuery(/brd:stop_confirm:(\\w+)/, async (ctx) => {\r\n let id = ctx.match[1];\r\n\r\n await options.storage.del(options.keyPrefix + 'chats:' + id);\r\n await options.storage.del(options.keyPrefix + 'info:' + id);\r\n await options.storage.lrem(options.keyPrefix + 'list', 1, id);\r\n return ctx.editMessageText('Broadcast stopped');\r\n });\r\n\r\n return middleware;\r\n}\r\n\r\n\r\n","export function sleep(milli: number) {\r\n return new Promise(resolve => {\r\n setTimeout(resolve, milli);\r\n });\r\n}\r\n\r\nexport function buildProgressBtnText(percent: number, chars: number = 10) {\r\n let progress = Math.floor(percent * chars);\r\n let empty = chars - progress;\r\n console.log({progress, empty});\r\n return '█'.repeat(progress) + '░'.repeat(empty) + ` (${Math.floor(percent * 1000) / 10}%)`;\r\n}\r\n\r\nexport function buildProgressText(error: number, sent: number, total: number, rateLimit?: number) {\r\n const rateText = rateLimit !== undefined ? `\\n⚡ Rate: ${rateLimit} msg/sec` : '';\r\n return `⌛ Progress: ${error + (sent)}/${total}\r\n✅ Sent: ${sent}\r\n❌ Error: ${error} (${Math.floor((error / total) * 10000) / 100}%)${rateText}`;\r\n}","import {BroadcastInfo, BroadcastOptions} from \"./types\";\r\nimport {GrammyError, InlineKeyboard} from \"grammy\";\r\nimport {buildProgressBtnText, buildProgressText, sleep} from \"./utils\";\r\nimport {ChatsFetcher} from \"./initChats.queue\";\r\n\r\n// Rate limiter class for concurrent requests with rate limiting\r\nclass RateLimiter {\r\n private queue: Array<() => void> = [];\r\n private tokens: number;\r\n private maxTokens: number;\r\n private initialMaxTokens: number;\r\n private refillInterval: number;\r\n private refillTimer: NodeJS.Timeout | null = null;\r\n private lastRefillTime: number = Date.now();\r\n\r\n constructor(requestsPerSecond: number) {\r\n this.initialMaxTokens = requestsPerSecond;\r\n this.maxTokens = requestsPerSecond;\r\n this.tokens = requestsPerSecond;\r\n // Refill tokens more frequently for smoother rate limiting\r\n // For high rates (1000/sec), refill every 10ms with appropriate tokens\r\n // For lower rates (30/sec), refill every 100ms\r\n this.refillInterval = requestsPerSecond >= 100 ? 10 : 100;\r\n this.startRefill();\r\n }\r\n\r\n getCurrentRate(): number {\r\n return this.maxTokens;\r\n }\r\n\r\n reduceRate(factor: number = 0.5): void {\r\n // Reduce rate by factor (default: half)\r\n const newRate = Math.max(1, Math.floor(this.maxTokens * factor));\r\n console.log(`Reducing rate limit from ${this.maxTokens}/sec to ${newRate}/sec`);\r\n this.maxTokens = newRate;\r\n // Adjust refill interval based on new rate\r\n this.refillInterval = newRate >= 100 ? 10 : 100;\r\n // Don't increase tokens beyond new max\r\n this.tokens = Math.min(this.tokens, this.maxTokens);\r\n }\r\n\r\n resetRate(): void {\r\n // Reset to initial rate\r\n if (this.maxTokens !== this.initialMaxTokens) {\r\n console.log(`Resetting rate limit from ${this.maxTokens}/sec to ${this.initialMaxTokens}/sec`);\r\n this.maxTokens = this.initialMaxTokens;\r\n this.refillInterval = this.initialMaxTokens >= 100 ? 10 : 100;\r\n this.tokens = Math.min(this.tokens, this.maxTokens);\r\n }\r\n }\r\n\r\n private startRefill() {\r\n if (this.refillTimer) return;\r\n this.refillTimer = setInterval(() => {\r\n const now = Date.now();\r\n const elapsed = now - this.lastRefillTime;\r\n // Calculate how many tokens to add based on elapsed time\r\n const tokensToAdd = Math.floor((this.maxTokens * elapsed) / 1000);\r\n if (tokensToAdd > 0) {\r\n this.tokens = Math.min(this.maxTokens, this.tokens + tokensToAdd);\r\n this.lastRefillTime = now;\r\n this.processQueue();\r\n }\r\n }, this.refillInterval);\r\n }\r\n\r\n private processQueue() {\r\n while (this.queue.length > 0 && this.tokens > 0) {\r\n this.tokens--;\r\n const resolve = this.queue.shift()!;\r\n resolve();\r\n }\r\n }\r\n\r\n async acquire(): Promise<void> {\r\n // Check if we can refill tokens based on time elapsed\r\n const now = Date.now();\r\n const elapsed = now - this.lastRefillTime;\r\n if (elapsed >= 1000) {\r\n // More than a second has passed, refill all tokens\r\n this.tokens = this.maxTokens;\r\n this.lastRefillTime = now;\r\n } else if (elapsed > 0) {\r\n // Add tokens proportionally to elapsed time\r\n const tokensToAdd = Math.floor((this.maxTokens * elapsed) / 1000);\r\n if (tokensToAdd > 0) {\r\n this.tokens = Math.min(this.maxTokens, this.tokens + tokensToAdd);\r\n this.lastRefillTime = now;\r\n }\r\n }\r\n\r\n if (this.tokens > 0) {\r\n this.tokens--;\r\n return Promise.resolve();\r\n }\r\n return new Promise((resolve) => {\r\n this.queue.push(resolve);\r\n });\r\n }\r\n\r\n destroy() {\r\n if (this.refillTimer) {\r\n clearInterval(this.refillTimer);\r\n this.refillTimer = null;\r\n }\r\n }\r\n}\r\n\r\nexport class BroadcastQueue {\r\n private reportIds: Record<string, number> = {};\r\n private lastReports: Record<string, Date> = {};\r\n private processingBroadcasts: Set<string> = new Set();\r\n private rateLimiter: RateLimiter;\r\n private lastRateLimitTime: number = 0;\r\n\r\n constructor(private options: BroadcastOptions) {\r\n // Initialize rate limiter: 1000/sec for paid broadcasts, 30/sec otherwise\r\n const requestsPerSecond = this.options.allowPaidBroadcast ? 1000 : 30;\r\n this.rateLimiter = new RateLimiter(requestsPerSecond);\r\n }\r\n\r\n async checkBroadcasts() {\r\n let broadcasts = await this.options.storage.lrange(this.options.keyPrefix + 'list', 0, -1);\r\n let newBroadcasts = broadcasts.filter(id => !this.processingBroadcasts.has(id));\r\n\r\n if (newBroadcasts.length > 0) {\r\n newBroadcasts.forEach(id => this.processingBroadcasts.add(id));\r\n Promise.all(newBroadcasts.map(broadcastId =>\r\n this.sendBroadcast(broadcastId).finally(() => {\r\n this.processingBroadcasts.delete(broadcastId);\r\n })\r\n )).catch(err => {\r\n console.error('Error processing broadcasts:', err);\r\n });\r\n }\r\n\r\n setTimeout(this.checkBroadcasts.bind(this), this.options.checkQueueInterval);\r\n }\r\n\r\n async sendBroadcast(id: string) {\r\n let broadcastInfo = await this.options.storage.hgetall(this.options.keyPrefix + 'info:' + id) as unknown as BroadcastInfo;\r\n if (broadcastInfo.total === '-1') {\r\n console.log(\"fetching chats\")\r\n let fetcher = new ChatsFetcher(this.options);\r\n await fetcher.fetchChats(broadcastInfo, async (info) => {\r\n await this.sendProgress(info, false, 'fetching');\r\n });\r\n // بهروزرسانی broadcastInfo پس از اتمام fetchChats\r\n broadcastInfo = await this.options.storage.hgetall(this.options.keyPrefix + 'info:' + id) as unknown as BroadcastInfo;\r\n }\r\n if (!broadcastInfo) {\r\n await this.options.storage.lrem(this.options.keyPrefix + 'list', 1, id);\r\n return;\r\n }\r\n let chats = await this.options.storage.lpop(this.options.keyPrefix + 'chats:' + id, this.options!.chunkSize!);\r\n\r\n if (broadcastInfo.paused) return;\r\n\r\n if (!chats?.length) {\r\n await this.options.storage.del(this.options.keyPrefix + 'chats:' + id);\r\n await this.options.storage.del(this.options.keyPrefix + 'info:' + id);\r\n await this.options.storage.lrem(this.options.keyPrefix + 'list', 1, id);\r\n await this.sendProgress(broadcastInfo, true);\r\n return;\r\n }\r\n broadcastInfo.sent = broadcastInfo.sent || '0';\r\n broadcastInfo.error = broadcastInfo.error || '0';\r\n\r\n // Send messages concurrently with rate limiting\r\n const sendPromises = chats!.map(async (chat) => {\r\n // Acquire rate limit token before sending\r\n await this.rateLimiter.acquire();\r\n let isSent = await this.sendToChat(chat, broadcastInfo);\r\n if (isSent) {\r\n broadcastInfo.sent = ((+broadcastInfo.sent) + 1).toString();\r\n await this.options.storage.hincrby(this.options.keyPrefix + 'info:' + id, 'sent', 1);\r\n } else {\r\n broadcastInfo.error = ((+broadcastInfo.error) + 1).toString();\r\n await this.options.storage.hincrby(this.options.keyPrefix + 'info:' + id, 'error', 1);\r\n }\r\n });\r\n\r\n await Promise.all(sendPromises);\r\n await this.sendProgress(broadcastInfo);\r\n await this.sendBroadcast(id);\r\n\r\n }\r\n\r\n async sendProgress(broadcastInfo: BroadcastInfo, finished: boolean = false, stage: 'fetching' | 'broadcasting' = 'broadcasting') {\r\n if (this.options.progressCallback) {\r\n this.options.progressCallback(\r\n broadcastInfo.id,\r\n +broadcastInfo.sent! || 0,\r\n +broadcastInfo.error! || 0,\r\n +broadcastInfo.total! || 0\r\n )\r\n return;\r\n }\r\n let api = await this.options.getApi(+broadcastInfo.botId);\r\n\r\n let progressText: string;\r\n let percent: number;\r\n let title: string;\r\n\r\n if (stage === 'fetching') {\r\n // در مرحله fetchChats\r\n let chatOffset = +(broadcastInfo.chatOffset || '0');\r\n // اگر total هنوز -1 است، از chatOffset استفاده میکنیم\r\n // در غیر این صورت از total استفاده میکنیم\r\n let currentTotal = broadcastInfo.total === '-1' ? chatOffset : +broadcastInfo.total!;\r\n // برای نمایش درصد، از chatOffset استفاده میکنیم\r\n // اما چون total هنوز مشخص نیست، درصد را نمیتوانیم محاسبه کنیم\r\n // پس فقط تعداد چتهای fetch شده را نشان میدهیم\r\n progressText = `🔍 Fetching chats...\r\n📊 Chats fetched: ${chatOffset}/${currentTotal}`;\r\n percent = 0; // در مرحله fetching نمیتوانیم درصد دقیق بدهیم\r\n title = '🔍 Fetching Chats';\r\n } else {\r\n // در مرحله broadcasting\r\n let error = +broadcastInfo.error! || 0;\r\n let sent = +broadcastInfo.sent! || 0;\r\n let total = +broadcastInfo.total! || 0;\r\n percent = total > 0 ? ((error + sent) / total) : 0;\r\n const currentRate = this.rateLimiter.getCurrentRate();\r\n progressText = buildProgressText(error, sent, total, currentRate);\r\n title = finished ? '✅ Broadcast Finished' : '⌛ Broadcasting';\r\n }\r\n\r\n let replyMarkup = new InlineKeyboard()\r\n .text(buildProgressBtnText(percent), `brd:progress:${broadcastInfo.id}`)\r\n .row()\r\n .text(\"Pause\", `brd:pause:${broadcastInfo.id}`)\r\n .text('Stop', `brd:stop:${broadcastInfo.id}`)\r\n\r\n if (finished) {\r\n await api.sendMessage(broadcastInfo.chat_id, `${title}\r\n${progressText}`);\r\n return;\r\n }\r\n let msgId = this.reportIds[broadcastInfo.id];\r\n if (!msgId) {\r\n let msg = await api.sendMessage(broadcastInfo.chat_id, `${title}\r\n${progressText}`, {\r\n reply_markup: replyMarkup\r\n });\r\n this.reportIds[broadcastInfo.id] = msg.message_id;\r\n this.lastReports[broadcastInfo.id] = new Date();\r\n } else {\r\n let lastReport = this.lastReports[broadcastInfo.id];\r\n if (lastReport && Date.now() - lastReport.getTime() < this.options.reportFrequency!) {\r\n return;\r\n }\r\n await api.editMessageText(broadcastInfo.chat_id, msgId, `${title}\r\n${progressText}`, {\r\n reply_markup: replyMarkup\r\n });\r\n this.lastReports[broadcastInfo.id] = new Date();\r\n }\r\n\r\n\r\n }\r\n\r\n async sendToChat(chatId: string, broadcastInfo: BroadcastInfo): Promise<boolean> {\r\n let msgIds = broadcastInfo.message_ids?.split('_').map((e) => parseInt(e));\r\n let api = await this.options.getApi(+broadcastInfo.botId);\r\n try {\r\n let msgId;\r\n const paidBroadcastOptions: any = this.options.allowPaidBroadcast ? {allow_paid_broadcast: true} : {};\r\n\r\n if (broadcastInfo.type === 'text') {\r\n let msg = await api.sendMessage(chatId, broadcastInfo.text!, paidBroadcastOptions);\r\n msgId = msg.message_id;\r\n } else if (broadcastInfo.type === 'forward') {\r\n let msgs = await api.forwardMessages(chatId, broadcastInfo.chat_id, msgIds!, paidBroadcastOptions);\r\n msgId = msgs.pop().message_id;\r\n } else if (broadcastInfo.type === 'copy') {\r\n let msgs = await api.copyMessages(chatId, broadcastInfo.chat_id, msgIds!, paidBroadcastOptions);\r\n msgId = msgs.pop().message_id;\r\n }\r\n if (broadcastInfo.pin) {\r\n await api.pinChatMessage(chatId, msgId, {disable_notification: true, ...paidBroadcastOptions});\r\n }\r\n // Rate limiting is now handled at the sendBroadcast level, so no need for waitTime here\r\n return true;\r\n } catch (err) {\r\n let retry = await this.handleError(+broadcastInfo.botId, chatId, err);\r\n if (retry) {\r\n await this.sendToChat(chatId, broadcastInfo);\r\n return true;\r\n }\r\n return false;\r\n }\r\n\r\n }\r\n\r\n async handleError(botId: number, chatId: string, error: Error | GrammyError): Promise<boolean> {\r\n try {\r\n const message = 'description' in error ? error.description : error.message;\r\n const errorMessage = (message).toLowerCase();\r\n const setRestricted = this.options.setRestricted?.bind(null, botId, chatId) || ((reason) => {\r\n console.log(`ChatId: ${chatId} is restricted for reason: ${reason} you didn't handled this error`);\r\n });\r\n if (errorMessage.includes('blocked')) {\r\n setRestricted('block');\r\n }\r\n if (errorMessage.includes('deactivated')) {\r\n setRestricted('deactivated');\r\n }\r\n if (errorMessage.includes('kicked')) {\r\n setRestricted('banned');\r\n }\r\n if (errorMessage.includes('restricted')) {\r\n setRestricted('restricted');\r\n }\r\n if (errorMessage.includes('initiate conversation')) {\r\n setRestricted('no-conv')\r\n }\r\n if ('parameters' in error) {\r\n if (error.parameters.retry_after) {\r\n const retryAfter = error.parameters.retry_after;\r\n console.log(`Rate limited by Telegram for ${retryAfter} secs`)\r\n await sleep(retryAfter * 1000);\r\n\r\n // Reduce rate limit to avoid hitting limits again\r\n // Reduce more aggressively if we hit limits multiple times quickly\r\n const now = Date.now();\r\n const timeSinceLastLimit = now - this.lastRateLimitTime;\r\n this.lastRateLimitTime = now;\r\n\r\n // If we hit limits multiple times in short period, reduce more\r\n if (timeSinceLastLimit < 60000) { // Within 1 minute\r\n this.rateLimiter.reduceRate(0.5); // Reduce to 50%\r\n } else {\r\n this.rateLimiter.reduceRate(0.7); // Reduce to 70%\r\n }\r\n\r\n return true;\r\n }\r\n }\r\n } catch (err) {\r\n console.log(\"HandlerError error: \", err);\r\n } finally {\r\n }\r\n\r\n // todo: more errors\r\n return false;\r\n }\r\n\r\n\r\n}\r\n","import {BroadcastInfo, BroadcastOptions} from \"./types\";\r\n\r\n\r\nexport class ChatsFetcher {\r\n constructor(private options: BroadcastOptions) {\r\n }\r\n\r\n async fetchChats(broadcast: BroadcastInfo, progressCallback?: (info: BroadcastInfo) => Promise<void>) {\r\n let chatOffset = +(broadcast.chatOffset || '0')\r\n\r\n // گزارش شروع fetch\r\n if (progressCallback) {\r\n await progressCallback(broadcast);\r\n }\r\n\r\n while (true) {\r\n let chatIds = await this.options.getBroadcastChats(+broadcast.botId, chatOffset, this.options.chunkSize!, broadcast.chatFilter);\r\n await this.options.storage.rpush(this.options.keyPrefix + 'chats:' + broadcast.id, ...chatIds.map(String));\r\n \r\n chatOffset += chatIds.length;\r\n broadcast.chatOffset = chatOffset.toString();\r\n await this.options.storage.hset(this.options.keyPrefix + 'info:' + broadcast.id, 'chatOffset', chatOffset.toString());\r\n \r\n // گزارش پیشرفت در هر chunk\r\n if (progressCallback) {\r\n await progressCallback(broadcast);\r\n }\r\n \r\n if (chatIds.length < this.options.chunkSize!) {\r\n await this.options.storage.hset(this.options.keyPrefix + 'info:' + broadcast.id, 'total', chatOffset.toString());\r\n broadcast.total = chatOffset.toString();\r\n break;\r\n }\r\n }\r\n\r\n\r\n }\r\n}\r\n\r\n\r\n\r\n\r\n\r\n","/**\r\n * Abstract Storage class that defines the interface for storage operations\r\n * Used for broadcast queue management\r\n */\r\nexport abstract class Storage {\r\n /**\r\n * Get a range of items from a list\r\n * @param key List key\r\n * @param start Start index (0-based)\r\n * @param end End index (-1 for all)\r\n * @returns Array of string values\r\n */\r\n abstract lrange(key: string, start: number, end: number): Promise<string[]>;\r\n\r\n /**\r\n * Get all fields and values from a hash\r\n * @param key Hash key\r\n * @returns Object with field-value pairs\r\n */\r\n abstract hgetall(key: string): Promise<Record<string, string>>;\r\n\r\n /**\r\n * Remove items from a list\r\n * @param key List key\r\n * @param count Number of items to remove (0 for all, positive for first N, negative for last N)\r\n * @param value Value to remove\r\n * @returns Promise that resolves when done\r\n */\r\n abstract lrem(key: string, count: number, value: string): Promise<void>;\r\n\r\n /**\r\n * Pop items from the left side of a list\r\n * @param key List key\r\n * @param count Number of items to pop\r\n * @returns Array of popped values or null if list is empty\r\n */\r\n abstract lpop(key: string, count: number): Promise<string[] | null>;\r\n\r\n /**\r\n * Delete one or more keys\r\n * @param keys Key(s) to delete\r\n * @returns Promise that resolves when done\r\n */\r\n abstract del(...keys: string[]): Promise<void>;\r\n\r\n /**\r\n * Increment a hash field by a value\r\n * @param key Hash key\r\n * @param field Field name\r\n * @param increment Increment value\r\n * @returns Promise that resolves when done\r\n */\r\n abstract hincrby(key: string, field: string, increment: number): Promise<void>;\r\n\r\n /**\r\n * Set hash field(s)\r\n * @param key Hash key\r\n * @param fieldOrObject Field name or object with field-value pairs\r\n * @param value Value (if field is a string)\r\n * @returns Promise that resolves when done\r\n */\r\n abstract hset(key: string, fieldOrObject: string | Record<string, string>, value?: string): Promise<void>;\r\n\r\n /**\r\n * Get a hash field value\r\n * @param key Hash key\r\n * @param field Field name\r\n * @returns Field value or null if not found\r\n */\r\n abstract hget(key: string, field: string): Promise<string | null>;\r\n\r\n /**\r\n * Delete one or more hash fields\r\n * @param key Hash key\r\n * @param fields Field name(s) to delete\r\n * @returns Promise that resolves when done\r\n */\r\n abstract hdel(key: string, ...fields: string[]): Promise<void>;\r\n\r\n /**\r\n * Push values to the right side of a list\r\n * @param key List key\r\n * @param values Values to push\r\n * @returns Promise that resolves when done\r\n */\r\n abstract rpush(key: string, ...values: string[]): Promise<void>;\r\n}\r\n","import {Redis} from \"ioredis\";\r\nimport {Storage} from \"../storage\";\r\n\r\n/**\r\n * Redis storage implementation using ioredis\r\n */\r\nexport class RedisStorage extends Storage {\r\n constructor(private redis: Redis) {\r\n super();\r\n }\r\n\r\n async lrange(key: string, start: number, end: number): Promise<string[]> {\r\n return await this.redis.lrange(key, start, end);\r\n }\r\n\r\n async hgetall(key: string): Promise<Record<string, string>> {\r\n return await this.redis.hgetall(key);\r\n }\r\n\r\n async lrem(key: string, count: number, value: string): Promise<void> {\r\n await this.redis.lrem(key, count, value);\r\n }\r\n\r\n async lpop(key: string, count: number): Promise<string[] | null> {\r\n const result = await this.redis.lpop(key, count);\r\n if (result === null) return null;\r\n return Array.isArray(result) ? result : [result];\r\n }\r\n\r\n async del(...keys: string[]): Promise<void> {\r\n await this.redis.del(...keys);\r\n }\r\n\r\n async hincrby(key: string, field: string, increment: number): Promise<void> {\r\n await this.redis.hincrby(key, field, increment);\r\n }\r\n\r\n async hset(key: string, fieldOrObject: string | Record<string, string>, value?: string): Promise<void> {\r\n if (typeof fieldOrObject === 'string') {\r\n await this.redis.hset(key, fieldOrObject, value!);\r\n } else {\r\n await this.redis.hset(key, fieldOrObject);\r\n }\r\n }\r\n\r\n async hget(key: string, field: string): Promise<string | null> {\r\n return await this.redis.hget(key, field);\r\n }\r\n\r\n async hdel(key: string, ...fields: string[]): Promise<void> {\r\n await this.redis.hdel(key, ...fields);\r\n }\r\n\r\n async rpush(key: string, ...values: string[]): Promise<void> {\r\n await this.redis.rpush(key, ...values);\r\n }\r\n}\r\n","import {Storage} from \"../storage\";\r\n\r\n/**\r\n * Memory storage implementation using in-memory data structures\r\n */\r\nexport class MemoryStorage extends Storage {\r\n private lists: Map<string, string[]> = new Map();\r\n private hashes: Map<string, Map<string, string>> = new Map();\r\n\r\n async lrange(key: string, start: number, end: number): Promise<string[]> {\r\n const list = this.lists.get(key) || [];\r\n const actualEnd = end === -1 ? list.length : end + 1;\r\n return list.slice(start, actualEnd);\r\n }\r\n\r\n async hgetall(key: string): Promise<Record<string, string>> {\r\n const hash = this.hashes.get(key);\r\n if (!hash) return {};\r\n const result: Record<string, string> = {};\r\n hash.forEach((value, field) => {\r\n result[field] = value;\r\n });\r\n return result;\r\n }\r\n\r\n async lrem(key: string, count: number, value: string): Promise<void> {\r\n const list = this.lists.get(key);\r\n if (!list) return;\r\n\r\n if (count === 0) {\r\n // Remove all occurrences\r\n const filtered = list.filter(item => item !== value);\r\n this.lists.set(key, filtered);\r\n } else if (count > 0) {\r\n // Remove first N occurrences\r\n let removed = 0;\r\n const filtered = list.filter(item => {\r\n if (item === value && removed < count) {\r\n removed++;\r\n return false;\r\n }\r\n return true;\r\n });\r\n this.lists.set(key, filtered);\r\n } else {\r\n // Remove last N occurrences\r\n let removed = 0;\r\n const filtered = list.reverse().filter(item => {\r\n if (item === value && removed < Math.abs(count)) {\r\n removed++;\r\n return false;\r\n }\r\n return true;\r\n }).reverse();\r\n this.lists.set(key, filtered);\r\n }\r\n }\r\n\r\n async lpop(key: string, count: number): Promise<string[] | null> {\r\n const list = this.lists.get(key);\r\n if (!list || list.length === 0) return null;\r\n\r\n const popped = list.splice(0, count);\r\n if (list.length === 0) {\r\n this.lists.delete(key);\r\n }\r\n return popped;\r\n }\r\n\r\n async del(...keys: string[]): Promise<void> {\r\n for (const key of keys) {\r\n this.lists.delete(key);\r\n this.hashes.delete(key);\r\n }\r\n }\r\n\r\n async hincrby(key: string, field: string, increment: number): Promise<void> {\r\n let hash = this.hashes.get(key);\r\n if (!hash) {\r\n hash = new Map();\r\n this.hashes.set(key, hash);\r\n }\r\n const currentValue = hash.get(field) || '0';\r\n const newValue = (parseInt(currentValue, 10) + increment).toString();\r\n hash.set(field, newValue);\r\n }\r\n\r\n async hset(key: string, fieldOrObject: string | Record<string, string>, value?: string): Promise<void> {\r\n let hash = this.hashes.get(key);\r\n if (!hash) {\r\n hash = new Map();\r\n this.hashes.set(key, hash);\r\n }\r\n\r\n if (typeof fieldOrObject === 'string') {\r\n hash.set(fieldOrObject, value!);\r\n } else {\r\n Object.entries(fieldOrObject).forEach(([field, val]) => {\r\n hash!.set(field, val);\r\n });\r\n }\r\n }\r\n\r\n async hget(key: string, field: string): Promise<string | null> {\r\n const hash = this.hashes.get(key);\r\n if (!hash) return null;\r\n return hash.get(field) || null;\r\n }\r\n\r\n async hdel(key: string, ...fields: string[]): Promise<void> {\r\n const hash = this.hashes.get(key);\r\n if (!hash) return;\r\n fields.forEach(field => hash.delete(field));\r\n if (hash.size === 0) {\r\n this.hashes.delete(key);\r\n }\r\n }\r\n\r\n async rpush(key: string, ...values: string[]): Promise<void> {\r\n let list = this.lists.get(key);\r\n if (!list) {\r\n list = [];\r\n this.lists.set(key, list);\r\n }\r\n list.push(...values);\r\n }\r\n}\r\n","import {Storage} from \"../storage\";\r\nimport * as fs from \"fs/promises\";\r\nimport * as path from \"path\";\r\n\r\n/**\r\n * File storage implementation using filesystem\r\n */\r\nexport class FileStorage extends Storage {\r\n private baseDir: string;\r\n\r\n constructor(baseDir: string = \"./broadcast-storage\") {\r\n super();\r\n this.baseDir = baseDir;\r\n }\r\n\r\n private async ensureDir(): Promise<void> {\r\n try {\r\n await fs.mkdir(this.baseDir, {recursive: true});\r\n } catch (error) {\r\n // Directory might already exist\r\n }\r\n }\r\n\r\n private getListPath(key: string): string {\r\n return path.join(this.baseDir, `list_${key.replace(/[^a-zA-Z0-9]/g, '_')}.json`);\r\n }\r\n\r\n private getHashPath(key: string): string {\r\n return path.join(this.baseDir, `hash_${key.replace(/[^a-zA-Z0-9]/g, '_')}.json`);\r\n }\r\n\r\n private async readList(key: string): Promise<string[]> {\r\n await this.ensureDir();\r\n const filePath = this.getListPath(key);\r\n try {\r\n const content = await fs.readFile(filePath, 'utf-8');\r\n return JSON.parse(content);\r\n } catch (error) {\r\n return [];\r\n }\r\n }\r\n\r\n private async writeList(key: string, list: string[]): Promise<void> {\r\n await this.ensureDir();\r\n const filePath = this.getListPath(key);\r\n if (list.length === 0) {\r\n try {\r\n await fs.unlink(filePath);\r\n } catch (error) {\r\n // File might not exist\r\n }\r\n } else {\r\n await fs.writeFile(filePath, JSON.stringify(list), 'utf-8');\r\n }\r\n }\r\n\r\n private async readHash(key: string): Promise<Record<string, string>> {\r\n await this.ensureDir();\r\n const filePath = this.getHashPath(key);\r\n try {\r\n const content = await fs.readFile(filePath, 'utf-8');\r\n return JSON.parse(content);\r\n } catch (error) {\r\n return {};\r\n }\r\n }\r\n\r\n private async writeHash(key: string, hash: Record<string, string>): Promise<void> {\r\n await this.ensureDir();\r\n const filePath = this.getHashPath(key);\r\n if (Object.keys(hash).length === 0) {\r\n try {\r\n await fs.unlink(filePath);\r\n } catch (error) {\r\n // File might not exist\r\n }\r\n } else {\r\n await fs.writeFile(filePath, JSON.stringify(hash), 'utf-8');\r\n }\r\n }\r\n\r\n async lrange(key: string, start: number, end: number): Promise<string[]> {\r\n const list = await this.readList(key);\r\n const actualEnd = end === -1 ? list.length : end + 1;\r\n return list.slice(start, actualEnd);\r\n }\r\n\r\n async hgetall(key: string): Promise<Record<string, string>> {\r\n return await this.readHash(key);\r\n }\r\n\r\n async lrem(key: string, count: number, value: string): Promise<void> {\r\n const list = await this.readList(key);\r\n if (count === 0) {\r\n const filtered = list.filter(item => item !== value);\r\n await this.writeList(key, filtered);\r\n } else if (count > 0) {\r\n let removed = 0;\r\n const filtered = list.filter(item => {\r\n if (item === value && removed < count) {\r\n removed++;\r\n return false;\r\n }\r\n return true;\r\n });\r\n await this.writeList(key, filtered);\r\n } else {\r\n let removed = 0;\r\n const filtered = list.reverse().filter(item => {\r\n if (item === value && removed < Math.abs(count)) {\r\n removed++;\r\n return false;\r\n }\r\n return true;\r\n }).reverse();\r\n await this.writeList(key, filtered);\r\n }\r\n }\r\n\r\n async lpop(key: string, count: number): Promise<string[] | null> {\r\n const list = await this.readList(key);\r\n if (list.length === 0) return null;\r\n\r\n const popped = list.splice(0, count);\r\n await this.writeList(key, list);\r\n return popped;\r\n }\r\n\r\n async del(...keys: string[]): Promise<void> {\r\n for (const key of keys) {\r\n const listPath = this.getListPath(key);\r\n const hashPath = this.getHashPath(key);\r\n try {\r\n await fs.unlink(listPath);\r\n } catch (error) {\r\n // File might not exist\r\n }\r\n try {\r\n await fs.unlink(hashPath);\r\n } catch (error) {\r\n // File might not exist\r\n }\r\n }\r\n }\r\n\r\n async hincrby(key: string, field: string, increment: number): Promise<void> {\r\n const hash = await this.readHash(key);\r\n const currentValue = hash[field] || '0';\r\n hash[field] = (parseInt(currentValue, 10) + increment).toString();\r\n await this.writeHash(key, hash);\r\n }\r\n\r\n async hset(key: string, fieldOrObject: string | Record<string, string>, value?: string): Promise<void> {\r\n const hash = await this.readHash(key);\r\n if (typeof fieldOrObject === 'string') {\r\n hash[fieldOrObject] = value!;\r\n } else {\r\n Object.assign(hash, fieldOrObject);\r\n }\r\n await this.writeHash(key, hash);\r\n }\r\n\r\n async hget(key: string, field: string): Promise<string | null> {\r\n const hash = await this.readHash(key);\r\n return hash[field] || null;\r\n }\r\n\r\n async hdel(key: string, ...fields: string[]): Promise<void> {\r\n const hash = await this.readHash(key);\r\n fields.forEach(field => delete hash[field]);\r\n await this.writeHash(key, hash);\r\n }\r\n\r\n async rpush(key: string, ...values: string[]): Promise<void> {\r\n const list = await this.readList(key);\r\n list.push(...values);\r\n await this.writeList(key, list);\r\n }\r\n}\r\n","import {BroadcastOptions, Defaults} from \"./types\";\r\n\r\nimport {getMiddleware} from \"./middleware\";\r\nimport {BroadcastQueue} from \"./broadcast.queue\";\r\n\r\n// Export storage classes\r\nexport {Storage} from \"./storage\";\r\nexport {RedisStorage, MemoryStorage, FileStorage} from \"./storage/index\";\r\n\r\nconst defaultOptions: Defaults<BroadcastOptions> = {\r\n chunkSize: 100,\r\n keyPrefix: 'brdc:',\r\n reportFrequency: 60 * 1000,\r\n progressCallback: null,\r\n setRestricted: null,\r\n checkQueueInterval: 60 * 1000,\r\n hasPermission: null,\r\n allowPaidBroadcast: false,\r\n cmds: {\r\n broadcast: 'broadcast',\r\n copy: 'copy',\r\n forward: 'forward',\r\n addmsg: 'addmsg'\r\n }\r\n}\r\n\r\nclass Broadcaster {\r\n static _instance?: Broadcaster;\r\n\r\n private constructor(private options: BroadcastOptions) {\r\n\r\n }\r\n\r\n static getInstance(options: BroadcastOptions) {\r\n if (Broadcaster._instance) {\r\n return Broadcaster._instance;\r\n }\r\n let instance = new Broadcaster(options);\r\n const queue = new BroadcastQueue(options);\r\n queue.checkBroadcasts().then(() => {\r\n });\r\n Broadcaster._instance = instance;\r\n return instance;\r\n }\r\n\r\n getMiddleware() {\r\n return getMiddleware(this.options);\r\n }\r\n\r\n\r\n}\r\n\r\nexport function createBroadcaster(options: BroadcastOptions) {\r\n const allOptions = {\r\n ...defaultOptions,\r\n cmds: {\r\n ...defaultOptions.cmds,\r\n ...options.cmds\r\n },\r\n ...options\r\n }\r\n return Broadcaster.getInstance(allOptions);\r\n}"],"mappings":"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","names":["_a","InlineKeyboard","InlineKeyboard"]}
|
|
1
|
+
{"version":3,"sources":["../src/middleware.ts","../src/utils.ts","../src/broadcast.queue.ts","../src/initChats.queue.ts","../src/storage.ts","../src/storage/redis.storage.ts","../src/storage/memory.storage.ts","../src/storage/file.storage.ts","../src/index.ts"],"sourcesContent":["import {Composer, Context, InlineKeyboard} from \"grammy\";\nimport {BroadcastOptions} from \"./types\";\nimport {buildProgressText} from \"./utils\";\n\nexport function getMiddleware(options: BroadcastOptions) {\n const middleware = new Composer();\n\n\n let broadcastMiddleware: Composer<Context>;\n if (options.sudoUsers?.length) {\n broadcastMiddleware = middleware.filter((ctx) => {\n if (ctx.from?.id) {\n return options.sudoUsers.includes(ctx.from.id)\n }\n return false;\n })\n } else if (typeof options.hasPermission === 'function') {\n broadcastMiddleware = middleware.filter(options.hasPermission)\n } else {\n broadcastMiddleware = middleware;\n }\n broadcastMiddleware.command([options.cmds.broadcast, options.cmds.copy, options.cmds.forward], async (ctx) => {\n let [command, ...args] = ctx.message!.text.substring(1).split(' ');\n let type: string;\n let filter: string;\n if (command === options.cmds.broadcast) {\n if (args.length < 1) {\n return ctx.reply(`Usage: /${options.cmds.broadcast} <type> [filter]\n\n\\`type\\` should be copy or forward\n\\`filter\\` is anything that want to passed to getBroadcastChats\n`, {\n parse_mode: \"Markdown\",\n })\n }\n type = args[0];\n filter = args.slice(1).join(' ')\n } else if (command === options.cmds.copy) {\n type = 'copy';\n filter = args.join(' ')\n } else if (command === options.cmds.forward) {\n type = 'forward';\n filter = args.join(' ')\n }\n\n if (!['copy', 'forward'].includes(type)) {\n return ctx.reply(`Invalid type ${type}`)\n }\n\n let brdId = Math.random().toString(36).substring(7);\n if (!ctx.message!.reply_to_message) {\n return ctx.reply('Reply to a message')\n }\n await options.storage.hset(options.keyPrefix + 'info:' + brdId, {\n type: type,\n chatFilter: filter,\n message_ids: ctx.message!.reply_to_message?.message_id.toString(),\n chat_id: ctx.chat.id.toString(),\n user_id: ctx.from!.id.toString(),\n id: brdId,\n error: '0',\n sent: '0',\n botId: ctx.me.id.toString(),\n total: '-1'\n });\n return ctx.reply(`\nReady to broadcast!\ncurrently 1 message is in queue\nfor send multi message in this broadcast reply this command to another message\n<code>/${options.cmds.addmsg} ${brdId}</code>\n`, {\n parse_mode: \"HTML\",\n reply_markup: new InlineKeyboard()\n .text('Preview', 'brd:preview:' + brdId)\n .text('Pin', `brd:pin:${brdId}`)\n .row()\n .text('Start', 'brd:start:' + brdId)\n .text('Cancel', 'brd:stop:' + brdId)\n })\n })\n\n broadcastMiddleware.command(options.cmds.addmsg, async (ctx) => {\n let args = ctx.message!.text.split(' ').slice(1);\n if (args.length < 1) {\n return ctx.reply(`Usage: /${options.cmds.addmsg} <id>`)\n }\n let brdId = args[0];\n if (!ctx.message!.reply_to_message) {\n return ctx.reply('Reply to a message')\n }\n let newMsgId = ctx.message!.reply_to_message?.message_id;\n let messageIds = await options.storage.hget(options.keyPrefix + 'info:' + brdId, 'message_ids');\n if (!messageIds) {\n return ctx.reply('Broadcast not found');\n }\n let currentIds = messageIds.split('_').map((e: string) => Number.parseInt(e));\n if (Math.max(newMsgId, ...currentIds) !== newMsgId) {\n return ctx.reply('Message should be newer than previous messages')\n }\n if (currentIds.includes(newMsgId)) {\n return ctx.reply('Message already in queue')\n }\n currentIds.push(newMsgId);\n\n await options.storage.hset(options.keyPrefix + 'info:' + brdId, 'message_ids', currentIds.join('_'));\n let isPin = await options.storage.hget(options.keyPrefix + 'info:' + brdId, 'pin');\n return ctx.reply(`Message added to queue\n\nMessages Count ${currentIds.length}`, {\n reply_markup: new InlineKeyboard()\n .text('Preview', 'brd:preview:' + brdId)\n .text(`Pin${isPin ? ' ✅' : ''}`, `brd:pin:${brdId}`)\n .row()\n .text('Start', 'brd:start:' + brdId)\n .text('Cancel', 'brd:stop:' + brdId)\n })\n });\n\n\n broadcastMiddleware.callbackQuery(/brd:progress:(\\w+)/, async (ctx) => {\n let info = await options.storage.hgetall(options.keyPrefix + 'info:' + ctx.match[1]);\n return ctx.answerCallbackQuery(\n {\n text: buildProgressText(+info.error, +info.sent, +info.total),\n show_alert: true\n }\n )\n\n });\n broadcastMiddleware.callbackQuery(/brd:pause:(\\w+)/, async (ctx) => {\n await options.storage.hset(options.keyPrefix + 'info:' + ctx.match[1], 'paused', '1');\n return ctx.editMessageText('Broadcast paused!', {\n reply_markup: new InlineKeyboard()\n\n .text('Resume', 'brd:resume:' + ctx.match[1])\n .text('Stop', 'brd:stop:' + ctx.match[1])\n });\n\n });\n broadcastMiddleware.callbackQuery(/brd:resume:(\\w+)/, async (ctx) => {\n await options.storage.hdel(options.keyPrefix + 'info:' + ctx.match[1], 'paused');\n return ctx.editMessageText(\n \"Lets begin...\", {\n reply_markup: new InlineKeyboard()\n .text('Pause', 'brd:pause:' + ctx.match[1])\n .text('Stop', 'brd:stop:' + ctx.match[1])\n });\n });\n broadcastMiddleware.callbackQuery(/brd:pin:(\\w+)/, async (ctx) => {\n let brdId = ctx.match[1];\n let isPin = await options.storage.hget(options.keyPrefix + 'info:' + brdId, 'pin');\n if (isPin) {\n await options.storage.hdel(options.keyPrefix + 'info:' + brdId, 'pin');\n } else {\n await options.storage.hset(options.keyPrefix + 'info:' + brdId, 'pin', '1');\n }\n return ctx.editMessageReplyMarkup({\n reply_markup: new InlineKeyboard()\n .text('Preview', 'brd:preview:' + brdId)\n .text(`Pin${(!isPin) ? ' ✅' : ''}`, `brd:pin:${brdId}`)\n .row()\n .text('Start', 'brd:start:' + brdId)\n .text('Cancel', 'brd:stop:' + brdId)\n\n })\n });\n broadcastMiddleware.callbackQuery(/brd:preview:(\\w+)/, async (ctx) => {\n let info = await options.storage.hgetall(options.keyPrefix + 'info:' + ctx.match[1]);\n if (!info.message_ids) {\n return;\n }\n let messageIds = info.message_ids.split('_').map((e: string) => Number.parseInt(e));\n if (info.type === 'copy') {\n let msgs = await ctx.copyMessages(info.chat_id, messageIds)\n if (info.pin) {\n await ctx.pinChatMessage(msgs.pop().message_id)\n }\n } else if (info.type === 'forward') {\n let msgs = await ctx.forwardMessages(info.chat_id, messageIds)\n if (info.pin) {\n await ctx.pinChatMessage(msgs.pop().message_id)\n }\n }\n });\n broadcastMiddleware.callbackQuery(/brd:start:(\\w+)/, async (ctx) => {\n let id = ctx.match[1];\n await options.storage.rpush(options.keyPrefix + 'list', id);\n return ctx.editMessageText(`Broadcast added to queue it takes some time to start...`, {\n reply_markup: new InlineKeyboard()\n .text('Pause', 'brd:pause:' + id)\n .text('Stop', 'brd:stop:' + id)\n });\n });\n broadcastMiddleware.callbackQuery(/brd:stop:(\\w+)/, async (ctx) => {\n return ctx.editMessageReplyMarkup({\n reply_markup: new InlineKeyboard().text('Sure?')\n .row()\n .text('Yes', 'brd:stop_confirm:' + ctx.match[1])\n .text('No', `brd:stop_cancel:${ctx.match[1]}`)\n });\n });\n broadcastMiddleware.callbackQuery(/brd:stop_cancel/, async (ctx) => {\n return ctx.editMessageReplyMarkup(\n {\n reply_markup: new InlineKeyboard()\n .text('Pause', 'brd:pause:' + ctx.match[1])\n }\n )\n });\n broadcastMiddleware.callbackQuery(/brd:stop_confirm:(\\w+)/, async (ctx) => {\n let id = ctx.match[1];\n\n await options.storage.del(options.keyPrefix + 'chats:' + id);\n await options.storage.del(options.keyPrefix + 'info:' + id);\n await options.storage.lrem(options.keyPrefix + 'list', 1, id);\n return ctx.editMessageText('Broadcast stopped');\n });\n\n return middleware;\n}\n\n\n","export function sleep(milli: number) {\n return new Promise(resolve => {\n setTimeout(resolve, milli);\n });\n}\n\nexport function buildProgressBtnText(percent: number, chars: number = 10) {\n let progress = Math.floor(percent * chars);\n let empty = chars - progress;\n console.log({progress, empty});\n return '█'.repeat(progress) + '░'.repeat(empty) + ` (${Math.floor(percent * 1000) / 10}%)`;\n}\n\nexport function buildProgressText(error: number, sent: number, total: number, rateLimit?: number) {\n const rateText = rateLimit !== undefined ? `\\n⚡ Rate: ${rateLimit} msg/sec` : '';\n return `⌛ Progress: ${error + (sent)}/${total}\n✅ Sent: ${sent}\n❌ Error: ${error} (${Math.floor((error / total) * 10000) / 100}%)${rateText}`;\n}","import {BroadcastInfo, BroadcastOptions} from \"./types\";\nimport {GrammyError, InlineKeyboard} from \"grammy\";\nimport {buildProgressBtnText, buildProgressText, sleep} from \"./utils\";\nimport {ChatsFetcher} from \"./initChats.queue\";\n\n// Rate limiter class for concurrent requests with rate limiting\nclass RateLimiter {\n private queue: Array<() => void> = [];\n private tokens: number;\n private maxTokens: number;\n private initialMaxTokens: number;\n private refillInterval: number;\n private refillTimer: NodeJS.Timeout | null = null;\n private lastRefillTime: number = Date.now();\n\n constructor(requestsPerSecond: number) {\n this.initialMaxTokens = requestsPerSecond;\n this.maxTokens = requestsPerSecond;\n this.tokens = requestsPerSecond;\n // Refill tokens more frequently for smoother rate limiting\n // For high rates (1000/sec), refill every 10ms with appropriate tokens\n // For lower rates (30/sec), refill every 100ms\n this.refillInterval = requestsPerSecond >= 100 ? 10 : 100;\n this.startRefill();\n }\n\n getCurrentRate(): number {\n return this.maxTokens;\n }\n\n reduceRate(factor: number = 0.5): void {\n // Reduce rate by factor (default: half)\n const newRate = Math.max(1, Math.floor(this.maxTokens * factor));\n console.log(`Reducing rate limit from ${this.maxTokens}/sec to ${newRate}/sec`);\n this.maxTokens = newRate;\n // Adjust refill interval based on new rate\n this.refillInterval = newRate >= 100 ? 10 : 100;\n // Don't increase tokens beyond new max\n this.tokens = Math.min(this.tokens, this.maxTokens);\n }\n\n resetRate(): void {\n // Reset to initial rate\n if (this.maxTokens !== this.initialMaxTokens) {\n console.log(`Resetting rate limit from ${this.maxTokens}/sec to ${this.initialMaxTokens}/sec`);\n this.maxTokens = this.initialMaxTokens;\n this.refillInterval = this.initialMaxTokens >= 100 ? 10 : 100;\n this.tokens = Math.min(this.tokens, this.maxTokens);\n }\n }\n\n private startRefill() {\n if (this.refillTimer) return;\n this.refillTimer = setInterval(() => {\n const now = Date.now();\n const elapsed = now - this.lastRefillTime;\n // Calculate how many tokens to add based on elapsed time\n const tokensToAdd = Math.floor((this.maxTokens * elapsed) / 1000);\n if (tokensToAdd > 0) {\n this.tokens = Math.min(this.maxTokens, this.tokens + tokensToAdd);\n this.lastRefillTime = now;\n this.processQueue();\n }\n }, this.refillInterval);\n }\n\n private processQueue() {\n while (this.queue.length > 0 && this.tokens > 0) {\n this.tokens--;\n const resolve = this.queue.shift()!;\n resolve();\n }\n }\n\n async acquire(): Promise<void> {\n // Check if we can refill tokens based on time elapsed\n const now = Date.now();\n const elapsed = now - this.lastRefillTime;\n if (elapsed >= 1000) {\n // More than a second has passed, refill all tokens\n this.tokens = this.maxTokens;\n this.lastRefillTime = now;\n } else if (elapsed > 0) {\n // Add tokens proportionally to elapsed time\n const tokensToAdd = Math.floor((this.maxTokens * elapsed) / 1000);\n if (tokensToAdd > 0) {\n this.tokens = Math.min(this.maxTokens, this.tokens + tokensToAdd);\n this.lastRefillTime = now;\n }\n }\n\n if (this.tokens > 0) {\n this.tokens--;\n return Promise.resolve();\n }\n return new Promise((resolve) => {\n this.queue.push(resolve);\n });\n }\n\n destroy() {\n if (this.refillTimer) {\n clearInterval(this.refillTimer);\n this.refillTimer = null;\n }\n }\n}\n\nexport class BroadcastQueue {\n private reportIds: Record<string, number> = {};\n private lastReports: Record<string, Date> = {};\n private processingBroadcasts: Set<string> = new Set();\n private rateLimiter: RateLimiter;\n private lastRateLimitTime: number = 0;\n\n constructor(private options: BroadcastOptions) {\n // Initialize rate limiter: 1000/sec for paid broadcasts, 30/sec otherwise\n const requestsPerSecond = this.options.allowPaidBroadcast ? 1000 : 30;\n this.rateLimiter = new RateLimiter(requestsPerSecond);\n }\n\n async checkBroadcasts() {\n let broadcasts = await this.options.storage.lrange(this.options.keyPrefix + 'list', 0, -1);\n let newBroadcasts = broadcasts.filter(id => !this.processingBroadcasts.has(id));\n\n if (newBroadcasts.length > 0) {\n newBroadcasts.forEach(id => this.processingBroadcasts.add(id));\n Promise.all(newBroadcasts.map(broadcastId =>\n this.sendBroadcast(broadcastId).finally(() => {\n this.processingBroadcasts.delete(broadcastId);\n })\n )).catch(err => {\n console.error('Error processing broadcasts:', err);\n });\n }\n\n setTimeout(this.checkBroadcasts.bind(this), this.options.checkQueueInterval);\n }\n\n async sendBroadcast(id: string) {\n let broadcastInfo = await this.options.storage.hgetall(this.options.keyPrefix + 'info:' + id) as unknown as BroadcastInfo;\n if (broadcastInfo.total === '-1') {\n console.log(\"fetching chats\")\n let fetcher = new ChatsFetcher(this.options);\n await fetcher.fetchChats(broadcastInfo, async (info) => {\n await this.sendProgress(info, false, 'fetching');\n });\n // بهروزرسانی broadcastInfo پس از اتمام fetchChats\n broadcastInfo = await this.options.storage.hgetall(this.options.keyPrefix + 'info:' + id) as unknown as BroadcastInfo;\n }\n if (!broadcastInfo) {\n await this.options.storage.lrem(this.options.keyPrefix + 'list', 1, id);\n return;\n }\n let chats = await this.options.storage.lpop(this.options.keyPrefix + 'chats:' + id, this.options!.chunkSize!);\n\n if (broadcastInfo.paused) return;\n\n if (!chats?.length) {\n await this.options.storage.del(this.options.keyPrefix + 'chats:' + id);\n await this.options.storage.del(this.options.keyPrefix + 'info:' + id);\n await this.options.storage.lrem(this.options.keyPrefix + 'list', 1, id);\n await this.sendProgress(broadcastInfo, true);\n return;\n }\n broadcastInfo.sent = broadcastInfo.sent || '0';\n broadcastInfo.error = broadcastInfo.error || '0';\n\n // Send messages concurrently with rate limiting\n const sendPromises = chats!.map(async (chat) => {\n // Acquire rate limit token before sending\n await this.rateLimiter.acquire();\n let isSent = await this.sendToChat(chat, broadcastInfo);\n if (isSent) {\n broadcastInfo.sent = ((+broadcastInfo.sent) + 1).toString();\n await this.options.storage.hincrby(this.options.keyPrefix + 'info:' + id, 'sent', 1);\n } else {\n broadcastInfo.error = ((+broadcastInfo.error) + 1).toString();\n await this.options.storage.hincrby(this.options.keyPrefix + 'info:' + id, 'error', 1);\n }\n });\n\n await Promise.all(sendPromises);\n await this.sendProgress(broadcastInfo);\n await this.sendBroadcast(id);\n\n }\n\n async sendProgress(broadcastInfo: BroadcastInfo, finished: boolean = false, stage: 'fetching' | 'broadcasting' = 'broadcasting') {\n if (this.options.progressCallback) {\n this.options.progressCallback(\n broadcastInfo.id,\n +broadcastInfo.sent! || 0,\n +broadcastInfo.error! || 0,\n +broadcastInfo.total! || 0\n )\n return;\n }\n let api = await this.options.getApi(+broadcastInfo.botId);\n\n let progressText: string;\n let percent: number;\n let title: string;\n\n if (stage === 'fetching') {\n // در مرحله fetchChats\n let chatOffset = +(broadcastInfo.chatOffset || '0');\n // اگر total هنوز -1 است، از chatOffset استفاده میکنیم\n // در غیر این صورت از total استفاده میکنیم\n let currentTotal = broadcastInfo.total === '-1' ? chatOffset : +broadcastInfo.total!;\n // برای نمایش درصد، از chatOffset استفاده میکنیم\n // اما چون total هنوز مشخص نیست، درصد را نمیتوانیم محاسبه کنیم\n // پس فقط تعداد چتهای fetch شده را نشان میدهیم\n progressText = `🔍 Fetching chats...\n📊 Chats fetched: ${chatOffset}/${currentTotal}`;\n percent = 0; // در مرحله fetching نمیتوانیم درصد دقیق بدهیم\n title = '🔍 Fetching Chats';\n } else {\n // در مرحله broadcasting\n let error = +broadcastInfo.error! || 0;\n let sent = +broadcastInfo.sent! || 0;\n let total = +broadcastInfo.total! || 0;\n percent = total > 0 ? ((error + sent) / total) : 0;\n const currentRate = this.rateLimiter.getCurrentRate();\n progressText = buildProgressText(error, sent, total, currentRate);\n title = finished ? '✅ Broadcast Finished' : '⌛ Broadcasting';\n }\n\n let replyMarkup = new InlineKeyboard()\n .text(buildProgressBtnText(percent), `brd:progress:${broadcastInfo.id}`)\n .row()\n .text(\"Pause\", `brd:pause:${broadcastInfo.id}`)\n .text('Stop', `brd:stop:${broadcastInfo.id}`)\n\n if (finished) {\n await api.sendMessage(broadcastInfo.chat_id, `${title}\n${progressText}`);\n return;\n }\n let msgId = this.reportIds[broadcastInfo.id];\n if (!msgId) {\n let msg = await api.sendMessage(broadcastInfo.chat_id, `${title}\n${progressText}`, {\n reply_markup: replyMarkup\n });\n this.reportIds[broadcastInfo.id] = msg.message_id;\n this.lastReports[broadcastInfo.id] = new Date();\n } else {\n let lastReport = this.lastReports[broadcastInfo.id];\n if (lastReport && Date.now() - lastReport.getTime() < this.options.reportFrequency!) {\n return;\n }\n await api.editMessageText(broadcastInfo.chat_id, msgId, `${title}\n${progressText}`, {\n reply_markup: replyMarkup\n });\n this.lastReports[broadcastInfo.id] = new Date();\n }\n\n\n }\n\n async sendToChat(chatId: string, broadcastInfo: BroadcastInfo): Promise<boolean> {\n let msgIds = broadcastInfo.message_ids?.split('_').map((e) => parseInt(e));\n let api = await this.options.getApi(+broadcastInfo.botId);\n try {\n let msgId;\n const paidBroadcastOptions: any = this.options.allowPaidBroadcast ? {allow_paid_broadcast: true} : {};\n\n if (broadcastInfo.type === 'text') {\n let msg = await api.sendMessage(chatId, broadcastInfo.text!, paidBroadcastOptions);\n msgId = msg.message_id;\n } else if (broadcastInfo.type === 'forward') {\n let msgs = await api.forwardMessages(chatId, broadcastInfo.chat_id, msgIds!, paidBroadcastOptions);\n msgId = msgs.pop().message_id;\n } else if (broadcastInfo.type === 'copy') {\n let msgs = await api.copyMessages(chatId, broadcastInfo.chat_id, msgIds!, paidBroadcastOptions);\n msgId = msgs.pop().message_id;\n }\n if (broadcastInfo.pin) {\n await api.pinChatMessage(chatId, msgId, {disable_notification: true, ...paidBroadcastOptions});\n }\n // Rate limiting is now handled at the sendBroadcast level, so no need for waitTime here\n return true;\n } catch (err) {\n let retry = await this.handleError(+broadcastInfo.botId, chatId, err);\n if (retry) {\n await this.sendToChat(chatId, broadcastInfo);\n return true;\n }\n return false;\n }\n\n }\n\n async handleError(botId: number, chatId: string, error: Error | GrammyError): Promise<boolean> {\n try {\n const message = 'description' in error ? error.description : error.message;\n const errorMessage = (message).toLowerCase();\n const setRestricted = this.options.setRestricted?.bind(null, botId, chatId) || ((reason) => {\n console.log(`ChatId: ${chatId} is restricted for reason: ${reason} you didn't handled this error`);\n });\n if (errorMessage.includes('blocked')) {\n setRestricted('block');\n }\n if (errorMessage.includes('deactivated')) {\n setRestricted('deactivated');\n }\n if (errorMessage.includes('kicked')) {\n setRestricted('banned');\n }\n if (errorMessage.includes('restricted')) {\n setRestricted('restricted');\n }\n if (errorMessage.includes('initiate conversation')) {\n setRestricted('no-conv')\n }\n if ('parameters' in error) {\n if (error.parameters.retry_after) {\n const retryAfter = error.parameters.retry_after;\n console.log(`Rate limited by Telegram for ${retryAfter} secs`)\n await sleep(retryAfter * 1000);\n\n // Reduce rate limit to avoid hitting limits again\n // Reduce more aggressively if we hit limits multiple times quickly\n const now = Date.now();\n const timeSinceLastLimit = now - this.lastRateLimitTime;\n this.lastRateLimitTime = now;\n\n // If we hit limits multiple times in short period, reduce more\n if (timeSinceLastLimit < 60000) { // Within 1 minute\n this.rateLimiter.reduceRate(0.5); // Reduce to 50%\n } else {\n this.rateLimiter.reduceRate(0.7); // Reduce to 70%\n }\n\n return true;\n }\n }\n } catch (err) {\n console.log(\"HandlerError error: \", err);\n } finally {\n }\n\n // todo: more errors\n return false;\n }\n\n\n}\n","import {BroadcastInfo, BroadcastOptions} from \"./types\";\n\n\nexport class ChatsFetcher {\n constructor(private options: BroadcastOptions) {\n }\n\n async fetchChats(broadcast: BroadcastInfo, progressCallback?: (info: BroadcastInfo) => Promise<void>) {\n let chatOffset = +(broadcast.chatOffset || '0')\n\n // گزارش شروع fetch\n if (progressCallback) {\n await progressCallback(broadcast);\n }\n\n while (true) {\n let chatIds = await this.options.getBroadcastChats(+broadcast.botId, chatOffset, this.options.chunkSize!, broadcast.chatFilter);\n await this.options.storage.rpush(this.options.keyPrefix + 'chats:' + broadcast.id, ...chatIds.map(String));\n \n chatOffset += chatIds.length;\n broadcast.chatOffset = chatOffset.toString();\n await this.options.storage.hset(this.options.keyPrefix + 'info:' + broadcast.id, 'chatOffset', chatOffset.toString());\n \n // گزارش پیشرفت در هر chunk\n if (progressCallback) {\n await progressCallback(broadcast);\n }\n \n if (chatIds.length < this.options.chunkSize!) {\n await this.options.storage.hset(this.options.keyPrefix + 'info:' + broadcast.id, 'total', chatOffset.toString());\n broadcast.total = chatOffset.toString();\n break;\n }\n }\n\n\n }\n}\n\n\n\n\n\n","/**\n * Abstract Storage class that defines the interface for storage operations\n * Used for broadcast queue management\n */\nexport abstract class Storage {\n /**\n * Get a range of items from a list\n * @param key List key\n * @param start Start index (0-based)\n * @param end End index (-1 for all)\n * @returns Array of string values\n */\n abstract lrange(key: string, start: number, end: number): Promise<string[]>;\n\n /**\n * Get all fields and values from a hash\n * @param key Hash key\n * @returns Object with field-value pairs\n */\n abstract hgetall(key: string): Promise<Record<string, string>>;\n\n /**\n * Remove items from a list\n * @param key List key\n * @param count Number of items to remove (0 for all, positive for first N, negative for last N)\n * @param value Value to remove\n * @returns Promise that resolves when done\n */\n abstract lrem(key: string, count: number, value: string): Promise<void>;\n\n /**\n * Pop items from the left side of a list\n * @param key List key\n * @param count Number of items to pop\n * @returns Array of popped values or null if list is empty\n */\n abstract lpop(key: string, count: number): Promise<string[] | null>;\n\n /**\n * Delete one or more keys\n * @param keys Key(s) to delete\n * @returns Promise that resolves when done\n */\n abstract del(...keys: string[]): Promise<void>;\n\n /**\n * Increment a hash field by a value\n * @param key Hash key\n * @param field Field name\n * @param increment Increment value\n * @returns Promise that resolves when done\n */\n abstract hincrby(key: string, field: string, increment: number): Promise<void>;\n\n /**\n * Set hash field(s)\n * @param key Hash key\n * @param fieldOrObject Field name or object with field-value pairs\n * @param value Value (if field is a string)\n * @returns Promise that resolves when done\n */\n abstract hset(key: string, fieldOrObject: string | Record<string, string>, value?: string): Promise<void>;\n\n /**\n * Get a hash field value\n * @param key Hash key\n * @param field Field name\n * @returns Field value or null if not found\n */\n abstract hget(key: string, field: string): Promise<string | null>;\n\n /**\n * Delete one or more hash fields\n * @param key Hash key\n * @param fields Field name(s) to delete\n * @returns Promise that resolves when done\n */\n abstract hdel(key: string, ...fields: string[]): Promise<void>;\n\n /**\n * Push values to the right side of a list\n * @param key List key\n * @param values Values to push\n * @returns Promise that resolves when done\n */\n abstract rpush(key: string, ...values: string[]): Promise<void>;\n}\n","import {Redis} from \"ioredis\";\nimport {Storage} from \"../storage\";\n\n/**\n * Redis storage implementation using ioredis\n */\nexport class RedisStorage extends Storage {\n constructor(private redis: Redis) {\n super();\n }\n\n async lrange(key: string, start: number, end: number): Promise<string[]> {\n return await this.redis.lrange(key, start, end);\n }\n\n async hgetall(key: string): Promise<Record<string, string>> {\n return await this.redis.hgetall(key);\n }\n\n async lrem(key: string, count: number, value: string): Promise<void> {\n await this.redis.lrem(key, count, value);\n }\n\n async lpop(key: string, count: number): Promise<string[] | null> {\n const result = await this.redis.lpop(key, count);\n if (result === null) return null;\n return Array.isArray(result) ? result : [result];\n }\n\n async del(...keys: string[]): Promise<void> {\n await this.redis.del(...keys);\n }\n\n async hincrby(key: string, field: string, increment: number): Promise<void> {\n await this.redis.hincrby(key, field, increment);\n }\n\n async hset(key: string, fieldOrObject: string | Record<string, string>, value?: string): Promise<void> {\n if (typeof fieldOrObject === 'string') {\n await this.redis.hset(key, fieldOrObject, value!);\n } else {\n await this.redis.hset(key, fieldOrObject);\n }\n }\n\n async hget(key: string, field: string): Promise<string | null> {\n return await this.redis.hget(key, field);\n }\n\n async hdel(key: string, ...fields: string[]): Promise<void> {\n await this.redis.hdel(key, ...fields);\n }\n\n async rpush(key: string, ...values: string[]): Promise<void> {\n await this.redis.rpush(key, ...values);\n }\n}\n","import {Storage} from \"../storage\";\n\n/**\n * Memory storage implementation using in-memory data structures\n */\nexport class MemoryStorage extends Storage {\n private lists: Map<string, string[]> = new Map();\n private hashes: Map<string, Map<string, string>> = new Map();\n\n async lrange(key: string, start: number, end: number): Promise<string[]> {\n const list = this.lists.get(key) || [];\n const actualEnd = end === -1 ? list.length : end + 1;\n return list.slice(start, actualEnd);\n }\n\n async hgetall(key: string): Promise<Record<string, string>> {\n const hash = this.hashes.get(key);\n if (!hash) return {};\n const result: Record<string, string> = {};\n hash.forEach((value, field) => {\n result[field] = value;\n });\n return result;\n }\n\n async lrem(key: string, count: number, value: string): Promise<void> {\n const list = this.lists.get(key);\n if (!list) return;\n\n if (count === 0) {\n // Remove all occurrences\n const filtered = list.filter(item => item !== value);\n this.lists.set(key, filtered);\n } else if (count > 0) {\n // Remove first N occurrences\n let removed = 0;\n const filtered = list.filter(item => {\n if (item === value && removed < count) {\n removed++;\n return false;\n }\n return true;\n });\n this.lists.set(key, filtered);\n } else {\n // Remove last N occurrences\n let removed = 0;\n const filtered = list.reverse().filter(item => {\n if (item === value && removed < Math.abs(count)) {\n removed++;\n return false;\n }\n return true;\n }).reverse();\n this.lists.set(key, filtered);\n }\n }\n\n async lpop(key: string, count: number): Promise<string[] | null> {\n const list = this.lists.get(key);\n if (!list || list.length === 0) return null;\n\n const popped = list.splice(0, count);\n if (list.length === 0) {\n this.lists.delete(key);\n }\n return popped;\n }\n\n async del(...keys: string[]): Promise<void> {\n for (const key of keys) {\n this.lists.delete(key);\n this.hashes.delete(key);\n }\n }\n\n async hincrby(key: string, field: string, increment: number): Promise<void> {\n let hash = this.hashes.get(key);\n if (!hash) {\n hash = new Map();\n this.hashes.set(key, hash);\n }\n const currentValue = hash.get(field) || '0';\n const newValue = (parseInt(currentValue, 10) + increment).toString();\n hash.set(field, newValue);\n }\n\n async hset(key: string, fieldOrObject: string | Record<string, string>, value?: string): Promise<void> {\n let hash = this.hashes.get(key);\n if (!hash) {\n hash = new Map();\n this.hashes.set(key, hash);\n }\n\n if (typeof fieldOrObject === 'string') {\n hash.set(fieldOrObject, value!);\n } else {\n Object.entries(fieldOrObject).forEach(([field, val]) => {\n hash!.set(field, val);\n });\n }\n }\n\n async hget(key: string, field: string): Promise<string | null> {\n const hash = this.hashes.get(key);\n if (!hash) return null;\n return hash.get(field) || null;\n }\n\n async hdel(key: string, ...fields: string[]): Promise<void> {\n const hash = this.hashes.get(key);\n if (!hash) return;\n fields.forEach(field => hash.delete(field));\n if (hash.size === 0) {\n this.hashes.delete(key);\n }\n }\n\n async rpush(key: string, ...values: string[]): Promise<void> {\n let list = this.lists.get(key);\n if (!list) {\n list = [];\n this.lists.set(key, list);\n }\n list.push(...values);\n }\n}\n","import {Storage} from \"../storage\";\nimport * as fs from \"fs/promises\";\nimport * as path from \"path\";\n\n/**\n * File storage implementation using filesystem\n */\nexport class FileStorage extends Storage {\n private baseDir: string;\n\n constructor(baseDir: string = \"./broadcast-storage\") {\n super();\n this.baseDir = baseDir;\n }\n\n private async ensureDir(): Promise<void> {\n try {\n await fs.mkdir(this.baseDir, {recursive: true});\n } catch (error) {\n // Directory might already exist\n }\n }\n\n private getListPath(key: string): string {\n return path.join(this.baseDir, `list_${key.replace(/[^a-zA-Z0-9]/g, '_')}.json`);\n }\n\n private getHashPath(key: string): string {\n return path.join(this.baseDir, `hash_${key.replace(/[^a-zA-Z0-9]/g, '_')}.json`);\n }\n\n private async readList(key: string): Promise<string[]> {\n await this.ensureDir();\n const filePath = this.getListPath(key);\n try {\n const content = await fs.readFile(filePath, 'utf-8');\n return JSON.parse(content);\n } catch (error) {\n return [];\n }\n }\n\n private async writeList(key: string, list: string[]): Promise<void> {\n await this.ensureDir();\n const filePath = this.getListPath(key);\n if (list.length === 0) {\n try {\n await fs.unlink(filePath);\n } catch (error) {\n // File might not exist\n }\n } else {\n await fs.writeFile(filePath, JSON.stringify(list), 'utf-8');\n }\n }\n\n private async readHash(key: string): Promise<Record<string, string>> {\n await this.ensureDir();\n const filePath = this.getHashPath(key);\n try {\n const content = await fs.readFile(filePath, 'utf-8');\n return JSON.parse(content);\n } catch (error) {\n return {};\n }\n }\n\n private async writeHash(key: string, hash: Record<string, string>): Promise<void> {\n await this.ensureDir();\n const filePath = this.getHashPath(key);\n if (Object.keys(hash).length === 0) {\n try {\n await fs.unlink(filePath);\n } catch (error) {\n // File might not exist\n }\n } else {\n await fs.writeFile(filePath, JSON.stringify(hash), 'utf-8');\n }\n }\n\n async lrange(key: string, start: number, end: number): Promise<string[]> {\n const list = await this.readList(key);\n const actualEnd = end === -1 ? list.length : end + 1;\n return list.slice(start, actualEnd);\n }\n\n async hgetall(key: string): Promise<Record<string, string>> {\n return await this.readHash(key);\n }\n\n async lrem(key: string, count: number, value: string): Promise<void> {\n const list = await this.readList(key);\n if (count === 0) {\n const filtered = list.filter(item => item !== value);\n await this.writeList(key, filtered);\n } else if (count > 0) {\n let removed = 0;\n const filtered = list.filter(item => {\n if (item === value && removed < count) {\n removed++;\n return false;\n }\n return true;\n });\n await this.writeList(key, filtered);\n } else {\n let removed = 0;\n const filtered = list.reverse().filter(item => {\n if (item === value && removed < Math.abs(count)) {\n removed++;\n return false;\n }\n return true;\n }).reverse();\n await this.writeList(key, filtered);\n }\n }\n\n async lpop(key: string, count: number): Promise<string[] | null> {\n const list = await this.readList(key);\n if (list.length === 0) return null;\n\n const popped = list.splice(0, count);\n await this.writeList(key, list);\n return popped;\n }\n\n async del(...keys: string[]): Promise<void> {\n for (const key of keys) {\n const listPath = this.getListPath(key);\n const hashPath = this.getHashPath(key);\n try {\n await fs.unlink(listPath);\n } catch (error) {\n // File might not exist\n }\n try {\n await fs.unlink(hashPath);\n } catch (error) {\n // File might not exist\n }\n }\n }\n\n async hincrby(key: string, field: string, increment: number): Promise<void> {\n const hash = await this.readHash(key);\n const currentValue = hash[field] || '0';\n hash[field] = (parseInt(currentValue, 10) + increment).toString();\n await this.writeHash(key, hash);\n }\n\n async hset(key: string, fieldOrObject: string | Record<string, string>, value?: string): Promise<void> {\n const hash = await this.readHash(key);\n if (typeof fieldOrObject === 'string') {\n hash[fieldOrObject] = value!;\n } else {\n Object.assign(hash, fieldOrObject);\n }\n await this.writeHash(key, hash);\n }\n\n async hget(key: string, field: string): Promise<string | null> {\n const hash = await this.readHash(key);\n return hash[field] || null;\n }\n\n async hdel(key: string, ...fields: string[]): Promise<void> {\n const hash = await this.readHash(key);\n fields.forEach(field => delete hash[field]);\n await this.writeHash(key, hash);\n }\n\n async rpush(key: string, ...values: string[]): Promise<void> {\n const list = await this.readList(key);\n list.push(...values);\n await this.writeList(key, list);\n }\n}\n","import {BroadcastOptions, Defaults} from \"./types\";\n\nimport {getMiddleware} from \"./middleware\";\nimport {BroadcastQueue} from \"./broadcast.queue\";\n\n// Export storage classes\nexport {Storage} from \"./storage\";\nexport {RedisStorage, MemoryStorage, FileStorage} from \"./storage/index\";\n\nconst defaultOptions: Defaults<BroadcastOptions> = {\n chunkSize: 100,\n keyPrefix: 'brdc:',\n reportFrequency: 60 * 1000,\n progressCallback: null,\n setRestricted: null,\n checkQueueInterval: 60 * 1000,\n hasPermission: null,\n allowPaidBroadcast: false,\n cmds: {\n broadcast: 'broadcast',\n copy: 'copy',\n forward: 'forward',\n addmsg: 'addmsg'\n }\n}\n\nclass Broadcaster {\n static _instance?: Broadcaster;\n\n private constructor(private options: BroadcastOptions) {\n\n }\n\n static getInstance(options: BroadcastOptions) {\n if (Broadcaster._instance) {\n return Broadcaster._instance;\n }\n let instance = new Broadcaster(options);\n const queue = new BroadcastQueue(options);\n queue.checkBroadcasts().then(() => {\n });\n Broadcaster._instance = instance;\n return instance;\n }\n\n getMiddleware() {\n return getMiddleware(this.options);\n }\n\n\n}\n\nexport function createBroadcaster(options: BroadcastOptions) {\n const allOptions = {\n ...defaultOptions,\n cmds: {\n ...defaultOptions.cmds,\n ...options.cmds\n },\n ...options\n }\n return Broadcaster.getInstance(allOptions);\n}"],"mappings":"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","names":["_a","InlineKeyboard","InlineKeyboard"]}
|
package/package.json
CHANGED
|
@@ -1,33 +1,33 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "grammy-broadcast",
|
|
3
|
-
"version": "2.0.
|
|
4
|
-
"description": "A package for sending broadcast to chats using grammy",
|
|
5
|
-
"main": "./dist/index.js",
|
|
6
|
-
"module": "./dist/index.mjs",
|
|
7
|
-
"types": "./dist/index.d.ts",
|
|
8
|
-
"files": [
|
|
9
|
-
"dist"
|
|
10
|
-
],
|
|
11
|
-
"scripts": {
|
|
12
|
-
"build": "tsup",
|
|
13
|
-
"prepare": "npm run build"
|
|
14
|
-
},
|
|
15
|
-
"repository": {
|
|
16
|
-
"type": "git",
|
|
17
|
-
"url": "https://github.com/smaznet/grammy-broadcast.git"
|
|
18
|
-
},
|
|
19
|
-
"author": "Aria <smaznet98@gmail.com>",
|
|
20
|
-
"license": "MIT",
|
|
21
|
-
"peerDependencies": {
|
|
22
|
-
"grammy": "^1.22.4",
|
|
23
|
-
"ioredis": "^5.4.1"
|
|
24
|
-
},
|
|
25
|
-
"devDependencies": {
|
|
26
|
-
"@types/ioredis": "^5.0.0",
|
|
27
|
-
"grammy": "^1.22.4",
|
|
28
|
-
"ioredis": "^5.4.1",
|
|
29
|
-
"tsup": "8.3.5",
|
|
30
|
-
"typescript": "^5.4.5",
|
|
31
|
-
"@types/node": "^20.12.10"
|
|
32
|
-
}
|
|
33
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "grammy-broadcast",
|
|
3
|
+
"version": "2.0.3",
|
|
4
|
+
"description": "A package for sending broadcast to chats using grammy",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"module": "./dist/index.mjs",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"files": [
|
|
9
|
+
"dist"
|
|
10
|
+
],
|
|
11
|
+
"scripts": {
|
|
12
|
+
"build": "tsup",
|
|
13
|
+
"prepare": "npm run build"
|
|
14
|
+
},
|
|
15
|
+
"repository": {
|
|
16
|
+
"type": "git",
|
|
17
|
+
"url": "https://github.com/smaznet/grammy-broadcast.git"
|
|
18
|
+
},
|
|
19
|
+
"author": "Aria <smaznet98@gmail.com>",
|
|
20
|
+
"license": "MIT",
|
|
21
|
+
"peerDependencies": {
|
|
22
|
+
"grammy": "^1.22.4",
|
|
23
|
+
"ioredis": "^5.4.1"
|
|
24
|
+
},
|
|
25
|
+
"devDependencies": {
|
|
26
|
+
"@types/ioredis": "^5.0.0",
|
|
27
|
+
"grammy": "^1.22.4",
|
|
28
|
+
"ioredis": "^5.4.1",
|
|
29
|
+
"tsup": "8.3.5",
|
|
30
|
+
"typescript": "^5.4.5",
|
|
31
|
+
"@types/node": "^20.12.10"
|
|
32
|
+
}
|
|
33
|
+
}
|