# Chat (https://docs.pixl.lennox.zip/sdk/chat)

> Chat-Nachrichten mit 7TV-, BTTV- und FFZ-Emotes und 7TV-Paints

`twitch.chat_message` bringt jede Nachricht aus dem Chat mit Badges und allen Emotes: die von Twitch selbst und die von 7TV, BTTV und FFZ, die der Kanal oder alle nutzen. Heißen zwei gleich, gewinnt 7TV vor BTTV vor FFZ, und das Emote des Kanals vor dem globalen.

Der Schlüssel braucht **Events lesen** (`events:read`).

## Nachricht als HTML [#nachricht-als-html]

Das SDK hängt an jede Nachricht `html` an: der Text ist escaped, Emotes sind Bilder mit der Klasse `pixl-emote`. Zero-width Emotes (z.B. Hüte) liegen zusammen mit dem Emote davor in `<span class="pixl-emote-stack">`.

```html
<div id="chat"></div>
<script src="https://pixl.lennox.zip/sdk/pixl.js"></script>
<script>
  const pixl = new Pixl({ key: 'pixl_DEIN_SCHLÜSSEL' });
  document.head.append(Object.assign(document.createElement('style'), { textContent: pixl.chat.css }));

  pixl.on('twitch.chat_message', async (msg) => {
    const line = document.createElement('div');
    const name = document.createElement('b');
    name.textContent = msg.username;
    // 7TV-Paint, sonst die Twitch-Farbe
    name.style.cssText = await pixl.chat.paintStyle(msg.paint, msg.color || '#fff');
    const badges = document.createElement('span');
    badges.innerHTML = pixl.chat.badgesHtml(msg.badges);
    const text = document.createElement('span');
    text.innerHTML = ' ' + msg.html;
    line.append(badges, name, text);
    document.getElementById('chat').append(line);
  });
</script>
```

`msg.html` und `badgesHtml()` sind sicher für `innerHTML`, `msg.username` dagegen nicht: den immer über `textContent` setzen.

## Felder [#felder]

| Feld | Inhalt |
|---|---|
| `text` | Nachricht als reiner Text |
| `html` | Nachricht mit Emotes als HTML (baut das SDK) |
| `emotes` | Alle Emotes der Nachricht, Name → `{ provider, id, name, animated?, zeroWidth? }`. `provider` ist `twitch`, `7tv`, `bttv` oder `ffz` |
| `badges` | Badges vor dem Namen: erst die von Twitch (Mod, Sub, VIP, ...), dann das 7TV-Badge. Je `{ provider, set?, id, title, url, info? }` |
| `paint` | ID des 7TV-Paints des Chatters oder `null` |
| `username`, `login`, `userId` | Anzeigename, Login und Twitch-ID des Chatters |
| `messageId` | ID der Nachricht, passt zu `twitch.chat_message_deleted` |
| `color` | Twitch-Farbe des Namens |

Ohne SDK teilst du `text` an Leerzeichen und schaust jedes Wort in `emotes` nach. Die Bild-URL baut `pixl.chat.emoteUrl(emote, size)` mit `size` 1, 2 oder 4.

## 7TV-Paints [#7tv-paints]

`pixl.chat.paintStyle(paintId, fallback)` gibt einen Inline-Style für den Namen zurück. Die Definitionen lädt das SDK beim ersten Mal von [`GET /7tv/paints`](/sdk/api#get-7tvpaints) und merkt sie sich. Brauchst du die Rohdaten, gibt es `pixl.chat.paint(id)`.

## Emote-Änderungen live [#emote-änderungen-live]

Fügt der Kanal bei 7TV ein Emote hinzu, entfernt oder benennt es um, kommt das sofort an. Neue Nachrichten haben das Emote dann schon, die Events brauchst du nur, wenn dein Widget Emotes selbst anzeigt.

```js
pixl.on('seventv.emote_added', ({ emote, actor }) => {
  console.log(`${actor} hat ${emote.name} hinzugefügt`, pixl.chat.emoteUrl(emote, 4));
});
pixl.on('seventv.emote_removed', ({ emote }) => console.log(`${emote.name} ist weg`));
pixl.on('seventv.emote_renamed', ({ emote, oldName }) => console.log(`${oldName} heißt jetzt ${emote.name}`));
pixl.on('seventv.emote_set_changed', ({ name }) => console.log(`Neues Set: ${name}`));
```

Alle Emotes des Kanals auf einmal liefert `await pixl.chat.emotes()` ([`GET /emotes`](/sdk/api#get-emotes)). Änderungen bei BTTV und FFZ kommen nicht live, pixl lädt sie alle 10 Minuten neu.
