Files
furry_giffer_bot_mastodon/docs.md
2026-01-09 20:43:11 +03:00

256 lines
8.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Documentation / Документация
## EN
### 1) How the bot works
1. Poll Mastodon notifications for `mention` type (`/api/v1/notifications`).
2. For each mention:
- Extract plain text from HTML content
- Remove all mentions like `@giffer` / `@giffer@domain` / `@ giffer`
- Detect `nsfw` keyword
- Parse remaining text into tags (supports quotes and `-tag`)
3. Query Furbooru (Philomena API) for GIF images:
- SFW query adds: `safe, animated, gif`
- NSFW query adds: `animated, gif` (plus `filter_id` if configured)
4. Pick a random candidate GIF result.
5. Upload media to Mastodon:
- Try GIF representations in descending size: `full → large → medium → small → thumb`
- If Mastodon rejects GIF with 422 “not supported” / size limits:
- Convert GIF → MP4 using ffmpeg
- Upload MP4 instead
6. Wait for Mastodon media processing to finish (poll `/api/v1/media/:id`):
- prevents 422 “processing not finished” when posting the status
7. Post reply status with uploaded media:
- SFW: normal reply
- NSFW: `sensitive=True` and `spoiler_text="NSFW"` (+ configurable visibility)
8. Save state:
- `last_seen_notif_id`
- list of processed `status_id` (to avoid replying twice after restarts)
---
### 2) Query syntax
The bot converts the mention text to Furbooru tags:
- Spaces become multiple tags:
`cute fluffy tail``cute, fluffy, tail`
- Commas are also supported:
`cute, fluffy, tail`
- Quoted phrases stay together as one tag:
`"rainbow dash"``rainbow dash`
- Negative tags are supported:
`-gore``-gore`
- `random` / `rnd` are ignored and treated as no user tags (random result).
NSFW mode:
- Any mention containing the word `nsfw` enables NSFW mode and removes that word from the tag list.
---
### 3) Furbooru API notes
Endpoint used:
- `GET /api/v1/json/search/images?q=...&per_page=50&page=1`
The bot filters results:
- `format == "gif"`
- has usable `representations` URL(s)
- chooses randomly among candidates
---
### 4) ALT text generation
ALT text is generated from Furbooru tags:
- removes rating/system tags like `safe`, `nsfw`, `animated`, `gif`
- keeps up to 20 tags
- prefix:
- `Animated GIF: ...`
- `NSFW animated GIF: ...`
---
### 5) Rate limiting & anti-spam
Two layers:
1) Per-user cooldown:
- If the same user mentions the bot again within `USER_COOLDOWN_SEC`, bot skips.
2) Global token bucket:
- `GLOBAL_RATE_PER_SEC` tokens refill rate
- `GLOBAL_BURST` max burst
- applies to Furbooru requests
---
### 6) Prevent replying twice (state)
The bot persists state to `STATE_FILE` (default `giffer_state.json`):
- `last_seen_notif_id` (so it wont re-fetch old notifications after restart)
- `processed_status_ids` (cache to skip duplicates even if server repeats notifications)
If you delete the state file, the bot may reply to old mentions again.
---
### 7) Windows reliability notes
This project includes hardening for Windows:
- `socket.setdefaulttimeout(SOCKET_DEFAULT_TIMEOUT)` to prevent rare indefinite hangs
- `requests.Session` with retries
- explicit connect/read timeouts
- Mastodon API calls are wrapped with a watchdog timeout (thread executor)
---
### 8) Troubleshooting
**Bot replies “media processing not finished” / 422**
- Increase `MEDIA_PROCESS_MAX_WAIT` (e.g. 90)
- Your instance may be slow during peak hours
**GIF rejected: “1440x1440 GIF files are not supported”**
- Expected on some instances
- Bot will fallback to smaller GIF representations
- Then fallback to MP4 conversion
**MP4 conversion fails**
- Install bundled ffmpeg:
- `py -m pip install imageio-ffmpeg`
- Or install system ffmpeg and ensure its in PATH
**Bot replies to old mentions after restart**
- Check `STATE_FILE` exists and is writable
- Dont delete `giffer_state.json`
---
## RU
### 1) Как работает бот
1. Опрос уведомлений Mastodon типа `mention` (`/api/v1/notifications`).
2. Для каждого упоминания:
- Достаём текст из HTML
- Удаляем любые упоминания (`@giffer`, `@giffer@домен`, `@ giffer`)
- Определяем наличие `nsfw`
- Парсим оставшееся в теги (есть кавычки и `-тег`)
3. Запрос на Furbooru (Philomena API) за GIF:
- SFW добавляет: `safe, animated, gif`
- NSFW добавляет: `animated, gif``filter_id`, если задан)
4. Выбор случайного подходящего результата.
5. Загрузка медиа в Mastodon:
- Пробуем GIF (full → large → medium → small → thumb)
- Если инстанс отклоняет GIF с 422 (“not supported”/лимиты):
- Конвертим GIF → MP4 через ffmpeg
- Заливаем MP4
6. Ждём завершения обработки медиа в Mastodon (`/api/v1/media/:id`):
- предотвращает 422 “обработка не окончена” при публикации
7. Публикуем ответ:
- SFW: обычный ответ
- NSFW: `sensitive=True` и `spoiler_text="NSFW"` (+ настраиваемая видимость)
8. Сохраняем состояние:
- `last_seen_notif_id`
- кэш `status_id` (чтобы не отвечать повторно после рестарта)
---
### 2) Синтаксис запроса (теги)
- Пробелы = несколько тегов:
`cute fluffy tail``cute, fluffy, tail`
- Запятые тоже можно:
`cute, fluffy, tail`
- Кавычки сохраняют фразу как один тег:
`"rainbow dash"``rainbow dash`
- Минус-теги работают:
`-gore``-gore`
- `random` / `rnd` игнорируются (рандомный результат).
NSFW-режим:
- Если в тексте есть слово `nsfw`, включается NSFW и это слово убирается из тегов.
---
### 3) Про Furbooru API
Используем:
- `GET /api/v1/json/search/images?q=...&per_page=50&page=1`
Фильтруем результаты:
- `format == "gif"`
- есть рабочие ссылки `representations`
- выбираем случайно
---
### 4) ALT-текст
ALT строится из тегов Furbooru:
- выкидываются системные/рейтинг-теги `safe`, `nsfw`, `animated`, `gif`
- берём до 20 тегов
- префикс:
- `Animated GIF: ...`
- `NSFW animated GIF: ...`
---
### 5) Антиспам / Rate-limit
1) Кулдаун на пользователя (`USER_COOLDOWN_SEC`)
2) Глобальный token-bucket (`GLOBAL_RATE_PER_SEC`, `GLOBAL_BURST`)
---
### 6) Защита от повторных ответов (state)
Файл `STATE_FILE` (по умолчанию `giffer_state.json`) хранит:
- `last_seen_notif_id`
- `processed_status_ids`
Если удалить state-файл — бот может снова отвечать на старые упоминания.
---
### 7) Особенности Windows
Усиленная защита от “вечных зависаний”:
- `socket.setdefaulttimeout(...)`
- `requests.Session` с retry
- явные таймауты connect/read
- watchdog-таймаут вокруг вызовов Mastodon API
---
### 8) Типовые проблемы
**422 “обработка файлов не окончена”**
- увеличь `MEDIA_PROCESS_MAX_WAIT` (например до 90)
- инстанс может быть медленным
**“1440x1440 GIF files are not supported”**
- ожидаемо для некоторых инстансов
- бот уйдёт на меньшие версии GIF, потом на MP4
**Не конвертится в MP4**
- поставь `imageio-ffmpeg`:
- `py -m pip install imageio-ffmpeg`
- или установи ffmpeg в систему и добавь в PATH
**После рестарта отвечает на старые упоминания**
- проверь, что `giffer_state.json` не удаляется и доступен на запись
---
### 9) Рекомендуемая структура репо
- `giffer_bot.py`
- `README.md`
- `docs.md`
- `.gitignore` (исключить `config.env`, `giffer_state.json`, `*.log`)
- `LICENSE`