Эй, брат, подпишись! А потом, через месяц-два, тебе приходит увед о розыгрыше от канала, про который ты даже не знаешь. Так происходит потому, большинство групп, куда вас просят вступить ваши «друзья», — продажные. В том смысле, что они изначально созданы под перепродажу. Вот и получается, что сначала вы кому-то помогаете, а потом вас в 3 часа ночи будит увед от хз какого канала. Избежать таких ситуаций поможет бот для отписок от продажных групп.
Какие задачи решает бот для отписок от продажных групп
Собственно, для решения какой задачи создан этот бот, уже написано выше. На практике же это сводится к следующему:
Отписка от групп, в которых не было активности более месяца.
Отписка от каналов, в которых не было активности более месяца.
Игнорирование ЛС.
Игнорирование каналов и групп из белых списков.
Если кого-то вдруг интересует, почему только каналы и группы, а не чаты — потому что чаты — это и есть группы.
Принцип работы бота для отписок от продажных групп
Описанное разделом выше — это то, как проявляется работа бота со стороны юзера. На стороне алгоритмов исходного кода все сводится к тому, что:
Бот слушает эфир и реагирует на команды в избранном.
Команда /add — добавляет канал или группу в белый список.
Команда /del — удаляет канал или группу из белого списка.
Команда /list — выводит белый список.
Команда /check — имитирует работу, но без таймера, выхода/отписки.
Проверяет раз в сутки список каналов и групп.
Если последнее сообщение в канале или группе было более месяца назад — выход/отписывается.
Выводит инфу о совершенных действиях в лог, в консоль и в избранное.
Как видите, ничего сложного.
Также есть еще один момент — чтоб бот в случае бага не покинул те каналы и группы, которые вам нужны, в его код зашит предохранитель, значение которого нужно будет самостоятельно вручную переключить ПОСЛЕ всех текстов.
Пошаговая инструкция, как сделать бот для отписок от продажных групп
Как обычно, начинаем с базы — сервера. Подойдет любой Python-сервак — хоть личный ноутбук (да-да, на ноуте можно поднять сервер), хоть арендный VPS. Последний, впрочем, предпочтительнее, если вы не хотите, чтоб бот отвалился посреди конфы, потому что у вас дома выключили свет.
Также сервер нужно будет настроить, введя в консоль:
pip install telethon
После этого делаем следующие шаги:
- Открываем Telegram Web.
- Находим там «API development tools».
- Получаем и запоминаем api_id и api_hash.
- Сохраняем их.
Теперь к коду бота:
1. Создаем файл bot.py и пишем в него:
import asyncio
import json
import logging
import os
from datetime import datetime, timedelta, timezone
from telethon import TelegramClient, events
API_ID = ваш API_ID
API_HASH = "ваш API_HASH"
SESSION = "session"
CHECK_DAYS = 30
CHECK_INTERVAL = 60 * 60 * 24
WHITELIST_FILE = "whitelist.json"
AUTO_LEAVE_ENABLED = False
logging.basicConfig(
filename="log.log",
level=logging.INFO,
format="%(asctime)s | %(message)s",
encoding="utf-8"
)
client = TelegramClient(SESSION, API_ID, API_HASH)
def load_whitelist():
if not os.path.exists(WHITELIST_FILE):
return []
with open(WHITELIST_FILE, "r", encoding="utf-8") as f:
return json.load(f)
def save_whitelist(data):
with open(WHITELIST_FILE, "w", encoding="utf-8") as f:
json.dump(data, f, indent=4, ensure_ascii=False)
whitelist = load_whitelist()
async def send_to_saved_messages(lines, title="EXIT REPORT"):
if not lines:
return
MAX_LEN = 3500
chunk = ""
chunks = []
for line in lines:
if len(chunk) + len(line) + 1 > MAX_LEN:
chunks.append(chunk)
chunk = line + "\n"
else:
chunk += line + "\n"
if chunk:
chunks.append(chunk)
for i, part in enumerate(chunks, 1):
await client.send_message(
"me",
f"{title} ({i}/{len(chunks)})\n\n{part}"
)
async def process(check_only=False, auto_mode=False):
print("\n=== SCAN START ===\n")
border = datetime.now(timezone.utc) - timedelta(days=CHECK_DAYS)
exit_candidates = []
async for dialog in client.iter_dialogs():
if dialog.is_user:
continue
entity = dialog.entity
if entity.id in whitelist:
continue
last_date = dialog.date
if last_date is None:
last_date = datetime(1970, 1, 1, tzinfo=timezone.utc)
if last_date.tzinfo is None:
last_date = last_date.replace(tzinfo=timezone.utc)
if last_date > border:
continue
msg = f"{dialog.name} ({entity.id}) | last: {last_date}"
print("[EXIT]", msg)
logging.info(msg)
exit_candidates.append(msg)
if auto_mode and AUTO_LEAVE_ENABLED and not check_only:
try:
await client.delete_dialog(entity)
except Exception as e:
print("ERROR:", e)
await asyncio.sleep(0.2)
if exit_candidates:
try:
await send_to_saved_messages(
exit_candidates,
title="EXIT CANDIDATES"
)
except Exception as e:
print("Saved messages error:", e)
@client.on(events.NewMessage(outgoing=True, pattern=r"^/add (\-?\d+)$"))
async def add(event):
chat_id = int(event.pattern_match.group(1))
if chat_id not in whitelist:
whitelist.append(chat_id)
save_whitelist(whitelist)
await event.reply(f"✔ added {chat_id}")
else:
await event.reply("already in whitelist")
@client.on(events.NewMessage(outgoing=True, pattern=r"^/del (\-?\d+)$"))
async def delete(event):
chat_id = int(event.pattern_match.group(1))
if chat_id in whitelist:
whitelist.remove(chat_id)
save_whitelist(whitelist)
await event.reply(f"✔ removed {chat_id}")
else:
await event.reply("not in whitelist")
@client.on(events.NewMessage(outgoing=True, pattern=r"^/list$"))
async def lst(event):
if not whitelist:
await event.reply("empty")
return
text = "WHITELIST:\n"
for i in whitelist:
try:
ent = await client.get_entity(i)
text += f"• {getattr(ent, 'title', i)} ({i})\n"
except:
text += f"• {i}\n"
await event.reply(text)
@client.on(events.NewMessage(outgoing=True, pattern=r"^/check$"))
async def check(event):
await event.reply("checking (NO DELETE MODE)")
await process(check_only=True, auto_mode=False)
await event.reply("done")
async def scheduler():
while True:
try:
await process(check_only=False, auto_mode=True)
except Exception as e:
print("SCHEDULER ERROR:", e)
await asyncio.sleep(CHECK_INTERVAL)
async def main():
await client.start()
print("RUNNING")
asyncio.create_task(scheduler())
await client.run_until_disconnected()
asyncio.run(main())
2. Прописываем вместо API_ID = ваш API_ID, API_HASH = "ваш API_HASH" свои значения.
3. Сохраняем файл.
4. Проверяем работу бота.
5. Заменяем AUTO_LEAVE_ENABLED = False на AUTO_LEAVE_ENABLED = True ПОСЛЕ проверки работоспособности. Это предохранитель.
Демонстрация работы
По понятным причинам значительная часть скриншотов будет скрыта. Увы, провести демонстрацию на тестовом акке невозможно — так как там банально будет нечего демонстрировать. Нужен акк со старыми неактивными каналами и чатами.
Подводя итоги
Как видите, защититься от продажных групп не так уж и сложно. В идеале, конечно, выписывать их ID и запоминать, кто туда зовет. Но наш бот предлагает более элегантное решение — и «другу» помочь, и себя от кучи уведов в 3 часа ночи оградить. Подписывайтесь на нашу Телегу, чтобы получать исходный код арбитражных Telegram-ботов первыми.