koishi-plugin-ll-schedule 1.7.3 → 1.7.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.
Files changed (2) hide show
  1. package/index.js +59 -17
  2. package/package.json +3 -1
package/index.js CHANGED
@@ -627,6 +627,11 @@ function apply(ctx, config) {
627
627
  return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`
628
628
  }
629
629
 
630
+ // 分钟数 → "HH:MM"
631
+ function minToHM(min) {
632
+ return `${String(Math.floor(min / 60) % 24).padStart(2, '0')}:${String(min % 60).padStart(2, '0')}`
633
+ }
634
+
630
635
  // ===== 发送 =====
631
636
  const KNOWN_IGNORE_CODES = new Set([11293, 40034101, 40034105, 304101, 304102])
632
637
 
@@ -829,10 +834,19 @@ function apply(ctx, config) {
829
834
  // ① 活动表模式(有新活动表就只跑它,避免和旧任务重复发)
830
835
  const activities = parseActivities(config.activities)
831
836
  if (activities.length) {
837
+ const nowMin = hmToMin(hm)
832
838
  const reminds = computeReminders(activities, now, hm)
833
839
  for (const r of reminds) {
840
+ // 发送前复核:独立再算一次"这条提醒该在几点发",对不上就拒发(防任何上游错位)
841
+ const fireMin = r.inst.startMin - (r.inst.advance || 0)
842
+ if (fireMin !== nowMin) {
843
+ logger.warn(`[schedule] 触发复核未通过,已拒发:「${r.inst.activity}」提醒点 ${minToHM(fireMin)},当前 ${hm}`)
844
+ continue
845
+ }
834
846
  if (firedToday[r.key]) continue
835
847
  firedToday[r.key] = true
848
+ logger.info(`[schedule] 触发提醒:「${r.inst.activity}」星期${WEEK_CN[r.inst.day]} ${r.inst.start}-${r.inst.end}` +
849
+ `${r.inst.place ? '|' + r.inst.place : ''}|提醒点 ${minToHM(fireMin)}|当前 ${hm}`)
836
850
  await sendReminder(r.inst, r.next, now, hm)
837
851
  }
838
852
  return
@@ -918,30 +932,60 @@ function apply(ctx, config) {
918
932
  return formatTaskList()
919
933
  })
920
934
 
921
- // 自检:把"插件认为的当前时间 / 解析出的活动表 / 下一次提醒时刻"全打出来,便于排查
922
- ctx.command('schedule.debug', '自检:查看当前时间、活动表解析结果、下一次提醒时刻')
923
- .action(() => {
935
+ // 自检:看当前时间 / 活动表解析结果 / 某时刻会触发什么
936
+ // 可加参数模拟,如:schedule.debug 18:58 或 schedule.debug 周四18:58
937
+ ctx.command('schedule.debug [arg:text]', '自检:可加时间模拟(例:schedule.debug 18:58)')
938
+ .action((_, arg) => {
939
+ logger.info(`[schedule] 命令被调用: schedule.debug arg=${arg || ''}`)
924
940
  const now = new Date()
925
- const day = todayDay(now)
926
- const hm = nowHM(now)
927
- const nowMin = hmToMin(hm)
941
+ const nowDay = todayDay(now)
928
942
  const acts = parseActivities(config.activities)
929
943
  const instances = expandInstances(acts)
944
+ let day = nowDay
945
+ let hm = nowHM(now)
946
+ let simulated = false
947
+ if (arg) {
948
+ const tm = String(arg).match(/(\d{1,2}):(\d{2})/)
949
+ if (tm) {
950
+ hm = `${String(tm[1]).padStart(2, '0')}:${tm[2]}`
951
+ simulated = true
952
+ }
953
+ const dm = String(arg).match(/(?:周|星期|礼拜)([一二三四五六日天1-7])/)
954
+ if (dm) {
955
+ const map = { '一': 1, '二': 2, '三': 3, '四': 4, '五': 5, '六': 6, '日': 7, '天': 7 }
956
+ day = map[dm[1]] || parseInt(dm[1], 10) || day
957
+ simulated = true
958
+ }
959
+ }
960
+ const simDate = new Date(now)
961
+ simDate.setDate(now.getDate() + ((day - nowDay + 7) % 7))
962
+
930
963
  const lines = [
931
- `🕐 插件当前时间:${todayStr(now)} ${hm}:${String(now.getSeconds()).padStart(2, '0')}(星期${WEEK_CN[day]})`,
932
- `📋 活动表:解析出 ${acts.length} 个活动 / ${instances.length} 个时段实例`,
964
+ `🕐 插件当前时间:${todayStr(now)} ${nowHM(now)}:${String(now.getSeconds()).padStart(2, '0')}(星期${WEEK_CN[nowDay]})`,
965
+ `📋 活动表:${acts.length} 个活动 / ${instances.length} 个时段实例`,
933
966
  ]
934
967
  for (const a of acts) {
935
- lines.push(`【${a.name}】提前 ${a.advance} 分钟,${a.slots.length} 行`)
968
+ lines.push(`【${a.name}】提前 ${a.advance} 分钟`)
936
969
  for (const s of a.slots) {
937
- lines.push(` · ${s.wd} ${s.start}-${s.end}${s.place ? ' 地点:' + s.place : ''}`)
970
+ lines.push(` · ${s.wd} ${s.start}-${s.end}${s.place ? ' ' + s.place : ''}`)
971
+ }
972
+ }
973
+ const label = `${simulated ? '模拟' : '当前'} ${todayStr(simDate)} ${hm}(星期${WEEK_CN[day]})`
974
+ const hits = computeReminders(acts, simDate, hm)
975
+ if (hits.length) {
976
+ for (const h of hits) {
977
+ lines.push(`🔔 ${label} 会触发:「${h.inst.activity}」${h.inst.start}-${h.inst.end}${h.inst.place ? ' ' + h.inst.place : ''}(提前 ${h.inst.advance} 分钟)`)
938
978
  }
939
979
  }
940
- // 下一次提醒
980
+ else {
981
+ lines.push(`🔔 ${label} 不会触发任何提醒`)
982
+ }
983
+ // 下一次提醒(按当前时刻往后算)
984
+ const nowMin = hmToMin(nowHM(now))
941
985
  let best = null
942
986
  for (const inst of instances) {
943
987
  const fireMin = inst.startMin - (inst.advance || 0)
944
- let offset = (inst.day - day + 7) % 7
988
+ let offset = (inst.day - nowDay + 7) % 7
945
989
  if (offset === 0 && fireMin <= nowMin) offset = 7
946
990
  const key = offset * 1440 + fireMin
947
991
  if (!best || key < best.key) best = { key, inst, offset, fireMin }
@@ -949,14 +993,12 @@ function apply(ctx, config) {
949
993
  if (best) {
950
994
  const hh = String(Math.floor(best.fireMin / 60)).padStart(2, '0')
951
995
  const mm = String(best.fireMin % 60).padStart(2, '0')
952
- const when = best.offset === 0 ? '今天' : `星期${WEEK_CN[((day - 1 + best.offset) % 7) + 1]}`
996
+ const when = best.offset === 0 ? '今天' : `星期${WEEK_CN[((nowDay - 1 + best.offset) % 7) + 1]}`
953
997
  lines.push(`⏭ 下一次提醒:「${best.inst.activity}」${when} ${hh}:${mm}(活动 ${best.inst.start}-${best.inst.end}${best.inst.place ? ' ' + best.inst.place : ''})`)
954
998
  }
955
- else {
956
- lines.push('⏭ 下一次提醒:(活动表为空)')
957
- }
958
999
  lines.push(`💾 已订阅群:${(subs.get(ALL) || new Map()).size} 个`)
959
- logger.info('[schedule] 命令被调用: schedule.debug')
1000
+ const fired = Object.keys(firedToday).filter(k => k !== 'date')
1001
+ lines.push(`📤 今天已发过的提醒(${firedToday.date || todayStr(now)}):${fired.length ? fired.join('、') : '无'}`)
960
1002
  return lines.join('\n')
961
1003
  })
962
1004
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "koishi-plugin-ll-schedule",
3
- "version": "1.7.3",
3
+ "version": "1.7.5",
4
4
  "description": "Scheduled message sender with weekly slots (per-day time & content), QQ official markdown card support",
5
5
  "main": "index.js",
6
6
  "files": [
@@ -35,3 +35,5 @@
35
35
 
36
36
 
37
37
 
38
+
39
+