diff --git a/docs/images/wechat2.jpg b/docs/images/wechat2.jpg index d94dce44..994be070 100644 Binary files a/docs/images/wechat2.jpg and b/docs/images/wechat2.jpg differ diff --git a/package-lock.json b/package-lock.json index 6028eecc..1f26c264 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "bingo", - "version": "0.8.0", + "version": "1.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "bingo", - "version": "0.8.0", + "version": "1.0.0", "dependencies": { "@headlessui/react": "^1.7.17", "@radix-ui/react-alert-dialog": "^1.0.4", diff --git a/package.json b/package.json index 94436ca0..e68a546e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "bingo", - "version": "0.9.0", + "version": "1.0.0", "private": true, "main": "./cloudflare/cli.js", "scripts": { diff --git a/src/components/settings.tsx b/src/components/settings.tsx index e2781f8e..2103f13a 100644 --- a/src/components/settings.tsx +++ b/src/components/settings.tsx @@ -13,7 +13,7 @@ import { } from '@/components/ui/dialog' import { Button } from './ui/button' import { Input } from './ui/input' -import { ChunkKeys, parseCookies, extraCurlFromCookie, parseHeadersFromCurl, encodeHeadersToCookie, setCookie } from '@/lib/utils' +import { ChunkKeys, parseCookies, extraCurlFromCookie, parseHeadersFromCurl, encodeHeadersToCookie, setCookie, resetCookies } from '@/lib/utils' import { ExternalLink } from './external-link' import { useCopyToClipboard } from '@/lib/hooks/use-copy-to-clipboard' @@ -131,7 +131,7 @@ export function Settings() { } encodeHeadersToCookie(headerValue).forEach(cookie => setCookie(cookie)) } else { - [...ChunkKeys, 'BING_COOKIE', 'BING_UA', 'BING_IP', '_U'].forEach(key => setCookie(key, '')) + resetCookies() } setCookie('IMAGE_ONLY', RegExp.$1 === 'cn' || imageOnly || !headerValue ? '1' : '0') diff --git a/src/lib/bots/bing/index.ts b/src/lib/bots/bing/index.ts index 20e14f0f..af92b9dd 100644 --- a/src/lib/bots/bing/index.ts +++ b/src/lib/bots/bing/index.ts @@ -281,6 +281,7 @@ export class BingWebBot { conversationId: conversation.conversationId, userIpAddress: conversation.userIpAddress, conversationSignature: conversation.conversationSignature, + encryptedconversationsignature: conversation.encryptedconversationsignature, clientId: conversation.clientId, invocationId: conversation.invocationId ?? 0, conversationStyle, diff --git a/src/lib/bots/bing/types.ts b/src/lib/bots/bing/types.ts index 30158e14..3ace89e7 100644 --- a/src/lib/bots/bing/types.ts +++ b/src/lib/bots/bing/types.ts @@ -137,7 +137,8 @@ export interface ConversationInfoBase { conversationId: string userIpAddress: string clientId: string - conversationSignature: string + conversationSignature?: string + encryptedconversationsignature?: string invocationId: number } @@ -147,15 +148,6 @@ export interface ConversationInfo extends ConversationInfoBase { imageUrl?: string } -export interface BingChatResponse { - conversationSignature: string - conversationId: string - clientId: string - conversationExpiryTime: Date - response: string - details: ChatResponseMessage -} - export interface Throttling { maxNumLongDocSummaryUserMessagesInConversation: number maxNumUserMessagesInConversation: number diff --git a/src/lib/utils.ts b/src/lib/utils.ts index 15e14bb8..b1d929cf 100644 --- a/src/lib/utils.ts +++ b/src/lib/utils.ts @@ -132,6 +132,10 @@ export function parseCookies(cookie: string, cookieNames: string[]) { return cookies } +export function resetCookies() { + [...ChunkKeys, 'BING_COOKIE', 'BING_UA', '_U', 'BING_IP', 'MUID'].forEach(key => setCookie(key, '')) +} + export const DEFAULT_UA = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36 Edg/117.0.0.0' export const DEFAULT_UA_MOBILE = `Mozilla/5.0 (iPhone; CPU iPhone OS 15_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.7 Mobile/15E148 Safari/605.1.15 BingSapphire/1.0.410427012` @@ -158,6 +162,7 @@ export function mockUser(cookies: Partial<{ [key: string]: string }>) { 'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6', 'User-Agent': ua!, 'x-ms-useragent': 'azsdk-js-api-client-factory/1.0.0-beta.1 core-rest-pipeline/1.10.3 OS/Win32', + 'referer': 'https://www.bing.com/search?showconv=1&sendquery=1&q=Bing%20AI&form=MY02CJ&OCID=MY02CJ&OCID=MY02CJ&pl=launch', cookie: `_U=${_U || defaultUID}; MUID=${MUID || muid()}`, } } @@ -178,8 +183,9 @@ export function createHeaders(cookies: Partial<{ [key: string]: string }>, type? BING_HEADER, ...cookies, }) - headers['x-forwarded-for'] = BING_IP || randomIP() + // headers['x-forwarded-for'] = BING_IP || randomIP() headers['user-agent'] = parseUA(headers['user-agent']) + headers['referer'] = 'https://www.bing.com/search?showconv=1&sendquery=1&q=Bing%20AI&form=MY02CJ&OCID=MY02CJ&OCID=MY02CJ&pl=launch' headers['x-ms-useragent'] = headers['x-ms-useragent'] || 'azsdk-js-api-client-factory/1.0.0-beta.1 core-rest-pipeline/1.10.3 OS/Win32' return headers } diff --git a/src/pages/api/create.ts b/src/pages/api/create.ts index a339c3c0..263dc647 100644 --- a/src/pages/api/create.ts +++ b/src/pages/api/create.ts @@ -14,9 +14,13 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) const endpoints = [req.headers['x-endpoint'], ...(process.env.ENDPOINT || '').split(','), 'www.bing.com'].filter(Boolean) const endpoint = endpoints[count % endpoints.length] const { conversationId } = req.query - const query = conversationId ? new URLSearchParams({ - conversationId: String(conversationId), - }) : '' + const query = new URLSearchParams({ + bundleVersion: '1.1055.8', + }) + if (conversationId) { + query.set('conversationId', String(conversationId)) + } + debug(`try ${count+1}`, endpoint, headers['x-forwarded-for']) const response = await fetch(`https://${endpoint || 'www.bing.com'}/turing/conversation/create?${query}`, { method: 'GET', headers }) .catch(e => { @@ -29,7 +33,12 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) if (response.status === 200) { const json = await response.json().catch((e: any) => {}) console.log('json', json) - if (!json?.conversationSignature) { + if (!json?.clientId) { + continue + } + json.encryptedconversationsignature = response.headers.get('X-Sydney-encryptedconversationsignature') || undefined + + if (!json?.conversationSignature && !json.encryptedconversationsignature) { continue } diff --git a/src/pages/api/sydney.ts b/src/pages/api/sydney.ts index d25663af..459544ec 100644 --- a/src/pages/api/sydney.ts +++ b/src/pages/api/sydney.ts @@ -14,21 +14,19 @@ const { WS_ENDPOINT = 'sydney.bing.com' } = process.env export default async function handler(req: NextApiRequest, res: NextApiResponse) { const conversationContext = req.body - const headers = createHeaders(req.cookies) + const headers = createHeaders(req.cookies, req.cookies['BING_HEADER1'] ? undefined : 'image') const id = headers['x-forwarded-for'] - headers['x-forwarded-for'] = conversationContext?.userIpAddress || headers['x-forwarded-for'] + // headers['x-forwarded-for'] = conversationContext?.userIpAddress || headers['x-forwarded-for'] debug(id, conversationContext, headers) res.setHeader('Content-Type', 'text/stream; charset=UTF-8') - - const ws = new WebSocket(`wss://${req.headers['x-ws-endpoint'] || WS_ENDPOINT}/sydney/ChatHub`, { - headers: { - ...headers, - 'accept-language': 'zh-CN,zh;q=0.9', - 'cache-control': 'no-cache', - 'x-ms-useragent': 'azsdk-js-api-client-factory/1.0.0-beta.1 core-rest-pipeline/1.10.0 OS/Win32', - pragma: 'no-cache', - } + const uri = new URL(`wss://${req.headers['x-ws-endpoint'] || WS_ENDPOINT}/sydney/ChatHub`) + if ('encryptedconversationsignature' in conversationContext) { + uri.searchParams.set('sec_access_token', conversationContext['encryptedconversationsignature']) + } + debug(id, 'wss url', uri.toString()) + const ws = new WebSocket(uri.toString(), { + headers, }) const closeDog = new WatchDog()