mirror of
https://github.com/ikechan8370/chatgpt-plugin.git
synced 2025-12-16 13:27:08 +00:00
fix: bing绘图(beta)
This commit is contained in:
parent
da5adc0d10
commit
98943bee9a
2 changed files with 150 additions and 0 deletions
29
apps/draw.js
29
apps/draw.js
|
|
@ -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
121
utils/BingDraw.js
Normal 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)
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue