wechaty-web-panel 1.6.112 → 1.6.113
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/bot/chatgpt/index.js +235 -0
- package/dist/bot/coze/sdk/index.js +110 -0
- package/dist/bot/dify/sdk/index.js +461 -0
- package/dist/bot/dify/sdk/office.js +319 -0
- package/dist/bot/fastgpt/index.js +98 -0
- package/dist/bot/qanything/index.js +136 -0
- package/dist/botInstance/coze.js +167 -0
- package/dist/botInstance/cozev3.js +157 -0
- package/dist/botInstance/dify.js +160 -0
- package/dist/botInstance/fastgpt.js +130 -0
- package/dist/botInstance/gpt4v.js +95 -0
- package/dist/botInstance/officialOpenAi.js +186 -0
- package/dist/botInstance/qany.js +144 -0
- package/dist/botInstance/sdk/chatGPT4V.js +89 -0
- package/dist/botInstance/sdk/coze.js +200 -0
- package/dist/botInstance/sdk/difyClient.js +354 -0
- package/dist/botInstance/sdk/pTimeout.js +97 -0
- package/dist/botInstance/sdk/qanything.js +137 -0
- package/dist/botInstance/sdk/quick-lru.js +237 -0
- package/dist/common/hook.js +66 -0
- package/dist/common/index.js +513 -0
- package/dist/common/multiReply.js +158 -0
- package/dist/common/reply.js +23 -0
- package/dist/const/puppet-type.js +71 -0
- package/dist/db/aiDb.js +27 -0
- package/dist/db/aichatDb.js +84 -0
- package/dist/db/chatHistory.js +137 -0
- package/dist/db/configDb.js +97 -0
- package/dist/db/global.js +62 -0
- package/dist/db/gptConfig.js +85 -0
- package/dist/db/nedb.js +88 -0
- package/dist/db/puppetDb.js +58 -0
- package/dist/db/roomDb.js +83 -0
- package/dist/db/rssConfig.js +82 -0
- package/dist/db/rssHistory.js +88 -0
- package/dist/db/userDb.js +27 -0
- package/dist/handlers/on-callback-message.js +183 -0
- package/dist/handlers/on-error.js +5 -0
- package/dist/handlers/on-friend.js +62 -0
- package/dist/handlers/on-heartbeat.js +20 -0
- package/dist/handlers/on-login.js +58 -0
- package/dist/handlers/on-logout.js +17 -0
- package/dist/handlers/on-message.js +644 -0
- package/dist/handlers/on-ready.js +36 -0
- package/dist/handlers/on-record-message.js +56 -0
- package/dist/handlers/on-roomjoin.js +42 -0
- package/dist/handlers/on-roomleave.js +12 -0
- package/dist/handlers/on-roomtopic.js +16 -0
- package/dist/handlers/on-scan.js +64 -0
- package/dist/handlers/on-verifycode.js +42 -0
- package/dist/index.js +81 -69306
- package/dist/lib/contentCensor.js +23 -0
- package/dist/lib/index.js +562 -0
- package/dist/lib/oss.js +43 -0
- package/dist/lib/s3oss.js +33 -0
- package/dist/mcp/mcp-server.js +26 -0
- package/dist/mcp/src/config/database.js +51 -0
- package/dist/mcp/src/index.js +238 -0
- package/dist/mcp/src/mcp/schemas.js +178 -0
- package/dist/mcp/src/mcp/server.js +421 -0
- package/dist/mcp/src/mcp/streamable-server.js +690 -0
- package/dist/mcp/src/models/ChatMessage.js +151 -0
- package/dist/mcp/src/models/Friend.js +64 -0
- package/dist/mcp/src/models/Group.js +55 -0
- package/dist/mcp/src/models/GroupMember.js +67 -0
- package/dist/mcp/src/models/index.js +27 -0
- package/dist/mcp/src/scripts/migrate.js +21 -0
- package/dist/mcp/src/services/ChatDataService.js +284 -0
- package/dist/mcp/src/services/McpService.js +521 -0
- package/dist/mcp/src/services/McpTools.js +504 -0
- package/dist/mcp/streamable-examples.js +283 -0
- package/dist/mcp/streamable-server.js +79 -0
- package/dist/mcp/test-mcp.js +64 -0
- package/dist/mcp/test-streamable-server.js +86 -0
- package/dist/package-json.js +89 -0
- package/dist/proxy/aibotk.js +829 -0
- package/dist/proxy/api.js +431 -0
- package/dist/proxy/apib.js +587 -0
- package/dist/proxy/bot/chatgpt.js +38 -0
- package/dist/proxy/bot/coze.js +38 -0
- package/dist/proxy/bot/cozev3.js +38 -0
- package/dist/proxy/bot/dify.js +38 -0
- package/dist/proxy/bot/dispatch.js +81 -0
- package/dist/proxy/bot/fastgpt.js +27 -0
- package/dist/proxy/bot/qany.js +27 -0
- package/dist/proxy/config.js +14 -0
- package/dist/proxy/cozeAi.js +60 -0
- package/dist/proxy/cozeV3Ai.js +60 -0
- package/dist/proxy/difyAi.js +58 -0
- package/dist/proxy/fastgpt.js +55 -0
- package/dist/proxy/mqtt.js +275 -0
- package/dist/proxy/multimodal.js +122 -0
- package/dist/proxy/openAi.js +63 -0
- package/dist/proxy/outapi.js +62 -0
- package/dist/proxy/qAnyAi.js +57 -0
- package/dist/proxy/superagent.js +200 -0
- package/dist/proxy/tencent-open.js +255 -0
- package/dist/service/event-dispatch-service.js +309 -0
- package/dist/service/gpt4vService.js +45 -0
- package/dist/service/msg-filter-service.js +121 -0
- package/dist/service/msg-filters.js +645 -0
- package/dist/service/room-async-service.js +455 -0
- package/dist/task/index.js +535 -0
- package/dist/task/rss.js +174 -0
- package/package.json +2 -2
- package/src/package-json.js +2 -2
- package/tsconfig.json +3 -12
- package/dist/index.d.ts +0 -9
- package/tsconfig.cjs.json +0 -12
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import baiduApi from "baidu-aip-sdk";
|
|
2
|
+
export class ContentCensor {
|
|
3
|
+
constructor(config) {
|
|
4
|
+
this.client = null;
|
|
5
|
+
this.config = config;
|
|
6
|
+
}
|
|
7
|
+
init() {
|
|
8
|
+
if (this.config.type === 1) {
|
|
9
|
+
this.client = new baiduApi.contentCensor(this.config.appId, this.config.apiKey, this.config.secretKey);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
async checkText(text) {
|
|
13
|
+
if (!this.client) {
|
|
14
|
+
this.init();
|
|
15
|
+
}
|
|
16
|
+
if (this.config.type === 1) {
|
|
17
|
+
const result = await this.client.textCensorUserDefined(text);
|
|
18
|
+
console.log('result', result);
|
|
19
|
+
return result.conclusionType ? result.conclusionType === 1 : true;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=contentCensor.js.map
|
|
@@ -0,0 +1,562 @@
|
|
|
1
|
+
import Crypto from 'crypto';
|
|
2
|
+
import * as schedule from 'node-schedule';
|
|
3
|
+
import fs from 'fs';
|
|
4
|
+
import dayjs from "dayjs";
|
|
5
|
+
import path from 'path';
|
|
6
|
+
/**
|
|
7
|
+
* 设置定时器
|
|
8
|
+
* @param {*} date 日期
|
|
9
|
+
* @param {*} callback 回调
|
|
10
|
+
*/
|
|
11
|
+
//其他规则见 https://www.npmjs.com/package/node-schedule
|
|
12
|
+
// 规则参数讲解 *代表通配符
|
|
13
|
+
//
|
|
14
|
+
// * * * * * *
|
|
15
|
+
// ┬ ┬ ┬ ┬ ┬ ┬
|
|
16
|
+
// │ │ │ │ │ |
|
|
17
|
+
// │ │ │ │ │ └ day of week (0 - 7) (0 or 7 is Sun)
|
|
18
|
+
// │ │ │ │ └───── month (1 - 12)
|
|
19
|
+
// │ │ │ └────────── day of month (1 - 31)
|
|
20
|
+
// │ │ └─────────────── hour (0 - 23)
|
|
21
|
+
// │ └──────────────────── minute (0 - 59)
|
|
22
|
+
// └───────────────────────── second (0 - 59, OPTIONAL)
|
|
23
|
+
// 每分钟的第30秒触发: '30 * * * * *'
|
|
24
|
+
//
|
|
25
|
+
// 每小时的1分30秒触发 :'30 1 * * * *'
|
|
26
|
+
//
|
|
27
|
+
// 每天的凌晨1点1分30秒触发 :'30 1 1 * * *'
|
|
28
|
+
//
|
|
29
|
+
// 每月的1日1点1分30秒触发 :'30 1 1 1 * *'
|
|
30
|
+
//
|
|
31
|
+
// 每周1的1点1分30秒触发 :'30 1 1 * * 1'
|
|
32
|
+
function setLocalSchedule(date, callback, name) {
|
|
33
|
+
if (name) {
|
|
34
|
+
schedule.scheduleJob(name, { rule: date, tz: 'Asia/Shanghai' }, callback);
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
schedule.scheduleJob({ rule: date, tz: 'Asia/Shanghai' }, callback);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
// 取消任务
|
|
41
|
+
function cancelLocalSchedule(name) {
|
|
42
|
+
schedule.cancelJob(name);
|
|
43
|
+
}
|
|
44
|
+
// 取消指定任务
|
|
45
|
+
function cancelAllSchedule(type) {
|
|
46
|
+
for (let i in schedule.scheduledJobs) {
|
|
47
|
+
if (i.includes(type)) {
|
|
48
|
+
cancelLocalSchedule(i);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* 延时函数
|
|
54
|
+
* @param {*} ms 毫秒
|
|
55
|
+
*/
|
|
56
|
+
async function delay(ms) {
|
|
57
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* 获取周几
|
|
61
|
+
* @param {*} date 日期
|
|
62
|
+
*/
|
|
63
|
+
function getDay(date) {
|
|
64
|
+
var date2 = dayjs().startOf('day').valueOf();
|
|
65
|
+
var date1 = dayjs(date).endOf('day').valueOf();
|
|
66
|
+
var iDays = parseInt(Math.abs(date2 - date1) / 1000 / 60 / 60 / 24);
|
|
67
|
+
return iDays;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* 格式化日期
|
|
71
|
+
* @param {*} date
|
|
72
|
+
* @returns 例:2019-9-10 13:13:04 星期一
|
|
73
|
+
*/
|
|
74
|
+
function formatDate(date) {
|
|
75
|
+
var tempDate = new Date(date);
|
|
76
|
+
var year = tempDate.getFullYear();
|
|
77
|
+
var month = tempDate.getMonth() + 1;
|
|
78
|
+
var day = tempDate.getDate();
|
|
79
|
+
var hour = tempDate.getHours();
|
|
80
|
+
var min = tempDate.getMinutes();
|
|
81
|
+
var second = tempDate.getSeconds();
|
|
82
|
+
var week = tempDate.getDay();
|
|
83
|
+
var str = '';
|
|
84
|
+
if (week === 0) {
|
|
85
|
+
str = '星期日';
|
|
86
|
+
}
|
|
87
|
+
else if (week === 1) {
|
|
88
|
+
str = '星期一';
|
|
89
|
+
}
|
|
90
|
+
else if (week === 2) {
|
|
91
|
+
str = '星期二';
|
|
92
|
+
}
|
|
93
|
+
else if (week === 3) {
|
|
94
|
+
str = '星期三';
|
|
95
|
+
}
|
|
96
|
+
else if (week === 4) {
|
|
97
|
+
str = '星期四';
|
|
98
|
+
}
|
|
99
|
+
else if (week === 5) {
|
|
100
|
+
str = '星期五';
|
|
101
|
+
}
|
|
102
|
+
else if (week === 6) {
|
|
103
|
+
str = '星期六';
|
|
104
|
+
}
|
|
105
|
+
if (hour < 10) {
|
|
106
|
+
hour = '0' + hour;
|
|
107
|
+
}
|
|
108
|
+
if (min < 10) {
|
|
109
|
+
min = '0' + min;
|
|
110
|
+
}
|
|
111
|
+
if (second < 10) {
|
|
112
|
+
second = '0' + second;
|
|
113
|
+
}
|
|
114
|
+
return year + '-' + month + '-' + day + ' ' + hour + ':' + min + ' ' + str;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* 获取今天日期
|
|
118
|
+
* @returns 2019-7-19
|
|
119
|
+
*/
|
|
120
|
+
function getToday() {
|
|
121
|
+
const date = new Date();
|
|
122
|
+
let year = date.getFullYear();
|
|
123
|
+
let month = date.getMonth() + 1;
|
|
124
|
+
let day = date.getDate();
|
|
125
|
+
return year + '-' + month + '-' + day + ' ';
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* 转换定时日期格式
|
|
129
|
+
* @param {*} time
|
|
130
|
+
* @returns 0 12 15 * * * 每天下午3点12分
|
|
131
|
+
*/
|
|
132
|
+
function convertTime(time) {
|
|
133
|
+
let array = time.split(':');
|
|
134
|
+
return '0 ' + array[1] + ' ' + array[0] + ' * * *';
|
|
135
|
+
}
|
|
136
|
+
//
|
|
137
|
+
/**
|
|
138
|
+
* 判断日期时间格式是否正确
|
|
139
|
+
* @param {*} str 日期
|
|
140
|
+
* @returns {boolean}
|
|
141
|
+
*/
|
|
142
|
+
function isRealDate(str) {
|
|
143
|
+
var reg = /^(\d+)-(\d{1,2})-(\d{1,2}) (\d{1,2}):(\d{1,2})$/;
|
|
144
|
+
var r = str.match(reg);
|
|
145
|
+
if (r == null)
|
|
146
|
+
return false;
|
|
147
|
+
r[2] = r[2] - 1;
|
|
148
|
+
var d = new Date(r[1], r[2], r[3], r[4], r[5]);
|
|
149
|
+
if (d.getFullYear() != r[1])
|
|
150
|
+
return false;
|
|
151
|
+
if (d.getMonth() != r[2])
|
|
152
|
+
return false;
|
|
153
|
+
if (d.getDate() != r[3])
|
|
154
|
+
return false;
|
|
155
|
+
if (d.getHours() != r[4])
|
|
156
|
+
return false;
|
|
157
|
+
if (d.getMinutes() != r[5])
|
|
158
|
+
return false;
|
|
159
|
+
return true;
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* 获取星座的英文
|
|
163
|
+
* @param {*} msg
|
|
164
|
+
*/
|
|
165
|
+
function getConstellation(astro) {
|
|
166
|
+
if (astro.includes('白羊座')) {
|
|
167
|
+
return 'aries';
|
|
168
|
+
}
|
|
169
|
+
if (astro.includes('金牛座')) {
|
|
170
|
+
return 'taurus';
|
|
171
|
+
}
|
|
172
|
+
if (astro.includes('双子座')) {
|
|
173
|
+
return 'gemini';
|
|
174
|
+
}
|
|
175
|
+
if (astro.includes('巨蟹座') || astro.includes('钜蟹座')) {
|
|
176
|
+
return 'cancer';
|
|
177
|
+
}
|
|
178
|
+
if (astro.includes('狮子座')) {
|
|
179
|
+
return 'leo';
|
|
180
|
+
}
|
|
181
|
+
if (astro.includes('处女座')) {
|
|
182
|
+
return 'virgo';
|
|
183
|
+
}
|
|
184
|
+
if (astro.includes('天平座') || astro.includes('天秤座') || astro.includes('天瓶座') || astro.includes('天枰座')) {
|
|
185
|
+
return 'libra';
|
|
186
|
+
}
|
|
187
|
+
if (astro.includes('天蝎座')) {
|
|
188
|
+
return 'scorpio';
|
|
189
|
+
}
|
|
190
|
+
if (astro.includes('射手座')) {
|
|
191
|
+
return 'sagittarius';
|
|
192
|
+
}
|
|
193
|
+
if (astro.includes('射手座')) {
|
|
194
|
+
return 'sagittarius';
|
|
195
|
+
}
|
|
196
|
+
if (astro.includes('摩羯座')) {
|
|
197
|
+
return 'capricorn';
|
|
198
|
+
}
|
|
199
|
+
if (astro.includes('水瓶座')) {
|
|
200
|
+
return 'aquarius';
|
|
201
|
+
}
|
|
202
|
+
if (astro.includes('双鱼座')) {
|
|
203
|
+
return 'pisces';
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* 获取新闻的英文
|
|
208
|
+
* @param {*} msg
|
|
209
|
+
*/
|
|
210
|
+
function getNewsType(msg) {
|
|
211
|
+
const NewsMap = {
|
|
212
|
+
社会: 5,
|
|
213
|
+
国内: 7,
|
|
214
|
+
国际: 8,
|
|
215
|
+
娱乐: 10,
|
|
216
|
+
美女图片: 11,
|
|
217
|
+
体育: 12,
|
|
218
|
+
科技: 13,
|
|
219
|
+
奇闻异事: 41,
|
|
220
|
+
健康知识: 17,
|
|
221
|
+
旅游: 18,
|
|
222
|
+
汉服: 38,
|
|
223
|
+
房产: 37,
|
|
224
|
+
科学探索: 36,
|
|
225
|
+
汽车: 35,
|
|
226
|
+
互联网: 34,
|
|
227
|
+
动漫: 33,
|
|
228
|
+
财经: 32,
|
|
229
|
+
游戏: 32,
|
|
230
|
+
CBA: 30,
|
|
231
|
+
人工智能: 29,
|
|
232
|
+
区块链: 28,
|
|
233
|
+
军事: 27,
|
|
234
|
+
足球: 26,
|
|
235
|
+
创业: 24,
|
|
236
|
+
移动互联: 23,
|
|
237
|
+
IT: 22,
|
|
238
|
+
VR科技: 21,
|
|
239
|
+
};
|
|
240
|
+
return NewsMap[msg] || 7;
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* 返回指定范围的随机整数
|
|
244
|
+
* @param {*} min
|
|
245
|
+
* @param {*} max
|
|
246
|
+
*/
|
|
247
|
+
function randomRange(min, max) {
|
|
248
|
+
// min最小值,max最大值
|
|
249
|
+
return Math.floor(Math.random() * (max - min)) + min;
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* 写入文件内容
|
|
253
|
+
* @param fpath
|
|
254
|
+
* @param encoding
|
|
255
|
+
* @returns {Promise<unknown>}
|
|
256
|
+
*/
|
|
257
|
+
async function writeFile(fpath, encoding) {
|
|
258
|
+
return new Promise(function (resolve, reject) {
|
|
259
|
+
fs.writeFile(fpath, encoding, function (err, content) {
|
|
260
|
+
if (err) {
|
|
261
|
+
reject(err);
|
|
262
|
+
}
|
|
263
|
+
else {
|
|
264
|
+
resolve(content);
|
|
265
|
+
}
|
|
266
|
+
});
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* 解析响应数据
|
|
271
|
+
* @param {*} content 内容
|
|
272
|
+
*/
|
|
273
|
+
function parseBody(content) {
|
|
274
|
+
if (!content)
|
|
275
|
+
return;
|
|
276
|
+
return JSON.parse(content.text);
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* MD5加密
|
|
280
|
+
* @return {string}
|
|
281
|
+
*/
|
|
282
|
+
function MD5(str) {
|
|
283
|
+
return Crypto.createHash('md5').update(str).digest('hex');
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* 对象内容按照字母排序
|
|
287
|
+
* @param obj
|
|
288
|
+
*/
|
|
289
|
+
function objKeySort(obj) {
|
|
290
|
+
const newkey = Object.keys(obj).sort();
|
|
291
|
+
const newObj = {};
|
|
292
|
+
for (let i = 0; i < newkey.length; i++) {
|
|
293
|
+
newObj[newkey[i]] = obj[newkey[i]];
|
|
294
|
+
}
|
|
295
|
+
return newObj;
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* 根据排序后的数据返回url参数
|
|
299
|
+
* @param datas
|
|
300
|
+
* @returns {string}
|
|
301
|
+
*/
|
|
302
|
+
function getQueryString(datas) {
|
|
303
|
+
const data = objKeySort(datas);
|
|
304
|
+
let url = '';
|
|
305
|
+
if (typeof data === 'undefined' || data == null || typeof data !== 'object') {
|
|
306
|
+
return '';
|
|
307
|
+
}
|
|
308
|
+
for (var k in data) {
|
|
309
|
+
const string = typeof data[k] === 'object' ? JSON.stringify(data[k]) : data[k];
|
|
310
|
+
url += (url.indexOf('=') !== -1 ? '&' : '') + k + '=' + string;
|
|
311
|
+
}
|
|
312
|
+
return url;
|
|
313
|
+
}
|
|
314
|
+
/**
|
|
315
|
+
* 获取MD5加密后的Sign
|
|
316
|
+
* @param secret
|
|
317
|
+
* @param query
|
|
318
|
+
* @returns {string}
|
|
319
|
+
*/
|
|
320
|
+
function getSign(secret, query) {
|
|
321
|
+
const stringSignTemp = `${query}&ApiSecret=${secret}`;
|
|
322
|
+
return MD5(stringSignTemp).toUpperCase();
|
|
323
|
+
}
|
|
324
|
+
/**
|
|
325
|
+
* 生成n位随机数
|
|
326
|
+
* @param n
|
|
327
|
+
* @returns {string}
|
|
328
|
+
*/
|
|
329
|
+
function rndNum(n) {
|
|
330
|
+
let rnd = '';
|
|
331
|
+
for (let i = 0; i < n; i++) {
|
|
332
|
+
rnd += Math.floor(Math.random() * 10);
|
|
333
|
+
}
|
|
334
|
+
return rnd;
|
|
335
|
+
}
|
|
336
|
+
/**
|
|
337
|
+
* 生成加密后的对象
|
|
338
|
+
* @param apiKey
|
|
339
|
+
* @param apiSecret
|
|
340
|
+
* @param params
|
|
341
|
+
* @returns {{apiKey: *, nonce: *, timestamp: *}}
|
|
342
|
+
*/
|
|
343
|
+
function getFormatQuery(apiKey, apiSecret, params = {}) {
|
|
344
|
+
const query = {
|
|
345
|
+
apiKey: apiKey,
|
|
346
|
+
timestamp: new Date().getTime(),
|
|
347
|
+
nonce: rndNum(3),
|
|
348
|
+
...params,
|
|
349
|
+
};
|
|
350
|
+
const sign = getSign(getQueryString(query), apiSecret);
|
|
351
|
+
query.sign = sign;
|
|
352
|
+
return query;
|
|
353
|
+
}
|
|
354
|
+
/**
|
|
355
|
+
* 生成回复内容
|
|
356
|
+
* @param type 内容类型
|
|
357
|
+
* @param content 内容
|
|
358
|
+
* @param url 链接
|
|
359
|
+
* @returns {[{type: *, content: *, url: *}]}
|
|
360
|
+
*/
|
|
361
|
+
function msgArr(type = 1, content = '', url = '') {
|
|
362
|
+
let obj = { type: type, content: content, url: url };
|
|
363
|
+
return [obj];
|
|
364
|
+
}
|
|
365
|
+
/**
|
|
366
|
+
* 设置提醒内容解析
|
|
367
|
+
* @param {*} keywordArray 分词后内容
|
|
368
|
+
* @param name
|
|
369
|
+
*/
|
|
370
|
+
function contentDistinguish(keywordArray, name) {
|
|
371
|
+
let scheduleObj = {};
|
|
372
|
+
let today = getToday();
|
|
373
|
+
scheduleObj.setter = name; // 设置定时任务的用户
|
|
374
|
+
scheduleObj.subscribe = keywordArray[1] === '我' ? name : keywordArray[1]; // 定时任务接收者
|
|
375
|
+
if (keywordArray[2] === '每天') {
|
|
376
|
+
// 判断是否属于循环任务
|
|
377
|
+
console.log('已设置每日定时任务');
|
|
378
|
+
scheduleObj.isLoop = true;
|
|
379
|
+
if (keywordArray[3].includes(':') || keywordArray[3].includes(':')) {
|
|
380
|
+
let time = keywordArray[3].replace(':', ':');
|
|
381
|
+
scheduleObj.time = convertTime(time);
|
|
382
|
+
}
|
|
383
|
+
else {
|
|
384
|
+
scheduleObj.time = '';
|
|
385
|
+
}
|
|
386
|
+
scheduleObj.content = scheduleObj.setter === scheduleObj.subscribe ? `亲爱的${scheduleObj.subscribe},温馨提醒:${keywordArray[4].replace('我', '你')}` : `亲爱的${scheduleObj.subscribe},${scheduleObj.setter}委托我提醒你,${keywordArray[4].replace('我', '你')}`;
|
|
387
|
+
}
|
|
388
|
+
else if (keywordArray[2] && keywordArray[2].includes('-')) {
|
|
389
|
+
console.log('已设置指定日期时间任务');
|
|
390
|
+
scheduleObj.isLoop = false;
|
|
391
|
+
scheduleObj.time = keywordArray[2] + ' ' + keywordArray[3].replace(':', ':');
|
|
392
|
+
scheduleObj.content = scheduleObj.setter === scheduleObj.subscribe ? `亲爱的${scheduleObj.subscribe},温馨提醒:${keywordArray[4].replace('我', '你')}` : `亲爱的${scheduleObj.subscribe},${scheduleObj.setter}委托我提醒你,${keywordArray[4].replace('我', '你')}`;
|
|
393
|
+
}
|
|
394
|
+
else {
|
|
395
|
+
console.log('已设置当天任务');
|
|
396
|
+
scheduleObj.isLoop = false;
|
|
397
|
+
scheduleObj.time = today + keywordArray[2].replace(':', ':');
|
|
398
|
+
scheduleObj.content = scheduleObj.setter === scheduleObj.subscribe ? `亲爱的${scheduleObj.subscribe},温馨提醒:${keywordArray[3].replace('我', '你')}` : `亲爱的${scheduleObj.subscribe},${scheduleObj.setter}委托我提醒你,${keywordArray[3].replace('我', '你')}`;
|
|
399
|
+
}
|
|
400
|
+
return scheduleObj;
|
|
401
|
+
}
|
|
402
|
+
/**
|
|
403
|
+
* 函数节流
|
|
404
|
+
* @param fn
|
|
405
|
+
* @param wait
|
|
406
|
+
* @returns {Function}
|
|
407
|
+
*/
|
|
408
|
+
function throttle(fn, wait) {
|
|
409
|
+
var timer = null;
|
|
410
|
+
return function () {
|
|
411
|
+
var context = this;
|
|
412
|
+
var args = arguments;
|
|
413
|
+
if (!timer) {
|
|
414
|
+
timer = setTimeout(function () {
|
|
415
|
+
fn.apply(context, args);
|
|
416
|
+
timer = null;
|
|
417
|
+
}, wait);
|
|
418
|
+
}
|
|
419
|
+
};
|
|
420
|
+
}
|
|
421
|
+
/**
|
|
422
|
+
* @return {string}
|
|
423
|
+
*/
|
|
424
|
+
function Base64Encode(str) {
|
|
425
|
+
return Buffer.from(str).toString('base64');
|
|
426
|
+
}
|
|
427
|
+
/**
|
|
428
|
+
* @return {string}
|
|
429
|
+
*/
|
|
430
|
+
function Base64Decode(str) {
|
|
431
|
+
return Buffer.from(str, 'base64').toString('ascii');
|
|
432
|
+
}
|
|
433
|
+
/**
|
|
434
|
+
* 数组拆分
|
|
435
|
+
* @param {array} array 数组
|
|
436
|
+
* @param {*} subGroupLength 每个数组长度
|
|
437
|
+
*/
|
|
438
|
+
function groupArray(array, subGroupLength) {
|
|
439
|
+
let index = 0;
|
|
440
|
+
let newArray = [];
|
|
441
|
+
while (index < array.length) {
|
|
442
|
+
newArray.push(array.slice(index, (index += subGroupLength)));
|
|
443
|
+
}
|
|
444
|
+
return newArray;
|
|
445
|
+
}
|
|
446
|
+
export function delHtmlTag(str) {
|
|
447
|
+
if (str) {
|
|
448
|
+
return str.replace(/<[^>]+>/g, ""); //去掉所有的html标记
|
|
449
|
+
}
|
|
450
|
+
return '';
|
|
451
|
+
}
|
|
452
|
+
export function isCDNFileUrl(url) {
|
|
453
|
+
// 常见的CDN文件扩展名
|
|
454
|
+
const cdnFileExtensions = ['.png', '.jpg', '.jpeg', '.gif', '.svg', '.webp', '.mp4', '.doc', '.docx', '.xls', '.xlsx', '.ppt', '.pptx', '.avi', '.zip', '.wav', '.rar', '.pdf', '.txt', '.log'];
|
|
455
|
+
try {
|
|
456
|
+
const parsedUrl = new URL(url);
|
|
457
|
+
const fileExt = path.extname(parsedUrl.pathname).toLowerCase();
|
|
458
|
+
// 检查文件扩展名是否在cdnFileExtensions列表中
|
|
459
|
+
return cdnFileExtensions.includes(fileExt);
|
|
460
|
+
}
|
|
461
|
+
catch (err) {
|
|
462
|
+
// 无效的URL
|
|
463
|
+
return false;
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
/**
|
|
467
|
+
* 提取文字中的图片链接 文件链接
|
|
468
|
+
* @param text
|
|
469
|
+
* @returns {*[]}
|
|
470
|
+
*/
|
|
471
|
+
function extractMarkdownLinks(text) {
|
|
472
|
+
// 正则表达式匹配所有 Markdown 链接格式
|
|
473
|
+
const linkRegex = /\[([^\]]*)\]\(([^)]+)\)/g;
|
|
474
|
+
const links = [];
|
|
475
|
+
let cleanedText = text;
|
|
476
|
+
let match;
|
|
477
|
+
while ((match = linkRegex.exec(text)) !== null) {
|
|
478
|
+
let url = match[2];
|
|
479
|
+
// 移除 URL 两端可能存在的引号
|
|
480
|
+
url = url.replace(/^["']|["']$/g, '');
|
|
481
|
+
if (url) {
|
|
482
|
+
links.push(url);
|
|
483
|
+
}
|
|
484
|
+
cleanedText = cleanedText.replace(match[0], '');
|
|
485
|
+
}
|
|
486
|
+
return {
|
|
487
|
+
links: links,
|
|
488
|
+
cleanedText: cleanedText.trim()
|
|
489
|
+
};
|
|
490
|
+
}
|
|
491
|
+
export function extractImageLinks(text, returnFilterContent = false) {
|
|
492
|
+
// const httpRegex = /(http:\/\/\S+\.(?:jpg|png|gif|webp|jpeg|mp4|doc|docx|xls|xlsx|ppt|pptx|avi|zip|wav|rar|pdf|txt|log))/g;
|
|
493
|
+
// const httpsRegex = /(https:\/\/\S+\.(?:jpg|png|gif|webp|jpeg|mp4|doc|docx|xls|xlsx|ppt|pptx|avi|zip|wav|rar|pdf|txt|log))/g;
|
|
494
|
+
const fileRegexHttp = /\[[^\]]*\]\((http?:\/\/\S+)\)/g;
|
|
495
|
+
const filesRegexHttp = /\[[^\]]*\]\((https?:\/\/\S+)\)/g;
|
|
496
|
+
const { links, cleanedText } = extractMarkdownLinks(text);
|
|
497
|
+
let imageLinks = links || [];
|
|
498
|
+
let match;
|
|
499
|
+
// while ((match = httpRegex.exec(text)) !== null) {
|
|
500
|
+
// imageLinks.push(match[0]);
|
|
501
|
+
// }
|
|
502
|
+
//
|
|
503
|
+
// while ((match = httpsRegex.exec(text)) !== null) {
|
|
504
|
+
// imageLinks.push(match[0]);
|
|
505
|
+
// }
|
|
506
|
+
while ((match = fileRegexHttp.exec(cleanedText)) !== null || (match = filesRegexHttp.exec(cleanedText)) !== null) {
|
|
507
|
+
imageLinks.push(match[1]);
|
|
508
|
+
}
|
|
509
|
+
imageLinks = Array.from(new Set(imageLinks)).filter(item => isCDNFileUrl(item));
|
|
510
|
+
if (returnFilterContent) {
|
|
511
|
+
return {
|
|
512
|
+
imageReplys: imageLinks.map(item => ({ type: 2, url: item })),
|
|
513
|
+
content: cleanedText
|
|
514
|
+
};
|
|
515
|
+
}
|
|
516
|
+
return imageLinks.map(item => ({ type: 2, url: item }));
|
|
517
|
+
}
|
|
518
|
+
export { Base64Encode };
|
|
519
|
+
export { Base64Decode };
|
|
520
|
+
export { setLocalSchedule };
|
|
521
|
+
export { parseBody };
|
|
522
|
+
export { delay };
|
|
523
|
+
export { getToday };
|
|
524
|
+
export { convertTime };
|
|
525
|
+
export { getDay };
|
|
526
|
+
export { formatDate };
|
|
527
|
+
export { isRealDate };
|
|
528
|
+
export { getConstellation };
|
|
529
|
+
export { randomRange };
|
|
530
|
+
export { writeFile };
|
|
531
|
+
export { MD5 };
|
|
532
|
+
export { getFormatQuery };
|
|
533
|
+
export { contentDistinguish };
|
|
534
|
+
export { msgArr };
|
|
535
|
+
export { throttle };
|
|
536
|
+
export { cancelAllSchedule };
|
|
537
|
+
export { groupArray };
|
|
538
|
+
export { getNewsType };
|
|
539
|
+
export default {
|
|
540
|
+
Base64Encode,
|
|
541
|
+
Base64Decode,
|
|
542
|
+
setLocalSchedule,
|
|
543
|
+
parseBody,
|
|
544
|
+
delay,
|
|
545
|
+
getToday,
|
|
546
|
+
convertTime,
|
|
547
|
+
getDay,
|
|
548
|
+
formatDate,
|
|
549
|
+
isRealDate,
|
|
550
|
+
getConstellation,
|
|
551
|
+
randomRange,
|
|
552
|
+
writeFile,
|
|
553
|
+
MD5,
|
|
554
|
+
getFormatQuery,
|
|
555
|
+
contentDistinguish,
|
|
556
|
+
msgArr,
|
|
557
|
+
throttle,
|
|
558
|
+
cancelAllSchedule,
|
|
559
|
+
groupArray,
|
|
560
|
+
getNewsType,
|
|
561
|
+
};
|
|
562
|
+
//# sourceMappingURL=index.js.map
|
package/dist/lib/oss.js
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import OSS from 'ali-oss';
|
|
2
|
+
import { allConfig } from '../db/configDb.js';
|
|
3
|
+
import { uploadGlobalS3File } from './s3oss.js';
|
|
4
|
+
export async function uploadOssFile(fileName, file) {
|
|
5
|
+
const config = await allConfig();
|
|
6
|
+
const ossConfig = config.conversationRecord && config.conversationRecord.ossConfig;
|
|
7
|
+
const options = {
|
|
8
|
+
region: ossConfig.region,
|
|
9
|
+
accessKeyId: ossConfig.aliAkId,
|
|
10
|
+
accessKeySecret: ossConfig.aliAkSecret,
|
|
11
|
+
bucket: ossConfig.bucket,
|
|
12
|
+
};
|
|
13
|
+
if (ossConfig.custom_domain) {
|
|
14
|
+
options.endpoint = ossConfig.custom_domain;
|
|
15
|
+
options.cname = true;
|
|
16
|
+
}
|
|
17
|
+
const store = new OSS(options);
|
|
18
|
+
const result = await store.put(fileName, file);
|
|
19
|
+
return result?.url || '';
|
|
20
|
+
}
|
|
21
|
+
export async function uploadGlobalOssFile(fileName, file) {
|
|
22
|
+
const config = await allConfig();
|
|
23
|
+
const ossConfig = config.uploadFileConfig && config.uploadFileConfig.ossConfig;
|
|
24
|
+
if (ossConfig.type === 2) {
|
|
25
|
+
// 使用S3存储
|
|
26
|
+
return await uploadGlobalS3File(fileName, file);
|
|
27
|
+
}
|
|
28
|
+
const options = {
|
|
29
|
+
region: ossConfig.region,
|
|
30
|
+
accessKeyId: ossConfig.aliAkId,
|
|
31
|
+
accessKeySecret: ossConfig.aliAkSecret,
|
|
32
|
+
bucket: ossConfig.bucket,
|
|
33
|
+
};
|
|
34
|
+
if (ossConfig.custom_domain) {
|
|
35
|
+
options.endpoint = ossConfig.custom_domain;
|
|
36
|
+
options.cname = true;
|
|
37
|
+
}
|
|
38
|
+
const store = new OSS(options);
|
|
39
|
+
const result = await store.put(fileName, file);
|
|
40
|
+
console.log('文件上传地址', result);
|
|
41
|
+
return result?.url || '';
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=oss.js.map
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// s3 存储实现
|
|
2
|
+
import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3';
|
|
3
|
+
import { allConfig } from '../db/configDb.js';
|
|
4
|
+
export async function uploadGlobalS3File(fileName, file) {
|
|
5
|
+
try {
|
|
6
|
+
const config = await allConfig();
|
|
7
|
+
const s3Config = config.uploadFileConfig && config.uploadFileConfig.ossConfig;
|
|
8
|
+
const options = {
|
|
9
|
+
region: s3Config.s3Region,
|
|
10
|
+
credentials: {
|
|
11
|
+
accessKeyId: s3Config.s3AkId,
|
|
12
|
+
secretAccessKey: s3Config.s3AkSecret,
|
|
13
|
+
},
|
|
14
|
+
endpoint: `https://${s3Config.s3Endpoint}`, // 可选,适用于自定义域名
|
|
15
|
+
};
|
|
16
|
+
console.log('上传文件到S3配置:', options);
|
|
17
|
+
const client = new S3Client(options);
|
|
18
|
+
const params = {
|
|
19
|
+
Bucket: s3Config.s3Bucket,
|
|
20
|
+
Key: fileName,
|
|
21
|
+
Body: file
|
|
22
|
+
};
|
|
23
|
+
const result = await client.send(new PutObjectCommand(params));
|
|
24
|
+
// 拼接文件访问 URL,具体格式根据你的 S3 服务商而定
|
|
25
|
+
const url = `https://${s3Config.s3Bucket}.${s3Config.s3Endpoint}${encodeURI(fileName)}`;
|
|
26
|
+
return url;
|
|
27
|
+
}
|
|
28
|
+
catch (e) {
|
|
29
|
+
console.log('s3 文件上传失败', e);
|
|
30
|
+
return '';
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=s3oss.js.map
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* 微信聊天数据 MCP 服务器入口文件
|
|
4
|
+
*
|
|
5
|
+
* 这是一个标准的 MCP (Model Context Protocol) 服务器,
|
|
6
|
+
* 允许AI模型与微信聊天数据系统进行交互。
|
|
7
|
+
*
|
|
8
|
+
* 使用方法:
|
|
9
|
+
* node mcp-server.js
|
|
10
|
+
*
|
|
11
|
+
* 或者配置在 MCP 客户端中使用
|
|
12
|
+
*/
|
|
13
|
+
import ChatMcpServer from './src/mcp/server.js';
|
|
14
|
+
async function main() {
|
|
15
|
+
const server = new ChatMcpServer();
|
|
16
|
+
await server.run();
|
|
17
|
+
}
|
|
18
|
+
// 检查是否直接运行此文件
|
|
19
|
+
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
20
|
+
main().catch((error) => {
|
|
21
|
+
console.error('启动MCP服务器失败:', error);
|
|
22
|
+
process.exit(1);
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
export default ChatMcpServer;
|
|
26
|
+
//# sourceMappingURL=mcp-server.js.map
|