diff --git a/.gitignore b/.gitignore
index 9fa9cf7..e1c023a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1 @@
-/quora/__pycache__
\ No newline at end of file
+/gpt4free/__pycache__
\ No newline at end of file
diff --git a/BUILD/build.py b/BUILD/build.py
index a0a450b..5075b84 100644
--- a/BUILD/build.py
+++ b/BUILD/build.py
@@ -6,7 +6,7 @@
system("rd /s /q build")
system("rd /s /q dist")
system("del /q *.spec")
- system(f'pyinstaller --noconfirm --onefile --icon "cli.ico" --add-data "../quora;." "../main.py"')
+ system(f'pyinstaller --noconfirm --onefile --icon "cli.ico" --add-data "../gpt4free;." "../main.py"')
system("del /q *.spec")
system("rd /s /q build")
system("rd /s /q %USERPROFILE%\AppData\Local\pyinstaller")
diff --git a/gpt4free/README.md b/gpt4free/README.md
new file mode 100644
index 0000000..23f8178
--- /dev/null
+++ b/gpt4free/README.md
@@ -0,0 +1,116 @@
+# gpt4free package
+
+### What is it?
+
+gpt4free is a python package that provides some language model api's
+
+### Main Features
+
+- It's free to use
+- Easy access
+
+### Installation:
+
+```bash
+pip install gpt4free
+```
+
+#### Usage:
+
+```python
+import gpt4free
+import gpt4free
+from gpt4free import Provider, quora, forefront
+
+# usage You
+response = gpt4free.Completion.create(Provider.You, prompt='Write a poem on Lionel Messi')
+print(response)
+
+# usage Poe
+token = quora.Account.create(logging=False)
+response = gpt4free.Completion.create(Provider.Poe, prompt='Write a poem on Lionel Messi', token=token, model='ChatGPT')
+print(response)
+
+# usage forefront
+token = forefront.Account.create(logging=False)
+response = gpt4free.Completion.create(
+ Provider.ForeFront, prompt='Write a poem on Lionel Messi', model='gpt-4', token=token
+)
+print(response)
+print(f'END')
+
+# usage theb
+response = gpt4free.Completion.create(Provider.Theb, prompt='Write a poem on Lionel Messi')
+print(response)
+
+# usage cocalc
+response = gpt4free.Completion.create(Provider.CoCalc, prompt='Write a poem on Lionel Messi', cookie_input='')
+print(response)
+
+```
+
+### Invocation Arguments
+
+`gpt4free.Completion.create()` method has two required arguments
+
+1. Provider: This is an enum representing different provider
+2. prompt: This is the user input
+
+#### Keyword Arguments
+
+Some of the keyword arguments are optional, while others are required.
+
+- You:
+ - `safe_search`: boolean - default value is `False`
+ - `include_links`: boolean - default value is `False`
+ - `detailed`: boolean - default value is `False`
+- Quora:
+ - `token`: str - this needs to be provided by the user
+ - `model`: str - default value is `gpt-4`.
+
+ (Available models: `['Sage', 'GPT-4', 'Claude+', 'Claude-instant', 'ChatGPT', 'Dragonfly', 'NeevaAI']`)
+- ForeFront:
+ - `token`: str - this need to be provided by the user
+
+- Theb:
+ (no keyword arguments required)
+- CoCalc:
+ - `cookie_input`: str - this needs to be provided by user
+
+#### Token generation of quora
+```python
+from gpt4free import quora
+
+token = quora.Account.create(logging=False)
+```
+
+### Token generation of ForeFront
+```python
+from gpt4free import forefront
+
+token = forefront.Account.create(logging=False)
+```
+
+## Copyright:
+
+This program is licensed under the [GNU GPL v3](https://www.gnu.org/licenses/gpl-3.0.txt)
+
+### Copyright Notice:
+
+```
+xtekky/gpt4free: multiple reverse engineered language-model api's to decentralise the ai industry.
+Copyright (C) 2023 xtekky
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+```
diff --git a/gpt4free/__init__.py b/gpt4free/__init__.py
new file mode 100644
index 0000000..5336c82
--- /dev/null
+++ b/gpt4free/__init__.py
@@ -0,0 +1,64 @@
+from enum import Enum
+
+from gpt4free import cocalc
+from gpt4free import forefront
+from gpt4free import quora
+from gpt4free import theb
+from gpt4free import you
+
+
+class Provider(Enum):
+ """An enum representing different providers."""
+
+ You = 'you'
+ Poe = 'poe'
+ ForeFront = 'fore_front'
+ Theb = 'theb'
+ CoCalc = 'cocalc'
+
+
+class Completion:
+ """This class will be used for invoking the given provider"""
+
+ @staticmethod
+ def create(provider: Provider, prompt: str, **kwargs) -> str:
+ """
+ Invokes the given provider with given prompt and addition arguments and returns the string response
+
+ :param provider: an enum representing the provider to use while invoking
+ :param prompt: input provided by the user
+ :param kwargs: Additional keyword arguments to pass to the provider while invoking
+ :return: A string representing the response from the provider
+ """
+ if provider == Provider.Poe:
+ return Completion.__poe_service(prompt, **kwargs)
+ elif provider == Provider.You:
+ return Completion.__you_service(prompt, **kwargs)
+ elif provider == Provider.ForeFront:
+ return Completion.__fore_front_service(prompt, **kwargs)
+ elif provider == Provider.Theb:
+ return Completion.__theb_service(prompt, **kwargs)
+ elif provider == Provider.CoCalc:
+ return Completion.__cocalc_service(prompt, **kwargs)
+ else:
+ raise Exception('Provider not exist, Please try again')
+
+ @staticmethod
+ def __you_service(prompt: str, **kwargs) -> str:
+ return you.Completion.create(prompt, **kwargs).text
+
+ @staticmethod
+ def __poe_service(prompt: str, **kwargs) -> str:
+ return quora.Completion.create(prompt=prompt, **kwargs).text
+
+ @staticmethod
+ def __fore_front_service(prompt: str, **kwargs) -> str:
+ return forefront.Completion.create(prompt=prompt, **kwargs).text
+
+ @staticmethod
+ def __theb_service(prompt: str, **kwargs):
+ return ''.join(theb.Completion.create(prompt=prompt))
+
+ @staticmethod
+ def __cocalc_service(prompt: str, **kwargs):
+ return cocalc.Completion.create(prompt, cookie_input=kwargs.get('cookie_input', '')).text
diff --git a/gpt4free/cocalc/__init__.py b/gpt4free/cocalc/__init__.py
new file mode 100644
index 0000000..0ed2410
--- /dev/null
+++ b/gpt4free/cocalc/__init__.py
@@ -0,0 +1,47 @@
+import requests
+from fake_useragent import UserAgent
+from pydantic import BaseModel
+
+
+class CoCalcResponse(BaseModel):
+ text: str
+ status: bool
+
+
+class Completion:
+ @staticmethod
+ def create(prompt: str, cookie_input: str) -> CoCalcResponse:
+ # Initialize a session with custom headers
+ session = Completion._initialize_session(cookie_input)
+
+ # Set the data that will be submitted
+ payload = Completion._create_payload(prompt, 'ASSUME I HAVE FULL ACCESS TO COCALC. ')
+
+ # Submit the request and return the results
+ return Completion._submit_request(session, payload)
+
+ @classmethod
+ def _initialize_session(cls, conversation_cookie) -> requests.Session:
+ """Initialize a session with custom headers for the request."""
+
+ session = requests.Session()
+ headers = {
+ 'Accept': '*/*',
+ 'Accept-Language': 'en-US,en;q=0.5',
+ 'Origin': 'https://cocalc.com',
+ 'Referer': 'https://cocalc.com/api/v2/openai/chatgpt',
+ 'Cookie': conversation_cookie,
+ 'User-Agent': UserAgent().random,
+ }
+ session.headers.update(headers)
+
+ return session
+
+ @staticmethod
+ def _create_payload(prompt: str, system_prompt: str) -> dict:
+ return {'input': prompt, 'system': system_prompt, 'tag': 'next:index'}
+
+ @staticmethod
+ def _submit_request(session: requests.Session, payload: dict) -> CoCalcResponse:
+ response = session.post('https://cocalc.com/api/v2/openai/chatgpt', json=payload).json()
+ return CoCalcResponse(text=response['output'], status=response['success'])
diff --git a/gpt4free/cocalc/__pycache__/__init__.cpython-311.pyc b/gpt4free/cocalc/__pycache__/__init__.cpython-311.pyc
new file mode 100644
index 0000000..b681383
Binary files /dev/null and b/gpt4free/cocalc/__pycache__/__init__.cpython-311.pyc differ
diff --git a/gpt4free/cocalc/readme.md b/gpt4free/cocalc/readme.md
new file mode 100644
index 0000000..f091115
--- /dev/null
+++ b/gpt4free/cocalc/readme.md
@@ -0,0 +1,19 @@
+### Example: `cocalc`
+
+```python
+# import library
+from gpt4free import cocalc
+
+cocalc.Completion.create(prompt="How are you!", cookie_input="cookieinput") ## Tutorial
+```
+
+### How to grab cookie input
+```js
+// input this into ur developer tools console and the exact response u get from this u put into ur cookieInput!
+var cookies = document.cookie.split("; ");
+var cookieString = "";
+for (var i = 0; i < cookies.length; i++) {
+ cookieString += cookies[i] + "; ";
+}
+console.log(cookieString);
+```
diff --git a/gpt4free/forefront/README.md b/gpt4free/forefront/README.md
new file mode 100644
index 0000000..3d0aac4
--- /dev/null
+++ b/gpt4free/forefront/README.md
@@ -0,0 +1,16 @@
+### Example: `forefront` (use like openai pypi package)
+
+```python
+
+from gpt4free import forefront
+
+# create an account
+token = forefront.Account.create(logging=False)
+print(token)
+
+# get a response
+for response in forefront.StreamingCompletion.create(token=token,
+ prompt='hello world', model='gpt-4'):
+ print(response.completion.choices[0].text, end='')
+print("")
+```
diff --git a/gpt4free/forefront/__init__.py b/gpt4free/forefront/__init__.py
new file mode 100644
index 0000000..f0ca1a1
--- /dev/null
+++ b/gpt4free/forefront/__init__.py
@@ -0,0 +1,192 @@
+from json import loads
+from re import match
+from time import time, sleep
+from typing import Generator, Optional
+from uuid import uuid4
+
+from fake_useragent import UserAgent
+from requests import post
+from tls_client import Session
+
+from .mail import Mail
+from .typing import ForeFrontResponse
+
+
+class Account:
+ @staticmethod
+ def create(proxy: Optional[str] = None, logging: bool = False):
+ proxies = {'http': 'http://' + proxy, 'https': 'http://' + proxy} if proxy else False
+
+ start = time()
+
+ mail_client = Mail(proxies)
+ mail_token = None
+ mail_address = mail_client.get_mail()
+
+ # print(mail_address)
+
+ client = Session(client_identifier='chrome110')
+ client.proxies = proxies
+ client.headers = {
+ 'origin': 'https://accounts.forefront.ai',
+ 'user-agent': UserAgent().random,
+ }
+
+ response = client.post(
+ 'https://clerk.forefront.ai/v1/client/sign_ups?_clerk_js_version=4.32.6',
+ data={'email_address': mail_address},
+ )
+
+ try:
+ trace_token = response.json()['response']['id']
+ if logging:
+ print(trace_token)
+ except KeyError:
+ return 'Failed to create account!'
+
+ response = client.post(
+ f'https://clerk.forefront.ai/v1/client/sign_ups/{trace_token}/prepare_verification?_clerk_js_version=4.32.6',
+ data={
+ 'strategy': 'email_code',
+ },
+ )
+
+ if logging:
+ print(response.text)
+
+ if 'sign_up_attempt' not in response.text:
+ return 'Failed to create account!'
+
+ while True:
+ sleep(1)
+ for _ in mail_client.fetch_inbox():
+ if logging:
+ print(mail_client.get_message_content(_['id']))
+ mail_token = match(r'(\d){5,6}', mail_client.get_message_content(_['id'])).group(0)
+
+ if mail_token:
+ break
+
+ if logging:
+ print(mail_token)
+
+ response = client.post(
+ f'https://clerk.forefront.ai/v1/client/sign_ups/{trace_token}/attempt_verification?_clerk_js_version=4.38.4',
+ data={'code': mail_token, 'strategy': 'email_code'},
+ )
+
+ if logging:
+ print(response.json())
+
+ token = response.json()['client']['sessions'][0]['last_active_token']['jwt']
+
+ with open('accounts.txt', 'a') as f:
+ f.write(f'{mail_address}:{token}\n')
+
+ if logging:
+ print(time() - start)
+
+ return token
+
+
+class StreamingCompletion:
+ @staticmethod
+ def create(
+ token=None,
+ chat_id=None,
+ prompt='',
+ action_type='new',
+ default_persona='607e41fe-95be-497e-8e97-010a59b2e2c0', # default
+ model='gpt-4',
+ ) -> Generator[ForeFrontResponse, None, None]:
+ if not token:
+ raise Exception('Token is required!')
+ if not chat_id:
+ chat_id = str(uuid4())
+
+ headers = {
+ 'authority': 'chat-server.tenant-forefront-default.knative.chi.coreweave.com',
+ 'accept': '*/*',
+ 'accept-language': 'en,fr-FR;q=0.9,fr;q=0.8,es-ES;q=0.7,es;q=0.6,en-US;q=0.5,am;q=0.4,de;q=0.3',
+ 'authorization': 'Bearer ' + token,
+ 'cache-control': 'no-cache',
+ 'content-type': 'application/json',
+ 'origin': 'https://chat.forefront.ai',
+ 'pragma': 'no-cache',
+ 'referer': 'https://chat.forefront.ai/',
+ 'sec-ch-ua': '"Chromium";v="112", "Google Chrome";v="112", "Not:A-Brand";v="99"',
+ 'sec-ch-ua-mobile': '?0',
+ 'sec-ch-ua-platform': '"macOS"',
+ 'sec-fetch-dest': 'empty',
+ 'sec-fetch-mode': 'cors',
+ 'sec-fetch-site': 'cross-site',
+ 'user-agent': UserAgent().random,
+ }
+
+ json_data = {
+ 'text': prompt,
+ 'action': action_type,
+ 'parentId': chat_id,
+ 'workspaceId': chat_id,
+ 'messagePersona': default_persona,
+ 'model': model,
+ }
+
+ for chunk in post(
+ 'https://chat-server.tenant-forefront-default.knative.chi.coreweave.com/chat',
+ headers=headers,
+ json=json_data,
+ stream=True,
+ ).iter_lines():
+ if b'finish_reason":null' in chunk:
+ data = loads(chunk.decode('utf-8').split('data: ')[1])
+ token = data['choices'][0]['delta'].get('content')
+
+ if token is not None:
+ yield ForeFrontResponse(
+ **{
+ 'id': chat_id,
+ 'object': 'text_completion',
+ 'created': int(time()),
+ 'text': token,
+ 'model': model,
+ 'choices': [{'text': token, 'index': 0, 'logprobs': None, 'finish_reason': 'stop'}],
+ 'usage': {
+ 'prompt_tokens': len(prompt),
+ 'completion_tokens': len(token),
+ 'total_tokens': len(prompt) + len(token),
+ },
+ }
+ )
+
+
+class Completion:
+ @staticmethod
+ def create(
+ token=None,
+ chat_id=None,
+ prompt='',
+ action_type='new',
+ default_persona='607e41fe-95be-497e-8e97-010a59b2e2c0', # default
+ model='gpt-4',
+ ) -> ForeFrontResponse:
+ text = ''
+ final_response = None
+ for response in StreamingCompletion.create(
+ token=token,
+ chat_id=chat_id,
+ prompt=prompt,
+ action_type=action_type,
+ default_persona=default_persona,
+ model=model,
+ ):
+ if response:
+ final_response = response
+ text += response.text
+
+ if final_response:
+ final_response.text = text
+ else:
+ raise Exception('Unable to get the response, Please try again')
+
+ return final_response
diff --git a/gpt4free/forefront/__pycache__/__init__.cpython-311.pyc b/gpt4free/forefront/__pycache__/__init__.cpython-311.pyc
new file mode 100644
index 0000000..5063fa9
Binary files /dev/null and b/gpt4free/forefront/__pycache__/__init__.cpython-311.pyc differ
diff --git a/gpt4free/forefront/__pycache__/mail.cpython-311.pyc b/gpt4free/forefront/__pycache__/mail.cpython-311.pyc
new file mode 100644
index 0000000..eb00279
Binary files /dev/null and b/gpt4free/forefront/__pycache__/mail.cpython-311.pyc differ
diff --git a/gpt4free/forefront/__pycache__/typing.cpython-311.pyc b/gpt4free/forefront/__pycache__/typing.cpython-311.pyc
new file mode 100644
index 0000000..d4e461c
Binary files /dev/null and b/gpt4free/forefront/__pycache__/typing.cpython-311.pyc differ
diff --git a/gpt4free/forefront/mail.py b/gpt4free/forefront/mail.py
new file mode 100644
index 0000000..2c00051
--- /dev/null
+++ b/gpt4free/forefront/mail.py
@@ -0,0 +1,52 @@
+from random import choices
+from string import ascii_letters
+
+from requests import Session
+
+
+class Mail:
+ def __init__(self, proxies: dict = None) -> None:
+ self.client = Session()
+ self.client.proxies = proxies
+ self.client.headers = {
+ "host": "api.mail.tm",
+ "connection": "keep-alive",
+ "sec-ch-ua": "\"Google Chrome\";v=\"111\", \"Not(A:Brand\";v=\"8\", \"Chromium\";v=\"111\"",
+ "accept": "application/json, text/plain, */*",
+ "content-type": "application/json",
+ "sec-ch-ua-mobile": "?0",
+ "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36",
+ "sec-ch-ua-platform": "\"macOS\"",
+ "origin": "https://mail.tm",
+ "sec-fetch-site": "same-site",
+ "sec-fetch-mode": "cors",
+ "sec-fetch-dest": "empty",
+ "referer": "https://mail.tm/",
+ "accept-encoding": "gzip, deflate, br",
+ "accept-language": "en-GB,en-US;q=0.9,en;q=0.8",
+ }
+
+ def get_mail(self) -> str:
+ token = ''.join(choices(ascii_letters, k=14)).lower()
+ init = self.client.post(
+ "https://api.mail.tm/accounts", json={"address": f"{token}@bugfoo.com", "password": token}
+ )
+
+ if init.status_code == 201:
+ resp = self.client.post("https://api.mail.tm/token", json={**init.json(), "password": token})
+
+ self.client.headers['authorization'] = 'Bearer ' + resp.json()['token']
+
+ return f"{token}@bugfoo.com"
+
+ else:
+ raise Exception("Failed to create email")
+
+ def fetch_inbox(self):
+ return self.client.get(f"https://api.mail.tm/messages").json()["hydra:member"]
+
+ def get_message(self, message_id: str):
+ return self.client.get(f"https://api.mail.tm/messages/{message_id}").json()
+
+ def get_message_content(self, message_id: str):
+ return self.get_message(message_id)["text"]
diff --git a/gpt4free/forefront/typing.py b/gpt4free/forefront/typing.py
new file mode 100644
index 0000000..23e9090
--- /dev/null
+++ b/gpt4free/forefront/typing.py
@@ -0,0 +1,26 @@
+from typing import Any, List
+
+from pydantic import BaseModel
+
+
+class Choice(BaseModel):
+ text: str
+ index: int
+ logprobs: Any
+ finish_reason: str
+
+
+class Usage(BaseModel):
+ prompt_tokens: int
+ completion_tokens: int
+ total_tokens: int
+
+
+class ForeFrontResponse(BaseModel):
+ id: str
+ object: str
+ created: int
+ model: str
+ choices: List[Choice]
+ usage: Usage
+ text: str
diff --git a/quora/README.md b/gpt4free/quora/README.md
similarity index 70%
rename from quora/README.md
rename to gpt4free/quora/README.md
index 88f9ceb..c6eeac3 100644
--- a/quora/README.md
+++ b/gpt4free/quora/README.md
@@ -1,4 +1,5 @@
-#### warning !!!
+
+> ⚠ Warning !!!
poe.com added security and can detect if you are making automated requests. You may get your account banned if you are using this api.
The normal non-driver api is also currently not very stable
@@ -16,34 +17,33 @@ models = {
}
```
-#### !! new: bot creation
+### New: bot creation
```python
# import quora (poe) package
-import quora
+from gpt4free import quora
# create account
# make sure to set enable_bot_creation to True
-token = quora.Account.create(logging = True, enable_bot_creation=True)
+token = quora.Account.create(logging=True, enable_bot_creation=True)
model = quora.Model.create(
- token = token,
- model = 'gpt-3.5-turbo', # or claude-instant-v1.0
- system_prompt = 'you are ChatGPT a large language model ...'
+ token=token,
+ model='gpt-3.5-turbo', # or claude-instant-v1.0
+ system_prompt='you are ChatGPT a large language model ...'
)
-print(model.name) # gptx....
+print(model.name) # gptx....
# streaming response
for response in quora.StreamingCompletion.create(
- custom_model = model.name,
- prompt ='hello world',
- token = token):
-
+ custom_model=model.name,
+ prompt='hello world',
+ token=token):
print(response.completion.choices[0].text)
```
-#### Normal Response:
+### Normal Response:
```python
response = quora.Completion.create(model = 'gpt-4',
@@ -53,13 +53,13 @@ response = quora.Completion.create(model = 'gpt-4',
print(response.completion.choices[0].text)
```
-#### Update Use This For Poe
+### Update Use This For Poe
```python
from quora import Poe
# available models: ['Sage', 'GPT-4', 'Claude+', 'Claude-instant', 'ChatGPT', 'Dragonfly', 'NeevaAI']
-poe = Poe(model='ChatGPT')
+poe = Poe(model='ChatGPT', driver='firefox', cookie_path='cookie.json', driver_path='path_of_driver')
poe.chat('who won the football world cup most?')
# new bot creation
diff --git a/gpt4free/quora/__init__.py b/gpt4free/quora/__init__.py
new file mode 100644
index 0000000..f548ff4
--- /dev/null
+++ b/gpt4free/quora/__init__.py
@@ -0,0 +1,471 @@
+import json
+from datetime import datetime
+from hashlib import md5
+from json import dumps
+from pathlib import Path
+from random import choice, choices, randint
+from re import search, findall
+from string import ascii_letters, digits
+from typing import Optional, Union, List, Any, Generator
+from urllib.parse import unquote
+
+import selenium.webdriver.support.expected_conditions as EC
+from fake_useragent import UserAgent
+from pydantic import BaseModel
+from pypasser import reCaptchaV3
+from requests import Session
+from selenium.webdriver import Firefox, Chrome, FirefoxOptions, ChromeOptions
+from selenium.webdriver.common.by import By
+from selenium.webdriver.support.wait import WebDriverWait
+from tls_client import Session as TLS
+
+from .api import Client as PoeClient
+from .mail import Emailnator
+
+SELENIUM_WEB_DRIVER_ERROR_MSG = b'''The error message you are receiving is due to the `geckodriver` executable not
+being found in your system\'s PATH. To resolve this issue, you need to download the geckodriver and add its location
+to your system\'s PATH.\n\nHere are the steps to resolve the issue:\n\n1. Download the geckodriver for your platform
+(Windows, macOS, or Linux) from the following link: https://github.com/mozilla/geckodriver/releases\n\n2. Extract the
+downloaded archive and locate the geckodriver executable.\n\n3. Add the geckodriver executable to your system\'s
+PATH.\n\nFor macOS and Linux:\n\n- Open a terminal window.\n- Move the geckodriver executable to a directory that is
+already in your PATH, or create a new directory and add it to your PATH:\n\n```bash\n# Example: Move geckodriver to
+/usr/local/bin\nmv /path/to/your/geckodriver /usr/local/bin\n```\n\n- If you created a new directory, add it to your
+PATH:\n\n```bash\n# Example: Add a new directory to PATH\nexport PATH=$PATH:/path/to/your/directory\n```\n\nFor
+Windows:\n\n- Right-click on "My Computer" or "This PC" and select "Properties".\n- Click on "Advanced system
+settings".\n- Click on the "Environment Variables" button.\n- In the "System variables" section, find the "Path"
+variable, select it, and click "Edit".\n- Click "New" and add the path to the directory containing the geckodriver
+executable.\n\nAfter adding the geckodriver to your PATH, restart your terminal or command prompt and try running
+your script again. The error should be resolved.'''
+
+# from twocaptcha import TwoCaptcha
+# solver = TwoCaptcha('72747bf24a9d89b4dcc1b24875efd358')
+
+MODELS = {
+ 'Sage': 'capybara',
+ 'GPT-4': 'beaver',
+ 'Claude+': 'a2_2',
+ 'Claude-instant': 'a2',
+ 'ChatGPT': 'chinchilla',
+ 'Dragonfly': 'nutria',
+ 'NeevaAI': 'hutia',
+}
+
+
+def extract_formkey(html):
+ script_regex = r''
+ script_text = search(script_regex, html).group(1)
+ key_regex = r'var .="([0-9a-f]+)",'
+ key_text = search(key_regex, script_text).group(1)
+ cipher_regex = r'.\[(\d+)\]=.\[(\d+)\]'
+ cipher_pairs = findall(cipher_regex, script_text)
+
+ formkey_list = [''] * len(cipher_pairs)
+ for pair in cipher_pairs:
+ formkey_index, key_index = map(int, pair)
+ formkey_list[formkey_index] = key_text[key_index]
+ formkey = ''.join(formkey_list)
+
+ return formkey
+
+
+class Choice(BaseModel):
+ text: str
+ index: int
+ logprobs: Any
+ finish_reason: str
+
+
+class Usage(BaseModel):
+ prompt_tokens: int
+ completion_tokens: int
+ total_tokens: int
+
+
+class PoeResponse(BaseModel):
+ id: int
+ object: str
+ created: int
+ model: str
+ choices: List[Choice]
+ usage: Usage
+ text: str
+
+
+class ModelResponse:
+ def __init__(self, json_response: dict) -> None:
+ self.id = json_response['data']['poeBotCreate']['bot']['id']
+ self.name = json_response['data']['poeBotCreate']['bot']['displayName']
+ self.limit = json_response['data']['poeBotCreate']['bot']['messageLimit']['dailyLimit']
+ self.deleted = json_response['data']['poeBotCreate']['bot']['deletionState']
+
+
+class Model:
+ @staticmethod
+ def create(
+ token: str,
+ model: str = 'gpt-3.5-turbo', # claude-instant
+ system_prompt: str = 'You are ChatGPT a large language model developed by Openai. Answer as consisely as possible',
+ description: str = 'gpt-3.5 language model from openai, skidded by poe.com',
+ handle: str = None,
+ ) -> ModelResponse:
+ if not handle:
+ handle = f'gptx{randint(1111111, 9999999)}'
+
+ client = Session()
+ client.cookies['p-b'] = token
+
+ formkey = extract_formkey(client.get('https://poe.com').text)
+ settings = client.get('https://poe.com/api/settings').json()
+
+ client.headers = {
+ 'host': 'poe.com',
+ 'origin': 'https://poe.com',
+ 'referer': 'https://poe.com/',
+ 'poe-formkey': formkey,
+ 'poe-tchannel': settings['tchannelData']['channel'],
+ 'user-agent': UserAgent().random,
+ 'connection': 'keep-alive',
+ 'sec-ch-ua': '"Chromium";v="112", "Google Chrome";v="112", "Not:A-Brand";v="99"',
+ 'sec-ch-ua-mobile': '?0',
+ 'sec-ch-ua-platform': '"macOS"',
+ 'content-type': 'application/json',
+ 'sec-fetch-site': 'same-origin',
+ 'sec-fetch-mode': 'cors',
+ 'sec-fetch-dest': 'empty',
+ 'accept': '*/*',
+ 'accept-encoding': 'gzip, deflate, br',
+ 'accept-language': 'en-GB,en-US;q=0.9,en;q=0.8',
+ }
+
+ payload = dumps(
+ separators=(',', ':'),
+ obj={
+ 'queryName': 'CreateBotMain_poeBotCreate_Mutation',
+ 'variables': {
+ 'model': MODELS[model],
+ 'handle': handle,
+ 'prompt': system_prompt,
+ 'isPromptPublic': True,
+ 'introduction': '',
+ 'description': description,
+ 'profilePictureUrl': 'https://qph.fs.quoracdn.net/main-qimg-24e0b480dcd946e1cc6728802c5128b6',
+ 'apiUrl': None,
+ 'apiKey': ''.join(choices(ascii_letters + digits, k=32)),
+ 'isApiBot': False,
+ 'hasLinkification': False,
+ 'hasMarkdownRendering': False,
+ 'hasSuggestedReplies': False,
+ 'isPrivateBot': False,
+ },
+ 'query': 'mutation CreateBotMain_poeBotCreate_Mutation(\n $model: String!\n $handle: String!\n $prompt: String!\n $isPromptPublic: Boolean!\n $introduction: String!\n $description: String!\n $profilePictureUrl: String\n $apiUrl: String\n $apiKey: String\n $isApiBot: Boolean\n $hasLinkification: Boolean\n $hasMarkdownRendering: Boolean\n $hasSuggestedReplies: Boolean\n $isPrivateBot: Boolean\n) {\n poeBotCreate(model: $model, handle: $handle, promptPlaintext: $prompt, isPromptPublic: $isPromptPublic, introduction: $introduction, description: $description, profilePicture: $profilePictureUrl, apiUrl: $apiUrl, apiKey: $apiKey, isApiBot: $isApiBot, hasLinkification: $hasLinkification, hasMarkdownRendering: $hasMarkdownRendering, hasSuggestedReplies: $hasSuggestedReplies, isPrivateBot: $isPrivateBot) {\n status\n bot {\n id\n ...BotHeader_bot\n }\n }\n}\n\nfragment BotHeader_bot on Bot {\n displayName\n messageLimit {\n dailyLimit\n }\n ...BotImage_bot\n ...BotLink_bot\n ...IdAnnotation_node\n ...botHelpers_useViewerCanAccessPrivateBot\n ...botHelpers_useDeletion_bot\n}\n\nfragment BotImage_bot on Bot {\n displayName\n ...botHelpers_useDeletion_bot\n ...BotImage_useProfileImage_bot\n}\n\nfragment BotImage_useProfileImage_bot on Bot {\n image {\n __typename\n ... on LocalBotImage {\n localName\n }\n ... on UrlBotImage {\n url\n }\n }\n ...botHelpers_useDeletion_bot\n}\n\nfragment BotLink_bot on Bot {\n displayName\n}\n\nfragment IdAnnotation_node on Node {\n __isNode: __typename\n id\n}\n\nfragment botHelpers_useDeletion_bot on Bot {\n deletionState\n}\n\nfragment botHelpers_useViewerCanAccessPrivateBot on Bot {\n isPrivateBot\n viewerIsCreator\n}\n',
+ },
+ )
+
+ base_string = payload + client.headers['poe-formkey'] + 'WpuLMiXEKKE98j56k'
+ client.headers['poe-tag-id'] = md5(base_string.encode()).hexdigest()
+
+ response = client.post('https://poe.com/api/gql_POST', data=payload)
+
+ if 'success' not in response.text:
+ raise Exception(
+ '''
+ Bot creation Failed
+ !! Important !!
+ Bot creation was not enabled on this account
+ please use: quora.Account.create with enable_bot_creation set to True
+ '''
+ )
+
+ return ModelResponse(response.json())
+
+
+class Account:
+ @staticmethod
+ def create(
+ proxy: Optional[str] = None,
+ logging: bool = False,
+ enable_bot_creation: bool = False,
+ ):
+ client = TLS(client_identifier='chrome110')
+ client.proxies = {'http': f'http://{proxy}', 'https': f'http://{proxy}'} if proxy else None
+
+ mail_client = Emailnator()
+ mail_address = mail_client.get_mail()
+
+ if logging:
+ print('email', mail_address)
+
+ client.headers = {
+ 'authority': 'poe.com',
+ 'accept': '*/*',
+ 'accept-language': 'en,fr-FR;q=0.9,fr;q=0.8,es-ES;q=0.7,es;q=0.6,en-US;q=0.5,am;q=0.4,de;q=0.3',
+ 'content-type': 'application/json',
+ 'origin': 'https://poe.com',
+ 'poe-tag-id': 'null',
+ 'referer': 'https://poe.com/login',
+ 'sec-ch-ua': '"Chromium";v="112", "Google Chrome";v="112", "Not:A-Brand";v="99"',
+ 'sec-ch-ua-mobile': '?0',
+ 'sec-ch-ua-platform': '"macOS"',
+ 'sec-fetch-dest': 'empty',
+ 'sec-fetch-mode': 'cors',
+ 'sec-fetch-site': 'same-origin',
+ 'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36',
+ 'poe-formkey': extract_formkey(client.get('https://poe.com/login').text),
+ 'poe-tchannel': client.get('https://poe.com/api/settings').json()['tchannelData']['channel'],
+ }
+
+ token = reCaptchaV3(
+ 'https://www.recaptcha.net/recaptcha/enterprise/anchor?ar=1&k=6LflhEElAAAAAI_ewVwRWI9hsyV4mbZnYAslSvlG&co=aHR0cHM6Ly9wb2UuY29tOjQ0Mw..&hl=en&v=4PnKmGB9wRHh1i04o7YUICeI&size=invisible&cb=bi6ivxoskyal'
+ )
+ # token = solver.recaptcha(sitekey='6LflhEElAAAAAI_ewVwRWI9hsyV4mbZnYAslSvlG',
+ # url = 'https://poe.com/login?redirect_url=%2F',
+ # version = 'v3',
+ # enterprise = 1,
+ # invisible = 1,
+ # action = 'login',)['code']
+
+ payload = dumps(
+ separators=(',', ':'),
+ obj={
+ 'queryName': 'MainSignupLoginSection_sendVerificationCodeMutation_Mutation',
+ 'variables': {
+ 'emailAddress': mail_address,
+ 'phoneNumber': None,
+ 'recaptchaToken': token,
+ },
+ 'query': 'mutation MainSignupLoginSection_sendVerificationCodeMutation_Mutation(\n $emailAddress: String\n $phoneNumber: String\n $recaptchaToken: String\n) {\n sendVerificationCode(verificationReason: login, emailAddress: $emailAddress, phoneNumber: $phoneNumber, recaptchaToken: $recaptchaToken) {\n status\n errorMessage\n }\n}\n',
+ },
+ )
+
+ base_string = payload + client.headers['poe-formkey'] + 'WpuLMiXEKKE98j56k'
+ client.headers['poe-tag-id'] = md5(base_string.encode()).hexdigest()
+
+ print(dumps(client.headers, indent=4))
+
+ response = client.post('https://poe.com/api/gql_POST', data=payload)
+
+ if 'automated_request_detected' in response.text:
+ print('please try using a proxy / wait for fix')
+
+ if 'Bad Request' in response.text:
+ if logging:
+ print('bad request, retrying...', response.json())
+ quit()
+
+ if logging:
+ print('send_code', response.json())
+
+ mail_content = mail_client.get_message()
+ mail_token = findall(r';">(\d{6,7})', mail_content)[0]
+
+ if logging:
+ print('code', mail_token)
+
+ payload = dumps(
+ separators=(',', ':'),
+ obj={
+ 'queryName': 'SignupOrLoginWithCodeSection_signupWithVerificationCodeMutation_Mutation',
+ 'variables': {
+ 'verificationCode': str(mail_token),
+ 'emailAddress': mail_address,
+ 'phoneNumber': None,
+ },
+ 'query': 'mutation SignupOrLoginWithCodeSection_signupWithVerificationCodeMutation_Mutation(\n $verificationCode: String!\n $emailAddress: String\n $phoneNumber: String\n) {\n signupWithVerificationCode(verificationCode: $verificationCode, emailAddress: $emailAddress, phoneNumber: $phoneNumber) {\n status\n errorMessage\n }\n}\n',
+ },
+ )
+
+ base_string = payload + client.headers['poe-formkey'] + 'WpuLMiXEKKE98j56k'
+ client.headers['poe-tag-id'] = md5(base_string.encode()).hexdigest()
+
+ response = client.post('https://poe.com/api/gql_POST', data=payload)
+ if logging:
+ print('verify_code', response.json())
+
+ def get(self):
+ cookies = open(Path(__file__).resolve().parent / 'cookies.txt', 'r').read().splitlines()
+ return choice(cookies)
+
+
+class StreamingCompletion:
+ @staticmethod
+ def create(
+ model: str = 'gpt-4',
+ custom_model: bool = None,
+ prompt: str = 'hello world',
+ token: str = '',
+ ) -> Generator[PoeResponse, None, None]:
+ _model = MODELS[model] if not custom_model else custom_model
+
+ client = PoeClient(token)
+
+ for chunk in client.send_message(_model, prompt):
+ yield PoeResponse(
+ **{
+ 'id': chunk['messageId'],
+ 'object': 'text_completion',
+ 'created': chunk['creationTime'],
+ 'model': _model,
+ 'text': chunk['text_new'],
+ 'choices': [
+ {
+ 'text': chunk['text_new'],
+ 'index': 0,
+ 'logprobs': None,
+ 'finish_reason': 'stop',
+ }
+ ],
+ 'usage': {
+ 'prompt_tokens': len(prompt),
+ 'completion_tokens': len(chunk['text_new']),
+ 'total_tokens': len(prompt) + len(chunk['text_new']),
+ },
+ }
+ )
+
+
+class Completion:
+ @staticmethod
+ def create(
+ model: str = 'gpt-4',
+ custom_model: str = None,
+ prompt: str = 'hello world',
+ token: str = '',
+ ) -> PoeResponse:
+ _model = MODELS[model] if not custom_model else custom_model
+
+ client = PoeClient(token)
+
+ chunk = None
+ for response in client.send_message(_model, prompt):
+ chunk = response
+
+ return PoeResponse(
+ **{
+ 'id': chunk['messageId'],
+ 'object': 'text_completion',
+ 'created': chunk['creationTime'],
+ 'model': _model,
+ 'text': chunk['text'],
+ 'choices': [
+ {
+ 'text': chunk['text'],
+ 'index': 0,
+ 'logprobs': None,
+ 'finish_reason': 'stop',
+ }
+ ],
+ 'usage': {
+ 'prompt_tokens': len(prompt),
+ 'completion_tokens': len(chunk['text']),
+ 'total_tokens': len(prompt) + len(chunk['text']),
+ },
+ }
+ )
+
+
+class Poe:
+ def __init__(
+ self,
+ model: str = 'ChatGPT',
+ driver: str = 'firefox',
+ download_driver: bool = False,
+ driver_path: Optional[str] = None,
+ cookie_path: str = './quora/cookie.json',
+ ):
+ # validating the model
+ if model and model not in MODELS:
+ raise RuntimeError('Sorry, the model you provided does not exist. Please check and try again.')
+ self.model = MODELS[model]
+ self.cookie_path = cookie_path
+ self.cookie = self.__load_cookie(driver, driver_path=driver_path)
+ self.client = PoeClient(self.cookie)
+
+ def __load_cookie(self, driver: str, driver_path: Optional[str] = None) -> str:
+ if (cookie_file := Path(self.cookie_path)).exists():
+ with cookie_file.open() as fp:
+ cookie = json.load(fp)
+ if datetime.fromtimestamp(cookie['expiry']) < datetime.now():
+ cookie = self.__register_and_get_cookie(driver, driver_path=driver_path)
+ else:
+ print('Loading the cookie from file')
+ else:
+ cookie = self.__register_and_get_cookie(driver, driver_path=driver_path)
+
+ return unquote(cookie['value'])
+
+ def __register_and_get_cookie(self, driver: str, driver_path: Optional[str] = None) -> dict:
+ mail_client = Emailnator()
+ mail_address = mail_client.get_mail()
+
+ driver = self.__resolve_driver(driver, driver_path=driver_path)
+ driver.get("https://www.poe.com")
+
+ # clicking use email button
+ driver.find_element(By.XPATH, '//button[contains(text(), "Use email")]').click()
+
+ email = WebDriverWait(driver, 30).until(EC.presence_of_element_located((By.XPATH, '//input[@type="email"]')))
+ email.send_keys(mail_address)
+ driver.find_element(By.XPATH, '//button[text()="Go"]').click()
+
+ code = findall(r';">(\d{6,7})', mail_client.get_message())[0]
+ print(code)
+
+ verification_code = WebDriverWait(driver, 30).until(
+ EC.presence_of_element_located((By.XPATH, '//input[@placeholder="Code"]'))
+ )
+ verification_code.send_keys(code)
+ verify_button = EC.presence_of_element_located((By.XPATH, '//button[text()="Verify"]'))
+ login_button = EC.presence_of_element_located((By.XPATH, '//button[text()="Log In"]'))
+
+ WebDriverWait(driver, 30).until(EC.any_of(verify_button, login_button)).click()
+
+ cookie = driver.get_cookie('p-b')
+
+ with open(self.cookie_path, 'w') as fw:
+ json.dump(cookie, fw)
+
+ driver.close()
+ return cookie
+
+ @staticmethod
+ def __resolve_driver(driver: str, driver_path: Optional[str] = None) -> Union[Firefox, Chrome]:
+ options = FirefoxOptions() if driver == 'firefox' else ChromeOptions()
+ options.add_argument('-headless')
+
+ if driver_path:
+ options.binary_location = driver_path
+ try:
+ return Firefox(options=options) if driver == 'firefox' else Chrome(options=options)
+ except Exception:
+ raise Exception(SELENIUM_WEB_DRIVER_ERROR_MSG)
+
+ def chat(self, message: str, model: Optional[str] = None) -> str:
+ if model and model not in MODELS:
+ raise RuntimeError('Sorry, the model you provided does not exist. Please check and try again.')
+ model = MODELS[model] if model else self.model
+ response = None
+ for chunk in self.client.send_message(model, message):
+ response = chunk['text']
+ return response
+
+ def create_bot(
+ self,
+ name: str,
+ /,
+ prompt: str = '',
+ base_model: str = 'ChatGPT',
+ description: str = '',
+ ) -> None:
+ if base_model not in MODELS:
+ raise RuntimeError('Sorry, the base_model you provided does not exist. Please check and try again.')
+
+ response = self.client.create_bot(
+ handle=name,
+ prompt=prompt,
+ base_model=MODELS[base_model],
+ description=description,
+ )
+ print(f'Successfully created bot with name: {response["bot"]["displayName"]}')
+
+ def list_bots(self) -> list:
+ return list(self.client.bot_names.values())
diff --git a/gpt4free/quora/__pycache__/__init__.cpython-311.pyc b/gpt4free/quora/__pycache__/__init__.cpython-311.pyc
new file mode 100644
index 0000000..acf3a9e
Binary files /dev/null and b/gpt4free/quora/__pycache__/__init__.cpython-311.pyc differ
diff --git a/gpt4free/quora/__pycache__/api.cpython-311.pyc b/gpt4free/quora/__pycache__/api.cpython-311.pyc
new file mode 100644
index 0000000..ab34ab6
Binary files /dev/null and b/gpt4free/quora/__pycache__/api.cpython-311.pyc differ
diff --git a/gpt4free/quora/__pycache__/mail.cpython-311.pyc b/gpt4free/quora/__pycache__/mail.cpython-311.pyc
new file mode 100644
index 0000000..78b1cbb
Binary files /dev/null and b/gpt4free/quora/__pycache__/mail.cpython-311.pyc differ
diff --git a/quora/api.py b/gpt4free/quora/api.py
similarity index 89%
rename from quora/api.py
rename to gpt4free/quora/api.py
index b28c124..897215a 100644
--- a/quora/api.py
+++ b/gpt4free/quora/api.py
@@ -18,23 +18,21 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
-import requests
-import re
+import hashlib
import json
-import random
import logging
-import time
import queue
+import random
+import re
import threading
+import time
import traceback
-import hashlib
-import string
-import random
-import requests.adapters
-import websocket
from pathlib import Path
from urllib.parse import urlparse
+import requests
+import requests.adapters
+import websocket
parent_path = Path(__file__).resolve().parent
queries_path = parent_path / "graphql"
@@ -66,7 +64,7 @@ def request_with_retries(method, *args, **kwargs):
if r.status_code == 200:
return r
logger.warn(
- f"Server returned a status code of {r.status_code} while downloading {url}. Retrying ({i+1}/{attempts})..."
+ f"Server returned a status code of {r.status_code} while downloading {url}. Retrying ({i + 1}/{attempts})..."
)
raise RuntimeError(f"Failed to download {url} too many times.")
@@ -81,9 +79,7 @@ class Client:
def __init__(self, token, proxy=None):
self.proxy = proxy
self.session = requests.Session()
- self.adapter = requests.adapters.HTTPAdapter(
- pool_connections=100, pool_maxsize=100
- )
+ self.adapter = requests.adapters.HTTPAdapter(pool_connections=100, pool_maxsize=100)
self.session.mount("http://", self.adapter)
self.session.mount("https://", self.adapter)
@@ -139,9 +135,7 @@ def get_next_data(self, overwrite_vars=False):
logger.info("Downloading next_data...")
r = request_with_retries(self.session.get, self.home_url)
- json_regex = (
- r''
- )
+ json_regex = r''
json_text = re.search(json_regex, r.text).group(1)
next_data = json.loads(json_text)
@@ -213,19 +207,14 @@ def get_websocket_url(self, channel=None):
if channel is None:
channel = self.channel
query = f'?min_seq={channel["minSeq"]}&channel={channel["channel"]}&hash={channel["channelHash"]}'
- return (
- f'wss://{self.ws_domain}.tch.{channel["baseHost"]}/up/{channel["boxName"]}/updates'
- + query
- )
+ return f'wss://{self.ws_domain}.tch.{channel["baseHost"]}/up/{channel["boxName"]}/updates' + query
def send_query(self, query_name, variables):
for i in range(20):
json_data = generate_payload(query_name, variables)
payload = json.dumps(json_data, separators=(",", ":"))
- base_string = (
- payload + self.gql_headers["poe-formkey"] + "WpuLMiXEKKE98j56k"
- )
+ base_string = payload + self.gql_headers["poe-formkey"] + "WpuLMiXEKKE98j56k"
headers = {
"content-type": "application/json",
@@ -233,15 +222,11 @@ def send_query(self, query_name, variables):
}
headers = {**self.gql_headers, **headers}
- r = request_with_retries(
- self.session.post, self.gql_url, data=payload, headers=headers
- )
+ r = request_with_retries(self.session.post, self.gql_url, data=payload, headers=headers)
data = r.json()
- if data["data"] == None:
- logger.warn(
- f'{query_name} returned an error: {data["errors"][0]["message"]} | Retrying ({i+1}/20)'
- )
+ if data["data"] is None:
+ logger.warn(f'{query_name} returned an error: {data["errors"][0]["message"]} | Retrying ({i + 1}/20)')
time.sleep(2)
continue
@@ -304,9 +289,7 @@ def on_ws_connect(self, ws):
def on_ws_close(self, ws, close_status_code, close_message):
self.ws_connected = False
- logger.warn(
- f"Websocket closed with status {close_status_code}: {close_message}"
- )
+ logger.warn(f"Websocket closed with status {close_status_code}: {close_message}")
def on_ws_error(self, ws, error):
self.disconnect_ws()
@@ -333,11 +316,7 @@ def on_message(self, ws, msg):
return
# indicate that the response id is tied to the human message id
- elif (
- key != "pending"
- and value == None
- and message["state"] != "complete"
- ):
+ elif key != "pending" and value is None and message["state"] != "complete":
self.active_messages[key] = message["messageId"]
self.message_queues[key].put(message)
return
@@ -381,9 +360,7 @@ def send_message(self, chatbot, message, with_chat_break=False, timeout=20):
human_message = message_data["data"]["messageEdgeCreate"]["message"]
human_message_id = human_message["node"]["messageId"]
except TypeError:
- raise RuntimeError(
- f"An unknown error occurred. Raw response data: {message_data}"
- )
+ raise RuntimeError(f"An unknown error occurred. Raw response data: {message_data}")
# indicate that the current message is waiting for a response
self.active_messages[human_message_id] = None
@@ -418,16 +395,14 @@ def send_message(self, chatbot, message, with_chat_break=False, timeout=20):
def send_chat_break(self, chatbot):
logger.info(f"Sending chat break to {chatbot}")
- result = self.send_query(
- "AddMessageBreakMutation", {"chatId": self.bots[chatbot]["chatId"]}
- )
+ result = self.send_query("AddMessageBreakMutation", {"chatId": self.bots[chatbot]["chatId"]})
return result["data"]["messageBreakCreate"]["message"]
def get_message_history(self, chatbot, count=25, cursor=None):
logger.info(f"Downloading {count} messages from {chatbot}")
messages = []
- if cursor == None:
+ if cursor is None:
chat_data = self.get_bot(self.bot_names[chatbot])
if not chat_data["messagesConnection"]["edges"]:
return []
@@ -437,15 +412,11 @@ def get_message_history(self, chatbot, count=25, cursor=None):
cursor = str(cursor)
if count > 50:
- messages = (
- self.get_message_history(chatbot, count=50, cursor=cursor) + messages
- )
+ messages = self.get_message_history(chatbot, count=50, cursor=cursor) + messages
while count > 0:
count -= 50
new_cursor = messages[0]["cursor"]
- new_messages = self.get_message_history(
- chatbot, min(50, count), cursor=new_cursor
- )
+ new_messages = self.get_message_history(chatbot, min(50, count), cursor=new_cursor)
messages = new_messages + messages
return messages
elif count <= 0:
@@ -523,9 +494,7 @@ def create_bot(
data = result["data"]["poeBotCreate"]
if data["status"] != "success":
- raise RuntimeError(
- f"Poe returned an error while trying to create a bot: {data['status']}"
- )
+ raise RuntimeError(f"Poe returned an error while trying to create a bot: {data['status']}")
self.get_bots()
return data
@@ -568,9 +537,7 @@ def edit_bot(
data = result["data"]["poeBotEdit"]
if data["status"] != "success":
- raise RuntimeError(
- f"Poe returned an error while trying to edit a bot: {data['status']}"
- )
+ raise RuntimeError(f"Poe returned an error while trying to edit a bot: {data['status']}")
self.get_bots()
return data
diff --git a/quora/cookies.txt b/gpt4free/quora/cookies.txt
similarity index 100%
rename from quora/cookies.txt
rename to gpt4free/quora/cookies.txt
diff --git a/quora/graphql/AddHumanMessageMutation.graphql b/gpt4free/quora/graphql/AddHumanMessageMutation.graphql
similarity index 100%
rename from quora/graphql/AddHumanMessageMutation.graphql
rename to gpt4free/quora/graphql/AddHumanMessageMutation.graphql
diff --git a/quora/graphql/AddMessageBreakMutation.graphql b/gpt4free/quora/graphql/AddMessageBreakMutation.graphql
similarity index 100%
rename from quora/graphql/AddMessageBreakMutation.graphql
rename to gpt4free/quora/graphql/AddMessageBreakMutation.graphql
diff --git a/quora/graphql/AutoSubscriptionMutation.graphql b/gpt4free/quora/graphql/AutoSubscriptionMutation.graphql
similarity index 100%
rename from quora/graphql/AutoSubscriptionMutation.graphql
rename to gpt4free/quora/graphql/AutoSubscriptionMutation.graphql
diff --git a/quora/graphql/BioFragment.graphql b/gpt4free/quora/graphql/BioFragment.graphql
similarity index 100%
rename from quora/graphql/BioFragment.graphql
rename to gpt4free/quora/graphql/BioFragment.graphql
diff --git a/quora/graphql/ChatAddedSubscription.graphql b/gpt4free/quora/graphql/ChatAddedSubscription.graphql
similarity index 100%
rename from quora/graphql/ChatAddedSubscription.graphql
rename to gpt4free/quora/graphql/ChatAddedSubscription.graphql
diff --git a/quora/graphql/ChatFragment.graphql b/gpt4free/quora/graphql/ChatFragment.graphql
similarity index 100%
rename from quora/graphql/ChatFragment.graphql
rename to gpt4free/quora/graphql/ChatFragment.graphql
diff --git a/quora/graphql/ChatListPaginationQuery.graphql b/gpt4free/quora/graphql/ChatListPaginationQuery.graphql
similarity index 100%
rename from quora/graphql/ChatListPaginationQuery.graphql
rename to gpt4free/quora/graphql/ChatListPaginationQuery.graphql
diff --git a/quora/graphql/ChatPaginationQuery.graphql b/gpt4free/quora/graphql/ChatPaginationQuery.graphql
similarity index 100%
rename from quora/graphql/ChatPaginationQuery.graphql
rename to gpt4free/quora/graphql/ChatPaginationQuery.graphql
diff --git a/quora/graphql/ChatViewQuery.graphql b/gpt4free/quora/graphql/ChatViewQuery.graphql
similarity index 100%
rename from quora/graphql/ChatViewQuery.graphql
rename to gpt4free/quora/graphql/ChatViewQuery.graphql
diff --git a/quora/graphql/DeleteHumanMessagesMutation.graphql b/gpt4free/quora/graphql/DeleteHumanMessagesMutation.graphql
similarity index 100%
rename from quora/graphql/DeleteHumanMessagesMutation.graphql
rename to gpt4free/quora/graphql/DeleteHumanMessagesMutation.graphql
diff --git a/quora/graphql/DeleteMessageMutation.graphql b/gpt4free/quora/graphql/DeleteMessageMutation.graphql
similarity index 100%
rename from quora/graphql/DeleteMessageMutation.graphql
rename to gpt4free/quora/graphql/DeleteMessageMutation.graphql
diff --git a/quora/graphql/HandleFragment.graphql b/gpt4free/quora/graphql/HandleFragment.graphql
similarity index 100%
rename from quora/graphql/HandleFragment.graphql
rename to gpt4free/quora/graphql/HandleFragment.graphql
diff --git a/quora/graphql/LoginWithVerificationCodeMutation.graphql b/gpt4free/quora/graphql/LoginWithVerificationCodeMutation.graphql
similarity index 100%
rename from quora/graphql/LoginWithVerificationCodeMutation.graphql
rename to gpt4free/quora/graphql/LoginWithVerificationCodeMutation.graphql
diff --git a/quora/graphql/MessageAddedSubscription.graphql b/gpt4free/quora/graphql/MessageAddedSubscription.graphql
similarity index 100%
rename from quora/graphql/MessageAddedSubscription.graphql
rename to gpt4free/quora/graphql/MessageAddedSubscription.graphql
diff --git a/quora/graphql/MessageDeletedSubscription.graphql b/gpt4free/quora/graphql/MessageDeletedSubscription.graphql
similarity index 100%
rename from quora/graphql/MessageDeletedSubscription.graphql
rename to gpt4free/quora/graphql/MessageDeletedSubscription.graphql
diff --git a/quora/graphql/MessageFragment.graphql b/gpt4free/quora/graphql/MessageFragment.graphql
similarity index 100%
rename from quora/graphql/MessageFragment.graphql
rename to gpt4free/quora/graphql/MessageFragment.graphql
diff --git a/quora/graphql/MessageRemoveVoteMutation.graphql b/gpt4free/quora/graphql/MessageRemoveVoteMutation.graphql
similarity index 100%
rename from quora/graphql/MessageRemoveVoteMutation.graphql
rename to gpt4free/quora/graphql/MessageRemoveVoteMutation.graphql
diff --git a/quora/graphql/MessageSetVoteMutation.graphql b/gpt4free/quora/graphql/MessageSetVoteMutation.graphql
similarity index 100%
rename from quora/graphql/MessageSetVoteMutation.graphql
rename to gpt4free/quora/graphql/MessageSetVoteMutation.graphql
diff --git a/quora/graphql/PoeBotCreateMutation.graphql b/gpt4free/quora/graphql/PoeBotCreateMutation.graphql
similarity index 100%
rename from quora/graphql/PoeBotCreateMutation.graphql
rename to gpt4free/quora/graphql/PoeBotCreateMutation.graphql
diff --git a/quora/graphql/PoeBotEditMutation.graphql b/gpt4free/quora/graphql/PoeBotEditMutation.graphql
similarity index 100%
rename from quora/graphql/PoeBotEditMutation.graphql
rename to gpt4free/quora/graphql/PoeBotEditMutation.graphql
diff --git a/quora/graphql/SendMessageMutation.graphql b/gpt4free/quora/graphql/SendMessageMutation.graphql
similarity index 100%
rename from quora/graphql/SendMessageMutation.graphql
rename to gpt4free/quora/graphql/SendMessageMutation.graphql
diff --git a/quora/graphql/SendVerificationCodeForLoginMutation.graphql b/gpt4free/quora/graphql/SendVerificationCodeForLoginMutation.graphql
similarity index 100%
rename from quora/graphql/SendVerificationCodeForLoginMutation.graphql
rename to gpt4free/quora/graphql/SendVerificationCodeForLoginMutation.graphql
diff --git a/quora/graphql/ShareMessagesMutation.graphql b/gpt4free/quora/graphql/ShareMessagesMutation.graphql
similarity index 100%
rename from quora/graphql/ShareMessagesMutation.graphql
rename to gpt4free/quora/graphql/ShareMessagesMutation.graphql
diff --git a/quora/graphql/SignupWithVerificationCodeMutation.graphql b/gpt4free/quora/graphql/SignupWithVerificationCodeMutation.graphql
similarity index 100%
rename from quora/graphql/SignupWithVerificationCodeMutation.graphql
rename to gpt4free/quora/graphql/SignupWithVerificationCodeMutation.graphql
diff --git a/quora/graphql/StaleChatUpdateMutation.graphql b/gpt4free/quora/graphql/StaleChatUpdateMutation.graphql
similarity index 100%
rename from quora/graphql/StaleChatUpdateMutation.graphql
rename to gpt4free/quora/graphql/StaleChatUpdateMutation.graphql
diff --git a/quora/graphql/SubscriptionsMutation.graphql b/gpt4free/quora/graphql/SubscriptionsMutation.graphql
similarity index 100%
rename from quora/graphql/SubscriptionsMutation.graphql
rename to gpt4free/quora/graphql/SubscriptionsMutation.graphql
diff --git a/quora/graphql/SummarizePlainPostQuery.graphql b/gpt4free/quora/graphql/SummarizePlainPostQuery.graphql
similarity index 100%
rename from quora/graphql/SummarizePlainPostQuery.graphql
rename to gpt4free/quora/graphql/SummarizePlainPostQuery.graphql
diff --git a/quora/graphql/SummarizeQuotePostQuery.graphql b/gpt4free/quora/graphql/SummarizeQuotePostQuery.graphql
similarity index 100%
rename from quora/graphql/SummarizeQuotePostQuery.graphql
rename to gpt4free/quora/graphql/SummarizeQuotePostQuery.graphql
diff --git a/quora/graphql/SummarizeSharePostQuery.graphql b/gpt4free/quora/graphql/SummarizeSharePostQuery.graphql
similarity index 100%
rename from quora/graphql/SummarizeSharePostQuery.graphql
rename to gpt4free/quora/graphql/SummarizeSharePostQuery.graphql
diff --git a/quora/graphql/UserSnippetFragment.graphql b/gpt4free/quora/graphql/UserSnippetFragment.graphql
similarity index 100%
rename from quora/graphql/UserSnippetFragment.graphql
rename to gpt4free/quora/graphql/UserSnippetFragment.graphql
diff --git a/quora/graphql/ViewerInfoQuery.graphql b/gpt4free/quora/graphql/ViewerInfoQuery.graphql
similarity index 100%
rename from quora/graphql/ViewerInfoQuery.graphql
rename to gpt4free/quora/graphql/ViewerInfoQuery.graphql
diff --git a/quora/graphql/ViewerStateFragment.graphql b/gpt4free/quora/graphql/ViewerStateFragment.graphql
similarity index 100%
rename from quora/graphql/ViewerStateFragment.graphql
rename to gpt4free/quora/graphql/ViewerStateFragment.graphql
diff --git a/quora/graphql/ViewerStateUpdatedSubscription.graphql b/gpt4free/quora/graphql/ViewerStateUpdatedSubscription.graphql
similarity index 100%
rename from quora/graphql/ViewerStateUpdatedSubscription.graphql
rename to gpt4free/quora/graphql/ViewerStateUpdatedSubscription.graphql
diff --git a/quora/graphql/__init__.py b/gpt4free/quora/graphql/__init__.py
similarity index 100%
rename from quora/graphql/__init__.py
rename to gpt4free/quora/graphql/__init__.py
diff --git a/quora/mail.py b/gpt4free/quora/mail.py
similarity index 71%
rename from quora/mail.py
rename to gpt4free/quora/mail.py
index c470786..864d956 100644
--- a/quora/mail.py
+++ b/gpt4free/quora/mail.py
@@ -38,17 +38,16 @@ def get_mail(self):
return self.email
def get_message(self):
- print("waiting for code...")
+ print("Waiting for message...")
while True:
sleep(2)
- mail_token = self.client.post(
- "https://www.emailnator.com/message-list", json={"email": self.email}
- )
+ mail_token = self.client.post("https://www.emailnator.com/message-list", json={"email": self.email})
mail_token = loads(mail_token.text)["messageData"]
if len(mail_token) == 2:
+ print("Message received!")
print(mail_token[1]["messageID"])
break
@@ -63,4 +62,19 @@ def get_message(self):
return mail_context.text
def get_verification_code(self):
- return findall(r';">(\d{6,7})', self.get_message())[0]
+ message = self.get_message()
+ code = findall(r';">(\d{6,7})', message)[0]
+ print(f"Verification code: {code}")
+ return code
+
+ def clear_inbox(self):
+ print("Clearing inbox...")
+ self.client.post(
+ "https://www.emailnator.com/delete-all",
+ json={"email": self.email},
+ )
+ print("Inbox cleared!")
+
+ def __del__(self):
+ if self.email:
+ self.clear_inbox()
diff --git a/gpt4free/theb/README.md b/gpt4free/theb/README.md
new file mode 100644
index 0000000..a4abdf6
--- /dev/null
+++ b/gpt4free/theb/README.md
@@ -0,0 +1,11 @@
+### Example: `theb` (use like openai pypi package)
+
+```python
+# import library
+from gpt4free import theb
+
+# simple streaming completion
+for token in theb.Completion.create('hello world'):
+ print(token, end='', flush=True)
+print("")
+```
diff --git a/gpt4free/theb/__init__.py b/gpt4free/theb/__init__.py
new file mode 100644
index 0000000..9605387
--- /dev/null
+++ b/gpt4free/theb/__init__.py
@@ -0,0 +1,54 @@
+from json import loads
+from queue import Queue, Empty
+from re import findall
+from threading import Thread
+from typing import Generator
+
+from curl_cffi import requests
+from fake_useragent import UserAgent
+
+
+class Completion:
+ # experimental
+ part1 = '{"role":"assistant","id":"chatcmpl'
+ part2 = '"},"index":0,"finish_reason":null}]}}'
+ regex = rf'{part1}(.*){part2}'
+
+ timer = None
+ message_queue = Queue()
+ stream_completed = False
+
+ @staticmethod
+ def request(prompt: str):
+ headers = {
+ 'authority': 'chatbot.theb.ai',
+ 'content-type': 'application/json',
+ 'origin': 'https://chatbot.theb.ai',
+ 'user-agent': UserAgent().random,
+ }
+
+ requests.post(
+ 'https://chatbot.theb.ai/api/chat-process',
+ headers=headers,
+ content_callback=Completion.handle_stream_response,
+ json={'prompt': prompt, 'options': {}},
+ )
+
+ Completion.stream_completed = True
+
+ @staticmethod
+ def create(prompt: str) -> Generator[str, None, None]:
+ Thread(target=Completion.request, args=[prompt]).start()
+
+ while not Completion.stream_completed or not Completion.message_queue.empty():
+ try:
+ message = Completion.message_queue.get(timeout=0.01)
+ for message in findall(Completion.regex, message):
+ yield loads(Completion.part1 + message + Completion.part2)['delta']
+
+ except Empty:
+ pass
+
+ @staticmethod
+ def handle_stream_response(response):
+ Completion.message_queue.put(response.decode())
diff --git a/gpt4free/theb/__pycache__/__init__.cpython-311.pyc b/gpt4free/theb/__pycache__/__init__.cpython-311.pyc
new file mode 100644
index 0000000..b82233d
Binary files /dev/null and b/gpt4free/theb/__pycache__/__init__.cpython-311.pyc differ
diff --git a/gpt4free/theb/theb_test.py b/gpt4free/theb/theb_test.py
new file mode 100644
index 0000000..c57d5c6
--- /dev/null
+++ b/gpt4free/theb/theb_test.py
@@ -0,0 +1,4 @@
+import theb
+
+for token in theb.Completion.create('hello world'):
+ print(token, end='', flush=True)
diff --git a/gpt4free/you/README.md b/gpt4free/you/README.md
new file mode 100644
index 0000000..11b4723
--- /dev/null
+++ b/gpt4free/you/README.md
@@ -0,0 +1,38 @@
+### Example: `you` (use like openai pypi package)
+
+```python
+
+from gpt4free import you
+
+# simple request with links and details
+response = you.Completion.create(
+ prompt="hello world",
+ detailed=True,
+ include_links=True, )
+
+print(response)
+
+# {
+# "response": "...",
+# "links": [...],
+# "extra": {...},
+# "slots": {...}
+# }
+# }
+
+# chatbot
+
+chat = []
+
+while True:
+ prompt = input("You: ")
+ if prompt == 'q':
+ break
+ response = you.Completion.create(
+ prompt=prompt,
+ chat=chat)
+
+ print("Bot:", response["response"])
+
+ chat.append({"question": prompt, "answer": response["response"]})
+```
diff --git a/gpt4free/you/__init__.py b/gpt4free/you/__init__.py
new file mode 100644
index 0000000..97b4846
--- /dev/null
+++ b/gpt4free/you/__init__.py
@@ -0,0 +1,108 @@
+import json
+import re
+from typing import Optional, List, Dict, Any
+from uuid import uuid4
+
+from fake_useragent import UserAgent
+from pydantic import BaseModel
+from tls_client import Session
+
+
+class PoeResponse(BaseModel):
+ text: Optional[str] = None
+ links: List[str] = []
+ extra: Dict[str, Any] = {}
+
+
+class Completion:
+ @staticmethod
+ def create(
+ prompt: str,
+ page: int = 1,
+ count: int = 10,
+ safe_search: str = 'Moderate',
+ on_shopping_page: bool = False,
+ mkt: str = '',
+ response_filter: str = 'WebPages,Translations,TimeZone,Computation,RelatedSearches',
+ domain: str = 'youchat',
+ query_trace_id: str = None,
+ chat: list = None,
+ include_links: bool = False,
+ detailed: bool = False,
+ debug: bool = False,
+ ) -> PoeResponse:
+ if chat is None:
+ chat = []
+
+ client = Session(client_identifier='chrome_108')
+ client.headers = Completion.__get_headers()
+
+ response = client.get(
+ f'https://you.com/api/streamingSearch',
+ params={
+ 'q': prompt,
+ 'page': page,
+ 'count': count,
+ 'safeSearch': safe_search,
+ 'onShoppingPage': on_shopping_page,
+ 'mkt': mkt,
+ 'responseFilter': response_filter,
+ 'domain': domain,
+ 'queryTraceId': str(uuid4()) if query_trace_id is None else query_trace_id,
+ 'chat': str(chat), # {'question':'','answer':' ''}
+ },
+ )
+
+ if debug:
+ print('\n\n------------------\n\n')
+ print(response.text)
+ print('\n\n------------------\n\n')
+
+ if 'youChatToken' not in response.text:
+ return Completion.__get_failure_response()
+
+ you_chat_serp_results = re.search(
+ r'(?<=event: youChatSerpResults\ndata:)(.*\n)*?(?=event: )', response.text
+ ).group()
+ third_party_search_results = re.search(
+ r'(?<=event: thirdPartySearchResults\ndata:)(.*\n)*?(?=event: )', response.text
+ ).group()
+ # slots = findall(r"slots\ndata: (.*)\n\nevent", response.text)[0]
+
+ text = ''.join(re.findall(r'{\"youChatToken\": \"(.*?)\"}', response.text))
+
+ extra = {
+ 'youChatSerpResults': json.loads(you_chat_serp_results),
+ # 'slots' : loads(slots)
+ }
+
+ response = PoeResponse(text=text.replace('\\n', '\n').replace('\\\\', '\\').replace('\\"', '"'))
+ if include_links:
+ response.links = json.loads(third_party_search_results)['search']['third_party_search_results']
+
+ if detailed:
+ response.extra = extra
+
+ return response
+
+ @staticmethod
+ def __get_headers() -> dict:
+ return {
+ 'authority': 'you.com',
+ 'accept': 'text/event-stream',
+ 'accept-language': 'en,fr-FR;q=0.9,fr;q=0.8,es-ES;q=0.7,es;q=0.6,en-US;q=0.5,am;q=0.4,de;q=0.3',
+ 'cache-control': 'no-cache',
+ 'referer': 'https://you.com/search?q=who+are+you&tbm=youchat',
+ 'sec-ch-ua': '"Not_A Brand";v="99", "Google Chrome";v="109", "Chromium";v="109"',
+ 'sec-ch-ua-mobile': '?0',
+ 'sec-ch-ua-platform': '"Windows"',
+ 'sec-fetch-dest': 'empty',
+ 'sec-fetch-mode': 'cors',
+ 'sec-fetch-site': 'same-origin',
+ 'cookie': f'safesearch_guest=Moderate; uuid_guest={str(uuid4())}',
+ 'user-agent': UserAgent().random,
+ }
+
+ @staticmethod
+ def __get_failure_response() -> PoeResponse:
+ return PoeResponse(text='Unable to fetch the response, Please try again.')
diff --git a/gpt4free/you/__pycache__/__init__.cpython-311.pyc b/gpt4free/you/__pycache__/__init__.cpython-311.pyc
new file mode 100644
index 0000000..8d01e03
Binary files /dev/null and b/gpt4free/you/__pycache__/__init__.cpython-311.pyc differ
diff --git a/main.py b/main.py
index 0ede4cf..493f080 100644
--- a/main.py
+++ b/main.py
@@ -1,7 +1,8 @@
+from gpt4free import Provider
from termcolor import colored
from sys import platform
from os import system
-import quora
+import gpt4free
def clear():
if platform == "linux" or platform == "linux2" or platform == "unix":
@@ -29,8 +30,8 @@ def clear():
while True:
youinput = input(colored("\n👨 You ", "yellow") + colored(">> ", "green"))
try:
- response = quora.Completion.create(model = 'sage', prompt = youinput, token = 'AuYSfjZVc5eyAzrWjKmjFg%3D%3D')
- output = response.completion.choices[0].text
+ response = gpt4free.Completion.create(Provider.Theb, prompt=youinput)
+ output = response
print(colored("\n🤖 CHATGPT V4.0 ", "cyan") + colored(">> ", "green") + output)
except Exception as e:
print(colored("\n🛑 ERROR ", "light_red") + colored(">> ", "green") + str(e))
diff --git a/quora/__init__.py b/quora/__init__.py
deleted file mode 100644
index 4c78313..0000000
--- a/quora/__init__.py
+++ /dev/null
@@ -1,487 +0,0 @@
-import json
-from datetime import datetime
-from hashlib import md5
-from json import dumps
-from pathlib import Path
-from random import choice, choices, randint
-from re import search, findall
-from string import ascii_letters, digits
-from typing import Optional
-from urllib.parse import unquote
-
-import selenium.webdriver.support.expected_conditions as EC
-from pypasser import reCaptchaV3
-from requests import Session
-from selenium import webdriver
-from selenium.webdriver.common.by import By
-from selenium.webdriver.support.wait import WebDriverWait
-from tls_client import Session as TLS
-
-from quora.api import Client as PoeClient
-from quora.mail import Emailnator
-
-# from twocaptcha import TwoCaptcha
-# solver = TwoCaptcha('72747bf24a9d89b4dcc1b24875efd358')
-
-MODELS = {
- "Sage": "capybara",
- "GPT-4": "beaver",
- "Claude+": "a2_2",
- "Claude-instant": "a2",
- "ChatGPT": "chinchilla",
- "Dragonfly": "nutria",
- "NeevaAI": "hutia",
-}
-
-
-def extract_formkey(html):
- script_regex = r""
- script_text = search(script_regex, html).group(1)
- key_regex = r'var .="([0-9a-f]+)",'
- key_text = search(key_regex, script_text).group(1)
- cipher_regex = r".\[(\d+)\]=.\[(\d+)\]"
- cipher_pairs = findall(cipher_regex, script_text)
-
- formkey_list = [""] * len(cipher_pairs)
- for pair in cipher_pairs:
- formkey_index, key_index = map(int, pair)
- formkey_list[formkey_index] = key_text[key_index]
- formkey = "".join(formkey_list)
-
- return formkey
-
-
-class PoeResponse:
- class Completion:
- class Choices:
- def __init__(self, choice: dict) -> None:
- self.text = choice["text"]
- self.content = self.text.encode()
- self.index = choice["index"]
- self.logprobs = choice["logprobs"]
- self.finish_reason = choice["finish_reason"]
-
- def __repr__(self) -> str:
- return f"""<__main__.APIResponse.Completion.Choices(\n text = {self.text.encode()},\n index = {self.index},\n logprobs = {self.logprobs},\n finish_reason = {self.finish_reason})object at 0x1337>"""
-
- def __init__(self, choices: dict) -> None:
- self.choices = [self.Choices(choice) for choice in choices]
-
- class Usage:
- def __init__(self, usage_dict: dict) -> None:
- self.prompt_tokens = usage_dict["prompt_tokens"]
- self.completion_tokens = usage_dict["completion_tokens"]
- self.total_tokens = usage_dict["total_tokens"]
-
- def __repr__(self):
- return f"""<__main__.APIResponse.Usage(\n prompt_tokens = {self.prompt_tokens},\n completion_tokens = {self.completion_tokens},\n total_tokens = {self.total_tokens})object at 0x1337>"""
-
- def __init__(self, response_dict: dict) -> None:
- self.response_dict = response_dict
- self.id = response_dict["id"]
- self.object = response_dict["object"]
- self.created = response_dict["created"]
- self.model = response_dict["model"]
- self.completion = self.Completion(response_dict["choices"])
- self.usage = self.Usage(response_dict["usage"])
-
- def json(self) -> dict:
- return self.response_dict
-
-
-class ModelResponse:
- def __init__(self, json_response: dict) -> None:
- self.id = json_response["data"]["poeBotCreate"]["bot"]["id"]
- self.name = json_response["data"]["poeBotCreate"]["bot"]["displayName"]
- self.limit = json_response["data"]["poeBotCreate"]["bot"]["messageLimit"][
- "dailyLimit"
- ]
- self.deleted = json_response["data"]["poeBotCreate"]["bot"]["deletionState"]
-
-
-class Model:
- def create(
- token: str,
- model: str = "gpt-3.5-turbo", # claude-instant
- system_prompt: str = "You are ChatGPT a large language model developed by Openai. Answer as consisely as possible",
- description: str = "gpt-3.5 language model from openai, skidded by poe.com",
- handle: str = None,
- ) -> ModelResponse:
- models = {
- "gpt-3.5-turbo": "chinchilla",
- "claude-instant-v1.0": "a2",
- "gpt-4": "beaver",
- }
-
- if not handle:
- handle = f"gptx{randint(1111111, 9999999)}"
-
- client = Session()
- client.cookies["p-b"] = token
-
- formkey = extract_formkey(client.get("https://poe.com").text)
- settings = client.get("https://poe.com/api/settings").json()
-
- client.headers = {
- "host": "poe.com",
- "origin": "https://poe.com",
- "referer": "https://poe.com/",
- "poe-formkey": formkey,
- "poe-tchannel": settings["tchannelData"]["channel"],
- "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36",
- "connection": "keep-alive",
- "sec-ch-ua": '"Chromium";v="112", "Google Chrome";v="112", "Not:A-Brand";v="99"',
- "sec-ch-ua-mobile": "?0",
- "sec-ch-ua-platform": '"macOS"',
- "content-type": "application/json",
- "sec-fetch-site": "same-origin",
- "sec-fetch-mode": "cors",
- "sec-fetch-dest": "empty",
- "accept": "*/*",
- "accept-encoding": "gzip, deflate, br",
- "accept-language": "en-GB,en-US;q=0.9,en;q=0.8",
- }
-
- payload = dumps(
- separators=(",", ":"),
- obj={
- "queryName": "CreateBotMain_poeBotCreate_Mutation",
- "variables": {
- "model": models[model],
- "handle": handle,
- "prompt": system_prompt,
- "isPromptPublic": True,
- "introduction": "",
- "description": description,
- "profilePictureUrl": "https://qph.fs.quoracdn.net/main-qimg-24e0b480dcd946e1cc6728802c5128b6",
- "apiUrl": None,
- "apiKey": "".join(choices(ascii_letters + digits, k=32)),
- "isApiBot": False,
- "hasLinkification": False,
- "hasMarkdownRendering": False,
- "hasSuggestedReplies": False,
- "isPrivateBot": False,
- },
- "query": "mutation CreateBotMain_poeBotCreate_Mutation(\n $model: String!\n $handle: String!\n $prompt: String!\n $isPromptPublic: Boolean!\n $introduction: String!\n $description: String!\n $profilePictureUrl: String\n $apiUrl: String\n $apiKey: String\n $isApiBot: Boolean\n $hasLinkification: Boolean\n $hasMarkdownRendering: Boolean\n $hasSuggestedReplies: Boolean\n $isPrivateBot: Boolean\n) {\n poeBotCreate(model: $model, handle: $handle, promptPlaintext: $prompt, isPromptPublic: $isPromptPublic, introduction: $introduction, description: $description, profilePicture: $profilePictureUrl, apiUrl: $apiUrl, apiKey: $apiKey, isApiBot: $isApiBot, hasLinkification: $hasLinkification, hasMarkdownRendering: $hasMarkdownRendering, hasSuggestedReplies: $hasSuggestedReplies, isPrivateBot: $isPrivateBot) {\n status\n bot {\n id\n ...BotHeader_bot\n }\n }\n}\n\nfragment BotHeader_bot on Bot {\n displayName\n messageLimit {\n dailyLimit\n }\n ...BotImage_bot\n ...BotLink_bot\n ...IdAnnotation_node\n ...botHelpers_useViewerCanAccessPrivateBot\n ...botHelpers_useDeletion_bot\n}\n\nfragment BotImage_bot on Bot {\n displayName\n ...botHelpers_useDeletion_bot\n ...BotImage_useProfileImage_bot\n}\n\nfragment BotImage_useProfileImage_bot on Bot {\n image {\n __typename\n ... on LocalBotImage {\n localName\n }\n ... on UrlBotImage {\n url\n }\n }\n ...botHelpers_useDeletion_bot\n}\n\nfragment BotLink_bot on Bot {\n displayName\n}\n\nfragment IdAnnotation_node on Node {\n __isNode: __typename\n id\n}\n\nfragment botHelpers_useDeletion_bot on Bot {\n deletionState\n}\n\nfragment botHelpers_useViewerCanAccessPrivateBot on Bot {\n isPrivateBot\n viewerIsCreator\n}\n",
- },
- )
-
- base_string = payload + client.headers["poe-formkey"] + "WpuLMiXEKKE98j56k"
- client.headers["poe-tag-id"] = md5(base_string.encode()).hexdigest()
-
- response = client.post("https://poe.com/api/gql_POST", data=payload)
-
- if "success" not in response.text:
- raise Exception(
- """
- Bot creation Failed
- !! Important !!
- Bot creation was not enabled on this account
- please use: quora.Account.create with enable_bot_creation set to True
- """
- )
-
- return ModelResponse(response.json())
-
-
-class Account:
- def create(
- proxy: Optional[str] = None,
- logging: bool = False,
- enable_bot_creation: bool = False,
- ):
- client = TLS(client_identifier="chrome110")
- client.proxies = (
- {"http": f"http://{proxy}", "https": f"http://{proxy}"} if proxy else None
- )
-
- mail_client = Emailnator()
- mail_address = mail_client.get_mail()
-
- if logging:
- print("email", mail_address)
-
- client.headers = {
- "authority": "poe.com",
- "accept": "*/*",
- "accept-language": "en,fr-FR;q=0.9,fr;q=0.8,es-ES;q=0.7,es;q=0.6,en-US;q=0.5,am;q=0.4,de;q=0.3",
- "content-type": "application/json",
- "origin": "https://poe.com",
- "poe-tag-id": "null",
- "referer": "https://poe.com/login",
- "sec-ch-ua": '"Chromium";v="112", "Google Chrome";v="112", "Not:A-Brand";v="99"',
- "sec-ch-ua-mobile": "?0",
- "sec-ch-ua-platform": '"macOS"',
- "sec-fetch-dest": "empty",
- "sec-fetch-mode": "cors",
- "sec-fetch-site": "same-origin",
- "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36",
- "poe-formkey": extract_formkey(client.get("https://poe.com/login").text),
- "poe-tchannel": client.get("https://poe.com/api/settings").json()[
- "tchannelData"
- ]["channel"],
- }
-
- token = reCaptchaV3(
- "https://www.recaptcha.net/recaptcha/enterprise/anchor?ar=1&k=6LflhEElAAAAAI_ewVwRWI9hsyV4mbZnYAslSvlG&co=aHR0cHM6Ly9wb2UuY29tOjQ0Mw..&hl=en&v=4PnKmGB9wRHh1i04o7YUICeI&size=invisible&cb=bi6ivxoskyal"
- )
- # token = solver.recaptcha(sitekey='6LflhEElAAAAAI_ewVwRWI9hsyV4mbZnYAslSvlG',
- # url = 'https://poe.com/login?redirect_url=%2F',
- # version = 'v3',
- # enterprise = 1,
- # invisible = 1,
- # action = 'login',)['code']
-
- payload = dumps(
- separators=(",", ":"),
- obj={
- "queryName": "MainSignupLoginSection_sendVerificationCodeMutation_Mutation",
- "variables": {
- "emailAddress": mail_address,
- "phoneNumber": None,
- "recaptchaToken": token,
- },
- "query": "mutation MainSignupLoginSection_sendVerificationCodeMutation_Mutation(\n $emailAddress: String\n $phoneNumber: String\n $recaptchaToken: String\n) {\n sendVerificationCode(verificationReason: login, emailAddress: $emailAddress, phoneNumber: $phoneNumber, recaptchaToken: $recaptchaToken) {\n status\n errorMessage\n }\n}\n",
- },
- )
-
- base_string = payload + client.headers["poe-formkey"] + "WpuLMiXEKKE98j56k"
- client.headers["poe-tag-id"] = md5(base_string.encode()).hexdigest()
-
- print(dumps(client.headers, indent=4))
-
- response = client.post("https://poe.com/api/gql_POST", data=payload)
-
- if "automated_request_detected" in response.text:
- print("please try using a proxy / wait for fix")
-
- if "Bad Request" in response.text:
- if logging:
- print("bad request, retrying...", response.json())
- quit()
-
- if logging:
- print("send_code", response.json())
-
- mail_content = mail_client.get_message()
- mail_token = findall(r';">(\d{6,7})', mail_content)[0]
-
- if logging:
- print("code", mail_token)
-
- payload = dumps(
- separators=(",", ":"),
- obj={
- "queryName": "SignupOrLoginWithCodeSection_signupWithVerificationCodeMutation_Mutation",
- "variables": {
- "verificationCode": str(mail_token),
- "emailAddress": mail_address,
- "phoneNumber": None,
- },
- "query": "mutation SignupOrLoginWithCodeSection_signupWithVerificationCodeMutation_Mutation(\n $verificationCode: String!\n $emailAddress: String\n $phoneNumber: String\n) {\n signupWithVerificationCode(verificationCode: $verificationCode, emailAddress: $emailAddress, phoneNumber: $phoneNumber) {\n status\n errorMessage\n }\n}\n",
- },
- )
-
- base_string = payload + client.headers["poe-formkey"] + "WpuLMiXEKKE98j56k"
- client.headers["poe-tag-id"] = md5(base_string.encode()).hexdigest()
-
- response = client.post("https://poe.com/api/gql_POST", data=payload)
- if logging:
- print("verify_code", response.json())
-
- def get(self):
- cookies = (
- open(Path(__file__).resolve().parent / "cookies.txt", "r")
- .read()
- .splitlines()
- )
- return choice(cookies)
-
-
-class StreamingCompletion:
- def create(
- model: str = "gpt-4",
- custom_model: bool = None,
- prompt: str = "hello world",
- token: str = "",
- ):
- _model = MODELS[model] if not custom_model else custom_model
-
- client = PoeClient(token)
-
- for chunk in client.send_message(_model, prompt):
- yield PoeResponse(
- {
- "id": chunk["messageId"],
- "object": "text_completion",
- "created": chunk["creationTime"],
- "model": _model,
- "choices": [
- {
- "text": chunk["text_new"],
- "index": 0,
- "logprobs": None,
- "finish_reason": "stop",
- }
- ],
- "usage": {
- "prompt_tokens": len(prompt),
- "completion_tokens": len(chunk["text_new"]),
- "total_tokens": len(prompt) + len(chunk["text_new"]),
- },
- }
- )
-
-
-class Completion:
- def create(
- model: str = "gpt-4",
- custom_model: str = None,
- prompt: str = "hello world",
- token: str = "",
- ):
- models = {
- "sage": "capybara",
- "gpt-4": "beaver",
- "claude-v1.2": "a2_2",
- "claude-instant-v1.0": "a2",
- "gpt-3.5-turbo": "chinchilla",
- }
-
- _model = models[model] if not custom_model else custom_model
-
- client = PoeClient(token)
-
- for chunk in client.send_message(_model, prompt):
- pass
-
- return PoeResponse(
- {
- "id": chunk["messageId"],
- "object": "text_completion",
- "created": chunk["creationTime"],
- "model": _model,
- "choices": [
- {
- "text": chunk["text"],
- "index": 0,
- "logprobs": None,
- "finish_reason": "stop",
- }
- ],
- "usage": {
- "prompt_tokens": len(prompt),
- "completion_tokens": len(chunk["text"]),
- "total_tokens": len(prompt) + len(chunk["text"]),
- },
- }
- )
-
-
-class Poe:
- def __init__(self, model: str = "ChatGPT"):
- # validating the model
- if model and model not in MODELS:
- raise RuntimeError(
- "Sorry, the model you provided does not exist. Please check and try again."
- )
- self.model = MODELS[model]
- self.cookie = self.__load_cookie()
- self.client = PoeClient(self.cookie)
-
- def __load_cookie(self) -> str:
- if (cookie_file := Path("./quora/cookie.json")).exists():
- with cookie_file.open() as fp:
- cookie = json.load(fp)
- if datetime.fromtimestamp(cookie["expiry"]) < datetime.now():
- cookie = self.__register_and_get_cookie()
- else:
- print("Loading the cookie from file")
- else:
- cookie = self.__register_and_get_cookie()
-
- return unquote(cookie["value"])
-
- @classmethod
- def __register_and_get_cookie(cls) -> dict:
- mail_client = Emailnator()
- mail_address = mail_client.get_mail()
-
- print(mail_address)
- options = webdriver.FirefoxOptions()
- # options.add_argument("-headless")
- try:
- driver = webdriver.Firefox(options=options)
-
- except Exception:
- raise Exception(b'The error message you are receiving is due to the `geckodriver` executable not being found in your system\'s PATH. To resolve this issue, you need to download the geckodriver and add its location to your system\'s PATH.\n\nHere are the steps to resolve the issue:\n\n1. Download the geckodriver for your platform (Windows, macOS, or Linux) from the following link: https://github.com/mozilla/geckodriver/releases\n\n2. Extract the downloaded archive and locate the geckodriver executable.\n\n3. Add the geckodriver executable to your system\'s PATH.\n\nFor macOS and Linux:\n\n- Open a terminal window.\n- Move the geckodriver executable to a directory that is already in your PATH, or create a new directory and add it to your PATH:\n\n```bash\n# Example: Move geckodriver to /usr/local/bin\nmv /path/to/your/geckodriver /usr/local/bin\n```\n\n- If you created a new directory, add it to your PATH:\n\n```bash\n# Example: Add a new directory to PATH\nexport PATH=$PATH:/path/to/your/directory\n```\n\nFor Windows:\n\n- Right-click on "My Computer" or "This PC" and select "Properties".\n- Click on "Advanced system settings".\n- Click on the "Environment Variables" button.\n- In the "System variables" section, find the "Path" variable, select it, and click "Edit".\n- Click "New" and add the path to the directory containing the geckodriver executable.\n\nAfter adding the geckodriver to your PATH, restart your terminal or command prompt and try running your script again. The error should be resolved.')
-
- driver.get("https://www.poe.com")
-
- # clicking use email button
- driver.find_element(By.XPATH, '//button[contains(text(), "Use email")]').click()
-
- email = WebDriverWait(driver, 30).until(
- EC.presence_of_element_located((By.XPATH, '//input[@type="email"]'))
- )
- email.send_keys(mail_address)
- driver.find_element(By.XPATH, '//button[text()="Go"]').click()
-
- code = findall(r';">(\d{6,7})', mail_client.get_message())[0]
- print(code)
-
- verification_code = WebDriverWait(driver, 30).until(
- EC.presence_of_element_located((By.XPATH, '//input[@placeholder="Code"]'))
- )
- verification_code.send_keys(code)
- verify_button = EC.presence_of_element_located(
- (By.XPATH, '//button[text()="Verify"]')
- )
- login_button = EC.presence_of_element_located(
- (By.XPATH, '//button[text()="Log In"]')
- )
-
- WebDriverWait(driver, 30).until(EC.any_of(verify_button, login_button)).click()
-
- cookie = driver.get_cookie("p-b")
-
- with open("./quora/cookie.json", "w") as fw:
- json.dump(cookie, fw)
-
- driver.close()
- return cookie
-
- def chat(self, message: str, model: Optional[str] = None) -> str:
- if model and model not in MODELS:
- raise RuntimeError(
- "Sorry, the model you provided does not exist. Please check and try again."
- )
- model = MODELS[model] if model else self.model
- response = None
- for chunk in self.client.send_message(model, message):
- response = chunk["text"]
- return response
-
- def create_bot(
- self,
- name: str,
- /,
- prompt: str = "",
- base_model: str = "ChatGPT",
- description: str = "",
- ) -> None:
- if base_model not in MODELS:
- raise RuntimeError(
- "Sorry, the base_model you provided does not exist. Please check and try again."
- )
-
- response = self.client.create_bot(
- handle=name,
- prompt=prompt,
- base_model=MODELS[base_model],
- description=description,
- )
- print(f'Successfully created bot with name: {response["bot"]["displayName"]}')
-
- def list_bots(self) -> list:
- return list(self.client.bot_names.values())