Бот, добавляющий в ЧС за кружки
Traffic Cardinal Traffic Cardinal  написал 19.01.2026

Бот, добавляющий в ЧС за кружки

Traffic Cardinal Traffic Cardinal  написал 19.01.2026
10 мин
0
25
Содержание

Кружки в чатах — это прекрасно, ведь они добавляют общению иммерсивности. Да только одно дело, когда кружки отправляет кто-то, от кого вы их ждете. Например, Юрьевич. И совсем другое, когда кто-то ими спамит 24/7. Конечно, кружки всегда можно отключить. Но что если вы хотите отключать их не у всех, а только у спамеров? Тут-то и приходит на помощь наш бот.

banner banner

Какие задачи решает бот, добавляющий в ЧС за кружки

Из названия очевидно — добавляет в ЧС за отправку кружков. Но как он тогда понимает, кому можно отправлять кружки, а кому нельзя? Все просто: по умолчанию нельзя всем. Даже вам, но бот не сможет вас забанить, если вы админ и не выдали ему права на бан админов. Но есть белый список, и тем, кто в него внесен, отправлять кружки можно. Их бот трогать не будет. Для чего это нужно? Ну например, для:

  • Борьбы со спамерами.

  • Чтобы не потерять ни один кружок от Е. Ю.

  • Чтоб оставить возможность отправки кружков только тем, кому вы готовы ее предоставить. Например, сотрудникам вашей партнерки, если речь про чат ПП.

А в целом для чего придумаете, для того и нужно. Каких-то ограничений, «пляшущих» от ситуации, у бота нет.

Принцип работы бота для добавления в ЧС за кружки

С точки зрения алгоритма он тоже несложный и делает вот что:

  1. Слушает эфир.
  2. Автоматически создает папку whitelist (если ее еще нет) и .txt с ID чата в имени (если такого еще нет) для хранения списка тех, кому можно отправлять кружки, по триггеру — любое сообщение в чате (где бот админ).
  3. При обнаружении сообщений с кружком — удаляет его и банит отправителя, если его ID отсутствует в .txt, хранящем список тех, кому можно отправлять кружки в данном чате.
  4. При получении в ЛС какого-либо сообщения проверяет, есть ли его отправить в списке админов (список вшит в код для безопасности). Если нет — игнорирует. Если да — реагирует на команды.
  5. При вводе /list — выводит список чатов, для которых подключен БС.
  6. При вводе /all — «выбирает» все чаты.
  7. При вводе /set ID чата — «выбирает» указанный чат.
  8. При вводе /add ID юзера — добавляет юзера в БС выбранного чата.
  9. При вводе /del ID юзера — удаляет юзера из БС выбранного чата.
  10. Выводит сервисные сообщения о банах в консоль — для дополнительного мониторинга.

Как видите, все просто.

Пошаговая инструкция, как сделать бот для добавления в ЧС за кружки

Не сложно и создать данный бот. Но сначала нужно настроить сервак для работы с Телегой (север должен поддерживать Python). Если у вас такого нет — здесь способ развернуть такой бесплатно на своем ПК. Но в целом сгодится и арендный (вообще он предпочтительнее — вы же не будете гонять домашний ПК 24/7). Затем в консоль сервера пишем:

pip install aiogram

После этого делаем следующее:

1. Пишем в ЛС BotFather — и получаем токен для нашего бота.

2. В корневом каталоге сервера создаем bot.py

3. Открываем в текстовом редакторе и копируем в него:

import asyncio

import os

from aiogram import Bot, Dispatcher, F

from aiogram.types import Message

from aiogram.filters import Command

TOKEN = "ВАШ ТОКЕН"

CONTROL_USERS = {ВАШ ID,}

WHITELIST_DIR = "whitelists"

os.makedirs(WHITELIST_DIR, exist_ok=True)

bot = Bot(token=TOKEN)

dp = Dispatcher()

selected_chat: dict[int, str] = {}

def whitelist_path(chat_id: str) -> str:

return os.path.join(WHITELIST_DIR, f"{chat_id}.txt")

def ensure_whitelist_exists(chat_id: str):

path = whitelist_path(chat_id)

if not os.path.exists(path):

open(path, "w", encoding="utf-8").close()

def load_whitelist(chat_id: str) -> set[int]:

ensure_whitelist_exists(chat_id)

with open(whitelist_path(chat_id), "r", encoding="utf-8") as f:

return {int(line.strip()) for line in f if line.strip().isdigit()}

def save_whitelist(chat_id: str, data: set[int]):

ensure_whitelist_exists(chat_id)

with open(whitelist_path(chat_id), "w", encoding="utf-8") as f:

for uid in sorted(data):

f.write(f"{uid}\n")

def get_all_chats() -> list[str]:

return sorted(

f.replace(".txt", "")

for f in os.listdir(WHITELIST_DIR)

if f.endswith(".txt")

)

def is_control_user(user_id: int) -> bool:

return user_id in CONTROL_USERS

async def ensure_chat_registered(message: Message):

if message.chat.type in {"group", "supergroup"}:

try:

member = await bot.get_chat_member(message.chat.id, bot.id)

if member.status in {"administrator", "creator"}:

ensure_whitelist_exists(str(message.chat.id))

except Exception:

pass

@dp.message(F.video_note, F.chat.type.in_({"group", "supergroup"}))

async def handle_video_note(message: Message):

user = message.from_user

if not user:

return

chat_id = message.chat.id

whitelist = load_whitelist(str(chat_id)) # загружаем из файла

if user.id in whitelist:

return

try:

await bot.ban_chat_member(chat_id=chat_id, user_id=user.id)

await message.delete()

print(f"[BAN] {user.id} в чате {chat_id}")

except Exception as e:

print(f"[ERROR BAN] {e}")

@dp.message(F.chat.type.in_({"group", "supergroup"}))

async def any_message_hook(message: Message):

await ensure_chat_registered(message)

@dp.message(Command("list"), F.chat.type == "private")

async def cmd_list(message: Message):

if not is_control_user(message.from_user.id):

return

chats = get_all_chats()

if not chats:

await message.answer("Чаты ещё не обнаружены")

return

text = ["Чаты с whitelist:"]

for chat_id in chats:

wl = load_whitelist(chat_id)

text.append(f"{chat_id} — {len(wl)} ID")

await message.answer("\n".join(text))

@dp.message(Command("set"), F.chat.type == "private")

async def cmd_set(message: Message):

if not is_control_user(message.from_user.id):

return

parts = message.text.split()

if len(parts) != 2:

await message.answer("Использование:\n/set <chat_id>")

return

chat_id = parts[1]

ensure_whitelist_exists(chat_id)

selected_chat[message.from_user.id] = chat_id

await message.answer(f"Выбран чат:\n{chat_id}")

@dp.message(Command("all"), F.chat.type == "private")

async def cmd_all(message: Message):

if not is_control_user(message.from_user.id):

return

selected_chat[message.from_user.id] = "ALL"

await message.answer("Выбраны все чаты")

@dp.message(Command("add"), F.chat.type == "private")

async def cmd_add(message: Message):

if not is_control_user(message.from_user.id):

return

parts = message.text.split()

if len(parts) != 2 or not parts[1].isdigit():

await message.answer("Использование:\n/add <user_id>")

return

uid = int(parts[1])

target = selected_chat.get(message.from_user.id)

if not target:

await message.answer("Сначала выбери чат: /set или /all")

return

chats = get_all_chats() if target == "ALL" else [target]

for chat_id in chats:

wl = load_whitelist(chat_id)

wl.add(uid)

save_whitelist(chat_id, wl)

await message.answer(f"ID {uid} добавлен")

@dp.message(Command("del"), F.chat.type == "private")

async def cmd_del(message: Message):

if not is_control_user(message.from_user.id):

return

parts = message.text.split()

if len(parts) != 2 or not parts[1].isdigit():

await message.answer("Использование:\n/del <user_id>")

return

uid = int(parts[1])

target = selected_chat.get(message.from_user.id)

if not target:

await message.answer("Сначала выбери чат: /set или /all")

return

chats = get_all_chats() if target == "ALL" else [target]

for chat_id in chats:

wl = load_whitelist(chat_id)

wl.discard(uid)

save_whitelist(chat_id, wl)

await message.answer(f"ID {uid} удалён")

async def main():

await dp.start_polling(bot)

if __name__ == "__main__":

asyncio.run(main())

4. Находим TOKEN = "ВАШ ТОКЕН" и подставляем ваш токен.

5. Находим CONTROL_USERS = {ВАШ ID,} и подставляем ваш ID (или несколько через запятую.

6. Запускаем бот командой python bot.py

7. Проверяем, все ли работает.

Демонстрация работы

Обязательно делаем бота админом в чатах, которые он будет админить, иначе ничего не будет работать.

Видим, что в папке whitelists пусто (вообще, у вас этой папки и не будет, пока вы не запустите бот впервые)
Видим, что в папке whitelists пусто (вообще, у вас этой папки и не будет, пока вы не запустите бот впервые)


Создаем чат, в котором будет вестись фильтрация кружков. Инициируем создание БС, написав в него любое сообщение
Создаем чат, в котором будет вестись фильтрация кружков. Инициируем создание БС, написав в него любое сообщение

Создаем второй чат, в котором будет вестись фильтрация кружков. Инициируем создание БС, написав в него любое сообщение. Видим, что файла стало два
Создаем второй чат, в котором будет вестись фильтрация кружков. Инициируем создание БС, написав в него любое сообщение. Видим, что файла стало два

Пишем /list — видим, что в обоих файлах 0 ID. Вносим себя (просто для демонстрации)
Пишем /list — видим, что в обоих файлах 0 ID. Вносим себя (просто для демонстрации)

Добавляем в оба чата по 2 страницы. Итого 4 участника — мы сами, бот и 2 профиля
Добавляем в оба чата по 2 страницы. Итого 4 участника — мы сами, бот и 2 профиля

Добавляем в БС каждого чата по 1 ID — для каждого разный
Добавляем в БС каждого чата по 1 ID — для каждого разный

Попутно проверяем, как бот отображает количество ID в белых листах
Попутно проверяем, как бот отображает количество ID в белых листах

Шлем кружки поочередно со всех трех акков
Шлем кружки поочередно со всех трех акков

Видим, что в каждом чате остается лишь по 3 человека — ведь бот банит того, кого нет в БС
Видим, что в каждом чате остается лишь по 3 человека — ведь бот банит того, кого нет в БС

Видим это и в консоли
Видим это и в консоли

Убираем из БС вторые тестовые профили, оставляя в нем только себя
Убираем из БС вторые тестовые профили, оставляя в нем только себя

Видим, что теперь бот банит и тех, чьи кружки ранее пропускал
Видим, что теперь бот банит и тех, чьи кружки ранее пропускал

И видим это же в консоли
И видим это же в консоли

Все работает.

Подводя итоги

Как видите, банить спамеров кружками, пропуская при этом кружки от Юрьевича, проще, чем кажется. Достаточно быть подписанным на Traffic Cardinal.

Здравствуйте! У вас включен блокировщик рекламы, часть сайта не будет работать!