leech / bot /modules /broadcast.py
dragxd's picture
Initial commit: Push project to Hugging Face
db78256
from asyncio import sleep
from time import time
from secrets import token_hex
from pyrogram.errors import FloodWait, InputUserDeactivated, UserIsBlocked
from ..core.config_manager import Config
from ..core.tg_client import TgClient
from ..helper.ext_utils.bot_utils import new_task
from ..helper.ext_utils.db_handler import database
from ..helper.ext_utils.status_utils import get_readable_time
from ..helper.telegram_helper.message_utils import (
edit_message,
send_message,
)
bc_cache = {}
async def delete_broadcast(bc_id, message):
"""Delete broadcasted messages based on the broadcast ID."""
if bc_id not in bc_cache:
return await send_message(message, "Invalid Broadcast ID!")
temp_wait = await send_message(
message, "<i>Deleting the Broadcasted Message! Please Wait ...</i>"
)
total, success, failed = 0, 0, 0
msgs = bc_cache.get(bc_id, [])
for uid, msg_id in msgs:
try:
await (await TgClient.bot.get_messages(uid, msg_id)).delete()
success += 1
except FloodWait as e:
await sleep(e.value)
await (await TgClient.bot.get_messages(uid, msg_id)).delete()
success += 1
except Exception as e:
print(f"Error deleting message for user {uid}: {e}")
failed += 1
total += 1
return await edit_message(
temp_wait,
f"""⌬ <b><i>Broadcast Deleted Stats :</i></b>
┠ <b>Total Users:</b> <code>{total}</code>
┠ <b>Success:</b> <code>{success}</code>
┖ <b>Failed Attempts:</b> <code>{failed}</code>
<b>Broadcast ID:</b> <code>{bc_id}</code>""",
)
async def edit_broadcast(bc_id, message, rply):
"""Edit broadcasted messages based on the broadcast ID."""
if bc_id not in bc_cache:
return await send_message(message, "Invalid Broadcast ID!")
temp_wait = await send_message(
message, "<i>Editing the Broadcasted Message! Please Wait ...</i>"
)
total, success, failed = 0, 0, 0
for uid, msg_id in bc_cache[bc_id]:
msg = await TgClient.bot.get_messages(uid, msg_id)
if hasattr(msg, "forward_from"):
return await edit_message(
temp_wait,
"<i>Forwarded Messages can't be Edited, Only can be Deleted!</i>",
)
try:
await msg.edit(
text=rply.text,
entities=rply.entities,
reply_markup=rply.reply_markup,
)
await sleep(0.3)
success += 1
except FloodWait as e:
await sleep(e.value)
await msg.edit(
text=rply.text,
entities=rply.entities,
reply_markup=rply.reply_markup,
)
success += 1
except Exception as e:
print(f"Error editing message for user {uid}: {e}")
failed += 1
total += 1
return await edit_message(
temp_wait,
f"""⌬ <b><i>Broadcast Edited Stats :</i></b>
┠ <b>Total Users:</b> <code>{total}</code>
┠ <b>Success:</b> <code>{success}</code>
┖ <b>Failed Attempts:</b> <code>{failed}</code>
<b>Broadcast ID:</b> <code>{bc_id}</code>""",
)
@new_task
async def broadcast(_, message):
"""Handle different broadcast actions: send, edit, delete, or forward."""
bc_id, forwarded, quietly, deleted, edited = "", False, False, False, False
if not Config.DATABASE_URL:
return await send_message(
message, "DATABASE_URL not provided to fetch PM Users!"
)
rply = message.reply_to_message
if len(message.command) > 1:
if not message.command[1].startswith("-"):
bc_id = (
message.command[1] if bc_cache.get(message.command[1], False) else ""
)
if not bc_id:
return await send_message(
message,
"<i>Broadcast ID not found! After Restart, you can't edit or delete broadcasted messages...</i>",
)
for arg in message.command:
if arg in ["-f", "-forward"] and rply:
forwarded = True
if arg in ["-q", "-quiet"] and rply:
quietly = True
elif arg in ["-d", "-delete"] and bc_id:
deleted = True
elif arg in ["-e", "-edit"] and bc_id and rply:
edited = True
if not bc_id and not rply:
return await send_message(
message,
"""<b>By replying to msg to Broadcast:</b>
/broadcast bc_id -d -e -f -q
<b>Forward Broadcast with Tag:</b> -f or -forward
/cmd [reply_msg] -f
<b>Quietly Broadcast msg:</b> -q or -quiet
/cmd [reply_msg] -q -f
<b>Edit Broadcast msg:</b> -e or -edit
/cmd [reply_edited_msg] broadcast_id -e
<b>Delete Broadcast msg:</b> -d or -delete
/bc broadcast_id -d
<b>Notes:</b>
1. Broadcast msgs can be only edited or deleted until restart.
2. Forwarded msgs can't be Edited""",
)
if deleted:
return await delete_broadcast(bc_id, message)
elif edited:
return await edit_broadcast(bc_id, message, rply)
# Broadcasting logic
start_time = time()
status = """⌬ <b><i>Broadcast Stats :</i></b>
┠ <b>Total Users:</b> <code>{t}</code>
┠ <b>Success:</b> <code>{s}</code>
┠ <b>Blocked Users:</b> <code>{b}</code>
┠ <b>Deleted Accounts:</b> <code>{d}</code>
┖ <b>Unsuccess Attempt:</b> <code>{u}</code>"""
updater = time()
bc_hash, bc_msgs = token_hex(5), []
pls_wait = await send_message(message, status.format(t=0, s=0, b=0, d=0, u=0))
t, s, b, d, u = 0, 0, 0, 0, 0
for uid in await database.get_pm_uids():
try:
bc_msg = (
await rply.forward(uid, disable_notification=quietly)
if forwarded
else await rply.copy(uid, disable_notification=quietly)
)
s += 1
except FloodWait as e:
await sleep(e.value * 1.1)
bc_msg = (
await rply.forward(uid, disable_notification=quietly)
if forwarded
else await rply.copy(uid, disable_notification=quietly)
)
s += 1
except UserIsBlocked:
await database.rm_pm_user(uid)
b += 1
except InputUserDeactivated:
await database.rm_pm_user(uid)
d += 1
except Exception as e:
print(f"Error broadcasting message to user {uid}: {e}")
u += 1
if bc_msg:
bc_msgs.append((uid, bc_msg.id))
t += 1
if (time() - updater) > 10:
await edit_message(pls_wait, status.format(t=t, s=s, b=b, d=d, u=u))
updater = time()
bc_cache[bc_hash] = bc_msgs
await edit_message(
pls_wait,
f"{status.format(t=t, s=s, b=b, d=d, u=u)}\n\n<b>Elapsed Time:</b> <code>{get_readable_time(time() - start_time)}</code>\n<b>Broadcast ID:</b> <code>{bc_hash}</code>",
)