feat: add support for super stickers in chat and overlay components, including image display, accessibility labels, and backend parsing enhancements

This commit is contained in:
Yusuf İpek
2025-10-12 21:37:53 +03:00
parent da1499733f
commit 1678117d16
10 changed files with 138 additions and 15 deletions
+8 -3
View File
@@ -224,13 +224,18 @@ export async function startBackend() {
return { error: 'url parameter is required' };
}
// Only allow YouTube CDN domains
const allowedDomains = ['yt3.ggpht.com', 'yt4.ggpht.com', 'i.ytimg.com'];
// Only allow YouTube CDN and Google User Content domains
const allowedDomains = [
'yt3.ggpht.com',
'yt4.ggpht.com',
'i.ytimg.com',
'lh3.googleusercontent.com' // For super stickers
];
try {
const urlObj = new URL(url);
if (!allowedDomains.includes(urlObj.hostname)) {
reply.status(403);
return { error: 'Only YouTube CDN URLs are allowed' };
return { error: 'Only YouTube CDN and Google User Content URLs are allowed' };
}
} catch (error) {
reply.status(400);
+31 -4
View File
@@ -65,9 +65,9 @@ export async function bootstrapInnertube(videoId: string): Promise<IngestionCont
liveChat.on('chat-update', (action: any) => {
// Log the complete raw action data from YouTube (commented out for production)
// console.log('=== YOUTUBE RAW MESSAGE DATA ===');
// console.log('Action type:', action?.type);
// console.log('Complete action object:', JSON.stringify(action, null, 2));
console.log('=== YOUTUBE RAW MESSAGE DATA ===');
console.log('Action type:', action?.type);
console.log('Complete action object:', JSON.stringify(action, null, 2));
const normalized = normalizeAction(action);
if (normalized) {
@@ -307,10 +307,37 @@ function extractSuperChatInfo(item: any): SuperChatInfo | undefined {
}
}
// Extract super sticker image URL if present
let stickerUrl: string | undefined;
let stickerAlt: string | undefined;
if (Array.isArray(item.sticker) && item.sticker.length > 0) {
// Prefer larger image (first in array is usually largest)
const stickerThumb = item.sticker[0];
if (stickerThumb?.url) {
// URLs from YouTube might be protocol-relative (//domain.com)
// Convert to absolute HTTPS URL
let url = String(stickerThumb.url);
if (url.startsWith('//')) {
url = 'https:' + url;
} else if (!url.startsWith('http')) {
url = 'https://' + url;
}
stickerUrl = url;
}
// Extract accessibility label for alt text
if (item.sticker_accessibility_label) {
stickerAlt = String(item.sticker_accessibility_label);
}
}
return {
amount,
currency,
color
color,
stickerUrl,
stickerAlt
};
}