koishi-plugin-jrys-prpr
Version:
[<ruby>**jrys-prpr**<rp>(</rp><rt>点我查看预览图</rt><rp>)</rp></ruby>](https://i0.hdslb.com/bfs/article/ae33f1b2e9dbc3fe89363a40fbf040703493298333289018.png)😽QQ官方json按钮支持,20个群即可发按钮!支持 monetary!很好看的字体! 支持自动清理记录内容。
148 lines (130 loc) • 6.12 kB
text/typescript
import { Context, h } from 'koishi'
import type { Config } from '../types'
import { getRandomBackground } from '../utils/background'
import { getJrys } from '../utils/jrys'
import { alreadySignedInToday, recordSignIn, updateUserCurrency } from '../utils/database'
import { convertToBase64image } from '../utils/image'
import { generateFortuneHTML, getImageBuffer } from '../utils/render'
import { sendImageMessage } from '../utils/message-sender'
/**
* 注册今日运势主命令
*/
export function registerJrysCommand(
ctx: Context,
config: Config,
jsonFilePath: string,
retryCounts: Record<string, number>,
logInfo: (...args: any[]) => void
) {
ctx.command(`${config.command}`, { authority: 1 })
.userFields(["id"])
.option('split', '-s 以图文输出今日运势')
.action(async ({ session, options }) => {
let hasSignedInToday = await alreadySignedInToday(ctx, session.userId, session.channelId, config)
retryCounts[session.userId] = retryCounts[session.userId] || 0 // 初始化重试次数
let Checkin_HintText_messageid: any
let backgroundImage = getRandomBackground(config)
let BackgroundURL = backgroundImage.replace(/\\/g, '/')
let imageBuffer: Buffer
const dJson = await getJrys(session, config, logInfo)
if (options.split) {
// 如果开启了分离模式,那就只返回图文消息内容。即文字运势内容与背景图片
if (config.Checkin_HintText && config.Checkin_HintText !== 'unset') {
Checkin_HintText_messageid = await session.send(config.Checkin_HintText)
}
let textjrys = `
${dJson.fortuneSummary}
${dJson.luckyStar}\n
${dJson.signText}\n
${dJson.unsignText}\n
`
let enablecurrencymessage: any
if (config.enablecurrency) {
if (hasSignedInToday) {
enablecurrencymessage = h.text(session.text(".hasSignedInTodaysplit"))
} else {
enablecurrencymessage = h.text(session.text(".CurrencyGetbackgroundimagesplit", [config.maintenanceCostPerUnit]))
}
}
let backgroundImage = getRandomBackground(config)
let BackgroundURL = backgroundImage.replace(/\\/g, '/')
let BackgroundURL_base64 = await convertToBase64image(ctx, BackgroundURL, logInfo)
let message = [
h.image(BackgroundURL_base64),
h.text(textjrys),
enablecurrencymessage
]
if (config.enablecurrency && !hasSignedInToday) {
await updateUserCurrency(ctx, String(session.user.id), config.maintenanceCostPerUnit, config.currency, logInfo)
}
await recordSignIn(ctx, session.userId, session.channelId)
await session.send(message)
if (Checkin_HintText_messageid && config.recallCheckin_HintText) {
await session.bot.deleteMessage(session.channelId, Checkin_HintText_messageid)
}
return
}
if (config.Checkin_HintText && config.Checkin_HintText !== 'unset') {
Checkin_HintText_messageid = await session.send(config.Checkin_HintText)
}
let page: any
try {
if (config.markdown_button_mode !== "raw_jrys") {
page = await ctx.puppeteer.page()
await page.setViewport({ width: 1080, height: 1920 })
let BackgroundURL_base64 = await convertToBase64image(ctx, BackgroundURL, logInfo)
// 生成 HTML
const HTMLsource = await generateFortuneHTML(ctx, session, config, dJson, BackgroundURL_base64, logInfo)
logInfo(`使用背景URL: ${BackgroundURL}`)
await page.setContent(HTMLsource)
// 等待网络空闲
await page.waitForNetworkIdle()
const element = await page.$('body')
imageBuffer = await element.screenshot({
type: "jpeg", // 使用 JPEG 格式
encoding: "binary",
quality: config.screenshotquality // 设置图片质量
})
} else {
imageBuffer = await getImageBuffer(ctx, BackgroundURL)
}
if (config.enablecurrency && !hasSignedInToday) {
await updateUserCurrency(ctx, String(session.user.id), config.maintenanceCostPerUnit, config.currency, logInfo)
}
// 发送图片消息
await sendImageMessage(ctx, session, config, imageBuffer, BackgroundURL, hasSignedInToday, jsonFilePath, logInfo)
if (config.markdown_button_mode !== "raw_jrys") {
await recordSignIn(ctx, session.userId, session.channelId)
}
if (Checkin_HintText_messageid && config.recallCheckin_HintText) {
await session.bot.deleteMessage(session.channelId, Checkin_HintText_messageid)
}
} catch (e) {
const errorTime = new Date().toISOString() // 获取错误发生时间的ISO格式
ctx.logger.error(`状态渲染失败 [${errorTime}]: `, e) // 记录错误信息并包含时间戳
if (config.retryexecute && retryCounts[session.userId] < config.maxretrytimes) {
retryCounts[session.userId]++
ctx.logger.warn(`用户 ${session.userId} 尝试第 ${retryCounts[session.userId]} 次重试...`)
try {
await session.execute(config.command) // 使用 session.execute 重试
delete retryCounts[session.userId] // 执行成功,删除重试次数
return // 阻止发送错误消息,因为我们正在重试
} catch (retryError) {
ctx.logger.error(`重试失败 [${errorTime}]: `, retryError)
// 重试失败,继续执行错误处理
}
}
// 如果达到最大重试次数或未启用重试,则发送错误消息
delete retryCounts[session.userId] // 清理重试次数
return "渲染失败 " + e.message + '\n' + e.stack
} finally {
if (page && !page.isClosed()) {
page.close()
}
// 仅在成功或达到最大重试后清理
if (!config.retryexecute || retryCounts[session.userId] >= config.maxretrytimes) {
delete retryCounts[session.userId]
}
}
})
}