acheong08 / OpenAIAuth

Reverse engineered Auth0 for OpenAI

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Feature: Implement Captcha - Success

acheong08 opened this issue · comments

            if soup.find('img', alt='captcha'):
                print(f"{Fore.RED}[OpenAI][5] {Fore.RED}Captcha detected")

                svg_captcha = soup.find('img', alt='captcha')['src'].split(',')[1]
                decoded_svg = base64.decodebytes(svg_captcha.encode("ascii"))

                # Convert decoded svg to png
                drawing = svg2rlg(BytesIO(decoded_svg))

                # Better quality
                renderPM.drawToFile(drawing, "captcha.png", fmt="PNG", dpi=300)
                print(f"{Fore.GREEN}[OpenAI][5] {Fore.WHITE}Captcha saved to {Fore.GREEN}captcha.png"
                      + f" {Fore.WHITE}in the current directory")

                # Wait.
                captcha_input = input(f"{Fore.GREEN}[OpenAI][5] {Fore.WHITE}Please solve the captcha and "
                                      f"press enter to continue: ")
                if captcha_input:
                    print(f"{Fore.GREEN}[OpenAI][5] {Fore.WHITE}Continuing...")
                    self._part_six(state=state, captcha=captcha_input)
                else:
                    raise Exceptions.PyChatGPTException("[OpenAI][5] You didn't enter anything.")

            else:
                print(f"{Fore.GREEN}[OpenAI][5] {Fore.GREEN}No captcha detected")
                self._part_six(state=state, captcha=None)

Translate this to use requests and regex

Stage 1: Success. Captcha svg has been detected. Now need to save to disk somehow

Stage 2: Success. Saved to .svg file

Complete! Login with captcha successful

Any chances that we get a sneaky captcha_solver parameter to the login method now that the captcha infrastructure is in place 😄 ? The parameter would receive a method that can be executed if provided.

One could wrap up a solver method like this:

from twocaptcha import TwoCaptcha

def captcha_solver(image_path):
  api = TwoCaptcha('API_KEY')
  result = solver.normal(image_path, caseSensitive=1)

  return result['code']

Then you could run it here:

# Better quality
renderPM.drawToFile(drawing, "captcha.png", fmt="PNG", dpi=300)
print(f"{Fore.GREEN}[OpenAI][5] {Fore.WHITE}Captcha saved to {Fore.GREEN}captcha.png"
      + f" {Fore.WHITE}in the current directory")
                      
if captcha_solver:
    await captcha_input = captcha_solver('captcha.png')
else:
    ...

Some captcha solving APIs and ML models will block until they have a result, others don't. It would be up to the developer to write the method in such a way that it guarantees that the execution only continues once it has the result to return be it in the synchronous or asynchronous version of the library.

Another thing that I think is important is that we keep the login information somewhere in order to keep that info between executions. Let's say all relevant information is stored in the state variable, a simple solution would be to serialize it to a file like this:

import pickle

with open('./state.pck', 'wb') as file:
    pickle.dump(state, file, protocol=pickle.HIGHEST_PROTOCOL)

If the data is just a simple dictionary, you could as well just dump it to a JSON. The format doesn't really matter as long as you're able to keep the information safe. Another possibility would be to return the state object/dictionary on the login method so developers can store it however they want and provide it to the login method on the next time it is called using an auth_state parameter. If this parameter is provided the login method then checks if the information is still valid. If it's not, just restart the login process. If it is, renew it (if necessary) and return the updated object.

If the state object suffers alterations during the program execution (for example, if you're required to refresh tokens every now and then) please offer a get_state method that developers can use to dump the state at the end of the execution in order to have the latest version of it so we don't have to keep repeating the login steps between executions.

EDIT: If I can say so, letting developers deal with storing the state information is probably the best way. As developers are currently required to save the conversation thread themselves so they can make sure the AI remembers context in future evocations, storing the auth information should be trivial.

Any chances that we get a sneaky captcha_solver parameter to the login method now that the captcha infrastructure is in place smile ? The parameter would receive a method that can be executed if provided.

Edit: I found a way. Let me look through it

Example from ChatGPT:

# Define a function that takes another function as an argument
def apply_function(func, arg):
  # Call the function that was passed as an argument, passing it the specified argument
  return func(arg)

# Define a function that takes a single argument and returns its square
def square(x):
  return x * x

# Call the `apply_function()` function, passing it the `square()` function and the argument 2
result = apply_function(square, 2)

# Print the result
print(result)  # Output: 4

If I can say so, letting developers deal with storing the state information is probably the best way. As developers are currently required to save the conversation thread themselves so they can make sure the AI remembers context in future evocations, storing the auth information should be trivial.

I'm a but confused about this part. Could you explain?

Another thing that I think is important is that we keep the login information somewhere in order to keep that info between executions. Let's say all relevant information is stored in the state variable, a simple solution would be to serialize it to a file like this:

Rather than writing to a file from the library itself, I think it would be better to return a serialized object which can be saved by the user. I want to minimize file read/writes in the library. (Captcha is the exception because I can't find any other way)

I am writing the captcha solver param now and the example

Also, moving this to OpenAIAuth repo

@alexandreteles I have added the feature you requested. You can now pass an object into the Chatbot class which contains a solve_captcha function. This will run if not null with raw_svg being a param input

I'll look into the implementation when I have some free time later today. Raw svg is fine, if the captcha solver needs something different wand-py will do the conversion magic.

Do you plan on adding support for this on the async version as well?

Do you plan on adding support for this on the async version as well?

The async version is maintained by @Harry-Jing so it'll take some time to implement there

If I can say so, letting developers deal with storing the state information is probably the best way. As developers are currently required to save the conversation thread themselves so they can make sure the AI remembers context in future evocations, storing the auth information should be trivial.

I'm a but confused about this part. Could you explain?

When /src/asyncChatGPT/asyncChatGPT.py:351 calls the begin method from OpenAIAuth.py it receives back a session_token that is then internally stored in the object and can be refreshed, if required, by calling the refresh_session method.

This means that developers can access the token and store it for posterior use by just accessing the attribute and storing it however they prefer. What I was trying to suggest here although I did a terrible job at it (it was like 5 in the morning, I beg your pardon) is the following:

  1. Add a way to provide a session token to the Chatbot
  2. Check if the session token is still valid
  3. If it's not, renew it
  4. If renewing failed, run the authentication pipeline again

This should allow developers to keep session information between runs, lowering the login attempts necessary during development and deployment.

At this moment I think this is more about ChatGPT than OpenAIAuth but I'm posting my answer here to preserve the context. Please let me know if I wasn't clear enough once again, English isn't my first language so I can be a bit unclear sometimes 😄

EDIT: the async library works like a charm, thank you!

I see. I will try to do some refactoring today to simplify the logic and allow the sessions to be saved.

Add a way to provide a session token to the Chatbot
Check if the session token is still valid
If it's not, renew it
If renewing failed, run the authentication pipeline again

This was done in the revChatGPT package

Add a way to provide a session token to the Chatbot
Check if the session token is still valid
If it's not, renew it
If renewing failed, run the authentication pipeline again

This was done in the revChatGPT package

Would you mind sharing which attributes contain the relevant information at runtime?

Chatbot.config contains all relevant authentication details. (session token, access token, email, password) while Chatbot.conversation_id_prev_queue contains a list of previous conversation ids and Chatbot.parent_id_prev_queue contains the list for previous message ids