П/ВИН

Social Media Automation: архитектура и анти-бан система

·7 мин чтения
Social Media Automation: архитектура и анти-бан система

Когда начинаешь проект по автоматизации социальных сетей, первое с чем сталкиваешься — это не «как написать код», а «как не получить бан через 10 минут после запуска». Именно этот вопрос стал центральным в нескольких итерациях разработки нашего проекта tg-army — системы для управления массовыми рассылками через Telegram.

В этой статье расскажу как мы исследовали стек, проектировали анти-бан архитектуру, реализовывали защиту по TDD и попутно чинили неожиданные проблемы вроде кодировки cp1251 в архивах с lolz.team.

Контекст: что мы строим

Проект tg-army — это оркестратор для управления фармом Telegram-аккаунтов. Основные задачи:

  • Массовая рассылка сообщений через пул аккаунтов
  • Автоматическая закупка и прогрев новых аккаунтов
  • Управление каналами и лимитами на аккаунт
  • Мониторинг состояния аккаунтов и автоматический вывод из ротации при заморозке

Стек: Python + Telethon для работы с Telegram API, PostgreSQL для хранения состояния, простой веб-интерфейс на Flask для управления.

Перед тем как двигаться вперёд, мы провели масштабное исследование — запустили параллельные поисковые агенты по 10 направлениям: статус библиотек для Instagram и TikTok, анти-детект браузеры, инструменты массовой публикации видео, MQTT для realtime-уведомлений и многое другое. Часть агентов оказалась без доступа к веб-поиску (ограничение окружения), поэтому критические исследования провели напрямую.

Один из важных выводов: instagrapi с 6000+ звёзд на GitHub всё ещё живёт и обновляется, хотя авторы активно толкают своё SaaS-решение. Для Telegram же основным инструментом остаётся Telethon — зрелая, стабильная библиотека с отличной документацией.

Главная проблема: почему аккаунты замораживаются

Самая болезненная точка в любом проекте с автоматизацией аккаунтов — это их выживаемость. Мы изучили материалы по анти-бан стратегиям (в том числе публикации профильных блогов) и нашли несколько критических ошибок в нашей реализации.

Проблема 1: Неправильный порядок setup-этапов

Мы делали так: купили аккаунт → сразу меняем аватар, имя, bio → включаем 2FA → начинаем рассылку.

Правильный порядок: купили аккаунт → 24-48 часов отлёжки → warmup 2-4 дня (читаем каналы, пишем в личку друзьям) → только потом меняем профиль → активируем для рассылки.

Тelegram фиксирует подозрительное поведение: новый аккаунт с новым IP сразу начинает менять данные профиля — это классический паттерн бота.

Проблема 2: Geo-mismatch между аккаунтом и прокси

Аккаунт зарегистрирован в России, а мы подключаем его через нидерландский прокси. Для Telegram это красный флаг. Нужна валидация: страна аккаунта должна совпадать со страной прокси.

Проблема 3: Нет имитации human-behavior

Бот отправляет сообщения мгновенно — без задержек на «печатание». Реальный человек сначала несколько секунд печатает, потом отправляет. Отсутствие этой паузы — один из самых простых сигналов для детектирования ботов.

Проблема 4: Один аккаунт в слишком многих каналах

Если аккаунт состоит в 50+ каналах — это подозрительно. Нужен лимит, например не более 20 каналов на один аккаунт.

Реализация: TDD по всем четырём задачам

Мы написали план в docs/plans/2026-03-13-anti-ban-improvements.md и реализовали его строго по TDD: сначала тест (красный), потом реализация (зелёный).

Задача 1: Geo-Match Validation

Добавили функцию validate_geo_match в account_pool.py:

def validate_geo_match(account_country: str, proxy_country: str) -> bool:
    """Проверяет совпадение страны аккаунта и прокси."""
    if not account_country or not proxy_country:
        return True  # Если нет данных — пропускаем проверку
    return account_country.lower() == proxy_country.lower()

В lolz_market.py добавили предупреждение при несовпадении, в account_setup.py — проверку в check_all(). Тест:

def test_geo_match_blocks_mismatch():
    assert validate_geo_match("RU", "NL") == False
 
def test_geo_match_allows_same_country():
    assert validate_geo_match("RU", "RU") == True
 
def test_geo_match_skips_empty():
    assert validate_geo_match("", "NL") == True

Задача 2: IP Settle Delay

Новая функция should_start_setup проверяет что прошло минимум 12 часов с момента привязки аккаунта к IP:

def should_start_setup(account_created_at: datetime, settle_hours: int = 12) -> bool:
    """Аккаунт должен 'отлежаться' на новом IP перед настройкой."""
    elapsed = datetime.utcnow() - account_created_at
    return elapsed.total_seconds() >= settle_hours * 3600

Эта проверка встроена в check_all() — если аккаунт слишком свежий, он пропускается до следующего прохода.

Задача 3: Typing Simulation

Добавили в sender.py имитацию набора текста перед отправкой сообщения:

def calc_typing_delay(text: str) -> float:
    """~40 символов в секунду, минимум 1с, максимум 8с."""
    base = len(text) / 40.0
    return max(1.0, min(8.0, base))
 
async def _simulate_typing(self, client, peer, text: str):
    delay = calc_typing_delay(text)
    async with client.action(peer, 'typing'):
        await asyncio.sleep(delay)

Эта функция вызывается перед send_text, send_photo, send_voice и _do_send для альбомов. Теперь боту нужно от 1 до 8 секунд «напечатать» сообщение — точно как живому человеку.

Задача 4: Channel-Per-Account Limit

Добавили в pg_database.py функцию подсчёта каналов на аккаунт:

async def count_account_channels(self, account_id: int) -> int:
    """Считает количество активных каналов для аккаунта."""
    result = await self.fetchval(
        "SELECT COUNT(*) FROM channel_accounts "
        "WHERE account_id = $1 AND active = true",
        account_id
    )
    return result or 0

В _select_account() и send_step() добавили проверку: если у аккаунта уже 20+ каналов — пропускаем его. Лимит настраивается через таблицу settings в БД (MAX_CHANNELS_PER_ACCOUNT, дефолт 20).

Результат: все 12 тестов зелёные

tests/test_geo_match.py ....    (4 теста)
tests/test_ip_settle.py ....    (4 теста)
tests/test_typing_sim.py ....   (4 теста)
12 passed in 0.43s

Сервис tg-army-orchestrator рестартован без ошибок, настройки вставлены в БД.

Неожиданная проблема: cp1251 в архивах lolz.team

Пока работали над анти-бан защитой, всплыла другая проблема: при попытке загрузить ZIP-архив с аккаунтами с lolz.team получали:

'utf-8' codec can't decode byte 0xc8 in position 99: invalid continuation byte

Байт 0xc8 в кодировке Windows-1251 — это буква «И». То есть в JSON-файле внутри архива было русское слово, а Python пытался читать его как UTF-8.

Проблема была в bulk_import.py:

# Было — Python открывает в системной кодировке (UTF-8 на Linux)
with open(json_file) as f:
    meta = json.load(f)

Фикс — пробуем UTF-8, при ошибке откатываемся на cp1251:

# Стало — работаем с обеими кодировками
with open(json_file, 'rb') as f:
    raw = f.read()
 
try:
    meta = json.loads(raw.decode('utf-8'))
except UnicodeDecodeError:
    meta = json.loads(raw.decode('cp1251'))

Простой двухстрочный фикс, который снимает проблему навсегда. lolz.team — один из основных маркетплейсов для покупки аккаунтов на постсоветском пространстве, и их экспорты часто идут в cp1251 из-за исторической совместимости с Windows.

UX: объединяем ZIP-импорт с основной страницей

Заодно разобрали небольшой UX-вопрос: зачем у нас два раздела /import и /import/bulk, которые делают одно и то же?

  • /import — загрузка аккаунта по одному (json+session), импорт из директории сервера, создание через HeroSMS
  • /import/bulk — загрузка ZIP-архива с пачкой аккаунтов

ZIP-загрузка — это просто «загрузка по одному, но пачкой». Логично держать это в одном месте. Сделали:

  1. Добавили карточку «ZIP-архив» на основную страницу /import
  2. Убрали ссылку «ZIP Импорт» из навбара
  3. Удалили роут /import/bulk (API-эндпоинт /api/import/bulk оставили — он нужен для обработки)

Теперь у пользователя одна страница импорта с четырьмя способами добавить аккаунты, вместо двух разрозненных разделов.

Архитектурные уроки

Первый урок: человекоподобность — это не опция, а основа. Любая система автоматизации аккаунтов, которая не имитирует поведение живого человека, имеет ограниченный срок жизни. Typing simulation, задержки между действиями, правильный порядок onboarding-шагов — всё это должно быть встроено в архитектуру с самого начала, а не добавляться постфактум. Telegram ML-модели обучены на миллиардах пользователей и очень хорошо знают как выглядит «неправильное» поведение.

Второй урок: TDD особенно ценен в проектах с внешними API. Когда пишешь тесты для calc_typing_delay или validate_geo_match — они полностью изолированы от внешних зависимостей и запускаются за миллисекунды. Это позволяет итерировать быстро и уверенно деплоить изменения. В проектах с Telegram API, где каждый тест с реальным подключением — это риск блокировки, изоляция логики особенно важна. Документация Telethon хорошо описывает как мокировать клиент для тестов.

Третий урок: кодировки — вечная боль при работе с русскоязычным контентом. cp1251 всё ещё живёт в легаси-системах, выгрузках из 1С, архивах с постсоветских маркетплейсов. Защитный паттерн «пробуй UTF-8, откатывайся на cp1251» стоит иметь в любом парсере файлов, который работает с русскоязычными данными. Python документация содержит полный список поддерживаемых кодировок.

Четвёртый урок: UX-долг накапливается незаметно. Два раздела для одного и того же действия — это кажется мелочью, но когда ты ежедневно работаешь в интерфейсе, это начинает раздражать. Маленькие UX-улучшения (объединить, убрать лишнее, упростить навигацию) стоит делать сразу когда видишь проблему, не копить.

Что дальше

Анти-бан система — это живой организм. Telegram регулярно обновляет алгоритмы детектирования, и то что работает сегодня, может перестать работать через месяц. В планах:

  • Расширить warmup-сценарии: не просто задержка, а реальная активность (чтение каналов, реакции)
  • Добавить поддержку Pyrogram-формата сессий для расширения источников закупки аккаунтов
  • Мониторинг метрик выживаемости аккаунтов по когортам (купили в одну дату — смотрим кто выжил через неделю/месяц)
  • Интеграция с PostgreSQL для аналитики по паттернам блокировок

Если работаете над похожим проектом — welcome в комменты, обсудим подходы.

Паша Вин
Паша Вин

AI-инженер, предприниматель, маркетолог. Основатель feberra.com и x10seo.ru. 13 лет в перфоманс-маркетинге, 3 года в системной интеграции AI в бизнес.