// 聊天室偏好与每日状态工具,承接从 Blade 内联脚本迁移出的纯数据规整逻辑。 export const BLOCKABLE_SYSTEM_SENDERS = ["钓鱼播报", "星海小博士", "百家乐", "跑马", "神秘箱子"]; export const BLOCKED_SYSTEM_SENDERS_STORAGE_KEY = "chat_blocked_system_senders"; export const CHAT_SOUND_MUTED_STORAGE_KEY = "chat_sound_muted"; /** * 规整聊天室偏好对象,过滤非法配置并补齐默认值。 * * @param {Record|null|undefined} raw * @param {string[]} blockableSystemSenders * @returns {{blocked_system_senders:string[],sound_muted:boolean}} */ export function normalizeChatPreferences(raw, blockableSystemSenders = BLOCKABLE_SYSTEM_SENDERS) { const blocked = Array.isArray(raw?.blocked_system_senders) ? raw.blocked_system_senders.filter((sender) => blockableSystemSenders.includes(sender)) : []; return { blocked_system_senders: Array.from(new Set(blocked)), sound_muted: Boolean(raw?.sound_muted), }; } /** * 解析并标准化状态到期时间。 * * @param {string|null|undefined} expiresAt * @returns {Date|null} */ export function parseDailyStatusExpiry(expiresAt) { if (!expiresAt) { return null; } const parsed = new Date(expiresAt); return Number.isNaN(parsed.getTime()) ? null : parsed; } /** * 将状态对象规整为前端统一结构,并过滤掉已过期状态。 * * @param {Record|null|undefined} raw * @param {number} nowTimestamp * @returns {{key:string,label:string,icon:string,group:string,expires_at:string}|null} */ export function normalizeDailyStatus(raw, nowTimestamp = Date.now()) { if (!raw || typeof raw !== "object") { return null; } const key = String(raw.key ?? raw.daily_status_key ?? ""); const label = String(raw.label ?? raw.daily_status_label ?? ""); const icon = String(raw.icon ?? raw.daily_status_icon ?? ""); const group = String(raw.group ?? raw.daily_status_group ?? ""); const expiresAt = raw.expires_at ?? raw.daily_status_expires_at ?? null; const parsedExpiry = parseDailyStatusExpiry(expiresAt); if (!key || !label || !icon || !parsedExpiry) { return null; } if (parsedExpiry.getTime() <= nowTimestamp) { return null; } return { key, label, icon, group, expires_at: parsedExpiry.toISOString(), }; }