mirror of
https://github.com/ikechan8370/chatgpt-plugin.git
synced 2025-12-16 13:27:08 +00:00
150 lines
6 KiB
JavaScript
150 lines
6 KiB
JavaScript
import fetch, { FormData } from 'node-fetch'
|
||
import { makeForwardMsg } from './common.js'
|
||
import { Config } from './config.js'
|
||
import { getProxy } from './proxy.js'
|
||
|
||
let proxy = getProxy()
|
||
export default class BingDrawClient {
|
||
constructor (opts) {
|
||
this.opts = opts
|
||
if (Config.proxy && !Config.sydneyForceUseReverse) {
|
||
// 如果设置代理,走代理
|
||
this.opts.baseUrl = 'https://www.bing.com'
|
||
}
|
||
}
|
||
|
||
async getImages (prompt, e) {
|
||
let urlEncodedPrompt = encodeURIComponent(prompt)
|
||
let url = `${this.opts.baseUrl}/images/create?q=${urlEncodedPrompt}&rt=4&FORM=GENCRE`
|
||
// let d = Math.ceil(Math.random() * 255)
|
||
// let randomIp = '141.11.138.' + d
|
||
let 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 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36 Edg/113.0.1774.50',
|
||
cookie: this.opts.cookies || `_U=${this.opts.userToken}`,
|
||
// 'x-forwarded-for': randomIp,
|
||
Dnt: '1',
|
||
'sec-ch-ua': '"Microsoft Edge";v="113", "Chromium";v="113", "Not-A.Brand";v="24"',
|
||
'sec-ch-ua-arch': '"x86"',
|
||
'sec-ch-ua-bitness': '"64"',
|
||
'sec-ch-ua-full-version': '"113.0.5672.126"',
|
||
'sec-ch-ua-full-version-list': '"Google Chrome";v="113.0.5672.126", "Chromium";v="113.0.5672.126", "Not-A.Brand";v="24.0.0.0"',
|
||
'sec-ch-ua-mobile': '?0',
|
||
'sec-ch-ua-model': '',
|
||
'sec-ch-ua-platform': '"macOS"',
|
||
'sec-ch-ua-platform-version': '"13.1.0"',
|
||
'sec-fetch-dest': 'document',
|
||
'sec-fetch-mode': 'navigate',
|
||
'sec-fetch-site': 'same-origin',
|
||
'sec-fetch-user': '?1',
|
||
'Referrer-Policy': 'origin-when-cross-origin',
|
||
'x-edge-shopping-flag': '1'
|
||
}
|
||
// headers['x-forwarded-for'] = '141.11.138.30'
|
||
let body = new FormData()
|
||
body.append('q', prompt)
|
||
body.append('qs', 'ds')
|
||
let fetchOptions = {
|
||
headers
|
||
}
|
||
if (Config.proxy) {
|
||
fetchOptions.agent = proxy(Config.proxy)
|
||
}
|
||
let success = false
|
||
let retry = 5
|
||
let response
|
||
while (!success && retry >= 0) {
|
||
response = await fetch(url, Object.assign(fetchOptions, { body, redirect: 'manual', method: 'POST', credentials: 'include' }))
|
||
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`
|
||
response = await fetch(url, Object.assign(fetchOptions, { body, redirect: 'manual', method: 'POST', credentials: 'include' }))
|
||
}
|
||
if (response.status === 302) {
|
||
success = true
|
||
break
|
||
} else {
|
||
retry--
|
||
}
|
||
}
|
||
if (!success) {
|
||
// 最后尝试使用https://cn.bing.com进行一次绘图
|
||
logger.info('尝试使用https://cn.bing.com进行绘图')
|
||
url = `https://cn.bing.com/images/create?q=${urlEncodedPrompt}&rt=3&FORM=GENCRE`
|
||
fetchOptions.referrer = 'https://cn.bing.com/images/create/'
|
||
fetchOptions.origin = 'https://cn.bing.com'
|
||
response = await fetch(url, Object.assign(fetchOptions, { body, redirect: 'manual', method: 'POST', credentials: 'include' }))
|
||
if (response.status !== 302) {
|
||
throw new Error('绘图失败,请检查Bing token和代理/反代配置')
|
||
}
|
||
}
|
||
let redirectUrl = response.headers.get('Location').replace('&nfy=1', '')
|
||
let requestId = redirectUrl.split('id=')[1]
|
||
// 模拟跳转
|
||
await fetch(`${this.opts.baseUrl}${redirectUrl}`, {
|
||
headers
|
||
})
|
||
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 found = false
|
||
let timer = setInterval(async () => {
|
||
if (found) {
|
||
return
|
||
}
|
||
let r = await fetch(pollingUrl, fetchOptions)
|
||
let rText = await r.text()
|
||
if (r.status === 200 && rText) {
|
||
// logger.info(rText)
|
||
logger.info('got bing draw results!')
|
||
found = true
|
||
let regex = /src="([^"]+)"/g
|
||
let imageLinks = rText.match(regex)
|
||
if (!imageLinks || imageLinks.length === 0) {
|
||
// 很可能是微软内部error,重试即可
|
||
return
|
||
}
|
||
imageLinks = imageLinks
|
||
.map(link => link.split('?w=')[0])
|
||
.map(link => link.replace('src="', ''))
|
||
.filter(link => !link.includes('.svg'))
|
||
imageLinks = [...new Set(imageLinks)]
|
||
const badImages = [
|
||
'https://r.bing.com/rp/in-2zU3AJUdkgFe7ZKv19yPBHVs.png"',
|
||
'https://r.bing.com/rp/TX9QuO3WzcCJz1uaaSwQAz39Kb0.jpg"',
|
||
'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('❌绘图失败:绘图完成但被屏蔽,请调整提示词。', 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)
|
||
timer = null
|
||
} else {
|
||
logger.info('still waiting for bing draw results... times left: ' + timeoutTimes)
|
||
timeoutTimes--
|
||
}
|
||
}
|
||
}, 3000)
|
||
}
|
||
}
|