Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Signed-off-by: pengzhile <[email protected]>
  • Loading branch information
pengzhile committed Feb 17, 2023
1 parent 657b833 commit 220a978
Show file tree
Hide file tree
Showing 14 changed files with 84 additions and 42 deletions.
Binary file added .DS_Store
Binary file not shown.
15 changes: 13 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@
# Pandora

### `潘多拉`,一个命令行的`ChatGPT`
### 实现了网页版`ChatGPT`的主要操作。能过`Cloudflare`理论上不开代理也能用
### 实现了网页版`ChatGPT`的主要操作。能过`Cloudflare`理论上速度还可以

## 如何运行:

* 直接运行(`Python`版本目测起码要`3.7`
* `Python`版本目测起码要`3.7`

* `pip`安装运行

```shell
pip install Pandora-ChatGPT
pandora
```

* 编译运行

```shell
python setup.py install
Expand Down Expand Up @@ -38,6 +47,8 @@
* `/regen` 如果对`ChatGPT`当前回答不满意,可以让它重新回答。
* `/new` 直接开启一个新会话。
* `/del` 删除当前会话,回到会话选择界面。
* `/token` 打印当前的`Access Token`,也许你用得上,但不要泄露。
* `/clear` 清屏,应该不用解释。
* `/exit` 退出`潘多拉`

## 其他说明
Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.0.1
0.0.3
6 changes: 0 additions & 6 deletions pandora/__main__.py

This file was deleted.

1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
aiohttp==3.8.3
termcolor==2.2.0
tls_client==0.1.8
colorama==0.4.6
1 change: 0 additions & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

[metadata]
description_file=README.md
license_files=LICENSE
Expand Down
26 changes: 17 additions & 9 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,25 +1,33 @@
from os.path import join, dirname
from setuptools import setup

from setuptools import setup, find_packages
with open('VERSION', 'r', encoding='utf-8') as f:
version = f.read().strip()

with open(join(dirname(__file__), 'VERSION'), 'rb') as f:
version = f.read().decode('ascii').strip()
with open('README.md', 'r', encoding='utf-8') as f:
long_description = f.read()

setup(
name='Pandora',
name='Pandora-ChatGPT',
version=version,
python_requires='~=3.7',
packages=find_packages(),
python_requires='>=3.7',
author='Neo Peng',
author_email='[email protected]',
description='A command-line interface to ChatGPT',
long_description=long_description,
long_description_content_type='text/markdown',
url="https://github.com/pengzhile/pandora",
packages=['pandora', 'pandora.openai'],
package_dir={'pandora': 'src'},
include_package_data=True,
zip_safe=False,
install_requires=[
'aiohttp == 3.8.3',
'termcolor == 2.2.0',
'tls_client == 0.1.8',
'colorama == 0.4.6',
],
entry_points={
"console_scripts": [
"pandora = pandora.launcher:run",
"pandora = pandora.__main__:main",
]
}
)
2 changes: 2 additions & 0 deletions pandora/openai/__init__.py → src/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
# -*- coding: utf-8 -*-

__version__ = '0.0.3'
10 changes: 5 additions & 5 deletions pandora/launcher.py → src/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
import getpass
import sys

from pandora.openai.api import ChatGPT
from pandora.openai.auth import Auth0
from pandora.openai.bot import ChatBot
from pandora.openai.utils import Console
from .openai.api import ChatGPT
from .openai.auth import Auth0
from .openai.bot import ChatBot
from .openai.utils import Console


def main():
Expand Down Expand Up @@ -48,7 +48,7 @@ def main():
ChatBot(ChatGPT(access_token, args.proxy)).run()


def run():
if __name__ == '__main__':
try:
main()
except KeyboardInterrupt:
Expand Down
File renamed without changes.
File renamed without changes.
21 changes: 12 additions & 9 deletions pandora/openai/auth.py → src/openai/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def auth(self) -> str:
return self.access_token

if not self.__check_email(self.email) or not self.password:
raise Exception('invalid email or password')
raise Exception('invalid email or password.')

if self.proxy:
self.session.proxies = {
Expand All @@ -53,7 +53,7 @@ def __part_two(self) -> str:
csrf_token = response.json()['csrfToken']
return self.__part_three(token=csrf_token)
else:
raise Exception('Error logging in')
raise Exception('Error logging in.')

def __part_three(self, token: str) -> str:
url = 'https://home.apps.openai.com/api/auth/signin/auth0?prompt=login'
Expand All @@ -75,7 +75,7 @@ def __part_three(self, token: str) -> str:
raise Exception('You have been rate limited.')
return self.__part_four(url=url)
else:
raise Exception('Error get login url')
raise Exception('Error get login url.')

def __part_four(self, url: str) -> str:
headers = {
Expand All @@ -90,9 +90,9 @@ def __part_four(self, url: str) -> str:
state = url_params['state'][0]
return self.__part_five(state)
except IndexError as exc:
raise Exception('Rate limit hit') from exc
raise Exception('Rate limit hit.') from exc
else:
raise Exception('Error request login url')
raise Exception('Error request login url.')

def __part_five(self, state: str) -> str:
url = 'https://auth0.openai.com/u/login/identifier?state=' + state
Expand All @@ -115,7 +115,7 @@ def __part_five(self, state: str) -> str:
if response.status_code == 302:
return self.__part_six(state=state)
else:
raise Exception('Error check email')
raise Exception('Error check email.')

def __part_six(self, state: str) -> str:
url = 'https://auth0.openai.com/u/login/password?state=' + state
Expand All @@ -135,9 +135,9 @@ def __part_six(self, state: str) -> str:
if response.status_code == 200:
return self.get_access_token()
if response.status_code == 400:
raise Exception('Wrong email or password')
raise Exception('Wrong email or password.')
else:
raise Exception('Error login')
raise Exception('Error login.')

def get_access_token(self) -> str:
url = 'https://home.apps.openai.com/api/auth/session'
Expand All @@ -149,8 +149,11 @@ def get_access_token(self) -> str:

if response.status_code == 200:
json = response.json()
if 'accessToken' not in json:
raise Exception('Get access token failed, maybe you need a proxy.')

self.access_token = json['accessToken']
self.expires = dt.strptime(json['expires'], '%Y-%m-%dT%H:%M:%S.%fZ') - datetime.timedelta(minutes=5)
return self.access_token
else:
raise Exception('Error get access token')
raise Exception('Error get access token.')
31 changes: 26 additions & 5 deletions pandora/openai/bot.py → src/openai/bot.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
import asyncio
import uuid

from pandora.openai.api import ChatGPT
from pandora.openai.utils import Console
from .api import ChatGPT
from .utils import Console


class Prompt:
Expand All @@ -19,7 +19,9 @@ def gen_message_id():


class State:
def __init__(self, conversation_id=None, model_slug=None, user_prompt=Prompt(), chatgpt_prompt=Prompt()):
def __init__(self, title=None, conversation_id=None, model_slug=None, user_prompt=Prompt(),
chatgpt_prompt=Prompt()):
self.title = title
self.conversation_id = conversation_id
self.model_slug = model_slug
self.user_prompt = user_prompt
Expand Down Expand Up @@ -91,6 +93,10 @@ def __process_command(self, command):
self.__talk_loop()
elif '/regen' == command or '/regenerate' == command:
self.__regenerate_reply(self.state)
elif '/token' == command:
self.__print_access_token()
elif '/cls' == command or '/clear' == command:
self.__clear_screen()
elif '/help' == command or 'usage' == command or '/?' == command:
self.__print_usage()

Expand All @@ -104,13 +110,25 @@ def __print_usage():
print('/regen\t\tRegenerate response.')
print('/new\t\tStart a new conversation.')
print('/del\t\tDelete the current conversation.')
print('/token\t\tPrint your access token.')
print('/clear\t\tClear your screen.')
print('/exit\t\tExit Pandora.')
print()

def __print_access_token(self):
Console.warn_b('\n#### Your access token (keep it private)')
Console.warn(self.chatgpt.access_token)
print()

def __clear_screen(self):
Console.clear()
self.__print_conversation_title(self.state.title)

def __new_conversation(self):
self.state = State(model_slug=self.__choice_model()['slug'])

self.__print_conversation_title('New Chat')
self.state.title = 'New Chat'
self.__print_conversation_title(self.state.title)

@staticmethod
def __print_conversation_title(title: str):
Expand All @@ -128,6 +146,7 @@ def __set_conversation_title(self, state: State):
return

if self.chatgpt.set_conversation_title(state.conversation_id, new_title):
self.state.title = new_title
Console.success('#### Set title success.')
else:
Console.error('#### Set title failed.')
Expand Down Expand Up @@ -160,7 +179,8 @@ def __load_conversation(self, conversation_id):
nodes.insert(0, node)
current_node_id = node['parent']

self.__print_conversation_title(result['title'])
self.state.title = result['title']
self.__print_conversation_title(self.state.title)

for node in nodes:
message = node['message']
Expand Down Expand Up @@ -197,6 +217,7 @@ def __talk(self, prompt):
if first_prompt:
new_title = self.chatgpt.gen_conversation_title(self.state.conversation_id, self.state.model_slug,
self.state.chatgpt_prompt.message_id)
self.state.title = new_title
Console.success_bh('#### Title generated: ' + new_title)

def __regenerate_reply(self, state):
Expand Down
11 changes: 7 additions & 4 deletions pandora/openai/utils.py → src/openai/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,25 @@
import os

from termcolor import colored
from colorama import just_fix_windows_console


class Console:
@staticmethod
def __clear():
os.system('cls' if 'nt' == os.name else 'clear')

@staticmethod
def __colored(text: str, color, highlight, bold):
just_fix_windows_console()

white = 'white'
black = 'black'
for_color = (black if white == color else white) if highlight else color
bg_color = 'on_' + color if highlight else None

return colored(text, color=for_color, on_color=bg_color, attrs=['bold'] if bold else None)

@staticmethod
def clear():
os.system('cls' if 'nt' == os.name else 'clear')

@staticmethod
def info(text: str, highlight=False, bold=False, output=True, end='\n', flush=False):
result = Console.__colored(text, 'white', highlight, bold)
Expand Down

0 comments on commit 220a978

Please sign in to comment.