@zhin.js/plugin-60s 3.0.0 → 3.0.2

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.
Files changed (130) hide show
  1. package/agent/tools/60s_news.ts +13 -0
  2. package/agent/tools/bing_image.ts +13 -0
  3. package/agent/tools/douyin_hot.ts +13 -0
  4. package/agent/tools/duanzi.ts +13 -0
  5. package/agent/tools/exchange_rate.ts +13 -0
  6. package/agent/tools/fuel_price.ts +13 -0
  7. package/agent/tools/gold_price.ts +13 -0
  8. package/agent/tools/history_today.ts +13 -0
  9. package/agent/tools/hitokoto.ts +13 -0
  10. package/agent/tools/ip_query.ts +13 -0
  11. package/agent/tools/kfc.ts +13 -0
  12. package/agent/tools/moyu.ts +13 -0
  13. package/agent/tools/toutiao_hot.ts +13 -0
  14. package/agent/tools/translate_60s.ts +13 -0
  15. package/agent/tools/weather.ts +13 -0
  16. package/agent/tools/weibo_hot.ts +13 -0
  17. package/agent/tools/zhihu_hot.ts +13 -0
  18. package/lib/agent/tools/60s_news.js +13 -0
  19. package/lib/agent/tools/60s_news.js.map +1 -0
  20. package/lib/agent/tools/bing_image.js +13 -0
  21. package/lib/agent/tools/bing_image.js.map +1 -0
  22. package/lib/agent/tools/douyin_hot.js +13 -0
  23. package/lib/agent/tools/douyin_hot.js.map +1 -0
  24. package/lib/agent/tools/duanzi.js +13 -0
  25. package/lib/agent/tools/duanzi.js.map +1 -0
  26. package/lib/agent/tools/exchange_rate.js +13 -0
  27. package/lib/agent/tools/exchange_rate.js.map +1 -0
  28. package/lib/agent/tools/fuel_price.js +13 -0
  29. package/lib/agent/tools/fuel_price.js.map +1 -0
  30. package/lib/agent/tools/gold_price.js +13 -0
  31. package/lib/agent/tools/gold_price.js.map +1 -0
  32. package/lib/agent/tools/history_today.js +13 -0
  33. package/lib/agent/tools/history_today.js.map +1 -0
  34. package/lib/agent/tools/hitokoto.js +13 -0
  35. package/lib/agent/tools/hitokoto.js.map +1 -0
  36. package/lib/agent/tools/ip_query.js +13 -0
  37. package/lib/agent/tools/ip_query.js.map +1 -0
  38. package/lib/agent/tools/kfc.js +13 -0
  39. package/lib/agent/tools/kfc.js.map +1 -0
  40. package/lib/agent/tools/moyu.js +13 -0
  41. package/lib/agent/tools/moyu.js.map +1 -0
  42. package/lib/agent/tools/toutiao_hot.js +13 -0
  43. package/lib/agent/tools/toutiao_hot.js.map +1 -0
  44. package/lib/agent/tools/translate_60s.js +13 -0
  45. package/lib/agent/tools/translate_60s.js.map +1 -0
  46. package/lib/agent/tools/weather.js +13 -0
  47. package/lib/agent/tools/weather.js.map +1 -0
  48. package/lib/agent/tools/weibo_hot.js +13 -0
  49. package/lib/agent/tools/weibo_hot.js.map +1 -0
  50. package/lib/agent/tools/zhihu_hot.js +13 -0
  51. package/lib/agent/tools/zhihu_hot.js.map +1 -0
  52. package/lib/{index.js → src/index.js} +1 -1
  53. package/lib/src/index.js.map +1 -0
  54. package/lib/tools/60s-news/handler.js +12 -0
  55. package/lib/tools/60s-news/handler.js.map +1 -0
  56. package/lib/tools/api.js +45 -0
  57. package/lib/tools/api.js.map +1 -0
  58. package/lib/tools/bing-image/handler.js +18 -0
  59. package/lib/tools/bing-image/handler.js.map +1 -0
  60. package/lib/tools/douyin-hot/handler.js +6 -0
  61. package/lib/tools/douyin-hot/handler.js.map +1 -0
  62. package/lib/tools/duanzi/handler.js +6 -0
  63. package/lib/tools/duanzi/handler.js.map +1 -0
  64. package/lib/tools/exchange-rate/handler.js +28 -0
  65. package/lib/tools/exchange-rate/handler.js.map +1 -0
  66. package/lib/tools/fuel-price/handler.js +21 -0
  67. package/lib/tools/fuel-price/handler.js.map +1 -0
  68. package/lib/tools/gold-price/handler.js +24 -0
  69. package/lib/tools/gold-price/handler.js.map +1 -0
  70. package/lib/tools/history-today/handler.js +16 -0
  71. package/lib/tools/history-today/handler.js.map +1 -0
  72. package/lib/tools/hitokoto/handler.js +16 -0
  73. package/lib/tools/hitokoto/handler.js.map +1 -0
  74. package/lib/tools/ip-query/handler.js +17 -0
  75. package/lib/tools/ip-query/handler.js.map +1 -0
  76. package/lib/tools/kfc/handler.js +6 -0
  77. package/lib/tools/kfc/handler.js.map +1 -0
  78. package/lib/tools/moyu/handler.js +39 -0
  79. package/lib/tools/moyu/handler.js.map +1 -0
  80. package/lib/tools/toutiao-hot/handler.js +6 -0
  81. package/lib/tools/toutiao-hot/handler.js.map +1 -0
  82. package/lib/tools/translate/handler.js +26 -0
  83. package/lib/tools/translate/handler.js.map +1 -0
  84. package/lib/tools/weather/handler.js +22 -0
  85. package/lib/tools/weather/handler.js.map +1 -0
  86. package/lib/tools/weibo-hot/handler.js +6 -0
  87. package/lib/tools/weibo-hot/handler.js.map +1 -0
  88. package/lib/tools/zhihu-hot/handler.js +6 -0
  89. package/lib/tools/zhihu-hot/handler.js.map +1 -0
  90. package/package.json +19 -9
  91. package/src/index.ts +1 -1
  92. package/tools/60s-news/handler.ts +1 -1
  93. package/tools/api.ts +35 -6
  94. package/tools/bing-image/handler.ts +4 -4
  95. package/tools/douyin-hot/handler.ts +2 -2
  96. package/tools/duanzi/handler.ts +1 -1
  97. package/tools/exchange-rate/handler.ts +8 -6
  98. package/tools/fuel-price/handler.ts +5 -4
  99. package/tools/gold-price/handler.ts +8 -7
  100. package/tools/history-today/handler.ts +8 -7
  101. package/tools/hitokoto/handler.ts +1 -1
  102. package/tools/ip-query/handler.ts +1 -1
  103. package/tools/kfc/handler.ts +1 -1
  104. package/tools/moyu/handler.ts +23 -16
  105. package/tools/toutiao-hot/handler.ts +2 -2
  106. package/tools/translate/handler.ts +13 -7
  107. package/tools/weather/handler.ts +13 -13
  108. package/tools/weibo-hot/handler.ts +2 -2
  109. package/tools/zhihu-hot/handler.ts +2 -2
  110. package/lib/index.d.ts +0 -2
  111. package/lib/index.d.ts.map +0 -1
  112. package/lib/index.js.map +0 -1
  113. package/tools/60s-news/60s-news.tool.md +0 -8
  114. package/tools/bing-image/bing-image.tool.md +0 -8
  115. package/tools/douyin-hot/douyin-hot.tool.md +0 -12
  116. package/tools/duanzi/duanzi.tool.md +0 -8
  117. package/tools/exchange-rate/exchange-rate.tool.md +0 -14
  118. package/tools/fuel-price/fuel-price.tool.md +0 -11
  119. package/tools/gold-price/gold-price.tool.md +0 -8
  120. package/tools/history-today/history-today.tool.md +0 -8
  121. package/tools/hitokoto/hitokoto.tool.md +0 -12
  122. package/tools/ip-query/ip-query.tool.md +0 -12
  123. package/tools/kfc/kfc.tool.md +0 -8
  124. package/tools/moyu/moyu.tool.md +0 -8
  125. package/tools/toutiao-hot/toutiao-hot.tool.md +0 -12
  126. package/tools/translate/translate.tool.md +0 -15
  127. package/tools/weather/weather.tool.md +0 -12
  128. package/tools/weibo-hot/weibo-hot.tool.md +0 -12
  129. package/tools/zhihu-hot/zhihu-hot.tool.md +0 -12
  130. /package/{skills/60s/SKILL.md → agent/skills/60s.md} +0 -0
@@ -0,0 +1,45 @@
1
+ /**
2
+ * 60s API 共享模块 — 供 *.tool.md handler 使用
3
+ */
4
+ const API_BASE = process.env.ZHIN_60S_API || 'https://60s.viki.moe';
5
+ export async function fetchApi(endpoint, params) {
6
+ const url = new URL(`${API_BASE}/v2${endpoint}`);
7
+ if (params) {
8
+ Object.entries(params).forEach(([k, v]) => url.searchParams.set(k, v));
9
+ }
10
+ const res = await fetch(url.toString());
11
+ const data = (await res.json());
12
+ if (data.error)
13
+ throw new Error(data.error);
14
+ if (data.code !== undefined && data.code !== 200 && data.code !== 0) {
15
+ throw new Error(data.message || data.msg || `API 错误: ${data.code}`);
16
+ }
17
+ return (data.data ?? data);
18
+ }
19
+ /** Coerce nested API JSON objects for property access in handlers. */
20
+ export function asRecord(value) {
21
+ return value !== null && typeof value === 'object' && !Array.isArray(value)
22
+ ? value
23
+ : {};
24
+ }
25
+ export function asString(value) {
26
+ return value == null ? '' : String(value);
27
+ }
28
+ export function asArray(value) {
29
+ return Array.isArray(value) ? value : [];
30
+ }
31
+ export function formatList(items, limit = 10) {
32
+ return items
33
+ .slice(0, limit)
34
+ .map((item, i) => {
35
+ const obj = typeof item === 'string' ? null : item;
36
+ const title = obj
37
+ ? String(obj.title ?? obj.name ?? obj.word ?? item)
38
+ : item;
39
+ const hot = obj ? obj.hot_value ?? obj.hot : undefined;
40
+ const hotStr = hot ? ` 🔥${hot}` : '';
41
+ return `${i + 1}. ${title}${hotStr}`;
42
+ })
43
+ .join('\n');
44
+ }
45
+ //# sourceMappingURL=api.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.js","sourceRoot":"","sources":["../../tools/api.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,sBAAsB,CAAC;AAOpE,MAAM,CAAC,KAAK,UAAU,QAAQ,CAC5B,QAAgB,EAChB,MAA+B;IAE/B,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,QAAQ,MAAM,QAAQ,EAAE,CAAC,CAAC;IACjD,IAAI,MAAM,EAAE,CAAC;QACX,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IACzE,CAAC;IACD,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC;IACxC,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAM7B,CAAC;IACF,IAAI,IAAI,CAAC,KAAK;QAAE,MAAM,IAAI,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC5C,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,IAAI,IAAI,CAAC,IAAI,KAAK,GAAG,IAAI,IAAI,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;QACpE,MAAM,IAAI,KAAK,CAAC,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,GAAG,IAAI,WAAW,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;IACtE,CAAC;IACD,OAAO,CAAC,IAAI,CAAC,IAAI,IAAI,IAAI,CAAM,CAAC;AAClC,CAAC;AAED,sEAAsE;AACtE,MAAM,UAAU,QAAQ,CAAC,KAAc;IACrC,OAAO,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QACzE,CAAC,CAAE,KAAoB;QACvB,CAAC,CAAC,EAAE,CAAC;AACT,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,KAAc;IACrC,OAAO,KAAK,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC5C,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,KAAc;IACpC,OAAO,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;AAC3C,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,KAAiB,EAAE,KAAK,GAAG,EAAE;IACtD,OAAO,KAAK;SACT,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC;SACf,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE;QACf,MAAM,GAAG,GAAG,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;QACnD,MAAM,KAAK,GAAG,GAAG;YACf,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,IAAI,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,IAAI,IAAI,IAAI,CAAC;YACnD,CAAC,CAAC,IAAI,CAAC;QACT,MAAM,GAAG,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,SAAS,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC;QACvD,MAAM,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACtC,OAAO,GAAG,CAAC,GAAG,CAAC,KAAK,KAAK,GAAG,MAAM,EAAE,CAAC;IACvC,CAAC,CAAC;SACD,IAAI,CAAC,IAAI,CAAC,CAAC;AAChB,CAAC"}
@@ -0,0 +1,18 @@
1
+ import { asString, fetchApi } from '../api.js';
2
+ export default async function () {
3
+ const data = await fetchApi('/bing');
4
+ const lines = ['🖼️ Bing 每日壁纸', ''];
5
+ if (data.title)
6
+ lines.push(`📌 ${data.title}`);
7
+ if (data.headline)
8
+ lines.push(`💡 ${data.headline}`);
9
+ if (data.copyright)
10
+ lines.push(`📝 ${data.copyright}`);
11
+ if (data.description)
12
+ lines.push('', asString(data.description));
13
+ const imgUrl = data.cover || data.cover_4k || data.url || data.image;
14
+ if (imgUrl)
15
+ lines.push('', asString(imgUrl));
16
+ return lines.join('\n');
17
+ }
18
+ //# sourceMappingURL=handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handler.js","sourceRoot":"","sources":["../../../tools/bing-image/handler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAE/C,MAAM,CAAC,OAAO,CAAC,KAAK;IAClB,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,OAAO,CAAC,CAAC;IACrC,MAAM,KAAK,GAAG,CAAC,eAAe,EAAE,EAAE,CAAC,CAAC;IACpC,IAAI,IAAI,CAAC,KAAK;QAAE,KAAK,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;IAC/C,IAAI,IAAI,CAAC,QAAQ;QAAE,KAAK,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;IACrD,IAAI,IAAI,CAAC,SAAS;QAAE,KAAK,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC;IACvD,IAAI,IAAI,CAAC,WAAW;QAAE,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC;IACjE,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC;IACrE,IAAI,MAAM;QAAE,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;IAC7C,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC"}
@@ -0,0 +1,6 @@
1
+ import { fetchApi, formatList } from '../api.js';
2
+ export default async function (args) {
3
+ const data = await fetchApi('/douyin');
4
+ return ['🔥 抖音热搜', '', formatList(data, args.limit || 10)].join('\n');
5
+ }
6
+ //# sourceMappingURL=handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handler.js","sourceRoot":"","sources":["../../../tools/douyin-hot/handler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAiB,MAAM,WAAW,CAAC;AAEhE,MAAM,CAAC,OAAO,CAAC,KAAK,WAAW,IAAwB;IACrD,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAa,SAAS,CAAC,CAAC;IACnD,OAAO,CAAC,SAAS,EAAE,EAAE,EAAE,UAAU,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACxE,CAAC"}
@@ -0,0 +1,6 @@
1
+ import { fetchApi } from '../api.js';
2
+ export default async function () {
3
+ const data = await fetchApi('/duanzi');
4
+ return `😂 段子\n\n${data.duanzi || data.content || data.text || (typeof data === 'string' ? data : '')}`;
5
+ }
6
+ //# sourceMappingURL=handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handler.js","sourceRoot":"","sources":["../../../tools/duanzi/handler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAErC,MAAM,CAAC,OAAO,CAAC,KAAK;IAClB,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,SAAS,CAAC,CAAC;IACvC,OAAO,YAAY,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,IAAI,IAAI,CAAC,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;AAC1G,CAAC"}
@@ -0,0 +1,28 @@
1
+ import { asArray, asRecord, asString, fetchApi } from '../api.js';
2
+ export default async function (args) {
3
+ const params = {};
4
+ if (args.from)
5
+ params.from = args.from.toUpperCase();
6
+ if (args.to)
7
+ params.to = args.to.toUpperCase();
8
+ const data = await fetchApi('/exchange-rate', Object.keys(params).length ? params : undefined);
9
+ const lines = ['💱 汇率查询', ''];
10
+ const base = data.base_code || args.from || 'CNY';
11
+ lines.push(`基准货币: ${base}`);
12
+ if (data.updated)
13
+ lines.push(`更新时间: ${data.updated}`);
14
+ lines.push('');
15
+ const rates = asArray(data.rates);
16
+ const targetCurrencies = args.to
17
+ ? [args.to.toUpperCase()]
18
+ : ['USD', 'EUR', 'JPY', 'GBP', 'HKD', 'KRW', 'AUD', 'CAD', 'SGD', 'CHF'];
19
+ rates.forEach((item) => {
20
+ const row = asRecord(item);
21
+ const currency = asString(row.currency);
22
+ if (targetCurrencies.includes(currency) && currency !== base) {
23
+ lines.push(`${base} → ${currency}: ${row.rate}`);
24
+ }
25
+ });
26
+ return lines.join('\n');
27
+ }
28
+ //# sourceMappingURL=handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handler.js","sourceRoot":"","sources":["../../../tools/exchange-rate/handler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAElE,MAAM,CAAC,OAAO,CAAC,KAAK,WAAW,IAAoC;IACjE,MAAM,MAAM,GAA2B,EAAE,CAAC;IAC1C,IAAI,IAAI,CAAC,IAAI;QAAE,MAAM,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;IACrD,IAAI,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,GAAG,IAAI,CAAC,EAAE,CAAC,WAAW,EAAE,CAAC;IAC/C,MAAM,IAAI,GAAG,MAAM,QAAQ,CACzB,gBAAgB,EAChB,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAChD,CAAC;IACF,MAAM,KAAK,GAAG,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;IAC9B,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,IAAI,IAAI,KAAK,CAAC;IAClD,KAAK,CAAC,IAAI,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC;IAC5B,IAAI,IAAI,CAAC,OAAO;QAAE,KAAK,CAAC,IAAI,CAAC,SAAS,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;IACtD,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACf,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAClC,MAAM,gBAAgB,GAAG,IAAI,CAAC,EAAE;QAC9B,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,WAAW,EAAE,CAAC;QACzB,CAAC,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;IAC3E,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;QACrB,MAAM,GAAG,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;QAC3B,MAAM,QAAQ,GAAG,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QACxC,IAAI,gBAAgB,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,QAAQ,KAAK,IAAI,EAAE,CAAC;YAC7D,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,MAAM,QAAQ,KAAK,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;QACnD,CAAC;IACH,CAAC,CAAC,CAAC;IACH,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC"}
@@ -0,0 +1,21 @@
1
+ import { asRecord, asString, fetchApi } from '../api.js';
2
+ export default async function (args) {
3
+ const params = args.province
4
+ ? { province: args.province }
5
+ : undefined;
6
+ const data = await fetchApi('/fuel-price', params);
7
+ const lines = ['⛽ 今日油价', ''];
8
+ if (data.region)
9
+ lines.push(`📍 ${data.region}`);
10
+ if (data.items && Array.isArray(data.items)) {
11
+ data.items.forEach((item) => {
12
+ lines.push(`${item.name}: ${item.price_desc || `¥${item.price}/升`}`);
13
+ });
14
+ }
15
+ if (data.trend) {
16
+ const trend = asRecord(data.trend);
17
+ lines.push('', `📊 ${asString(trend.description)}`);
18
+ }
19
+ return lines.join('\n');
20
+ }
21
+ //# sourceMappingURL=handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handler.js","sourceRoot":"","sources":["../../../tools/fuel-price/handler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAEzD,MAAM,CAAC,OAAO,CAAC,KAAK,WAAW,IAA2B;IACxD,MAAM,MAAM,GAAuC,IAAI,CAAC,QAAQ;QAC9D,CAAC,CAAC,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE;QAC7B,CAAC,CAAC,SAAS,CAAC;IACd,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC;IACnD,MAAM,KAAK,GAAG,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;IAC7B,IAAI,IAAI,CAAC,MAAM;QAAE,KAAK,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;IACjD,IAAI,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QAC5C,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAA6B,EAAE,EAAE;YACnD,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,UAAU,IAAI,IAAI,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC;QACvE,CAAC,CAAC,CAAC;IACL,CAAC;IACD,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;QACf,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACnC,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,MAAM,QAAQ,CAAC,KAAK,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;IACtD,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC"}
@@ -0,0 +1,24 @@
1
+ import { asArray, asRecord, fetchApi } from '../api.js';
2
+ export default async function () {
3
+ const data = await fetchApi('/gold-price');
4
+ const lines = ['💰 今日金价', ''];
5
+ if (data.date)
6
+ lines.push(`📅 ${data.date}`);
7
+ const metals = asArray(data.metals);
8
+ if (metals.length > 0) {
9
+ lines.push('');
10
+ metals.forEach((item) => {
11
+ const row = asRecord(item);
12
+ const name = row.name || '黄金';
13
+ const price = row.today_price || row.sell_price || row.price || 'N/A';
14
+ const unit = row.unit || '元/克';
15
+ if (price !== 'N/A')
16
+ lines.push(`${name}: ¥${price} ${unit}`);
17
+ });
18
+ }
19
+ else if (data.price) {
20
+ lines.push(`当前金价: ¥${data.price}/克`);
21
+ }
22
+ return lines.join('\n');
23
+ }
24
+ //# sourceMappingURL=handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handler.js","sourceRoot":"","sources":["../../../tools/gold-price/handler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAExD,MAAM,CAAC,OAAO,CAAC,KAAK;IAClB,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,aAAa,CAAC,CAAC;IAC3C,MAAM,KAAK,GAAG,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;IAC9B,IAAI,IAAI,CAAC,IAAI;QAAE,KAAK,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;IAC7C,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACpC,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACtB,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACf,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;YACtB,MAAM,GAAG,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;YAC3B,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,IAAI,IAAI,CAAC;YAC9B,MAAM,KAAK,GAAG,GAAG,CAAC,WAAW,IAAI,GAAG,CAAC,UAAU,IAAI,GAAG,CAAC,KAAK,IAAI,KAAK,CAAC;YACtE,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,IAAI,KAAK,CAAC;YAC/B,IAAI,KAAK,KAAK,KAAK;gBAAE,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,MAAM,KAAK,IAAI,IAAI,EAAE,CAAC,CAAC;QAChE,CAAC,CAAC,CAAC;IACL,CAAC;SAAM,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;QACtB,KAAK,CAAC,IAAI,CAAC,UAAU,IAAI,CAAC,KAAK,IAAI,CAAC,CAAC;IACvC,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC"}
@@ -0,0 +1,16 @@
1
+ import { asArray, asRecord, fetchApi } from '../api.js';
2
+ export default async function () {
3
+ const data = await fetchApi('/today-in-history');
4
+ const dateStr = data.date || `${data.month || ''}月${data.day || ''}日`;
5
+ const lines = [`📅 历史上的今天 (${dateStr})`, ''];
6
+ const items = asArray(data.items);
7
+ items.slice(0, 10).forEach((item, i) => {
8
+ const row = asRecord(item);
9
+ const year = row.year || '';
10
+ const title = row.title || row.event || row.content || item;
11
+ const typeIcon = row.event_type === 'birth' ? '👶' : row.event_type === 'death' ? '🕊️' : '📌';
12
+ lines.push(`${typeIcon} ${i + 1}. ${year ? `[${year}] ` : ''}${title}`);
13
+ });
14
+ return lines.join('\n');
15
+ }
16
+ //# sourceMappingURL=handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handler.js","sourceRoot":"","sources":["../../../tools/history-today/handler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAExD,MAAM,CAAC,OAAO,CAAC,KAAK;IAClB,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,mBAAmB,CAAC,CAAC;IACjD,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,IAAI,GAAG,IAAI,CAAC,KAAK,IAAI,EAAE,IAAI,IAAI,CAAC,GAAG,IAAI,EAAE,GAAG,CAAC;IACtE,MAAM,KAAK,GAAG,CAAC,cAAc,OAAO,GAAG,EAAE,EAAE,CAAC,CAAC;IAC7C,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAClC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,CAAS,EAAE,EAAE;QAC7C,MAAM,GAAG,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;QAC3B,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC;QAC5B,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,IAAI,GAAG,CAAC,KAAK,IAAI,GAAG,CAAC,OAAO,IAAI,IAAI,CAAC;QAC5D,MAAM,QAAQ,GAAG,GAAG,CAAC,UAAU,KAAK,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,UAAU,KAAK,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;QAC/F,KAAK,CAAC,IAAI,CAAC,GAAG,QAAQ,IAAI,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,GAAG,KAAK,EAAE,CAAC,CAAC;IAC1E,CAAC,CAAC,CAAC;IACH,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC"}
@@ -0,0 +1,16 @@
1
+ import { fetchApi } from '../api.js';
2
+ export default async function (args) {
3
+ const params = args.type
4
+ ? { c: args.type }
5
+ : undefined;
6
+ const data = await fetchApi('/hitokoto', params);
7
+ const text = data.hitokoto || data.content || (typeof data === 'string' ? data : '');
8
+ const lines = ['💬 一言', '', `「${text}」`];
9
+ if (data.from || data.source || data.from_who || data.author) {
10
+ const author = data.from_who || data.author || '';
11
+ const source = data.from || data.source || '';
12
+ lines.push(`——${author}${source ? `《${source}》` : ''}`);
13
+ }
14
+ return lines.join('\n');
15
+ }
16
+ //# sourceMappingURL=handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handler.js","sourceRoot":"","sources":["../../../tools/hitokoto/handler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAErC,MAAM,CAAC,OAAO,CAAC,KAAK,WAAW,IAAuB;IACpD,MAAM,MAAM,GAAuC,IAAI,CAAC,IAAI;QAC1D,CAAC,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,IAAI,EAAE;QAClB,CAAC,CAAC,SAAS,CAAC;IACd,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;IACjD,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,OAAO,IAAI,CAAC,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IACrF,MAAM,KAAK,GAAG,CAAC,OAAO,EAAE,EAAE,EAAE,IAAI,IAAI,GAAG,CAAC,CAAC;IACzC,IAAI,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;QAC7D,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,MAAM,IAAI,EAAE,CAAC;QAClD,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,IAAI,EAAE,CAAC;QAC9C,KAAK,CAAC,IAAI,CAAC,KAAK,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC,IAAI,MAAM,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAC1D,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC"}
@@ -0,0 +1,17 @@
1
+ import { fetchApi } from '../api.js';
2
+ export default async function (args) {
3
+ const params = args.ip
4
+ ? { ip: args.ip }
5
+ : undefined;
6
+ const data = await fetchApi('/ip', params);
7
+ const lines = ['🌐 IP 查询', '', `IP: ${data.ip || args.ip || '当前 IP'}`];
8
+ if (data.country || data.region || data.city) {
9
+ lines.push(`位置: ${[data.country, data.region, data.city].filter(Boolean).join(' ')}`);
10
+ }
11
+ if (data.location)
12
+ lines.push(`位置: ${data.location}`);
13
+ if (data.isp)
14
+ lines.push(`运营商: ${data.isp}`);
15
+ return lines.join('\n');
16
+ }
17
+ //# sourceMappingURL=handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handler.js","sourceRoot":"","sources":["../../../tools/ip-query/handler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAErC,MAAM,CAAC,OAAO,CAAC,KAAK,WAAW,IAAqB;IAClD,MAAM,MAAM,GAAuC,IAAI,CAAC,EAAE;QACxD,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE;QACjB,CAAC,CAAC,SAAS,CAAC;IACd,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;IAC3C,MAAM,KAAK,GAAG,CAAC,UAAU,EAAE,EAAE,EAAE,OAAO,IAAI,CAAC,EAAE,IAAI,IAAI,CAAC,EAAE,IAAI,OAAO,EAAE,CAAC,CAAC;IACvE,IAAI,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;QAC7C,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IACxF,CAAC;IACD,IAAI,IAAI,CAAC,QAAQ;QAAE,KAAK,CAAC,IAAI,CAAC,OAAO,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;IACtD,IAAI,IAAI,CAAC,GAAG;QAAE,KAAK,CAAC,IAAI,CAAC,QAAQ,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;IAC7C,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC"}
@@ -0,0 +1,6 @@
1
+ import { fetchApi } from '../api.js';
2
+ export default async function () {
3
+ const data = await fetchApi('/kfc');
4
+ return `🍗 疯狂星期四\n\n${data.kfc || data.content || data.text || (typeof data === 'string' ? data : '')}`;
5
+ }
6
+ //# sourceMappingURL=handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handler.js","sourceRoot":"","sources":["../../../tools/kfc/handler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAErC,MAAM,CAAC,OAAO,CAAC,KAAK;IAClB,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC,CAAC;IACpC,OAAO,eAAe,IAAI,CAAC,GAAG,IAAI,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,IAAI,IAAI,CAAC,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;AAC1G,CAAC"}
@@ -0,0 +1,39 @@
1
+ import { asArray, asRecord, asString, fetchApi } from '../api.js';
2
+ export default async function () {
3
+ const data = await fetchApi('/moyu');
4
+ if (typeof data === 'string')
5
+ return `🐟 摸鱼日历\n\n${data}`;
6
+ const lines = ['🐟 摸鱼日历', ''];
7
+ const date = asRecord(data.date);
8
+ if (date.gregorian)
9
+ lines.push(`📅 ${date.gregorian} ${asString(date.weekday)}`);
10
+ const lunar = asRecord(date.lunar);
11
+ if (lunar.monthCN || lunar.dayCN) {
12
+ lines.push(`🌙 农历${asString(lunar.monthCN)}${asString(lunar.dayCN)} ${asString(lunar.yearGanZhi)}年`);
13
+ }
14
+ const today = asRecord(data.today);
15
+ if (today.holidayName)
16
+ lines.push(`🎉 ${today.holidayName}`);
17
+ if (today.solarTerm)
18
+ lines.push(`🌿 ${today.solarTerm}`);
19
+ if (today.isWorkday !== undefined) {
20
+ lines.push(today.isWorkday ? '💼 今天是工作日' : '🎮 今天不上班');
21
+ }
22
+ if (Array.isArray(data.festivals)) {
23
+ data.festivals.forEach((f) => {
24
+ lines.push(`🎊 ${typeof f === 'string' ? f : asString(asRecord(f).name ?? f)}`);
25
+ });
26
+ }
27
+ const countdown = asArray(data.countdown);
28
+ if (countdown.length > 0) {
29
+ lines.push('');
30
+ countdown.forEach((c) => {
31
+ const row = asRecord(c);
32
+ if (typeof row.name === 'string' && typeof row.days === 'number') {
33
+ lines.push(`⏳ 距 ${row.name} 还有 ${row.days} 天`);
34
+ }
35
+ });
36
+ }
37
+ return lines.join('\n');
38
+ }
39
+ //# sourceMappingURL=handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handler.js","sourceRoot":"","sources":["../../../tools/moyu/handler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAmB,MAAM,WAAW,CAAC;AAEnF,MAAM,CAAC,OAAO,CAAC,KAAK;IAClB,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAsB,OAAO,CAAC,CAAC;IAC1D,IAAI,OAAO,IAAI,KAAK,QAAQ;QAAE,OAAO,cAAc,IAAI,EAAE,CAAC;IAC1D,MAAM,KAAK,GAAG,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;IAC9B,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACjC,IAAI,IAAI,CAAC,SAAS;QAAE,KAAK,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,SAAS,IAAI,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IACjF,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACnC,IAAI,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;QACjC,KAAK,CAAC,IAAI,CAAC,QAAQ,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,QAAQ,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;IACvG,CAAC;IACD,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACnC,IAAI,KAAK,CAAC,WAAW;QAAE,KAAK,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC;IAC7D,IAAI,KAAK,CAAC,SAAS;QAAE,KAAK,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC;IACzD,IAAI,KAAK,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;QAClC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC;IACzD,CAAC;IACD,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;QAClC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAU,EAAE,EAAE;YACpC,KAAK,CAAC,IAAI,CAAC,MAAM,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC;QAClF,CAAC,CAAC,CAAC;IACL,CAAC;IACD,MAAM,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAC1C,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACzB,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACf,SAAS,CAAC,OAAO,CAAC,CAAC,CAAU,EAAE,EAAE;YAC/B,MAAM,GAAG,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;YACxB,IAAI,OAAO,GAAG,CAAC,IAAI,KAAK,QAAQ,IAAI,OAAO,GAAG,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBACjE,KAAK,CAAC,IAAI,CAAC,OAAO,GAAG,CAAC,IAAI,OAAO,GAAG,CAAC,IAAI,IAAI,CAAC,CAAC;YACjD,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC"}
@@ -0,0 +1,6 @@
1
+ import { fetchApi, formatList } from '../api.js';
2
+ export default async function (args) {
3
+ const data = await fetchApi('/toutiao');
4
+ return ['🔥 头条热搜', '', formatList(data, args.limit || 10)].join('\n');
5
+ }
6
+ //# sourceMappingURL=handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handler.js","sourceRoot":"","sources":["../../../tools/toutiao-hot/handler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAiB,MAAM,WAAW,CAAC;AAEhE,MAAM,CAAC,OAAO,CAAC,KAAK,WAAW,IAAwB;IACrD,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAa,UAAU,CAAC,CAAC;IACpD,OAAO,CAAC,SAAS,EAAE,EAAE,EAAE,UAAU,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACxE,CAAC"}
@@ -0,0 +1,26 @@
1
+ import { asRecord, asString, fetchApi } from '../api.js';
2
+ export default async function (args) {
3
+ const params = { text: args.text };
4
+ if (args.to)
5
+ params.to = args.to;
6
+ const data = await fetchApi('/fanyi', params);
7
+ const source = asRecord(data.source);
8
+ const target = asRecord(data.target);
9
+ const srcText = asString(source.text) || args.text;
10
+ const srcLang = asString(source.type_desc) || asString(source.type);
11
+ const tgtText = asString(target.text) ||
12
+ asString(data.result) ||
13
+ asString(data.translation) ||
14
+ (typeof data === 'string' ? data : '');
15
+ const tgtLang = asString(target.type_desc) || asString(target.type);
16
+ const lines = [
17
+ '🌐 翻译结果',
18
+ '',
19
+ `原文${srcLang ? ` (${srcLang})` : ''}: ${srcText}`,
20
+ `译文${tgtLang ? ` (${tgtLang})` : ''}: ${tgtText}`,
21
+ ];
22
+ if (target.pronounce)
23
+ lines.push(`发音: ${asString(target.pronounce)}`);
24
+ return lines.join('\n');
25
+ }
26
+ //# sourceMappingURL=handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handler.js","sourceRoot":"","sources":["../../../tools/translate/handler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAEzD,MAAM,CAAC,OAAO,CAAC,KAAK,WAAW,IAAmC;IAChE,MAAM,MAAM,GAA2B,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC;IAC3D,IAAI,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,GAAG,IAAI,CAAC,EAAE,CAAC;IACjC,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IAC9C,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACrC,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACrC,MAAM,OAAO,GAAG,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC;IACnD,MAAM,OAAO,GAAG,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACpE,MAAM,OAAO,GACX,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC;QACrB,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC;QACrB,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC;QAC1B,CAAC,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IACzC,MAAM,OAAO,GAAG,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACpE,MAAM,KAAK,GAAG;QACZ,SAAS;QACT,EAAE;QACF,KAAK,OAAO,CAAC,CAAC,CAAC,KAAK,OAAO,GAAG,CAAC,CAAC,CAAC,EAAE,KAAK,OAAO,EAAE;QACjD,KAAK,OAAO,CAAC,CAAC,CAAC,KAAK,OAAO,GAAG,CAAC,CAAC,CAAC,EAAE,KAAK,OAAO,EAAE;KAClD,CAAC;IACF,IAAI,MAAM,CAAC,SAAS;QAAE,KAAK,CAAC,IAAI,CAAC,OAAO,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;IACtE,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC"}
@@ -0,0 +1,22 @@
1
+ import { asRecord, asString, fetchApi } from '../api.js';
2
+ export default async function (args) {
3
+ const data = await fetchApi('/weather', { query: args.city });
4
+ const w = asRecord(data.weather);
5
+ const aq = asRecord(data.air_quality);
6
+ const loc = asRecord(data.location);
7
+ const cityName = asString(loc.city) || asString(loc.name) || args.city;
8
+ const lines = [
9
+ `🌤️ ${cityName} 天气`,
10
+ '',
11
+ `🌡️ 温度: ${asString(w.temperature)}°C`,
12
+ `☁️ 天气: ${asString(w.condition)}`,
13
+ `💧 湿度: ${asString(w.humidity)}%`,
14
+ `💨 风: ${asString(w.wind_direction)} ${asString(w.wind_power)}`,
15
+ ];
16
+ if (Object.keys(aq).length > 0) {
17
+ const quality = asString(aq.quality);
18
+ lines.push(`🌬️ 空气: ${quality}${aq.aqi ? ` (AQI ${asString(aq.aqi)})` : ''}`);
19
+ }
20
+ return lines.join('\n');
21
+ }
22
+ //# sourceMappingURL=handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handler.js","sourceRoot":"","sources":["../../../tools/weather/handler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAEzD,MAAM,CAAC,OAAO,CAAC,KAAK,WAAW,IAAsB;IACnD,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,UAAU,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;IAC9D,MAAM,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACjC,MAAM,EAAE,GAAG,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IACtC,MAAM,GAAG,GAAG,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACpC,MAAM,QAAQ,GAAG,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC;IACvE,MAAM,KAAK,GAAG;QACZ,OAAO,QAAQ,KAAK;QACpB,EAAE;QACF,WAAW,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC,IAAI;QACtC,UAAU,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,EAAE;QACjC,UAAU,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG;QACjC,SAAS,QAAQ,CAAC,CAAC,CAAC,cAAc,CAAC,IAAI,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,EAAE;KAChE,CAAC;IACF,IAAI,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC/B,MAAM,OAAO,GAAG,QAAQ,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC;QACrC,KAAK,CAAC,IAAI,CAAC,WAAW,OAAO,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,QAAQ,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAChF,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC"}
@@ -0,0 +1,6 @@
1
+ import { fetchApi, formatList } from '../api.js';
2
+ export default async function (args) {
3
+ const data = await fetchApi('/weibo');
4
+ return ['🔥 微博热搜', '', formatList(data, args.limit || 10)].join('\n');
5
+ }
6
+ //# sourceMappingURL=handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handler.js","sourceRoot":"","sources":["../../../tools/weibo-hot/handler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAiB,MAAM,WAAW,CAAC;AAEhE,MAAM,CAAC,OAAO,CAAC,KAAK,WAAW,IAAwB;IACrD,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAa,QAAQ,CAAC,CAAC;IAClD,OAAO,CAAC,SAAS,EAAE,EAAE,EAAE,UAAU,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACxE,CAAC"}
@@ -0,0 +1,6 @@
1
+ import { fetchApi, formatList } from '../api.js';
2
+ export default async function (args) {
3
+ const data = await fetchApi('/zhihu');
4
+ return ['🔥 知乎热榜', '', formatList(data, args.limit || 10)].join('\n');
5
+ }
6
+ //# sourceMappingURL=handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handler.js","sourceRoot":"","sources":["../../../tools/zhihu-hot/handler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAiB,MAAM,WAAW,CAAC;AAEhE,MAAM,CAAC,OAAO,CAAC,KAAK,WAAW,IAAwB;IACrD,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAa,QAAQ,CAAC,CAAC;IAClD,OAAO,CAAC,SAAS,EAAE,EAAE,EAAE,UAAU,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACxE,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zhin.js/plugin-60s",
3
- "version": "3.0.0",
3
+ "version": "3.0.2",
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",
@@ -16,9 +16,7 @@
16
16
  "files": [
17
17
  "src",
18
18
  "lib",
19
- "client",
20
- "dist",
21
- "skills",
19
+ "agent",
22
20
  "tools",
23
21
  "plugin.yml",
24
22
  "README.md"
@@ -45,13 +43,16 @@
45
43
  "url": "https://github.com/lc-cn"
46
44
  },
47
45
  "license": "MIT",
48
- "dependencies": {},
49
46
  "devDependencies": {
50
47
  "typescript": "^6.0.3",
51
- "zhin.js": "4.1.0"
48
+ "zod": "^4.4.3",
49
+ "zhin.js": "4.1.2",
50
+ "@zhin.js/agent": "1.0.3"
52
51
  },
53
52
  "peerDependencies": {
54
- "zhin.js": "4.1.0"
53
+ "zod": "^4.0.0",
54
+ "zhin.js": "4.1.2",
55
+ "@zhin.js/agent": "1.0.3"
55
56
  },
56
57
  "repository": {
57
58
  "type": "git",
@@ -62,8 +63,17 @@
62
63
  "access": "public",
63
64
  "registry": "https://registry.npmjs.org"
64
65
  },
66
+ "peerDependenciesMeta": {
67
+ "@zhin.js/agent": {
68
+ "optional": true
69
+ },
70
+ "zod": {
71
+ "optional": true
72
+ }
73
+ },
65
74
  "scripts": {
66
- "build": "tsc --build",
67
- "clean": "rimraf lib"
75
+ "build": "tsc",
76
+ "clean": "rimraf lib",
77
+ "test": "sh -c 'cd ../../.. && vitest run plugins/utils/60s/tests'"
68
78
  }
69
79
  }
package/src/index.ts CHANGED
@@ -24,7 +24,7 @@
24
24
  import { usePlugin } from 'zhin.js';
25
25
 
26
26
  const plugin = usePlugin();
27
- const { logger, root } = plugin;
27
+ const { root } = plugin;
28
28
 
29
29
  // ─── 配置 ────────────────────────────────────────────────────────────────────
30
30
 
@@ -1,7 +1,7 @@
1
1
  import { fetchApi } from '../api.js';
2
2
 
3
3
  export default async function () {
4
- const data = await fetchApi<any>('/60s');
4
+ const data = await fetchApi('/60s');
5
5
  const lines = [`📰 今日60秒新闻 (${data.date || ''})`, ''];
6
6
  if (data.news && Array.isArray(data.news)) {
7
7
  lines.push(...data.news.map((n: string, i: number) => `${i + 1}. ${n}`));
package/tools/api.ts CHANGED
@@ -4,7 +4,12 @@
4
4
 
5
5
  const API_BASE = process.env.ZHIN_60S_API || 'https://60s.viki.moe';
6
6
 
7
- export async function fetchApi<T = any>(
7
+ export type ListItem = string | Record<string, unknown>;
8
+
9
+ /** Untyped 60s API JSON payload (handlers narrow fields at runtime). */
10
+ export type ApiPayload = Record<string, unknown>;
11
+
12
+ export async function fetchApi<T = ApiPayload>(
8
13
  endpoint: string,
9
14
  params?: Record<string, string>,
10
15
  ): Promise<T> {
@@ -13,20 +18,44 @@ export async function fetchApi<T = any>(
13
18
  Object.entries(params).forEach(([k, v]) => url.searchParams.set(k, v));
14
19
  }
15
20
  const res = await fetch(url.toString());
16
- const data = (await res.json()) as any;
21
+ const data = (await res.json()) as {
22
+ error?: string;
23
+ code?: number;
24
+ message?: string;
25
+ msg?: string;
26
+ data?: T;
27
+ };
17
28
  if (data.error) throw new Error(data.error);
18
29
  if (data.code !== undefined && data.code !== 200 && data.code !== 0) {
19
30
  throw new Error(data.message || data.msg || `API 错误: ${data.code}`);
20
31
  }
21
- return data.data ?? data;
32
+ return (data.data ?? data) as T;
33
+ }
34
+
35
+ /** Coerce nested API JSON objects for property access in handlers. */
36
+ export function asRecord(value: unknown): ApiPayload {
37
+ return value !== null && typeof value === 'object' && !Array.isArray(value)
38
+ ? (value as ApiPayload)
39
+ : {};
40
+ }
41
+
42
+ export function asString(value: unknown): string {
43
+ return value == null ? '' : String(value);
44
+ }
45
+
46
+ export function asArray(value: unknown): unknown[] {
47
+ return Array.isArray(value) ? value : [];
22
48
  }
23
49
 
24
- export function formatList(items: any[], limit = 10): string {
50
+ export function formatList(items: ListItem[], limit = 10): string {
25
51
  return items
26
52
  .slice(0, limit)
27
53
  .map((item, i) => {
28
- const title = item.title || item.name || item.word || item;
29
- const hot = item.hot_value || item.hot;
54
+ const obj = typeof item === 'string' ? null : item;
55
+ const title = obj
56
+ ? String(obj.title ?? obj.name ?? obj.word ?? item)
57
+ : item;
58
+ const hot = obj ? obj.hot_value ?? obj.hot : undefined;
30
59
  const hotStr = hot ? ` 🔥${hot}` : '';
31
60
  return `${i + 1}. ${title}${hotStr}`;
32
61
  })
@@ -1,13 +1,13 @@
1
- import { fetchApi } from '../api.js';
1
+ import { asString, fetchApi } from '../api.js';
2
2
 
3
3
  export default async function () {
4
- const data = await fetchApi<any>('/bing');
4
+ const data = await fetchApi('/bing');
5
5
  const lines = ['🖼️ Bing 每日壁纸', ''];
6
6
  if (data.title) lines.push(`📌 ${data.title}`);
7
7
  if (data.headline) lines.push(`💡 ${data.headline}`);
8
8
  if (data.copyright) lines.push(`📝 ${data.copyright}`);
9
- if (data.description) lines.push('', data.description);
9
+ if (data.description) lines.push('', asString(data.description));
10
10
  const imgUrl = data.cover || data.cover_4k || data.url || data.image;
11
- if (imgUrl) lines.push('', imgUrl);
11
+ if (imgUrl) lines.push('', asString(imgUrl));
12
12
  return lines.join('\n');
13
13
  }
@@ -1,6 +1,6 @@
1
- import { fetchApi, formatList } from '../api.js';
1
+ import { fetchApi, formatList, type ListItem } from '../api.js';
2
2
 
3
3
  export default async function (args: { limit?: number }) {
4
- const data = await fetchApi<any[]>('/douyin');
4
+ const data = await fetchApi<ListItem[]>('/douyin');
5
5
  return ['🔥 抖音热搜', '', formatList(data, args.limit || 10)].join('\n');
6
6
  }
@@ -1,6 +1,6 @@
1
1
  import { fetchApi } from '../api.js';
2
2
 
3
3
  export default async function () {
4
- const data = await fetchApi<any>('/duanzi');
4
+ const data = await fetchApi('/duanzi');
5
5
  return `😂 段子\n\n${data.duanzi || data.content || data.text || (typeof data === 'string' ? data : '')}`;
6
6
  }