syncLepaoAccountFromToken.js 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. /**
  2. * 用 JKES token 拉取 getMyInfo 并更新 lepao_account(沐晨乐跑 / JKES 唯一数据源)
  3. */
  4. const db = require('../DataBase/db.js')
  5. const { jkesRequest } = require('./request.js')
  6. const { resolveQQAvatarFromEmail } = require('./resolveQQAvatar.js')
  7. const DEFAULT_AVATAR =
  8. 'https://lepao-cloud.xxoo365.top/view.php/25aa126dc406974ff3579a99a2c6501a.png'
  9. const LOGIN_EXPIRED_MSG = '乐跑账号登录失效,请重新使用乐跑登录器进行登录'
  10. async function markLoginExpiredByStudentNum(studentNum) {
  11. const sid = String(studentNum ?? '').trim()
  12. if (!sid) return
  13. await db.query(
  14. 'UPDATE lepao_account SET state = 0, update_time = ? WHERE student_num = ?',
  15. [Date.now(), sid]
  16. )
  17. }
  18. async function markLoginExpiredByToken(token) {
  19. const tokenClean = String(token ?? '').trim()
  20. if (!tokenClean) return
  21. await db.query(
  22. 'UPDATE lepao_account SET state = 0, update_time = ? WHERE token = ?',
  23. [Date.now(), tokenClean]
  24. )
  25. }
  26. /**
  27. * @param {string} token
  28. * @param {{ userAgent?: string, deviceModel?: string }} [device]
  29. * @returns {Promise<
  30. * | { ok: false, msg: string, jkesRes?: object }
  31. * | {
  32. * ok: true
  33. * student_num: string
  34. * findRows: object[]
  35. * profile: {
  36. * name: string
  37. * academy_name: string
  38. * grade_id: any
  39. * class_id: any
  40. * sex: number
  41. * user_avatar: string
  42. * }
  43. * }
  44. * >}
  45. */
  46. async function syncLepaoAccountFromToken(token, device = {}) {
  47. let jkesRes
  48. try {
  49. jkesRes = await jkesRequest('/sys/user/getMyInfo', {}, token)
  50. } catch (error) {
  51. if (error?.loginExpired) {
  52. await markLoginExpiredByToken(token)
  53. return {
  54. ok: false,
  55. msg: LOGIN_EXPIRED_MSG
  56. }
  57. }
  58. throw error
  59. }
  60. if (!jkesRes || jkesRes.code !== 0 || !jkesRes.data || !jkesRes.data.info) {
  61. return {
  62. ok: false,
  63. msg: jkesRes?.message || '获取用户信息失败,请稍后重试或联系客服',
  64. jkesRes
  65. }
  66. }
  67. const {
  68. code,
  69. realName,
  70. identifyCode,
  71. mobileNumber,
  72. gender,
  73. gradeYear,
  74. collegeCode,
  75. classCode,
  76. homeAddr
  77. } = jkesRes.data.info
  78. const sex = gender?.label === '男' ? 1 : 2
  79. const name = realName
  80. const academy_name = collegeCode?.name ?? ''
  81. const grade_id = gradeYear
  82. const class_id = classCode?.className ?? ''
  83. const student_num = code
  84. const findSql = `
  85. SELECT
  86. a.email, a.user_avatar, a.create_user, a.auto_run, a.auto_day, a.notice_type, a.target_count,
  87. a.auto_run_distance_min_km, a.auto_run_distance_max_km, a.pace_min_sec_per_km, a.pace_max_sec_per_km,
  88. e.bot_umo
  89. FROM
  90. lepao_account a
  91. LEFT JOIN
  92. lepao_extra e
  93. ON
  94. a.student_num = e.student_num
  95. WHERE
  96. a.student_num = ? AND a.create_user IS NOT NULL
  97. `
  98. const findRows = await db.query(findSql, [student_num])
  99. if (!findRows) {
  100. return { ok: false, msg: '无法获取用户数据,请重试' }
  101. }
  102. if (findRows.length === 0) {
  103. return {
  104. ok: false,
  105. msg: '该乐跑账号尚未在沐晨乐跑中添加,请先前往 https://jkes.xxoo365.top/ 添加你的账户'
  106. }
  107. }
  108. const user_avatar =
  109. resolveQQAvatarFromEmail(findRows[0].email) ||
  110. findRows[0].user_avatar ||
  111. DEFAULT_AVATAR
  112. const time = Date.now()
  113. const ua = device.userAgent
  114. const dm = device.deviceModel
  115. let updateSql =
  116. 'UPDATE lepao_account SET token = ?, name = ?, grade_id = ?, class_id = ?, sex = ?, academy_name = ?, update_time = ?, user_avatar = ?, identifyCode = ?, mobileNumber = ?, homeAddr = ?, state = 1'
  117. const params = [
  118. token,
  119. name,
  120. grade_id,
  121. class_id,
  122. sex,
  123. academy_name,
  124. time,
  125. user_avatar,
  126. identifyCode,
  127. mobileNumber,
  128. homeAddr
  129. ]
  130. if (ua != null && ua !== '') {
  131. updateSql += ', userAgent = ?'
  132. params.push(ua)
  133. }
  134. if (dm != null && dm !== '') {
  135. updateSql += ', deviceModel = ?'
  136. params.push(dm)
  137. }
  138. updateSql += ' WHERE student_num = ?'
  139. params.push(student_num)
  140. const updateRows = await db.query(updateSql, params)
  141. if (!updateRows || updateRows.affectedRows < 1) {
  142. return { ok: false, msg: '更新账号信息失败,请重试' }
  143. }
  144. return {
  145. ok: true,
  146. student_num,
  147. findRows,
  148. profile: {
  149. name,
  150. academy_name,
  151. grade_id,
  152. class_id,
  153. sex,
  154. user_avatar
  155. }
  156. }
  157. }
  158. module.exports = {
  159. syncLepaoAccountFromToken,
  160. markLoginExpiredByStudentNum,
  161. markLoginExpiredByToken,
  162. LOGIN_EXPIRED_MSG,
  163. DEFAULT_AVATAR
  164. }