StartAutoLepao.js 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. const API = require("../../lib/API");
  2. const db = require('../../plugin/DataBase/db')
  3. const Redis = require('../../plugin/DataBase/Redis')
  4. const mq = require('../../plugin/mq')
  5. const { BaseStdResponse } = require("../../BaseStdResponse");
  6. class StartAutoLepao extends API {
  7. constructor() {
  8. super();
  9. this.noEncrypt()
  10. this.setPath('/Corn/StartAutoLepao');
  11. this.setMethod('GET');
  12. }
  13. async onRequest(req, res) {
  14. try {
  15. res.json({
  16. ...BaseStdResponse.OK
  17. })
  18. const day = new Date().getDay()
  19. const hour = new Date().getHours()
  20. this.logger.info('开始执行自动乐跑任务')
  21. let sql = `
  22. SELECT name, create_user, student_num, token, uid, school_id, state
  23. FROM lepao_account
  24. WHERE auto_run = 1
  25. AND (auto_time = ? OR (auto_time = -1 AND today_auto_time = ?))
  26. AND JSON_CONTAINS(auto_day, CAST(? AS JSON))
  27. `
  28. let r = await db.query(sql, [hour, hour, day])
  29. if (!r)
  30. return this.logger.error('获取自动乐跑账号失败!')
  31. // 为本小时内随机打散投递时间,减轻瞬时并发(0 ~ 当前小时剩余毫秒数)
  32. const nowMs = Date.now()
  33. const hourEnd = new Date()
  34. hourEnd.setHours(hourEnd.getHours() + 1, 0, 0, 0)
  35. const spreadWindowMs = Math.max(0, hourEnd.getTime() - nowMs)
  36. let channel
  37. try {
  38. channel = await mq.getChannel('lepao_corn')
  39. await channel.assertQueue('runforge_task_queue', { durable: true })
  40. } catch (err) {
  41. this.logger.error(`自动乐跑:连接 MQ 失败:${err.message || err}`)
  42. return
  43. }
  44. for (const item of r) {
  45. const { name, create_user, student_num, token, uid, school_id, state } = item
  46. const isSuccess = await Redis.get(`lepaoSuccess:${student_num}`)
  47. if (isSuccess) {
  48. this.logger.info(`${name}(${student_num})当天已乐跑成功,不执行自动乐跑`)
  49. continue
  50. }
  51. const delayMs = spreadWindowMs > 0 ? Math.floor(Math.random() * spreadWindowMs) : 0
  52. const fireAt = nowMs + delayMs
  53. this.logger.info(`${name}(${student_num})将加入自动乐跑队列(延迟约 ${Math.round(delayMs / 1000)}s)`)
  54. setTimeout(() => {
  55. try {
  56. const taskId = `lepao:auto:${fireAt}:${student_num}`
  57. const payload = {
  58. id: taskId,
  59. type: 'lepao.startRun',
  60. data: {
  61. taskId,
  62. account: student_num
  63. },
  64. retry: 0
  65. }
  66. channel.sendToQueue(
  67. 'runforge_task_queue',
  68. Buffer.from(JSON.stringify(payload)),
  69. { persistent: true, contentType: 'application/json' }
  70. )
  71. this.logger.info(`${name}(${student_num})已投递自动乐跑任务(延迟约 ${Math.round(delayMs / 1000)}s)`)
  72. } catch (err) {
  73. this.logger.error(`${name}(${student_num})乐跑投递失败:${err.message || err}`)
  74. }
  75. }, delayMs)
  76. }
  77. } catch (error) {
  78. this.logger.error(error)
  79. }
  80. }
  81. }
  82. module.exports.StartAutoLepao = StartAutoLepao;