209 lines
5.2 KiB
TypeScript
209 lines
5.2 KiB
TypeScript
import { SoupGameMessage } from "../../constant/message"
|
||
import db from "../../db"
|
||
import { SoupGame } from "../../db/soupGame"
|
||
import { Context } from "../../types"
|
||
import { isP2POrAtBot } from "../../utils/message"
|
||
|
||
/**
|
||
* 开启或者停止游戏
|
||
* @param ctx
|
||
* @param value
|
||
*/
|
||
const startOrStopGame = async (
|
||
ctx: Context,
|
||
value: boolean,
|
||
which: "auto" | "manual" = "manual"
|
||
) => {
|
||
const {
|
||
logger,
|
||
larkBody: { chatId, messageId },
|
||
attachService,
|
||
larkCard,
|
||
larkService,
|
||
} = ctx
|
||
const cardGender = larkCard.child("soupAgent")
|
||
if (!chatId) {
|
||
logger.error("chatId is required")
|
||
return
|
||
}
|
||
// 获取正在进行中的游戏
|
||
const activeGame = await db.soupGame.getActiveOneByChatId(chatId)
|
||
if (!activeGame) {
|
||
logger.info(`chatId: ${chatId} has no active game`)
|
||
}
|
||
// 停止游戏
|
||
if (!value) {
|
||
// 没有进行中的游戏,是私聊或者at机器人,回复停止游戏
|
||
if (!activeGame && isP2POrAtBot(ctx)) {
|
||
await larkService.message.replyCard(
|
||
messageId,
|
||
cardGender.genSuccessCard(SoupGameMessage.hasStopped)
|
||
)
|
||
return
|
||
}
|
||
// 没有进行中的游戏,且是正常对话,不响应
|
||
if (!activeGame) return
|
||
// 有进行中的游戏,关闭游戏
|
||
logger.info(`chatId: ${chatId} is closing the game`)
|
||
const res = await db.soupGame.close(activeGame.id)
|
||
if (!res) {
|
||
logger.error(`chatId: ${chatId} failed to close the game`)
|
||
await larkService.message.replyCard(
|
||
messageId,
|
||
cardGender.genErrorCard(SoupGameMessage.startFailed)
|
||
)
|
||
}
|
||
// 手动结束
|
||
if (which === "manual") {
|
||
await larkService.message.replyCard(
|
||
messageId,
|
||
cardGender.genCard("markdownSuccessCard", {
|
||
content: `
|
||
游戏结束!
|
||
|
||
**汤面:**${activeGame?.query}
|
||
|
||
**汤底:**${activeGame?.answer}`,
|
||
})
|
||
)
|
||
} else {
|
||
// 自动结束
|
||
await larkService.message.replyCard(
|
||
messageId,
|
||
cardGender.genCard("markdownSuccessCard", {
|
||
llmRes: `
|
||
恭喜您回答正确!游戏结束!
|
||
|
||
**汤面:**${activeGame?.query}
|
||
|
||
**汤底:**${activeGame?.answer}`,
|
||
})
|
||
)
|
||
}
|
||
return
|
||
}
|
||
|
||
// 开始游戏,有进行中的游戏
|
||
if (activeGame) {
|
||
logger.info(`chatId: ${chatId} has an active game`)
|
||
await larkService.message.replyCard(
|
||
messageId,
|
||
cardGender.genSuccessCard(SoupGameMessage.hasStarted)
|
||
)
|
||
return
|
||
}
|
||
logger.info(`chatId: ${chatId} is starting a new game`)
|
||
// 没有进行中的游戏,开始新游戏
|
||
const game = await attachService.startSoup()
|
||
if (!game) {
|
||
logger.error(`chatId: ${chatId} failed to start a new game`)
|
||
await larkService.message.replyCard(
|
||
messageId,
|
||
cardGender.genErrorCard(SoupGameMessage.startFailed)
|
||
)
|
||
return
|
||
}
|
||
// 写到数据库
|
||
const newSoupGame: SoupGame = {
|
||
...game,
|
||
chatId,
|
||
history: [],
|
||
active: true,
|
||
}
|
||
const res = await db.soupGame.create(newSoupGame)
|
||
if (!res) {
|
||
logger.error(`chatId: ${chatId} failed to create a new game`)
|
||
await larkService.message.replyCard(
|
||
messageId,
|
||
cardGender.genErrorCard(SoupGameMessage.startFailed)
|
||
)
|
||
return
|
||
}
|
||
logger.info(`chatId: ${chatId} created a new game`)
|
||
// 回复用户模型的消息
|
||
await larkService.message.replyCard(
|
||
messageId,
|
||
cardGender.genCard("markdownSuccessCard", {
|
||
content: `
|
||
游戏开始啦!
|
||
|
||
**题目:**${game.title}
|
||
|
||
**汤面:**${game.query}
|
||
|
||
艾特机器人说“结束游戏”即可结束游戏
|
||
`,
|
||
})
|
||
)
|
||
}
|
||
|
||
const chat2Soup = async (ctx: Context) => {
|
||
const {
|
||
larkBody: { msgText, chatId, messageId },
|
||
logger,
|
||
attachService,
|
||
larkCard,
|
||
larkService,
|
||
} = ctx
|
||
const cardGender = larkCard.child("soupAgent")
|
||
const activeGame = await db.soupGame.getActiveOneByChatId(chatId)
|
||
if (!activeGame) {
|
||
logger.info(`chatId: ${chatId} has no active game`)
|
||
return
|
||
}
|
||
const {
|
||
data: { message_id },
|
||
} = await larkService.message.reply(messageId, "text", "模型生成中...")
|
||
|
||
const res = await attachService.chat2Soup({
|
||
user_query: msgText,
|
||
soup_id: activeGame.title,
|
||
history: "",
|
||
})
|
||
if (!res) {
|
||
logger.error(`chatId: ${chatId} failed to get soup result`)
|
||
await larkService.message.replyCard(
|
||
messageId,
|
||
cardGender.genErrorCard(SoupGameMessage.chatFailed)
|
||
)
|
||
return
|
||
}
|
||
// 用户答对了
|
||
if (res.type === "END") {
|
||
await startOrStopGame(ctx, false, "auto")
|
||
return
|
||
}
|
||
// 继续游戏,更新历史记录
|
||
await db.soupGame.insertHistory(activeGame.id, [
|
||
...activeGame.history,
|
||
msgText,
|
||
])
|
||
// 回复用户模型的消息
|
||
await larkService.message.update(message_id, res.content, true)
|
||
}
|
||
|
||
/**
|
||
* 海龟汤游戏
|
||
* @param ctx
|
||
*/
|
||
const soupAgent = async (ctx: Context) => {
|
||
const {
|
||
larkBody: { msgText, chatId },
|
||
} = ctx
|
||
if (!chatId) return
|
||
if (msgText === "开始游戏" && isP2POrAtBot(ctx)) {
|
||
startOrStopGame(ctx, true)
|
||
return true
|
||
}
|
||
if (msgText === "结束游戏" || msgText === "停止游戏") {
|
||
startOrStopGame(ctx, false)
|
||
return true
|
||
}
|
||
const activeGame = await db.soupGame.getActiveOneByChatId(chatId)
|
||
if (!activeGame) return false
|
||
chat2Soup(ctx)
|
||
return true
|
||
}
|
||
|
||
export default soupAgent
|