s
🧩 Syntax:
import asyncio
import json
import os
import random
import aiogram.types
from aiogram.exceptions import TelegramBadRequest
from telethon import TelegramClient, functions, types
import text
import db
# Полная карта всех возможных репортов
REPORT_MAP = {
'idontlikeit': b'1:c',
'childabuse': b'2:c',
'violence': b'3:c',
'illegalgoods': {
'main': b'4',
'weapons': b'41:c',
'drugs': b'42:c',
'fakedocs': b'43:c',
'counterfeit': b'44:c',
'othergoods': b'45:c'
},
'illegaladultcontent': {
'main': b'5',
'childabuse': b'51:c',
'nonconsensual': b'52:c',
'otherillegal': b'53:c'
},
'personaldata': {
'main': b'6',
'privateimages': b'61:c',
'phonenumber': b'62:c',
'address': b'63:c',
'otherinfo': b'64:c'
},
'terrorism': b'7:c',
'scamorspam': {
'main': b'8',
'phishing': b'81:c',
'impersonation': b'82:c',
'fraud': b'83:c',
'spam': b'84:c'
},
'copyright': b'9:c',
'other': b'a:c',
'notillegalmbtd': b'b:c'
}
# Быстрые пресеты
QUICK_PRESETS = {
'scam': 'scamorspam>fraud',
'spam': 'scamorspam>spam',
'drugs': 'illegalgoods>drugs',
'porn': 'illegaladultcontent>otherillegal',
'personal': 'personaldata>otherinfo'
}
api_id = 11876346
api_hash = '954ec954bedb3afbf649304a5b918553'
async def mass_bot_report(
bot_username: str,
msg_to_target: str,
report_reason: str,
report_message_string: str,
message: aiogram.types.Message,
ogtext=None,
channels: list = None
) -> list:
"""
Улучшенная mass_bot_report с поддержкой:
- Публичных каналов (@username)
- Приватных каналов (t.me/+invite)
- Прямых ссылок (t.me/xxx)
- Отключение уведомлений от бота и удаление их после
- Автоматическая отписка от каналов после завершения атаки
- Пометка сообщений как прочитанных после репорта
"""
report_path = QUICK_PRESETS.get(report_reason, report_reason)
sessions = db.getReadySessions()
success, fail = 0, 0
status_lines = []
og_text = message.text if not ogtext else ogtext
current_message = message # Сообщение для вывода логов
for session_file, proxy_str in sessions:
try:
proxy_dict = text.parseProxyFromString(proxy_str)
client = TelegramClient(session_file, api_id, api_hash, proxy=proxy_dict)
await client.connect()
# 2) Быстро проверяем, авторизована ли сессия
if not await client.is_user_authorized():
status_lines.append(f"<b>🖧 {session_file}</b> — <code>Unauthorized</code>")
fail += 1
await client.disconnect() # сразу отключаемся
continue # пропускаем эту сессию
# Блок подписок с улучшенной обработкой ссылок
sub_info = []
joined_channels = []
if channels:
for channel in channels:
try:
if channel.startswith(('https://t.me/+', 't.me/+')):
invite_hash = channel.split('+')[-1]
await client(functions.messages.ImportChatInviteRequest(invite_hash))
sub_info.append(f"✓ [приватный t.me/+{invite_hash[:5]}...]")
joined_channels.append(invite_hash)
elif channel.startswith(('https://t.me/', 't.me/')):
username = channel.split('t.me/')[-1]
entity = await client.get_entity(username)
await client(functions.channels.JoinChannelRequest(entity))
sub_info.append(f"✓ t.me/{username}")
joined_channels.append(entity)
elif channel.startswith('@'):
entity = await client.get_entity(channel)
await client(functions.channels.JoinChannelRequest(entity))
sub_info.append(f"✓ {channel}")
joined_channels.append(entity)
else:
sub_info.append(f"✗ {channel} (неподдерживаемый формат)")
await asyncio.sleep(random.uniform(1, 3))
except Exception as e:
sub_info.append(f"✗ {channel} ({str(e)[:50]})")
# Основная логика репорта
bot_entity = await client.get_input_entity(bot_username)
# Отключаем уведомления
try:
await client(functions.account.UpdateNotifySettingsRequest(
peer=bot_entity,
settings=types.InputPeerNotifySettings(mute_until=2 ** 31 - 1)
))
except Exception as e:
status_lines.append(f"⚠️ Не удалось отключить уведомления: {str(e)[:50]}")
await client.send_message(bot_entity, msg_to_target)
await asyncio.sleep(3)
target_message = (await client.get_messages(bot_entity, limit=1))[0]
msg_preview = target_message.text[:15] + "..." if target_message.text else "[медиа]"
comment = text.unpackBotnetString(report_message_string) if report_message_string != "notext" else ''
result = await client(functions.messages.ReportRequest(
peer=bot_entity,
id=[target_message.id],
option=REPORT_MAP[report_path.split('>')[0]][report_path.split('>')[1]] if '>' in report_path else
REPORT_MAP[report_path],
message=comment
))
# Пометка как прочитанное
try:
await client(functions.messages.ReadHistoryRequest(
peer=bot_entity,
max_id=target_message.id
))
except Exception as e:
status_lines.append(f"⚠️ Не удалось пометить как прочитанное: {str(e)[:50]}")
status_lines.append(
f"<b>🖧 {session_file}</b>\n"
f" <b>├ Подписки: </b><code>{', '.join(sub_info) if sub_info else 'нет'}</code>\n"
f" <b>├ Report:</b> <code>отправлен (тип: {report_path})</code>\n"
f" <b>├ Message: </b><code>{msg_preview}</code>\n"
f" <b>└ Response: </b><code>{result}</code>\n"
f"<blockquote>{comment}</blockquote>"
)
success += 1
# Отписка от каналов после
for entity in joined_channels:
try:
if isinstance(entity, str): # приватный канал (invite_hash)
try:
chat = await client.get_entity(f'https://t.me/+{entity}')
await client(functions.channels.LeaveChannelRequest(chat))
except Exception as e:
status_lines.append(f"⚠️ Не удалось отписаться от приватного канала: {str(e)[:50]}")
else:
await client(functions.channels.LeaveChannelRequest(entity))
except Exception as e:
status_lines.append(f"⚠️ Не удалось отписаться от канала: {str(e)[:50]}")
await client.disconnect()
except Exception as e:
fail += 1
status_lines.append(
f"<b>🖧 {session_file}</b>\n"
f" <b>└ Ошибка: </b><code>{str(e)[:100]}</code>"
)
continue
try:
await current_message.edit_text(
f"{og_text}\n" + "\n\n".join(status_lines[-5:]), # Показываем только последние 5 записей
parse_mode="HTML"
)
except TelegramBadRequest as e:
if "MESSAGE_TOO_LONG" in str(e):
# Если сообщение слишком длинное, отправляем новое и продолжаем в нем
current_message = await current_message.answer(
"<b>Продолжение лога:</b>\n" + "\n\n".join(status_lines[-5:]),
parse_mode="HTML"
)
else:
raise
await asyncio.sleep(random.uniform(2, 5))
# Финальный отчет после обработки всех сессий
try:
await current_message.edit_text(
f"{og_text}\n" + "\n\n".join(status_lines[-10:]) + # Последние 10 записей
f"\n\n<b>Итог:</b> Успешно — <code>{success}</code>, Ошибок — <code>{fail}</code>",
parse_mode="HTML"
)
except TelegramBadRequest as e:
if "MESSAGE_TOO_LONG" in str(e):
part1 = "\n\n".join(status_lines[:len(status_lines) // 2])
part2 = "\n\n".join(status_lines[len(status_lines) // 2:])
await current_message.edit_text(
f"{og_text}\n{part1}\n\n<b>MESSAGE_TOO_LONG, продолжение в новом сообщении...</b>",
parse_mode="HTML"
)
await current_message.answer(
f"{part2}\n\n<b>Итог:</b> Успешно — <code>{success}</code>, Ошибок — <code>{fail}</code>",
parse_mode="HTML"
)
await db.addBotnetHistoryRecord(target=bot_username, report_type=report_path, sf=f"{success}/{fail}",
comment_str=report_message_string)
return [success, fail]
# Причины для репорта профиля
PROFILE_REPORT_PRESETS = {
'spam': types.InputReportReasonSpam,
'violence': types.InputReportReasonViolence,
'porn': types.InputReportReasonPornography,
'childabuse': types.InputReportReasonChildAbuse,
'fake': types.InputReportReasonFake,
'drugs': types.InputReportReasonIllegalDrugs,
'personal': types.InputReportReasonPersonalDetails,
'other': types.InputReportReasonOther,
}
async def mass_bot_profile_report(
bot_username: str,
report_reason: str,
report_message: str,
message: aiogram.types.Message,
concurrent_limit: int = 10
) -> list[int]:
ReasonClass = PROFILE_REPORT_PRESETS.get(report_reason)
if not ReasonClass:
valid = ', '.join(PROFILE_REPORT_PRESETS.keys())
raise ValueError(f"Неизвестная причина репорта: {report_reason}. Валид: {valid}")
sessions = db.getReadySessions()
sem = asyncio.Semaphore(concurrent_limit)
results = []
async def worker(session_file, proxy_str):
async with sem:
# Создаем клиент и подключаемся без контекстного менеджера
client = TelegramClient(
session_file,
api_id=11876346,
api_hash='954ec954bedb3afbf649304a5b918553',
proxy=text.parseProxyFromString(proxy_str)
)
await client.connect()
# Проверяем, авторизована ли сессия
if not await client.is_user_authorized():
await client.disconnect()
return session_file, False, f"❌ Unauthorized"
try:
entity = await client.get_input_entity(bot_username)
comment = text.unpackBotnetString(report_message) if report_message != "notext" else ''
resp = await client(functions.account.ReportPeerRequest(
peer=entity,
reason=ReasonClass(),
message=comment
))
log = f"✅ Reported: {resp} | <i>{comment}</i>"
success = True
except Exception as e:
log = f"❌ {e!r}"
success = False
# Отключаемся после работы
await client.disconnect()
return session_file, success, log
tasks = [worker(sess, proxy) for sess, proxy in sessions]
for coro in asyncio.as_completed(tasks):
session_file, ok, log = await coro
results.append((session_file, ok, log))
tail = results[-5:]
chunk = "\n\n".join(f"<b>{s}</b> — {'✅' if ok else '❌'} <blockquote>{l}</blockquote>" for s, ok, l in tail)
try:
await message.edit_text(f"{message.text}\n\n{chunk}", parse_mode="HTML")
except TelegramBadRequest:
pass
good = sum(1 for _, ok, _ in results if ok)
bad = len(results) - good
summary = "\n".join(
f"<b>{s}</b> — {'✅' if ok else '❌'} <blockquote>{l.split('|')[-1].strip()}</blockquote>"
for s, ok, l in results[-10:]
)
await message.edit_text(
f"{message.text}\n\n{summary}\n\n<b>Итог:</b> Успех {good}, Ошибок {bad}",
parse_mode="HTML"
)
await db.addBotnetHistoryRecord(
target=bot_username,
report_type=f"profile:{report_reason}",
sf=f"{good}/{bad}",
comment_str=report_message
)
return [good, bad]
async def recheckSessions() -> str:
sessions_casual, file_sessions = db.getReadySessions(), db.getBotnetSesh()
c_status_lines, s_status_lines = [], []
cs, cf = 0, 0
ss, sf = 0, 0
for session_file, proxy_str in sessions_casual:
proxy_dict = text.parseProxyFromString(proxy_str)
type, login, password, ip, port = [*proxy_str.split("@")[0].split(":"), *proxy_str.split("@")[1].split(":")]
if not (await text.checkProxy(type, login, password, ip, port)).get('success'):
c_status_lines.append(f"<b>🟡 Proxy unavail. {session_file}</b>")
cf += 1
continue
client = TelegramClient(session_file, api_id, api_hash, proxy=proxy_dict)
await client.connect()
if not await client.is_user_authorized():
c_status_lines.append(f"<b>🔴 {session_file}</b>")
cf += 1
await client.disconnect()
continue
c_status_lines.append(f"<b>🟢 {session_file}</b>")
cs += 1
_cr = '\n'.join(i for i in c_status_lines)
casualRecheckResult = f"<b>Casual-сессий {len(sessions_casual)}</b>\n" \
f"<blockquote expandable>{_cr}</blockquote>"
for session, phone, user_id, app_id, app_hash, sdk, app_version, device, name, lang_code, system_lang_code, twoFA, proxy in file_sessions:
type, login, password, ip, port = [*proxy.split("@")[0].split(":"), *proxy.split("@")[1].split(":")]
if not (await text.checkProxy(type, login, password, ip, port)).get('success'):
s_status_lines.append(f"<code>🟡 Proxy unavail. {phone}</code>")
sf += 1
continue
info = json.load(open(session, 'r', encoding='utf-8'))
session_file = info['session_file']
session_full = os.path.join(os.path.dirname(session), session_file)
client = TelegramClient(
session_full,
info['app_id'],
info['app_hash'],
device_model=info.get('sdk'),
system_version=info.get('sdk'),
app_version=info.get('app_version'),
lang_code=info.get('lang_code'),
system_lang_code=info.get('system_lang_code'),
proxy=text.parseProxyFromString(proxy)
)
await client.connect()
if not await client.is_user_authorized():
s_status_lines.append(f"<code>🔴 SS: {phone}</code>")
sf += 1
await client.disconnect()
continue
s_status_lines.append(f"<code>🟢 SS: {phone}</code>")
ss += 1
_sr = '\n'.join(i for i in s_status_lines)
seshRecheckResult = f"<b>File-сессий {len(file_sessions)}</b>\n" \
f"<blockquote expandable>{_sr}</blockquote>"
return f"{casualRecheckResult}\n\n{seshRecheckResult}"