Files
cozsweet-frontend-nextjs/src/stores/chat/helper/unlock.ts
T

102 lines
2.9 KiB
TypeScript

import type {
ChatLockType,
UnlockPrivateResponse,
} from "@/data/schemas/chat";
import type { UiMessage } from "@/stores/chat/ui-message";
export interface UnlockMessageRequest {
displayMessageId: string;
messageId?: string;
lockType?: ChatLockType;
clientLockId?: string;
}
export interface UnlockMessageOutput {
displayMessageId: string;
request: UnlockMessageRequest;
response: UnlockPrivateResponse;
}
export function countLockedHistoryMessages(messages: readonly UiMessage[]): number {
return messages.filter(isUnlockableLockedMessage).length;
}
export function applySingleUnlockOutput(
messages: readonly UiMessage[],
output: UnlockMessageOutput,
): UiMessage[] {
return messages.map((message) => {
if (!shouldApplySingleUnlock(message, output.displayMessageId)) {
return message;
}
const remoteId = output.response.messageId || message.remoteId;
if (!output.response.unlocked) {
return {
...message,
...(remoteId ? { remoteId } : {}),
};
}
const resolvedImageUrl =
output.response.image.url ?? message.imageUrl;
const resolvedContent =
message.lockReason === "private_message"
? output.response.content || message.content
: message.content;
return {
...message,
...(remoteId ? { remoteId } : {}),
content: resolvedContent,
audioUrl: getUnlockedAudioUrl(message, output.response),
imageUrl: resolvedImageUrl,
locked: false,
lockReason: null,
imagePaywalled: resolvedImageUrl ? false : undefined,
lockedPrivate: false,
privateMessageHint: null,
};
});
}
function getUnlockedAudioUrl(
message: UiMessage,
response: UnlockPrivateResponse,
): string | undefined {
if (message.lockReason !== "voice_message") return message.audioUrl;
if (response.audioUrl.length === 0) return message.audioUrl;
return response.audioUrl;
}
function shouldApplySingleUnlock(
message: UiMessage,
displayMessageId: string,
): boolean {
if (message.displayId !== displayMessageId) return false;
if (!message.isFromAI) return false;
if (message.locked !== true) return false;
return (
message.imagePaywalled === true ||
message.lockReason === "image_paywall" ||
message.lockReason === "image" ||
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 === "image_paywall" ||
message.lockReason === "image" ||
message.lockReason === "private_message" ||
message.lockReason === "voice_message"
);
}