mirror of
https://github.com/ikechan8370/chatgpt-plugin.git
synced 2025-12-18 06:17:06 +00:00
156 lines
4.3 KiB
JavaScript
156 lines
4.3 KiB
JavaScript
import WebSocket from 'ws';
|
|
|
|
export class BingAIClient {
|
|
constructor(baseUrl = 'wss://copilot.microsoft.com/c/api/chat') {
|
|
this.baseUrl = baseUrl;
|
|
this.ws = null;
|
|
this.conversationId = null;
|
|
this.currentMessageId = null;
|
|
this.partialMessages = new Map();
|
|
}
|
|
|
|
async sendMessage(text, options = {}) {
|
|
// If conversationId is provided, use it, otherwise create a new one
|
|
if (options.conversationId) {
|
|
this.conversationId = options.conversationId;
|
|
} else {
|
|
this.conversationId = this._generateConversationId();
|
|
}
|
|
|
|
// Connect WebSocket
|
|
await this.connectWebSocket();
|
|
|
|
// Send the initial message or challenge response
|
|
await this.sendInitialMessage();
|
|
|
|
// Send the text message
|
|
const messagePayload = {
|
|
event: 'send',
|
|
conversationId: this.conversationId,
|
|
content: [{ type: 'text', text }],
|
|
mode: 'chat',
|
|
context: { edge: 'NonContextual' },
|
|
};
|
|
|
|
this.ws.send(JSON.stringify(messagePayload));
|
|
|
|
// Wait for the response and collect the full message
|
|
const responseText = await this.collectResponse();
|
|
return responseText;
|
|
}
|
|
|
|
async connectWebSocket() {
|
|
return new Promise((resolve, reject) => {
|
|
this.ws = new WebSocket(this.baseUrl);
|
|
|
|
this.ws.on('open', () => {
|
|
console.log('WebSocket connection established.');
|
|
resolve();
|
|
});
|
|
|
|
this.ws.on('message', (data) => this.handleServerMessage(data));
|
|
|
|
this.ws.on('close', () => {
|
|
console.log('WebSocket connection closed.');
|
|
});
|
|
|
|
this.ws.on('error', (err) => {
|
|
reject(err);
|
|
});
|
|
});
|
|
}
|
|
|
|
async sendInitialMessage() {
|
|
return new Promise((resolve, reject) => {
|
|
this.ws.once('message', (data) => {
|
|
const message = JSON.parse(data);
|
|
if (message.event === 'challenge') {
|
|
// Handle challenge by sending the challenge response
|
|
this.handleChallenge(message)
|
|
.then(resolve)
|
|
.catch(reject);
|
|
} else {
|
|
resolve(); // Proceed if no challenge event
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
async handleChallenge(challenge) {
|
|
// Get the token by calling getTurnstile function (you need to define this function)
|
|
const token = await this.getTurnstile(challenge.conversationId);
|
|
|
|
const challengeResponse = {
|
|
event: 'challengeResponse',
|
|
token: token,
|
|
method: 'cloudflare',
|
|
};
|
|
|
|
this.ws.send(JSON.stringify(challengeResponse));
|
|
}
|
|
|
|
async collectResponse() {
|
|
return new Promise((resolve, reject) => {
|
|
let fullResponse = '';
|
|
|
|
const checkMessageComplete = (messageId) => {
|
|
// Wait for the complete message
|
|
if (this.partialMessages.has(messageId) && this.partialMessages.get(messageId).done) {
|
|
const completeMessage = this.partialMessages.get(messageId).text;
|
|
resolve(completeMessage);
|
|
}
|
|
};
|
|
|
|
this.ws.on('message', (data) => {
|
|
const message = JSON.parse(data);
|
|
|
|
switch (message.event) {
|
|
case 'received':
|
|
break;
|
|
|
|
case 'startMessage':
|
|
this.currentMessageId = message.messageId;
|
|
break;
|
|
|
|
case 'appendText':
|
|
if (!this.partialMessages.has(message.messageId)) {
|
|
this.partialMessages.set(message.messageId, { text: '', done: false });
|
|
}
|
|
|
|
this.partialMessages.get(message.messageId).text += message.text;
|
|
|
|
// Check if this part is the last one
|
|
if (message.partId === '0') {
|
|
this.partialMessages.get(message.messageId).done = true;
|
|
}
|
|
|
|
checkMessageComplete(message.messageId);
|
|
break;
|
|
|
|
case 'partCompleted':
|
|
break;
|
|
|
|
case 'done':
|
|
checkMessageComplete(message.messageId);
|
|
break;
|
|
|
|
default:
|
|
console.warn('Unexpected event:', message.event);
|
|
break;
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
async getTurnstile(conversationId) {
|
|
// This is a mock implementation, you should replace this with the actual logic
|
|
// to interact with the turnstile system to get the token.
|
|
// In a real-world scenario, this would involve making a request to some endpoint.
|
|
return '0.EHn0JUxxxx';
|
|
}
|
|
|
|
_generateConversationId() {
|
|
return 'conversation-' + Math.random().toString(36).substring(2, 15);
|
|
}
|
|
}
|
|
|