fix: bing绘图(beta)

This commit is contained in:
ikechan8370 2023-04-01 21:58:04 +08:00
parent da5adc0d10
commit 98943bee9a
2 changed files with 150 additions and 0 deletions

View file

@ -3,6 +3,7 @@ import { createImage, editImage, imageVariation } from '../utils/dalle.js'
import { makeForwardMsg } from '../utils/common.js'
import _ from 'lodash'
import { Config } from '../utils/config.js'
import BingDrawClient from '../utils/BingDraw.js'
export class dalle extends plugin {
constructor (e) {
@ -27,6 +28,10 @@ export class dalle extends plugin {
{
reg: '^#(chatgpt|dalle)编辑图片',
fnc: 'edit'
},
{
reg: '^#bing(画图|绘图)',
fnc: 'bingDraw'
}
]
})
@ -222,4 +227,28 @@ export class dalle extends plugin {
await redis.del(`CHATGPT:EDIT:${e.sender.user_id}`)
}
}
async bingDraw (e) {
let prompt = e.msg.replace(/^#bing(画图|绘图)/, '')
let bingToken = await redis.get('CHATGPT:BING_TOKEN')
if (!bingToken) {
throw new Error('未绑定Bing Cookie请使用#chatgpt设置必应token命令绑定Bing Cookie')
}
const bingTokens = bingToken.split('|')
// 负载均衡
if (Config.toneStyle === 'Sydney' || Config.toneStyle === 'Custom') {
// sydney下不需要保证同一token
const select = Math.floor(Math.random() * bingTokens.length)
bingToken = bingTokens[select]
}
let client = new BingDrawClient({
baseUrl: 'https://bing.ikechan8370.com',
userToken: bingToken
})
try {
await client.getImages(prompt, e)
} catch (e) {
await e.reply('绘图失败:' + e)
}
}
}

121
utils/BingDraw.js Normal file
View file

@ -0,0 +1,121 @@
import fetch from 'node-fetch'
import { makeForwardMsg } from './common.js'
export default class BingDrawClient {
constructor (opts) {
this.opts = opts
}
async getImages (prompt, e) {
let urlEncodedPrompt = encodeURIComponent(prompt)
let url = `${this.opts.baseUrl}/images/create?q=${urlEncodedPrompt}&rt=4&FORM=GENCRE`
let response = await fetch(url, {
method: 'POST',
headers: {
accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
'accept-language': 'en-US,en;q=0.9',
'cache-control': 'max-age=0',
'content-type': 'application/x-www-form-urlencoded',
referrer: 'https://www.bing.com/images/create/',
origin: 'https://www.bing.com',
'user-agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36 Edg/110.0.1587.63',
cookie: this.opts.cookies || `_U=${this.opts.userToken}`
},
redirect: 'manual'
})
let res = await response.text()
if (res.toLowerCase().indexOf('this prompt has been blocked') > -1) {
throw new Error('Your prompt has been blocked by Bing. Try to change any bad words and try again.')
}
if (response.status !== 302) {
url = `${this.opts.baseUrl}/images/create?q=${urlEncodedPrompt}&rt=3&FORM=GENCRE`
let response3 = await fetch(url, {
method: 'POST',
headers: {
accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
'accept-language': 'en-US,en;q=0.9',
'cache-control': 'max-age=0',
'content-type': 'application/x-www-form-urlencoded',
referrer: 'https://www.bing.com/images/create/',
origin: 'https://www.bing.com',
'user-agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36 Edg/110.0.1587.63',
cookie: this.opts.cookies || `_U=${this.opts.userToken}`
},
redirect: 'manual'
})
if (response3.status !== 302) {
throw new Error(await response3.text())
}
response = response3
}
let redirectUrl = response.headers.get('Location').replace('&nfy=1', '')
let requestId = redirectUrl.split('id=')[1]
// 模拟跳转
await fetch(`${this.opts.baseUrl}${redirectUrl}`, {
headers: {
accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
'accept-language': 'en-US,en;q=0.9',
'cache-control': 'max-age=0',
'content-type': 'application/x-www-form-urlencoded',
referrer: 'https://www.bing.com/images/create/',
origin: 'https://www.bing.com',
'user-agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36 Edg/110.0.1587.63',
cookie: this.opts.cookies || `_U=${this.opts.userToken}`
}
})
let pollingUrl = `${this.opts.baseUrl}/images/create/async/results/${requestId}?q=${urlEncodedPrompt}`
logger.info({ pollingUrl })
logger.info('waiting for bing draw results...')
let timeoutTimes = 50
let timer = setInterval(async () => {
let r = await fetch(pollingUrl, {
headers: {
accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
'accept-language': 'en-US,en;q=0.9',
'cache-control': 'max-age=0',
'content-type': 'application/x-www-form-urlencoded',
referrer: 'https://www.bing.com/images/create/',
origin: 'https://www.bing.com',
'user-agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36 Edg/110.0.1587.63',
cookie: this.opts.cookies || `_U=${this.opts.userToken}`
}
})
let rText = await r.text()
if (rText) {
// logger.info(rText)
logger.info('got bing draw results!')
let regex = /src="([^"]+)"/g
let imageLinks = rText.match(regex)
if (!imageLinks || imageLinks.length === 0) {
await e.reply('绘图失败no images', true)
logger.error(rText)
throw new Error('no images')
}
imageLinks = imageLinks.map(link => link.split('?w=')[0]).map(link => link.replace('src="', ''))
imageLinks = [...new Set(imageLinks)]
const badImages = [
'https://r.bing.com/rp/in-2zU3AJUdkgFe7ZKv19yPBHVs.png',
'https://r.bing.com/rp/TX9QuO3WzcCJz1uaaSwQAz39Kb0.jpg'
]
for (let imageLink of imageLinks) {
if (badImages.indexOf(imageLink) > -1) {
await e.reply('绘图失败Bad images', true)
logger.error(rText)
}
}
logger.info(imageLinks)
let images = imageLinks.map(link => segment.image(link))
let msg = await makeForwardMsg(e, images, `bing绘图结果${prompt}`)
await e.reply(msg)
clearInterval(timer)
} else {
if (timeoutTimes === 0) {
await e.reply('绘图超时', true)
clearInterval(timer)
} else {
logger.info('still waiting for bing draw results... times left: ' + timeoutTimes)
timeoutTimes--
}
}
}, 1500)
}
}