# meta-puller

Тянет **свои** посты из Instagram и Threads вместе с метриками, копит историю в
SQLite и раскладывает два архива в волт — чтобы контент-планёрка разбирала эти
площадки так же, как разбирает телеграм-канал.

Родня: `tgstat-puller` (то же самое для ТГ-канала), `feedwatch` (то же самое,
но для чужих аккаунтов).

## Что собирается

**Instagram:** просмотры, охват, лайки, комментарии, сохранения, шеры, а для
ленты ещё подписки и заходы в профиль. Тип контента (рилс / карусель / фото)
пишется явно: охваты у них несопоставимы, поэтому медиана считается **внутри
типа**.

**Threads:** просмотры, лайки, ответы, репосты, цитаты, шеры.

Сторис не собираются — это отдельная работа (у них 24 часа жизни и свой
ритм опроса).

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

- Первый прогон забирает **год истории**: старые посты приходят с уже
  устоявшимися метриками, поэтому медиана работает сразу, а не через месяц.
- Дальше каждый прогон добавляет новые посты и обновляет метрики за последние
  **30 дней** — именно в этом окне цифры ещё заметно растут.
- Медианы считаются при рендере и кладутся готовыми в шапку архива. У планёрки
  одна точка истины, она их не пересчитывает.
- Токены живут 60 дней и обновляются сами на 50-й день. Если обновиться не
  вышло — на 53-й день придёт предупреждение в телеграм, чтобы осталось время
  переавторизоваться руками.
- Три упавших прогона подряд → алерт в телеграм. Одиночный сбой сети не тревожит.

## Установка

```bash
cd ~/Projects/meta-puller
python3 -m venv venv && ./venv/bin/pip install -r requirements.txt
cp .env.example .env      # заполнить
```

### Приложение Meta (разово, руками)

Кликать придётся самой — это личный аккаунт, и Meta требует подтверждения в
браузере. **Из России сайты Meta без VPN не открываются.**

1. На `developers.facebook.com` создать приложение. Оба сценария —
   **«Доступ к Threads API»** и **«Управление сообщениями и контентом в
   Instagram»** — выбираются сразу при создании, они совместимы.
2. Добавить разрешения на статистику: `instagram_business_manage_insights` и
   `threads_manage_insights`. **В обязательный набор они не входят**, а без
   них API отдаёт посты без охватов и сохранений — считать медиану не из чего.
3. Подключить аккаунт: **«Роли в приложении» → «Добавить людей» → «Тестировщик
   Instagram»** (и отдельным заходом «Тестировщик Threads»), затем принять
   приглашение в самом аккаунте — Instagram: Настройки → «Приложения и сайты»
   → «Приглашения тестировщиков»; Threads: Настройки → «Разрешения сайтов».

   Кнопка «Добавить аккаунт» в разделе «Сгенерируйте маркеры доступа» для
   этого не годится: она отдаёт **429** и ждать бесполезно. Роль тестировщика —
   рабочий путь, после принятия приглашения аккаунт появляется в списке сам.
4. Получить маркеры. Instagram: «Настройка API для входа в Instagram» → шаг 2 →
   «Сгенерировать маркер». Threads: «Настройки» сценария Threads → «Генератор
   маркеров пользователя» → «Сгенерировать маркер доступа». Оба сразу
   долгоживущие, на 60 дней. Вставить их:

```bash
./venv/bin/python setup_auth.py instagram --paste
./venv/bin/python setup_auth.py threads --paste
```

Ввод скрыт — маркер не попадёт ни на экран, ни в историю команд. Секрет
приложения и redirect URI для этого пути не нужны: обновление токена идёт по
самому токену.

Запасной путь — OAuth, если маркера в дашборде почему-то нет. Тогда заполнить
в `.env` `META_IG_APP_ID`/`META_IG_APP_SECRET` (и такую же пару для Threads),
прописать redirect URI в настройках приложения символ в символ и запустить те
же команды **без** `--paste`: скрипт напечатает ссылку, ты подтвердишь доступ
в браузере и вставишь код из адресной строки. Код живёт считаные минуты и
срабатывает один раз.

## Запуск

```bash
bash run.sh                    # обычный прогон
./venv/bin/python cli.py       # то же самое без обёртки
./venv/bin/python -m pytest tests/ -q
```

## Расписание на Pi

```
sudo cp deploy/meta-puller.{service,timer} /etc/systemd/system/
sudo systemctl daemon-reload && sudo systemctl enable --now meta-puller.timer
systemctl list-timers meta-puller.timer
```

Ежедневно в 07:00 MSK — метрики растут неделями, и нужен их ход, а не снимок в
момент планёрки. Планёрка (воскресенье, 18:00) читает уже собранное.

## Что оно кладёт в волт

```
projects/channel/{channel} {source} Instagram архив постов.md
projects/channel/{channel} {source} Threads архив постов.md
```

Имена без даты — как у `{channel} {source} TGStat архив постов канала.md`: это
постоянно перезаписываемые архивы, а не снапшоты.

## Известные ограничения

- **Ход метрик задним числом недоступен.** Бэкфилл отдаёт сегодняшние цифры
  старых постов; как они росли — API не расскажет.
- **Только свои аккаунты.** Охват и сохранения Meta показывает лишь владельцу;
  для чужих аккаунтов есть `feedwatch`.
- **Комментарии не собираются** — только их количество.
- Meta признана экстремистской организацией и запрещена на территории РФ.
