refactor(chat): remove legacy unlock response fields
This commit is contained in:
@@ -25,15 +25,14 @@ describe("UnlockPrivateResponse", () => {
|
||||
expect(response.shortfallCredits).toBe(0);
|
||||
});
|
||||
|
||||
it("normalizes backend ids, audio aliases, and unlocked images", () => {
|
||||
it("parses canonical ids, audio, and unlocked images", () => {
|
||||
const response = UnlockPrivateResponse.from({
|
||||
unlocked: true,
|
||||
message_id: "backend-message-1",
|
||||
messageId: "backend-message-1",
|
||||
clientLockId: "promotion-1",
|
||||
lockType: "image_paywall",
|
||||
content: null,
|
||||
reply: "Unlocked reply",
|
||||
audio_url: "https://example.com/audio.mp3",
|
||||
content: "Unlocked reply",
|
||||
audioUrl: "https://example.com/audio.mp3",
|
||||
image: {
|
||||
type: "promotion",
|
||||
url: "https://example.com/image.jpg",
|
||||
@@ -41,18 +40,20 @@ describe("UnlockPrivateResponse", () => {
|
||||
});
|
||||
|
||||
expect(response.messageId).toBe("backend-message-1");
|
||||
expect(response.clientLockId).toBe("promotion-1");
|
||||
expect(response.lockType).toBe("image_paywall");
|
||||
expect(response.content).toBe("Unlocked reply");
|
||||
expect(response.audioUrl).toBe("https://example.com/audio.mp3");
|
||||
expect(response.image.url).toBe("https://example.com/image.jpg");
|
||||
expect(response.toJson()).toMatchObject({
|
||||
clientLockId: "promotion-1",
|
||||
lockType: "image_paywall",
|
||||
});
|
||||
});
|
||||
|
||||
it("parses an insufficient-balance unlock response", () => {
|
||||
it("parses an insufficient-credits unlock response", () => {
|
||||
const response = UnlockPrivateResponse.from({
|
||||
unlocked: false,
|
||||
content: "",
|
||||
reason: "insufficient_balance",
|
||||
reason: "insufficient_credits",
|
||||
creditBalance: 5,
|
||||
creditsCharged: 0,
|
||||
requiredCredits: 10,
|
||||
@@ -60,7 +61,7 @@ describe("UnlockPrivateResponse", () => {
|
||||
});
|
||||
|
||||
expect(response.unlocked).toBe(false);
|
||||
expect(response.reason).toBe("insufficient_balance");
|
||||
expect(response.reason).toBe("insufficient_credits");
|
||||
expect(response.creditBalance).toBe(5);
|
||||
expect(response.creditsCharged).toBe(0);
|
||||
expect(response.requiredCredits).toBe(10);
|
||||
@@ -72,7 +73,7 @@ describe("UnlockPrivateResponse", () => {
|
||||
unlocked: false,
|
||||
content: null,
|
||||
audioUrl: null,
|
||||
reason: "insufficient_balance",
|
||||
reason: "insufficient_credits",
|
||||
});
|
||||
|
||||
expect(response.content).toBe("");
|
||||
@@ -83,7 +84,7 @@ describe("UnlockPrivateResponse", () => {
|
||||
const response = UnlockPrivateResponse.from({
|
||||
unlocked: false,
|
||||
content: "",
|
||||
reason: "insufficient_balance",
|
||||
reason: "insufficient_credits",
|
||||
creditBalance: null,
|
||||
creditsCharged: null,
|
||||
requiredCredits: null,
|
||||
@@ -112,4 +113,20 @@ describe("UnlockPrivateResponse", () => {
|
||||
expect(response.toJson()).not.toHaveProperty("lockDetail");
|
||||
expect(response).not.toHaveProperty("lockDetail");
|
||||
});
|
||||
|
||||
it("does not fall back to removed response aliases", () => {
|
||||
const response = UnlockPrivateResponse.fromJson({
|
||||
unlocked: true,
|
||||
message_id: "legacy-message",
|
||||
reply: "Legacy reply",
|
||||
audio_url: "https://example.com/legacy.mp3",
|
||||
});
|
||||
|
||||
expect(response.messageId).toBe("");
|
||||
expect(response.content).toBe("");
|
||||
expect(response.audioUrl).toBe("");
|
||||
expect(response.toJson()).not.toHaveProperty("message_id");
|
||||
expect(response.toJson()).not.toHaveProperty("reply");
|
||||
expect(response.toJson()).not.toHaveProperty("audio_url");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -4,7 +4,7 @@ import {
|
||||
type UnlockPrivateResponseData,
|
||||
type UnlockPrivateResponseInput,
|
||||
} from "@/data/schemas/chat/response/unlock_private_response";
|
||||
import type { ChatImageData, ChatLockType } from "@/data/schemas/chat";
|
||||
import type { ChatImageData } from "@/data/schemas/chat";
|
||||
|
||||
/**
|
||||
* 单条历史付费 / 私密消息解锁响应 DTO。
|
||||
@@ -12,8 +12,6 @@ import type { ChatImageData, ChatLockType } from "@/data/schemas/chat";
|
||||
export class UnlockPrivateResponse {
|
||||
declare readonly unlocked: boolean;
|
||||
declare readonly messageId: string;
|
||||
declare readonly clientLockId: string | null;
|
||||
declare readonly lockType: ChatLockType | null;
|
||||
declare readonly content: string;
|
||||
declare readonly audioUrl: string;
|
||||
declare readonly image: ChatImageData;
|
||||
|
||||
@@ -14,30 +14,20 @@ import { ChatLockTypeSchema } from "../chat_lock_type";
|
||||
*/
|
||||
export const UnlockPrivateReasonSchema = stringOrEmpty;
|
||||
|
||||
export const UnlockPrivateResponseSchema = z
|
||||
.object({
|
||||
unlocked: booleanOrFalse,
|
||||
content: stringOrEmpty,
|
||||
reply: stringOrEmpty,
|
||||
messageId: stringOrEmpty,
|
||||
message_id: stringOrEmpty,
|
||||
clientLockId: stringOrNull,
|
||||
lockType: ChatLockTypeSchema.nullable().default(null),
|
||||
audioUrl: stringOrEmpty,
|
||||
audio_url: stringOrEmpty,
|
||||
image: ChatImageSchema,
|
||||
reason: UnlockPrivateReasonSchema,
|
||||
creditBalance: numberOrZero,
|
||||
creditsCharged: numberOrZero,
|
||||
requiredCredits: numberOrZero,
|
||||
shortfallCredits: numberOrZero,
|
||||
})
|
||||
.transform(({ reply, message_id, audio_url, ...data }) => ({
|
||||
...data,
|
||||
content: data.content || reply,
|
||||
messageId: data.messageId || message_id,
|
||||
audioUrl: data.audioUrl || audio_url,
|
||||
}));
|
||||
export const UnlockPrivateResponseSchema = z.object({
|
||||
unlocked: booleanOrFalse,
|
||||
content: stringOrEmpty,
|
||||
messageId: stringOrEmpty,
|
||||
clientLockId: stringOrNull,
|
||||
lockType: ChatLockTypeSchema.nullable().default(null),
|
||||
audioUrl: stringOrEmpty,
|
||||
image: ChatImageSchema,
|
||||
reason: UnlockPrivateReasonSchema,
|
||||
creditBalance: numberOrZero,
|
||||
creditsCharged: numberOrZero,
|
||||
requiredCredits: numberOrZero,
|
||||
shortfallCredits: numberOrZero,
|
||||
});
|
||||
|
||||
export type UnlockPrivateReason = z.output<typeof UnlockPrivateReasonSchema>;
|
||||
export type UnlockPrivateResponseInput = z.input<
|
||||
|
||||
@@ -442,7 +442,7 @@ describe("chat unlock flow", () => {
|
||||
response: makeUnlockPrivateResponse({
|
||||
unlocked: false,
|
||||
content: "",
|
||||
reason: "insufficient_balance",
|
||||
reason: "insufficient_credits",
|
||||
creditBalance: 3,
|
||||
creditsCharged: 0,
|
||||
requiredCredits: 10,
|
||||
@@ -472,7 +472,7 @@ describe("chat unlock flow", () => {
|
||||
displayMessageId: "msg-voice-locked",
|
||||
messageId: "msg-voice-locked",
|
||||
kind: "voice",
|
||||
reason: "insufficient_balance",
|
||||
reason: "insufficient_credits",
|
||||
creditBalance: 3,
|
||||
requiredCredits: 10,
|
||||
shortfallCredits: 7,
|
||||
|
||||
Reference in New Issue
Block a user