Skip to content

mik888em/threads

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

88 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Threads Metrics

Инструмент для сбора метрик постов Threads и загрузки их в Google Sheets.

Возможности

  • Асинхронно получает посты Threads по списку аккаунтов из листа accounts_threads, повторно используя сохранённые курсоры пагинации, чтобы не скачивать старые записи заново.
  • Запрашивает Insights только для тех постов, чьи данные устарели, и хранит отметки времени обновления в локальном состоянии.
  • Объединяет «сырые» данные постов и Insights, дополняя таблицу метрик без потери уже записанных колонок и обновляя строки по ключу account_name + post_id без дублирования.
  • Добавляет в таблицу время публикации постов, конвертируя его в часовой пояс Афин, и сортирует строки по возрастанию даты.
  • После каждой выгрузки отключает перенос текста в диапазоне и принудительно устанавливает высоту строк в 21 пиксель, чтобы таблица оставалась компактной.
  • Каждые 15 минут копирует лист Data_Po_kagdomy_posty в публичную таблицу, очищая целевой лист и выравнивая высоту строк в 21 пиксель.
  • Ведёт JSON-логирование с heartbeat-сообщениями и автоматически останавливается по таймауту, чтобы не зависать бесконечно.
  • Игнорирует аккаунты на листе accounts_threads, у которых в колонке A стоит заливка #9fc5e8, и выводит в логи список пропущенных никнеймов.
  • Для каждого ответа Threads API со статусом, отличным от 200, пишет в лог никнейм аккаунта, полный URL и текст ответа, что упрощает разбор проблемных запросов.
  • Автоматически повторяет неуспешные запросы Insights: после основного прохода запускает до трёх дополнительных попыток с паузами 20–30 секунд для каждого URL и отмечает прогресс в логах.

Требования

  • Python 3.11 или новее.
  • Учётные данные сервисного аккаунта Google с правами на чтение/запись в нужную таблицу.
  • Доступ к Threads Graph API и рабочие токены аккаунтов Threads.

Установка

python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
export PYTHONPATH=src

Конфигурация

Заполните файл .env на основе .env.example. Критичные переменные:

  • ID_GOOGLE_TABLE — идентификатор Google-таблицы с данными.
  • ID_GOOGLE_TABLE_PUBLIC_DANNYE — идентификатор публичной Google-таблицы для публикации листа Data_Po_kagdomy_posty.
  • URL_GAS_RAZVERTIVANIA — URL развёрнутого Google Apps Script.
  • GOOGLE_SERVICE_ACCOUNT_JSON — JSON-ключ сервисного аккаунта Google.
  • GOOGLE_MAX_STRING_PARSING — максимальное число строк для копирования в публичную таблицу (0 — без ограничений, значение для workflow берётся из одноимённого секрета).
  • THREADS_API_BASE_URL — базовый URL Threads Graph API (по умолчанию https://graph.threads.net, запросы выполняются к версии API v1.0).
  • THREADS_REQUEST_TIMEOUT — таймаут HTTP-запросов в секундах.
  • THREADS_CONCURRENCY — максимальное число параллельных запросов.
  • THREADS_STATE_FILE — путь к файлу состояния.
  • THREADS_METRICS_TTL_MIN — TTL метрик в минутах.
  • THREADS_RUN_TIMEOUT_MIN — максимальная продолжительность работы сервиса в минутах.

Остальные параметры можно оставить по умолчанию: запросы к API выполняются с таймаутом THREADS_REQUEST_TIMEOUT, а параллелизм ограничивается THREADS_CONCURRENCY, чтобы не превысить лимиты Threads Graph API.

Приложение не читает .env автоматически — переменные должны попасть в окружение перед запуском. В POSIX-оболочках можно сделать так:

set -a
source .env
set +a
python -m threads_metrics.main run

На Windows можно воспользоваться python-dotenv (python -m dotenv run -- python -m threads_metrics.main run) либо задать переменные вручную через set KEY=VALUE перед запуском.

Что хранят переменные окружения

  • THREADS_STATE_FILE задаёт путь к JSON-файлу, где сервис кеширует курсоры пагинации и отметки о последнем обновлении метрик.
  • THREADS_METRICS_TTL_MIN определяет, спустя сколько минут метрики считаются устаревшими и требуется новый сбор.
  • THREADS_CONCURRENCY ограничивает количество одновременных запросов к Threads Graph API и тем самым защищает от rate limit.

Локальная разработка

  • Активируйте виртуальное окружение и убедитесь, что переменная PYTHONPATH указывает на каталог src, чтобы импорты модулей работали одинаково и в тестах, и в CLI.
  • Для интерактивных экспериментов используйте python -m threads_metrics.main --help — команда выведет доступные подкоманды и опции запуска.
  • Чтобы сбросить кеш и повторно собрать все метрики, удалите файл, заданный переменной THREADS_STATE_FILE. При следующем запуске сервис создаст его заново и запросит свежие данные без использования сохранённых курсоров.

Отладка и диагностика

  • Логи пишутся в STDOUT в формате JSON; поля context.account, context.post и context.action помогут быстро понять, на каком шаге возникла ошибка.
  • Таймауты запросов регулируются THREADS_REQUEST_TIMEOUT, а количество ретраев определяется настройкой stop_after_attempt(5) в threads_metrics.threads_client. При необходимости скорректируйте её, чтобы изменить допустимое число повторов.
  • Если Threads API временно возвращает статусы вроде 403 или 5xx, сервис автоматически запустит дополнительный раунд повторов (до трёх попыток для каждого URL) и явно отметит в логах номер попытки и никнейм аккаунта.
  • Для подробной диагностики установите LOG_LEVEL=debug перед запуском — сервис будет выводить сообщения о каждом запросе и пропуске постов, что упрощает поиск проблемных мест.

Структура проекта

  • threads_metrics.main — CLI-обёртка, конфигурирование зависимостей и управление жизненным циклом сервиса (heartbeat, обработка сигналов, таймаут).
  • threads_metrics.threads_client — асинхронный клиент Threads Graph API с ретраями на httpx и семафором для ограничения параллелизма.
  • threads_metrics.google_sheets — чтение токенов и запись агрегированных метрик в Google Sheets, синхронизация с локальным состоянием.
  • threads_metrics.state_store — файловое хранилище курсоров и отметок времени, применяемое для дедупликации и TTL метрик.
  • threads_metrics.aggregation — объединение данных о постах и их Insights перед выгрузкой.

Логирование ведётся в JSON-формате (ts, level, msg, context), поэтому сбор логов интегрируется с системами наблюдаемости без дополнительной обработки.

Копирование данных в публичную таблицу

  • Команда python -m threads_metrics.sync_sheets переносит лист Data_Po_kagdomy_posty из таблицы ID_GOOGLE_TABLE в таблицу ID_GOOGLE_TABLE_PUBLIC_DANNYE.
  • Перед записью целевой лист полностью очищается, после чего переносится прямоугольный диапазон значений и устанавливается высота строк 21 пиксель для сохранения компактного вида.
  • После копирования столбец B переключается в текстовый формат, чтобы длинные идентификаторы постов сохранялись без экспоненциальной записи и потери точности.
  • При необходимости можно ограничить количество копируемых строк, задав переменную GOOGLE_MAX_STRING_PARSING; значение 0 отключает ограничение.
  • По умолчанию используется лист Data_Po_kagdomy_posty; чтобы выбрать другой лист, задайте переменную окружения SOURCE_WORKSHEET_NAME.

Запуск

python -m threads_metrics.main run

Перед выполнением убедитесь, что переменные окружения загружены согласно разделу «Конфигурация».

Команда запуска организует асинхронный сбор постов из Threads по токенам с листа accounts_threads, агрегирует метрики и записывает их на лист Data_Po_kagdomy_posty. Прогресс обработки хранится в файле состояния, а логи выводятся в формате JSON с heartbeat-сообщениями.

Как это работает

  1. Загрузка конфигурации. Переменные окружения проверяются и валидируются перед запуском; при ошибке сервис завершится с понятным сообщением.
  2. Чтение токенов и курсоров. Для каждого аккаунта берётся сохранённый курсор пагинации, чтобы продолжить с места предыдущего запуска. Строки с никнеймами, подсвеченными цветом #9fc5e8, пропускаются, чтобы не обращаться к забаненным профилям.
  3. Сбор постов. Параллельные запросы ограничены семафором, данные запрашиваются по эндпоинту https://graph.threads.net/v1.0/me/threads?fields=id,permalink,text,timestamp,media_type,media_url,like_count,repost_count,reply_count, а курсор обновляется только после успешного шага.
  4. Сбор Insights. Для каждого поста проверяется TTL; свежие записи пропускаются, а метрики запрашиваются по эндпоинту https://graph.threads.net/v1.0/{post_id}/insights?metric=views,likes,replies,reposts,quotes,shares, что заметно сокращает число запросов к API.
  5. Запись в Google Sheets. Данные сливаются с текущей таблицей: строки ищутся по сочетанию account_name и post_id, числовые метрики обновляются без создания дублей, новые колонки добавляются автоматически, а отметка updated_at обновляется при каждой выгрузке. Лист полностью перезаписывается, строки сортируются по колонке time_publish_(GR_time) (самые старые публикации сверху), перенос текста отключается, а высота строк принудительно выставляется в 21 пиксель. Текущее расположение колонок: time_publish_(GR_time), account_name, post_id, permalink, text, views, likes, replies, reposts, quotes, shares, updated_at.

Интеграция с GitHub Actions

  • Расписание (*/60 * * * *) запускает сбор каждые 60 минут, при этом блок concurrency гарантирует, что одновременно выполняется только один экземпляр workflow — новое срабатывание дождётся завершения предыдущего.
  • Workflow sheets-sync.yml каждые 15 минут синхронизирует лист Data_Po_kagdomy_posty между таблицами ID_GOOGLE_TABLE и ID_GOOGLE_TABLE_PUBLIC_DANNYE, используя тот же сервисный аккаунт и опциональный лимит строк из GOOGLE_MAX_STRING_PARSING.
  • Джобу ограничивает внешний таймаут в 100 минут, а сам сервис завершится раньше (по умолчанию через 100 минут ожидания, значение настраивается через THREADS_RUN_TIMEOUT_MIN), если зависнет или получит сигнал остановки.
  • Для локального запуска используется та же команда python -m threads_metrics.main run, поэтому отладка и CI ведут себя одинаково.

Отмена ожидающих запусков GitHub Actions

Для предотвращения накопления очереди workflow threads-metrics.yml добавлена подкоманда cancel-pending:

export GITHUB_OWNER=acme
export GITHUB_REPO=threads-metrics
export GITHUB_TOKEN=ghp_xxx
python -m threads_metrics.main cancel-pending --interval 10

Переменные окружения GITHUB_OWNER, GITHUB_REPO и GITHUB_TOKEN обязательны. Токен должен иметь доступ к GitHub Actions выбранного репозитория, чтобы читать список запусков и отправлять запросы отмены.

Скрипт раз в --interval секунд (по умолчанию 10) опрашивает GitHub REST API: ищет активные (in_progress) запуски workflow threads-metrics.yml и отменяет все ожидающие (queued). При превышении лимита запросов он использует экспоненциальный бэкофф и повторяет попытку после паузы, а на SIGINT/SIGTERM корректно завершает работу. Логи остаются в JSON-формате (ts, level, msg, context), поэтому отмена очередей вписывается в существующую систему наблюдаемости.

Тесты

pytest

Чтобы ускорить разработку, можно запускать подмножество тестов:

pytest tests/test_google_sheets.py -k update_rows

Команда выполнит только проверки, связанные с обновлением строк в Google Sheets, и позволит быстрее отлавливать регрессии в интеграции с таблицей.

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages