import type { UiMessage, UnlockPrivateResponse } from "@/data/dto/chat"; export interface UnlockMessageOutput { messageId: string; response: UnlockPrivateResponse; } export function countLockedHistoryMessages(messages: readonly UiMessage[]): number { return messages.filter(isUnlockableLockedMessage).length; } export function applySingleUnlockOutput( messages: readonly UiMessage[], output: UnlockMessageOutput, ): UiMessage[] { if (!output.response.unlocked) return [...messages]; return messages.map((message) => { if (!shouldApplySingleUnlock(message, output.messageId)) return message; return { ...message, locked: output.response.lockDetail.locked, lockReason: output.response.lockDetail.reason, imagePaywalled: message.imageUrl ? output.response.lockDetail.locked && output.response.lockDetail.showUpgrade : undefined, lockedPrivate: false, privateMessageHint: null, }; }); } function shouldApplySingleUnlock(message: UiMessage, messageId: string): boolean { if (message.id !== messageId) return false; if (!message.isFromAI) return false; if (message.locked !== true) return false; return ( message.imagePaywalled === true || message.lockReason === "private_message" || message.lockReason === "voice_message" ); } export function shouldPromptUnlockHistory(messages: readonly UiMessage[]): boolean { return countLockedHistoryMessages(messages) > 1; } function isUnlockableLockedMessage(message: UiMessage): boolean { if (!message.isFromAI || message.locked !== true) return false; if (message.imagePaywalled === true) return true; return ( message.lockReason === "private_message" || message.lockReason === "voice_message" ); }