独立render模块,添加图片回复引用

This commit is contained in:
Alcedo 2023-02-27 17:23:32 +08:00
parent ced9ffae06
commit 1fb0b85aff
6 changed files with 85 additions and 6 deletions

View file

@ -5,7 +5,7 @@ import { v4 as uuid } from 'uuid'
import delay from 'delay'
import { ChatGPTAPI } from 'chatgpt'
import { ChatGPTClient, BingAIClient } from '@waylaidwanderer/chatgpt-api'
import { escapeHtml, getMessageById, makeForwardMsg, tryTimes, upsertMessage, randomString } from '../utils/common.js'
import { render, getMessageById, makeForwardMsg, tryTimes, upsertMessage, randomString } from '../utils/common.js'
import { ChatGPTPuppeteer } from '../utils/browser.js'
import { KeyvFile } from 'keyv-file'
import { OfficialChatGPTClient } from '../utils/message.js'
@ -527,7 +527,7 @@ export class chatgpt extends plugin {
}
}
}
await e.runtime.render('chatgpt-plugin', template, {
await e.reply(await render(e, 'chatgpt-plugin', template, {
content: new Buffer.from(content).toString('base64'),
prompt: new Buffer.from(prompt).toString('base64'),
senderName: e.sender.nickname,
@ -535,7 +535,7 @@ export class chatgpt extends plugin {
quotes: quote,
cache: cacheData,
version
})
},{retType: Config.quoteReply ? 'base64' : ''}), e.isGroup && Config.quoteReply)
}
async sendMessage (prompt, conversation = {}, use, e) {
@ -717,7 +717,7 @@ export class chatgpt extends plugin {
logger.mark('all conversations: ', conversations)
}
// let conversationsFirst10 = conversations.slice(0, 10)
await e.runtime.render('chatgpt-plugin', 'conversation/chatgpt', { conversations, version })
await render(e, 'chatgpt-plugin', 'conversation/chatgpt', { conversations, version })
let text = '对话列表\n'
text += '对话id | 对话发起者 \n'
conversations.forEach(c => {

View file

@ -1,5 +1,6 @@
import plugin from '../../../lib/plugins/plugin.js'
import { Config } from '../utils/config.js'
import { render } from '../utils/common.js'
let version = Config.version
let helpData = [
{
@ -131,6 +132,6 @@ export class help extends plugin {
}
async help (e) {
await e.runtime.render('chatgpt-plugin', 'help/index', { helpData, version })
await render(e, 'chatgpt-plugin', 'help/index', { helpData, version })
}
}

View file

@ -22,6 +22,8 @@ export default {
// conversationPreserveTime: 0,
// 触发方式 可选值at 或 prefix 。at模式下只有at机器人才会回复。prefix模式下不需要at但需要添加前缀#chat
// toggleMode: 'at',
// 是否在回复图片时引用原始消息
// quoteReply: true,
// 是否在图片模式中启用二维码。该对话内容将被发送至第三方服务器以进行渲染展示。改为false关闭该功能
// showQRCode: true,
// 图片内容渲染服务器API地址

View file

@ -87,6 +87,12 @@ export function supportGuoba() {
],
},
},
{
field: 'quoteReply',
label: '图片引用消息',
bottomHelpMessage: '在回复图片时引用原始消息',
component: 'Switch',
},
{
field: 'showQRCode',
label: '启用二维码',

View file

@ -4,6 +4,7 @@ import { exec } from 'child_process'
import lodash from 'lodash'
import fs from 'node:fs'
import path from 'node:path'
import puppeteer from '../../../lib/puppeteer/puppeteer.js'
// export function markdownToText (markdown) {
// return remark()
// .use(stripMarkdown)
@ -217,4 +218,72 @@ export function mkdirs (dirname) {
return true
}
}
}
}
/**
*
* @param pluginKey plugin key
* @param htmlPath html文件路径相对于plugin resources目录
* @param data 渲染数据
* @param renderCfg 渲染配置
* @param renderCfg.retType 返回值类型
* * default/true
* * msgId自动发送图片返回msg id
* * base64: 不自动发送图像返回图像base64数据
* @param renderCfg.beforeRender({data}) 可改写渲染的data数据
* @returns {Promise<boolean>}
*/
export async function render (e, pluginKey, htmlPath, data = {}, renderCfg = {}) {
// 处理传入的path
htmlPath = htmlPath.replace(/.html$/, '')
let paths = lodash.filter(htmlPath.split('/'), (p) => !!p)
htmlPath = paths.join('/')
// 创建目录
const mkdir = (check) => {
let currDir = `${process.cwd()}/data`
for (let p of check.split('/')) {
currDir = `${currDir}/${p}`
if (!fs.existsSync(currDir)) {
fs.mkdirSync(currDir)
}
}
return currDir
}
mkdir(`html/${pluginKey}/${htmlPath}`)
// 自动计算pluResPath
let pluResPath = `../../../${lodash.repeat('../', paths.length)}plugins/${pluginKey}/resources/`
// 渲染data
data = {
...data,
_plugin: pluginKey,
_htmlPath: htmlPath,
pluResPath,
tplFile: `./plugins/${pluginKey}/resources/${htmlPath}.html`,
saveId: data.saveId || data.save_id || paths[paths.length - 1],
pageGotoParams: {
waitUntil: 'networkidle0'
}
}
// 处理beforeRender
if (renderCfg.beforeRender) {
data = renderCfg.beforeRender({ data }) || data
}
// 保存模板数据
if (process.argv.includes('web-debug')) {
// debug下保存当前页面的渲染数据方便模板编写与调试
// 由于只用于调试开发者只关注自己当时开发的文件即可暂不考虑app及plugin的命名冲突
let saveDir = mkdir(`ViewData/${pluginKey}`)
let file = `${saveDir}/${data._htmlPath.split('/').join('_')}.json`
fs.writeFileSync(file, JSON.stringify(data))
}
// 截图
let base64 = await puppeteer.screenshot(`${pluginKey}/${htmlPath}`, data)
if (renderCfg.retType === 'base64') {
return base64
}
let ret = true
if (base64) {
ret = await e.reply(base64)
}
return renderCfg.retType === 'msgId' ? ret : true
}

View file

@ -9,6 +9,7 @@ const defaultConfig = {
autoUsePictureThreshold: 1200,
conversationPreserveTime: 0,
toggleMode: 'at',
quoteReply: true,
showQRCode: true,
cacheUrl: 'https://content.alcedogroup.com',
cacheEntry: false,