refactor chat delivery to graphql + hatchet services
This commit is contained in:
@@ -8,7 +8,6 @@ import { normalizePhone, verifyPassword } from "../utils/password";
|
||||
import { persistAiMessage, runCrmAgentFor } from "../agent/crmAgent";
|
||||
import { buildChangeSet, captureSnapshot, rollbackChangeSet, rollbackChangeSetItems } from "../utils/changeSet";
|
||||
import type { ChangeSet } from "../utils/changeSet";
|
||||
import { enqueueTelegramSend } from "../queues/telegramSend";
|
||||
import { datasetRoot } from "../dataset/paths";
|
||||
|
||||
type GraphQLContext = {
|
||||
@@ -16,6 +15,11 @@ type GraphQLContext = {
|
||||
event: H3Event;
|
||||
};
|
||||
|
||||
type BackendGraphqlResponse<T> = {
|
||||
data?: T;
|
||||
errors?: Array<{ message?: string }>;
|
||||
};
|
||||
|
||||
function requireAuth(auth: AuthContext | null) {
|
||||
if (!auth) {
|
||||
throw new Error("Unauthorized");
|
||||
@@ -45,6 +49,79 @@ function asObject(value: unknown): Record<string, unknown> {
|
||||
return value as Record<string, unknown>;
|
||||
}
|
||||
|
||||
function asString(value: unknown) {
|
||||
if (typeof value !== "string") return null;
|
||||
const v = value.trim();
|
||||
return v || null;
|
||||
}
|
||||
|
||||
async function requestTelegramOutboundFromBackend(input: {
|
||||
omniMessageId: string;
|
||||
chatId: string;
|
||||
text: string;
|
||||
businessConnectionId?: string | null;
|
||||
}) {
|
||||
type Out = {
|
||||
requestTelegramOutbound: {
|
||||
ok: boolean;
|
||||
message: string;
|
||||
runId?: string | null;
|
||||
};
|
||||
};
|
||||
|
||||
const url = asString(process.env.BACKEND_GRAPHQL_URL);
|
||||
if (!url) {
|
||||
throw new Error("BACKEND_GRAPHQL_URL is required");
|
||||
}
|
||||
|
||||
const headers: Record<string, string> = {
|
||||
"content-type": "application/json",
|
||||
};
|
||||
|
||||
const secret = asString(process.env.BACKEND_GRAPHQL_SHARED_SECRET);
|
||||
if (secret) {
|
||||
headers["x-graphql-secret"] = secret;
|
||||
}
|
||||
|
||||
const query = `mutation RequestTelegramOutbound($input: TelegramOutboundTaskInput!) {
|
||||
requestTelegramOutbound(input: $input) {
|
||||
ok
|
||||
message
|
||||
runId
|
||||
}
|
||||
}`;
|
||||
|
||||
const response = await fetch(url, {
|
||||
method: "POST",
|
||||
headers,
|
||||
body: JSON.stringify({
|
||||
operationName: "RequestTelegramOutbound",
|
||||
query,
|
||||
variables: {
|
||||
input: {
|
||||
omniMessageId: input.omniMessageId,
|
||||
chatId: input.chatId,
|
||||
text: input.text,
|
||||
businessConnectionId: input.businessConnectionId ?? null,
|
||||
},
|
||||
},
|
||||
}),
|
||||
});
|
||||
|
||||
const payload = (await response.json()) as BackendGraphqlResponse<Out>;
|
||||
if (!response.ok || payload.errors?.length) {
|
||||
const message = payload.errors?.map((error) => error.message).filter(Boolean).join("; ") || `HTTP ${response.status}`;
|
||||
throw new Error(message);
|
||||
}
|
||||
|
||||
const result = payload.data?.requestTelegramOutbound;
|
||||
if (!result?.ok) {
|
||||
throw new Error(result?.message || "requestTelegramOutbound failed");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function readNestedString(obj: Record<string, unknown>, path: string[]): string {
|
||||
let current: unknown = obj;
|
||||
for (const segment of path) {
|
||||
@@ -1416,7 +1493,7 @@ async function createCommunication(auth: AuthContext | null, input: {
|
||||
channel: "TELEGRAM",
|
||||
},
|
||||
orderBy: { updatedAt: "desc" },
|
||||
select: { id: true, externalChatId: true, title: true },
|
||||
select: { id: true, externalChatId: true, businessConnectionId: true, title: true },
|
||||
});
|
||||
if (!thread) {
|
||||
throw new Error("telegram thread not found for contact");
|
||||
@@ -1464,7 +1541,12 @@ async function createCommunication(auth: AuthContext | null, input: {
|
||||
});
|
||||
|
||||
try {
|
||||
await enqueueTelegramSend({ omniMessageId: omniMessage.id });
|
||||
await requestTelegramOutboundFromBackend({
|
||||
omniMessageId: omniMessage.id,
|
||||
chatId: thread.externalChatId,
|
||||
text: content,
|
||||
businessConnectionId: thread.businessConnectionId ?? null,
|
||||
});
|
||||
} catch (error) {
|
||||
const message = error instanceof Error ? error.message : String(error);
|
||||
const existingOmni = await prisma.omniMessage.findUnique({
|
||||
@@ -1486,7 +1568,7 @@ async function createCommunication(auth: AuthContext | null, input: {
|
||||
},
|
||||
},
|
||||
}).catch(() => undefined);
|
||||
throw new Error(`telegram enqueue failed: ${message}`);
|
||||
throw new Error(`telegram outbound request failed: ${message}`);
|
||||
}
|
||||
} else {
|
||||
const existingInbox = await prisma.contactInbox.findFirst({
|
||||
|
||||
Reference in New Issue
Block a user