128 lines
3.5 KiB
TypeScript
128 lines
3.5 KiB
TypeScript
|
|
import type { DatabaseClient } from "./database";
|
|||
|
|
import {
|
|||
|
|
addTaskJoinWay,
|
|||
|
|
deleteJoinWay,
|
|||
|
|
getJoinWayQrCode,
|
|||
|
|
hasAppCredentials,
|
|||
|
|
listCustomerGroupChats,
|
|||
|
|
updateTaskJoinWay,
|
|||
|
|
type WecomConfig,
|
|||
|
|
type WecomGroupChat,
|
|||
|
|
} from "./wecom-client";
|
|||
|
|
|
|||
|
|
type FetchLike = typeof fetch;
|
|||
|
|
|
|||
|
|
function text(value: unknown) {
|
|||
|
|
return String(value ?? "").trim();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
export async function listOwnerCustomerChats(
|
|||
|
|
config: WecomConfig,
|
|||
|
|
ownerUserid: string,
|
|||
|
|
fetchImpl: FetchLike = fetch,
|
|||
|
|
): Promise<WecomGroupChat[]> {
|
|||
|
|
if (!hasAppCredentials(config)) {
|
|||
|
|
throw new Error("企业微信自建应用未配置(WECOM_CORP_ID / WECOM_AGENT_ID / WECOM_SECRET)");
|
|||
|
|
}
|
|||
|
|
const owner = text(ownerUserid);
|
|||
|
|
if (!owner) return [];
|
|||
|
|
return listCustomerGroupChats(config, fetchImpl, [owner]);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
export type BindTaskCustomerChatResult = {
|
|||
|
|
customerChatId: string;
|
|||
|
|
customerChatName: string;
|
|||
|
|
joinConfigId: string;
|
|||
|
|
joinQrCode: string;
|
|||
|
|
qrError?: string;
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
export async function bindTaskCustomerChat(
|
|||
|
|
db: DatabaseClient,
|
|||
|
|
params: { taskId: string; chatId: string; chatName: string },
|
|||
|
|
config: WecomConfig,
|
|||
|
|
fetchImpl: FetchLike = fetch,
|
|||
|
|
): Promise<BindTaskCustomerChatResult> {
|
|||
|
|
const taskId = text(params.taskId);
|
|||
|
|
const chatId = text(params.chatId);
|
|||
|
|
const chatName = text(params.chatName).slice(0, 255);
|
|||
|
|
if (!taskId) throw new Error("缺少 taskId");
|
|||
|
|
if (!chatId) throw new Error("请选择要绑定的客户群");
|
|||
|
|
|
|||
|
|
const task = await db
|
|||
|
|
.prepare("SELECT id, name, join_config_id FROM tasks WHERE id = ?")
|
|||
|
|
.bind(taskId)
|
|||
|
|
.first<{ id: string; name: string; join_config_id: string | null }>();
|
|||
|
|
if (!task) throw new Error("任务不存在");
|
|||
|
|
|
|||
|
|
const joinInput = {
|
|||
|
|
chatIdList: [chatId],
|
|||
|
|
roomBaseName: task.name,
|
|||
|
|
state: `task-${taskId}`,
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
let configId = text(task.join_config_id);
|
|||
|
|
if (configId) {
|
|||
|
|
try {
|
|||
|
|
await updateTaskJoinWay(config, { ...joinInput, configId }, fetchImpl);
|
|||
|
|
} catch {
|
|||
|
|
// 活码配置可能已被企微侧清理,降级为重新创建
|
|||
|
|
configId = (await addTaskJoinWay(config, joinInput, fetchImpl)).configId;
|
|||
|
|
}
|
|||
|
|
} else {
|
|||
|
|
configId = (await addTaskJoinWay(config, joinInput, fetchImpl)).configId;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
let joinQrCode = "";
|
|||
|
|
let qrError: string | undefined;
|
|||
|
|
try {
|
|||
|
|
joinQrCode = (await getJoinWayQrCode(config, configId, fetchImpl)).qrCode;
|
|||
|
|
} catch (error) {
|
|||
|
|
qrError = `活码二维码获取失败:${error instanceof Error ? error.message : String(error)}`;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
await db
|
|||
|
|
.prepare(
|
|||
|
|
`UPDATE tasks
|
|||
|
|
SET customer_chat_id = ?, customer_chat_name = ?, join_config_id = ?, join_qr_code = ?
|
|||
|
|
WHERE id = ?`,
|
|||
|
|
)
|
|||
|
|
.bind(chatId, chatName, configId, joinQrCode, taskId)
|
|||
|
|
.run();
|
|||
|
|
|
|||
|
|
return {
|
|||
|
|
customerChatId: chatId,
|
|||
|
|
customerChatName: chatName,
|
|||
|
|
joinConfigId: configId,
|
|||
|
|
joinQrCode,
|
|||
|
|
qrError,
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
export async function unbindTaskCustomerChat(
|
|||
|
|
db: DatabaseClient,
|
|||
|
|
taskId: string,
|
|||
|
|
config: WecomConfig,
|
|||
|
|
fetchImpl: FetchLike = fetch,
|
|||
|
|
): Promise<void> {
|
|||
|
|
const id = text(taskId);
|
|||
|
|
if (!id) throw new Error("缺少 taskId");
|
|||
|
|
const task = await db
|
|||
|
|
.prepare("SELECT join_config_id FROM tasks WHERE id = ?")
|
|||
|
|
.bind(id)
|
|||
|
|
.first<{ join_config_id: string | null }>();
|
|||
|
|
if (!task) throw new Error("任务不存在");
|
|||
|
|
const configId = text(task.join_config_id);
|
|||
|
|
if (configId) {
|
|||
|
|
await deleteJoinWay(config, configId, fetchImpl);
|
|||
|
|
}
|
|||
|
|
await db
|
|||
|
|
.prepare(
|
|||
|
|
`UPDATE tasks
|
|||
|
|
SET customer_chat_id = '', customer_chat_name = '', join_config_id = '', join_qr_code = ''
|
|||
|
|
WHERE id = ?`,
|
|||
|
|
)
|
|||
|
|
.bind(id)
|
|||
|
|
.run();
|
|||
|
|
}
|