Skip to main content

Emotes

Overview

The emotes module fetches, caches, and parses chat emotes from multiple providers across platforms. It supports both channel-specific emotes (fetched per platform + channel ID) and user-specific emotes (Twitch subscriber emotes for the authenticated user). Emotes are used in chat message rendering and overlay alerts.

Architecture

Dashboard UI / Overlay
|
v
Next.js API Proxy (/api/emotes)
|
v
REST API (GET /v1/emotes/{platform}/{channel_id}, GET /v1/emotes/user)
|
+--> Redis cache check
| Hit? --> Return cached EmoteSet[]
|
+--> Fetch from provider APIs (7TV, FFZ, BTTV, Twitch, etc.)
|
+--> Cache result in Redis
|
v
EmoteSet[] response

Emote Providers

ProviderEnum ValuePlatformsDescription
TwitchtwitchTwitchNative Twitch emotes (global + channel)
7TV7tvTwitch, YouTube, KickThird-party emote service
FrankerFaceZffzTwitchThird-party emote extension
BetterTTVbttvTwitch, YouTube, KickThird-party emote extension
DiscorddiscordDiscordGuild custom emojis
YouTubeyoutubeYouTubeYouTube emojis from chat
KickkickKickKick platform emotes
TrovotrovoTrovoTrovo platform emotes

Per-Platform Fetch Strategy

PlatformProviders Fetched
Twitch7TV (channel), FFZ (channel), BTTV (channel), FFZ (global)
YouTube7TV (channel), BTTV (channel), FFZ (global)
Kick7TV (channel), BTTV (channel), FFZ (global)
TrovoTrovo (native, requires client_id), 7TV (global), BTTV (global), FFZ (global)
DiscordDiscord guild emojis (requires bot token)

Empty sets are filtered out -- only providers with at least one emote are included in the response.

API

REST Endpoints

MethodPathDescriptionAuth
GET/v1/emotes/{platform}/{channel_id}Fetch channel emotesAuthenticated
GET/v1/emotes/userFetch user's Twitch subscriber emotesAuthenticated

GET /v1/emotes/{platform}/{channel_id}

Fetches all available emote sets for a given platform and channel. Results are cached in Redis.

Response:

{
"data": {
"sets": [
{
"provider": "7tv",
"emotes": [
{
"id": "60ae958e...",
"name": "LULW",
"url": "https://cdn.7tv.app/emote/.../1x.webp",
"provider": "7tv",
"animated": false
}
]
}
],
"owners": null
}
}

GET /v1/emotes/user

Fetches all Twitch emotes available to the authenticated user (subscriber emotes from all channels). Requires a Twitch login connection with user:read:emotes scope. Automatically refreshes the token if expired.

Also resolves emote owner information (channel names and avatars) via batch Twitch user lookup.

Response includes:

  • sets -- Array of EmoteSet with the user's available emotes
  • owners -- Map of owner IDs to { displayName, profileImageUrl } for grouping emotes by channel

Types

EmoteSet

struct EmoteSet {
provider: EmoteProvider, // twitch, 7tv, ffz, bttv, discord, youtube, kick, trovo
emotes: Vec<Emote>,
}

Emote

struct Emote {
id: String, // Provider-specific emote ID
name: String, // Emote name (e.g., "Kappa", "LULW")
url: String, // CDN URL for the emote image
provider: EmoteProvider, // Source provider
animated: bool, // Whether the emote is animated (GIF/WEBP)
owner_id: Option<String>, // Owner user/channel ID (Twitch-specific)
}

Message Parsing

The parse_emotes() function splits a chat message into segments of text and emotes:

fn parse_emotes(message: &str, emote_sets: &[EmoteSet]) -> Vec<EmotePart>

Behavior:

  • Builds a name-to-emote lookup from all provided sets
  • Splits message on whitespace boundaries
  • Exact, case-sensitive matching only (Kappa matches, kappa does not, KappaRoss does not)
  • Consecutive text words are merged into a single EmotePart::Text
  • Returns Vec<EmotePart> where each part is either Text { text } or Emote { id, name, url, provider }

Caching

Emote sets are cached in Redis per platform + channel ID. The cache is checked before making any external API calls. Cache keys follow the pattern used by emote_service::get_cached_emotes / cache_emotes.

User emotes are cached separately under twitch-user:user:{user_id} with owner data cached under lumio:emotes:owners:{user_id} (1 hour TTL).

Key Files

FilePurpose
apps/api/src/routes/emotes.rsREST endpoints for channel and user emotes
apps/api/src/services/emotes.rsProvider fetch functions, caching, owner resolution
crates/lo-chat/src/emotes.rsCore types (Emote, EmoteSet, EmoteProvider, EmotePart) and parse_emotes()