index.ts 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. import { Score } from '../../db/models'
  2. import { ScoreData } from '../../db/models/Score'
  3. import { sleep } from '../../utils'
  4. import chainService from '../chainService'
  5. import difyService, {
  6. CompletionMessagesPayload,
  7. DifyRateLimitExceedError,
  8. } from '../difyService'
  9. import {
  10. makePaginate,
  11. PaginateOptions,
  12. PaginationConnection,
  13. } from 'sequelize-cursor-pagination'
  14. async function getCompletionMessages(
  15. payload: CompletionMessagesPayload
  16. ): Promise<Score> {
  17. const { query, onUpdate, signature, address } = payload
  18. const signatureRowExist = await Score.findOne({ where: { signature } })
  19. if (signatureRowExist) {
  20. const { messageId } = signatureRowExist
  21. const words = signatureRowExist.answer.split(' ').map((word) => ` ${word}`)
  22. if (words[0]) {
  23. words[0] = words[0].trim()
  24. }
  25. for (const word of words) {
  26. const data = { event: 'message', messageId, signature, answer: word }
  27. const message = JSON.stringify(data)
  28. onUpdate(`data: ${message}\n\n`)
  29. await sleep(20)
  30. }
  31. const data = { event: 'message_end', messageId, signature }
  32. const message = JSON.stringify(data)
  33. onUpdate(`data: ${message}\n\n`)
  34. return signatureRowExist
  35. }
  36. const checkResult = await chainService.checkTxIsSendBananaToBlackhole(
  37. address,
  38. signature
  39. )
  40. if (!checkResult.success) {
  41. throw new Error('Invalid transaction signature')
  42. }
  43. const scoreId = Score.getScoreId(query)
  44. const exist = await Score.findOne({ where: { scoreId } })
  45. if (exist) {
  46. const { messageId } = exist
  47. const words = exist.answer.split(' ').map((word) => ` ${word}`)
  48. if (words[0]) {
  49. words[0] = words[0].trim()
  50. }
  51. for (const word of words) {
  52. const data = { event: 'message', messageId, signature, answer: word }
  53. const message = JSON.stringify(data)
  54. onUpdate(`data: ${message}\n\n`)
  55. await sleep(20)
  56. }
  57. const data = { event: 'message_end', messageId, signature }
  58. const message = JSON.stringify(data)
  59. onUpdate(`data: ${message}\n\n`)
  60. const row = await Score.create({
  61. address,
  62. signature,
  63. scoreId: exist.scoreId,
  64. query: exist.query,
  65. answer: exist.answer,
  66. messageId,
  67. score: exist.score,
  68. scoreText: exist.scoreText,
  69. })
  70. return row
  71. }
  72. try {
  73. const { answer, messageId } =
  74. await difyService.getCompletionMessagesByFetchAPI(payload)
  75. const [scoreText, score] = Score.getScore(answer)
  76. const row = await Score.create({
  77. address,
  78. signature,
  79. scoreId,
  80. query,
  81. answer,
  82. messageId,
  83. score,
  84. scoreText,
  85. })
  86. return row
  87. } catch (e) {
  88. if (e instanceof DifyRateLimitExceedError) {
  89. const { serveAt } = e
  90. const intime = Math.ceil((serveAt - Date.now()) / 1000)
  91. throw new Error(
  92. `Master is talking with other guys, please try after ${intime}s.`
  93. )
  94. }
  95. throw e
  96. }
  97. }
  98. // console.log(Tweet.rawAttributes)
  99. let paginate: (
  100. this: unknown,
  101. queryOptions: PaginateOptions<Score>
  102. ) => Promise<PaginationConnection<Score>>
  103. async function paginateScoreByOrder(
  104. after?: string,
  105. limit = 10
  106. ): Promise<PaginationConnection<ScoreData>> {
  107. if (!paginate) {
  108. paginate = makePaginate(Score)
  109. }
  110. const secondResult = await paginate({
  111. order: [['id', 'DESC']],
  112. limit,
  113. after,
  114. })
  115. const ret: PaginationConnection<ScoreData> = {
  116. ...secondResult,
  117. edges: secondResult.edges.map((edge) => ({
  118. cursor: edge.node.id,
  119. node: edge.node.getData(),
  120. })),
  121. }
  122. return ret
  123. }
  124. async function getScoreById(id: number): Promise<Score> {
  125. const row = await Score.findByPk(id)
  126. if (!row) {
  127. throw new Error('Score not found')
  128. }
  129. return row
  130. }
  131. const scoreService = {
  132. getCompletionMessages,
  133. paginateScoreByOrder,
  134. getScoreById,
  135. }
  136. export default scoreService