Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for new authentication methods in forefront #504

Merged
merged 2 commits into from
May 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 8 additions & 5 deletions gpt4free/forefront/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,18 @@

```python
from gpt4free import forefront


# create an account
token = forefront.Account.create(logging=False)
print(token)
account_data = forefront.Account.create(logging=False)

# get a response
for response in forefront.StreamingCompletion.create(
token=token,
prompt='hello world',
model='gpt-4'
account_data=account_data,
prompt='hello world',
model='gpt-4'
):
print(response.choices[0].text, end='')
print("")

```
71 changes: 45 additions & 26 deletions gpt4free/forefront/__init__.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,24 @@
import hashlib
from base64 import b64encode
from json import loads
from re import findall
from time import time, sleep
from typing import Generator, Optional
from uuid import uuid4

from mailgw_temporary_email import Email
from Crypto.Cipher import AES
from Crypto.Random import get_random_bytes
from fake_useragent import UserAgent
from mailgw_temporary_email import Email
from requests import post
from tls_client import Session

from .typing import ForeFrontResponse
from .typing import ForeFrontResponse, AccountData


class Account:
@staticmethod
def create(proxy: Optional[str] = None, logging: bool = False):
def create(proxy: Optional[str] = None, logging: bool = False) -> AccountData:
proxies = {'http': 'http://' + proxy, 'https': 'http://' + proxy} if proxy else False

start = time()
Expand All @@ -34,14 +38,13 @@ def create(proxy: Optional[str] = None, logging: bool = False):
'https://clerk.forefront.ai/v1/client/sign_ups?_clerk_js_version=4.38.4',
data={'email_address': mail_address},
)
print(response.json()['response']['id'])

try:
trace_token = response.json()['response']['id']
if logging:
print(trace_token)
except KeyError:
return 'Failed to create account!'
raise RuntimeError('Failed to create account!')

response = client.post(
f'https://clerk.forefront.ai/v1/client/sign_ups/{trace_token}/prepare_verification?_clerk_js_version=4.38.4',
Expand All @@ -55,60 +58,59 @@ def create(proxy: Optional[str] = None, logging: bool = False):
print(response.text)

if 'sign_up_attempt' not in response.text:
return 'Failed to create account!'
raise RuntimeError('Failed to create account!')

while True:
sleep(5)
message_id = mail_client.message_list()[0]['id']
message = mail_client.message(message_id)

new_message: Message = message
verification_url = findall(r'https:\/\/clerk\.forefront\.ai\/v1\/verify\?token=\w.+', new_message["text"])[0]

verification_url = findall(r'https:\/\/clerk\.forefront\.ai\/v1\/verify\?token=\w.+', message["text"])[0]
if verification_url:
break

if logging:
print(verification_url)
client.get(verification_url)

response = client.get(verification_url)

response = client.get('https://clerk.forefront.ai/v1/client?_clerk_js_version=4.38.4')
response = client.get('https://clerk.forefront.ai/v1/client?_clerk_js_version=4.38.4').json()
session_data = response['response']['sessions'][0]

token = response.json()['response']['sessions'][0]['last_active_token']['jwt']
user_id = session_data['user']['id']
session_id = session_data['id']
token = session_data['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
return AccountData(token=token, user_id=user_id, session_id=session_id)


class StreamingCompletion:
@staticmethod
def create(
token=None,
prompt: str,
account_data: AccountData,
chat_id=None,
prompt='',
action_type='new',
default_persona='607e41fe-95be-497e-8e97-010a59b2e2c0', # default
model='gpt-4',
proxy=None
) -> Generator[ForeFrontResponse, None, None]:
if not token:
raise Exception('Token is required!')
token = account_data.token
if not chat_id:
chat_id = str(uuid4())

proxies = { 'http': 'http://' + proxy, 'https': 'http://' + proxy } if proxy else None
proxies = {'http': 'http://' + proxy, 'https': 'http://' + proxy} if proxy else None
base64_data = b64encode((account_data.user_id + default_persona + chat_id).encode()).decode()
encrypted_signature = StreamingCompletion.__encrypt(base64_data, account_data.session_id)

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',
Expand All @@ -120,6 +122,8 @@ def create(
'sec-fetch-dest': 'empty',
'sec-fetch-mode': 'cors',
'sec-fetch-site': 'cross-site',
'authorization': f"Bearer {token}",
'X-Signature': encrypted_signature,
'user-agent': UserAgent().random,
}

Expand All @@ -133,7 +137,7 @@ def create(
}

for chunk in post(
'https://chat-server.tenant-forefront-default.knative.chi.coreweave.com/chat',
'https://streaming.tenant-forefront-default.knative.chi.coreweave.com/chat',
headers=headers,
proxies=proxies,
json=json_data,
Expand All @@ -160,13 +164,28 @@ def create(
}
)

@staticmethod
def __encrypt(data: str, key: str) -> str:
hash_key = hashlib.sha256(key.encode()).digest()
iv = get_random_bytes(16)
cipher = AES.new(hash_key, AES.MODE_CBC, iv)
encrypted_data = cipher.encrypt(StreamingCompletion.__pad_data(data.encode()))
return iv.hex() + encrypted_data.hex()

@staticmethod
def __pad_data(data: bytes) -> bytes:
block_size = AES.block_size
padding_size = block_size - len(data) % block_size
padding = bytes([padding_size] * padding_size)
return data + padding


class Completion:
@staticmethod
def create(
token=None,
prompt: str,
account_data: AccountData,
chat_id=None,
prompt='',
action_type='new',
default_persona='607e41fe-95be-497e-8e97-010a59b2e2c0', # default
model='gpt-4',
Expand All @@ -175,7 +194,7 @@ def create(
text = ''
final_response = None
for response in StreamingCompletion.create(
token=token,
account_data=account_data,
chat_id=chat_id,
prompt=prompt,
action_type=action_type,
Expand All @@ -190,6 +209,6 @@ def create(
if final_response:
final_response.text = text
else:
raise Exception('Unable to get the response, Please try again')
raise RuntimeError('Unable to get the response, Please try again')

return final_response
6 changes: 6 additions & 0 deletions gpt4free/forefront/typing.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,9 @@ class ForeFrontResponse(BaseModel):
choices: List[Choice]
usage: Usage
text: str


class AccountData(BaseModel):
token: str
user_id: str
session_id: str
6 changes: 3 additions & 3 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,6 @@ https://github.com/AI-Yash/st-chat/archive/refs/pull/24/head.zip
pydantic
pymailtm
Levenshtein
xtempmail
faker
retrying
retrying
mailgw_temporary_email
pycryptodome