koishi-plugin-wordpress-notifier 2.9.1 → 2.9.4

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/commands.js CHANGED
@@ -1,98 +1,74 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.CommandService = void 0;
4
- // 简化实现,避免继承 Service 类的问题
4
+ // WordPress 推送插件命令系统 - 全新设计
5
5
  class CommandService {
6
- constructor(ctx, config, wordpressService, storageService) {
6
+ constructor(ctx, config, wordpressService, storageService, scheduleService) {
7
7
  this.ctx = ctx;
8
8
  this.config = config;
9
9
  this.wordpressService = wordpressService;
10
10
  this.storageService = storageService;
11
+ this.scheduleService = scheduleService;
12
+ // 添加调试:确认服务已注入
13
+ if (!this.scheduleService) {
14
+ this.ctx.logger.error('致命错误: ScheduleService 未注入!');
15
+ }
16
+ else {
17
+ this.ctx.logger.info('CommandService 初始化成功,ScheduleService 已就绪');
18
+ }
11
19
  this.initCommands();
12
20
  }
21
+ // 检查用户是否为超级管理员
22
+ isSuperAdmin(userId) {
23
+ return this.config.superAdminUserIds?.includes(userId) || false;
24
+ }
25
+ // 检查用户是否为管理员(超级管理员或拥有足够权限)
26
+ isAdmin(session) {
27
+ const userId = session?.userId;
28
+ if (!userId)
29
+ return false;
30
+ // 优先检查超级管理员
31
+ if (this.isSuperAdmin(userId)) {
32
+ return true;
33
+ }
34
+ // 然后检查权限等级
35
+ return session?.user?.authority >= 3;
36
+ }
13
37
  initCommands() {
14
- // 创建父命令
15
- const wordpressParent = this.ctx.command('wordpress', 'WordPress 推送插件主命令');
16
- const wpParent = this.ctx.command('wp', 'WordPress 推送插件主命令(简写)');
17
- // 查询最新文章
18
- wordpressParent
19
- .subcommand('.最新 [count]', '查询 WordPress 最新文章')
20
- .alias('.latest')
21
- .action(async ({ session }, count) => {
38
+ // 直接注册所有命令为独立命令,使用 wp-xxx 格式
39
+ // 查看最新文章
40
+ this.ctx.command('wp-news [count]', '查看最新文章 (默认5篇)')
41
+ .action(async (argv, count) => {
22
42
  try {
23
- // 发送加载提示
24
- if (session) {
25
- await session.send('🔍 正在查询最新文章...');
26
- }
27
- const articleCount = Math.min(parseInt(count || '5') || 5, 20); // 限制最多20篇
28
- // 使用真实的 WordPress API 获取最新文章
43
+ const articleCount = Math.min(parseInt(count || '5') || 5, 20);
29
44
  const articles = await this.wordpressService.getLatestPosts(articleCount);
30
45
  if (!articles || articles.length === 0) {
31
- return '暂无最新文章';
46
+ return '📭 暂无最新文章';
32
47
  }
33
- let message = '📰 最新文章列表\n\n';
48
+ let message = '📰 最新文章\n\n';
34
49
  articles.forEach((article, index) => {
35
50
  const title = article.title?.rendered || '无标题';
36
51
  const date = new Date(article.date).toLocaleDateString('zh-CN');
37
52
  const link = article.link || this.config.wordpressUrl;
38
53
  const author = article.author_name || '未知作者';
39
- message += `${index + 1}. ${title}\n作者:${author}\n发布时间:${date}\n链接:${link}\n\n`;
54
+ message += `${index + 1}. ${title}\n👤 ${author} | 📅 ${date}\n🔗 ${link}\n\n`;
40
55
  });
41
56
  return message;
42
57
  }
43
58
  catch (error) {
44
- this.ctx.logger.error('Failed to get latest posts:', error);
45
- return '获取最新文章失败';
59
+ this.ctx.logger.error('获取最新文章失败:', error);
60
+ return `❌ 获取最新文章失败:${error instanceof Error ? error.message : '未知错误'}`;
46
61
  }
47
62
  });
48
- wpParent
49
- .subcommand('.latest [count]', '查询 WordPress 最新文章')
50
- .alias('.最新')
51
- .action(async ({ session }, count) => {
63
+ // 浏览文章列表
64
+ this.ctx.command('wp-list [page]', '浏览文章列表 (每页10篇)')
65
+ .action(async (argv, page) => {
52
66
  try {
53
- // 发送加载提示
54
- if (session) {
55
- await session.send('🔍 正在查询最新文章...');
56
- }
57
- const articleCount = Math.min(parseInt(count || '5') || 5, 20); // 限制最多20篇
58
- // 使用真实的 WordPress API 获取最新文章
59
- const articles = await this.wordpressService.getLatestPosts(articleCount);
60
- if (!articles || articles.length === 0) {
61
- return '暂无最新文章';
62
- }
63
- let message = '📰 最新文章列表\n\n';
64
- articles.forEach((article, index) => {
65
- const title = article.title?.rendered || '无标题';
66
- const date = new Date(article.date).toLocaleDateString('zh-CN');
67
- const link = article.link || this.config.wordpressUrl;
68
- const author = article.author_name || '未知作者';
69
- message += `${index + 1}. ${title}\n作者:${author}\n发布时间:${date}\n链接:${link}\n\n`;
70
- });
71
- return message;
72
- }
73
- catch (error) {
74
- this.ctx.logger.error('Failed to get latest posts:', error);
75
- return '获取最新文章失败';
76
- }
77
- });
78
- // 查询文章列表
79
- wordpressParent
80
- .subcommand('.列表 [page] [perPage]', '查询 WordPress 文章列表')
81
- .alias('.list')
82
- .action(async ({ session }, page, perPage) => {
83
- try {
84
- // 发送加载提示
85
- if (session) {
86
- await session.send('🔍 正在查询文章列表...');
87
- }
88
- // 验证分页参数
89
67
  const pageNum = Math.max(1, parseInt(page || '1') || 1);
90
- const perPageNum = Math.min(20, Math.max(1, parseInt(perPage || '10') || 10)); // 限制每页最多20条
91
- // 使用真实的 WordPress API 获取文章列表
92
- // 注意:WordPress REST API 默认从第1页开始,这里直接使用 pageNum
93
- const articles = await this.wordpressService.getLatestPosts(perPageNum);
68
+ const perPage = 10;
69
+ const articles = await this.wordpressService.getLatestPosts(perPage, pageNum);
94
70
  if (!articles || articles.length === 0) {
95
- return '暂无文章';
71
+ return '📭 暂无文章';
96
72
  }
97
73
  let message = `📋 文章列表 (第 ${pageNum} 页)\n\n`;
98
74
  articles.forEach((article, index) => {
@@ -100,146 +76,65 @@ class CommandService {
100
76
  const date = new Date(article.date).toLocaleDateString('zh-CN');
101
77
  const link = article.link || this.config.wordpressUrl;
102
78
  const author = article.author_name || '未知作者';
103
- message += `${index + 1}. ${title}\n作者:${author}\n发布时间:${date}\n链接:${link}\n\n`;
79
+ message += `${index + 1}. ${title}\n👤 ${author} | 📅 ${date}\n🔗 ${link}\n\n`;
104
80
  });
105
81
  return message;
106
82
  }
107
83
  catch (error) {
108
- this.ctx.logger.error('Failed to get posts:', error);
109
- return '获取文章列表失败';
110
- }
111
- });
112
- wpParent
113
- .subcommand('.list [page] [perPage]', '查询 WordPress 文章列表')
114
- .alias('.列表')
115
- .action(async ({ session }, page, perPage) => {
116
- try {
117
- // 发送加载提示
118
- if (session) {
119
- await session.send('🔍 正在查询文章列表...');
120
- }
121
- // 验证分页参数
122
- const pageNum = Math.max(1, parseInt(page || '1') || 1);
123
- const perPageNum = Math.min(20, Math.max(1, parseInt(perPage || '10') || 10)); // 限制每页最多20条
124
- // 使用真实的 WordPress API 获取文章列表
125
- // 注意:WordPress REST API 默认从第1页开始,这里直接使用 pageNum
126
- const articles = await this.wordpressService.getLatestPosts(perPageNum);
127
- if (!articles || articles.length === 0) {
128
- return '暂无文章';
129
- }
130
- let message = `📋 文章列表 (第 ${pageNum} 页)\n\n`;
131
- articles.forEach((article, index) => {
132
- const title = article.title?.rendered || '无标题';
133
- const date = new Date(article.date).toLocaleDateString('zh-CN');
134
- const link = article.link || this.config.wordpressUrl;
135
- const author = article.author_name || '未知作者';
136
- message += `${index + 1}. ${title}\n作者:${author}\n发布时间:${date}\n链接:${link}\n\n`;
137
- });
138
- return message;
139
- }
140
- catch (error) {
141
- this.ctx.logger.error('Failed to get posts:', error);
142
- return '获取文章列表失败';
143
- }
144
- });
145
- // 查询单篇文章
146
- wordpressParent
147
- .subcommand('.文章 <id>', '查询指定 WordPress 文章')
148
- .alias('.article')
149
- .action(async ({ session }, id) => {
150
- try {
151
- // 验证 ID 参数
152
- const articleId = parseInt(id);
153
- if (isNaN(articleId) || articleId <= 0) {
154
- return '请输入有效的文章 ID(必须是正整数)';
155
- }
156
- // 发送加载提示
157
- if (session) {
158
- await session.send(`🔍 正在查询文章 ID: ${articleId}...`);
159
- }
160
- // 使用真实的 WordPress API 获取文章详情
161
- const article = await this.wordpressService.getPostById(articleId);
162
- if (!article) {
163
- return '文章不存在';
164
- }
165
- const title = article.title?.rendered || '无标题';
166
- const author = article.author_name || '未知作者';
167
- const date = new Date(article.date).toLocaleString('zh-CN');
168
- const content = article.content?.rendered || '无内容';
169
- const link = article.link || this.config.wordpressUrl;
170
- // 移除 HTML 标签并截断内容
171
- const plainContent = content.replace(/<[^>]+>/g, '').trim();
172
- const displayContent = plainContent.length > 500 ? plainContent.substring(0, 500) + '...' : plainContent;
173
- return `📄 文章详情\n\n标题:${title}\n作者:${author}\n发布时间:${date}\n\n内容:${displayContent}\n\n阅读全文:${link}`;
174
- }
175
- catch (error) {
176
- this.ctx.logger.error(`Failed to get post ${id}:`, error);
177
- return '获取文章详情失败';
84
+ this.ctx.logger.error('获取文章列表失败:', error);
85
+ return `❌ 获取文章列表失败:${error instanceof Error ? error.message : '未知错误'}`;
178
86
  }
179
87
  });
180
- wpParent
181
- .subcommand('.article <id>', '查询指定 WordPress 文章')
182
- .alias('.文章')
183
- .action(async ({ session }, id) => {
88
+ // 查看文章详情
89
+ this.ctx.command('wp-post <id>', '查看指定文章详情')
90
+ .action(async (argv, id) => {
184
91
  try {
185
- // 验证 ID 参数
186
92
  const articleId = parseInt(id);
187
93
  if (isNaN(articleId) || articleId <= 0) {
188
- return '请输入有效的文章 ID(必须是正整数)';
94
+ return '请输入有效的文章 ID';
189
95
  }
190
- // 发送加载提示
191
- if (session) {
192
- await session.send(`🔍 正在查询文章 ID: ${articleId}...`);
193
- }
194
- // 使用真实的 WordPress API 获取文章详情
195
96
  const article = await this.wordpressService.getPostById(articleId);
196
97
  if (!article) {
197
- return '文章不存在';
98
+ return '📭 文章不存在';
198
99
  }
199
100
  const title = article.title?.rendered || '无标题';
200
101
  const author = article.author_name || '未知作者';
201
102
  const date = new Date(article.date).toLocaleString('zh-CN');
202
103
  const content = article.content?.rendered || '无内容';
203
104
  const link = article.link || this.config.wordpressUrl;
204
- // 移除 HTML 标签并截断内容
205
105
  const plainContent = content.replace(/<[^>]+>/g, '').trim();
206
106
  const displayContent = plainContent.length > 500 ? plainContent.substring(0, 500) + '...' : plainContent;
207
- return `📄 文章详情\n\n标题:${title}\n作者:${author}\n发布时间:${date}\n\n内容:${displayContent}\n\n阅读全文:${link}`;
107
+ return `📄 文章详情\n\n` +
108
+ `🎯 标题:${title}\n` +
109
+ `👤 作者:${author}\n` +
110
+ `📅 时间:${date}\n\n` +
111
+ `📝 内容:${displayContent}\n\n` +
112
+ `🔗 阅读全文:${link}`;
208
113
  }
209
114
  catch (error) {
210
- this.ctx.logger.error(`Failed to get post ${id}:`, error);
211
- return '获取文章详情失败';
115
+ this.ctx.logger.error(`获取文章详情失败:`, error);
116
+ return `❌ 获取文章详情失败:${error instanceof Error ? error.message : '未知错误'}`;
212
117
  }
213
118
  });
214
- // 推送开关控制
215
- wordpressParent
216
- .subcommand('.开关 [status]', '控制 WordPress 推送开关')
217
- .alias('.toggle')
119
+ // 控制推送开关(管理员)
120
+ this.ctx.command('wp-push [status]', '控制群推送开关 (仅管理员)')
218
121
  .userFields(['authority'])
219
- .action(async ({ session }, status) => {
122
+ .action(async (argv, status) => {
220
123
  try {
221
- // 检查权限:需要管理员权限
222
- if (!session?.user?.authority || session.user.authority < 3) {
223
- return '权限不足,需要管理员权限才能执行此操作';
224
- }
225
- if (!session.channelId) {
226
- return '请在群聊中使用此命令';
124
+ const session = argv.session;
125
+ if (!this.isAdmin(session)) {
126
+ return '❌ 权限不足,需要管理员权限';
227
127
  }
228
- const groupId = session.channelId;
229
- // 获取当前状态
128
+ const groupId = session.channelId || 'global';
230
129
  const pushConfig = await this.storageService.getPushConfig(groupId);
231
130
  const currentStatus = pushConfig?.enabled || false;
232
- // 如果没有指定状态,返回当前状态
233
131
  if (!status) {
234
- return `当前推送开关状态:${currentStatus ? '开启' : '关闭'}`;
132
+ return `📡 当前推送状态:${currentStatus ? '开启' : '关闭'}`;
235
133
  }
236
- // 计算新状态
237
134
  const newStatus = status === 'on' ? true : status === 'off' ? false : !currentStatus;
238
- // 如果状态没有变化,返回提示
239
135
  if (newStatus === currentStatus) {
240
- return `推送开关状态未变化,当前状态:${currentStatus ? '开启' : '关闭'}`;
136
+ return `📡 推送状态未变化:${currentStatus ? '开启' : '关闭'}`;
241
137
  }
242
- // 更新存储中的状态
243
138
  await this.storageService.setPushConfig({
244
139
  groupId,
245
140
  enabled: newStatus,
@@ -247,144 +142,183 @@ class CommandService {
247
142
  enableAtAll: pushConfig?.enableAtAll || false,
248
143
  lastPushTime: new Date()
249
144
  });
250
- return `推送开关已${newStatus ? '开启' : '关闭'}`;
145
+ return `📡 推送开关已${newStatus ? '开启' : '关闭'}`;
251
146
  }
252
147
  catch (error) {
253
- this.ctx.logger.error('Failed to toggle push:', error);
254
- return '操作失败';
148
+ this.ctx.logger.error('控制推送开关失败:', error);
149
+ return `❌ 操作失败:${error instanceof Error ? error.message : '未知错误'}`;
255
150
  }
256
151
  });
257
- wpParent
258
- .subcommand('.toggle [status]', '控制 WordPress 推送开关')
259
- .alias('.开关')
260
- .userFields(['authority'])
261
- .action(async ({ session }, status) => {
152
+ // 管理个人订阅
153
+ this.ctx.command('wp-sub [status]', '管理个人推送订阅')
154
+ .action(async (argv, status) => {
262
155
  try {
263
- // 检查权限:需要管理员权限
264
- if (!session?.user?.authority || session.user.authority < 3) {
265
- return '权限不足,需要管理员权限才能执行此操作';
266
- }
267
- if (!session.channelId) {
268
- return '请在群聊中使用此命令';
156
+ const session = argv.session;
157
+ if (!session?.userId) {
158
+ return '❌ 请在私聊或群聊中使用此命令';
269
159
  }
270
- const groupId = session.channelId;
271
- // 获取当前状态
272
- const pushConfig = await this.storageService.getPushConfig(groupId);
273
- const currentStatus = pushConfig?.enabled || false;
274
- // 如果没有指定状态,返回当前状态
160
+ const userId = session.userId;
161
+ const groupId = session.channelId || 'private';
162
+ const currentStatus = await this.storageService.isUserSubscribed(userId, groupId);
275
163
  if (!status) {
276
- return `当前推送开关状态:${currentStatus ? '开启' : '关闭'}`;
164
+ return `🔔 当前订阅状态:${currentStatus ? '开启' : '关闭'}`;
277
165
  }
278
- // 计算新状态
279
166
  const newStatus = status === 'on' ? true : status === 'off' ? false : !currentStatus;
280
- // 如果状态没有变化,返回提示
281
167
  if (newStatus === currentStatus) {
282
- return `推送开关状态未变化,当前状态:${currentStatus ? '开启' : '关闭'}`;
168
+ return `🔔 订阅状态未变化:${currentStatus ? '开启' : '关闭'}`;
283
169
  }
284
- // 更新存储中的状态
285
- await this.storageService.setPushConfig({
286
- groupId,
287
- enabled: newStatus,
288
- enableUpdatePush: pushConfig?.enableUpdatePush || true,
289
- enableAtAll: pushConfig?.enableAtAll || false,
290
- lastPushTime: new Date()
291
- });
292
- return `推送开关已${newStatus ? '开启' : '关闭'}`;
170
+ await this.storageService.setUserSubscription(userId, groupId, newStatus);
171
+ return `🔔 订阅状态已${newStatus ? '开启' : '关闭'}`;
293
172
  }
294
173
  catch (error) {
295
- this.ctx.logger.error('Failed to toggle push:', error);
296
- return '操作失败';
174
+ this.ctx.logger.error('管理订阅失败:', error);
175
+ return `❌ 操作失败:${error instanceof Error ? error.message : '未知错误'}`;
297
176
  }
298
177
  });
299
- // 订阅管理
300
- wordpressParent
301
- .subcommand('.订阅 [status]', '管理 WordPress 推送订阅')
302
- .alias('.subscribe')
303
- .action(async ({ session }, status) => {
178
+ // 手动检查推送(管理员)
179
+ this.ctx.command('wp-check', '手动触发一次推送检查 (仅管理员)')
180
+ .userFields(['authority'])
181
+ .action(async (argv) => {
304
182
  try {
305
- if (!session?.userId) {
306
- return '请在私聊或群聊中使用此命令';
307
- }
308
- const userId = session.userId;
309
- const groupId = session.channelId || 'private';
310
- // 获取当前订阅状态
311
- const currentStatus = await this.storageService.isUserSubscribed(userId, groupId);
312
- // 如果没有指定状态,返回当前订阅状态
313
- if (!status) {
314
- return `当前订阅状态:${currentStatus ? '开启' : '关闭'}`;
315
- }
316
- // 计算新状态
317
- const newStatus = status === 'on' ? true : status === 'off' ? false : !currentStatus;
318
- // 如果状态没有变化,返回提示
319
- if (newStatus === currentStatus) {
320
- return `订阅状态未变化,当前状态:${currentStatus ? '开启' : '关闭'}`;
183
+ const session = argv.session;
184
+ // 1. 再次确认权限 (防御性编程)
185
+ if (!this.isAdmin(session)) {
186
+ this.ctx.logger.warn(`用户 ${session?.userId} 权限不足,尝试执行 wp-check`);
187
+ return '❌ 权限不足,需要管理员权限';
321
188
  }
322
- // 更新存储中的订阅状态
323
- await this.storageService.setUserSubscription(userId, groupId, newStatus);
324
- return `订阅状态已${newStatus ? '开启' : '关闭'}`;
189
+ this.ctx.logger.info(`用户 ${session.userId} 手动触发推送检查`);
190
+ // 2. 执行检查
191
+ await this.scheduleService.triggerCheck();
192
+ // 3. 返回明确的成功消息,不要返回 undefined 或空
193
+ return '🔄 已触发推送检查\n\n' +
194
+ '⏰ 检查过程可能需要几分钟\n' +
195
+ '⚠️ 请勿重复触发,避免推送风暴\n' +
196
+ '📢 检查结果将通过群聊通知';
325
197
  }
326
198
  catch (error) {
327
- this.ctx.logger.error('Failed to toggle subscription:', error);
328
- return '操作失败';
199
+ this.ctx.logger.error('手动检查推送内部错误:', error);
200
+ return `❌ 触发检查时发生内部错误:${error instanceof Error ? error.message : '未知错误'}`;
329
201
  }
330
202
  });
331
- wpParent
332
- .subcommand('.subscribe [status]', '管理 WordPress 推送订阅')
333
- .alias('.订阅')
334
- .action(async ({ session }, status) => {
203
+ // 查看详细帮助
204
+ this.ctx.command('wp-help', '查看详细使用说明')
205
+ .action(() => {
206
+ return '📖 WordPress 推送插件帮助\n\n' +
207
+ '【文章相关】\n' +
208
+ 'wp-news [数量] 查看最新文章 (默认5篇)\n' +
209
+ 'wp-list [页码] 浏览文章列表 (每页10篇)\n' +
210
+ 'wp-post <ID> 查看指定文章详情\n\n' +
211
+ '【推送管理】\n' +
212
+ 'wp-push [on|off] 控制群推送开关 (管理员)\n' +
213
+ 'wp-sub [on|off] 管理个人订阅\n' +
214
+ 'wp-check 手动检查推送 (管理员)\n' +
215
+ 'wp-status 查看插件状态\n' +
216
+ 'wp-help 查看详细帮助\n\n' +
217
+ '【使用示例】\n' +
218
+ '• wp-news 8 → 查看最新8篇文章\n' +
219
+ '• wp-list 2 → 查看第2页文章\n' +
220
+ '• wp-post 456 → 查看ID为456的文章\n' +
221
+ '• wp-push on → 开启群推送\n' +
222
+ '• wp-sub off → 取消个人订阅\n' +
223
+ '• wp-check → 手动检查推送\n' +
224
+ '• wp-status → 查看插件状态\n\n' +
225
+ '💡 提示:所有命令都以 wp- 开头\n' +
226
+ '👑 管理员可以使用所有命令\n' +
227
+ '🙋 普通用户可以使用文章查询和个人订阅命令';
228
+ });
229
+ // 查看插件状态
230
+ this.ctx.command('wp-status', '查看插件状态')
231
+ .action(async (argv) => {
335
232
  try {
336
- if (!session?.userId) {
337
- return '请在私聊或群聊中使用此命令';
233
+ const session = argv.session;
234
+ const groupId = session.channelId || 'global';
235
+ // 获取推送配置
236
+ const pushConfig = await this.storageService.getPushConfig(groupId);
237
+ // 获取 WordPress 服务状态
238
+ const wordpressStatus = this.wordpressService.getStatus();
239
+ // 构建状态信息
240
+ let statusMessage = '📊 WordPress 推送插件状态\n\n';
241
+ // 基本信息
242
+ statusMessage += '【基本信息】\n';
243
+ statusMessage += `WordPress 站点:${this.config.wordpressUrl}\n`;
244
+ statusMessage += `API 端点:${this.config.apiEndpoint || '/wp-json/wp/v2'}\n`;
245
+ statusMessage += `WordPress 连接:${wordpressStatus.isAuthenticated ? '正常' : '连接失败'}\n`;
246
+ if (wordpressStatus.inCooldown) {
247
+ statusMessage += `认证冷却中:${wordpressStatus.cooldownTimeRemaining} 秒\n`;
338
248
  }
339
- const userId = session.userId;
340
- const groupId = session.channelId || 'private';
341
- // 获取当前订阅状态
342
- const currentStatus = await this.storageService.isUserSubscribed(userId, groupId);
343
- // 如果没有指定状态,返回当前订阅状态
344
- if (!status) {
345
- return `当前订阅状态:${currentStatus ? '开启' : '关闭'}`;
249
+ statusMessage += `推送间隔:${this.config.checkInterval || 30} 分钟\n\n`;
250
+ // 推送配置
251
+ statusMessage += '【推送配置】\n';
252
+ statusMessage += `群推送状态:${pushConfig?.enabled ? '开启' : '关闭'}\n`;
253
+ statusMessage += `更新推送:${pushConfig?.enableUpdatePush ? '开启' : '关闭'}\n`;
254
+ statusMessage += `允许@全体:${pushConfig?.enableAtAll ? '开启' : '关闭'}\n`;
255
+ if (pushConfig?.lastPushTime) {
256
+ statusMessage += `上次推送:${new Date(pushConfig.lastPushTime).toLocaleString('zh-CN')}\n`;
346
257
  }
347
- // 计算新状态
348
- const newStatus = status === 'on' ? true : status === 'off' ? false : !currentStatus;
349
- // 如果状态没有变化,返回提示
350
- if (newStatus === currentStatus) {
351
- return `订阅状态未变化,当前状态:${currentStatus ? '开启' : '关闭'}`;
258
+ statusMessage += '\n';
259
+ // 个人订阅状态
260
+ if (session?.userId) {
261
+ const isSubscribed = await this.storageService.isUserSubscribed(session.userId, groupId);
262
+ statusMessage += '【个人订阅】\n';
263
+ statusMessage += `订阅状态:${isSubscribed ? '开启' : '关闭'}\n\n`;
352
264
  }
353
- // 更新存储中的订阅状态
354
- await this.storageService.setUserSubscription(userId, groupId, newStatus);
355
- return `订阅状态已${newStatus ? '开启' : '关闭'}`;
265
+ // 推送时间范围
266
+ statusMessage += '【推送时间】\n';
267
+ const startHour = this.config.pushStartTime || 9;
268
+ const endHour = this.config.pushEndTime || 22;
269
+ statusMessage += `允许推送时间:${startHour}:00-${endHour}:00\n`;
270
+ const currentHour = new Date().getHours();
271
+ const isPushTime = currentHour >= startHour && currentHour <= endHour;
272
+ statusMessage += `当前是否允许推送:${isPushTime ? '是' : '否'}\n\n`;
273
+ // 服务统计
274
+ statusMessage += '【服务统计】\n';
275
+ statusMessage += `总请求数:${wordpressStatus.stats.totalRequests}\n`;
276
+ statusMessage += `成功请求:${wordpressStatus.stats.successfulRequests}\n`;
277
+ statusMessage += `失败请求:${wordpressStatus.stats.failedRequests}\n`;
278
+ statusMessage += `成功率:${wordpressStatus.stats.successRate}\n`;
279
+ statusMessage += `平均响应时间:${wordpressStatus.stats.averageResponseTime}\n`;
280
+ statusMessage += `命令调用次数:${wordpressStatus.stats.commandCount}\n\n`;
281
+ // 缓存信息
282
+ statusMessage += '【缓存信息】\n';
283
+ statusMessage += `缓存大小:${wordpressStatus.cache.size}\n`;
284
+ statusMessage += `缓存时长:${wordpressStatus.cache.duration} 秒\n`;
285
+ statusMessage += `清理间隔:${wordpressStatus.cache.cleanupInterval} 秒\n\n`;
286
+ // 并发控制
287
+ statusMessage += '【并发控制】\n';
288
+ statusMessage += `最大并发:${wordpressStatus.concurrency.max}\n\n`;
289
+ // 功能特性
290
+ statusMessage += '【功能特性】\n';
291
+ statusMessage += `重试机制:${wordpressStatus.features.retryEnabled ? '开启' : '关闭'}\n`;
292
+ statusMessage += `重试次数:${wordpressStatus.features.retryLimit}\n`;
293
+ statusMessage += `缓存机制:${wordpressStatus.features.cacheEnabled ? '开启' : '关闭'}\n`;
294
+ statusMessage += `并发控制:${wordpressStatus.features.concurrencyControl ? '开启' : '关闭'}\n\n`;
295
+ // 命令提示
296
+ statusMessage += '💡 提示:\n';
297
+ statusMessage += '• 使用 wp-push on/off 开启/关闭群推送\n';
298
+ statusMessage += '• 使用 wp-sub on/off 开启/关闭个人订阅\n';
299
+ statusMessage += '• 使用 wp-check 手动触发推送检查\n';
300
+ statusMessage += '• 使用 wp-help 查看详细帮助';
301
+ return statusMessage;
356
302
  }
357
303
  catch (error) {
358
- this.ctx.logger.error('Failed to toggle subscription:', error);
359
- return '操作失败';
304
+ this.ctx.logger.error('获取插件状态失败:', error);
305
+ return `❌ 获取插件状态失败:${error instanceof Error ? error.message : '未知错误'}`;
360
306
  }
361
307
  });
362
- // 帮助指令
363
- wordpressParent
364
- .subcommand('.帮助', '查看 WordPress 插件帮助')
365
- .alias('.help')
366
- .action(() => {
367
- return `📖 WordPress 推送插件帮助\n\n` +
368
- `1. wordpress 最新 / wp latest [数量] - 查询最新文章\n` +
369
- `2. wordpress 列表 / wp list [页码] [数量] - 查询文章列表\n` +
370
- `3. wordpress 文章 / wp article <ID> - 查询单篇文章\n` +
371
- `4. wordpress 开关 / wp toggle [on|off] - 控制推送开关 (管理员)\n` +
372
- `5. wordpress 订阅 / wp subscribe [on|off] - 管理个人订阅\n` +
373
- `6. wordpress 帮助 / wp help - 查看此帮助\n\n` +
374
- `🤖 由 WordPress 推送机器人提供`;
375
- });
376
- wpParent
377
- .subcommand('.help', '查看 WordPress 插件帮助')
378
- .alias('.帮助')
308
+ // 主命令
309
+ this.ctx.command('wp', 'WordPress 推送插件主命令')
379
310
  .action(() => {
380
- return `📖 WordPress 推送插件帮助\n\n` +
381
- `1. wordpress 最新 / wp latest [数量] - 查询最新文章\n` +
382
- `2. wordpress 列表 / wp list [页码] [数量] - 查询文章列表\n` +
383
- `3. wordpress 文章 / wp article <ID> - 查询单篇文章\n` +
384
- `4. wordpress 开关 / wp toggle [on|off] - 控制推送开关 (管理员)\n` +
385
- `5. wordpress 订阅 / wp subscribe [on|off] - 管理个人订阅\n` +
386
- `6. wordpress 帮助 / wp help - 查看此帮助\n\n` +
387
- `🤖 WordPress 推送机器人提供`;
311
+ return 'WordPress 推送插件命令帮助\n\n' +
312
+ '📖 可用命令:\n' +
313
+ '- wp-news [数量] 查看最新文章\n' +
314
+ '- wp-list [页码] 浏览文章列表\n' +
315
+ '- wp-post <ID> 查看文章详情\n' +
316
+ '- wp-push [on|off] 控制群推送开关 (管理员)\n' +
317
+ '- wp-sub [on|off] 管理个人订阅\n' +
318
+ '- wp-check 手动检查推送 (管理员)\n' +
319
+ '- wp-status 查看插件状态\n' +
320
+ '- wp-help 查看详细帮助\n\n' +
321
+ '💡 示例:wp-news 10 查看最新10篇文章';
388
322
  });
389
323
  }
390
324
  }
package/lib/index.d.ts CHANGED
@@ -16,6 +16,10 @@ export interface Config {
16
16
  allowAtAll?: boolean;
17
17
  messageType?: MessageType;
18
18
  signatureKey?: string;
19
+ adminUserId?: string;
20
+ superAdminUserIds?: string[];
21
+ pushStartTime?: number;
22
+ pushEndTime?: number;
19
23
  }
20
24
  export declare const schema: Schema<Config>;
21
25
  export declare function apply(ctx: Context, config: Config): void;