@lih-x-x/kmr 1.0.26 → 1.0.28
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunk-4KKCJLHW.js +107 -0
- package/dist/chunk-KK3DMZOA.js +35 -0
- package/dist/chunk-SBNKH4H7.js +68 -0
- package/dist/cli.js +25 -4
- package/dist/client-CKWRSYEN.js +12 -0
- package/dist/index.js +20 -198
- package/dist/sync-E4SW7QFZ.js +6 -0
- package/dist/taskCreator-FMA77Z7K.js +6 -0
- package/package.json +1 -1
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
// src/lark/client.ts
|
|
2
|
+
import * as lark from "@larksuiteoapi/node-sdk";
|
|
3
|
+
function createLarkClient(config) {
|
|
4
|
+
return new lark.Client({
|
|
5
|
+
appId: config.lark.appId,
|
|
6
|
+
appSecret: config.lark.appSecret,
|
|
7
|
+
appType: lark.AppType.SelfBuild
|
|
8
|
+
});
|
|
9
|
+
}
|
|
10
|
+
async function getBotOpenId(client) {
|
|
11
|
+
try {
|
|
12
|
+
const res = await client.request({
|
|
13
|
+
method: "GET",
|
|
14
|
+
url: "/open-apis/bot/v3/info"
|
|
15
|
+
});
|
|
16
|
+
console.log(`[bot] bot info response:`, JSON.stringify(res?.data || res, null, 2));
|
|
17
|
+
const openId = res.data?.bot?.open_id || res.bot?.open_id || "";
|
|
18
|
+
if (openId) {
|
|
19
|
+
console.log(`[bot] \u673A\u5668\u4EBA open_id: ${openId}`);
|
|
20
|
+
} else {
|
|
21
|
+
console.warn(`[bot] \u672A\u80FD\u83B7\u53D6\u673A\u5668\u4EBA open_id\uFF0C\u7FA4\u804A @\u5224\u65AD\u53EF\u80FD\u4E0D\u51C6\u786E`);
|
|
22
|
+
}
|
|
23
|
+
return openId;
|
|
24
|
+
} catch (err) {
|
|
25
|
+
console.error(`[bot] \u83B7\u53D6\u673A\u5668\u4EBA\u4FE1\u606F\u5931\u8D25:`, err.message);
|
|
26
|
+
return "";
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
function createEventDispatcher(botOpenId, onMessage) {
|
|
30
|
+
const dispatcher = new lark.EventDispatcher({});
|
|
31
|
+
const processedMessages = /* @__PURE__ */ new Set();
|
|
32
|
+
dispatcher.register({
|
|
33
|
+
"im.message.receive_v1": async (data) => {
|
|
34
|
+
console.log(`[recv] \u6536\u5230\u98DE\u4E66\u4E8B\u4EF6:`, JSON.stringify(data, null, 2));
|
|
35
|
+
const message = data.message;
|
|
36
|
+
if (message.message_type !== "text") {
|
|
37
|
+
console.log(`[recv] \u5FFD\u7565\u975E\u6587\u672C\u6D88\u606F, type=${message.message_type}`);
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
const messageId = message.message_id;
|
|
41
|
+
const senderType = data.sender?.sender_type;
|
|
42
|
+
if (senderType === "app") {
|
|
43
|
+
console.log(`[recv] \u5FFD\u7565\u673A\u5668\u4EBA\u81EA\u8EAB\u6D88\u606F: ${messageId}`);
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
if (processedMessages.has(messageId)) {
|
|
47
|
+
console.log(`[dedup] \u8DF3\u8FC7\u91CD\u590D\u6D88\u606F: ${messageId}`);
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
processedMessages.add(messageId);
|
|
51
|
+
const createTime = parseInt(message.create_time, 10);
|
|
52
|
+
if (createTime && Date.now() - createTime > 2 * 60 * 1e3) {
|
|
53
|
+
console.log(`[dedup] \u8DF3\u8FC7\u8FC7\u671F\u6D88\u606F: ${messageId}, \u521B\u5EFA\u4E8E ${new Date(createTime).toISOString()}`);
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
if (processedMessages.size > 1e3) {
|
|
57
|
+
const first = processedMessages.values().next().value;
|
|
58
|
+
processedMessages.delete(first);
|
|
59
|
+
}
|
|
60
|
+
const content = JSON.parse(message.content);
|
|
61
|
+
let text = content.text || "";
|
|
62
|
+
const chatId = message.chat_id;
|
|
63
|
+
const mentions = message.mentions || [];
|
|
64
|
+
if (mentions.length > 0) {
|
|
65
|
+
console.log(`[recv] mentions:`, JSON.stringify(mentions));
|
|
66
|
+
}
|
|
67
|
+
const isMentioned = mentions.length > 0 && (!botOpenId || mentions.some((m) => {
|
|
68
|
+
const mentionOpenId = m.id?.open_id || m.id_str || "";
|
|
69
|
+
return mentionOpenId === botOpenId;
|
|
70
|
+
}));
|
|
71
|
+
const isGroup = message.chat_type === "group";
|
|
72
|
+
if (mentions.length > 0) {
|
|
73
|
+
for (const mention of mentions) {
|
|
74
|
+
if (mention.key) {
|
|
75
|
+
text = text.replace(mention.key, "").trim();
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
if (isGroup && !isMentioned) {
|
|
80
|
+
const hasDocLink = /(https?:\/\/[^\s]*feishu\.cn\/[^\s]+)/.test(text);
|
|
81
|
+
if (!hasDocLink) {
|
|
82
|
+
console.log(`[recv] \u7FA4\u804A\u975E@\u673A\u5668\u4EBA\u6D88\u606F\u4E14\u975E\u6587\u6863\u94FE\u63A5, \u5FFD\u7565`);
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
console.log(`[recv] \u89E3\u6790\u6D88\u606F: messageId=${messageId}, chatId=${chatId}, chatType=${message.chat_type}, text="${text}"`);
|
|
87
|
+
const senderId = data.sender?.sender_id?.open_id || "unknown";
|
|
88
|
+
await onMessage(messageId, text, chatId, senderId, { isGroup, isMentioned });
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
return dispatcher;
|
|
92
|
+
}
|
|
93
|
+
function startWSClient(client, dispatcher) {
|
|
94
|
+
const wsClient = new lark.WSClient({
|
|
95
|
+
appId: client.appId,
|
|
96
|
+
appSecret: client.appSecret,
|
|
97
|
+
loggerLevel: lark.LoggerLevel.info
|
|
98
|
+
});
|
|
99
|
+
wsClient.start({ eventDispatcher: dispatcher });
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export {
|
|
103
|
+
createLarkClient,
|
|
104
|
+
getBotOpenId,
|
|
105
|
+
createEventDispatcher,
|
|
106
|
+
startWSClient
|
|
107
|
+
};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
// src/task/sync.ts
|
|
2
|
+
async function syncTaskStatuses(store, taskCreator) {
|
|
3
|
+
console.log("[task-sync] \u5F00\u59CB\u540C\u6B65\u98DE\u4E66\u4EFB\u52A1\u72B6\u6001...");
|
|
4
|
+
try {
|
|
5
|
+
const meetings = await store.list();
|
|
6
|
+
let updatedCount = 0;
|
|
7
|
+
for (const meeting of meetings) {
|
|
8
|
+
if (!meeting.createdTasks || meeting.createdTasks.length === 0) continue;
|
|
9
|
+
let changed = false;
|
|
10
|
+
for (const task of meeting.createdTasks) {
|
|
11
|
+
if (!task.taskId || task.status === "completed") continue;
|
|
12
|
+
const result = await taskCreator.getTaskStatus(task.taskId);
|
|
13
|
+
if (result && result.status !== (task.status || "open")) {
|
|
14
|
+
task.status = result.status;
|
|
15
|
+
task.completedAt = result.completedAt;
|
|
16
|
+
changed = true;
|
|
17
|
+
if (task.todoIndex != null && meeting.todos[task.todoIndex]) {
|
|
18
|
+
meeting.todos[task.todoIndex].status = result.status;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
if (changed) {
|
|
23
|
+
await store.save(meeting);
|
|
24
|
+
updatedCount++;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
console.log(`[task-sync] \u540C\u6B65\u5B8C\u6210, \u66F4\u65B0\u4E86 ${updatedCount} \u6761\u4F1A\u8BAE\u8BB0\u5F55`);
|
|
28
|
+
} catch (err) {
|
|
29
|
+
console.error("[task-sync] \u540C\u6B65\u5931\u8D25:", err.message);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export {
|
|
34
|
+
syncTaskStatuses
|
|
35
|
+
};
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
// src/lark/taskCreator.ts
|
|
2
|
+
var TaskCreator = class {
|
|
3
|
+
constructor(client) {
|
|
4
|
+
this.client = client;
|
|
5
|
+
}
|
|
6
|
+
client;
|
|
7
|
+
async createTask(params) {
|
|
8
|
+
const taskBody = {
|
|
9
|
+
summary: params.summary
|
|
10
|
+
};
|
|
11
|
+
if (params.due) {
|
|
12
|
+
const dueDate = /* @__PURE__ */ new Date(params.due + "T23:59:59+08:00");
|
|
13
|
+
taskBody.due = {
|
|
14
|
+
timestamp: dueDate.getTime().toString(),
|
|
15
|
+
is_all_day: true
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
if (params.description) {
|
|
19
|
+
taskBody.description = params.description;
|
|
20
|
+
}
|
|
21
|
+
if (params.assigneeOpenId) {
|
|
22
|
+
taskBody.members = [
|
|
23
|
+
{
|
|
24
|
+
id: params.assigneeOpenId,
|
|
25
|
+
type: "user",
|
|
26
|
+
role: "assignee"
|
|
27
|
+
}
|
|
28
|
+
];
|
|
29
|
+
}
|
|
30
|
+
console.log(`[task] \u521B\u5EFA\u98DE\u4E66\u4EFB\u52A1: ${params.summary}`);
|
|
31
|
+
console.log(`[task] \u8BF7\u6C42\u4F53:`, JSON.stringify(taskBody, null, 2));
|
|
32
|
+
const response = await this.client.task.v2.task.create({
|
|
33
|
+
params: { user_id_type: "open_id" },
|
|
34
|
+
data: taskBody
|
|
35
|
+
});
|
|
36
|
+
console.log(`[task] API \u8FD4\u56DE:`, JSON.stringify(response.data, null, 2));
|
|
37
|
+
const taskId = response.data?.task?.guid || "";
|
|
38
|
+
const url = response.data?.task?.url || "";
|
|
39
|
+
console.log(`[task] \u4EFB\u52A1\u521B\u5EFA\u6210\u529F: taskId=${taskId}`);
|
|
40
|
+
return { taskId, url };
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* 查询飞书任务的最新状态
|
|
44
|
+
*/
|
|
45
|
+
async getTaskStatus(taskId) {
|
|
46
|
+
try {
|
|
47
|
+
const response = await this.client.task.v2.task.get({
|
|
48
|
+
path: { task_guid: taskId }
|
|
49
|
+
});
|
|
50
|
+
const task = response.data?.task;
|
|
51
|
+
if (!task) return null;
|
|
52
|
+
console.log(`[task-sync] \u4EFB\u52A1 ${taskId} \u72B6\u6001: completed_at="${task.completed_at}"`);
|
|
53
|
+
const completedAt = task.completed_at || "";
|
|
54
|
+
const ts = parseInt(completedAt, 10);
|
|
55
|
+
const isCompleted = ts > 0;
|
|
56
|
+
const status = isCompleted ? "completed" : "open";
|
|
57
|
+
const completedAtISO = isCompleted ? new Date(ts).toISOString() : void 0;
|
|
58
|
+
return { status, completedAt: completedAtISO };
|
|
59
|
+
} catch (err) {
|
|
60
|
+
console.error(`[task-sync] \u67E5\u8BE2\u4EFB\u52A1\u72B6\u6001\u5931\u8D25: taskId=${taskId}`, err.message);
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
export {
|
|
67
|
+
TaskCreator
|
|
68
|
+
};
|
package/dist/cli.js
CHANGED
|
@@ -6,9 +6,9 @@ async function checkUpdate() {
|
|
|
6
6
|
try {
|
|
7
7
|
const res = await fetch(`https://registry.npmjs.org/${"@lih-x-x/kmr"}/latest`, { signal: AbortSignal.timeout(3e3) });
|
|
8
8
|
const data = await res.json();
|
|
9
|
-
if (data.version && data.version !== "1.0.
|
|
9
|
+
if (data.version && data.version !== "1.0.28") {
|
|
10
10
|
console.log(`
|
|
11
|
-
\u2B06\uFE0F \u65B0\u7248\u672C\u53EF\u7528: ${"1.0.
|
|
11
|
+
\u2B06\uFE0F \u65B0\u7248\u672C\u53EF\u7528: ${"1.0.28"} \u2192 ${data.version}`);
|
|
12
12
|
console.log(` \u8FD0\u884C npm install -g ${"@lih-x-x/kmr"} \u66F4\u65B0
|
|
13
13
|
`);
|
|
14
14
|
}
|
|
@@ -54,12 +54,18 @@ KMR\uFF08Key Meetings Record\uFF09\u2014 \u4F1A\u8BAE\u6316\u6398\u673A
|
|
|
54
54
|
kmr --help \u663E\u793A\u5E2E\u52A9
|
|
55
55
|
`);
|
|
56
56
|
} else if (command === "--version" || command === "-v") {
|
|
57
|
-
console.log("1.0.
|
|
57
|
+
console.log("1.0.28");
|
|
58
58
|
} else if (command === "list") {
|
|
59
59
|
const { loadConfig } = await import("./config-L2SVVMAR.js");
|
|
60
60
|
const { JsonStore } = await import("./jsonStore-AL73KEUG.js");
|
|
61
|
+
const { createLarkClient } = await import("./client-CKWRSYEN.js");
|
|
62
|
+
const { TaskCreator } = await import("./taskCreator-FMA77Z7K.js");
|
|
63
|
+
const { syncTaskStatuses } = await import("./sync-E4SW7QFZ.js");
|
|
61
64
|
const config = loadConfig();
|
|
62
65
|
const store = new JsonStore(config.storage.dataDir);
|
|
66
|
+
const client = createLarkClient(config);
|
|
67
|
+
const taskCreator = new TaskCreator(client);
|
|
68
|
+
await syncTaskStatuses(store, taskCreator);
|
|
63
69
|
const all = await store.list();
|
|
64
70
|
all.sort((a, b) => b.extractedAt.localeCompare(a.extractedAt));
|
|
65
71
|
if (all.length === 0) {
|
|
@@ -75,7 +81,14 @@ KMR\uFF08Key Meetings Record\uFF09\u2014 \u4F1A\u8BAE\u6316\u6398\u673A
|
|
|
75
81
|
}
|
|
76
82
|
const { loadConfig } = await import("./config-L2SVVMAR.js");
|
|
77
83
|
const { JsonStore } = await import("./jsonStore-AL73KEUG.js");
|
|
78
|
-
const
|
|
84
|
+
const { createLarkClient } = await import("./client-CKWRSYEN.js");
|
|
85
|
+
const { TaskCreator } = await import("./taskCreator-FMA77Z7K.js");
|
|
86
|
+
const { syncTaskStatuses } = await import("./sync-E4SW7QFZ.js");
|
|
87
|
+
const config = loadConfig();
|
|
88
|
+
const store = new JsonStore(config.storage.dataDir);
|
|
89
|
+
const client = createLarkClient(config);
|
|
90
|
+
const taskCreator = new TaskCreator(client);
|
|
91
|
+
await syncTaskStatuses(store, taskCreator);
|
|
79
92
|
const record = await store.load(id);
|
|
80
93
|
if (!record) {
|
|
81
94
|
console.error(`\u672A\u627E\u5230\u8BB0\u5F55: ${id}`);
|
|
@@ -102,7 +115,15 @@ KMR\uFF08Key Meetings Record\uFF09\u2014 \u4F1A\u8BAE\u6316\u6398\u673A
|
|
|
102
115
|
const { loadConfig } = await import("./config-L2SVVMAR.js");
|
|
103
116
|
const { ClaudeCodeProvider } = await import("./claudeCode-PPRQZG5K.js");
|
|
104
117
|
const { QueryHandler } = await import("./handler-46CQQIA2.js");
|
|
118
|
+
const { JsonStore } = await import("./jsonStore-AL73KEUG.js");
|
|
119
|
+
const { createLarkClient } = await import("./client-CKWRSYEN.js");
|
|
120
|
+
const { TaskCreator } = await import("./taskCreator-FMA77Z7K.js");
|
|
121
|
+
const { syncTaskStatuses } = await import("./sync-E4SW7QFZ.js");
|
|
105
122
|
const config = loadConfig();
|
|
123
|
+
const store = new JsonStore(config.storage.dataDir);
|
|
124
|
+
const client = createLarkClient(config);
|
|
125
|
+
const taskCreator = new TaskCreator(client);
|
|
126
|
+
await syncTaskStatuses(store, taskCreator);
|
|
106
127
|
const agent = new ClaudeCodeProvider(config.agent.timeout);
|
|
107
128
|
const handler = new QueryHandler(agent, config.storage.dataDir);
|
|
108
129
|
const results = await handler.find(query);
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,21 @@
|
|
|
1
|
+
import {
|
|
2
|
+
QueryHandler
|
|
3
|
+
} from "./chunk-SGTENG37.js";
|
|
1
4
|
import {
|
|
2
5
|
JsonStore
|
|
3
6
|
} from "./chunk-TUCCS6QJ.js";
|
|
7
|
+
import {
|
|
8
|
+
createEventDispatcher,
|
|
9
|
+
createLarkClient,
|
|
10
|
+
getBotOpenId,
|
|
11
|
+
startWSClient
|
|
12
|
+
} from "./chunk-4KKCJLHW.js";
|
|
13
|
+
import {
|
|
14
|
+
TaskCreator
|
|
15
|
+
} from "./chunk-SBNKH4H7.js";
|
|
16
|
+
import {
|
|
17
|
+
syncTaskStatuses
|
|
18
|
+
} from "./chunk-KK3DMZOA.js";
|
|
4
19
|
import {
|
|
5
20
|
ClaudeCodeProvider,
|
|
6
21
|
getExecEnv
|
|
@@ -10,110 +25,6 @@ import {
|
|
|
10
25
|
getAgentProvider,
|
|
11
26
|
loadConfig
|
|
12
27
|
} from "./chunk-ZXGVA5QX.js";
|
|
13
|
-
import {
|
|
14
|
-
QueryHandler
|
|
15
|
-
} from "./chunk-SGTENG37.js";
|
|
16
|
-
|
|
17
|
-
// src/lark/client.ts
|
|
18
|
-
import * as lark from "@larksuiteoapi/node-sdk";
|
|
19
|
-
function createLarkClient(config) {
|
|
20
|
-
return new lark.Client({
|
|
21
|
-
appId: config.lark.appId,
|
|
22
|
-
appSecret: config.lark.appSecret,
|
|
23
|
-
appType: lark.AppType.SelfBuild
|
|
24
|
-
});
|
|
25
|
-
}
|
|
26
|
-
async function getBotOpenId(client) {
|
|
27
|
-
try {
|
|
28
|
-
const res = await client.request({
|
|
29
|
-
method: "GET",
|
|
30
|
-
url: "/open-apis/bot/v3/info"
|
|
31
|
-
});
|
|
32
|
-
console.log(`[bot] bot info response:`, JSON.stringify(res?.data || res, null, 2));
|
|
33
|
-
const openId = res.data?.bot?.open_id || res.bot?.open_id || "";
|
|
34
|
-
if (openId) {
|
|
35
|
-
console.log(`[bot] \u673A\u5668\u4EBA open_id: ${openId}`);
|
|
36
|
-
} else {
|
|
37
|
-
console.warn(`[bot] \u672A\u80FD\u83B7\u53D6\u673A\u5668\u4EBA open_id\uFF0C\u7FA4\u804A @\u5224\u65AD\u53EF\u80FD\u4E0D\u51C6\u786E`);
|
|
38
|
-
}
|
|
39
|
-
return openId;
|
|
40
|
-
} catch (err) {
|
|
41
|
-
console.error(`[bot] \u83B7\u53D6\u673A\u5668\u4EBA\u4FE1\u606F\u5931\u8D25:`, err.message);
|
|
42
|
-
return "";
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
function createEventDispatcher(botOpenId, onMessage) {
|
|
46
|
-
const dispatcher = new lark.EventDispatcher({});
|
|
47
|
-
const processedMessages = /* @__PURE__ */ new Set();
|
|
48
|
-
dispatcher.register({
|
|
49
|
-
"im.message.receive_v1": async (data) => {
|
|
50
|
-
console.log(`[recv] \u6536\u5230\u98DE\u4E66\u4E8B\u4EF6:`, JSON.stringify(data, null, 2));
|
|
51
|
-
const message = data.message;
|
|
52
|
-
if (message.message_type !== "text") {
|
|
53
|
-
console.log(`[recv] \u5FFD\u7565\u975E\u6587\u672C\u6D88\u606F, type=${message.message_type}`);
|
|
54
|
-
return;
|
|
55
|
-
}
|
|
56
|
-
const messageId = message.message_id;
|
|
57
|
-
const senderType = data.sender?.sender_type;
|
|
58
|
-
if (senderType === "app") {
|
|
59
|
-
console.log(`[recv] \u5FFD\u7565\u673A\u5668\u4EBA\u81EA\u8EAB\u6D88\u606F: ${messageId}`);
|
|
60
|
-
return;
|
|
61
|
-
}
|
|
62
|
-
if (processedMessages.has(messageId)) {
|
|
63
|
-
console.log(`[dedup] \u8DF3\u8FC7\u91CD\u590D\u6D88\u606F: ${messageId}`);
|
|
64
|
-
return;
|
|
65
|
-
}
|
|
66
|
-
processedMessages.add(messageId);
|
|
67
|
-
const createTime = parseInt(message.create_time, 10);
|
|
68
|
-
if (createTime && Date.now() - createTime > 2 * 60 * 1e3) {
|
|
69
|
-
console.log(`[dedup] \u8DF3\u8FC7\u8FC7\u671F\u6D88\u606F: ${messageId}, \u521B\u5EFA\u4E8E ${new Date(createTime).toISOString()}`);
|
|
70
|
-
return;
|
|
71
|
-
}
|
|
72
|
-
if (processedMessages.size > 1e3) {
|
|
73
|
-
const first = processedMessages.values().next().value;
|
|
74
|
-
processedMessages.delete(first);
|
|
75
|
-
}
|
|
76
|
-
const content = JSON.parse(message.content);
|
|
77
|
-
let text = content.text || "";
|
|
78
|
-
const chatId = message.chat_id;
|
|
79
|
-
const mentions = message.mentions || [];
|
|
80
|
-
if (mentions.length > 0) {
|
|
81
|
-
console.log(`[recv] mentions:`, JSON.stringify(mentions));
|
|
82
|
-
}
|
|
83
|
-
const isMentioned = mentions.length > 0 && (!botOpenId || mentions.some((m) => {
|
|
84
|
-
const mentionOpenId = m.id?.open_id || m.id_str || "";
|
|
85
|
-
return mentionOpenId === botOpenId;
|
|
86
|
-
}));
|
|
87
|
-
const isGroup = message.chat_type === "group";
|
|
88
|
-
if (mentions.length > 0) {
|
|
89
|
-
for (const mention of mentions) {
|
|
90
|
-
if (mention.key) {
|
|
91
|
-
text = text.replace(mention.key, "").trim();
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
if (isGroup && !isMentioned) {
|
|
96
|
-
const hasDocLink = /(https?:\/\/[^\s]*feishu\.cn\/[^\s]+)/.test(text);
|
|
97
|
-
if (!hasDocLink) {
|
|
98
|
-
console.log(`[recv] \u7FA4\u804A\u975E@\u673A\u5668\u4EBA\u6D88\u606F\u4E14\u975E\u6587\u6863\u94FE\u63A5, \u5FFD\u7565`);
|
|
99
|
-
return;
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
console.log(`[recv] \u89E3\u6790\u6D88\u606F: messageId=${messageId}, chatId=${chatId}, chatType=${message.chat_type}, text="${text}"`);
|
|
103
|
-
const senderId = data.sender?.sender_id?.open_id || "unknown";
|
|
104
|
-
await onMessage(messageId, text, chatId, senderId, { isGroup, isMentioned });
|
|
105
|
-
}
|
|
106
|
-
});
|
|
107
|
-
return dispatcher;
|
|
108
|
-
}
|
|
109
|
-
function startWSClient(client, dispatcher) {
|
|
110
|
-
const wsClient = new lark.WSClient({
|
|
111
|
-
appId: client.appId,
|
|
112
|
-
appSecret: client.appSecret,
|
|
113
|
-
loggerLevel: lark.LoggerLevel.info
|
|
114
|
-
});
|
|
115
|
-
wsClient.start({ eventDispatcher: dispatcher });
|
|
116
|
-
}
|
|
117
28
|
|
|
118
29
|
// src/lark/docReader.ts
|
|
119
30
|
function extractDocumentId(url) {
|
|
@@ -792,68 +703,6 @@ ${stdout}`);
|
|
|
792
703
|
}
|
|
793
704
|
};
|
|
794
705
|
|
|
795
|
-
// src/lark/taskCreator.ts
|
|
796
|
-
var TaskCreator = class {
|
|
797
|
-
constructor(client) {
|
|
798
|
-
this.client = client;
|
|
799
|
-
}
|
|
800
|
-
client;
|
|
801
|
-
async createTask(params) {
|
|
802
|
-
const taskBody = {
|
|
803
|
-
summary: params.summary
|
|
804
|
-
};
|
|
805
|
-
if (params.due) {
|
|
806
|
-
const dueDate = /* @__PURE__ */ new Date(params.due + "T23:59:59+08:00");
|
|
807
|
-
taskBody.due = {
|
|
808
|
-
timestamp: dueDate.getTime().toString(),
|
|
809
|
-
is_all_day: true
|
|
810
|
-
};
|
|
811
|
-
}
|
|
812
|
-
if (params.description) {
|
|
813
|
-
taskBody.description = params.description;
|
|
814
|
-
}
|
|
815
|
-
if (params.assigneeOpenId) {
|
|
816
|
-
taskBody.members = [
|
|
817
|
-
{
|
|
818
|
-
id: params.assigneeOpenId,
|
|
819
|
-
type: "user",
|
|
820
|
-
role: "assignee"
|
|
821
|
-
}
|
|
822
|
-
];
|
|
823
|
-
}
|
|
824
|
-
console.log(`[task] \u521B\u5EFA\u98DE\u4E66\u4EFB\u52A1: ${params.summary}`);
|
|
825
|
-
console.log(`[task] \u8BF7\u6C42\u4F53:`, JSON.stringify(taskBody, null, 2));
|
|
826
|
-
const response = await this.client.task.v2.task.create({
|
|
827
|
-
params: { user_id_type: "open_id" },
|
|
828
|
-
data: taskBody
|
|
829
|
-
});
|
|
830
|
-
console.log(`[task] API \u8FD4\u56DE:`, JSON.stringify(response.data, null, 2));
|
|
831
|
-
const taskId = response.data?.task?.guid || "";
|
|
832
|
-
const url = response.data?.task?.url || "";
|
|
833
|
-
console.log(`[task] \u4EFB\u52A1\u521B\u5EFA\u6210\u529F: taskId=${taskId}`);
|
|
834
|
-
return { taskId, url };
|
|
835
|
-
}
|
|
836
|
-
/**
|
|
837
|
-
* 查询飞书任务的最新状态
|
|
838
|
-
*/
|
|
839
|
-
async getTaskStatus(taskId) {
|
|
840
|
-
try {
|
|
841
|
-
const response = await this.client.task.v2.task.get({
|
|
842
|
-
path: { task_guid: taskId }
|
|
843
|
-
});
|
|
844
|
-
const task = response.data?.task;
|
|
845
|
-
if (!task) return null;
|
|
846
|
-
const completedAt = task.completed_at || "";
|
|
847
|
-
const status = completedAt ? "completed" : "open";
|
|
848
|
-
const completedAtISO = completedAt ? new Date(parseInt(completedAt, 10)).toISOString() : void 0;
|
|
849
|
-
return { status, completedAt: completedAtISO };
|
|
850
|
-
} catch (err) {
|
|
851
|
-
console.error(`[task-sync] \u67E5\u8BE2\u4EFB\u52A1\u72B6\u6001\u5931\u8D25: taskId=${taskId}`, err.message);
|
|
852
|
-
return null;
|
|
853
|
-
}
|
|
854
|
-
}
|
|
855
|
-
};
|
|
856
|
-
|
|
857
706
|
// src/lark/userResolver.ts
|
|
858
707
|
var UserResolver = class {
|
|
859
708
|
constructor(client) {
|
|
@@ -982,6 +831,7 @@ async function main() {
|
|
|
982
831
|
}
|
|
983
832
|
case "find_query" /* FIND_QUERY */: {
|
|
984
833
|
console.log(`[process] \u5F00\u59CB\u641C\u7D22: query="${parsed.query}"`);
|
|
834
|
+
await syncTaskStatuses(store, taskCreator);
|
|
985
835
|
const results = await queryHandler.find(parsed.query);
|
|
986
836
|
console.log(`[process] \u641C\u7D22\u5B8C\u6210, \u7ED3\u679C\u6570=${results.length}`);
|
|
987
837
|
await messenger.replySearchResults(messageId, results);
|
|
@@ -990,6 +840,7 @@ async function main() {
|
|
|
990
840
|
}
|
|
991
841
|
case "list_all" /* LIST_ALL */: {
|
|
992
842
|
console.log(`[process] \u5217\u51FA\u6240\u6709\u8BB0\u5F55`);
|
|
843
|
+
await syncTaskStatuses(store, taskCreator);
|
|
993
844
|
const all = await store.list();
|
|
994
845
|
console.log(`[process] \u5171 ${all.length} \u6761\u8BB0\u5F55`);
|
|
995
846
|
await messenger.replyRecordList(messageId, all);
|
|
@@ -1010,6 +861,7 @@ async function main() {
|
|
|
1010
861
|
}
|
|
1011
862
|
case "show_detail" /* SHOW_DETAIL */: {
|
|
1012
863
|
console.log(`[process] \u67E5\u770B\u8BE6\u60C5: id=${parsed.showId}`);
|
|
864
|
+
await syncTaskStatuses(store, taskCreator);
|
|
1013
865
|
const detail = await store.load(parsed.showId);
|
|
1014
866
|
if (detail) {
|
|
1015
867
|
await messenger.replyRecordDetail(messageId, detail);
|
|
@@ -1120,38 +972,8 @@ async function main() {
|
|
|
1120
972
|
console.error("[notify] \u5411\u7BA1\u7406\u5458\u63A8\u9001\u542F\u52A8\u901A\u77E5\u5931\u8D25:", err.message);
|
|
1121
973
|
});
|
|
1122
974
|
}
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
try {
|
|
1126
|
-
const meetings = await store.list();
|
|
1127
|
-
let updatedCount = 0;
|
|
1128
|
-
for (const meeting of meetings) {
|
|
1129
|
-
if (!meeting.createdTasks || meeting.createdTasks.length === 0) continue;
|
|
1130
|
-
let changed = false;
|
|
1131
|
-
for (const task of meeting.createdTasks) {
|
|
1132
|
-
if (!task.taskId || task.status === "completed") continue;
|
|
1133
|
-
const result = await taskCreator.getTaskStatus(task.taskId);
|
|
1134
|
-
if (result && result.status !== (task.status || "open")) {
|
|
1135
|
-
task.status = result.status;
|
|
1136
|
-
task.completedAt = result.completedAt;
|
|
1137
|
-
changed = true;
|
|
1138
|
-
if (task.todoIndex != null && meeting.todos[task.todoIndex]) {
|
|
1139
|
-
meeting.todos[task.todoIndex].status = result.status;
|
|
1140
|
-
}
|
|
1141
|
-
}
|
|
1142
|
-
}
|
|
1143
|
-
if (changed) {
|
|
1144
|
-
await store.save(meeting);
|
|
1145
|
-
updatedCount++;
|
|
1146
|
-
}
|
|
1147
|
-
}
|
|
1148
|
-
console.log(`[task-sync] \u540C\u6B65\u5B8C\u6210, \u66F4\u65B0\u4E86 ${updatedCount} \u6761\u4F1A\u8BAE\u8BB0\u5F55`);
|
|
1149
|
-
} catch (err) {
|
|
1150
|
-
console.error("[task-sync] \u540C\u6B65\u5931\u8D25:", err.message);
|
|
1151
|
-
}
|
|
1152
|
-
}
|
|
1153
|
-
syncTaskStatuses();
|
|
1154
|
-
setInterval(syncTaskStatuses, 60 * 60 * 1e3);
|
|
975
|
+
syncTaskStatuses(store, taskCreator);
|
|
976
|
+
setInterval(() => syncTaskStatuses(store, taskCreator), 60 * 60 * 1e3);
|
|
1155
977
|
if (config.lark.adminOpenId) {
|
|
1156
978
|
const adminId = config.lark.adminOpenId;
|
|
1157
979
|
let exiting = false;
|