import { Score } from '../../db/models' import { ScoreData } from '../../db/models/Score' import { sleep } from '../../utils' import chainService from '../chainService' import difyService, { CompletionMessagesPayload, DifyRateLimitExceedError, } from '../difyService' import { makePaginate, PaginateOptions, PaginationConnection, } from 'sequelize-cursor-pagination' async function getCompletionMessages( payload: CompletionMessagesPayload ): Promise { const { query, onUpdate, signature, address } = payload const signatureRowExist = await Score.findOne({ where: { signature } }) if (signatureRowExist) { const { messageId } = signatureRowExist const words = signatureRowExist.answer.split(' ').map((word) => ` ${word}`) if (words[0]) { words[0] = words[0].trim() } for (const word of words) { const data = { event: 'message', messageId, signature, answer: word } const message = JSON.stringify(data) onUpdate(`data: ${message}\n\n`) await sleep(20) } const data = { event: 'message_end', messageId, signature } const message = JSON.stringify(data) onUpdate(`data: ${message}\n\n`) return signatureRowExist } const checkResult = await chainService.checkTxIsSendBananaToBlackhole( address, signature ) if (!checkResult.success) { throw new Error('Invalid transaction signature') } const scoreId = Score.getScoreId(query) const exist = await Score.findOne({ where: { scoreId } }) if (exist) { const { messageId } = exist const words = exist.answer.split(' ').map((word) => ` ${word}`) if (words[0]) { words[0] = words[0].trim() } for (const word of words) { const data = { event: 'message', messageId, signature, answer: word } const message = JSON.stringify(data) onUpdate(`data: ${message}\n\n`) await sleep(20) } const data = { event: 'message_end', messageId, signature } const message = JSON.stringify(data) onUpdate(`data: ${message}\n\n`) const row = await Score.create({ address, signature, scoreId: exist.scoreId, query: exist.query, answer: exist.answer, messageId, score: exist.score, scoreText: exist.scoreText, }) return row } try { const { answer, messageId } = await difyService.getCompletionMessagesByFetchAPI(payload) const [scoreText, score] = Score.getScore(answer) const row = await Score.create({ address, signature, scoreId, query, answer, messageId, score, scoreText, }) return row } catch (e) { if (e instanceof DifyRateLimitExceedError) { const { serveAt } = e const intime = Math.ceil((serveAt - Date.now()) / 1000) throw new Error( `Master is talking with other guys, please try after ${intime}s.` ) } throw e } } // console.log(Tweet.rawAttributes) let paginate: ( this: unknown, queryOptions: PaginateOptions ) => Promise> async function paginateScoreByOrder( after?: string, limit = 10 ): Promise> { if (!paginate) { paginate = makePaginate(Score) } const secondResult = await paginate({ order: [['id', 'DESC']], limit, after, }) const ret: PaginationConnection = { ...secondResult, edges: secondResult.edges.map((edge) => ({ cursor: edge.node.id, node: edge.node.getData(), })), } return ret } async function getScoreById(id: number): Promise { const row = await Score.findByPk(id) if (!row) { throw new Error('Score not found') } return row } const scoreService = { getCompletionMessages, paginateScoreByOrder, getScoreById, } export default scoreService