acheong08 / ChatGPT

Reverse engineered ChatGPT API
GNU General Public License v2.0
28.01k stars 4.48k forks source link

Experimental pure Python Cloudflare bypass #1382

Closed hldr4 closed 1 year ago

hldr4 commented 1 year ago

Been playing around with this to avoid using the GO proxy method for TLS spoofing. It uses curl-cffi module to spoof the TLS fingerprint (I set chrome110). But, since that module doesn't support stream=True on requests, a workaround is to write content_callback to a temp file, then read from it, then delete. For async it is the same principle, just uses AsyncSession instead. Works well enough from my various tests, but can never be 100% sure. For example, the following outputs every task result correctly with no parts missing or any weirdness like that.

import asyncio
import sys
from revChatGPT.V1 import Chatbot, AsyncChatbot
from const import access_token, conversation_id

# Needed on my Windows machine for asyncio, idk why
if sys.version_info >= (3, 8) and sys.platform.lower().startswith("win"):
    asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())

async def run_prompt(prompt: str, idx: int):
    bot = AsyncChatbot(config={'access_token': access_token}, conversation_id=conversation_id)
    print(f'Task {idx}:\n') 
    prev_text = ""
    async for data in bot.ask(prompt):
        message = data["message"][len(prev_text):]
        print(message, end="", flush=True)
        prev_text = data["message"]
    print('\n'*2)

def start_tasks(tasks: list):
    for i, task in enumerate(tasks):
        asyncio.run(run_prompt(task, i+1))

tasks = ['Calculate the sum of the first 10 prime numbers', 'Tell me what distance is the moon from earth', 'Write "Hello World" in C']    

def main():
    print('\nAsync Taskbot:\n')
    start_tasks(tasks)

if __name__ == '__main__':
    main()

So this change allows to use the official https://chat.openai.com/backend-api/conversation endpoint without having to spin up a local proxy or using a bypass site, but only on those IPs where the CF challenge isn't triggered for whatever reason.

acheong08 commented 1 year ago

This is good. Removing the need for a proxy server has pretty high demand but I could never figure out how to do it in Python.

Is curl-cffi installation reliable?

If it does not work, you may need to compile and install curl-impersonate first.

hldr4 commented 1 year ago

Is curl-cffi installation reliable?

I cannot speak for everyone, but it works without any additional setup on my Windows PC and remote Linux server

acheong08 commented 1 year ago

Um there are conflicts now. I'll merge right after they are resolved. Will be on the next release 6.0.0

acheong08 commented 1 year ago

I'll make the changes myself. Merging

18870 commented 1 year ago

did you try io.StringIO or something similar, i mean you probably don't need a regular file to do this, it's stupid to write into a file then read from a file in hard disk

acheong08 commented 1 year ago

I'll look into this. There are streaming issues with file due to buffers