Include twitch message metadata

This commit is contained in:
2026-01-13 22:00:24 +01:00
parent 467977ddac
commit c9aac6e4f1
3 changed files with 87 additions and 15 deletions

View File

@@ -29,9 +29,62 @@ function formatLines(messages, ctx, width) {
const maxWidth = Math.max(width - PADDING * 2, 0); const maxWidth = Math.max(width - PADDING * 2, 0);
const lines = []; const lines = [];
messages.forEach((message) => { messages.forEach((message) => {
const prefix = message.displayName ? `${message.displayName}: ` : ""; const prefixText = message.displayName ? `${message.displayName}: ` : "";
const raw = `${prefix}${message.message || ""}`; const bodyText = message.message || "";
wrapLine(ctx, raw, maxWidth).forEach((line) => lines.push(line)); const nameColor = message.tags?.color || "#ffffff";
if (!prefixText) {
wrapLine(ctx, bodyText, maxWidth).forEach((line) =>
lines.push({
prefixText: "",
prefixWidth: 0,
nameColor,
text: line,
}),
);
return;
}
const prefixWidth = ctx.measureText(prefixText).width;
const words = bodyText.split(" ");
let current = "";
let isFirstLine = true;
let availableWidth = Math.max(maxWidth - prefixWidth, 0);
const flushLine = () => {
lines.push({
prefixText: isFirstLine ? prefixText : "",
prefixWidth: isFirstLine ? prefixWidth : 0,
nameColor,
text: current,
});
current = "";
isFirstLine = false;
availableWidth = maxWidth;
};
if (!words.length || !bodyText.trim()) {
lines.push({
prefixText,
prefixWidth,
nameColor,
text: "",
});
return;
}
words.forEach((word) => {
const test = current ? `${current} ${word}` : word;
if (ctx.measureText(test).width > availableWidth && current) {
flushLine();
current = word;
} else {
current = test;
}
});
if (current) {
flushLine();
}
}); });
return lines.slice(-MAX_LINES); return lines.slice(-MAX_LINES);
} }
@@ -53,15 +106,21 @@ function tick(context) {
const lines = formatLines(messages, ctx, width); const lines = formatLines(messages, ctx, width);
const boxHeight = lines.length * LINE_HEIGHT + PADDING * 2; const boxHeight = lines.length * LINE_HEIGHT + PADDING * 2;
const boxWidth = Math.max( const boxWidth = Math.max(
...lines.map((line) => ctx.measureText(line).width), ...lines.map((line) => line.prefixWidth + ctx.measureText(line.text).width),
120, 120,
); );
ctx.fillStyle = "rgba(0, 0, 0, 0.55)"; ctx.fillStyle = "rgba(0, 0, 0, 0.55)";
ctx.fillRect(PADDING, height - boxHeight - PADDING, boxWidth + PADDING * 2, boxHeight); ctx.fillRect(PADDING, height - boxHeight - PADDING, boxWidth + PADDING * 2, boxHeight);
ctx.fillStyle = "#ffffff";
lines.forEach((line, index) => { lines.forEach((line, index) => {
ctx.fillText(line, PADDING * 2, height - boxHeight - PADDING + PADDING + index * LINE_HEIGHT); const x = PADDING * 2;
const y = height - boxHeight - PADDING + PADDING + index * LINE_HEIGHT;
if (line.prefixText) {
ctx.fillStyle = line.nameColor || "#ffffff";
ctx.fillText(line.prefixText, x, y);
}
ctx.fillStyle = "#ffffff";
ctx.fillText(line.text, x + line.prefixWidth, y);
}); });
} }

View File

@@ -7,14 +7,20 @@ const scriptLayer = document.getElementById("broadcast-script-layer");
setUpElectronWindowFrame(); setUpElectronWindowFrame();
const renderer = new BroadcastRenderer({ canvas, scriptLayer, broadcaster, showToast }); const renderer = new BroadcastRenderer({ canvas, scriptLayer, broadcaster, showToast });
const disconnectChat = connectTwitchChat(broadcaster, ({ channel, displayName, message }) => { const disconnectChat = connectTwitchChat(
broadcaster,
({ channel, displayName, message, tags, prefix, raw }) => {
console.log(`[twitch:${broadcaster}] ${displayName}: ${message}`); console.log(`[twitch:${broadcaster}] ${displayName}: ${message}`);
renderer.receiveChatMessage({ renderer.receiveChatMessage({
channel, channel,
displayName, displayName,
message, message,
tags,
prefix,
raw,
}); });
}); },
);
setUpElectronWindowResizeListener(canvas); setUpElectronWindowResizeListener(canvas);
renderer.start(); renderer.start();

View File

@@ -47,6 +47,7 @@ const parseIrcMessage = (rawLine) => {
params, params,
prefix, prefix,
tags, tags,
raw: rawLine,
}; };
}; };
@@ -64,6 +65,9 @@ const extractChatMessage = (ircMessage) => {
channel, channel,
displayName, displayName,
message, message,
tags: ircMessage.tags,
prefix: ircMessage.prefix,
raw: ircMessage.raw,
}; };
}; };
@@ -80,7 +84,7 @@ export const connectTwitchChat = (channelName, onMessage = console.log) => {
socket.addEventListener("open", () => { socket.addEventListener("open", () => {
socket.send(`PASS ${ANON_PASSWORD}`); socket.send(`PASS ${ANON_PASSWORD}`);
socket.send(`NICK ${nick}`); socket.send(`NICK ${nick}`);
socket.send("CAP REQ :twitch.tv/tags twitch.tv/commands"); socket.send("CAP REQ :twitch.tv/tags twitch.tv/commands twitch.tv/membership");
socket.send(`JOIN #${normalizedChannel}`); socket.send(`JOIN #${normalizedChannel}`);
}); });
@@ -102,6 +106,9 @@ export const connectTwitchChat = (channelName, onMessage = console.log) => {
channel: chatMessage.channel, channel: chatMessage.channel,
displayName: chatMessage.displayName, displayName: chatMessage.displayName,
message: chatMessage.message, message: chatMessage.message,
tags: chatMessage.tags,
prefix: chatMessage.prefix,
raw: chatMessage.raw,
}); });
} }
}); });