mirror of
https://github.com/yusufipk/YTChatHub.git
synced 2026-09-11 10:56:17 +00:00
refactor: simplify superchat amount extraction and display logic
This commit is contained in:
@@ -157,7 +157,6 @@ function extractBadges(item: any): Badge[] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function extractSuperChatInfo(item: any): SuperChatInfo | undefined {
|
function extractSuperChatInfo(item: any): SuperChatInfo | undefined {
|
||||||
// Support multiple superchat-like types from Innertube
|
|
||||||
const superTypes = new Set([
|
const superTypes = new Set([
|
||||||
'LiveChatPaidMessage',
|
'LiveChatPaidMessage',
|
||||||
'LiveChatPaidSticker',
|
'LiveChatPaidSticker',
|
||||||
@@ -168,8 +167,7 @@ function extractSuperChatInfo(item: any): SuperChatInfo | undefined {
|
|||||||
const isSuper = superTypes.has(typeName) || !!(item.purchase_amount_text || item.purchaseAmountText);
|
const isSuper = superTypes.has(typeName) || !!(item.purchase_amount_text || item.purchaseAmountText);
|
||||||
if (!isSuper) return undefined;
|
if (!isSuper) return undefined;
|
||||||
|
|
||||||
// Try multiple possible field names for the amount (search shallow + nested header)
|
let amountText = '';
|
||||||
let amount = '';
|
|
||||||
const candidates = [
|
const candidates = [
|
||||||
item.purchase_amount_text,
|
item.purchase_amount_text,
|
||||||
item.purchaseAmountText,
|
item.purchaseAmountText,
|
||||||
@@ -185,58 +183,25 @@ function extractSuperChatInfo(item: any): SuperChatInfo | undefined {
|
|||||||
if (typeof v === 'number') return String(v);
|
if (typeof v === 'number') return String(v);
|
||||||
if (typeof v.simpleText === 'string') return v.simpleText;
|
if (typeof v.simpleText === 'string') return v.simpleText;
|
||||||
if (Array.isArray(v.runs)) return v.runs.map((r: any) => r.text ?? '').join('');
|
if (Array.isArray(v.runs)) return v.runs.map((r: any) => r.text ?? '').join('');
|
||||||
if (typeof v.toString === 'function') return v.toString();
|
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const v of candidates) {
|
for (const v of candidates) {
|
||||||
amount = toText(v);
|
amountText = toText(v);
|
||||||
if (amount) break;
|
if (amountText) break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fallback deep scan for a purchase/amount text-like field
|
let amount = 'Super Chat';
|
||||||
if (!amount) {
|
let currency = '';
|
||||||
try {
|
|
||||||
const stack: any[] = [item];
|
if (amountText) {
|
||||||
const seen = new Set<any>();
|
const match = amountText.match(/^([\$\€\£\¥\₹\₺A-Z]+)?\s*([\d,\.]+)/);
|
||||||
while (stack.length) {
|
if (match) {
|
||||||
const cur = stack.pop();
|
currency = match[1] || '';
|
||||||
if (!cur || typeof cur !== 'object' || seen.has(cur)) continue;
|
amount = match[2];
|
||||||
seen.add(cur);
|
|
||||||
for (const [k, v] of Object.entries(cur)) {
|
|
||||||
if (/purchase.*amount.*text|purchaseAmountText|amountText|purchase_amount_text/i.test(k)) {
|
|
||||||
amount = toText(v);
|
|
||||||
if (amount) throw new Error('_found');
|
|
||||||
}
|
|
||||||
if (v && typeof v === 'object') stack.push(v);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (e: any) {
|
|
||||||
if (e?.message !== '_found') throw e;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Last resort: search any string-like leaf for a currency pattern
|
|
||||||
if (!amount) {
|
|
||||||
const currencyPattern = /([€$£¥₹]|AUD|USD|EUR|GBP|JPY|INR)\s?\d{1,3}(?:[\,\s]?\d{3})*(?:[\.,]\d{1,2})?/i;
|
|
||||||
const stack: any[] = [item];
|
|
||||||
const seen = new Set<any>();
|
|
||||||
while (stack.length) {
|
|
||||||
const cur = stack.pop();
|
|
||||||
if (!cur || typeof cur !== 'object' || seen.has(cur)) continue;
|
|
||||||
seen.add(cur);
|
|
||||||
for (const v of Object.values(cur)) {
|
|
||||||
if (typeof v === 'string') {
|
|
||||||
const m = v.match(currencyPattern);
|
|
||||||
if (m) { amount = m[0]; stack.length = 0; break; }
|
|
||||||
} else if (v && typeof v === 'object') {
|
|
||||||
stack.push(v);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Normalize color; Innertube often provides ARGB/number
|
|
||||||
let rawColor = item.body_background_color ?? item.bodyBackgroundColor ?? item.headerBackgroundColor;
|
let rawColor = item.body_background_color ?? item.bodyBackgroundColor ?? item.headerBackgroundColor;
|
||||||
let color = '#1e3a8a';
|
let color = '#1e3a8a';
|
||||||
if (rawColor != null) {
|
if (rawColor != null) {
|
||||||
@@ -250,8 +215,8 @@ function extractSuperChatInfo(item: any): SuperChatInfo | undefined {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
amount: amount || 'Super Chat',
|
amount,
|
||||||
currency: item.currency ?? 'USD',
|
currency,
|
||||||
color
|
color
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -280,10 +245,10 @@ function normalizeAction(action: any): ChatMessage | null {
|
|||||||
|
|
||||||
// Extract membership level for new members
|
// Extract membership level for new members
|
||||||
let membershipLevel: string | undefined;
|
let membershipLevel: string | undefined;
|
||||||
if (isMembership || isGiftPurchase || isGiftReceived) {
|
if (isMembership || isGiftPurchase || isGiftReceived || isPaid) {
|
||||||
membershipLevel = item.header_subtext?.toString() ||
|
membershipLevel = item.header_subtext?.toString() ||
|
||||||
item.header_primary_text?.toString() ||
|
item.header_primary_text?.toString() ||
|
||||||
'New member';
|
(isPaid ? undefined : 'New member');
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -409,7 +409,7 @@ function ChatItem({ message, isSelected, onSelect }: ChatItemProps) {
|
|||||||
</div>
|
</div>
|
||||||
{message.superChat && (
|
{message.superChat && (
|
||||||
<div className="chatItem__superchat" style={{ backgroundColor: message.superChat.color }}>
|
<div className="chatItem__superchat" style={{ backgroundColor: message.superChat.color }}>
|
||||||
💰 {message.superChat.amount} {message.superChat.currency}
|
💰 {message.superChat.currency}{message.superChat.amount}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<p className="chatItem__text">{message.text}</p>
|
<p className="chatItem__text">{message.text}</p>
|
||||||
|
|||||||
@@ -519,6 +519,7 @@ main {
|
|||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
padding-right: 0.25rem;
|
padding-right: 0.25rem;
|
||||||
|
padding-bottom: 1rem; /* Add space at the bottom */
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user