196 lines
4.6 KiB
TypeScript

import { SoupGameMessage } from "../../constant/message"
import { SoupGame } from "../../db/soupGame"
import { Context } from "../../types"
/**
* 开启或者停止游戏
* @param ctx
* @param value
*/
const startOrStopGame = async (
ctx: Context,
value: boolean,
which: "auto" | "manual" = "manual"
) => {
const {
db,
logger,
larkBody: { chatId },
attachService,
larkCard,
larkService: { message },
} = 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) {
// 没有进行中的游戏
if (!activeGame) {
await message.updateOrReply(
cardGender.genSuccessCard(SoupGameMessage.hasStopped)
)
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 message.updateOrReply(
cardGender.genErrorCard(SoupGameMessage.startFailed)
)
}
// 手动结束
if (which === "manual") {
await message.updateOrReply(
cardGender.genCard("markdownSuccessCard", {
content: `
游戏结束!
**汤面:**${activeGame?.query}
**汤底:**${activeGame?.answer}`,
})
)
} else {
// 自动结束
await message.updateOrReply(
cardGender.genCard("markdownSuccessCard", {
llmRes: `
恭喜您回答正确!游戏结束!
**汤面:**${activeGame?.query}
**汤底:**${activeGame?.answer}`,
})
)
}
return
}
// 开始游戏,有进行中的游戏
if (activeGame) {
logger.info(`chatId: ${chatId} has an active game`)
await message.updateOrReply(
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 message.updateOrReply(
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 message.updateOrReply(
cardGender.genErrorCard(SoupGameMessage.startFailed)
)
return
}
logger.info(`chatId: ${chatId} created a new game`)
// 回复用户模型的消息
await message.updateOrReply(
cardGender.genCard("markdownSuccessCard", {
content: `
游戏开始啦!
**题目:**${game.title}
**汤面:**${game.query}
艾特机器人说“结束游戏”即可结束游戏
`,
})
)
}
const chat2Soup = async (ctx: Context) => {
const {
db,
larkBody: { msgText, chatId, messageId },
logger,
attachService,
larkService: { message },
} = ctx
message.setReplyMessage(messageId, "text")
const activeGame = await db.soupGame.getActiveOneByChatId(chatId)
if (!activeGame) {
logger.info(`chatId: ${chatId} has no active game`)
return
}
await message.updateOrReply("模型生成中...")
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 message.updateOrReply(SoupGameMessage.chatFailed)
return
}
// 用户答对了
if (res.type === "END") {
await startOrStopGame(ctx, false, "auto")
return
}
// 继续游戏,更新历史记录
await db.soupGame.overrideHistory(activeGame.id, [
...activeGame.history,
msgText,
])
// 回复用户模型的消息
await message.updateOrReply(res.content)
}
/**
* 海龟汤游戏
* @param ctx
*/
const agent = async (ctx: Context) => {
const {
larkBody: { chatId, msgText },
db,
} = ctx
if (!chatId) return
const activeGame = await db.soupGame.getActiveOneByChatId(chatId)
if (!activeGame) return false
if (msgText === "结束游戏" || msgText === "停止游戏") {
startOrStopGame(ctx, false)
return true
}
chat2Soup(ctx)
return true
}
const soupAgent = {
startOrStopGame,
agent,
}
export default soupAgent