koishi-plugin-stock 2.1.4 → 2.1.6
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/README.md +11 -3
- package/lib/commands/stock-commands.js +78 -8
- package/lib/index.backup.js +12 -12
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -65,12 +65,20 @@ npm install koishi-plugin-stock
|
|
|
65
65
|
|
|
66
66
|
## 更新日志
|
|
67
67
|
|
|
68
|
-
### v2.1.
|
|
68
|
+
### v2.1.6 (2026-03-02)
|
|
69
|
+
- ⚡ **性能优化**:超时时间从15秒调整为10秒
|
|
70
|
+
- 🔁 **重试机制**:添加3次重试机制,使用指数退避策略(2s/4s/8s)
|
|
71
|
+
- 🔄 **统一处理**:所有API请求使用统一的重试函数
|
|
72
|
+
- 📊 **可观测性**:增强日志记录,便于问题排查
|
|
73
|
+
|
|
74
|
+
### v2.1.5 (2026-03-02)
|
|
75
|
+
- 🚀 **性能优化**:增加API请求超时时间至15秒
|
|
76
|
+
- 🔧 **错误处理增强**:添加详细的错误类型识别和针对性提示
|
|
77
|
+
- 🔒 **安全性提升**:统一使用HTTPS协议替代HTTP
|
|
78
|
+
- 📊 **用户体验改善**:区分超时错误与其他网络错误,提供更准确的错误信息
|
|
69
79
|
- 🎉 **新增心法**:添加第58条心法 "我能怎么办,我真的我,我,我真的没招了,我"
|
|
70
80
|
- ✅ 心法总数更新为58条
|
|
71
81
|
- 📦 保持所有功能稳定运行
|
|
72
|
-
|
|
73
|
-
### v2.1.3 (2026-02-28)
|
|
74
82
|
- 🐛 **紧急修复**:修复"骑"命令图片读取问题
|
|
75
83
|
- ✅ 改为从本地images/qi.jpeg读取图片而非网络请求
|
|
76
84
|
- 🔧 增强错误日志,提供更详细的调试信息
|
|
@@ -2,6 +2,35 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.StockCommands = void 0;
|
|
4
4
|
const blacklist_1 = require("../utils/blacklist");
|
|
5
|
+
// 带重试机制的HTTP请求函数
|
|
6
|
+
async function httpRequestWithRetry(ctx, url, options, maxRetries = 3) {
|
|
7
|
+
const logger = ctx.logger('stock');
|
|
8
|
+
let lastError = new Error('Unknown error'); // 初始化错误对象
|
|
9
|
+
for (let attempt = 1; attempt <= maxRetries; attempt++) {
|
|
10
|
+
try {
|
|
11
|
+
logger.info(`第${attempt}次尝试请求: ${url}`);
|
|
12
|
+
const result = await ctx.http.get(url, {
|
|
13
|
+
...options,
|
|
14
|
+
timeout: 10000 // 设置为10秒超时
|
|
15
|
+
});
|
|
16
|
+
logger.info(`第${attempt}次请求成功`);
|
|
17
|
+
return result;
|
|
18
|
+
}
|
|
19
|
+
catch (error) {
|
|
20
|
+
lastError = error;
|
|
21
|
+
logger.warn(`第${attempt}次请求失败:`, error.message);
|
|
22
|
+
// 如果不是最后一次尝试,等待一段时间后重试
|
|
23
|
+
if (attempt < maxRetries) {
|
|
24
|
+
const delay = Math.pow(2, attempt) * 1000; // 指数退避: 2s, 4s, 8s
|
|
25
|
+
logger.info(`等待${delay}ms后进行第${attempt + 1}次重试`);
|
|
26
|
+
await new Promise(resolve => setTimeout(resolve, delay));
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
// 所有重试都失败了
|
|
31
|
+
logger.error(`所有${maxRetries}次重试都失败了`);
|
|
32
|
+
throw lastError;
|
|
33
|
+
}
|
|
5
34
|
class StockCommands {
|
|
6
35
|
static register(ctx, config) {
|
|
7
36
|
const logger = ctx.logger('stock');
|
|
@@ -12,11 +41,20 @@ class StockCommands {
|
|
|
12
41
|
return;
|
|
13
42
|
}
|
|
14
43
|
try {
|
|
15
|
-
|
|
44
|
+
// 使用带重试机制的HTTP请求
|
|
45
|
+
const responseText = await httpRequestWithRetry(ctx, 'https://stock.svip886.com/api/indexes', {
|
|
46
|
+
responseType: 'text'
|
|
47
|
+
});
|
|
16
48
|
return `📊 指数看板:\n\n${responseText}`;
|
|
17
49
|
}
|
|
18
50
|
catch (error) {
|
|
19
51
|
logger.error('获取活跃市值数据失败:', error);
|
|
52
|
+
logger.error('错误类型:', error.constructor.name);
|
|
53
|
+
logger.error('错误消息:', error.message);
|
|
54
|
+
// 提供更有帮助的错误信息
|
|
55
|
+
if (error.message && error.message.includes('timeout')) {
|
|
56
|
+
return '获取活跃市值数据超时,请检查网络连接后重试。';
|
|
57
|
+
}
|
|
20
58
|
return '获取活跃市值数据失败,请稍后重试。';
|
|
21
59
|
}
|
|
22
60
|
});
|
|
@@ -30,11 +68,19 @@ class StockCommands {
|
|
|
30
68
|
return '请输入股票代码,格式:异动 [股票代码]';
|
|
31
69
|
}
|
|
32
70
|
try {
|
|
33
|
-
|
|
71
|
+
// 使用带重试机制的HTTP请求
|
|
72
|
+
const responseText = await httpRequestWithRetry(ctx, `https://stock.svip886.com/api/analyze?code=${stockCode}`, {
|
|
73
|
+
responseType: 'text'
|
|
74
|
+
});
|
|
34
75
|
return `📈 股票 ${stockCode} 异动分析:\n\n${responseText}`;
|
|
35
76
|
}
|
|
36
77
|
catch (error) {
|
|
37
78
|
logger.error('获取股票异动数据失败:', error);
|
|
79
|
+
logger.error('错误类型:', error.constructor.name);
|
|
80
|
+
logger.error('错误消息:', error.message);
|
|
81
|
+
if (error.message && error.message.includes('timeout')) {
|
|
82
|
+
return `获取股票 ${stockCode} 异动数据超时,请检查网络连接后重试。`;
|
|
83
|
+
}
|
|
38
84
|
return `获取股票 ${stockCode} 异动数据失败,请稍后重试。`;
|
|
39
85
|
}
|
|
40
86
|
});
|
|
@@ -45,13 +91,21 @@ class StockCommands {
|
|
|
45
91
|
return;
|
|
46
92
|
}
|
|
47
93
|
try {
|
|
48
|
-
|
|
49
|
-
const
|
|
94
|
+
// 使用带重试机制的HTTP请求获取图片
|
|
95
|
+
const imageUrl = 'https://stock.svip886.com/api/limit_up.png';
|
|
96
|
+
const imageBuffer = await httpRequestWithRetry(ctx, imageUrl, {
|
|
97
|
+
responseType: 'arraybuffer'
|
|
98
|
+
});
|
|
50
99
|
const base64Image = Buffer.from(imageBuffer).toString('base64');
|
|
51
100
|
return `<img src="data:image/png;base64,${base64Image}" />`;
|
|
52
101
|
}
|
|
53
102
|
catch (error) {
|
|
54
103
|
logger.error('获取涨停看板图片失败:', error);
|
|
104
|
+
logger.error('错误类型:', error.constructor.name);
|
|
105
|
+
logger.error('错误消息:', error.message);
|
|
106
|
+
if (error.message && error.message.includes('timeout')) {
|
|
107
|
+
return '获取涨停看板图片超时,请检查网络连接后重试。';
|
|
108
|
+
}
|
|
55
109
|
return '获取涨停看板图片失败,请稍后重试。';
|
|
56
110
|
}
|
|
57
111
|
});
|
|
@@ -62,13 +116,21 @@ class StockCommands {
|
|
|
62
116
|
return;
|
|
63
117
|
}
|
|
64
118
|
try {
|
|
65
|
-
|
|
66
|
-
const
|
|
119
|
+
// 使用带重试机制的HTTP请求获取图片
|
|
120
|
+
const imageUrl = 'https://stock.svip886.com/api/limit_down.png';
|
|
121
|
+
const imageBuffer = await httpRequestWithRetry(ctx, imageUrl, {
|
|
122
|
+
responseType: 'arraybuffer'
|
|
123
|
+
});
|
|
67
124
|
const base64Image = Buffer.from(imageBuffer).toString('base64');
|
|
68
125
|
return `<img src="data:image/png;base64,${base64Image}" />`;
|
|
69
126
|
}
|
|
70
127
|
catch (error) {
|
|
71
128
|
logger.error('获取跌停看板图片失败:', error);
|
|
129
|
+
logger.error('错误类型:', error.constructor.name);
|
|
130
|
+
logger.error('错误消息:', error.message);
|
|
131
|
+
if (error.message && error.message.includes('timeout')) {
|
|
132
|
+
return '获取跌停看板图片超时,请检查网络连接后重试。';
|
|
133
|
+
}
|
|
72
134
|
return '获取跌停看板图片失败,请稍后重试。';
|
|
73
135
|
}
|
|
74
136
|
});
|
|
@@ -101,12 +163,20 @@ class StockCommands {
|
|
|
101
163
|
return `不支持的选股策略: ${strategy}\n支持的策略:N型(1)、填坑(2)、少妇(3)、突破(4)、补票(5)、少妇pro(6)`;
|
|
102
164
|
}
|
|
103
165
|
try {
|
|
104
|
-
|
|
166
|
+
// 使用带重试机制的HTTP请求
|
|
167
|
+
const responseText = await httpRequestWithRetry(ctx, `https://stock.svip886.com/api/dyq_${apiEndpoint}`, {
|
|
168
|
+
responseType: 'text'
|
|
169
|
+
});
|
|
105
170
|
return `🎯 选股结果 (${strategy}): \n\n${responseText}`;
|
|
106
171
|
}
|
|
107
172
|
catch (error) {
|
|
108
173
|
logger.error('获取选股数据失败:', error);
|
|
109
|
-
|
|
174
|
+
logger.error('错误类型:', error.constructor.name);
|
|
175
|
+
logger.error('错误消息:', error.message);
|
|
176
|
+
if (error.message && error.message.includes('timeout')) {
|
|
177
|
+
return `获取选股数据超时,请检查网络连接后重试。`;
|
|
178
|
+
}
|
|
179
|
+
return `获取选股数据失败,请稍后重试。`;
|
|
110
180
|
}
|
|
111
181
|
});
|
|
112
182
|
// 骑命令
|
package/lib/index.backup.js
CHANGED
|
@@ -136,7 +136,7 @@ function apply(ctx, config) {
|
|
|
136
136
|
// 1. 获取内容
|
|
137
137
|
if (task.content === '活跃市值') {
|
|
138
138
|
try {
|
|
139
|
-
const responseText = await ctx.http.get('
|
|
139
|
+
const responseText = await ctx.http.get('https://stock.svip886.com/api/indexes', { responseType: 'text' });
|
|
140
140
|
message = `📊 定时广播 - 指数看板:\n\n${responseText}`;
|
|
141
141
|
}
|
|
142
142
|
catch (apiErr) {
|
|
@@ -147,7 +147,7 @@ function apply(ctx, config) {
|
|
|
147
147
|
else if (task.content === '涨停看板' || task.content === '跌停看板') {
|
|
148
148
|
try {
|
|
149
149
|
const apiType = task.content === '涨停看板' ? 'limit_up' : 'limit_down';
|
|
150
|
-
const imageUrl = `
|
|
150
|
+
const imageUrl = `https://stock.svip886.com/api/${apiType}.png`;
|
|
151
151
|
const imageBuffer = await ctx.http.get(imageUrl, { responseType: 'arraybuffer' });
|
|
152
152
|
const base64Image = Buffer.from(imageBuffer).toString('base64');
|
|
153
153
|
message = `🔔 定时广播 - ${task.content}:\n<img src="data:image/png;base64,${base64Image}" />`;
|
|
@@ -417,7 +417,7 @@ function apply(ctx, config) {
|
|
|
417
417
|
try {
|
|
418
418
|
// 使用Koishi的HTTP服务发起请求获取数据
|
|
419
419
|
// 根据测试,API返回的是文本格式而非JSON
|
|
420
|
-
const responseText = await ctx.http.get('
|
|
420
|
+
const responseText = await ctx.http.get('https://stock.svip886.com/api/indexes', { responseType: 'text' });
|
|
421
421
|
// 直接返回API返回的数据
|
|
422
422
|
return `📊 指数看板:\n\n${responseText}`;
|
|
423
423
|
}
|
|
@@ -437,7 +437,7 @@ function apply(ctx, config) {
|
|
|
437
437
|
}
|
|
438
438
|
try {
|
|
439
439
|
// 使用Koishi的HTTP服务发起请求获取数据
|
|
440
|
-
const responseText = await ctx.http.get(`
|
|
440
|
+
const responseText = await ctx.http.get(`https://stock.svip886.com/api/analyze?code=${stockCode}`, { responseType: 'text' });
|
|
441
441
|
// 直接返回API返回的数据
|
|
442
442
|
return `📈 股票 ${stockCode} 异动分析:\n\n${responseText}`;
|
|
443
443
|
}
|
|
@@ -454,7 +454,7 @@ function apply(ctx, config) {
|
|
|
454
454
|
}
|
|
455
455
|
try {
|
|
456
456
|
// 使用Koishi的HTTP服务下载图片
|
|
457
|
-
const imageUrl = '
|
|
457
|
+
const imageUrl = 'https://stock.svip886.com/api/limit_up.png';
|
|
458
458
|
// 获取图片的Buffer数据
|
|
459
459
|
const imageBuffer = await ctx.http.get(imageUrl, { responseType: 'arraybuffer' });
|
|
460
460
|
// 将Buffer转换为Base64编码
|
|
@@ -475,7 +475,7 @@ function apply(ctx, config) {
|
|
|
475
475
|
}
|
|
476
476
|
try {
|
|
477
477
|
// 使用Koishi的HTTP服务下载图片
|
|
478
|
-
const imageUrl = '
|
|
478
|
+
const imageUrl = 'https://stock.svip886.com/api/limit_down.png';
|
|
479
479
|
// 获取图片的Buffer数据
|
|
480
480
|
const imageBuffer = await ctx.http.get(imageUrl, { responseType: 'arraybuffer' });
|
|
481
481
|
// 将Buffer转换为Base64编码
|
|
@@ -524,7 +524,7 @@ function apply(ctx, config) {
|
|
|
524
524
|
}
|
|
525
525
|
try {
|
|
526
526
|
// 使用Koishi的HTTP服务发起请求获取数据
|
|
527
|
-
const apiUrl = `
|
|
527
|
+
const apiUrl = `https://stock.svip886.com/api/dyq_select/${apiStrategy}`;
|
|
528
528
|
const responseText = await ctx.http.get(apiUrl, { responseType: 'text' });
|
|
529
529
|
// 直接返回API返回的数据
|
|
530
530
|
return `选股策略【${strategy}】结果:\n\n${responseText}`;
|
|
@@ -672,7 +672,7 @@ function apply(ctx, config) {
|
|
|
672
672
|
}
|
|
673
673
|
try {
|
|
674
674
|
// 使用Koishi的HTTP服务发起请求获取数据
|
|
675
|
-
const responseText = await ctx.http.get('
|
|
675
|
+
const responseText = await ctx.http.get('https://stock.svip886.com/api/indexes', { responseType: 'text' });
|
|
676
676
|
// 直接返回API返回的数据
|
|
677
677
|
return `📊 指数看板:\n\n${responseText}`;
|
|
678
678
|
}
|
|
@@ -691,7 +691,7 @@ function apply(ctx, config) {
|
|
|
691
691
|
const stockCode = match[1].trim();
|
|
692
692
|
try {
|
|
693
693
|
// 使用Koishi的HTTP服务发起请求获取数据
|
|
694
|
-
const responseText = await ctx.http.get(`
|
|
694
|
+
const responseText = await ctx.http.get(`https://stock.svip886.com/api/analyze?code=${stockCode}`, { responseType: 'text' });
|
|
695
695
|
// 直接返回API返回的数据
|
|
696
696
|
return `📈 异动分析:\n\n${responseText}`;
|
|
697
697
|
}
|
|
@@ -707,7 +707,7 @@ function apply(ctx, config) {
|
|
|
707
707
|
}
|
|
708
708
|
try {
|
|
709
709
|
// 使用Koishi的HTTP服务下载图片
|
|
710
|
-
const imageUrl = '
|
|
710
|
+
const imageUrl = 'https://stock.svip886.com/api/limit_up.png';
|
|
711
711
|
// 获取图片的Buffer数据
|
|
712
712
|
const imageBuffer = await ctx.http.get(imageUrl, { responseType: 'arraybuffer' });
|
|
713
713
|
// 将Buffer转换为Base64编码
|
|
@@ -726,7 +726,7 @@ function apply(ctx, config) {
|
|
|
726
726
|
}
|
|
727
727
|
try {
|
|
728
728
|
// 使用Koishi的HTTP服务下载图片
|
|
729
|
-
const imageUrl = '
|
|
729
|
+
const imageUrl = 'https://stock.svip886.com/api/limit_down.png';
|
|
730
730
|
// 获取图片的Buffer数据
|
|
731
731
|
const imageBuffer = await ctx.http.get(imageUrl, { responseType: 'arraybuffer' });
|
|
732
732
|
// 将Buffer转换为Base64编码
|
|
@@ -774,7 +774,7 @@ function apply(ctx, config) {
|
|
|
774
774
|
}
|
|
775
775
|
try {
|
|
776
776
|
// 使用Koishi的HTTP服务发起请求获取数据
|
|
777
|
-
const apiUrl = `
|
|
777
|
+
const apiUrl = `https://stock.svip886.com/api/dyq_select/${apiStrategy}`;
|
|
778
778
|
const responseText = await ctx.http.get(apiUrl, { responseType: 'text' });
|
|
779
779
|
// 直接返回API返回的数据
|
|
780
780
|
return `选股策略【${strategy}】结果:\n\n${responseText}`;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "koishi-plugin-stock",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.6",
|
|
4
4
|
"description": "A Koishi plugin that fetches stock data and provides market analysis, including active market cap, stock alerts, limit-up board, stock selection features, and heart method card drawing with configurable blacklists for each command.",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"typings": "lib/index.d.ts",
|