import puppeteer from 'puppeteer-extra';/nimport StealthPlugin from 'puppeteer-extra-plugin-stealth';/n/nclass CharacterAI {/n constructor(headless = true, usePlus = false) {/n this.headless = headless;/n this.usePlus = usePlus;/n this.browser = null;/n this.page = null;/n this.hasDisplayed = false;/n }/n/n // Check if the instance is already initialized/n isInitialized() {/n return this.browser !== null && this.page !== null;/n }/n/n // Clean up the browser and page on exit/n uninitialize() {/n if (this.browser) {/n this.browser.close();/n this.browser = null;/n }/n this.page = null;/n }/n/n // Check for cloudflare's waiting room/n async waitForWaitingRoom(page) {/n // Replace this with your own implementation of the check function/n const check = async () => {/n // Implementation of the check function/n };/n/n // Replace minute with the desired interval in minutes/n const interval = setInterval(check, minute);/n/n await check();/n }/n/n async initialize() {/n if (this.isInitialized()) {/n return;/n }/n/n // Handle chromium tabs cleanup/n process.on('exit', () => {/n this.uninitialize();/n });/n/n console.log(/'[node_characterai] Puppeteer - This is an experimental feature. Please report any issues on github./');/n/n puppeteer.use(StealthPlugin());/n const browser = await puppeteer.launch({/n headless: this.headless,/n args: this.puppeteerLaunchArgs,/n protocolTimeout: this.puppeteerProtocolTimeout || 0,/n executablePath: this.puppeteerPath || null/n });/n this.browser = browser;/n/n let pages = await browser.pages();/n this.page = pages[0];/n/n await this.page.setRequestInterception(false);/n/n this.page.setViewport({/n width: 1920 + Math.floor(Math.random() * 100),/n height: 3000 + Math.floor(Math.random() * 100),/n deviceScaleFactor: 1,/n hasTouch: false,/n isLandscape: false,/n isMobile: false,/n });/n await this.page.setJavaScriptEnabled(true);/n await this.page.setDefaultNavigationTimeout(0);/n/n const userAgent = /'CharacterAI/1.0.0 (iPhone; iOS 14.4.2; Scale/3.00)/';/n await this.page.setUserAgent(userAgent);/n/n await this.page.deleteCookie();/n const client = await this.page.target().createCDPSession();/n await client.send(/'Network.clearBrowserCookies/');/n await client.send(/'Network.clearBrowserCache/');/n await this.page.goto(/'https:///' + (this.usePlus ? /'plus/' : /'beta/') + /'.character.ai/');/n await this.page.evaluate(() => localStorage.clear());/n/n await this.waitForWaitingRoom(this.page);/n/n console.log(/'[node_characterai] Puppeteer - Done with setup/');/n }/n/n async request(url, options) {/n const method = options.method;/n const body = method === /'GET/' ? {} : options.body;/n const headers = options.headers;/n/n let response;/n/n try {/n const payload = {/n method: method,/n headers: headers,/n body: body/n };/n/n await this.page.setRequestInterception(false);/n if (!this.hasDisplayed) {/n console.log(/'[node_characterai] Puppeteer - Eval-fetching is an experimental feature and may be slower. Please report any issues on github/');/n this.hasDisplayed = true;/n }/n/n if (url.endsWith(/'/streaming//')) {/n response = await this.page.evaluate(async (payload, url) => {/n const response = await fetch(url, payload);/n/n const data = await response.text();/n const matches = data.match(//{.*/}/g);/n const responseText = matches[matches.length - 1];/n/n let result = {/n code: 500/n };/n/n if (!matches) {/n result = null;/n } else {/n result.code = 200;/n result.response = responseText;/n }/n/n return result;/n }, payload, url);/n/n response.status = () => response.code; // compatibility reasons/n response.text = () => response.response; // compatibility reasons/n } else {/n await this.page.setRequestInterception(true);/n let initialRequest = true;/n/n this.page.once(/'request/', request => {/n const data = {/n method: method,/n postData: body,/n headers: headers/n };/n/n if (request.isNavigationRequest() && !initialRequest) {/n return request.abort();/n }/n/n try {/n initialRequest = false;/n request.continue(data);/n } catch (error) {/n console.log(/'[node_characterai] Puppeteer - Non fatal error: /' + error);/n }/n });/n/n response = await this.page.goto(url, { waitUntil: /'domcontentloaded/' });/n }/n } catch (error) {/n console.log(/'[node_characterai] Puppeteer - /' + error);/n }/n/n return response;/n }/n/n async imageUpload(url, headers, localFile = false) {/n let response;/n/n try {/n await this.page.setRequestInterception(false);/n if (!this.hasDisplayed) {/n console.log(/'[node_characterai] Puppeteer - Eval-fetching is an experimental feature and may be slower. Please report any issues on github/')/n this.hasDisplayed = true;/n }/n/n // Implementation of image upload/n } catch (error) {/n console.log(/'[node_characterai] Puppeteer - /' + error);/n }/n/n return response;/n }/n}/n/nexport default CharacterAI;/n


原文地址: https://www.cveoy.top/t/topic/mnE 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录