feat(payment): add chat support discounts and gratitude
Docker Image / Build and Push Docker Image (push) Successful in 2m14s
Docker Image / Build and Push Docker Image (push) Successful in 2m14s
(cherry picked from commit ef9b79bc83)
This commit is contained in:
@@ -0,0 +1,34 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
|
||||
import { appendCommercialMessage } from "../helper/commercial-message";
|
||||
|
||||
describe("chat commercial message", () => {
|
||||
const incoming = {
|
||||
messageId: "payment-thanks-1",
|
||||
message: "Thank you for supporting me.",
|
||||
characterId: "maya-tan",
|
||||
createdAt: "2026-07-28T08:30:00.000Z",
|
||||
};
|
||||
|
||||
it("appends one persisted payment thank-you to the matching character chat", () => {
|
||||
const messages = appendCommercialMessage([], "maya-tan", incoming);
|
||||
|
||||
expect(messages).toHaveLength(1);
|
||||
expect(messages[0]).toMatchObject({
|
||||
remoteId: "payment-thanks-1",
|
||||
content: "Thank you for supporting me.",
|
||||
isFromAI: true,
|
||||
});
|
||||
});
|
||||
|
||||
it("ignores duplicate delivery and a message for another character", () => {
|
||||
const messages = appendCommercialMessage([], "maya-tan", incoming);
|
||||
|
||||
expect(appendCommercialMessage(messages, "maya-tan", incoming)).toEqual(
|
||||
messages,
|
||||
);
|
||||
expect(appendCommercialMessage(messages, "elio", incoming)).toEqual(
|
||||
messages,
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -28,6 +28,15 @@ export type ChatEvent =
|
||||
}
|
||||
| { type: "ChatOlderHistoryLoadFailed"; error: unknown }
|
||||
| { type: "ChatHistoryRefreshRequested" }
|
||||
| {
|
||||
type: "ChatCommercialMessageReceived";
|
||||
message: {
|
||||
messageId: string;
|
||||
message: string;
|
||||
characterId: string;
|
||||
createdAt: string;
|
||||
};
|
||||
}
|
||||
// Chat domain events.
|
||||
| { type: "ChatSendMessage"; content: string }
|
||||
| { type: "ChatSendImage"; imageBase64: string }
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
import { createRemoteUiMessageIdentity, type UiMessage } from "../ui-message";
|
||||
import { todayString } from "@/utils/date";
|
||||
|
||||
export interface IncomingCommercialMessage {
|
||||
messageId: string;
|
||||
message: string;
|
||||
characterId: string;
|
||||
createdAt: string;
|
||||
}
|
||||
|
||||
export function appendCommercialMessage(
|
||||
messages: readonly UiMessage[],
|
||||
activeCharacterId: string,
|
||||
incoming: IncomingCommercialMessage,
|
||||
): UiMessage[] {
|
||||
if (incoming.characterId !== activeCharacterId) return [...messages];
|
||||
if (messages.some((message) => message.remoteId === incoming.messageId)) {
|
||||
return [...messages];
|
||||
}
|
||||
const createdAt = new Date(incoming.createdAt);
|
||||
return [
|
||||
...messages,
|
||||
{
|
||||
...createRemoteUiMessageIdentity(incoming.messageId, true),
|
||||
content: incoming.message,
|
||||
isFromAI: true,
|
||||
date: todayString(Number.isNaN(createdAt.getTime()) ? new Date() : createdAt),
|
||||
},
|
||||
];
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
import { createChatPromotionState } from "../helper/promotion";
|
||||
import { appendCommercialMessage } from "../helper/commercial-message";
|
||||
import { shouldPromptUnlockHistory } from "../helper/unlock";
|
||||
import { createInitialChatState } from "../chat-state";
|
||||
import {
|
||||
@@ -53,6 +54,19 @@ const injectPromotionAction = unlockMachineSetup.assign(({ event }) => {
|
||||
|
||||
const clearPromotionAction = unlockMachineSetup.assign({ promotion: null });
|
||||
|
||||
const appendCommercialMessageAction = unlockMachineSetup.assign(
|
||||
({ context, event }) => {
|
||||
if (event.type !== "ChatCommercialMessageReceived") return {};
|
||||
return {
|
||||
messages: appendCommercialMessage(
|
||||
context.messages,
|
||||
context.characterId,
|
||||
event.message,
|
||||
),
|
||||
};
|
||||
},
|
||||
);
|
||||
|
||||
export const chatMachineSetup = unlockMachineSetup.extend({
|
||||
actions: {
|
||||
startGuestSession: startGuestSessionAction,
|
||||
@@ -60,6 +74,7 @@ export const chatMachineSetup = unlockMachineSetup.extend({
|
||||
clearChatSession: clearChatSessionAction,
|
||||
injectPromotion: injectPromotionAction,
|
||||
clearPromotion: clearPromotionAction,
|
||||
appendCommercialMessage: appendCommercialMessageAction,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -258,6 +273,7 @@ export const chatRootStateConfig = chatMachineSetup.createStateConfig({
|
||||
on: {
|
||||
ChatPromotionInjected: { actions: "injectPromotion" },
|
||||
ChatPromotionCleared: { actions: "clearPromotion" },
|
||||
ChatCommercialMessageReceived: { actions: "appendCommercialMessage" },
|
||||
},
|
||||
states: {
|
||||
idle: idleState,
|
||||
|
||||
Reference in New Issue
Block a user