Repository: ultrasev/chatrapper
Branch: master
Commit: 46633bd3d406
Files: 5
Total size: 7.1 KB
Directory structure:
gitextract_s8xdcfmo/
├── LICENCE
├── README.md
├── chatrapper/
│ └── __init__.py
├── pyproject.toml
└── tests/
└── __init__.py
================================================
FILE CONTENTS
================================================
================================================
FILE: LICENCE
================================================
MIT License
Copyright (c) 2023-2024 ultrasev
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: README.md
================================================
<div align="center">
<figure style="text-align: align;">
<img src="https://s3.bmp.ovh/imgs/2024/03/15/2aa0a21860f0ded7.png" width=189pt>
</figure>
<h2>ChatGPT API (W)rapper</h2>
</div>
把网页版 ChatGPT 封装为一个简单的 API,以便在代码中使用。
> OpenAI 对逆向的限制越来越严格,逆向难度越来越大,且各平台的 API 已经很便宜了,像 Groq 的 Llama 3 API 还一直是免费的,不太建议大家继续研究这类项目了。如果特别需要,可以参考作者的另一个项目 [juchats](https://github.com/ultrasev/juchats),有更多免费模型可以使用。
# Installation
```bash
pip3 install git+https://github.com/ultrasev/chatrapper.git
```
# Usage
环境变量中设置 `TOKEN`,然后调用 `chat` 函数即可。
```bash
export TOKEN="eyJhbGci..."
```
在代码中使用 `Rapper`:
```python
import os
from chatrapper import Rapper
token = os.environ.get("TOKEN")
rapper = Rapper(
access_token=token
model="text-davinci-002-render-sha"
)
rapper("鲁迅为什么打周树人?")
```
或者有异步需求的话,可以使用 `AsyncRapper`。这种情况下,最好有多个账号支持,单账号下,同一时间只支持一轮对话。
```python
import os
import asyncio
from chatrapper import AsyncRapper
token = os.environ.get("TOKEN")
rapper = AsyncRapper(
access_token=token
model="text-davinci-002-render-sha"
)
async def main():
print(await rapper("鲁迅为什么打周树人?"))
asyncio.run(main())
```
Demo:
<figure style="text-align: left;">
<img src="https://s3.bmp.ovh/imgs/2024/03/15/25ea45935e95e00e.gif" width=589pt>
</figure>
# Notes
- 一定要保护好自己的 token,不要泄露给他人。
- 合理使用 API,调用频率不宜过高,树大易招风,避免触发风控。
================================================
FILE: chatrapper/__init__.py
================================================
#!/usr/bin/env python
import asyncio
import base64
import json
import typing
from uuid import uuid4
import httpx
import websockets
import logging
from websockets.exceptions import ConnectionClosedError, ConnectionClosedOK
class MessageDeserializer(object):
def __init__(self, data: str) -> None:
self.data = data.lstrip("data: ").strip()
def __str__(self) -> str:
try:
js = json.loads(self.data)
return js['message']['content']['parts'][0]
except json.decoder.JSONDecodeError:
return ""
except KeyError:
logging.error(f"Error: {self.data}")
return ""
class AsyncRapper(object):
def __init__(self,
access_token: str,
model: str = "text-davinci-002-render-sha") -> None:
""" API (w)rapper for OpenAI's ChatGPT.
Args:
access_token (str): ChatGPT access token, acquired from https://chat.openai.com/api/auth/session
model (str): model name, options include:
- "text-davinci-002-render-sha", default model for ChatGPT-3.5
- "GPT-4", GPT-4 model
"""
self.access_token = access_token
self.model = model
async def _stream_from_wss(self, chunk: str) -> typing.AsyncGenerator[str, None]:
url = json.loads(chunk)['wss_url']
async with websockets.connect(url) as websocket:
while True:
try:
response = await websocket.recv()
body = json.loads(response)["body"]
body = base64.b64decode(body).decode('utf-8')
if 'DONE' in body:
break
yield body
except ConnectionClosedOK:
break
except ConnectionClosedError:
break
async def stream(self,
text: str) -> typing.AsyncGenerator[str, None]:
body = {
"action": "next",
"arkose_token": "null",
"conversation_mode": {"kind": "primary_assistant"},
"force_paragen": False,
"force_rate_limit": False,
"history_and_training_disabled": True,
"messages": [{
"metadata": {},
"author": {
"role": "user"
},
"content": {
"content_type": "text",
"parts": [text]
}
}],
"model": self.model,
"parent_message_id": str(uuid4()),
"timezone_offset_min": -330,
"stream": True
}
async with httpx.AsyncClient() as client:
async with client.stream(
'POST',
url="https://chat.openai.com/backend-api/conversation",
headers={
"accept": "text/event-stream",
"accept-language": "en-US",
"authorization": f"Bearer {self.access_token}",
"content-type": "application/json",
"sec-fetch-dest": "empty",
"sec-fetch-mode": "cors",
"sec-fetch-site": "same-origin",
"Referer": "https://chat.openai.com/",
"Referrer-Policy": "strict-origin-when-cross-origin",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36"
},
data=json.dumps(body)) as response:
async for chunk in response.aiter_text():
chunk = chunk.lstrip("data: ").strip()
if "wss_url" in chunk:
async for x in self._stream_from_wss(chunk):
yield str(MessageDeserializer(x))
else:
yield str(MessageDeserializer(chunk))
async def __call__(self, text: str) -> str:
prev = ""
async for x in self.stream(text):
print(x.replace(prev, ""), end="", flush=True)
prev = max(prev, x, key=len)
return prev
class Rapper(object):
def __init__(self,
access_token: str,
model: str = "text-davinci-002-render-sha") -> None:
self._proxy = AsyncRapper(access_token, model)
def __call__(self, text: str) -> str:
return asyncio.run(self._proxy(text))
================================================
FILE: pyproject.toml
================================================
[tool.poetry]
name = "chatrapper"
version = "0.1.0"
description = ""
authors = ["ultrasev <i@ultrasev.com>"]
readme = "README.md"
packages = [{include = "chatrapper"}]
[tool.poetry.dependencies]
python = "^3.8"
uuid = "^1.30"
httpx = "^0.27.0"
websockets = "^12.0"
[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"
================================================
FILE: tests/__init__.py
================================================
gitextract_s8xdcfmo/
├── LICENCE
├── README.md
├── chatrapper/
│ └── __init__.py
├── pyproject.toml
└── tests/
└── __init__.py
SYMBOL INDEX (11 symbols across 1 files)
FILE: chatrapper/__init__.py
class MessageDeserializer (line 14) | class MessageDeserializer(object):
method __init__ (line 15) | def __init__(self, data: str) -> None:
method __str__ (line 18) | def __str__(self) -> str:
class AsyncRapper (line 29) | class AsyncRapper(object):
method __init__ (line 30) | def __init__(self,
method _stream_from_wss (line 43) | async def _stream_from_wss(self, chunk: str) -> typing.AsyncGenerator[...
method stream (line 59) | async def stream(self,
method __call__ (line 109) | async def __call__(self, text: str) -> str:
class Rapper (line 117) | class Rapper(object):
method __init__ (line 118) | def __init__(self,
method __call__ (line 123) | def __call__(self, text: str) -> str:
Condensed preview — 5 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (8K chars).
[
{
"path": "LICENCE",
"chars": 1069,
"preview": "MIT License\n\nCopyright (c) 2023-2024 ultrasev\n\nPermission is hereby granted, free of charge, to any person obtaining a c"
},
{
"path": "README.md",
"chars": 1325,
"preview": "\n<div align=\"center\">\n <figure style=\"text-align: align;\">\n <img src=\"https://s3.bmp.ovh/imgs/2024/03/15/2aa0a21860f"
},
{
"path": "chatrapper/__init__.py",
"chars": 4542,
"preview": "#!/usr/bin/env python\nimport asyncio\nimport base64\nimport json\nimport typing\nfrom uuid import uuid4\n\nimport httpx\nimport"
},
{
"path": "pyproject.toml",
"chars": 351,
"preview": "[tool.poetry]\nname = \"chatrapper\"\nversion = \"0.1.0\"\ndescription = \"\"\nauthors = [\"ultrasev <i@ultrasev.com>\"]\nreadme = \"R"
},
{
"path": "tests/__init__.py",
"chars": 0,
"preview": ""
}
]
About this extraction
This page contains the full source code of the ultrasev/chatrapper GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 5 files (7.1 KB), approximately 2.0k tokens, and a symbol index with 11 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.