Публичное API
JSON API для доступа к мемам, тегам и комментариям. Базовый URL: https://смешнявки.рф
Общие правила
- Все ответы — JSON, кодировка UTF-8.
- Публичные эндпоинты не требуют авторизации и CSRF-токена.
- Админские эндпоинты требуют авторизацию и CSRF-токен.
- Rate limits применяются по IP клиента (flask-limiter, storage
memory://или Redis). - Ошибки:
429— rate limit,404— не найдено,400— невалидный ввод,500— ошибка сервера.
Загрузка мема
/api/upload
Загрузка изображения (multipart/form-data). Мем создаётся как неопубликованный до модерации.
curl -X POST https://смешнявки.рф/api/upload \
-F "file=@meme.png" \
-F "title=Смешной мем" \
-F "description=Описание" \
-F "tags=кот,смешное"
Ответ 201:
{
"success": true,
"meme_id": 123,
"filename": "abc123.avif",
"warning": "Похожий мем уже есть (#456)" // optional
}
Лимит: 10 загрузок/мин на IP. Файл конвертируется в AVIF, EXIF удаляется.
Лайки
/api/like/<meme_id>
Инкремент счётчика лайков (не toggle).
// 200
{"liked": true, "count": 43}
// 429 — rate limit (3 лайка в 30 с)
// 404 — мем не найден
/api/like-status/<meme_id>
// 200
{"liked": false, "count": 43}
IP не хранится — «лайкнуто» вернуть невозможно, только счётчик.
Реакции (эмодзи)
/api/reaction/<meme_id>
Тело: {"reaction": "🗿"}. Допустимые: 🗿 🔥 🥺 👏 💔 🤡 💀
// 200
{"reaction": "🗿", "count": 5, "counts": {"🗿": 5, "🔥": 0, ...}}
// 400 — неизвестный эмодзи
// 429 — 3 реакции в 30 с
// 404 — мем не найден/неопубликован
/api/reaction-status/<meme_id>
// 200
{"counts": {"🗿": 5, "🔥": 0, ...}}
Комментарии
/api/comment/<meme_id>
Content-Type: application/json. Тело: {"nickname": "Аноним", "text": "Отличный мем!"}
// 201
{"success": true}
// 429 — 1 комментарий/мин или дубликат за 5 мин
// 400 — пустой текст, >2000 символов, невалидный parent
// 404 — мем не найден
/api/comments/<meme_id>?cursor=<id>&limit=<n>
// 200
{"comments": [{"id", "nickname", "text", "created_at", "replies": [...]}],
"next_cursor": 123}
Только approved-комментарии с ветками; limit ≤ 50. Никнейм санитизируется, HTML из текста вырезается.
Прочее
| Метод | Путь | Описание |
|---|---|---|
| GET | /api/random-meme | Случайный мем |
| GET | /api/meme-of-the-day | Мем дня (детерминированный по дате, кеш 24 ч) |
| GET | /api/meme-id?filename=abc.avif | ID мема по имени файла |
| GET | /api/all-tags | Все теги с количеством |
Админские (требуют авторизацию + CSRF)
| Метод | Путь | Описание |
|---|---|---|
| POST | /api/comment/<id>/approve | Одобрить комментарий |
| POST | /api/comment/<id>/reject | Отклонить комментарий |
| DELETE | /api/comment/<id> | Удалить комментарий |
Публичные страницы (HTML)
| Роут | Описание |
|---|---|
GET / | Главная: галерея + мем дня; ?sort=new|likes|views|random, ?cursor= |
GET /meme/<id> | Страница мема (og-image, canonical, JSON-LD, похожие, комментарии) |
GET /search?q= | Поиск (FTS5, fallback ILIKE) |
GET /tags | Облако тегов с количеством |
GET /tag/<name> | Мемы по тегу |
GET /uploads | Форма загрузки |
GET /favorites?ids= | Избранное (id через запятую, макс. 100) |
GET /random | Редирект на случайный мем |
GET /stats | Публичная статистика |
GET /feed.xml | RSS 2.0 (30 последних) |
GET /sitemap.xml | Sitemap (кеш 1 ч) |
GET /robots.txt | Robots |
GET /privacy | Политика конфиденциальности |
HTMX-фрагменты
Запросы с заголовком HX-Request: true возвращают HTML-фрагменты (partials/meme_items.html) вместо полных страниц. Используется для infinite scroll. Библиотека HTMX не подключена — клиентский JS отправляет заголовок через fetch.