koishi-plugin-ll-schedule 1.0.4 → 1.0.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.
Files changed (2) hide show
  1. package/index.js +34 -29
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -1,21 +1,28 @@
1
1
  'use strict'
2
2
 
3
3
  // koishi-plugin-ll-schedule
4
- // 定时发送插件:设置时间自动向指定群发送文字/图片
5
- // v1.0.4:群内订阅(发关键词即可让本群加入推送列表,官机自动用 openid,无需手动填群号)
4
+ // 定时发送插件:设置时间自动向指定群发送文字
5
+ // v1.0.6:一个任务支持多个时间(逗号分隔),群内"订阅"关键词自动注册推送群
6
6
 
7
7
  const { Schema, h } = require('koishi')
8
8
 
9
9
  exports.name = 'll-schedule'
10
10
 
11
- exports.usage = `定时发送插件:设置时间自动向指定群发送文字/图片。
11
+ exports.usage = `定时发送插件:设置时间自动向指定群发送文字。
12
12
 
13
13
  ## 快速上手(推荐用法)
14
14
 
15
- 1. 在插件设置页的 \`tasks\` 表格中添加任务:**键=任务名**,设置 \`time\`(发送时间)和 \`text\`/\`image\`(推送内容)
15
+ 1. 在插件设置页的 \`tasks\` 表格中添加任务:**键=任务名**,设置 \`time\`(发送时间,**可多个**)和 \`text\`(推送内容)
16
16
  2. 在任意群里 @机器人 发:\`订阅 任务名\` → 这个群就加入了该任务的推送列表(自动记录,重启不丢)
17
17
  3. 到点后插件自动把内容推送到所有订阅了该任务的群
18
18
 
19
+ ## 任务配置
20
+
21
+ - \`time\`:发送时间(24小时制 HH:MM),**可填多个,用逗号分隔**,如 \`09:00, 21:30\`(一条内容会在每个时间点各发一次)
22
+ - \`text\`:推送内容(文字,可留空)
23
+ - \`groups\`:手动指定的目标群列表(**推荐留空**,用群内"订阅"命令添加更省事;留空且无订阅 = 发给所有已知群)
24
+ - \`enabled\`:是否启用
25
+
19
26
  ## 群内命令
20
27
 
21
28
  - \`订阅 [任务名]\`:当前群订阅指定任务的推送(不填任务名时,只有一个启用任务则自动选它)
@@ -27,14 +34,6 @@ exports.usage = `定时发送插件:设置时间自动向指定群发送文字
27
34
 
28
35
  订阅/取消订阅的权限等级可在设置页 \`subscribeAuthority\` 调整(默认 2=群管理)。
29
36
 
30
- ## 任务配置
31
-
32
- - \`time\`:发送时间,HH:MM 格式(24小时制)
33
- - \`groups\`:手动指定的目标群列表(**推荐留空**,用群内"订阅"命令添加更省事;留空且无订阅 = 发给所有已知群)
34
- - \`text\`:文字内容(可留空)
35
- - \`image\`:图片 URL(可留空)
36
- - \`enabled\`:是否启用
37
-
38
37
  ## 官机(官方QQ机器人)说明
39
38
 
40
39
  官方平台没有"群号",只有 openid——用群内"订阅"命令即可,插件会自动记录当前群的 openid,无需手动填写。手动填 \`groups\` 时可用 \`schedule.groups\` 查看已知群的 openid。官机主动发群消息有平台频率限制,且机器人需在群里。
@@ -43,16 +42,13 @@ exports.usage = `定时发送插件:设置时间自动向指定群发送文字
43
42
  const TaskItem = Schema.object({
44
43
  time: Schema.string()
45
44
  .required()
46
- .description('发送时间,HH:MM 格式(24小时制),如 08:30、21:00'),
45
+ .description('发送时间(24小时制 HH:MM),可填多个用逗号分隔,如 09:00, 21:30'),
47
46
  groups: Schema.array(Schema.string())
48
47
  .default([])
49
48
  .description('手动指定的目标群 ID(可留空;推荐用群内"订阅"命令自动添加,无需手动填 openid)'),
50
49
  text: Schema.string()
51
50
  .default('')
52
- .description('文字内容(可留空)'),
53
- image: Schema.string()
54
- .default('')
55
- .description('图片URL(可留空)'),
51
+ .description('推送内容(文字,可留空)'),
56
52
  enabled: Schema.boolean()
57
53
  .default(true)
58
54
  .description('是否启用'),
@@ -247,6 +243,15 @@ function apply(ctx, config) {
247
243
  return `${String(d.getHours()).padStart(2, '0')}:${String(d.getMinutes()).padStart(2, '0')}`
248
244
  }
249
245
 
246
+ // 解析任务时间:支持多个时间,逗号/顿号/空格分隔,如 "09:00, 21:30"
247
+ function parseTimes(timeStr) {
248
+ if (!timeStr) return []
249
+ return String(timeStr).split(/[,,、;;\s]+/)
250
+ .map(s => s.trim())
251
+ .filter(s => /^\d{1,2}:\d{2}$/.test(s))
252
+ .map(s => (s.length === 4 ? '0' + s : s))
253
+ }
254
+
250
255
  function todayStr() {
251
256
  const d = new Date()
252
257
  return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`
@@ -264,7 +269,8 @@ function apply(ctx, config) {
264
269
 
265
270
  for (const [name, task] of Object.entries(tasks)) {
266
271
  if (!task || task.enabled === false) continue
267
- if (!task.time || task.time.trim() !== hm) continue
272
+ const timeList = parseTimes(task.time)
273
+ if (!timeList.includes(hm)) continue
268
274
  // 今天这个时间点已经发过这个任务 → 跳过
269
275
  const fireKey = `${name}@${hm}`
270
276
  if (firedToday[fireKey]) continue
@@ -376,11 +382,13 @@ function apply(ctx, config) {
376
382
  return keys.map(k => {
377
383
  const t = tasks[k]
378
384
  const s = t.enabled === false ? '⛔' : '✅'
379
- const content = [t.text && '文字', t.image && '图片'].filter(Boolean).join('+') || '(空)'
385
+ const content = [t.text && '文字'].filter(Boolean).join('+') || '(空)'
380
386
  const staticGroups = (t.groups || []).join(',')
381
387
  const subCount = (subs.get(k) || new Map()).size
382
388
  const target = staticGroups ? staticGroups : (subCount ? `订阅${subCount}群` : '所有已知群')
383
- return `${s} ${k} @ ${t.time} → ${content} → 群:${target}${subCount && staticGroups ? ` +订阅${subCount}群` : ''}`
389
+ const times = parseTimes(t.time)
390
+ const timeStr = times.length ? times.join(', ') : (t.time || '(无时间)')
391
+ return `${s} ${k} @ ${timeStr} → ${content} → 群:${target}${subCount && staticGroups ? ` +订阅${subCount}群` : ''}`
384
392
  }).join('\n')
385
393
  }
386
394
 
@@ -446,7 +454,8 @@ function apply(ctx, config) {
446
454
  taskSubs.set(key, entry)
447
455
  persistSub(name, entry)
448
456
  logger.info(`[schedule] 群 ${session.guildId} 已订阅任务 "${name}"`)
449
- return `✅ 本群已加入任务 "${name}" 的推送列表\n时间:${task.time}\n内容:${task.text || '(图片)'}`
457
+ const times = parseTimes(task.time)
458
+ return `✅ 本群已加入任务 "${name}" 的推送列表\n时间:${times.length ? times.join(', ') : '(未设置)'}\n内容:${task.text || '(空)'}`
450
459
  }
451
460
 
452
461
  async function unsubscribeCurrentGroup(session, taskName) {
@@ -463,26 +472,22 @@ function apply(ctx, config) {
463
472
  return `✅ 本群已取消订阅任务 "${name}"`
464
473
  }
465
474
 
466
- ctx.command(config.subscribeKeyword + ' [taskName:text]', '让当前群订阅指定任务的推送')
467
- .authority(config.subscribeAuthority)
475
+ ctx.command(config.subscribeKeyword + ' [taskName:text]', '让当前群订阅指定任务的推送', { authority: config.subscribeAuthority })
468
476
  .action(async ({ session }, taskName) => {
469
477
  return await subscribeCurrentGroup(session, taskName)
470
478
  })
471
479
 
472
- ctx.command('lls.sub [taskName:text]', '订阅推送(备用入口)')
473
- .authority(config.subscribeAuthority)
480
+ ctx.command('lls.sub [taskName:text]', '订阅推送(备用入口)', { authority: config.subscribeAuthority })
474
481
  .action(async ({ session }, taskName) => {
475
482
  return await subscribeCurrentGroup(session, taskName)
476
483
  })
477
484
 
478
- ctx.command(config.unsubscribeKeyword + ' [taskName:text]', '让当前群取消订阅指定任务的推送')
479
- .authority(config.subscribeAuthority)
485
+ ctx.command(config.unsubscribeKeyword + ' [taskName:text]', '让当前群取消订阅指定任务的推送', { authority: config.subscribeAuthority })
480
486
  .action(async ({ session }, taskName) => {
481
487
  return await unsubscribeCurrentGroup(session, taskName)
482
488
  })
483
489
 
484
- ctx.command('lls.unsub [taskName:text]', '取消订阅(备用入口)')
485
- .authority(config.subscribeAuthority)
490
+ ctx.command('lls.unsub [taskName:text]', '取消订阅(备用入口)', { authority: config.subscribeAuthority })
486
491
  .action(async ({ session }, taskName) => {
487
492
  return await unsubscribeCurrentGroup(session, taskName)
488
493
  })
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "koishi-plugin-ll-schedule",
3
- "version": "1.0.4",
3
+ "version": "1.0.6",
4
4
  "description": "Scheduled message sender with text/image support, works with official QQ bot",
5
5
  "main": "index.js",
6
6
  "files": [