@zhin.js/plugin-60s 0.0.3 → 0.0.5
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/lib/index.js +7 -445
- package/lib/index.js.map +1 -1
- package/package.json +8 -3
- package/skills/60s/SKILL.md +38 -0
- package/src/index.ts +45 -0
- package/src/index.ts.bak +487 -0
package/lib/index.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* 60s API 聚合插件 —— 基于 https://github.com/vikiboss/60s
|
|
5
5
|
*
|
|
6
|
-
* 提供多种实用 API
|
|
6
|
+
* 提供多种实用 API 功能,每个功能通过 tools/*.tool.md 文件定义:
|
|
7
7
|
* - 聊天命令(/60s, /天气 北京, /微博 …)
|
|
8
8
|
* - AI 工具(Agent 可通过关键词自动匹配并调用)
|
|
9
9
|
*
|
|
@@ -12,6 +12,8 @@
|
|
|
12
12
|
* 一言 · 摸鱼日历 · IP查询 · Bing壁纸 · 金价 · 油价
|
|
13
13
|
* 汇率 · 翻译 · 历史上的今天 · KFC文案 · 段子
|
|
14
14
|
*
|
|
15
|
+
* 所有工具定义在 tools/ 目录下,框架自动发现注册。
|
|
16
|
+
*
|
|
15
17
|
* 配置方式(zhin.config.yml):
|
|
16
18
|
* ```yaml
|
|
17
19
|
* plugins:
|
|
@@ -19,7 +21,7 @@
|
|
|
19
21
|
* apiBase: https://60s.viki.moe
|
|
20
22
|
* ```
|
|
21
23
|
*/
|
|
22
|
-
import { usePlugin
|
|
24
|
+
import { usePlugin } from 'zhin.js';
|
|
23
25
|
const plugin = usePlugin();
|
|
24
26
|
const { logger, root } = plugin;
|
|
25
27
|
const configService = root.inject('config');
|
|
@@ -28,447 +30,7 @@ const config = {
|
|
|
28
30
|
apiBase: 'https://60s.viki.moe',
|
|
29
31
|
...appConfig['60s'],
|
|
30
32
|
};
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
async function fetchApi(endpoint, params) {
|
|
35
|
-
const url = new URL(`${API_BASE}/v2${endpoint}`);
|
|
36
|
-
if (params) {
|
|
37
|
-
Object.entries(params).forEach(([k, v]) => url.searchParams.set(k, v));
|
|
38
|
-
}
|
|
39
|
-
logger.debug(`[60s] 请求: ${url.toString()}`);
|
|
40
|
-
const res = await fetch(url.toString());
|
|
41
|
-
const data = (await res.json());
|
|
42
|
-
if (data.error)
|
|
43
|
-
throw new Error(data.error);
|
|
44
|
-
if (data.code !== undefined && data.code !== 200 && data.code !== 0) {
|
|
45
|
-
throw new Error(data.message || data.msg || `API 错误: ${data.code}`);
|
|
46
|
-
}
|
|
47
|
-
return data.data ?? data;
|
|
48
|
-
}
|
|
49
|
-
// ─── 工具函数 ────────────────────────────────────────────────────────────────
|
|
50
|
-
function formatList(items, limit = 10) {
|
|
51
|
-
return items
|
|
52
|
-
.slice(0, limit)
|
|
53
|
-
.map((item, i) => {
|
|
54
|
-
const title = item.title || item.name || item.word || item;
|
|
55
|
-
const hot = item.hot_value || item.hot;
|
|
56
|
-
const hotStr = hot ? ` 🔥${hot}` : '';
|
|
57
|
-
return `${i + 1}. ${title}${hotStr}`;
|
|
58
|
-
})
|
|
59
|
-
.join('\n');
|
|
60
|
-
}
|
|
61
|
-
// ═══════════════════════════════════════════════════════════════════════════════
|
|
62
|
-
// 工具定义(ZhinTool 链式风格 — 同时注册命令 + AI 工具)
|
|
63
|
-
// ═══════════════════════════════════════════════════════════════════════════════
|
|
64
|
-
// ── 60 秒新闻 ────────────────────────────────────────────────────────────────
|
|
65
|
-
const newsTool = new ZhinTool('60s_news')
|
|
66
|
-
.desc('获取每日60秒新闻,快速了解今日要闻')
|
|
67
|
-
.tag('新闻', '资讯', '60s')
|
|
68
|
-
.keyword('60s', '新闻', '今日新闻', '60秒', '每日新闻', '读懂世界')
|
|
69
|
-
.alias('新闻', '今日新闻', '60秒')
|
|
70
|
-
.usage('获取今日60秒新闻')
|
|
71
|
-
.examples('/60s')
|
|
72
|
-
.execute(async () => {
|
|
73
|
-
const data = await fetchApi('/60s');
|
|
74
|
-
const lines = [`📰 今日60秒新闻 (${data.date || ''})`, ''];
|
|
75
|
-
if (data.news && Array.isArray(data.news)) {
|
|
76
|
-
lines.push(...data.news.map((n, i) => `${i + 1}. ${n}`));
|
|
77
|
-
}
|
|
78
|
-
if (data.tip)
|
|
79
|
-
lines.push('', `💡 ${data.tip}`);
|
|
80
|
-
return lines.join('\n');
|
|
81
|
-
});
|
|
82
|
-
// ── 天气 ──────────────────────────────────────────────────────────────────────
|
|
83
|
-
const weatherTool = new ZhinTool('weather')
|
|
84
|
-
.desc('查询指定城市的当前天气信息')
|
|
85
|
-
.tag('天气', '生活', '查询')
|
|
86
|
-
.keyword('天气', '气温', '温度', '下雨', '晴天', '阴天', 'weather')
|
|
87
|
-
.alias('天气', 'tq')
|
|
88
|
-
.usage('查询城市天气')
|
|
89
|
-
.examples('/weather 成都', '/天气 北京')
|
|
90
|
-
.param('city', { type: 'string', description: '城市名称,如"成都"、"北京"' }, true)
|
|
91
|
-
.execute(async (args) => {
|
|
92
|
-
const data = await fetchApi('/weather', { city: args.city });
|
|
93
|
-
const w = data.weather;
|
|
94
|
-
const aq = data.air_quality;
|
|
95
|
-
const loc = data.location;
|
|
96
|
-
const cityName = loc?.city || loc?.name || args.city;
|
|
97
|
-
const lines = [
|
|
98
|
-
`🌤️ ${cityName} 天气`,
|
|
99
|
-
'',
|
|
100
|
-
`🌡️ 温度: ${w.temperature}°C`,
|
|
101
|
-
`☁️ 天气: ${w.condition}`,
|
|
102
|
-
`💧 湿度: ${w.humidity}%`,
|
|
103
|
-
`💨 风: ${w.wind_direction} ${w.wind_power}`,
|
|
104
|
-
];
|
|
105
|
-
if (aq) {
|
|
106
|
-
const quality = aq.quality || '';
|
|
107
|
-
lines.push(`🌬️ 空气: ${quality}${aq.aqi ? ` (AQI ${aq.aqi})` : ''}`);
|
|
108
|
-
}
|
|
109
|
-
return lines.join('\n');
|
|
110
|
-
});
|
|
111
|
-
// ── 微博热搜 ──────────────────────────────────────────────────────────────────
|
|
112
|
-
const weiboTool = new ZhinTool('weibo_hot')
|
|
113
|
-
.desc('获取微博热搜榜')
|
|
114
|
-
.tag('热搜', '社交', '微博')
|
|
115
|
-
.keyword('微博', '热搜', 'weibo', 'wb')
|
|
116
|
-
.alias('微博热搜', 'wb')
|
|
117
|
-
.usage('获取微博热搜')
|
|
118
|
-
.examples('/weibo', '/weibo 20')
|
|
119
|
-
.param('limit', { type: 'number', description: '返回条数,默认10条' })
|
|
120
|
-
.execute(async (args) => {
|
|
121
|
-
const data = await fetchApi('/weibo');
|
|
122
|
-
return ['🔥 微博热搜', '', formatList(data, args.limit || 10)].join('\n');
|
|
123
|
-
});
|
|
124
|
-
// ── 知乎热榜 ──────────────────────────────────────────────────────────────────
|
|
125
|
-
const zhihuTool = new ZhinTool('zhihu_hot')
|
|
126
|
-
.desc('获取知乎热榜')
|
|
127
|
-
.tag('热搜', '社交', '知乎')
|
|
128
|
-
.keyword('知乎', '热榜', 'zhihu', 'zh')
|
|
129
|
-
.alias('知乎热榜', 'zh')
|
|
130
|
-
.usage('获取知乎热榜')
|
|
131
|
-
.examples('/zhihu', '/zhihu 20')
|
|
132
|
-
.param('limit', { type: 'number', description: '返回条数,默认10条' })
|
|
133
|
-
.execute(async (args) => {
|
|
134
|
-
const data = await fetchApi('/zhihu');
|
|
135
|
-
return ['🔥 知乎热榜', '', formatList(data, args.limit || 10)].join('\n');
|
|
136
|
-
});
|
|
137
|
-
// ── 抖音热搜 ──────────────────────────────────────────────────────────────────
|
|
138
|
-
const douyinTool = new ZhinTool('douyin_hot')
|
|
139
|
-
.desc('获取抖音热搜榜')
|
|
140
|
-
.tag('热搜', '短视频', '抖音')
|
|
141
|
-
.keyword('抖音', '热搜', 'douyin', 'dy')
|
|
142
|
-
.alias('抖音热搜', 'dy')
|
|
143
|
-
.usage('获取抖音热搜')
|
|
144
|
-
.examples('/douyin', '/douyin 20')
|
|
145
|
-
.param('limit', { type: 'number', description: '返回条数,默认10条' })
|
|
146
|
-
.execute(async (args) => {
|
|
147
|
-
const data = await fetchApi('/douyin');
|
|
148
|
-
return ['🔥 抖音热搜', '', formatList(data, args.limit || 10)].join('\n');
|
|
149
|
-
});
|
|
150
|
-
// ── 头条热搜 ──────────────────────────────────────────────────────────────────
|
|
151
|
-
const toutiaoTool = new ZhinTool('toutiao_hot')
|
|
152
|
-
.desc('获取今日头条热搜榜')
|
|
153
|
-
.tag('热搜', '资讯', '头条')
|
|
154
|
-
.keyword('头条', '今日头条', '热搜', 'toutiao', 'tt')
|
|
155
|
-
.alias('头条热搜', 'tt')
|
|
156
|
-
.usage('获取头条热搜')
|
|
157
|
-
.examples('/toutiao', '/tt 20')
|
|
158
|
-
.param('limit', { type: 'number', description: '返回条数,默认10条' })
|
|
159
|
-
.execute(async (args) => {
|
|
160
|
-
const data = await fetchApi('/toutiao');
|
|
161
|
-
return ['🔥 头条热搜', '', formatList(data, args.limit || 10)].join('\n');
|
|
162
|
-
});
|
|
163
|
-
// ── 一言 ──────────────────────────────────────────────────────────────────────
|
|
164
|
-
const hitokotoTool = new ZhinTool('hitokoto')
|
|
165
|
-
.desc('获取一言/每日一句,随机返回一条语句')
|
|
166
|
-
.tag('语录', '文学', '随机')
|
|
167
|
-
.keyword('一言', '每日一句', '语录', '名言', 'hitokoto')
|
|
168
|
-
.alias('一言', '每日一句', 'yy')
|
|
169
|
-
.usage('获取随机一言')
|
|
170
|
-
.examples('/hitokoto', '/一言 i')
|
|
171
|
-
.param('type', {
|
|
172
|
-
type: 'string',
|
|
173
|
-
description: '类型:a=动画, b=漫画, c=游戏, d=文学, e=原创, f=网络, g=其他, h=影视, i=诗词, j=网易云, k=哲学, l=抖机灵',
|
|
174
|
-
})
|
|
175
|
-
.execute(async (args) => {
|
|
176
|
-
const params = args.type
|
|
177
|
-
? { c: args.type }
|
|
178
|
-
: undefined;
|
|
179
|
-
const data = await fetchApi('/hitokoto', params);
|
|
180
|
-
const text = data.hitokoto || data.content || (typeof data === 'string' ? data : '');
|
|
181
|
-
const lines = ['💬 一言', '', `「${text}」`];
|
|
182
|
-
if (data.from || data.source || data.from_who || data.author) {
|
|
183
|
-
const author = data.from_who || data.author || '';
|
|
184
|
-
const source = data.from || data.source || '';
|
|
185
|
-
lines.push(`——${author}${source ? `《${source}》` : ''}`);
|
|
186
|
-
}
|
|
187
|
-
return lines.join('\n');
|
|
188
|
-
});
|
|
189
|
-
// ── 摸鱼日历 ──────────────────────────────────────────────────────────────────
|
|
190
|
-
const moyuTool = new ZhinTool('moyu')
|
|
191
|
-
.desc('获取摸鱼日历,查看今天适不适合摸鱼')
|
|
192
|
-
.tag('生活', '摸鱼', '日历')
|
|
193
|
-
.keyword('摸鱼', '摸鱼日历', 'moyu')
|
|
194
|
-
.alias('摸鱼', '摸鱼日历')
|
|
195
|
-
.usage('获取摸鱼日历')
|
|
196
|
-
.examples('/moyu')
|
|
197
|
-
.execute(async () => {
|
|
198
|
-
const data = await fetchApi('/moyu');
|
|
199
|
-
if (typeof data === 'string')
|
|
200
|
-
return `🐟 摸鱼日历\n\n${data}`;
|
|
201
|
-
const lines = ['🐟 摸鱼日历', ''];
|
|
202
|
-
if (data.date?.gregorian)
|
|
203
|
-
lines.push(`📅 ${data.date.gregorian} ${data.date.weekday || ''}`);
|
|
204
|
-
if (data.date?.lunar) {
|
|
205
|
-
const l = data.date.lunar;
|
|
206
|
-
lines.push(`🌙 农历${l.monthCN || ''}${l.dayCN || ''} ${l.yearGanZhi || ''}年`);
|
|
207
|
-
}
|
|
208
|
-
if (data.today) {
|
|
209
|
-
const t = data.today;
|
|
210
|
-
if (t.holidayName)
|
|
211
|
-
lines.push(`🎉 ${t.holidayName}`);
|
|
212
|
-
if (t.solarTerm)
|
|
213
|
-
lines.push(`🌿 ${t.solarTerm}`);
|
|
214
|
-
lines.push(t.isWorkday ? '💼 今天是工作日' : '🎮 今天不上班');
|
|
215
|
-
}
|
|
216
|
-
if (data.festivals && Array.isArray(data.festivals)) {
|
|
217
|
-
data.festivals.forEach((f) => lines.push(`🎊 ${f.name || f}`));
|
|
218
|
-
}
|
|
219
|
-
if (data.countdown && Array.isArray(data.countdown)) {
|
|
220
|
-
lines.push('');
|
|
221
|
-
data.countdown.forEach((c) => {
|
|
222
|
-
if (c.name && c.days !== undefined)
|
|
223
|
-
lines.push(`⏳ 距 ${c.name} 还有 ${c.days} 天`);
|
|
224
|
-
});
|
|
225
|
-
}
|
|
226
|
-
return lines.join('\n');
|
|
227
|
-
});
|
|
228
|
-
// ── IP 查询 ───────────────────────────────────────────────────────────────────
|
|
229
|
-
const ipTool = new ZhinTool('ip_query')
|
|
230
|
-
.desc('查询 IP 地址的地理位置信息')
|
|
231
|
-
.tag('网络', '查询', 'IP')
|
|
232
|
-
.keyword('ip', 'IP', 'IP查询', 'ip查询')
|
|
233
|
-
.alias('IP查询')
|
|
234
|
-
.usage('查询 IP 地址信息')
|
|
235
|
-
.examples('/ip', '/ip 8.8.8.8')
|
|
236
|
-
.param('ip', { type: 'string', description: 'IP 地址,不填则查询当前 IP' })
|
|
237
|
-
.execute(async (args) => {
|
|
238
|
-
const params = args.ip
|
|
239
|
-
? { ip: args.ip }
|
|
240
|
-
: undefined;
|
|
241
|
-
const data = await fetchApi('/ip', params);
|
|
242
|
-
const lines = ['🌐 IP 查询', '', `IP: ${data.ip || args.ip || '当前 IP'}`];
|
|
243
|
-
if (data.country || data.region || data.city) {
|
|
244
|
-
lines.push(`位置: ${[data.country, data.region, data.city].filter(Boolean).join(' ')}`);
|
|
245
|
-
}
|
|
246
|
-
if (data.location)
|
|
247
|
-
lines.push(`位置: ${data.location}`);
|
|
248
|
-
if (data.isp)
|
|
249
|
-
lines.push(`运营商: ${data.isp}`);
|
|
250
|
-
return lines.join('\n');
|
|
251
|
-
});
|
|
252
|
-
// ── Bing 每日图片 ─────────────────────────────────────────────────────────────
|
|
253
|
-
const bingTool = new ZhinTool('bing_image')
|
|
254
|
-
.desc('获取 Bing 每日壁纸图片')
|
|
255
|
-
.tag('图片', '壁纸', 'Bing')
|
|
256
|
-
.keyword('bing', '必应', '壁纸', '每日壁纸')
|
|
257
|
-
.alias('必应', '每日壁纸')
|
|
258
|
-
.usage('获取 Bing 每日壁纸')
|
|
259
|
-
.examples('/bing')
|
|
260
|
-
.execute(async () => {
|
|
261
|
-
const data = await fetchApi('/bing');
|
|
262
|
-
const lines = ['🖼️ Bing 每日壁纸', ''];
|
|
263
|
-
if (data.title)
|
|
264
|
-
lines.push(`📌 ${data.title}`);
|
|
265
|
-
if (data.headline)
|
|
266
|
-
lines.push(`💡 ${data.headline}`);
|
|
267
|
-
if (data.copyright)
|
|
268
|
-
lines.push(`📝 ${data.copyright}`);
|
|
269
|
-
if (data.description)
|
|
270
|
-
lines.push('', data.description);
|
|
271
|
-
const imgUrl = data.cover || data.cover_4k || data.url || data.image;
|
|
272
|
-
if (imgUrl)
|
|
273
|
-
lines.push('', imgUrl);
|
|
274
|
-
return lines.join('\n');
|
|
275
|
-
});
|
|
276
|
-
// ── 金价 ──────────────────────────────────────────────────────────────────────
|
|
277
|
-
const goldPriceTool = new ZhinTool('gold_price')
|
|
278
|
-
.desc('查询今日黄金价格')
|
|
279
|
-
.tag('金融', '黄金', '价格')
|
|
280
|
-
.keyword('金价', '黄金', '黄金价格', 'gold')
|
|
281
|
-
.alias('金价', '黄金价格', 'jj')
|
|
282
|
-
.usage('查询今日金价')
|
|
283
|
-
.examples('/gold', '/金价')
|
|
284
|
-
.execute(async () => {
|
|
285
|
-
const data = await fetchApi('/gold-price');
|
|
286
|
-
const lines = ['💰 今日金价', ''];
|
|
287
|
-
if (data.date)
|
|
288
|
-
lines.push(`📅 ${data.date}`);
|
|
289
|
-
const metals = data.metals || (Array.isArray(data) ? data : []);
|
|
290
|
-
if (metals.length > 0) {
|
|
291
|
-
lines.push('');
|
|
292
|
-
metals.forEach((item) => {
|
|
293
|
-
const name = item.name || '黄金';
|
|
294
|
-
const price = item.today_price || item.sell_price || item.price || 'N/A';
|
|
295
|
-
const unit = item.unit || '元/克';
|
|
296
|
-
if (price !== 'N/A')
|
|
297
|
-
lines.push(`${name}: ¥${price} ${unit}`);
|
|
298
|
-
});
|
|
299
|
-
}
|
|
300
|
-
else if (data.price) {
|
|
301
|
-
lines.push(`当前金价: ¥${data.price}/克`);
|
|
302
|
-
}
|
|
303
|
-
return lines.join('\n');
|
|
304
|
-
});
|
|
305
|
-
// ── 油价 ──────────────────────────────────────────────────────────────────────
|
|
306
|
-
const fuelPriceTool = new ZhinTool('fuel_price')
|
|
307
|
-
.desc('查询今日油价')
|
|
308
|
-
.tag('生活', '油价', '价格')
|
|
309
|
-
.keyword('油价', '汽油', '柴油', 'fuel')
|
|
310
|
-
.alias('油价', 'yj')
|
|
311
|
-
.usage('查询今日油价')
|
|
312
|
-
.examples('/fuel', '/油价 四川')
|
|
313
|
-
.param('province', { type: 'string', description: '省份名称,如"四川"、"北京"' })
|
|
314
|
-
.execute(async (args) => {
|
|
315
|
-
const params = args.province
|
|
316
|
-
? { province: args.province }
|
|
317
|
-
: undefined;
|
|
318
|
-
const data = await fetchApi('/fuel-price', params);
|
|
319
|
-
const lines = ['⛽ 今日油价', ''];
|
|
320
|
-
if (data.region)
|
|
321
|
-
lines.push(`📍 ${data.region}`);
|
|
322
|
-
if (data.items && Array.isArray(data.items)) {
|
|
323
|
-
data.items.forEach((item) => {
|
|
324
|
-
lines.push(`${item.name}: ${item.price_desc || `¥${item.price}/升`}`);
|
|
325
|
-
});
|
|
326
|
-
}
|
|
327
|
-
if (data.trend) {
|
|
328
|
-
lines.push('', `📊 ${data.trend.description || ''}`);
|
|
329
|
-
}
|
|
330
|
-
return lines.join('\n');
|
|
331
|
-
});
|
|
332
|
-
// ── 汇率 ──────────────────────────────────────────────────────────────────────
|
|
333
|
-
const exchangeRateTool = new ZhinTool('exchange_rate')
|
|
334
|
-
.desc('查询货币汇率')
|
|
335
|
-
.tag('金融', '汇率', '查询')
|
|
336
|
-
.keyword('汇率', '兑换', '外汇', 'exchange', 'rate')
|
|
337
|
-
.alias('汇率', 'hl')
|
|
338
|
-
.usage('查询汇率')
|
|
339
|
-
.examples('/exchange USD CNY', '/汇率')
|
|
340
|
-
.param('from', { type: 'string', description: '源货币,如 USD, EUR, JPY' })
|
|
341
|
-
.param('to', { type: 'string', description: '目标货币,如 CNY' })
|
|
342
|
-
.execute(async (args) => {
|
|
343
|
-
const params = {};
|
|
344
|
-
if (args.from)
|
|
345
|
-
params.from = args.from.toUpperCase();
|
|
346
|
-
if (args.to)
|
|
347
|
-
params.to = args.to.toUpperCase();
|
|
348
|
-
const data = await fetchApi('/exchange-rate', Object.keys(params).length ? params : undefined);
|
|
349
|
-
const lines = ['💱 汇率查询', ''];
|
|
350
|
-
const base = data.base_code || args.from || 'CNY';
|
|
351
|
-
lines.push(`基准货币: ${base}`);
|
|
352
|
-
if (data.updated)
|
|
353
|
-
lines.push(`更新时间: ${data.updated}`);
|
|
354
|
-
lines.push('');
|
|
355
|
-
const rates = data.rates || (Array.isArray(data) ? data : []);
|
|
356
|
-
const targetCurrencies = args.to
|
|
357
|
-
? [args.to.toUpperCase()]
|
|
358
|
-
: ['USD', 'EUR', 'JPY', 'GBP', 'HKD', 'KRW', 'AUD', 'CAD', 'SGD', 'CHF'];
|
|
359
|
-
rates.forEach((item) => {
|
|
360
|
-
if (targetCurrencies.includes(item.currency) && item.currency !== base) {
|
|
361
|
-
lines.push(`${base} → ${item.currency}: ${item.rate}`);
|
|
362
|
-
}
|
|
363
|
-
});
|
|
364
|
-
return lines.join('\n');
|
|
365
|
-
});
|
|
366
|
-
// ── 翻译 ──────────────────────────────────────────────────────────────────────
|
|
367
|
-
const translateTool = new ZhinTool('translate_60s')
|
|
368
|
-
.desc('翻译文本')
|
|
369
|
-
.tag('工具', '翻译', '语言')
|
|
370
|
-
.keyword('翻译', '英文', '中文', '日文', 'translate', '译')
|
|
371
|
-
.alias('翻译', 'fy')
|
|
372
|
-
.usage('翻译文本')
|
|
373
|
-
.examples('/fanyi hello', '/翻译 你好 en')
|
|
374
|
-
.param('text', { type: 'string', description: '要翻译的文本' }, true)
|
|
375
|
-
.param('to', { type: 'string', description: '目标语言,如 en, zh, ja' })
|
|
376
|
-
.execute(async (args) => {
|
|
377
|
-
const params = { text: args.text };
|
|
378
|
-
if (args.to)
|
|
379
|
-
params.to = args.to;
|
|
380
|
-
const data = await fetchApi('/fanyi', params);
|
|
381
|
-
const srcText = data.source?.text || args.text;
|
|
382
|
-
const srcLang = data.source?.type_desc || data.source?.type || '';
|
|
383
|
-
const tgtText = data.target?.text || data.result || data.translation || (typeof data === 'string' ? data : '');
|
|
384
|
-
const tgtLang = data.target?.type_desc || data.target?.type || '';
|
|
385
|
-
const lines = [
|
|
386
|
-
'🌐 翻译结果',
|
|
387
|
-
'',
|
|
388
|
-
`原文${srcLang ? ` (${srcLang})` : ''}: ${srcText}`,
|
|
389
|
-
`译文${tgtLang ? ` (${tgtLang})` : ''}: ${tgtText}`,
|
|
390
|
-
];
|
|
391
|
-
if (data.target?.pronounce)
|
|
392
|
-
lines.push(`发音: ${data.target.pronounce}`);
|
|
393
|
-
return lines.join('\n');
|
|
394
|
-
});
|
|
395
|
-
// ── 历史上的今天 ──────────────────────────────────────────────────────────────
|
|
396
|
-
const historyTodayTool = new ZhinTool('history_today')
|
|
397
|
-
.desc('查看历史上的今天发生了什么')
|
|
398
|
-
.tag('历史', '知识', '日历')
|
|
399
|
-
.keyword('历史', '历史上的今天', '今天历史', 'history')
|
|
400
|
-
.alias('历史上的今天', '历史')
|
|
401
|
-
.usage('查看历史上的今天')
|
|
402
|
-
.examples('/history')
|
|
403
|
-
.execute(async () => {
|
|
404
|
-
const data = await fetchApi('/today-in-history');
|
|
405
|
-
const dateStr = data.date || `${data.month || ''}月${data.day || ''}日`;
|
|
406
|
-
const lines = [`📅 历史上的今天 (${dateStr})`, ''];
|
|
407
|
-
const items = data.items || (Array.isArray(data) ? data : []);
|
|
408
|
-
items.slice(0, 10).forEach((item, i) => {
|
|
409
|
-
const year = item.year || '';
|
|
410
|
-
const title = item.title || item.event || item.content || item;
|
|
411
|
-
const typeIcon = item.event_type === 'birth' ? '👶' : item.event_type === 'death' ? '🕊️' : '📌';
|
|
412
|
-
lines.push(`${typeIcon} ${i + 1}. ${year ? `[${year}] ` : ''}${title}`);
|
|
413
|
-
});
|
|
414
|
-
return lines.join('\n');
|
|
415
|
-
});
|
|
416
|
-
// ── KFC 疯狂星期四 ────────────────────────────────────────────────────────────
|
|
417
|
-
const kfcTool = new ZhinTool('kfc')
|
|
418
|
-
.desc('获取 KFC 疯狂星期四文案')
|
|
419
|
-
.tag('娱乐', 'KFC', '文案')
|
|
420
|
-
.keyword('kfc', 'KFC', '疯狂星期四', 'v50', '肯德基')
|
|
421
|
-
.alias('疯狂星期四', 'v50')
|
|
422
|
-
.usage('获取 KFC 文案')
|
|
423
|
-
.examples('/kfc')
|
|
424
|
-
.execute(async () => {
|
|
425
|
-
const data = await fetchApi('/kfc');
|
|
426
|
-
return `🍗 疯狂星期四\n\n${data.kfc || data.content || data.text || (typeof data === 'string' ? data : '')}`;
|
|
427
|
-
});
|
|
428
|
-
// ── 段子 ──────────────────────────────────────────────────────────────────────
|
|
429
|
-
const duanziTool = new ZhinTool('duanzi')
|
|
430
|
-
.desc('获取一个段子')
|
|
431
|
-
.tag('娱乐', '笑话', '段子')
|
|
432
|
-
.keyword('段子', '笑话', '搞笑', 'joke', 'duanzi')
|
|
433
|
-
.alias('段子', 'joke')
|
|
434
|
-
.usage('获取段子')
|
|
435
|
-
.examples('/duanzi')
|
|
436
|
-
.execute(async () => {
|
|
437
|
-
const data = await fetchApi('/duanzi');
|
|
438
|
-
return `😂 段子\n\n${data.duanzi || data.content || data.text || (typeof data === 'string' ? data : '')}`;
|
|
439
|
-
});
|
|
440
|
-
// ═══════════════════════════════════════════════════════════════════════════════
|
|
441
|
-
// 注册所有工具
|
|
442
|
-
// ═══════════════════════════════════════════════════════════════════════════════
|
|
443
|
-
const allTools = [
|
|
444
|
-
newsTool,
|
|
445
|
-
weatherTool,
|
|
446
|
-
weiboTool,
|
|
447
|
-
zhihuTool,
|
|
448
|
-
douyinTool,
|
|
449
|
-
toutiaoTool,
|
|
450
|
-
hitokotoTool,
|
|
451
|
-
moyuTool,
|
|
452
|
-
ipTool,
|
|
453
|
-
bingTool,
|
|
454
|
-
goldPriceTool,
|
|
455
|
-
fuelPriceTool,
|
|
456
|
-
exchangeRateTool,
|
|
457
|
-
translateTool,
|
|
458
|
-
historyTodayTool,
|
|
459
|
-
kfcTool,
|
|
460
|
-
duanziTool,
|
|
461
|
-
];
|
|
462
|
-
allTools.forEach((tool) => plugin.addTool(tool.toTool()));
|
|
463
|
-
// 声明 Skill 元数据 — 让 AI Agent 知道这个插件的能力
|
|
464
|
-
plugin.declareSkill({
|
|
465
|
-
description: '60s API 聚合服务:提供新闻、天气、热搜、金价、油价、汇率、翻译、一言、摸鱼日历等 17 种实用查询能力',
|
|
466
|
-
tags: ['新闻', '资讯', '天气', '热搜', '生活', '金融', '娱乐', '工具'],
|
|
467
|
-
keywords: [
|
|
468
|
-
'60s', '新闻', '天气', '微博', '知乎', '抖音', '头条',
|
|
469
|
-
'一言', '摸鱼', '金价', '油价', '汇率', '翻译', '历史',
|
|
470
|
-
'kfc', '段子', '壁纸', 'bing', 'ip',
|
|
471
|
-
],
|
|
472
|
-
});
|
|
473
|
-
logger.debug(`[60s] 已注册 ${allTools.length} 个工具`);
|
|
33
|
+
// 将 API 地址写入环境变量,供 tool handler 使用
|
|
34
|
+
process.env.ZHIN_60S_API = config.apiBase || 'https://60s.viki.moe';
|
|
35
|
+
logger.info(`[60s] 插件已加载,API 地址: ${process.env.ZHIN_60S_API},工具由 tools/ 目录自动发现`);
|
|
474
36
|
//# sourceMappingURL=index.js.map
|
package/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAEpC,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;AAC3B,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,CAAC;AAQhC,MAAM,aAAa,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;AAC5C,MAAM,SAAS,GAAG,aAAa,EAAE,GAAG,CAAqB,iBAAiB,CAAC,IAAI,EAAE,CAAC;AAClF,MAAM,MAAM,GAAW;IACrB,OAAO,EAAE,sBAAsB;IAC/B,GAAG,SAAS,CAAC,KAAK,CAAC;CACpB,CAAC;AAEF,mCAAmC;AACnC,OAAO,CAAC,GAAG,CAAC,YAAY,GAAG,MAAM,CAAC,OAAO,IAAI,sBAAsB,CAAC;AAEpE,MAAM,CAAC,IAAI,CAAC,uBAAuB,OAAO,CAAC,GAAG,CAAC,YAAY,oBAAoB,CAAC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zhin.js/plugin-60s",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.5",
|
|
4
4
|
"description": "60s API aggregation plugin for Zhin.js — news, weather, hot searches, utilities and more",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./lib/index.js",
|
|
@@ -14,11 +14,16 @@
|
|
|
14
14
|
"./package.json": "./package.json"
|
|
15
15
|
},
|
|
16
16
|
"files": [
|
|
17
|
+
"src",
|
|
17
18
|
"lib",
|
|
19
|
+
"client",
|
|
20
|
+
"dist",
|
|
21
|
+
"skills",
|
|
18
22
|
"README.md"
|
|
19
23
|
],
|
|
20
24
|
"keywords": [
|
|
21
25
|
"zhin",
|
|
26
|
+
"zhin.js",
|
|
22
27
|
"bot",
|
|
23
28
|
"plugin",
|
|
24
29
|
"60s",
|
|
@@ -41,10 +46,10 @@
|
|
|
41
46
|
"dependencies": {},
|
|
42
47
|
"devDependencies": {
|
|
43
48
|
"typescript": "^5.3.3",
|
|
44
|
-
"zhin.js": "1.0.
|
|
49
|
+
"zhin.js": "1.0.54"
|
|
45
50
|
},
|
|
46
51
|
"peerDependencies": {
|
|
47
|
-
"zhin.js": ">=1.0.
|
|
52
|
+
"zhin.js": ">=1.0.54"
|
|
48
53
|
},
|
|
49
54
|
"repository": {
|
|
50
55
|
"type": "git",
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: "60s"
|
|
3
|
+
description: 60s API 聚合服务:提供新闻、天气、热搜、金价、油价、汇率、翻译、一言、摸鱼日历等多种实用查询能力。
|
|
4
|
+
keywords:
|
|
5
|
+
- 60s
|
|
6
|
+
- 新闻
|
|
7
|
+
- 天气
|
|
8
|
+
- 微博
|
|
9
|
+
- 知乎
|
|
10
|
+
- 抖音
|
|
11
|
+
- 头条
|
|
12
|
+
- 一言
|
|
13
|
+
- 摸鱼
|
|
14
|
+
- 金价
|
|
15
|
+
- 油价
|
|
16
|
+
- 汇率
|
|
17
|
+
- 翻译
|
|
18
|
+
- 历史
|
|
19
|
+
- kfc
|
|
20
|
+
- 段子
|
|
21
|
+
- 壁纸
|
|
22
|
+
- bing
|
|
23
|
+
- ip
|
|
24
|
+
tags:
|
|
25
|
+
- 新闻
|
|
26
|
+
- 资讯
|
|
27
|
+
- 天气
|
|
28
|
+
- 热搜
|
|
29
|
+
- 生活
|
|
30
|
+
- 金融
|
|
31
|
+
- 娱乐
|
|
32
|
+
- 工具
|
|
33
|
+
tools: []
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## 执行规则
|
|
37
|
+
|
|
38
|
+
- 按用户意图选择对应 `*_60s` 或插件注册名称的工具完成查询。
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @zhin.js/plugin-60s
|
|
3
|
+
*
|
|
4
|
+
* 60s API 聚合插件 —— 基于 https://github.com/vikiboss/60s
|
|
5
|
+
*
|
|
6
|
+
* 提供多种实用 API 功能,每个功能通过 tools/*.tool.md 文件定义:
|
|
7
|
+
* - 聊天命令(/60s, /天气 北京, /微博 …)
|
|
8
|
+
* - AI 工具(Agent 可通过关键词自动匹配并调用)
|
|
9
|
+
*
|
|
10
|
+
* 功能列表:
|
|
11
|
+
* 60s新闻 · 天气 · 微博热搜 · 知乎热榜 · 抖音热搜 · 头条热搜
|
|
12
|
+
* 一言 · 摸鱼日历 · IP查询 · Bing壁纸 · 金价 · 油价
|
|
13
|
+
* 汇率 · 翻译 · 历史上的今天 · KFC文案 · 段子
|
|
14
|
+
*
|
|
15
|
+
* 所有工具定义在 tools/ 目录下,框架自动发现注册。
|
|
16
|
+
*
|
|
17
|
+
* 配置方式(zhin.config.yml):
|
|
18
|
+
* ```yaml
|
|
19
|
+
* plugins:
|
|
20
|
+
* 60s:
|
|
21
|
+
* apiBase: https://60s.viki.moe
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
import { usePlugin } from 'zhin.js';
|
|
25
|
+
|
|
26
|
+
const plugin = usePlugin();
|
|
27
|
+
const { logger, root } = plugin;
|
|
28
|
+
|
|
29
|
+
// ─── 配置 ────────────────────────────────────────────────────────────────────
|
|
30
|
+
|
|
31
|
+
interface Config {
|
|
32
|
+
apiBase?: string;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const configService = root.inject('config');
|
|
36
|
+
const appConfig = configService?.get<{ '60s'?: Config }>('zhin.config.yml') || {};
|
|
37
|
+
const config: Config = {
|
|
38
|
+
apiBase: 'https://60s.viki.moe',
|
|
39
|
+
...appConfig['60s'],
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
// 将 API 地址写入环境变量,供 tool handler 使用
|
|
43
|
+
process.env.ZHIN_60S_API = config.apiBase || 'https://60s.viki.moe';
|
|
44
|
+
|
|
45
|
+
logger.info(`[60s] 插件已加载,API 地址: ${process.env.ZHIN_60S_API},工具由 tools/ 目录自动发现`);
|
package/src/index.ts.bak
ADDED
|
@@ -0,0 +1,487 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @zhin.js/plugin-60s
|
|
3
|
+
*
|
|
4
|
+
* 60s API 聚合插件 —— 基于 https://github.com/vikiboss/60s
|
|
5
|
+
*
|
|
6
|
+
* 提供多种实用 API 功能,每个功能同时注册为:
|
|
7
|
+
* - 聊天命令(/60s, /天气 北京, /微博 …)
|
|
8
|
+
* - AI 工具(Agent 可通过关键词自动匹配并调用)
|
|
9
|
+
*
|
|
10
|
+
* 功能列表:
|
|
11
|
+
* 60s新闻 · 天气 · 微博热搜 · 知乎热榜 · 抖音热搜 · 头条热搜
|
|
12
|
+
* 一言 · 摸鱼日历 · IP查询 · Bing壁纸 · 金价 · 油价
|
|
13
|
+
* 汇率 · 翻译 · 历史上的今天 · KFC文案 · 段子
|
|
14
|
+
*
|
|
15
|
+
* 配置方式(zhin.config.yml):
|
|
16
|
+
* ```yaml
|
|
17
|
+
* plugins:
|
|
18
|
+
* 60s:
|
|
19
|
+
* apiBase: https://60s.viki.moe
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
import { usePlugin, ZhinTool } from 'zhin.js';
|
|
23
|
+
|
|
24
|
+
const plugin = usePlugin();
|
|
25
|
+
const { logger, root } = plugin;
|
|
26
|
+
|
|
27
|
+
// ─── 配置 ────────────────────────────────────────────────────────────────────
|
|
28
|
+
|
|
29
|
+
interface Config {
|
|
30
|
+
apiBase?: string;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const configService = root.inject('config');
|
|
34
|
+
const appConfig = configService?.get<{ '60s'?: Config }>('zhin.config.yml') || {};
|
|
35
|
+
const config: Config = {
|
|
36
|
+
apiBase: 'https://60s.viki.moe',
|
|
37
|
+
...appConfig['60s'],
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const API_BASE = config.apiBase || 'https://60s.viki.moe';
|
|
41
|
+
|
|
42
|
+
logger.debug(`[60s] API 地址: ${API_BASE}`);
|
|
43
|
+
|
|
44
|
+
// ─── 通用请求 ────────────────────────────────────────────────────────────────
|
|
45
|
+
|
|
46
|
+
async function fetchApi<T = any>(
|
|
47
|
+
endpoint: string,
|
|
48
|
+
params?: Record<string, string>,
|
|
49
|
+
): Promise<T> {
|
|
50
|
+
const url = new URL(`${API_BASE}/v2${endpoint}`);
|
|
51
|
+
if (params) {
|
|
52
|
+
Object.entries(params).forEach(([k, v]) => url.searchParams.set(k, v));
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
logger.debug(`[60s] 请求: ${url.toString()}`);
|
|
56
|
+
|
|
57
|
+
const res = await fetch(url.toString());
|
|
58
|
+
const data = (await res.json()) as any;
|
|
59
|
+
|
|
60
|
+
if (data.error) throw new Error(data.error);
|
|
61
|
+
if (data.code !== undefined && data.code !== 200 && data.code !== 0) {
|
|
62
|
+
throw new Error(data.message || data.msg || `API 错误: ${data.code}`);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return data.data ?? data;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// ─── 工具函数 ────────────────────────────────────────────────────────────────
|
|
69
|
+
|
|
70
|
+
function formatList(items: any[], limit = 10): string {
|
|
71
|
+
return items
|
|
72
|
+
.slice(0, limit)
|
|
73
|
+
.map((item, i) => {
|
|
74
|
+
const title = item.title || item.name || item.word || item;
|
|
75
|
+
const hot = item.hot_value || item.hot;
|
|
76
|
+
const hotStr = hot ? ` 🔥${hot}` : '';
|
|
77
|
+
return `${i + 1}. ${title}${hotStr}`;
|
|
78
|
+
})
|
|
79
|
+
.join('\n');
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
83
|
+
// 工具定义(ZhinTool 链式风格 — 同时注册命令 + AI 工具)
|
|
84
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
85
|
+
|
|
86
|
+
// ── 60 秒新闻 ────────────────────────────────────────────────────────────────
|
|
87
|
+
const newsTool = new ZhinTool('60s_news')
|
|
88
|
+
.desc('获取每日60秒新闻,快速了解今日要闻')
|
|
89
|
+
.tag('新闻', '资讯', '60s')
|
|
90
|
+
.keyword('60s', '新闻', '今日新闻', '60秒', '每日新闻', '读懂世界')
|
|
91
|
+
.alias('新闻', '今日新闻', '60秒')
|
|
92
|
+
.usage('获取今日60秒新闻')
|
|
93
|
+
.examples('/60s')
|
|
94
|
+
.execute(async () => {
|
|
95
|
+
const data = await fetchApi<any>('/60s');
|
|
96
|
+
const lines = [`📰 今日60秒新闻 (${data.date || ''})`, ''];
|
|
97
|
+
if (data.news && Array.isArray(data.news)) {
|
|
98
|
+
lines.push(...data.news.map((n: string, i: number) => `${i + 1}. ${n}`));
|
|
99
|
+
}
|
|
100
|
+
if (data.tip) lines.push('', `💡 ${data.tip}`);
|
|
101
|
+
return lines.join('\n');
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
// ── 天气 ──────────────────────────────────────────────────────────────────────
|
|
105
|
+
const weatherTool = new ZhinTool('weather')
|
|
106
|
+
.desc('查询指定城市的当前天气信息')
|
|
107
|
+
.tag('天气', '生活', '查询')
|
|
108
|
+
.keyword('天气', '气温', '温度', '下雨', '晴天', '阴天', 'weather')
|
|
109
|
+
.alias('天气', 'tq')
|
|
110
|
+
.usage('查询城市天气')
|
|
111
|
+
.examples('/weather 成都', '/天气 北京')
|
|
112
|
+
.param('city', { type: 'string', description: '城市名称,如"成都"、"北京"' }, true)
|
|
113
|
+
.execute(async (args) => {
|
|
114
|
+
const data = await fetchApi<any>('/weather', { city: args.city });
|
|
115
|
+
const w = data.weather;
|
|
116
|
+
const aq = data.air_quality;
|
|
117
|
+
const loc = data.location;
|
|
118
|
+
const cityName = loc?.city || loc?.name || args.city;
|
|
119
|
+
const lines = [
|
|
120
|
+
`🌤️ ${cityName} 天气`,
|
|
121
|
+
'',
|
|
122
|
+
`🌡️ 温度: ${w.temperature}°C`,
|
|
123
|
+
`☁️ 天气: ${w.condition}`,
|
|
124
|
+
`💧 湿度: ${w.humidity}%`,
|
|
125
|
+
`💨 风: ${w.wind_direction} ${w.wind_power}`,
|
|
126
|
+
];
|
|
127
|
+
if (aq) {
|
|
128
|
+
const quality = aq.quality || '';
|
|
129
|
+
lines.push(`🌬️ 空气: ${quality}${aq.aqi ? ` (AQI ${aq.aqi})` : ''}`);
|
|
130
|
+
}
|
|
131
|
+
return lines.join('\n');
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
// ── 微博热搜 ──────────────────────────────────────────────────────────────────
|
|
135
|
+
const weiboTool = new ZhinTool('weibo_hot')
|
|
136
|
+
.desc('获取微博热搜榜')
|
|
137
|
+
.tag('热搜', '社交', '微博')
|
|
138
|
+
.keyword('微博', '热搜', 'weibo', 'wb')
|
|
139
|
+
.alias('微博热搜', 'wb')
|
|
140
|
+
.usage('获取微博热搜')
|
|
141
|
+
.examples('/weibo', '/weibo 20')
|
|
142
|
+
.param('limit', { type: 'number', description: '返回条数,默认10条' })
|
|
143
|
+
.execute(async (args) => {
|
|
144
|
+
const data = await fetchApi<any[]>('/weibo');
|
|
145
|
+
return ['🔥 微博热搜', '', formatList(data, args.limit || 10)].join('\n');
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
// ── 知乎热榜 ──────────────────────────────────────────────────────────────────
|
|
149
|
+
const zhihuTool = new ZhinTool('zhihu_hot')
|
|
150
|
+
.desc('获取知乎热榜')
|
|
151
|
+
.tag('热搜', '社交', '知乎')
|
|
152
|
+
.keyword('知乎', '热榜', 'zhihu', 'zh')
|
|
153
|
+
.alias('知乎热榜', 'zh')
|
|
154
|
+
.usage('获取知乎热榜')
|
|
155
|
+
.examples('/zhihu', '/zhihu 20')
|
|
156
|
+
.param('limit', { type: 'number', description: '返回条数,默认10条' })
|
|
157
|
+
.execute(async (args) => {
|
|
158
|
+
const data = await fetchApi<any[]>('/zhihu');
|
|
159
|
+
return ['🔥 知乎热榜', '', formatList(data, args.limit || 10)].join('\n');
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
// ── 抖音热搜 ──────────────────────────────────────────────────────────────────
|
|
163
|
+
const douyinTool = new ZhinTool('douyin_hot')
|
|
164
|
+
.desc('获取抖音热搜榜')
|
|
165
|
+
.tag('热搜', '短视频', '抖音')
|
|
166
|
+
.keyword('抖音', '热搜', 'douyin', 'dy')
|
|
167
|
+
.alias('抖音热搜', 'dy')
|
|
168
|
+
.usage('获取抖音热搜')
|
|
169
|
+
.examples('/douyin', '/douyin 20')
|
|
170
|
+
.param('limit', { type: 'number', description: '返回条数,默认10条' })
|
|
171
|
+
.execute(async (args) => {
|
|
172
|
+
const data = await fetchApi<any[]>('/douyin');
|
|
173
|
+
return ['🔥 抖音热搜', '', formatList(data, args.limit || 10)].join('\n');
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
// ── 头条热搜 ──────────────────────────────────────────────────────────────────
|
|
177
|
+
const toutiaoTool = new ZhinTool('toutiao_hot')
|
|
178
|
+
.desc('获取今日头条热搜榜')
|
|
179
|
+
.tag('热搜', '资讯', '头条')
|
|
180
|
+
.keyword('头条', '今日头条', '热搜', 'toutiao', 'tt')
|
|
181
|
+
.alias('头条热搜', 'tt')
|
|
182
|
+
.usage('获取头条热搜')
|
|
183
|
+
.examples('/toutiao', '/tt 20')
|
|
184
|
+
.param('limit', { type: 'number', description: '返回条数,默认10条' })
|
|
185
|
+
.execute(async (args) => {
|
|
186
|
+
const data = await fetchApi<any[]>('/toutiao');
|
|
187
|
+
return ['🔥 头条热搜', '', formatList(data, args.limit || 10)].join('\n');
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
// ── 一言 ──────────────────────────────────────────────────────────────────────
|
|
191
|
+
const hitokotoTool = new ZhinTool('hitokoto')
|
|
192
|
+
.desc('获取一言/每日一句,随机返回一条语句')
|
|
193
|
+
.tag('语录', '文学', '随机')
|
|
194
|
+
.keyword('一言', '每日一句', '语录', '名言', 'hitokoto')
|
|
195
|
+
.alias('一言', '每日一句', 'yy')
|
|
196
|
+
.usage('获取随机一言')
|
|
197
|
+
.examples('/hitokoto', '/一言 i')
|
|
198
|
+
.param('type', {
|
|
199
|
+
type: 'string',
|
|
200
|
+
description:
|
|
201
|
+
'类型:a=动画, b=漫画, c=游戏, d=文学, e=原创, f=网络, g=其他, h=影视, i=诗词, j=网易云, k=哲学, l=抖机灵',
|
|
202
|
+
})
|
|
203
|
+
.execute(async (args) => {
|
|
204
|
+
const params: Record<string, string> | undefined = args.type
|
|
205
|
+
? { c: args.type }
|
|
206
|
+
: undefined;
|
|
207
|
+
const data = await fetchApi<any>('/hitokoto', params);
|
|
208
|
+
const text = data.hitokoto || data.content || (typeof data === 'string' ? data : '');
|
|
209
|
+
const lines = ['💬 一言', '', `「${text}」`];
|
|
210
|
+
if (data.from || data.source || data.from_who || data.author) {
|
|
211
|
+
const author = data.from_who || data.author || '';
|
|
212
|
+
const source = data.from || data.source || '';
|
|
213
|
+
lines.push(`——${author}${source ? `《${source}》` : ''}`);
|
|
214
|
+
}
|
|
215
|
+
return lines.join('\n');
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
// ── 摸鱼日历 ──────────────────────────────────────────────────────────────────
|
|
219
|
+
const moyuTool = new ZhinTool('moyu')
|
|
220
|
+
.desc('获取摸鱼日历,查看今天适不适合摸鱼')
|
|
221
|
+
.tag('生活', '摸鱼', '日历')
|
|
222
|
+
.keyword('摸鱼', '摸鱼日历', 'moyu')
|
|
223
|
+
.alias('摸鱼', '摸鱼日历')
|
|
224
|
+
.usage('获取摸鱼日历')
|
|
225
|
+
.examples('/moyu')
|
|
226
|
+
.execute(async () => {
|
|
227
|
+
const data = await fetchApi<any>('/moyu');
|
|
228
|
+
if (typeof data === 'string') return `🐟 摸鱼日历\n\n${data}`;
|
|
229
|
+
const lines = ['🐟 摸鱼日历', ''];
|
|
230
|
+
if (data.date?.gregorian) lines.push(`📅 ${data.date.gregorian} ${data.date.weekday || ''}`);
|
|
231
|
+
if (data.date?.lunar) {
|
|
232
|
+
const l = data.date.lunar;
|
|
233
|
+
lines.push(`🌙 农历${l.monthCN || ''}${l.dayCN || ''} ${l.yearGanZhi || ''}年`);
|
|
234
|
+
}
|
|
235
|
+
if (data.today) {
|
|
236
|
+
const t = data.today;
|
|
237
|
+
if (t.holidayName) lines.push(`🎉 ${t.holidayName}`);
|
|
238
|
+
if (t.solarTerm) lines.push(`🌿 ${t.solarTerm}`);
|
|
239
|
+
lines.push(t.isWorkday ? '💼 今天是工作日' : '🎮 今天不上班');
|
|
240
|
+
}
|
|
241
|
+
if (data.festivals && Array.isArray(data.festivals)) {
|
|
242
|
+
data.festivals.forEach((f: any) => lines.push(`🎊 ${f.name || f}`));
|
|
243
|
+
}
|
|
244
|
+
if (data.countdown && Array.isArray(data.countdown)) {
|
|
245
|
+
lines.push('');
|
|
246
|
+
data.countdown.forEach((c: any) => {
|
|
247
|
+
if (c.name && c.days !== undefined) lines.push(`⏳ 距 ${c.name} 还有 ${c.days} 天`);
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
return lines.join('\n');
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
// ── IP 查询 ───────────────────────────────────────────────────────────────────
|
|
254
|
+
const ipTool = new ZhinTool('ip_query')
|
|
255
|
+
.desc('查询 IP 地址的地理位置信息')
|
|
256
|
+
.tag('网络', '查询', 'IP')
|
|
257
|
+
.keyword('ip', 'IP', 'IP查询', 'ip查询')
|
|
258
|
+
.alias('IP查询')
|
|
259
|
+
.usage('查询 IP 地址信息')
|
|
260
|
+
.examples('/ip', '/ip 8.8.8.8')
|
|
261
|
+
.param('ip', { type: 'string', description: 'IP 地址,不填则查询当前 IP' })
|
|
262
|
+
.execute(async (args) => {
|
|
263
|
+
const params: Record<string, string> | undefined = args.ip
|
|
264
|
+
? { ip: args.ip }
|
|
265
|
+
: undefined;
|
|
266
|
+
const data = await fetchApi<any>('/ip', params);
|
|
267
|
+
const lines = ['🌐 IP 查询', '', `IP: ${data.ip || args.ip || '当前 IP'}`];
|
|
268
|
+
if (data.country || data.region || data.city) {
|
|
269
|
+
lines.push(`位置: ${[data.country, data.region, data.city].filter(Boolean).join(' ')}`);
|
|
270
|
+
}
|
|
271
|
+
if (data.location) lines.push(`位置: ${data.location}`);
|
|
272
|
+
if (data.isp) lines.push(`运营商: ${data.isp}`);
|
|
273
|
+
return lines.join('\n');
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
// ── Bing 每日图片 ─────────────────────────────────────────────────────────────
|
|
277
|
+
const bingTool = new ZhinTool('bing_image')
|
|
278
|
+
.desc('获取 Bing 每日壁纸图片')
|
|
279
|
+
.tag('图片', '壁纸', 'Bing')
|
|
280
|
+
.keyword('bing', '必应', '壁纸', '每日壁纸')
|
|
281
|
+
.alias('必应', '每日壁纸')
|
|
282
|
+
.usage('获取 Bing 每日壁纸')
|
|
283
|
+
.examples('/bing')
|
|
284
|
+
.execute(async () => {
|
|
285
|
+
const data = await fetchApi<any>('/bing');
|
|
286
|
+
const lines = ['🖼️ Bing 每日壁纸', ''];
|
|
287
|
+
if (data.title) lines.push(`📌 ${data.title}`);
|
|
288
|
+
if (data.headline) lines.push(`💡 ${data.headline}`);
|
|
289
|
+
if (data.copyright) lines.push(`📝 ${data.copyright}`);
|
|
290
|
+
if (data.description) lines.push('', data.description);
|
|
291
|
+
const imgUrl = data.cover || data.cover_4k || data.url || data.image;
|
|
292
|
+
if (imgUrl) lines.push('', imgUrl);
|
|
293
|
+
return lines.join('\n');
|
|
294
|
+
});
|
|
295
|
+
|
|
296
|
+
// ── 金价 ──────────────────────────────────────────────────────────────────────
|
|
297
|
+
const goldPriceTool = new ZhinTool('gold_price')
|
|
298
|
+
.desc('查询今日黄金价格')
|
|
299
|
+
.tag('金融', '黄金', '价格')
|
|
300
|
+
.keyword('金价', '黄金', '黄金价格', 'gold')
|
|
301
|
+
.alias('金价', '黄金价格', 'jj')
|
|
302
|
+
.usage('查询今日金价')
|
|
303
|
+
.examples('/gold', '/金价')
|
|
304
|
+
.execute(async () => {
|
|
305
|
+
const data = await fetchApi<any>('/gold-price');
|
|
306
|
+
const lines = ['💰 今日金价', ''];
|
|
307
|
+
if (data.date) lines.push(`📅 ${data.date}`);
|
|
308
|
+
const metals = data.metals || (Array.isArray(data) ? data : []);
|
|
309
|
+
if (metals.length > 0) {
|
|
310
|
+
lines.push('');
|
|
311
|
+
metals.forEach((item: any) => {
|
|
312
|
+
const name = item.name || '黄金';
|
|
313
|
+
const price = item.today_price || item.sell_price || item.price || 'N/A';
|
|
314
|
+
const unit = item.unit || '元/克';
|
|
315
|
+
if (price !== 'N/A') lines.push(`${name}: ¥${price} ${unit}`);
|
|
316
|
+
});
|
|
317
|
+
} else if (data.price) {
|
|
318
|
+
lines.push(`当前金价: ¥${data.price}/克`);
|
|
319
|
+
}
|
|
320
|
+
return lines.join('\n');
|
|
321
|
+
});
|
|
322
|
+
|
|
323
|
+
// ── 油价 ──────────────────────────────────────────────────────────────────────
|
|
324
|
+
const fuelPriceTool = new ZhinTool('fuel_price')
|
|
325
|
+
.desc('查询今日油价')
|
|
326
|
+
.tag('生活', '油价', '价格')
|
|
327
|
+
.keyword('油价', '汽油', '柴油', 'fuel')
|
|
328
|
+
.alias('油价', 'yj')
|
|
329
|
+
.usage('查询今日油价')
|
|
330
|
+
.examples('/fuel', '/油价 四川')
|
|
331
|
+
.param('province', { type: 'string', description: '省份名称,如"四川"、"北京"' })
|
|
332
|
+
.execute(async (args) => {
|
|
333
|
+
const params: Record<string, string> | undefined = args.province
|
|
334
|
+
? { province: args.province }
|
|
335
|
+
: undefined;
|
|
336
|
+
const data = await fetchApi<any>('/fuel-price', params);
|
|
337
|
+
const lines = ['⛽ 今日油价', ''];
|
|
338
|
+
if (data.region) lines.push(`📍 ${data.region}`);
|
|
339
|
+
if (data.items && Array.isArray(data.items)) {
|
|
340
|
+
data.items.forEach((item: any) => {
|
|
341
|
+
lines.push(`${item.name}: ${item.price_desc || `¥${item.price}/升`}`);
|
|
342
|
+
});
|
|
343
|
+
}
|
|
344
|
+
if (data.trend) {
|
|
345
|
+
lines.push('', `📊 ${data.trend.description || ''}`);
|
|
346
|
+
}
|
|
347
|
+
return lines.join('\n');
|
|
348
|
+
});
|
|
349
|
+
|
|
350
|
+
// ── 汇率 ──────────────────────────────────────────────────────────────────────
|
|
351
|
+
const exchangeRateTool = new ZhinTool('exchange_rate')
|
|
352
|
+
.desc('查询货币汇率')
|
|
353
|
+
.tag('金融', '汇率', '查询')
|
|
354
|
+
.keyword('汇率', '兑换', '外汇', 'exchange', 'rate')
|
|
355
|
+
.alias('汇率', 'hl')
|
|
356
|
+
.usage('查询汇率')
|
|
357
|
+
.examples('/exchange USD CNY', '/汇率')
|
|
358
|
+
.param('from', { type: 'string', description: '源货币,如 USD, EUR, JPY' })
|
|
359
|
+
.param('to', { type: 'string', description: '目标货币,如 CNY' })
|
|
360
|
+
.execute(async (args) => {
|
|
361
|
+
const params: Record<string, string> = {};
|
|
362
|
+
if (args.from) params.from = args.from.toUpperCase();
|
|
363
|
+
if (args.to) params.to = args.to.toUpperCase();
|
|
364
|
+
const data = await fetchApi<any>(
|
|
365
|
+
'/exchange-rate',
|
|
366
|
+
Object.keys(params).length ? params : undefined,
|
|
367
|
+
);
|
|
368
|
+
const lines = ['💱 汇率查询', ''];
|
|
369
|
+
const base = data.base_code || args.from || 'CNY';
|
|
370
|
+
lines.push(`基准货币: ${base}`);
|
|
371
|
+
if (data.updated) lines.push(`更新时间: ${data.updated}`);
|
|
372
|
+
lines.push('');
|
|
373
|
+
const rates = data.rates || (Array.isArray(data) ? data : []);
|
|
374
|
+
const targetCurrencies = args.to
|
|
375
|
+
? [args.to.toUpperCase()]
|
|
376
|
+
: ['USD', 'EUR', 'JPY', 'GBP', 'HKD', 'KRW', 'AUD', 'CAD', 'SGD', 'CHF'];
|
|
377
|
+
rates.forEach((item: any) => {
|
|
378
|
+
if (targetCurrencies.includes(item.currency) && item.currency !== base) {
|
|
379
|
+
lines.push(`${base} → ${item.currency}: ${item.rate}`);
|
|
380
|
+
}
|
|
381
|
+
});
|
|
382
|
+
return lines.join('\n');
|
|
383
|
+
});
|
|
384
|
+
|
|
385
|
+
// ── 翻译 ──────────────────────────────────────────────────────────────────────
|
|
386
|
+
const translateTool = new ZhinTool('translate_60s')
|
|
387
|
+
.desc('翻译文本')
|
|
388
|
+
.tag('工具', '翻译', '语言')
|
|
389
|
+
.keyword('翻译', '英文', '中文', '日文', 'translate', '译')
|
|
390
|
+
.alias('翻译', 'fy')
|
|
391
|
+
.usage('翻译文本')
|
|
392
|
+
.examples('/fanyi hello', '/翻译 你好 en')
|
|
393
|
+
.param('text', { type: 'string', description: '要翻译的文本' }, true)
|
|
394
|
+
.param('to', { type: 'string', description: '目标语言,如 en, zh, ja' })
|
|
395
|
+
.execute(async (args) => {
|
|
396
|
+
const params: Record<string, string> = { text: args.text };
|
|
397
|
+
if (args.to) params.to = args.to;
|
|
398
|
+
const data = await fetchApi<any>('/fanyi', params);
|
|
399
|
+
const srcText = data.source?.text || args.text;
|
|
400
|
+
const srcLang = data.source?.type_desc || data.source?.type || '';
|
|
401
|
+
const tgtText = data.target?.text || data.result || data.translation || (typeof data === 'string' ? data : '');
|
|
402
|
+
const tgtLang = data.target?.type_desc || data.target?.type || '';
|
|
403
|
+
const lines = [
|
|
404
|
+
'🌐 翻译结果',
|
|
405
|
+
'',
|
|
406
|
+
`原文${srcLang ? ` (${srcLang})` : ''}: ${srcText}`,
|
|
407
|
+
`译文${tgtLang ? ` (${tgtLang})` : ''}: ${tgtText}`,
|
|
408
|
+
];
|
|
409
|
+
if (data.target?.pronounce) lines.push(`发音: ${data.target.pronounce}`);
|
|
410
|
+
return lines.join('\n');
|
|
411
|
+
});
|
|
412
|
+
|
|
413
|
+
// ── 历史上的今天 ──────────────────────────────────────────────────────────────
|
|
414
|
+
const historyTodayTool = new ZhinTool('history_today')
|
|
415
|
+
.desc('查看历史上的今天发生了什么')
|
|
416
|
+
.tag('历史', '知识', '日历')
|
|
417
|
+
.keyword('历史', '历史上的今天', '今天历史', 'history')
|
|
418
|
+
.alias('历史上的今天', '历史')
|
|
419
|
+
.usage('查看历史上的今天')
|
|
420
|
+
.examples('/history')
|
|
421
|
+
.execute(async () => {
|
|
422
|
+
const data = await fetchApi<any>('/today-in-history');
|
|
423
|
+
const dateStr = data.date || `${data.month || ''}月${data.day || ''}日`;
|
|
424
|
+
const lines = [`📅 历史上的今天 (${dateStr})`, ''];
|
|
425
|
+
const items = data.items || (Array.isArray(data) ? data : []);
|
|
426
|
+
items.slice(0, 10).forEach((item: any, i: number) => {
|
|
427
|
+
const year = item.year || '';
|
|
428
|
+
const title = item.title || item.event || item.content || item;
|
|
429
|
+
const typeIcon = item.event_type === 'birth' ? '👶' : item.event_type === 'death' ? '🕊️' : '📌';
|
|
430
|
+
lines.push(`${typeIcon} ${i + 1}. ${year ? `[${year}] ` : ''}${title}`);
|
|
431
|
+
});
|
|
432
|
+
return lines.join('\n');
|
|
433
|
+
});
|
|
434
|
+
|
|
435
|
+
// ── KFC 疯狂星期四 ────────────────────────────────────────────────────────────
|
|
436
|
+
const kfcTool = new ZhinTool('kfc')
|
|
437
|
+
.desc('获取 KFC 疯狂星期四文案')
|
|
438
|
+
.tag('娱乐', 'KFC', '文案')
|
|
439
|
+
.keyword('kfc', 'KFC', '疯狂星期四', 'v50', '肯德基')
|
|
440
|
+
.alias('疯狂星期四', 'v50')
|
|
441
|
+
.usage('获取 KFC 文案')
|
|
442
|
+
.examples('/kfc')
|
|
443
|
+
.execute(async () => {
|
|
444
|
+
const data = await fetchApi<any>('/kfc');
|
|
445
|
+
return `🍗 疯狂星期四\n\n${data.kfc || data.content || data.text || (typeof data === 'string' ? data : '')}`;
|
|
446
|
+
});
|
|
447
|
+
|
|
448
|
+
// ── 段子 ──────────────────────────────────────────────────────────────────────
|
|
449
|
+
const duanziTool = new ZhinTool('duanzi')
|
|
450
|
+
.desc('获取一个段子')
|
|
451
|
+
.tag('娱乐', '笑话', '段子')
|
|
452
|
+
.keyword('段子', '笑话', '搞笑', 'joke', 'duanzi')
|
|
453
|
+
.alias('段子', 'joke')
|
|
454
|
+
.usage('获取段子')
|
|
455
|
+
.examples('/duanzi')
|
|
456
|
+
.execute(async () => {
|
|
457
|
+
const data = await fetchApi<any>('/duanzi');
|
|
458
|
+
return `😂 段子\n\n${data.duanzi || data.content || data.text || (typeof data === 'string' ? data : '')}`;
|
|
459
|
+
});
|
|
460
|
+
|
|
461
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
462
|
+
// 注册所有工具
|
|
463
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
464
|
+
|
|
465
|
+
const allTools = [
|
|
466
|
+
newsTool,
|
|
467
|
+
weatherTool,
|
|
468
|
+
weiboTool,
|
|
469
|
+
zhihuTool,
|
|
470
|
+
douyinTool,
|
|
471
|
+
toutiaoTool,
|
|
472
|
+
hitokotoTool,
|
|
473
|
+
moyuTool,
|
|
474
|
+
ipTool,
|
|
475
|
+
bingTool,
|
|
476
|
+
goldPriceTool,
|
|
477
|
+
fuelPriceTool,
|
|
478
|
+
exchangeRateTool,
|
|
479
|
+
translateTool,
|
|
480
|
+
historyTodayTool,
|
|
481
|
+
kfcTool,
|
|
482
|
+
duanziTool,
|
|
483
|
+
];
|
|
484
|
+
|
|
485
|
+
allTools.forEach((tool) => plugin.addTool(tool.toTool()));
|
|
486
|
+
|
|
487
|
+
logger.debug(`[60s] 已注册 ${allTools.length} 个工具`);
|