Skip to content

Commit

Permalink
Merge pull request #1950 from hlohaus/leech
Browse files Browse the repository at this point in the history
Update chatgpt url, uvloop support
  • Loading branch information
hlohaus committed May 15, 2024
2 parents 5a1aae8 + 59fcf9d commit 008ed60
Show file tree
Hide file tree
Showing 10 changed files with 222 additions and 86 deletions.
25 changes: 18 additions & 7 deletions g4f/Provider/needs_auth/Gemini.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@
pass

from ... import debug
from ...typing import Messages, Cookies, ImageType, AsyncResult
from ...typing import Messages, Cookies, ImageType, AsyncResult, AsyncIterator
from ..base_provider import AsyncGeneratorProvider
from ..helper import format_prompt, get_cookies
from ...requests.raise_for_status import raise_for_status
from ...errors import MissingAuthError, MissingRequirementsError
from ...image import to_bytes, ImageResponse
from ...image import to_bytes, to_data_uri, ImageResponse
from ...webdriver import get_browser, get_driver_cookies

REQUEST_HEADERS = {
Expand Down Expand Up @@ -59,7 +59,7 @@ class Gemini(AsyncGeneratorProvider):
_cookies: Cookies = None

@classmethod
async def nodriver_login(cls) -> Cookies:
async def nodriver_login(cls) -> AsyncIterator[str]:
try:
import nodriver as uc
except ImportError:
Expand All @@ -72,17 +72,20 @@ async def nodriver_login(cls) -> Cookies:
if debug.logging:
print(f"Open nodriver with user_dir: {user_data_dir}")
browser = await uc.start(user_data_dir=user_data_dir)
login_url = os.environ.get("G4F_LOGIN_URL")
if login_url:
yield f"Please login: [Google Gemini]({login_url})\n\n"
page = await browser.get(f"{cls.url}/app")
await page.select("div.ql-editor.textarea", 240)
cookies = {}
for c in await page.browser.cookies.get_all():
if c.domain.endswith(".google.com"):
cookies[c.name] = c.value
await page.close()
return cookies
cls._cookies = cookies

@classmethod
async def webdriver_login(cls, proxy: str):
async def webdriver_login(cls, proxy: str) -> AsyncIterator[str]:
driver = None
try:
driver = get_browser(proxy=proxy)
Expand Down Expand Up @@ -131,13 +134,14 @@ async def create_async_generator(
) as session:
snlm0e = await cls.fetch_snlm0e(session, cls._cookies) if cls._cookies else None
if not snlm0e:
cls._cookies = await cls.nodriver_login();
async for chunk in cls.nodriver_login():
yield chunk
if cls._cookies is None:
async for chunk in cls.webdriver_login(proxy):
yield chunk

if not snlm0e:
if "__Secure-1PSID" not in cls._cookies:
if cls._cookies is None or "__Secure-1PSID" not in cls._cookies:
raise MissingAuthError('Missing "__Secure-1PSID" cookie')
snlm0e = await cls.fetch_snlm0e(session, cls._cookies)
if not snlm0e:
Expand Down Expand Up @@ -193,6 +197,13 @@ async def create_async_generator(
image = fetch.headers["location"]
resolved_images.append(image)
preview.append(image.replace('=s512', '=s200'))
# preview_url = image.replace('=s512', '=s200')
# async with client.get(preview_url) as fetch:
# preview_data = to_data_uri(await fetch.content.read())
# async with client.get(image) as fetch:
# data = to_data_uri(await fetch.content.read())
# preview.append(preview_data)
# resolved_images.append(data)
yield ImageResponse(resolved_images, image_prompt, {"orginal_links": images, "preview": preview})

def build_request(
Expand Down
15 changes: 8 additions & 7 deletions g4f/Provider/needs_auth/OpenaiChat.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
"accept": "*/*",
"accept-encoding": "gzip, deflate, br, zstd",
"accept-language": "en-US,en;q=0.5",
"referer": "https://chat.openai.com/",
"referer": "https://chatgpt.com/",
"sec-ch-ua": "\"Brave\";v=\"123\", \"Not:A-Brand\";v=\"8\", \"Chromium\";v=\"123\"",
"sec-ch-ua-mobile": "?0",
"sec-ch-ua-platform": "\"Windows\"",
Expand All @@ -53,15 +53,15 @@ class OpenaiChat(AsyncGeneratorProvider, ProviderModelMixin):
"""A class for creating and managing conversations with OpenAI chat service"""

label = "OpenAI ChatGPT"
url = "https://chat.openai.com"
url = "https://chatgpt.com"
working = True
supports_gpt_35_turbo = True
supports_gpt_4 = True
supports_message_history = True
supports_system_message = True
default_model = None
default_vision_model = "gpt-4-vision"
models = ["gpt-3.5-turbo", "gpt-4", "gpt-4-gizmo"]
default_vision_model = "gpt-4o"
models = ["gpt-3.5-turbo", "gpt-4", "gpt-4-gizmo", "gpt-4o"]
model_aliases = {
"text-davinci-002-render-sha": "gpt-3.5-turbo",
"": "gpt-3.5-turbo",
Expand Down Expand Up @@ -442,6 +442,7 @@ async def create_async_generator(
try:
image_request = await cls.upload_image(session, cls._headers, image, image_name) if image else None
except Exception as e:
image_request = None
if debug.logging:
print("OpenaiChat: Upload image failed")
print(f"{e.__class__.__name__}: {e}")
Expand Down Expand Up @@ -601,7 +602,7 @@ async def webview_access_token(cls) -> str:
this._fetch = this.fetch;
this.fetch = async (url, options) => {
const response = await this._fetch(url, options);
if (url == "https://chat.openai.com/backend-api/conversation") {
if (url == "https://chatgpt.com/backend-api/conversation") {
this._headers = options.headers;
return response;
}
Expand Down Expand Up @@ -637,7 +638,7 @@ async def nodriver_access_token(cls):
if debug.logging:
print(f"Open nodriver with user_dir: {user_data_dir}")
browser = await uc.start(user_data_dir=user_data_dir)
page = await browser.get("https://chat.openai.com/")
page = await browser.get("https://chatgpt.com/")
await page.select("[id^=headlessui-menu-button-]", 240)
api_key = await page.evaluate(
"(async () => {"
Expand All @@ -652,7 +653,7 @@ async def nodriver_access_token(cls):
)
cookies = {}
for c in await page.browser.cookies.get_all():
if c.domain.endswith("chat.openai.com"):
if c.domain.endswith("chatgpt.com"):
cookies[c.name] = c.value
user_agent = await page.evaluate("window.navigator.userAgent")
await page.close()
Expand Down
2 changes: 1 addition & 1 deletion g4f/Provider/openai/har_file.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ def __init__(self, arkURL, arkBx, arkHeader, arkBody, arkCookies, userAgent):
self.userAgent = userAgent

arkPreURL = "https://tcr9i.chat.openai.com/fc/gt2/public_key/35536E1E-65B4-4D96-9D97-6ADB7EFF8147"
sessionUrl = "https://chat.openai.com/api/auth/session"
sessionUrl = "https://chatgpt.com/api/auth/session"
chatArk: arkReq = None
accessToken: str = None
cookies: dict = None
Expand Down
7 changes: 2 additions & 5 deletions g4f/Provider/openai/proofofwork.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,9 @@ def generate_proof_token(required: bool, seed: str, difficulty: str, user_agent:

# Get current UTC time
now_utc = datetime.now(timezone.utc)
# Convert UTC time to Eastern Time
now_et = now_utc.astimezone(timezone(timedelta(hours=-5)))
parse_time = now_utc.strftime('%a, %d %b %Y %H:%M:%S GMT')

parse_time = now_et.strftime('%a, %d %b %Y %H:%M:%S GMT')

config = [core + screen, parse_time, 4294705152, 0, user_agent]
config = [core + screen, parse_time, None, 0, user_agent, "https://tcr9i.chat.openai.com/v2/35536E1E-65B4-4D96-9D97-6ADB7EFF8147/api.js","dpl=53d243de46ff04dadd88d293f088c2dd728f126f","en","en-US",442,"plugins−[object PluginArray]","","alert"]

diff_len = len(difficulty) // 2

Expand Down
11 changes: 5 additions & 6 deletions g4f/client/async_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,9 @@
from .image_models import ImageModels
from .helper import filter_json, find_stop, filter_none, cast_iter_async
from .service import get_last_provider, get_model_and_provider
from ..typing import Union, Iterator, Messages, AsyncIterator, ImageType
from ..typing import Union, Messages, AsyncIterator, ImageType
from ..errors import NoImageResponseError
from ..image import ImageResponse as ImageProviderResponse
from ..providers.base_provider import AsyncGeneratorProvider

try:
anext
Expand Down Expand Up @@ -88,7 +87,7 @@ def create_response(
api_key: str = None,
**kwargs
):
has_asnyc = isinstance(provider, type) and issubclass(provider, AsyncGeneratorProvider)
has_asnyc = hasattr(provider, "create_async_generator")
if has_asnyc:
create = provider.create_async_generator
else:
Expand Down Expand Up @@ -157,7 +156,7 @@ class Chat():
def __init__(self, client: AsyncClient, provider: ProviderType = None):
self.completions = Completions(client, provider)

async def iter_image_response(response: Iterator) -> Union[ImagesResponse, None]:
async def iter_image_response(response: AsyncIterator) -> Union[ImagesResponse, None]:
async for chunk in response:
if isinstance(chunk, ImageProviderResponse):
return ImagesResponse([Image(image) for image in chunk.get_list()])
Expand All @@ -182,7 +181,7 @@ def __init__(self, client: AsyncClient, provider: ImageProvider = None):

async def generate(self, prompt, model: str = "", **kwargs) -> ImagesResponse:
provider = self.models.get(model, self.provider)
if isinstance(provider, type) and issubclass(provider, AsyncGeneratorProvider):
if hasattr(provider, "create_async_generator"):
response = create_image(self.client, provider, prompt, **kwargs)
else:
response = await provider.create_async(prompt)
Expand All @@ -195,7 +194,7 @@ async def generate(self, prompt, model: str = "", **kwargs) -> ImagesResponse:
async def create_variation(self, image: ImageType, model: str = None, **kwargs):
provider = self.models.get(model, self.provider)
result = None
if isinstance(provider, type) and issubclass(provider, AsyncGeneratorProvider):
if hasattr(provider, "create_async_generator"):
response = provider.create_async_generator(
"",
[{"role": "user", "content": "create a image like this"}],
Expand Down
6 changes: 1 addition & 5 deletions g4f/gui/client/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,7 @@
<script src="/static/js/highlightjs-copy.min.js"></script>
<script src="/static/js/chat.v1.js" defer></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/markdown-it.min.js"></script>
<link rel="stylesheet"
href="//cdn.jsdelivr.net/gh/highlightjs/[email protected]/build/styles/base16/dracula.min.css">
<link rel="stylesheet" href="/static/css/dracula.min.css">
<script>
MathJax = {
chtml: {
Expand Down Expand Up @@ -244,8 +243,5 @@ <h3>Settings</h3>
<div class="mobile-sidebar">
<i class="fa-solid fa-bars"></i>
</div>
<script>
</script>
</body>

</html>
7 changes: 7 additions & 0 deletions g4f/gui/client/static/css/dracula.min.css

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion g4f/gui/client/static/css/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -381,7 +381,8 @@ body {
}

.message .count .fa-clipboard,
.message .count .fa-volume-high {
.message .count .fa-volume-high,
.message .count .fa-rotate {
z-index: 1000;
cursor: pointer;
}
Expand Down
46 changes: 32 additions & 14 deletions g4f/gui/client/static/js/chat.v1.js
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,9 @@ const register_message_buttons = async () => {
let playlist = [];
function play_next() {
const next = playlist.shift();
if (next)
if (next && el.dataset.do_play) {
next.play();
}
}
if (el.dataset.stopped) {
el.classList.remove("blink")
Expand Down Expand Up @@ -179,6 +180,20 @@ const register_message_buttons = async () => {
});
}
});
document.querySelectorAll(".message .fa-rotate").forEach(async (el) => {
if (!("click" in el.dataset)) {
el.dataset.click = "true";
el.addEventListener("click", async () => {
const message_el = el.parentElement.parentElement.parentElement;
el.classList.add("clicked");
setTimeout(() => el.classList.remove("clicked"), 1000);
prompt_lock = true;
await hide_message(window.conversation_id, message_el.dataset.index);
window.token = message_id();
await ask_gpt(message_el.dataset.index);
})
}
});
}

const delete_conversations = async () => {
Expand Down Expand Up @@ -257,24 +272,26 @@ const remove_cancel_button = async () => {
}, 300);
};

const prepare_messages = (messages, filter_last_message=true) => {
const prepare_messages = (messages, message_index = -1) => {
// Removes none user messages at end
if (filter_last_message) {
if (message_index == -1) {
let last_message;
while (last_message = messages.pop()) {
if (last_message["role"] == "user") {
messages.push(last_message);
break;
}
}
} else if (message_index >= 0) {
messages = messages.filter((_, index) => message_index >= index);
}

// Remove history, if it's selected
if (document.getElementById('history')?.checked) {
if (filter_last_message) {
messages = [messages.pop()];
} else {
if (message_index == null) {
messages = [messages.pop(), messages.pop()];
} else {
messages = [messages.pop()];
}
}

Expand Down Expand Up @@ -361,11 +378,11 @@ imageInput?.addEventListener("click", (e) => {
}
});

const ask_gpt = async () => {
const ask_gpt = async (message_index = -1) => {
regenerate.classList.add(`regenerate-hidden`);
messages = await get_messages(window.conversation_id);
total_messages = messages.length;
messages = prepare_messages(messages);
messages = prepare_messages(messages, message_index);

stop_generating.classList.remove(`stop_generating-hidden`);

Expand Down Expand Up @@ -528,6 +545,7 @@ const hide_option = async (conversation_id) => {
const span_el = document.createElement("span");
span_el.innerText = input_el.value;
span_el.classList.add("convo-title");
span_el.onclick = () => set_conversation(conversation_id);
left_el.removeChild(input_el);
left_el.appendChild(span_el);
}
Expand Down Expand Up @@ -616,7 +634,7 @@ const load_conversation = async (conversation_id, scroll=true) => {
}

if (window.GPTTokenizer_cl100k_base) {
const filtered = prepare_messages(messages, false);
const filtered = prepare_messages(messages, null);
if (filtered.length > 0) {
last_model = last_model?.startsWith("gpt-4") ? "gpt-4" : "gpt-3.5-turbo"
let count_total = GPTTokenizer_cl100k_base?.encodeChat(filtered, last_model).length
Expand Down Expand Up @@ -683,15 +701,15 @@ async function save_system_message() {
await save_conversation(window.conversation_id, conversation);
}
}

const hide_last_message = async (conversation_id) => {
const hide_message = async (conversation_id, message_index =- 1) => {
const conversation = await get_conversation(conversation_id)
const last_message = conversation.items.pop();
message_index = message_index == -1 ? conversation.items.length - 1 : message_index
const last_message = message_index in conversation.items ? conversation.items[message_index] : null;
if (last_message !== null) {
if (last_message["role"] == "assistant") {
last_message["regenerate"] = true;
}
conversation.items.push(last_message);
conversation.items[message_index] = last_message;
}
await save_conversation(conversation_id, conversation);
};
Expand Down Expand Up @@ -790,7 +808,7 @@ document.getElementById("cancelButton").addEventListener("click", async () => {

document.getElementById("regenerateButton").addEventListener("click", async () => {
prompt_lock = true;
await hide_last_message(window.conversation_id);
await hide_message(window.conversation_id);
window.token = message_id();
await ask_gpt();
});
Expand Down
Loading

0 comments on commit 008ed60

Please sign in to comment.