Chatterino+ public API v1
API для тех, кто хочет показывать в СВОЁМ чате (экранный чат для OBS, бот, расширение, клиент) то, что есть у подписчиков Chatterino+ PLUS: пейнты ников, бейдж PLUS и эффекты смайликов. Больше ничего API не даёт.
База: https://chat.eblo.id/api/v1. Только чтение, без ключей и входа.
Ответы — JSON в UTF-8, Access-Control-Allow-Origin: *. Версия в адресе:
несовместимые изменения выйдут как /api/v2, а /v1 продолжит работать.
Новые поля в ответах могут появляться — неизвестные поля пропускайте.
Ошибки: {"error": "<код>", "message": "<текст>"} с HTTP-кодом 400/404/429/5xx.
Пределы частоты — по IP; при превышении 429 и заголовок Retry-After.
Список подписчиков скачивайте при запуске и держите в памяти, а изменения
получайте по живому соединению — опрашивать API по таймеру не нужно.
Остальные адреса сайта chat.eblo.id — внутренние, для нашего собственного экранного чата. Они не часть API и чужим страницам не отвечают.
Содержание: Подписчики PLUS · Один подписчик · Пейнт · Живые изменения · Формат пейнта · Эффекты смайликов
Подписчики PLUS: GET /plus/roster
Все действующие подписчики одним ответом — вместе с их пейнтами и бейджем.
{
"version": "3f9a1c0d2b7e4411",
"users": [
{"id": "47966045", "login": "nick", "badge": true, "paint": 42, "paint_v": 3}
],
"paints": {
"42": {"v": 3, "spec": {"type": "linear", "angle": 137, "stops": [[0, "#fcf9ff"], [1, "#9f73e6"]],
"shadows": [[0, 0, 8, "#9f73e6"]], "anim": {"kind": "slide", "speed": 3}}}
},
"badges": {
"plus": {"title": "Chatterino+ PLUS",
"urls": {"1x": "https://chat.eblo.id/chat/static/plus-badge-1x.png",
"2x": "https://chat.eblo.id/chat/static/plus-badge-2x.png",
"4x": "https://chat.eblo.id/chat/static/plus-badge-4x.png"}}
}
}
id— идентификатор пользователя Twitch (строка),login— логин.badge: true— показывать бейджbadges.plus(18/36/72 px) последним перед ником, вплотную к нему — так он выглядит в Chatterino+.paint— номер пейнта илиnull; описание — вpaints,paint_v— версия (сменилась версия — перерисуйте ник).- Эффекты смайликов PLUS работают только у тех, кто есть в этом списке (см. эффекты смайликов).
- Кэш:
Cache-Control: public, max-age=30,ETag=version; поддерживаетсяIf-None-Match→304.
Один подписчик: GET /plus/users/{login_or_id}
{"user": {…как в roster…}, "paint": {"id": 42, "v": 3, "spec": {…}} | null}.
Не подписчик — 404. Кэш 60 с.
Пейнт: GET /plus/paints/{id}
{"id": 42, "v": 3, "spec": {…}}. Отдаются только пейнты, которые кто-то носит
или которые опубликованы; отклонённые модерацией — 404. Кэш 5 мин.
Живые изменения: wss://chat.eblo.id/api/v1/plus/events
После подключения сервер присылает {"op": "hello", "version": "<версия списка>"},
затем на каждое изменение:
{"op": "user", "login": "nick", "user": {…} | null, "paint": {"id": 42, "v": 3, "spec": {…}} | null,
"version": "<после>", "prev": "<до>"}
user: null— человек больше не подписчик: уберите его пейнт и бейдж.prevне совпадает с вашей версией списка — вы пропустили изменение: перекачайте/plus/roster. То же — еслиversionвhelloотличается от вашей (например, после переподключения).- Каждые 20 с приходит
{"op": "ping"}. 50 с тишины — соединение мёртвое: переподключитесь (пауза 5–10 с со случайным разбросом, чтобы сотни чатов не стучались в одну секунду). - Присылать на сервер ничего не нужно.
Формат пейнта (spec)
Градиент (type: linear | radial)
| поле | значение |
|---|---|
angle | 0–360, как у CSS linear-gradient(<угол>deg) (у radial не используется) |
stops | 2–16 пар [позиция 0..1, "#rrggbb"] |
tiles | 1–6: сколько раз рисунок повторяется по длине (нет поля — 1) |
repeat | устаревшее: true без tiles означает 3 повтора |
shadows | до 3 теней [dx, dy, blur, "#rrggbb"]: dx/dy −4…4, blur 0–8 |
anim | {"kind": "none" | "slide" | "spin" | "pulse", "speed": секунд на цикл} (нет поля или speed < 0,5 — 6 с) |
Как рисовать, чтобы совпадало с Chatterino+ и сайтом PLUS:
linear— как CSSlinear-gradient(angle, stops)по размеру ника;radial—radial-gradient(circle farthest-side at 50% 50%, stops).- Повтор (
tiles> 1) или перелив (slide): рисунок «замыкается зеркалом» — от первого цвета к последнему и обратно, период = 1/tiles, без шва на стыке. slide— рисунок сдвигается на один период заspeedсекунд;spin— уголlinearповорачивается на 360° заspeed;pulse— рисунок масштабируется от центра: 1 + 0,25·sin(2π·t).- Фаза анимации — от РЕАЛЬНОГО времени: t = (время в секундах mod
speed) /speed. Так перелив у всех зрителей и на сайте PLUS идёт в лад.
Картинка (type: image)
| поле | значение |
|---|---|
img | адрес webp (может быть анимированным) |
fit | cover (заполнить, по центру) | tile (по высоте ника, повтор вбок) | stretch (растянуть) |
w, h | размеры картинки |
anim | 1 — картинка анимированная |
shadows | как у градиента |
Рядом с картинкой лежит лёгкое превью первого кадра — тот же адрес с .p.webp:
показывайте его, пока грузится основная картинка. Не загрузилась — рисуйте ник обычным цветом.
Общее
- Ник — текст с заливкой пейнта (в вебе:
background-clip: textи прозрачный цвет текста). - Тени заданы в пикселях для шрифта 14 px — масштабируйте пропорционально размеру шрифта. Рисуйте их ОТДЕЛЬНЫМ неподвижным слоем под текстом, а не фильтром на анимированном нике: иначе размытие пересчитывается каждый кадр.
- Бейдж PLUS и пейнт показываются независимо: у подписчика может быть бейдж без пейнта.
Эффекты смайликов: GET /effects
Справочник модификаторов: кто их пишет, где они стоят, кому доступны и что делают. Кэш 1 ч.
{"effects": [
{"code": "w!", "provider": "bttv", "position": "before", "applies_to": "third_party", "case_sensitive": true, "effect": "wide"},
{"code": "ffzSpin", "provider": "ffz", "position": "after", "applies_to": "any", "requires": "ffz_supporter", "effect": "spin"},
{"code": "+spin", "provider": "plus", "position": "before", "applies_to": "third_party", "case_sensitive": false, "requires": "plus_subscriber", "effect": "spin"}
]}
| поле | значение |
|---|---|
code | слово в сообщении |
provider | bttv | ffz | plus |
position | before — слово стоит перед смайликом, after — после |
applies_to | third_party — только смайлики 7TV/BTTV/FFZ (не Twitch), any — любые |
case_sensitive | учитывать ли регистр букв |
requires | нет поля — доступно всем; plus_subscriber — автор есть в /plus/roster;
ffz_supporter — автор поддержал FFZ (список у FFZ, набор «Subwoofer Emote Effects») |
effect | что сделать со смайликом (ниже) |
Значения effect: wide — растянуть вчетверо в ширину; grow_x — вдвое;
flip_x, flip_y — отразить по горизонтали / вертикали; rotate_left,
rotate_right — повернуть на 90°; no_space — поставить вплотную к предыдущему,
без пробела; cursed — обесцветить и затемнить; party — перелив цветов;
rainbow — бегущий оттенок; hyper — красный оттенок и мелкая тряска;
shake — тряска; spin — вращение; jam — покачивание;
bounce — подпрыгивание; slide — бегущая дорожка; arrive — въезжает;
leave — уезжает. Несколько модификаторов на одном смайлике складываются; повороты
и отражения — нет (действует один).