StartAutoLepao.js 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. const API = require("../../lib/API");
  2. const db = require('../../plugin/DataBase/db')
  3. const mq = require('../../plugin/mq')
  4. const { assertRunforgeTaskIngress, publishRunforgeTask } = require('../../plugin/mq/runforgeTaskMq')
  5. const { scheduleDelayedRunforgeTask } = require('../../plugin/mq/lepaoAutoScheduleRedis')
  6. const mqNames = require('../../plugin/mq/jkesMqNames')
  7. const { BaseStdResponse } = require("../../BaseStdResponse");
  8. const { prepareAutoRunTask, buildStartRunPayload } = require('../../plugin/jkes/prepareAutoRunTask')
  9. class StartAutoLepao extends API {
  10. constructor() {
  11. super();
  12. this.noEncrypt()
  13. this.setPath('/Corn/StartAutoLepao');
  14. this.setMethod('GET');
  15. }
  16. async publishAutoRun(channel, item, payload, logLabel) {
  17. const { name, student_num } = item
  18. try {
  19. publishRunforgeTask(channel, payload)
  20. this.logger.info(`${name}(${student_num})${logLabel}`)
  21. } catch (err) {
  22. this.logger.error(`${name}(${student_num})乐跑投递失败:${err.message || err}`)
  23. }
  24. }
  25. async onRequest(req, res) {
  26. try {
  27. res.json({
  28. ...BaseStdResponse.OK
  29. })
  30. const day = new Date().getDay()
  31. const hour = new Date().getHours()
  32. this.logger.info('开始执行自动乐跑任务')
  33. let sql = `
  34. SELECT name, student_num, auto_day, token, target_count,
  35. auto_run_distance_min_km, auto_run_distance_max_km, pace_min_sec_per_km, pace_max_sec_per_km
  36. FROM lepao_account
  37. WHERE auto_run = 1 AND state = 1
  38. AND (auto_time = ? OR (auto_time = -1 AND today_auto_time = ?))
  39. AND JSON_CONTAINS(auto_day, CAST(? AS JSON))
  40. `
  41. let r = await db.query(sql, [hour, hour, day])
  42. if (!r)
  43. return this.logger.error('获取自动乐跑账号失败!')
  44. const nowMs = Date.now()
  45. const hourEnd = new Date()
  46. hourEnd.setHours(hourEnd.getHours() + 1, 0, 0, 0)
  47. const spreadWindowMs = Math.max(0, hourEnd.getTime() - nowMs)
  48. let channel
  49. try {
  50. channel = await mq.getChannel(mqNames.channelLepaoCorn)
  51. await assertRunforgeTaskIngress(channel, this.logger)
  52. } catch (err) {
  53. this.logger.error(`自动乐跑:连接 MQ 或声明拓扑失败:${err.message || err}`)
  54. return
  55. }
  56. for (const item of r) {
  57. const { name, student_num } = item
  58. const prepared = await prepareAutoRunTask(item)
  59. if (!prepared.run) {
  60. this.logger.info(`${name}(${student_num}) JKES 自动乐跑跳过:${prepared.reason}`)
  61. continue
  62. }
  63. const delayMs = spreadWindowMs > 0 ? Math.floor(Math.random() * spreadWindowMs) : 0
  64. const fireAt = nowMs + delayMs
  65. const payload = buildStartRunPayload(student_num, prepared.task, {
  66. taskId: `lepao:auto:${fireAt}:${student_num}`
  67. })
  68. if (delayMs > 0) {
  69. try {
  70. await scheduleDelayedRunforgeTask(fireAt, payload, {
  71. name,
  72. account: student_num,
  73. delayMs
  74. })
  75. this.logger.info(
  76. `${name}(${student_num})已写入 Redis 调度(约 ${Math.round(delayMs / 1000)}s 后进 MQ)`
  77. )
  78. } catch (err) {
  79. this.logger.error(`${name}(${student_num})Redis 调度失败,改为立即投递:${err.message || err}`)
  80. await this.publishAutoRun(channel, item, payload, 'Redis 调度失败后已立即投递自动乐跑任务')
  81. }
  82. continue
  83. }
  84. await this.publishAutoRun(channel, item, payload, '已投递自动乐跑任务')
  85. }
  86. } catch (error) {
  87. this.logger.error(error)
  88. }
  89. }
  90. }
  91. module.exports.StartAutoLepao = StartAutoLepao;