8.3 KiB
Documentation / Документация
EN
1) How the bot works
- Poll Mastodon notifications for
mentiontype (/api/v1/notifications). - For each mention:
- Extract plain text from HTML content
- Remove all mentions like
@giffer/@giffer@domain/@ giffer - Detect
nsfwkeyword - Parse remaining text into tags (supports quotes and
-tag)
- Query Furbooru (Philomena API) for GIF images:
- SFW query adds:
safe, animated, gif - NSFW query adds:
animated, gif(plusfilter_idif configured)
- SFW query adds:
- Pick a random candidate GIF result.
- 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
- Try GIF representations in descending size:
- Wait for Mastodon media processing to finish (poll
/api/v1/media/:id):- prevents 422 “processing not finished” when posting the status
- Post reply status with uploaded media:
- SFW: normal reply
- NSFW:
sensitive=Trueandspoiler_text="NSFW"(+ configurable visibility)
- 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/rndare ignored and treated as no user tags (random result).
NSFW mode:
- Any mention containing the word
nsfwenables 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
representationsURL(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:
- Per-user cooldown:
- If the same user mentions the bot again within
USER_COOLDOWN_SEC, bot skips.
- Global token bucket:
GLOBAL_RATE_PER_SECtokens refill rateGLOBAL_BURSTmax 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 won’t 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 hangsrequests.Sessionwith 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 it’s in PATH
Bot replies to old mentions after restart
- Check
STATE_FILEexists and is writable - Don’t delete
giffer_state.json
RU
1) Как работает бот
- Опрос уведомлений Mastodon типа
mention(/api/v1/notifications). - Для каждого упоминания:
- Достаём текст из HTML
- Удаляем любые упоминания (
@giffer,@giffer@домен,@ giffer) - Определяем наличие
nsfw - Парсим оставшееся в теги (есть кавычки и
-тег)
- Запрос на Furbooru (Philomena API) за GIF:
- SFW добавляет:
safe, animated, gif - NSFW добавляет:
animated, gif(иfilter_id, если задан)
- SFW добавляет:
- Выбор случайного подходящего результата.
- Загрузка медиа в Mastodon:
- Пробуем GIF (full → large → medium → small → thumb)
- Если инстанс отклоняет GIF с 422 (“not supported”/лимиты):
- Конвертим GIF → MP4 через ffmpeg
- Заливаем MP4
- Ждём завершения обработки медиа в Mastodon (
/api/v1/media/:id):- предотвращает 422 “обработка не окончена” при публикации
- Публикуем ответ:
- SFW: обычный ответ
- NSFW:
sensitive=Trueиspoiler_text="NSFW"(+ настраиваемая видимость)
- Сохраняем состояние:
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
- Кулдаун на пользователя (
USER_COOLDOWN_SEC) - Глобальный token-bucket (
GLOBAL_RATE_PER_SEC,GLOBAL_BURST)
6) Защита от повторных ответов (state)
Файл STATE_FILE (по умолчанию giffer_state.json) хранит:
last_seen_notif_idprocessed_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.pyREADME.mddocs.md.gitignore(исключитьconfig.env,giffer_state.json,*.log)LICENSE