mirror of
https://github.com/ikechan8370/chatgpt-plugin.git
synced 2025-12-16 13:27:08 +00:00
去除bard
This commit is contained in:
parent
d111d2625e
commit
8efcce45a0
8 changed files with 4 additions and 517 deletions
13
apps/chat.js
13
apps/chat.js
|
|
@ -735,10 +735,6 @@ export class chatgpt extends plugin {
|
||||||
key = `CHATGPT:CONVERSATIONS_XH:${(e.isGroup && Config.groupMerge) ? e.group_id.toString() : e.sender.user_id}`
|
key = `CHATGPT:CONVERSATIONS_XH:${(e.isGroup && Config.groupMerge) ? e.group_id.toString() : e.sender.user_id}`
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
case 'bard': {
|
|
||||||
key = `CHATGPT:CONVERSATIONS_BARD:${(e.isGroup && Config.groupMerge) ? e.group_id.toString() : e.sender.user_id}`
|
|
||||||
break
|
|
||||||
}
|
|
||||||
case 'azure': {
|
case 'azure': {
|
||||||
key = `CHATGPT:CONVERSATIONS_AZURE:${e.sender.user_id}`
|
key = `CHATGPT:CONVERSATIONS_AZURE:${e.sender.user_id}`
|
||||||
break
|
break
|
||||||
|
|
@ -797,8 +793,8 @@ export class chatgpt extends plugin {
|
||||||
if (chatMessage?.noMsg) {
|
if (chatMessage?.noMsg) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
// 处理星火和bard图片
|
// 处理星火图片
|
||||||
if ((use === 'bard' || use === 'xh') && chatMessage?.images) {
|
if (use === 'xh' && chatMessage?.images) {
|
||||||
chatMessage.images.forEach(element => {
|
chatMessage.images.forEach(element => {
|
||||||
this.reply([element.tag, segment.image(element.url)])
|
this.reply([element.tag, segment.image(element.url)])
|
||||||
})
|
})
|
||||||
|
|
@ -826,11 +822,6 @@ export class chatgpt extends plugin {
|
||||||
}
|
}
|
||||||
previousConversation.messages.push(chatMessage.message)
|
previousConversation.messages.push(chatMessage.message)
|
||||||
}
|
}
|
||||||
if (use === 'bard' && !chatMessage.error) {
|
|
||||||
previousConversation.parentMessageId = chatMessage.responseID
|
|
||||||
previousConversation.clientId = chatMessage.choiceID
|
|
||||||
previousConversation.invocationId = chatMessage._reqID
|
|
||||||
}
|
|
||||||
if (Config.debug) {
|
if (Config.debug) {
|
||||||
logger.info(chatMessage)
|
logger.info(chatMessage)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -123,11 +123,6 @@ export class ChatgptManagement extends plugin {
|
||||||
fnc: 'useAzureBasedSolution',
|
fnc: 'useAzureBasedSolution',
|
||||||
permission: 'master'
|
permission: 'master'
|
||||||
},
|
},
|
||||||
{
|
|
||||||
reg: '^#chatgpt切换(Bard|bard)$',
|
|
||||||
fnc: 'useBardBasedSolution',
|
|
||||||
permission: 'master'
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
reg: '^#chatgpt切换(通义千问|qwen|千问)$',
|
reg: '^#chatgpt切换(通义千问|qwen|千问)$',
|
||||||
fnc: 'useQwenSolution',
|
fnc: 'useQwenSolution',
|
||||||
|
|
@ -968,16 +963,6 @@ azure语音:Azure 语音是微软 Azure 平台提供的一项语音服务,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async useBardBasedSolution () {
|
|
||||||
let use = await redis.get('CHATGPT:USE')
|
|
||||||
if (use !== 'bard') {
|
|
||||||
await redis.set('CHATGPT:USE', 'bard')
|
|
||||||
await this.reply('已切换到基于Bard的解决方案')
|
|
||||||
} else {
|
|
||||||
await this.reply('当前已经是Bard模式了')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async patchGemini () {
|
async patchGemini () {
|
||||||
const _path = process.cwd()
|
const _path = process.cwd()
|
||||||
let packageJson = fs.readFileSync(`${_path}/package.json`)
|
let packageJson = fs.readFileSync(`${_path}/package.json`)
|
||||||
|
|
|
||||||
|
|
@ -531,28 +531,6 @@ export function supportGuoba () {
|
||||||
bottomHelpMessage: '替换回复内容中的文本',
|
bottomHelpMessage: '替换回复内容中的文本',
|
||||||
component: 'Input'
|
component: 'Input'
|
||||||
},
|
},
|
||||||
{
|
|
||||||
label: '以下为Bard方式的配置',
|
|
||||||
component: 'Divider'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
field: 'bardPsid',
|
|
||||||
label: 'BardCookie',
|
|
||||||
bottomHelpMessage: '获取https://bard.google.com/页面的cookie,可完整输入,需至少包含__Secure-1PSID和__Secure-1PSIDTS',
|
|
||||||
component: 'Input'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
field: 'bardReverseProxy',
|
|
||||||
label: 'Bard反代地址',
|
|
||||||
bottomHelpMessage: 'bard反代服务器地址,用于绕过地区限制',
|
|
||||||
component: 'Input'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
field: 'bardForceUseReverse',
|
|
||||||
label: 'Bard使用反代',
|
|
||||||
bottomHelpMessage: '开启后将通过反代访问bard',
|
|
||||||
component: 'Switch'
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
label: '以下为通义千问API方式的配置',
|
label: '以下为通义千问API方式的配置',
|
||||||
component: 'Divider'
|
component: 'Divider'
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,8 @@ import { Config } from '../utils/config.js'
|
||||||
import { KeyvFile } from 'keyv-file'
|
import { KeyvFile } from 'keyv-file'
|
||||||
import _ from 'lodash'
|
import _ from 'lodash'
|
||||||
|
|
||||||
export const originalValues = ['星火', '通义千问', '克劳德', '克劳德2', '必应', 'api', 'API', 'api3', 'API3', 'glm', '巴德', '双子星', '双子座', '智谱']
|
export const originalValues = ['星火', '通义千问', '克劳德', '克劳德2', '必应', 'api', 'API', 'api3', 'API3', 'glm', '双子星', '双子座', '智谱']
|
||||||
export const correspondingValues = ['xh', 'qwen', 'claude', 'claude2', 'bing', 'api', 'api', 'api3', 'api3', 'chatglm', 'bard', 'gemini', 'gemini', 'chatglm4']
|
export const correspondingValues = ['xh', 'qwen', 'claude', 'claude2', 'bing', 'api', 'api', 'api3', 'api3', 'chatglm', 'gemini', 'gemini', 'chatglm4']
|
||||||
|
|
||||||
export class ConversationManager {
|
export class ConversationManager {
|
||||||
async endConversation (e) {
|
async endConversation (e) {
|
||||||
|
|
@ -35,11 +35,6 @@ export class ConversationManager {
|
||||||
await this.reply('星火对话已结束')
|
await this.reply('星火对话已结束')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (use === 'bard') {
|
|
||||||
await redis.del(`CHATGPT:CONVERSATIONS_BARD:${(e.isGroup && Config.groupMerge) ? e.group_id.toString() : e.sender.user_id}`)
|
|
||||||
await this.reply('Bard对话已结束')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
let ats = e.message.filter(m => m.type === 'at')
|
let ats = e.message.filter(m => m.type === 'at')
|
||||||
const isAtMode = Config.toggleMode === 'at'
|
const isAtMode = Config.toggleMode === 'at'
|
||||||
if (isAtMode) ats = ats.filter(item => item.qq !== getUin(e))
|
if (isAtMode) ats = ats.filter(item => item.qq !== getUin(e))
|
||||||
|
|
@ -259,17 +254,6 @@ export class ConversationManager {
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
case 'bard': {
|
|
||||||
let cs = await redis.keys('CHATGPT:CONVERSATIONS_BARD:*')
|
|
||||||
for (let i = 0; i < cs.length; i++) {
|
|
||||||
await redis.del(cs[i])
|
|
||||||
if (Config.debug) {
|
|
||||||
logger.info('delete bard conversation of qq: ' + cs[i])
|
|
||||||
}
|
|
||||||
deleted++
|
|
||||||
}
|
|
||||||
break
|
|
||||||
}
|
|
||||||
case 'bing': {
|
case 'bing': {
|
||||||
let cs = await redis.keys('CHATGPT:CONVERSATIONS_BING:*')
|
let cs = await redis.keys('CHATGPT:CONVERSATIONS_BING:*')
|
||||||
let we = await redis.keys('CHATGPT:WRONG_EMOTION:*')
|
let we = await redis.keys('CHATGPT:WRONG_EMOTION:*')
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,6 @@ import XinghuoClient from '../utils/xinghuo/xinghuo.js'
|
||||||
import { getMessageById, upsertMessage } from '../utils/history.js'
|
import { getMessageById, upsertMessage } from '../utils/history.js'
|
||||||
import { v4 as uuid } from 'uuid'
|
import { v4 as uuid } from 'uuid'
|
||||||
import fetch from 'node-fetch'
|
import fetch from 'node-fetch'
|
||||||
import Bard from '../utils/bard.js'
|
|
||||||
import { CustomGoogleGeminiClient } from '../client/CustomGoogleGeminiClient.js'
|
import { CustomGoogleGeminiClient } from '../client/CustomGoogleGeminiClient.js'
|
||||||
import { resizeAndCropImage } from '../utils/dalle.js'
|
import { resizeAndCropImage } from '../utils/dalle.js'
|
||||||
import fs from 'fs'
|
import fs from 'fs'
|
||||||
|
|
@ -706,55 +705,6 @@ class Core {
|
||||||
}
|
}
|
||||||
return msg
|
return msg
|
||||||
}
|
}
|
||||||
} else if (use === 'bard') {
|
|
||||||
// 处理cookie
|
|
||||||
const matchesPSID = /__Secure-1PSID=([^;]+)/.exec(Config.bardPsid)
|
|
||||||
const matchesPSIDTS = /__Secure-1PSIDTS=([^;]+)/.exec(Config.bardPsid)
|
|
||||||
const cookie = {
|
|
||||||
'__Secure-1PSID': matchesPSID[1],
|
|
||||||
'__Secure-1PSIDTS': matchesPSIDTS[1]
|
|
||||||
}
|
|
||||||
if (!matchesPSID[1] || !matchesPSIDTS[1]) {
|
|
||||||
throw new Error('未绑定bard')
|
|
||||||
}
|
|
||||||
// 处理图片
|
|
||||||
const image = await getImg(e)
|
|
||||||
let imageBuff
|
|
||||||
if (image) {
|
|
||||||
try {
|
|
||||||
let imgResponse = await fetch(image[0])
|
|
||||||
if (imgResponse.ok) {
|
|
||||||
imageBuff = await imgResponse.arrayBuffer()
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
logger.warn(`错误的图片链接${image[0]}`)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 发送数据
|
|
||||||
let bot = new Bard(cookie, {
|
|
||||||
fetch,
|
|
||||||
bardURL: Config.bardForceUseReverse ? Config.bardReverseProxy : 'https://bard.google.com'
|
|
||||||
})
|
|
||||||
let chat = await bot.createChat(conversation?.conversationId
|
|
||||||
? {
|
|
||||||
conversationID: conversation.conversationId,
|
|
||||||
responseID: conversation.parentMessageId,
|
|
||||||
choiceID: conversation.clientId,
|
|
||||||
_reqID: conversation.invocationId
|
|
||||||
}
|
|
||||||
: {})
|
|
||||||
let response = await chat.ask(prompt, {
|
|
||||||
image: imageBuff,
|
|
||||||
format: Bard.JSON
|
|
||||||
})
|
|
||||||
return {
|
|
||||||
conversationId: response.ids.conversationID,
|
|
||||||
responseID: response.ids.responseID,
|
|
||||||
choiceID: response.ids.choiceID,
|
|
||||||
_reqID: response.ids._reqID,
|
|
||||||
text: response.content,
|
|
||||||
images: response.images
|
|
||||||
}
|
|
||||||
} else if (use === 'gemini') {
|
} else if (use === 'gemini') {
|
||||||
let client = new CustomGoogleGeminiClient({
|
let client = new CustomGoogleGeminiClient({
|
||||||
e,
|
e,
|
||||||
|
|
|
||||||
|
|
@ -81,10 +81,6 @@
|
||||||
"label": "Azure OpenAI",
|
"label": "Azure OpenAI",
|
||||||
"value": "azure"
|
"value": "azure"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"label": "Bard",
|
|
||||||
"value": "bard"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"label": "ChatGPT API3",
|
"label": "ChatGPT API3",
|
||||||
"value": "api3"
|
"value": "api3"
|
||||||
|
|
@ -819,27 +815,6 @@
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"title": "Bard",
|
|
||||||
"tab": "bard",
|
|
||||||
"view": [
|
|
||||||
{
|
|
||||||
"type": "password",
|
|
||||||
"label": "BardCookie",
|
|
||||||
"data": "bardPsid"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "url",
|
|
||||||
"label": "Bard反代地址",
|
|
||||||
"data": "bardReverseProxy"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "check",
|
|
||||||
"label": "使用Bard反代",
|
|
||||||
"data": "bardForceUseReverse"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"title": "通义千问",
|
"title": "通义千问",
|
||||||
"tab": "qwen",
|
"tab": "qwen",
|
||||||
|
|
|
||||||
373
utils/bard.js
373
utils/bard.js
|
|
@ -1,373 +0,0 @@
|
||||||
// https://github.com/EvanZhouDev/bard-ai
|
|
||||||
|
|
||||||
class Bard {
|
|
||||||
static JSON = 'json'
|
|
||||||
static MD = 'markdown'
|
|
||||||
|
|
||||||
// ID derived from Cookie
|
|
||||||
SNlM0e
|
|
||||||
|
|
||||||
// HTTPS Headers
|
|
||||||
#headers
|
|
||||||
|
|
||||||
// Resolution status of initialization call
|
|
||||||
#initPromise
|
|
||||||
|
|
||||||
#bardURL = 'https://bard.google.com'
|
|
||||||
|
|
||||||
// Wether or not to log events to console
|
|
||||||
#verbose = false
|
|
||||||
|
|
||||||
// Fetch function
|
|
||||||
#fetch = fetch
|
|
||||||
|
|
||||||
constructor (cookie, config) {
|
|
||||||
// Register some settings
|
|
||||||
if (config?.verbose == true) this.#verbose = true
|
|
||||||
if (config?.fetch) this.#fetch = config.fetch
|
|
||||||
// 可变更访问地址,利用反向代理绕过区域限制
|
|
||||||
if (config?.bardURL) this.#bardURL = config.bardURL
|
|
||||||
|
|
||||||
// If a Cookie is provided, initialize
|
|
||||||
if (cookie) {
|
|
||||||
this.#initPromise = this.#init(cookie)
|
|
||||||
} else {
|
|
||||||
throw new Error('Please provide a Cookie when initializing Bard.')
|
|
||||||
}
|
|
||||||
this.cookie = cookie
|
|
||||||
}
|
|
||||||
|
|
||||||
// You can also choose to initialize manually
|
|
||||||
async #init (cookie) {
|
|
||||||
this.#verbose && console.log('🚀 Starting intialization')
|
|
||||||
// Assign headers
|
|
||||||
this.#headers = {
|
|
||||||
Host: this.#bardURL.match(/^https?:\/\/([^\/]+)\/?$/)[1],
|
|
||||||
'X-Same-Domain': '1',
|
|
||||||
'User-Agent':
|
|
||||||
'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36',
|
|
||||||
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
|
|
||||||
Origin: this.#bardURL,
|
|
||||||
Referer: this.#bardURL,
|
|
||||||
Cookie: (typeof cookie === 'object') ? (Object.entries(cookie).map(([key, val]) => `${key}=${val};`).join('')) : ('__Secure-1PSID=' + cookie)
|
|
||||||
}
|
|
||||||
|
|
||||||
let responseText
|
|
||||||
// Attempt to retrieve SNlM0e
|
|
||||||
try {
|
|
||||||
this.#verbose &&
|
|
||||||
console.log('🔒 Authenticating your Google account')
|
|
||||||
responseText = await this.#fetch(this.#bardURL, {
|
|
||||||
method: 'GET',
|
|
||||||
headers: this.#headers,
|
|
||||||
credentials: 'include'
|
|
||||||
})
|
|
||||||
.then((response) => response.text())
|
|
||||||
} catch (e) {
|
|
||||||
// Failure to get server
|
|
||||||
throw new Error(
|
|
||||||
'Could not fetch Google Bard. You may be disconnected from internet: ' +
|
|
||||||
e
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const SNlM0e = responseText.match(/SNlM0e":"(.*?)"/)[1]
|
|
||||||
// Assign SNlM0e and return it
|
|
||||||
this.SNlM0e = SNlM0e
|
|
||||||
this.#verbose && console.log('✅ Initialization finished\n')
|
|
||||||
return SNlM0e
|
|
||||||
} catch {
|
|
||||||
throw new Error(
|
|
||||||
'Could not use your Cookie. Make sure that you copied correctly the Cookie with name __Secure-1PSID exactly. If you are sure your cookie is correct, you may also have reached your rate limit.'
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async #uploadImage (name, buffer) {
|
|
||||||
this.#verbose && console.log('🖼️ Starting image processing')
|
|
||||||
let size = buffer.byteLength
|
|
||||||
let formBody = [
|
|
||||||
`${encodeURIComponent('File name')}=${encodeURIComponent([name])}`
|
|
||||||
]
|
|
||||||
|
|
||||||
try {
|
|
||||||
this.#verbose &&
|
|
||||||
console.log('💻 Finding Google server destination')
|
|
||||||
let response = await this.#fetch(
|
|
||||||
'https://content-push.googleapis.com/upload/',
|
|
||||||
{
|
|
||||||
method: 'POST',
|
|
||||||
headers: {
|
|
||||||
'X-Goog-Upload-Command': 'start',
|
|
||||||
'X-Goog-Upload-Protocol': 'resumable',
|
|
||||||
'X-Goog-Upload-Header-Content-Length': size,
|
|
||||||
'X-Tenant-Id': 'bard-storage',
|
|
||||||
'Push-Id': 'feeds/mcudyrk2a4khkz'
|
|
||||||
},
|
|
||||||
body: formBody,
|
|
||||||
credentials: 'include'
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
const uploadUrl = response.headers.get('X-Goog-Upload-URL')
|
|
||||||
this.#verbose && console.log('📤 Sending your image')
|
|
||||||
response = await this.#fetch(uploadUrl, {
|
|
||||||
method: 'POST',
|
|
||||||
headers: {
|
|
||||||
'X-Goog-Upload-Command': 'upload, finalize',
|
|
||||||
'X-Goog-Upload-Offset': 0,
|
|
||||||
'X-Tenant-Id': 'bard-storage'
|
|
||||||
},
|
|
||||||
body: buffer,
|
|
||||||
credentials: 'include'
|
|
||||||
})
|
|
||||||
|
|
||||||
const imageFileLocation = await response.text()
|
|
||||||
|
|
||||||
this.#verbose && console.log('✅ Image finished working\n')
|
|
||||||
return imageFileLocation
|
|
||||||
} catch (e) {
|
|
||||||
throw new Error(
|
|
||||||
'Could not fetch Google Bard. You may be disconnected from internet: ' +
|
|
||||||
e
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Query Bard
|
|
||||||
async #query (message, config) {
|
|
||||||
let formatMarkdown = (text, images) => {
|
|
||||||
if (!images) return text
|
|
||||||
|
|
||||||
for (let imageData of images) {
|
|
||||||
const formattedTag = `!${imageData.tag}(${imageData.url})`
|
|
||||||
text = text.replace(
|
|
||||||
new RegExp(`(?!\\!)\\[${imageData.tag.slice(1, -1)}\\]`),
|
|
||||||
formattedTag
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return text
|
|
||||||
}
|
|
||||||
|
|
||||||
let { ids, imageBuffer } = config
|
|
||||||
|
|
||||||
// Wait until after init
|
|
||||||
await this.#initPromise
|
|
||||||
|
|
||||||
this.#verbose && console.log('🔎 Starting Bard Query')
|
|
||||||
|
|
||||||
// If user has not run init
|
|
||||||
if (!this.SNlM0e) {
|
|
||||||
throw new Error(
|
|
||||||
"Please initialize Bard first. If you haven't passed in your Cookie into the class, run Bard.init(cookie)."
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
this.#verbose && console.log('🏗️ Building Request')
|
|
||||||
// HTTPS parameters
|
|
||||||
const params = {
|
|
||||||
bl: 'boq_assistant-bard-web-server_20230711.08_p0',
|
|
||||||
_reqID: ids?._reqID ?? '0',
|
|
||||||
rt: 'c'
|
|
||||||
}
|
|
||||||
|
|
||||||
// If IDs are provided, but doesn't have every one of the expected IDs, error
|
|
||||||
const messageStruct = [
|
|
||||||
[message],
|
|
||||||
null,
|
|
||||||
[null, null, null]
|
|
||||||
]
|
|
||||||
|
|
||||||
if (imageBuffer) {
|
|
||||||
let imageLocation = await this.#uploadImage(
|
|
||||||
'bard-ai_upload',
|
|
||||||
imageBuffer
|
|
||||||
)
|
|
||||||
messageStruct[0].push(0, null, [
|
|
||||||
[[imageLocation, 1], 'bard-ai_upload']
|
|
||||||
])
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ids) {
|
|
||||||
const { conversationID, responseID, choiceID } = ids
|
|
||||||
messageStruct[2] = [conversationID, responseID, choiceID]
|
|
||||||
}
|
|
||||||
|
|
||||||
// HTTPs data
|
|
||||||
const data = {
|
|
||||||
'f.req': JSON.stringify([null, JSON.stringify(messageStruct)]),
|
|
||||||
at: this.SNlM0e
|
|
||||||
}
|
|
||||||
|
|
||||||
// URL that we are submitting to
|
|
||||||
const url = new URL(
|
|
||||||
'/_/BardChatUi/data/assistant.lamda.BardFrontendService/StreamGenerate',
|
|
||||||
this.#bardURL
|
|
||||||
)
|
|
||||||
|
|
||||||
// Append parameters to the URL
|
|
||||||
for (const key in params) {
|
|
||||||
url.searchParams.append(key, params[key])
|
|
||||||
}
|
|
||||||
|
|
||||||
// Encode the data
|
|
||||||
const formBody = Object.entries(data)
|
|
||||||
.map(
|
|
||||||
([property, value]) =>
|
|
||||||
`${encodeURIComponent(property)}=${encodeURIComponent(
|
|
||||||
value
|
|
||||||
)}`
|
|
||||||
)
|
|
||||||
.join('&')
|
|
||||||
|
|
||||||
this.#verbose && console.log('💭 Sending message to Bard')
|
|
||||||
// Send the fetch request
|
|
||||||
const chatData = await this.#fetch(url.toString(), {
|
|
||||||
method: 'POST',
|
|
||||||
headers: this.#headers,
|
|
||||||
body: formBody,
|
|
||||||
credentials: 'include'
|
|
||||||
})
|
|
||||||
.then((response) => {
|
|
||||||
return response.text()
|
|
||||||
})
|
|
||||||
.then((text) => {
|
|
||||||
return JSON.parse(text.split('\n')[3])[0][2]
|
|
||||||
})
|
|
||||||
.then((rawData) => JSON.parse(rawData))
|
|
||||||
|
|
||||||
this.#verbose && console.log('🧩 Parsing output')
|
|
||||||
// Get first Bard-recommended answer
|
|
||||||
const answer = chatData[4][0]
|
|
||||||
|
|
||||||
// Text of that answer
|
|
||||||
const text = answer[1][0]
|
|
||||||
|
|
||||||
// Get data about images in that answer
|
|
||||||
const images =
|
|
||||||
answer[4]?.map((x) => ({
|
|
||||||
tag: x[2],
|
|
||||||
url: x[3][0][0],
|
|
||||||
info: {
|
|
||||||
raw: x[0][0][0],
|
|
||||||
source: x[1][0][0],
|
|
||||||
alt: x[0][4],
|
|
||||||
website: x[1][1],
|
|
||||||
favicon: x[1][3]
|
|
||||||
}
|
|
||||||
})) ?? []
|
|
||||||
|
|
||||||
this.#verbose && console.log('✅ All done!\n')
|
|
||||||
// Put everything together and return
|
|
||||||
return {
|
|
||||||
content: formatMarkdown(text, images),
|
|
||||||
images,
|
|
||||||
ids: {
|
|
||||||
conversationID: chatData[1][0],
|
|
||||||
responseID: chatData[1][1],
|
|
||||||
choiceID: answer[0],
|
|
||||||
_reqID: String(parseInt(ids?._reqID ?? 0) + 100000)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async #parseConfig (config) {
|
|
||||||
let result = {
|
|
||||||
useJSON: false,
|
|
||||||
imageBuffer: undefined, // Returns as {extension, filename}
|
|
||||||
ids: undefined
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verify that format is one of the two types
|
|
||||||
if (config?.format) {
|
|
||||||
switch (config.format) {
|
|
||||||
case Bard.JSON:
|
|
||||||
result.useJSON = true
|
|
||||||
break
|
|
||||||
case Bard.MD:
|
|
||||||
result.useJSON = false
|
|
||||||
break
|
|
||||||
default:
|
|
||||||
throw new Error(
|
|
||||||
'Format can obly be Bard.JSON for JSON output or Bard.MD for Markdown output.'
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verify that the image passed in is either a path to a jpeg, jpg, png, or webp, or that it is a Buffer
|
|
||||||
if (config?.image) {
|
|
||||||
if (
|
|
||||||
config.image instanceof ArrayBuffer
|
|
||||||
) {
|
|
||||||
result.imageBuffer = config.image
|
|
||||||
} else if (
|
|
||||||
typeof config.image === 'string' &&
|
|
||||||
/\.(jpeg|jpg|png|webp)$/.test(config.image)
|
|
||||||
) {
|
|
||||||
let fs
|
|
||||||
|
|
||||||
try {
|
|
||||||
fs = await import('fs')
|
|
||||||
} catch {
|
|
||||||
throw new Error(
|
|
||||||
'Loading from an image file path is not supported in a browser environment.'
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
result.imageBuffer = fs.readFileSync(
|
|
||||||
config.image
|
|
||||||
).buffer
|
|
||||||
} else {
|
|
||||||
throw new Error(
|
|
||||||
'Provide your image as a file path to a .jpeg, .jpg, .png, or .webp, or a Buffer.'
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verify that all values in IDs exist
|
|
||||||
if (config?.ids) {
|
|
||||||
if (config.ids.conversationID && config.ids.responseID && config.ids.choiceID && config.ids._reqID) {
|
|
||||||
result.ids = config.ids
|
|
||||||
} else {
|
|
||||||
throw new Error(
|
|
||||||
'Please provide the IDs exported exactly as given.'
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ask Bard a question!
|
|
||||||
async ask (message, config) {
|
|
||||||
let { useJSON, imageBuffer, ids } = await this.#parseConfig(config)
|
|
||||||
let response = await this.#query(message, { imageBuffer, ids })
|
|
||||||
return useJSON ? response : response.content
|
|
||||||
}
|
|
||||||
|
|
||||||
createChat (ids) {
|
|
||||||
let bard = this
|
|
||||||
class Chat {
|
|
||||||
ids = ids
|
|
||||||
|
|
||||||
async ask (message, config) {
|
|
||||||
let { useJSON, imageBuffer } = await bard.#parseConfig(config)
|
|
||||||
let response = await bard.#query(message, {
|
|
||||||
imageBuffer,
|
|
||||||
ids: this.ids
|
|
||||||
})
|
|
||||||
this.ids = response.ids
|
|
||||||
return useJSON ? response : response.content
|
|
||||||
}
|
|
||||||
|
|
||||||
export () {
|
|
||||||
return this.ids
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return new Chat()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Bard
|
|
||||||
|
|
@ -136,9 +136,6 @@ const defaultConfig = {
|
||||||
// slackCozeEnableGlobalPreset: true,
|
// slackCozeEnableGlobalPreset: true,
|
||||||
// slackCozeGlobalPreset: '',
|
// slackCozeGlobalPreset: '',
|
||||||
// slackCozeSpecifiedChannel: '',
|
// slackCozeSpecifiedChannel: '',
|
||||||
bardPsid: '',
|
|
||||||
bardReverseProxy: '',
|
|
||||||
bardForceUseReverse: false,
|
|
||||||
cloudTranscode: 'https://silk.201666.xyz',
|
cloudTranscode: 'https://silk.201666.xyz',
|
||||||
cloudRender: false,
|
cloudRender: false,
|
||||||
cloudMode: 'url',
|
cloudMode: 'url',
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue