mirror of https://github.com/openclaw/openclaw.git
refactor: share zalo monitor processing context
This commit is contained in:
parent
b9f0effd55
commit
58baf22230
|
|
@ -75,6 +75,35 @@ const WEBHOOK_CLEANUP_TIMEOUT_MS = 5_000;
|
||||||
const ZALO_TYPING_TIMEOUT_MS = 5_000;
|
const ZALO_TYPING_TIMEOUT_MS = 5_000;
|
||||||
|
|
||||||
type ZaloCoreRuntime = ReturnType<typeof getZaloRuntime>;
|
type ZaloCoreRuntime = ReturnType<typeof getZaloRuntime>;
|
||||||
|
type ZaloStatusSink = (patch: { lastInboundAt?: number; lastOutboundAt?: number }) => void;
|
||||||
|
type ZaloProcessingContext = {
|
||||||
|
token: string;
|
||||||
|
account: ResolvedZaloAccount;
|
||||||
|
config: OpenClawConfig;
|
||||||
|
runtime: ZaloRuntimeEnv;
|
||||||
|
core: ZaloCoreRuntime;
|
||||||
|
statusSink?: ZaloStatusSink;
|
||||||
|
fetcher?: ZaloFetch;
|
||||||
|
};
|
||||||
|
type ZaloPollingLoopParams = ZaloProcessingContext & {
|
||||||
|
abortSignal: AbortSignal;
|
||||||
|
isStopped: () => boolean;
|
||||||
|
mediaMaxMb: number;
|
||||||
|
};
|
||||||
|
type ZaloUpdateProcessingParams = ZaloProcessingContext & {
|
||||||
|
update: ZaloUpdate;
|
||||||
|
mediaMaxMb: number;
|
||||||
|
};
|
||||||
|
type ZaloMessagePipelineParams = ZaloProcessingContext & {
|
||||||
|
message: ZaloMessage;
|
||||||
|
text?: string;
|
||||||
|
mediaPath?: string;
|
||||||
|
mediaType?: string;
|
||||||
|
};
|
||||||
|
type ZaloImageMessageParams = ZaloProcessingContext & {
|
||||||
|
message: ZaloMessage;
|
||||||
|
mediaMaxMb: number;
|
||||||
|
};
|
||||||
|
|
||||||
function formatZaloError(error: unknown): string {
|
function formatZaloError(error: unknown): string {
|
||||||
if (error instanceof Error) {
|
if (error instanceof Error) {
|
||||||
|
|
@ -135,32 +164,21 @@ export async function handleZaloWebhookRequest(
|
||||||
res: ServerResponse,
|
res: ServerResponse,
|
||||||
): Promise<boolean> {
|
): Promise<boolean> {
|
||||||
return handleZaloWebhookRequestInternal(req, res, async ({ update, target }) => {
|
return handleZaloWebhookRequestInternal(req, res, async ({ update, target }) => {
|
||||||
await processUpdate(
|
await processUpdate({
|
||||||
update,
|
update,
|
||||||
target.token,
|
token: target.token,
|
||||||
target.account,
|
account: target.account,
|
||||||
target.config,
|
config: target.config,
|
||||||
target.runtime,
|
runtime: target.runtime,
|
||||||
target.core as ZaloCoreRuntime,
|
core: target.core as ZaloCoreRuntime,
|
||||||
target.mediaMaxMb,
|
mediaMaxMb: target.mediaMaxMb,
|
||||||
target.statusSink,
|
statusSink: target.statusSink,
|
||||||
target.fetcher,
|
fetcher: target.fetcher,
|
||||||
);
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function startPollingLoop(params: {
|
function startPollingLoop(params: ZaloPollingLoopParams) {
|
||||||
token: string;
|
|
||||||
account: ResolvedZaloAccount;
|
|
||||||
config: OpenClawConfig;
|
|
||||||
runtime: ZaloRuntimeEnv;
|
|
||||||
core: ZaloCoreRuntime;
|
|
||||||
abortSignal: AbortSignal;
|
|
||||||
isStopped: () => boolean;
|
|
||||||
mediaMaxMb: number;
|
|
||||||
statusSink?: (patch: { lastInboundAt?: number; lastOutboundAt?: number }) => void;
|
|
||||||
fetcher?: ZaloFetch;
|
|
||||||
}) {
|
|
||||||
const {
|
const {
|
||||||
token,
|
token,
|
||||||
account,
|
account,
|
||||||
|
|
@ -174,6 +192,16 @@ function startPollingLoop(params: {
|
||||||
fetcher,
|
fetcher,
|
||||||
} = params;
|
} = params;
|
||||||
const pollTimeout = 30;
|
const pollTimeout = 30;
|
||||||
|
const processingContext = {
|
||||||
|
token,
|
||||||
|
account,
|
||||||
|
config,
|
||||||
|
runtime,
|
||||||
|
core,
|
||||||
|
mediaMaxMb,
|
||||||
|
statusSink,
|
||||||
|
fetcher,
|
||||||
|
};
|
||||||
|
|
||||||
runtime.log?.(`[${account.accountId}] Zalo polling loop started timeout=${String(pollTimeout)}s`);
|
runtime.log?.(`[${account.accountId}] Zalo polling loop started timeout=${String(pollTimeout)}s`);
|
||||||
|
|
||||||
|
|
@ -186,17 +214,10 @@ function startPollingLoop(params: {
|
||||||
const response = await getUpdates(token, { timeout: pollTimeout }, fetcher);
|
const response = await getUpdates(token, { timeout: pollTimeout }, fetcher);
|
||||||
if (response.ok && response.result) {
|
if (response.ok && response.result) {
|
||||||
statusSink?.({ lastInboundAt: Date.now() });
|
statusSink?.({ lastInboundAt: Date.now() });
|
||||||
await processUpdate(
|
await processUpdate({
|
||||||
response.result,
|
update: response.result,
|
||||||
token,
|
...processingContext,
|
||||||
account,
|
});
|
||||||
config,
|
|
||||||
runtime,
|
|
||||||
core,
|
|
||||||
mediaMaxMb,
|
|
||||||
statusSink,
|
|
||||||
fetcher,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (err instanceof ZaloApiError && err.isPollingTimeout) {
|
if (err instanceof ZaloApiError && err.isPollingTimeout) {
|
||||||
|
|
@ -215,38 +236,27 @@ function startPollingLoop(params: {
|
||||||
void poll();
|
void poll();
|
||||||
}
|
}
|
||||||
|
|
||||||
async function processUpdate(
|
async function processUpdate(params: ZaloUpdateProcessingParams): Promise<void> {
|
||||||
update: ZaloUpdate,
|
const { update, token, account, config, runtime, core, mediaMaxMb, statusSink, fetcher } = params;
|
||||||
token: string,
|
|
||||||
account: ResolvedZaloAccount,
|
|
||||||
config: OpenClawConfig,
|
|
||||||
runtime: ZaloRuntimeEnv,
|
|
||||||
core: ZaloCoreRuntime,
|
|
||||||
mediaMaxMb: number,
|
|
||||||
statusSink?: (patch: { lastInboundAt?: number; lastOutboundAt?: number }) => void,
|
|
||||||
fetcher?: ZaloFetch,
|
|
||||||
): Promise<void> {
|
|
||||||
const { event_name, message } = update;
|
const { event_name, message } = update;
|
||||||
|
const sharedContext = { token, account, config, runtime, core, statusSink, fetcher };
|
||||||
if (!message) {
|
if (!message) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (event_name) {
|
switch (event_name) {
|
||||||
case "message.text.received":
|
case "message.text.received":
|
||||||
await handleTextMessage(message, token, account, config, runtime, core, statusSink, fetcher);
|
await handleTextMessage({
|
||||||
|
message,
|
||||||
|
...sharedContext,
|
||||||
|
});
|
||||||
break;
|
break;
|
||||||
case "message.image.received":
|
case "message.image.received":
|
||||||
await handleImageMessage(
|
await handleImageMessage({
|
||||||
message,
|
message,
|
||||||
token,
|
...sharedContext,
|
||||||
account,
|
|
||||||
config,
|
|
||||||
runtime,
|
|
||||||
core,
|
|
||||||
mediaMaxMb,
|
mediaMaxMb,
|
||||||
statusSink,
|
});
|
||||||
fetcher,
|
|
||||||
);
|
|
||||||
break;
|
break;
|
||||||
case "message.sticker.received":
|
case "message.sticker.received":
|
||||||
logVerbose(core, runtime, `[${account.accountId}] Received sticker from ${message.from.id}`);
|
logVerbose(core, runtime, `[${account.accountId}] Received sticker from ${message.from.id}`);
|
||||||
|
|
@ -262,46 +272,24 @@ async function processUpdate(
|
||||||
}
|
}
|
||||||
|
|
||||||
async function handleTextMessage(
|
async function handleTextMessage(
|
||||||
message: ZaloMessage,
|
params: ZaloProcessingContext & { message: ZaloMessage },
|
||||||
token: string,
|
|
||||||
account: ResolvedZaloAccount,
|
|
||||||
config: OpenClawConfig,
|
|
||||||
runtime: ZaloRuntimeEnv,
|
|
||||||
core: ZaloCoreRuntime,
|
|
||||||
statusSink?: (patch: { lastInboundAt?: number; lastOutboundAt?: number }) => void,
|
|
||||||
fetcher?: ZaloFetch,
|
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
|
const { message } = params;
|
||||||
const { text } = message;
|
const { text } = message;
|
||||||
if (!text?.trim()) {
|
if (!text?.trim()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await processMessageWithPipeline({
|
await processMessageWithPipeline({
|
||||||
message,
|
...params,
|
||||||
token,
|
|
||||||
account,
|
|
||||||
config,
|
|
||||||
runtime,
|
|
||||||
core,
|
|
||||||
text,
|
text,
|
||||||
mediaPath: undefined,
|
mediaPath: undefined,
|
||||||
mediaType: undefined,
|
mediaType: undefined,
|
||||||
statusSink,
|
|
||||||
fetcher,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function handleImageMessage(
|
async function handleImageMessage(params: ZaloImageMessageParams): Promise<void> {
|
||||||
message: ZaloMessage,
|
const { message, mediaMaxMb } = params;
|
||||||
token: string,
|
|
||||||
account: ResolvedZaloAccount,
|
|
||||||
config: OpenClawConfig,
|
|
||||||
runtime: ZaloRuntimeEnv,
|
|
||||||
core: ZaloCoreRuntime,
|
|
||||||
mediaMaxMb: number,
|
|
||||||
statusSink?: (patch: { lastInboundAt?: number; lastOutboundAt?: number }) => void,
|
|
||||||
fetcher?: ZaloFetch,
|
|
||||||
): Promise<void> {
|
|
||||||
const { photo, caption } = message;
|
const { photo, caption } = message;
|
||||||
|
|
||||||
let mediaPath: string | undefined;
|
let mediaPath: string | undefined;
|
||||||
|
|
@ -325,33 +313,14 @@ async function handleImageMessage(
|
||||||
}
|
}
|
||||||
|
|
||||||
await processMessageWithPipeline({
|
await processMessageWithPipeline({
|
||||||
message,
|
...params,
|
||||||
token,
|
|
||||||
account,
|
|
||||||
config,
|
|
||||||
runtime,
|
|
||||||
core,
|
|
||||||
text: caption,
|
text: caption,
|
||||||
mediaPath,
|
mediaPath,
|
||||||
mediaType,
|
mediaType,
|
||||||
statusSink,
|
|
||||||
fetcher,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function processMessageWithPipeline(params: {
|
async function processMessageWithPipeline(params: ZaloMessagePipelineParams): Promise<void> {
|
||||||
message: ZaloMessage;
|
|
||||||
token: string;
|
|
||||||
account: ResolvedZaloAccount;
|
|
||||||
config: OpenClawConfig;
|
|
||||||
runtime: ZaloRuntimeEnv;
|
|
||||||
core: ZaloCoreRuntime;
|
|
||||||
text?: string;
|
|
||||||
mediaPath?: string;
|
|
||||||
mediaType?: string;
|
|
||||||
statusSink?: (patch: { lastInboundAt?: number; lastOutboundAt?: number }) => void;
|
|
||||||
fetcher?: ZaloFetch;
|
|
||||||
}): Promise<void> {
|
|
||||||
const {
|
const {
|
||||||
message,
|
message,
|
||||||
token,
|
token,
|
||||||
|
|
@ -609,7 +578,7 @@ async function deliverZaloReply(params: {
|
||||||
core: ZaloCoreRuntime;
|
core: ZaloCoreRuntime;
|
||||||
config: OpenClawConfig;
|
config: OpenClawConfig;
|
||||||
accountId?: string;
|
accountId?: string;
|
||||||
statusSink?: (patch: { lastInboundAt?: number; lastOutboundAt?: number }) => void;
|
statusSink?: ZaloStatusSink;
|
||||||
fetcher?: ZaloFetch;
|
fetcher?: ZaloFetch;
|
||||||
tableMode?: MarkdownTableMode;
|
tableMode?: MarkdownTableMode;
|
||||||
}): Promise<void> {
|
}): Promise<void> {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue