├── Quick-Translator.py
├── API
├── pandora
│ ├── src
│ │ └── pandora
│ │ │ ├── py.typed
│ │ │ ├── bots
│ │ │ └── __init__.py
│ │ │ ├── exts
│ │ │ ├── __init__.py
│ │ │ ├── config.py
│ │ │ ├── sentry.py
│ │ │ ├── hooks.py
│ │ │ └── token.py
│ │ │ ├── openai
│ │ │ ├── __init__.py
│ │ │ ├── token.py
│ │ │ └── utils.py
│ │ │ ├── turbo
│ │ │ ├── __init__.py
│ │ │ └── base.py
│ │ │ ├── migrations
│ │ │ ├── __init__.py
│ │ │ ├── database.py
│ │ │ ├── migrate.py
│ │ │ ├── scripts
│ │ │ │ └── 20230308_01_7ctOr.sql
│ │ │ └── models.py
│ │ │ ├── __init__.py
│ │ │ ├── __main__.py
│ │ │ ├── flask
│ │ │ └── static
│ │ │ │ ├── _next
│ │ │ │ └── static
│ │ │ │ │ ├── olf4sv64FWIcQ_zCGl90t
│ │ │ │ │ ├── _ssgManifest.js
│ │ │ │ │ └── _buildManifest.js
│ │ │ │ │ └── chunks
│ │ │ │ │ ├── pages
│ │ │ │ │ └── _error-786d27d84962122a.js
│ │ │ │ │ ├── 68a27ff6-1185184b61bc22d0.js
│ │ │ │ │ ├── bd26816a-981e1ddc27b37cc6.js
│ │ │ │ │ ├── 949.1a6eb804b5e91f61.js
│ │ │ │ │ ├── 554.9b8bfd0762461d74.js
│ │ │ │ │ └── webpack-c9a868e8e0796ec6.js
│ │ │ │ ├── favicon-16x16.png
│ │ │ │ ├── favicon-32x32.png
│ │ │ │ ├── apple-touch-icon.png
│ │ │ │ ├── fonts
│ │ │ │ ├── Sohne-Buch.otf
│ │ │ │ ├── KaTeX_Main-Bold.woff
│ │ │ │ ├── Sohne-Halbfett.otf
│ │ │ │ ├── SohneMono-Buch.otf
│ │ │ │ ├── KaTeX_Main-Italic.woff
│ │ │ │ ├── KaTeX_Math-Italic.woff
│ │ │ │ ├── Signifier-Regular.otf
│ │ │ │ ├── SohneMono-Halbfett.otf
│ │ │ │ ├── KaTeX_Fraktur-Bold.woff
│ │ │ │ ├── KaTeX_Main-Regular.woff
│ │ │ │ ├── KaTeX_SansSerif-Bold.woff
│ │ │ │ ├── KaTeX_Script-Regular.woff
│ │ │ │ ├── KaTeX_Size1-Regular.woff
│ │ │ │ ├── KaTeX_Size2-Regular.woff
│ │ │ │ ├── KaTeX_Size3-Regular.woff
│ │ │ │ ├── KaTeX_Size4-Regular.woff
│ │ │ │ ├── KaTeX_Caligraphic-Bold.woff
│ │ │ │ ├── KaTeX_Fraktur-Regular.woff
│ │ │ │ ├── KaTeX_Main-BoldItalic.woff
│ │ │ │ ├── KaTeX_Math-BoldItalic.woff
│ │ │ │ ├── KaTeX_SansSerif-Italic.woff
│ │ │ │ ├── KaTeX_Caligraphic-Regular.woff
│ │ │ │ ├── KaTeX_SansSerif-Regular.woff
│ │ │ │ └── KaTeX_Typewriter-Regular.woff
│ │ │ │ └── images
│ │ │ │ └── 2022
│ │ │ │ └── 11
│ │ │ │ └── ChatGPT.jpg
│ │ │ └── cloud_launcher.py
│ ├── requirements_api.txt
│ ├── doc
│ │ ├── images
│ │ │ ├── s01.png
│ │ │ ├── s02.png
│ │ │ ├── s03.png
│ │ │ ├── s04.png
│ │ │ ├── s05.png
│ │ │ ├── s06.png
│ │ │ ├── t0.png
│ │ │ ├── t1.png
│ │ │ ├── t2.png
│ │ │ ├── t3.png
│ │ │ ├── t4.png
│ │ │ ├── t7.png
│ │ │ ├── s11.jpeg
│ │ │ ├── s12.jpeg
│ │ │ └── t1.1.png
│ │ ├── HTTP-API.md
│ │ ├── wiki_en.md
│ │ └── wiki.md
│ ├── .dockerignore
│ ├── MANIFEST.in
│ ├── Dockerfile
│ ├── requirements.txt
│ ├── docker-compose.yml
│ ├── bin
│ │ └── startup.sh
│ ├── .gitignore
│ ├── setup.py
│ └── README.md
├── go-chatgpt-api
│ ├── .gitignore
│ ├── .env.example
│ ├── compose.yaml
│ ├── Dockerfile
│ ├── middleware
│ │ ├── cors.go
│ │ └── check_header.go
│ ├── util
│ │ └── logger
│ │ │ └── logger.go
│ ├── LICENSE
│ ├── api
│ │ ├── chatgpt
│ │ │ ├── constant.go
│ │ │ ├── typings.go
│ │ │ ├── health_check.go
│ │ │ └── access_token.go
│ │ ├── platform
│ │ │ ├── constant.go
│ │ │ ├── typings.go
│ │ │ ├── access_token.go
│ │ │ └── api.go
│ │ └── common.go
│ ├── go.mod
│ └── main.go
├── ChatGPT-to-API
│ ├── .gitignore
│ ├── internal
│ │ ├── typings
│ │ │ ├── api.go
│ │ │ └── responses
│ │ │ │ └── typings.go
│ │ ├── chatgpt
│ │ │ ├── convert.go
│ │ │ ├── typings.go
│ │ │ └── request.go
│ │ └── tokens
│ │ │ └── tokens.go
│ ├── tools
│ │ ├── authenticator
│ │ │ ├── README.md
│ │ │ ├── go.mod
│ │ │ ├── remove_duplicates.py
│ │ │ ├── go.sum
│ │ │ └── main.go
│ │ ├── plugin_check
│ │ │ └── check_access.go
│ │ └── proxy_check
│ │ │ └── proxy_check.go
│ ├── docs
│ │ ├── TOKEN_CN.md
│ │ ├── admin.md
│ │ ├── Docker_CN.md
│ │ └── GUIDE_CN.md
│ ├── docker-compose.yml
│ ├── Dockerfile
│ ├── middleware.go
│ ├── README_CN.md
│ ├── go.mod
│ ├── README.md
│ ├── main.go
│ └── handlers.go
├── talkx2api
│ ├── talkx2api.js
│ └── talkx2api.py
├── cerebras2api
│ └── cerebras2api.py
└── snova2api
│ ├── snova-api.js
│ └── snova2api.js
├── README.md
├── GPT-Config.example.ini
├── QT_MD.py
├── chat2api-docker-host.yaml
├── chat2api-docker-warp.yaml
├── chat2api-docker-warp-host.yaml
├── .gitignore
└── Quick-ASK.py
/Quick-Translator.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/API/pandora/src/pandora/py.typed:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/API/pandora/src/pandora/bots/__init__.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
--------------------------------------------------------------------------------
/API/pandora/src/pandora/exts/__init__.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
--------------------------------------------------------------------------------
/API/pandora/src/pandora/openai/__init__.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
--------------------------------------------------------------------------------
/API/pandora/src/pandora/turbo/__init__.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
--------------------------------------------------------------------------------
/API/pandora/src/pandora/migrations/__init__.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # OpenAI-Quick-DEV
2 | 面向OpenAI开发的代码库,目标是构建一些轻松快速上手的小程序来使用OpenAI/ChatGPT的服务
3 |
--------------------------------------------------------------------------------
/API/go-chatgpt-api/.gitignore:
--------------------------------------------------------------------------------
1 | .idea
2 | .env
3 | go-chatgpt-api
4 | undetected_chromedriver
5 |
--------------------------------------------------------------------------------
/API/pandora/src/pandora/__init__.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | __version__ = '1.1.9'
4 |
--------------------------------------------------------------------------------
/API/pandora/requirements_api.txt:
--------------------------------------------------------------------------------
1 | pandora-tiktoken~=0.3.1
2 | sqlalchemy~=2.0.7
3 | yoyo-migrations~=8.2.0
--------------------------------------------------------------------------------
/API/pandora/doc/images/s01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlueSkyXN/OpenAI-Quick-DEV/HEAD/API/pandora/doc/images/s01.png
--------------------------------------------------------------------------------
/API/pandora/doc/images/s02.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlueSkyXN/OpenAI-Quick-DEV/HEAD/API/pandora/doc/images/s02.png
--------------------------------------------------------------------------------
/API/pandora/doc/images/s03.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlueSkyXN/OpenAI-Quick-DEV/HEAD/API/pandora/doc/images/s03.png
--------------------------------------------------------------------------------
/API/pandora/doc/images/s04.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlueSkyXN/OpenAI-Quick-DEV/HEAD/API/pandora/doc/images/s04.png
--------------------------------------------------------------------------------
/API/pandora/doc/images/s05.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlueSkyXN/OpenAI-Quick-DEV/HEAD/API/pandora/doc/images/s05.png
--------------------------------------------------------------------------------
/API/pandora/doc/images/s06.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlueSkyXN/OpenAI-Quick-DEV/HEAD/API/pandora/doc/images/s06.png
--------------------------------------------------------------------------------
/API/pandora/doc/images/t0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlueSkyXN/OpenAI-Quick-DEV/HEAD/API/pandora/doc/images/t0.png
--------------------------------------------------------------------------------
/API/pandora/doc/images/t1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlueSkyXN/OpenAI-Quick-DEV/HEAD/API/pandora/doc/images/t1.png
--------------------------------------------------------------------------------
/API/pandora/doc/images/t2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlueSkyXN/OpenAI-Quick-DEV/HEAD/API/pandora/doc/images/t2.png
--------------------------------------------------------------------------------
/API/pandora/doc/images/t3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlueSkyXN/OpenAI-Quick-DEV/HEAD/API/pandora/doc/images/t3.png
--------------------------------------------------------------------------------
/API/pandora/doc/images/t4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlueSkyXN/OpenAI-Quick-DEV/HEAD/API/pandora/doc/images/t4.png
--------------------------------------------------------------------------------
/API/pandora/doc/images/t7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlueSkyXN/OpenAI-Quick-DEV/HEAD/API/pandora/doc/images/t7.png
--------------------------------------------------------------------------------
/API/pandora/doc/images/s11.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlueSkyXN/OpenAI-Quick-DEV/HEAD/API/pandora/doc/images/s11.jpeg
--------------------------------------------------------------------------------
/API/pandora/doc/images/s12.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlueSkyXN/OpenAI-Quick-DEV/HEAD/API/pandora/doc/images/s12.jpeg
--------------------------------------------------------------------------------
/API/pandora/doc/images/t1.1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlueSkyXN/OpenAI-Quick-DEV/HEAD/API/pandora/doc/images/t1.1.png
--------------------------------------------------------------------------------
/API/pandora/.dockerignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 |
3 | .git/
4 | .idea/
5 | .run/
6 | .github/
7 |
8 | venv/
9 | build/
10 | dist/
11 | *.egg-info/
12 |
--------------------------------------------------------------------------------
/API/go-chatgpt-api/.env.example:
--------------------------------------------------------------------------------
1 | # API server port
2 | GO_CHATGPT_API_PORT=8080
3 | # Network proxy server address
4 | GO_CHATGPT_API_PROXY=socks5://ip:port
5 |
--------------------------------------------------------------------------------
/API/pandora/src/pandora/__main__.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | from pandora import launcher
4 |
5 | if __name__ == '__main__':
6 | launcher.run()
7 |
--------------------------------------------------------------------------------
/API/pandora/src/pandora/flask/static/_next/static/olf4sv64FWIcQ_zCGl90t/_ssgManifest.js:
--------------------------------------------------------------------------------
1 | self.__SSG_MANIFEST=new Set,self.__SSG_MANIFEST_CB&&self.__SSG_MANIFEST_CB();
--------------------------------------------------------------------------------
/API/pandora/src/pandora/flask/static/favicon-16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlueSkyXN/OpenAI-Quick-DEV/HEAD/API/pandora/src/pandora/flask/static/favicon-16x16.png
--------------------------------------------------------------------------------
/API/pandora/src/pandora/flask/static/favicon-32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlueSkyXN/OpenAI-Quick-DEV/HEAD/API/pandora/src/pandora/flask/static/favicon-32x32.png
--------------------------------------------------------------------------------
/API/pandora/src/pandora/flask/static/apple-touch-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlueSkyXN/OpenAI-Quick-DEV/HEAD/API/pandora/src/pandora/flask/static/apple-touch-icon.png
--------------------------------------------------------------------------------
/API/pandora/src/pandora/flask/static/fonts/Sohne-Buch.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlueSkyXN/OpenAI-Quick-DEV/HEAD/API/pandora/src/pandora/flask/static/fonts/Sohne-Buch.otf
--------------------------------------------------------------------------------
/API/pandora/src/pandora/flask/static/fonts/KaTeX_Main-Bold.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlueSkyXN/OpenAI-Quick-DEV/HEAD/API/pandora/src/pandora/flask/static/fonts/KaTeX_Main-Bold.woff
--------------------------------------------------------------------------------
/API/pandora/src/pandora/flask/static/fonts/Sohne-Halbfett.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlueSkyXN/OpenAI-Quick-DEV/HEAD/API/pandora/src/pandora/flask/static/fonts/Sohne-Halbfett.otf
--------------------------------------------------------------------------------
/API/pandora/src/pandora/flask/static/fonts/SohneMono-Buch.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlueSkyXN/OpenAI-Quick-DEV/HEAD/API/pandora/src/pandora/flask/static/fonts/SohneMono-Buch.otf
--------------------------------------------------------------------------------
/API/pandora/src/pandora/flask/static/fonts/KaTeX_Main-Italic.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlueSkyXN/OpenAI-Quick-DEV/HEAD/API/pandora/src/pandora/flask/static/fonts/KaTeX_Main-Italic.woff
--------------------------------------------------------------------------------
/API/pandora/src/pandora/flask/static/fonts/KaTeX_Math-Italic.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlueSkyXN/OpenAI-Quick-DEV/HEAD/API/pandora/src/pandora/flask/static/fonts/KaTeX_Math-Italic.woff
--------------------------------------------------------------------------------
/API/pandora/src/pandora/flask/static/fonts/Signifier-Regular.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlueSkyXN/OpenAI-Quick-DEV/HEAD/API/pandora/src/pandora/flask/static/fonts/Signifier-Regular.otf
--------------------------------------------------------------------------------
/API/pandora/src/pandora/flask/static/fonts/SohneMono-Halbfett.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlueSkyXN/OpenAI-Quick-DEV/HEAD/API/pandora/src/pandora/flask/static/fonts/SohneMono-Halbfett.otf
--------------------------------------------------------------------------------
/API/pandora/src/pandora/flask/static/fonts/KaTeX_Fraktur-Bold.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlueSkyXN/OpenAI-Quick-DEV/HEAD/API/pandora/src/pandora/flask/static/fonts/KaTeX_Fraktur-Bold.woff
--------------------------------------------------------------------------------
/API/pandora/src/pandora/flask/static/fonts/KaTeX_Main-Regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlueSkyXN/OpenAI-Quick-DEV/HEAD/API/pandora/src/pandora/flask/static/fonts/KaTeX_Main-Regular.woff
--------------------------------------------------------------------------------
/API/pandora/src/pandora/flask/static/fonts/KaTeX_SansSerif-Bold.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlueSkyXN/OpenAI-Quick-DEV/HEAD/API/pandora/src/pandora/flask/static/fonts/KaTeX_SansSerif-Bold.woff
--------------------------------------------------------------------------------
/API/pandora/src/pandora/flask/static/fonts/KaTeX_Script-Regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlueSkyXN/OpenAI-Quick-DEV/HEAD/API/pandora/src/pandora/flask/static/fonts/KaTeX_Script-Regular.woff
--------------------------------------------------------------------------------
/API/pandora/src/pandora/flask/static/fonts/KaTeX_Size1-Regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlueSkyXN/OpenAI-Quick-DEV/HEAD/API/pandora/src/pandora/flask/static/fonts/KaTeX_Size1-Regular.woff
--------------------------------------------------------------------------------
/API/pandora/src/pandora/flask/static/fonts/KaTeX_Size2-Regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlueSkyXN/OpenAI-Quick-DEV/HEAD/API/pandora/src/pandora/flask/static/fonts/KaTeX_Size2-Regular.woff
--------------------------------------------------------------------------------
/API/pandora/src/pandora/flask/static/fonts/KaTeX_Size3-Regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlueSkyXN/OpenAI-Quick-DEV/HEAD/API/pandora/src/pandora/flask/static/fonts/KaTeX_Size3-Regular.woff
--------------------------------------------------------------------------------
/API/pandora/src/pandora/flask/static/fonts/KaTeX_Size4-Regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlueSkyXN/OpenAI-Quick-DEV/HEAD/API/pandora/src/pandora/flask/static/fonts/KaTeX_Size4-Regular.woff
--------------------------------------------------------------------------------
/API/pandora/src/pandora/flask/static/fonts/KaTeX_Caligraphic-Bold.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlueSkyXN/OpenAI-Quick-DEV/HEAD/API/pandora/src/pandora/flask/static/fonts/KaTeX_Caligraphic-Bold.woff
--------------------------------------------------------------------------------
/API/pandora/src/pandora/flask/static/fonts/KaTeX_Fraktur-Regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlueSkyXN/OpenAI-Quick-DEV/HEAD/API/pandora/src/pandora/flask/static/fonts/KaTeX_Fraktur-Regular.woff
--------------------------------------------------------------------------------
/API/pandora/src/pandora/flask/static/fonts/KaTeX_Main-BoldItalic.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlueSkyXN/OpenAI-Quick-DEV/HEAD/API/pandora/src/pandora/flask/static/fonts/KaTeX_Main-BoldItalic.woff
--------------------------------------------------------------------------------
/API/pandora/src/pandora/flask/static/fonts/KaTeX_Math-BoldItalic.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlueSkyXN/OpenAI-Quick-DEV/HEAD/API/pandora/src/pandora/flask/static/fonts/KaTeX_Math-BoldItalic.woff
--------------------------------------------------------------------------------
/API/pandora/src/pandora/flask/static/fonts/KaTeX_SansSerif-Italic.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlueSkyXN/OpenAI-Quick-DEV/HEAD/API/pandora/src/pandora/flask/static/fonts/KaTeX_SansSerif-Italic.woff
--------------------------------------------------------------------------------
/API/pandora/src/pandora/flask/static/fonts/KaTeX_Caligraphic-Regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlueSkyXN/OpenAI-Quick-DEV/HEAD/API/pandora/src/pandora/flask/static/fonts/KaTeX_Caligraphic-Regular.woff
--------------------------------------------------------------------------------
/API/pandora/src/pandora/flask/static/fonts/KaTeX_SansSerif-Regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlueSkyXN/OpenAI-Quick-DEV/HEAD/API/pandora/src/pandora/flask/static/fonts/KaTeX_SansSerif-Regular.woff
--------------------------------------------------------------------------------
/API/pandora/src/pandora/flask/static/fonts/KaTeX_Typewriter-Regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlueSkyXN/OpenAI-Quick-DEV/HEAD/API/pandora/src/pandora/flask/static/fonts/KaTeX_Typewriter-Regular.woff
--------------------------------------------------------------------------------
/API/pandora/MANIFEST.in:
--------------------------------------------------------------------------------
1 | include requirements.txt
2 | include requirements_api.txt
3 | include src/pandora/py.typed
4 | recursive-include src/pandora/flask *
5 | recursive-include src/pandora/migrations/scripts *
6 |
--------------------------------------------------------------------------------
/API/pandora/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM python:3.9-slim
2 |
3 | MAINTAINER "Neo Peng "
4 |
5 | VOLUME /data
6 |
7 | WORKDIR /opt/app
8 |
9 | ADD . .
10 |
11 | RUN pip --no-cache-dir install --upgrade pip && pip --no-cache-dir install .[api,cloud]
12 |
13 | ENTRYPOINT ["bin/startup.sh"]
14 |
--------------------------------------------------------------------------------
/API/ChatGPT-to-API/.gitignore:
--------------------------------------------------------------------------------
1 | tools/authenticator/100-ACCOUNTS_COMPILED.txt
2 | tools/authenticator/accounts.txt
3 | tools/authenticator/proxies.txt
4 | tools/authenticator/authenticated_accounts.txt
5 | tools/authenticator/access_tokens.txt
6 | *.txt
7 | access_tokens.json
8 | freechatgpt
9 | chatgpttoapi
10 |
--------------------------------------------------------------------------------
/API/go-chatgpt-api/compose.yaml:
--------------------------------------------------------------------------------
1 | services:
2 | go-chatgpt-api:
3 | build: .
4 | container_name: go-chatgpt-api
5 | image: linweiyuan/go-chatgpt-api
6 | ports:
7 | - 8080:8080
8 | environment:
9 | - TZ=Asia/Shanghai
10 | - GO_CHATGPT_API_PROXY=
11 | restart: unless-stopped
12 |
--------------------------------------------------------------------------------
/API/pandora/src/pandora/flask/static/_next/static/chunks/pages/_error-786d27d84962122a.js:
--------------------------------------------------------------------------------
1 | (self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[820],{17917:function(n,_,u){(window.__NEXT_P=window.__NEXT_P||[]).push(["/_error",function(){return u(14902)}])}},function(n){n.O(0,[774,888,179],function(){return n(n.s=17917)}),_N_E=n.O()}]);
--------------------------------------------------------------------------------
/API/ChatGPT-to-API/internal/typings/api.go:
--------------------------------------------------------------------------------
1 | package types
2 |
3 | type APIRequest struct {
4 | Messages []api_message `json:"messages"`
5 | Stream bool `json:"stream"`
6 | Model string `json:"model"`
7 | }
8 |
9 | type api_message struct {
10 | Role string `json:"role"`
11 | Content string `json:"content"`
12 | }
13 |
--------------------------------------------------------------------------------
/API/go-chatgpt-api/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM golang:alpine AS builder
2 | WORKDIR /app
3 | COPY . .
4 | RUN go build -ldflags="-w -s" -o go-chatgpt-api main.go
5 |
6 | FROM alpine
7 | WORKDIR /app
8 | COPY --from=builder /app/go-chatgpt-api .
9 | RUN apk add --no-cache tzdata
10 | ENV TZ=Asia/Shanghai
11 | EXPOSE 8080
12 | CMD ["/app/go-chatgpt-api"]
13 |
--------------------------------------------------------------------------------
/API/pandora/src/pandora/migrations/database.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | from sqlalchemy import create_engine
4 | from sqlalchemy.orm import sessionmaker
5 |
6 | from ..exts.config import DATABASE_URI
7 |
8 | engine = create_engine(DATABASE_URI, echo=False)
9 |
10 | Session = sessionmaker(bind=engine)
11 |
12 | session = Session()
13 |
--------------------------------------------------------------------------------
/API/pandora/requirements.txt:
--------------------------------------------------------------------------------
1 | certifi
2 | pyreadline3 ~= 3.4.0; platform_system == 'Windows'
3 | httpx[socks]~=0.23.3
4 | requests[socks]~=2.28.2
5 | rich~=13.3.2
6 | appdirs~=1.4.4
7 | werkzeug~=2.2.3
8 | flask~=2.2.3
9 | flask-cors~=3.0.10
10 | waitress~=2.1.2
11 | loguru~=0.6.0
12 | sentry-sdk~=1.17.0
13 | pyjwt[crypto]~=2.6.0
14 | pyperclip~=1.8.2
15 |
--------------------------------------------------------------------------------
/API/pandora/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3'
2 | services:
3 | pandora:
4 | image: pengzhile/pandora:latest
5 | platform: linux/amd64
6 | ports:
7 | - 18848:8848
8 | environment:
9 | - PANDORA_SERVER=0.0.0.0:8848
10 | - PANDORA_ACCESS_TOKEN=eyJhGUiOnsiZW1
11 | ##- PANDORA_API=sk
12 | ##- PANDORA_VERBOSE=False
13 |
--------------------------------------------------------------------------------
/API/pandora/src/pandora/exts/config.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | from os import getenv
4 | from os.path import join
5 |
6 | from appdirs import user_config_dir
7 |
8 | USER_CONFIG_DIR = getenv('USER_CONFIG_DIR', user_config_dir('Pandora-ChatGPT'))
9 | DATABASE_URI = getenv('DATABASE_URI',
10 | 'sqlite:///{}?check_same_thread=False'.format(join(USER_CONFIG_DIR, 'pandora-chatgpt.db')))
11 |
--------------------------------------------------------------------------------
/API/ChatGPT-to-API/tools/authenticator/README.md:
--------------------------------------------------------------------------------
1 | # Automated authentication for ChatGPT
2 | Fetches access tokens from a large number of accounts
3 |
4 | ## Setup
5 | ### `proxies.txt`
6 | Format:
7 | ```
8 | IP:HOST:User:Password
9 | ...
10 | ```
11 |
12 | ### `accounts.txt`
13 | Format:
14 | ```
15 | email:password
16 | ...
17 | ```
18 |
19 | Remember to:
20 | `touch access_tokens.txt authenticated_accounts.txt`
21 |
--------------------------------------------------------------------------------
/API/pandora/src/pandora/flask/static/_next/static/chunks/68a27ff6-1185184b61bc22d0.js:
--------------------------------------------------------------------------------
1 | "use strict";(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[798],{13002:function(t,n,r){r.d(n,{oT$:function(){return o}});var e=r(50913);function o(t){return(0,e.w_)({tag:"svg",attr:{fill:"none",viewBox:"0 0 24 24",stroke:"currentColor"},child:[{tag:"path",attr:{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:"2",d:"M10 20l4-16m4 4l4 4-4 4M6 16l-4-4 4-4"}}]})(t)}}}]);
--------------------------------------------------------------------------------
/API/pandora/src/pandora/flask/static/_next/static/chunks/bd26816a-981e1ddc27b37cc6.js:
--------------------------------------------------------------------------------
1 | "use strict";(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[786],{54655:function(t,n,e){e.d(n,{Ny3:function(){return o}});var r=e(50913);function o(t){return(0,r.w_)({tag:"svg",attr:{viewBox:"0 0 24 24",strokeWidth:"2",stroke:"currentColor",fill:"none",strokeLinecap:"round",strokeLinejoin:"round"},child:[{tag:"desc",attr:{},child:[]},{tag:"path",attr:{stroke:"none",d:"M0 0h24v24H0z",fill:"none"}},{tag:"path",attr:{d:"M5 9h14m-14 6h14"}}]})(t)}}}]);
--------------------------------------------------------------------------------
/API/pandora/src/pandora/openai/token.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | import tiktoken
4 |
5 |
6 | def gpt_num_tokens(messages, model='gpt-3.5-turbo'):
7 | encoding = tiktoken.encoding_for_model(model)
8 |
9 | num_tokens = 0
10 | for message in messages:
11 | num_tokens += 4
12 | for key, value in message.items():
13 | num_tokens += len(encoding.encode(value))
14 | if 'name' == key:
15 | num_tokens -= 1
16 | num_tokens += 2
17 |
18 | return num_tokens
19 |
--------------------------------------------------------------------------------
/GPT-Config.example.ini:
--------------------------------------------------------------------------------
1 | ; GPT-Config.ini 配置文件
2 | ; 本配置文件用于设置GPT应用程序的相关参数。
3 | ; 请在明确了解相关配置项含义和作用的情况下修改本文件。
4 |
5 | [Settings]
6 | ; 以下是API端点的URL。
7 | ; 除非有特定的需要,否则请勿修改此设置。
8 | ; 默认值: http://127.0.0.1:31480/v1/chat/completions
9 | url = http://127.0.0.1:31480/v1/chat/completions
10 |
11 | ; 以下是API的认证令牌。
12 | ; 你应该将此项修改为你自己的独特且安全的令牌。
13 | ; 默认值: TotallySecurePassword
14 | auth = TotallySecurePassword
15 |
16 | ; 以下是API使用的模型。
17 | ; 如果你需要,可以将此项更改为任何其他兼容的模型。
18 | ; 默认值: gpt-3.5
19 | ; 可选值: gpt-3.5, gpt-3.5-mobile, gpt-4-mobile, gpt-4, gpt-4-browsing, gpt-4-plugins
20 | model = gpt-3.5
21 |
--------------------------------------------------------------------------------
/API/go-chatgpt-api/middleware/cors.go:
--------------------------------------------------------------------------------
1 | package middleware
2 |
3 | import (
4 | "github.com/gin-gonic/gin"
5 |
6 | http "github.com/bogdanfinn/fhttp"
7 | )
8 |
9 | func CORSMiddleware() gin.HandlerFunc {
10 | return func(c *gin.Context) {
11 | c.Writer.Header().Set("Access-Control-Allow-Origin", "*")
12 | c.Writer.Header().Set("Access-Control-Allow-Headers", "*")
13 | c.Writer.Header().Set("Access-Control-Allow-Methods", "*")
14 |
15 | if c.Request.Method == http.MethodOptions {
16 | c.AbortWithStatus(http.StatusNoContent)
17 | return
18 | }
19 |
20 | c.Next()
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/API/pandora/src/pandora/exts/sentry.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | import sentry_sdk
4 | from sentry_sdk import capture_exception
5 |
6 | from .. import __version__
7 |
8 |
9 | def init(proxy):
10 | sentry_sdk.init(
11 | dsn="https://8f3144c644b5410d825c644aa0040c71@o4504791776755712.ingest.sentry.io/4504791778394112",
12 | http_proxy=proxy,
13 | https_proxy=proxy,
14 | traces_sample_rate=0,
15 | environment='production',
16 | release='pandora@{}'.format(__version__),
17 | )
18 |
19 |
20 | def capture(e):
21 | capture_exception(e)
22 |
--------------------------------------------------------------------------------
/API/go-chatgpt-api/middleware/check_header.go:
--------------------------------------------------------------------------------
1 | package middleware
2 |
3 | import (
4 | "net/http"
5 |
6 | "github.com/gin-gonic/gin"
7 | "github.com/linweiyuan/go-chatgpt-api/api"
8 | )
9 |
10 | func CheckHeaderMiddleware() gin.HandlerFunc {
11 | return func(c *gin.Context) {
12 | if c.GetHeader(api.AuthorizationHeader) == "" &&
13 | c.Request.URL.Path != "/chatgpt/login" &&
14 | c.Request.URL.Path != "/platform/login" {
15 | c.AbortWithStatusJSON(http.StatusUnauthorized, api.ReturnMessage("Missing accessToken."))
16 | return
17 | }
18 |
19 | c.Header("Content-Type", "application/json")
20 | c.Next()
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/QT_MD.py:
--------------------------------------------------------------------------------
1 | import sys
2 | from PyQt6.QtWidgets import QApplication, QTextBrowser
3 | import markdown
4 |
5 | class MainWindow(QTextBrowser):
6 | def __init__(self):
7 | super().__init__()
8 |
9 | # Markdown text
10 | md_text = """
11 | # Hello
12 |
13 | This is some **Markdown** text.
14 | - First item
15 | - Second item
16 | """
17 |
18 | # Convert Markdown to HTML
19 | html = markdown.markdown(md_text)
20 |
21 | # Display HTML in QTextBrowser
22 | self.setHtml(html)
23 |
24 | app = QApplication(sys.argv)
25 | window = MainWindow()
26 | window.show()
27 | sys.exit(app.exec())
28 |
--------------------------------------------------------------------------------
/API/ChatGPT-to-API/docs/TOKEN_CN.md:
--------------------------------------------------------------------------------
1 | # 获取Token
2 | ---
3 | # 参考Pandora项目的作者指导
4 |
5 | https://github.com/pengzhile/pandora
6 |
7 | 获取Token的技术原理 https://zhile.io/2023/05/19/how-to-get-chatgpt-access-token-via-pkce.html
8 |
9 | ## 第三方接口获取Token
10 | http://ai.fakeopen.com/auth
11 |
12 | 你需要在这个新的网站的指导下安装浏览器插件,官方说明的有效期是14天。支持谷歌微软等第三方登录。(我谷歌注册的OpenAI就可以用这个)
13 |
14 | ## 官网获取 Token
15 | https://chat.openai.com/api/auth/session
16 |
17 | 打开后是个JSON,你需要先登录官方的ChatGPT网页版。里面有一个参数就是AccessToken。
18 |
19 | # 参考go-chatgpt-api项目的作者指导
20 | https://github.com/linweiyuan/go-chatgpt-api
21 |
22 | ChatGPT 登录(返回 accessToken)(目前仅支持 ChatGPT 账号,谷歌或微软账号没有测试)
23 |
24 | ```POST /chatgpt/login```
--------------------------------------------------------------------------------
/API/ChatGPT-to-API/tools/authenticator/go.mod:
--------------------------------------------------------------------------------
1 | module authenticator
2 |
3 | go 1.20
4 |
5 | require (
6 | github.com/bogdanfinn/fhttp v0.5.22
7 | github.com/bogdanfinn/tls-client v1.3.12
8 | github.com/nirasan/go-oauth-pkce-code-verifier v0.0.0-20220510032225-4f9f17eaec4c
9 | )
10 |
11 | require (
12 | github.com/andybalholm/brotli v1.0.5 // indirect
13 | github.com/bogdanfinn/utls v1.5.16 // indirect
14 | github.com/klauspost/compress v1.16.5 // indirect
15 | github.com/tam7t/hpkp v0.0.0-20160821193359-2b70b4024ed5 // indirect
16 | golang.org/x/crypto v0.9.0 // indirect
17 | golang.org/x/net v0.10.0 // indirect
18 | golang.org/x/sys v0.8.0 // indirect
19 | golang.org/x/text v0.9.0 // indirect
20 | )
21 |
--------------------------------------------------------------------------------
/API/pandora/src/pandora/migrations/migrate.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | from os import makedirs, path
4 | from os.path import abspath, join, dirname
5 |
6 | from yoyo import get_backend
7 | from yoyo import read_migrations
8 |
9 | from ..exts.config import DATABASE_URI, USER_CONFIG_DIR
10 |
11 |
12 | def do_migrate():
13 | if not path.exists(USER_CONFIG_DIR):
14 | makedirs(USER_CONFIG_DIR)
15 |
16 | url = 'mysql:{}'.format(DATABASE_URI[14:]) if 'mysql+pymysql:' == DATABASE_URI[0:14] else DATABASE_URI
17 | backend = get_backend(url)
18 | migrations = read_migrations(abspath(join(dirname(__file__), 'scripts')))
19 |
20 | with backend.lock():
21 | backend.apply_migrations(backend.to_apply(migrations))
22 |
--------------------------------------------------------------------------------
/API/go-chatgpt-api/util/logger/logger.go:
--------------------------------------------------------------------------------
1 | package logger
2 |
3 | import (
4 | "fmt"
5 |
6 | "github.com/sirupsen/logrus"
7 | )
8 |
9 | func init() {
10 | logrus.SetFormatter(&logrus.TextFormatter{
11 | ForceColors: true,
12 | })
13 | }
14 |
15 | func Ansi(colorString string) func(...interface{}) string {
16 | return func(args ...interface{}) string {
17 | return fmt.Sprintf(colorString, fmt.Sprint(args...))
18 | }
19 | }
20 |
21 | var (
22 | Green = Ansi("\033[1;32m%s\033[0m")
23 | Yellow = Ansi("\033[1;33m%s\033[0m")
24 | Red = Ansi("\033[1;31m%s\033[0m")
25 | )
26 |
27 | func Info(msg string) {
28 | logrus.Info(Green(msg))
29 | }
30 |
31 | func Warn(msg string) {
32 | logrus.Warn(Yellow(msg))
33 | }
34 |
35 | func Error(msg string) {
36 | logrus.Error(Red(msg))
37 | }
38 |
--------------------------------------------------------------------------------
/API/ChatGPT-to-API/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3'
2 |
3 | services:
4 | app:
5 | image: acheong08/chatgpt-to-api # 总是使用latest,更新时重新pull该tag镜像即可
6 | container_name: chatgpttoapi
7 | restart: unless-stopped
8 | ports:
9 | - '8080:8080'
10 | environment:
11 | SERVER_HOST: 0.0.0.0
12 | SERVER_PORT: 8080
13 | ADMIN_PASSWORD: TotallySecurePassword
14 | # Reverse Proxy - Available on accessToken
15 | API_REVERSE_PROXY: https://bypass.churchless.tech/api/conversation
16 | # If the parameter API_REVERSE_PROXY is empty, the default request URL is https://chat.openai.com/backend-api/conversation, and the PUID is required.
17 | # You can get your PUID for Plus account from the following link: https://chat.openai.com/api/auth/session.
18 | PUID: xxx
19 |
--------------------------------------------------------------------------------
/API/ChatGPT-to-API/internal/chatgpt/convert.go:
--------------------------------------------------------------------------------
1 | package chatgpt
2 |
3 | import (
4 | typings "freechatgpt/internal/typings"
5 | "strings"
6 | )
7 |
8 | func ConvertAPIRequest(api_request typings.APIRequest) ChatGPTRequest {
9 | chatgpt_request := NewChatGPTRequest()
10 | if strings.HasPrefix(api_request.Model, "gpt-4") {
11 | chatgpt_request.Model = "gpt-4"
12 | if api_request.Model == "gpt-4-browsing" || api_request.Model == "gpt-4-plugins" || api_request.Model == "gpt-4-mobile" || api_request.Model == "gpt-4-code-interpreter" {
13 | chatgpt_request.Model = api_request.Model
14 | }
15 | }
16 | for _, api_message := range api_request.Messages {
17 | if api_message.Role == "system" {
18 | api_message.Role = "critic"
19 | }
20 | chatgpt_request.AddMessage(api_message.Role, api_message.Content)
21 | }
22 | return chatgpt_request
23 | }
24 |
--------------------------------------------------------------------------------
/chat2api-docker-host.yaml:
--------------------------------------------------------------------------------
1 | version: '3'
2 |
3 | services:
4 | chat2api:
5 | image: lanqian528/chat2api:latest
6 | container_name: chat2api
7 | restart: unless-stopped
8 | network_mode: host # 使用 host 网络模式
9 | volumes:
10 | - ./data:/app/data # 挂载一些需要保存的数据
11 | environment:
12 | - TZ=Asia/Shanghai # 设置时区
13 | - ARKOSE_TOKEN_URL=http://127.0.0.1:5006/token # 使用 host 模式后,直接使用 localhost 访问 arkose 服务
14 | - USER_AGENTS=["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36 Edg/121.2.3.4"]
15 |
16 | arkose:
17 | image: lanqian528/funcaptcha_solver:latest
18 | container_name: funcaptcha_solver
19 | restart: unless-stopped
20 | network_mode: host # 使用 host 网络模式
21 | environment:
22 | - TZ=Asia/Shanghai # 设置时区
23 |
--------------------------------------------------------------------------------
/API/ChatGPT-to-API/tools/authenticator/remove_duplicates.py:
--------------------------------------------------------------------------------
1 | # Removes duplicate lines from a file
2 | # Usage: python remove_duplicates.py
3 |
4 | import sys
5 | import json
6 |
7 |
8 | def remove_duplicates(file_lines):
9 | """
10 | Removes duplicate lines from a file
11 | """
12 | lines_set = set()
13 | for lin in file_lines:
14 | #if json.loads(lin)["output"] == "":
15 | # continue
16 | lines_set.add(lin)
17 | return lines_set
18 |
19 |
20 | if __name__ == "__main__":
21 | if len(sys.argv) != 2:
22 | print("Usage: python remove_duplicates.py ")
23 | sys.exit(1)
24 | orig_file = open(sys.argv[1], "r", encoding="utf-8").readlines()
25 | lines = remove_duplicates(orig_file)
26 | file = open("clean_" + sys.argv[1], "w", encoding="utf-8")
27 | for line in lines:
28 | file.write(line)
29 | file.close()
30 | # Print difference
31 | print(len(orig_file) - len(lines))
32 |
--------------------------------------------------------------------------------
/API/ChatGPT-to-API/Dockerfile:
--------------------------------------------------------------------------------
1 | # Use the official Golang image as the builder
2 | FROM golang:1.20.3-alpine as builder
3 |
4 | # Enable CGO to use C libraries (set to 0 to disable it)
5 | # We set it to 0 to build a fully static binary for our final image
6 | ENV CGO_ENABLED=0
7 |
8 | # Set the working directory
9 | WORKDIR /app
10 |
11 | # Copy the Go Modules manifests (go.mod and go.sum files)
12 | COPY go.mod go.sum ./
13 |
14 | # Download the dependencies
15 | RUN go mod download
16 |
17 | # Copy the source code
18 | COPY . .
19 |
20 | # Build the Go application and output the binary to /app/ChatGPT-Proxy-V4
21 | RUN go build -o /app/ChatGPT-To-API .
22 |
23 | # Use a scratch image as the final distroless image
24 | FROM scratch
25 |
26 | # Set the working directory
27 | WORKDIR /app
28 |
29 | # Copy the built Go binary from the builder stage
30 | COPY --from=builder /app/ChatGPT-To-API /app/ChatGPT-To-API
31 |
32 | # Expose the port where the application is running
33 | EXPOSE 8080
34 |
35 | # Start the application
36 | CMD [ "./ChatGPT-To-API" ]
37 |
--------------------------------------------------------------------------------
/API/pandora/src/pandora/migrations/scripts/20230308_01_7ctOr.sql:
--------------------------------------------------------------------------------
1 | -- Init database
2 | -- depends:
3 |
4 | drop table if exists conversation_official;
5 | create table conversation_official
6 | (
7 | conversation_id char(36)
8 | primary key,
9 | title text not null,
10 | create_time integer not null
11 | );
12 |
13 | drop table if exists conversation_info;
14 | create table conversation_info
15 | (
16 | conversation_id char(36)
17 | primary key,
18 | title varchar(200) not null,
19 | create_time integer not null,
20 | current_node char(36)
21 | );
22 |
23 | drop table if exists prompt_info;
24 | create table prompt_info
25 | (
26 | prompt_id char(36) not null,
27 | conversation_id char(36) not null,
28 | model varchar(64),
29 | parent_id char(36),
30 | role varchar(20),
31 | content longtext,
32 | create_time integer not null,
33 | constraint prompt_info_pk
34 | primary key (conversation_id, prompt_id)
35 | );
36 |
--------------------------------------------------------------------------------
/API/pandora/src/pandora/exts/hooks.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | import logging
4 | import sys
5 |
6 | from loguru import logger
7 |
8 |
9 | def __exception_handle(e_type, e_value, e_traceback):
10 | if issubclass(e_type, KeyboardInterrupt):
11 | print('\nBye...')
12 | sys.exit(0)
13 |
14 | sys.__excepthook__(e_type, e_value, e_traceback)
15 |
16 |
17 | class __InterceptHandler(logging.Handler):
18 | def emit(self, record):
19 | try:
20 | level = logger.level(record.levelname).name
21 | except ValueError:
22 | level = record.levelno
23 |
24 | frame, depth = logging.currentframe(), 2
25 | while frame.f_code.co_filename == logging.__file__:
26 | frame = frame.f_back
27 | depth += 1
28 |
29 | logger.opt(depth=depth, exception=record.exc_info).log(
30 | level, record.getMessage()
31 | )
32 |
33 |
34 | def hook_except_handle():
35 | sys.excepthook = __exception_handle
36 |
37 |
38 | def hook_logging(**kwargs):
39 | logging.basicConfig(handlers=[__InterceptHandler()], **kwargs)
40 |
--------------------------------------------------------------------------------
/API/pandora/bin/startup.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | PANDORA_ARGS=""
4 | PANDORA_COMMAND="pandora"
5 | USER_CONFIG_DIR="/data"
6 |
7 | if [ -n "${PANDORA_PROXY}" ]; then
8 | PANDORA_ARGS="${PANDORA_ARGS} -p ${PANDORA_PROXY}"
9 | fi
10 |
11 | if [ -n "${PANDORA_ACCESS_TOKEN}" ]; then
12 | mkdir -p "${USER_CONFIG_DIR}"
13 |
14 | echo "${PANDORA_ACCESS_TOKEN}" >"${USER_CONFIG_DIR}/access_token.dat"
15 | fi
16 |
17 | if [ -n "${PANDORA_TOKENS_FILE}" ]; then
18 | PANDORA_ARGS="${PANDORA_ARGS} --tokens_file ${PANDORA_TOKENS_FILE}"
19 | fi
20 |
21 | if [ -n "${PANDORA_SERVER}" ]; then
22 | PANDORA_ARGS="${PANDORA_ARGS} -s ${PANDORA_SERVER}"
23 | fi
24 |
25 | if [ -n "${PANDORA_API}" ]; then
26 | PANDORA_ARGS="${PANDORA_ARGS} -a"
27 | fi
28 |
29 | if [ -n "${PANDORA_SENTRY}" ]; then
30 | PANDORA_ARGS="${PANDORA_ARGS} --sentry"
31 | fi
32 |
33 | if [ -n "${PANDORA_VERBOSE}" ]; then
34 | PANDORA_ARGS="${PANDORA_ARGS} -v"
35 | fi
36 |
37 | if [ -n "${PANDORA_CLOUD}" ]; then
38 | PANDORA_COMMAND="pandora-cloud"
39 | fi
40 |
41 | export USER_CONFIG_DIR
42 |
43 | # shellcheck disable=SC2086
44 | $(command -v ${PANDORA_COMMAND}) ${PANDORA_ARGS}
45 |
--------------------------------------------------------------------------------
/API/ChatGPT-to-API/internal/tokens/tokens.go:
--------------------------------------------------------------------------------
1 | package tokens
2 |
3 | import (
4 | "encoding/json"
5 | "os"
6 | "sync"
7 | )
8 |
9 | type AccessToken struct {
10 | tokens []string
11 | lock sync.Mutex
12 | }
13 |
14 | func NewAccessToken(tokens []string) AccessToken {
15 | // Save the tokens to a file
16 | if _, err := os.Stat("access_tokens.json"); os.IsNotExist(err) {
17 | // Create the file
18 | file, err := os.Create("access_tokens.json")
19 | if err != nil {
20 | return AccessToken{}
21 | }
22 | defer file.Close()
23 | }
24 | file, err := os.OpenFile("access_tokens.json", os.O_WRONLY|os.O_TRUNC, 0644)
25 | if err != nil {
26 | return AccessToken{}
27 | }
28 | defer file.Close()
29 | encoder := json.NewEncoder(file)
30 | err = encoder.Encode(tokens)
31 | if err != nil {
32 | return AccessToken{}
33 | }
34 | return AccessToken{
35 | tokens: tokens,
36 | }
37 | }
38 |
39 | func (a *AccessToken) GetToken() string {
40 | a.lock.Lock()
41 | defer a.lock.Unlock()
42 |
43 | if len(a.tokens) == 0 {
44 | return ""
45 | }
46 |
47 | token := a.tokens[0]
48 | a.tokens = append(a.tokens[1:], token)
49 | return token
50 | }
51 |
--------------------------------------------------------------------------------
/API/go-chatgpt-api/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 linweiyuan
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/API/ChatGPT-to-API/docs/admin.md:
--------------------------------------------------------------------------------
1 | # API Documentation:
2 |
3 | ## passwordHandler:
4 |
5 | This API endpoint receives a POST request with a JSON body that contains a "password" field. The API updates the value of the ADMIN_PASSWORD variable with the value provided in the request body.
6 |
7 | HTTP method: PATCH
8 |
9 | Endpoint: /password
10 |
11 | Request body:
12 |
13 | ```json
14 | {
15 | "password": string
16 | }
17 | ```
18 |
19 | Response status codes:
20 | - 200 OK: The ADMIN_PASSWORD variable was successfully updated.
21 | - 400 Bad Request: The "password" field is missing or not provided in the request body.
22 |
23 | ## tokensHandler:
24 |
25 | This API endpoint receives a POST request with a JSON body that contains an array of request tokens. The API updates the value of the ACCESS_TOKENS variable with a new access token generated from the request tokens provided in the request body.
26 |
27 | HTTP method: PATCH
28 |
29 | Endpoint: /tokens
30 |
31 | Request body:
32 |
33 | ```json
34 | [
35 | "string", "..."
36 | ]
37 | ```
38 |
39 | Response status codes:
40 | - 200 OK: The ACCESS_TOKENS variable was successfully updated.
41 | - 400 Bad Request: The request tokens are missing or not provided in the request body.
42 |
--------------------------------------------------------------------------------
/API/go-chatgpt-api/api/chatgpt/constant.go:
--------------------------------------------------------------------------------
1 | package chatgpt
2 |
3 | const (
4 | apiPrefix = "https://chat.openai.com/backend-api"
5 | defaultRole = "user"
6 | getConversationsErrorMessage = "Failed to get conversations."
7 | generateTitleErrorMessage = "Failed to generate title."
8 | getContentErrorMessage = "Failed to get content."
9 | updateConversationErrorMessage = "Failed to update conversation."
10 | clearConversationsErrorMessage = "Failed to clear conversations."
11 | feedbackMessageErrorMessage = "Failed to add feedback."
12 | getModelsErrorMessage = "Failed to get models."
13 | getAccountCheckErrorMessage = "Check failed." // Placeholder. Never encountered.
14 | parseJsonErrorMessage = "Failed to parse json request body."
15 | fallbackErrorMessage = "Fallback failed."
16 | fallbackMethodNotAllowedMessage = "Fallback method not allowed."
17 |
18 | csrfUrl = "https://chat.openai.com/api/auth/csrf"
19 | promptLoginUrl = "https://chat.openai.com/api/auth/signin/auth0?prompt=login"
20 | getCsrfTokenErrorMessage = "Failed to get CSRF token."
21 | authSessionUrl = "https://chat.openai.com/api/auth/session"
22 | )
23 |
--------------------------------------------------------------------------------
/chat2api-docker-warp.yaml:
--------------------------------------------------------------------------------
1 | version: '3'
2 |
3 | services:
4 | arkose:
5 | image: lanqian528/funcaptcha_solver:latest
6 | container_name: funcaptcha-solver
7 | restart: unless-stopped
8 | environment:
9 | - TZ=Asia/Shanghai
10 | ports:
11 | - "5006:5006"
12 | networks:
13 | - chat2api-network
14 |
15 | chat2api:
16 | image: lanqian528/chat2api:latest
17 | container_name: chat2api
18 | restart: unless-stopped
19 | environment:
20 | - ARKOSE_TOKEN_URL=http://arkose:5006/token
21 | - PROXY_URL=socks5://openai:chatgpt@warp:1080
22 | - TZ=Asia/Shanghai
23 | - ENABLE_GATEWAY=false
24 | ports:
25 | - "5005:5005"
26 | volumes:
27 | - /DATA/AppData/Chat2API/app/data:/app/data
28 | networks:
29 | - chat2api-network
30 |
31 | warp:
32 | image: caomingjun/warp:latest
33 | container_name: warp
34 | restart: always
35 | environment:
36 | - WARP_SLEEP=2
37 | - GOST_ARGS=-L openai:chatgpt@:1080
38 | ports:
39 | - "1080:1080"
40 | sysctls:
41 | net.ipv4.conf.all.src_valid_mark: "1"
42 | net.ipv6.conf.all.disable_ipv6: "0"
43 | networks:
44 | - chat2api-network
45 |
46 | networks:
47 | chat2api-network:
48 | name: my_chat2api_network
49 |
--------------------------------------------------------------------------------
/chat2api-docker-warp-host.yaml:
--------------------------------------------------------------------------------
1 | version: '3'
2 |
3 | services:
4 | chat2api:
5 | image: lanqian528/chat2api:latest
6 | container_name: chat2api
7 | restart: unless-stopped
8 | network_mode: host # 使用 host 网络模式
9 | volumes:
10 | - ./data:/app/data # 挂载一些需要保存的数据
11 | environment:
12 | - TZ=Asia/Shanghai # 设置时区
13 | - ARKOSE_TOKEN_URL=http://127.0.0.1:5006/token # 使用 host 模式后,直接使用 localhost 访问 arkose 服务
14 | - USER_AGENTS=["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.2.3.4 Safari/537.36", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36 Edg/121.2.3.4"]
15 | - PROXY_URL=socks5://openai:chatgpt@127.0.0.1:1080
16 | - ENABLE_GATEWAY=true
17 | - HISTORY_DISABLED=false
18 | - SCHEDULED_REFRESH=true
19 |
20 | arkose:
21 | image: lanqian528/funcaptcha_solver:latest
22 | container_name: funcaptcha_solver
23 | restart: unless-stopped
24 | network_mode: host # 使用 host 网络模式
25 | environment:
26 | - TZ=Asia/Shanghai # 设置时区
27 |
28 | warp:
29 | image: caomingjun/warp:latest
30 | container_name: warp
31 | restart: always
32 | network_mode: host # 使用 host 网络模式
33 | environment:
34 | - WARP_SLEEP=2
35 | - GOST_ARGS=-L 0.0.0.0:1080 # 监听所有 IP 地址的 1080 端口
36 |
--------------------------------------------------------------------------------
/API/ChatGPT-to-API/middleware.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "bufio"
5 | "os"
6 |
7 | gin "github.com/gin-gonic/gin"
8 | )
9 |
10 | var ADMIN_PASSWORD string
11 | var API_KEYS map[string]bool
12 |
13 | func init() {
14 | ADMIN_PASSWORD = os.Getenv("ADMIN_PASSWORD")
15 | if ADMIN_PASSWORD == "" {
16 | ADMIN_PASSWORD = "TotallySecurePassword"
17 | }
18 | }
19 |
20 | func adminCheck(c *gin.Context) {
21 | password := c.Request.Header.Get("Authorization")
22 | if password != ADMIN_PASSWORD {
23 | c.String(401, "Unauthorized")
24 | c.Abort()
25 | return
26 | }
27 | c.Next()
28 | }
29 |
30 | func cors(c *gin.Context) {
31 | c.Header("Access-Control-Allow-Origin", "*")
32 | c.Header("Access-Control-Allow-Methods", "*")
33 | c.Header("Access-Control-Allow-Headers", "*")
34 | c.Next()
35 | }
36 |
37 | func Authorization(c *gin.Context) {
38 | if API_KEYS == nil {
39 | API_KEYS = make(map[string]bool)
40 | if _, err := os.Stat("api_keys.txt"); err == nil {
41 | file, _ := os.Open("api_keys.txt")
42 | defer file.Close()
43 | scanner := bufio.NewScanner(file)
44 | for scanner.Scan() {
45 | key := scanner.Text()
46 | if key != "" {
47 | API_KEYS["Bearer "+key] = true
48 | }
49 | }
50 | }
51 | }
52 | if len(API_KEYS) != 0 && !API_KEYS[c.Request.Header.Get("Authorization")] {
53 | c.String(401, "Unauthorized")
54 | c.Abort()
55 | return
56 | }
57 | c.Next()
58 | }
59 |
--------------------------------------------------------------------------------
/API/ChatGPT-to-API/internal/chatgpt/typings.go:
--------------------------------------------------------------------------------
1 | package chatgpt
2 |
3 | import "github.com/google/uuid"
4 |
5 | type chatgpt_message struct {
6 | ID uuid.UUID `json:"id"`
7 | Author chatgpt_author `json:"author"`
8 | Content chatgpt_content `json:"content"`
9 | }
10 |
11 | type chatgpt_content struct {
12 | ContentType string `json:"content_type"`
13 | Parts []string `json:"parts"`
14 | }
15 |
16 | type chatgpt_author struct {
17 | Role string `json:"role"`
18 | }
19 |
20 | type ChatGPTRequest struct {
21 | Action string `json:"action"`
22 | Messages []chatgpt_message `json:"messages"`
23 | ParentMessageID string `json:"parent_message_id,omitempty"`
24 | Model string `json:"model"`
25 | HistoryAndTrainingDisabled bool `json:"history_and_training_disabled"`
26 | }
27 |
28 | func NewChatGPTRequest() ChatGPTRequest {
29 | return ChatGPTRequest{
30 | Action: "next",
31 | ParentMessageID: uuid.NewString(),
32 | Model: "text-davinci-002-render-sha",
33 | HistoryAndTrainingDisabled: true,
34 | }
35 | }
36 |
37 | func (c *ChatGPTRequest) AddMessage(role string, content string) {
38 | c.Messages = append(c.Messages, chatgpt_message{
39 | ID: uuid.New(),
40 | Author: chatgpt_author{Role: role},
41 | Content: chatgpt_content{ContentType: "text", Parts: []string{content}},
42 | })
43 | }
44 |
--------------------------------------------------------------------------------
/API/go-chatgpt-api/api/chatgpt/typings.go:
--------------------------------------------------------------------------------
1 | package chatgpt
2 |
3 | //goland:noinspection GoSnakeCaseUsage
4 | import tls_client "github.com/bogdanfinn/tls-client"
5 |
6 | type UserLogin struct {
7 | client tls_client.HttpClient
8 | }
9 |
10 | type CreateConversationRequest struct {
11 | Action string `json:"action"`
12 | Messages []Message `json:"messages"`
13 | Model string `json:"model"`
14 | ParentMessageID string `json:"parent_message_id"`
15 | ConversationID *string `json:"conversation_id"`
16 | TimezoneOffsetMin int `json:"timezone_offset_min"`
17 | VariantPurpose string `json:"variant_purpose"`
18 | ContinueText string `json:"continue_text"`
19 | }
20 |
21 | type Message struct {
22 | Author Author `json:"author"`
23 | Content Content `json:"content"`
24 | ID string `json:"id"`
25 | }
26 |
27 | type Author struct {
28 | Role string `json:"role"`
29 | }
30 |
31 | type Content struct {
32 | ContentType string `json:"content_type"`
33 | Parts []string `json:"parts"`
34 | }
35 |
36 | type FeedbackMessageRequest struct {
37 | MessageID string `json:"message_id"`
38 | ConversationID string `json:"conversation_id"`
39 | Rating string `json:"rating"`
40 | }
41 |
42 | type GenerateTitleRequest struct {
43 | MessageID string `json:"message_id"`
44 | }
45 |
46 | type PatchConversationRequest struct {
47 | Title *string `json:"title"`
48 | IsVisible bool `json:"is_visible"`
49 | }
50 |
51 | type Cookie struct {
52 | Name string `json:"name"`
53 | Value string `json:"value"`
54 | Expiry int64 `json:"expiry"`
55 | }
56 |
--------------------------------------------------------------------------------
/API/ChatGPT-to-API/README_CN.md:
--------------------------------------------------------------------------------
1 | # ChatGPT-to-API
2 | 创建一个模拟API(通过ChatGPT网页版)
3 |
4 | 本中文手册由 [@BlueSkyXN](https://github.com/BlueSkyXN) 编写
5 |
6 | [英文文档(English Docs)](README.md)
7 |
8 | ## 认证和各项准备工作
9 |
10 | 在使用之前,你需要完成一系列准备工作
11 |
12 | 1. 准备ChatGPT账号,最好的PLUS订阅的,有没有开API不重要
13 | 2. 完善的运行环境和网络环境(否则你总是要寻找方法绕过)
14 | 3. Access Token和PUID,下面会教你怎么获取
15 | 4. 选择一个代理后端或者自行搭建
16 | 5. 你可以在 https://github.com/BlueSkyXN/OpenAI-Quick-DEV 项目找到一些常用组件以及一些快速运行的教程或程序。
17 |
18 | ### 获取PUID
19 |
20 | PUID,就是Personal User ID。这是这个项目中一个特色,其他项目没遇到需要这个的,不过还是弄一下吧。(可能直接访问官网才要,使用或搭建的绕过WAF的代理不需要,目前第三方代理源已经可以自带绕过WAF)
21 |
22 | 获取链接是 https://chat.openai.com/api/auth/session 打开这个URL会得到一个JSON,最前面的 ```{"user":{"id":"user-XXXX","name":"XXXX","email":"XXX",``` 这里面的 user.id 就是我要的PUID(至少我的实践是这个,我并没有找到作者具体的说明)(有可能需要PLUS用户权限,作者的说明是用于绕过CloudFlare的速率限制)
23 |
24 | ### 获取Access Token
25 | 目前有多种方法和原理,这部分内容可以参考 [TOKEN中文手册](docs\TOKEN_CN.md)
26 |
27 | ## 安装和运行
28 |
29 | 作者在[英文版介绍](README.md) 通过GO编译来构建二进制程序,但是我猜测这可能需要一个GO编译环境。所以我建议基于作者的Compose配置文件来Docker运行。
30 |
31 | 有关docker的指导请阅读 [DOCKER中文手册](docs\Docker_CN.md)
32 |
33 | 安装好Docker和Docker-Compase后,通过Compase来启动
34 |
35 | ```docker-compose up -d```
36 |
37 | 注意,启动之前你需要配置 yml 配置文件,主要是端口和环境变量,各项参数、用法请参考 [中文指导手册](docs\GUIDE_CN.md)
38 |
39 | 最后的API端点(Endpoint)是
40 |
41 | ```http://127.0.0.1:8080/v1/chat/completions```
42 |
43 | 注意域名/IP和端口要改成你自己的
44 |
45 | ### 环境变量
46 | - `PUID` - 用户ID
47 | - `http_proxy` - SOCKS5 或 HTTP 代理 `socks5://HOST:PORT`
48 | - `SERVER_HOST` - (default)比如 127.0.0.1
49 | - `SERVER_PORT` - (default)比如 8080 by
50 |
51 | ### 文件选项
52 | - `access_tokens.json` - 附带AccessToken的Json文件
53 | - `proxies.txt` - 代理表 (格式: `USERNAME:PASSWORD:HOST:PORT`)
54 |
55 |
--------------------------------------------------------------------------------
/API/pandora/src/pandora/flask/static/images/2022/11/ChatGPT.jpg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/API/ChatGPT-to-API/tools/plugin_check/check_access.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "bufio"
5 | "encoding/json"
6 | "net/http"
7 | "os"
8 | )
9 |
10 | func main() {
11 | var access_tokens []string
12 | // Read access_tokens.txt and split by new line
13 | file, err := os.Open("access_tokens.txt")
14 | if err != nil {
15 | panic(err)
16 | }
17 | defer file.Close()
18 | scanner := bufio.NewScanner(file)
19 | for scanner.Scan() {
20 | access_tokens = append(access_tokens, scanner.Text())
21 | }
22 | if err := scanner.Err(); err != nil {
23 | panic(err)
24 | }
25 | // Go routine to check access for each token (limit to 20 simultaneous)
26 | sem := make(chan bool, 20)
27 | for _, token := range access_tokens {
28 | sem <- true
29 | go func(token string) {
30 | defer func() { <-sem }()
31 | if check_access(token) {
32 | println(token)
33 | }
34 | }(token)
35 | }
36 | for i := 0; i < cap(sem); i++ {
37 | sem <- true
38 | }
39 | }
40 |
41 | func check_access(token string) bool {
42 | print(".")
43 | req, _ := http.NewRequest("GET", "https://ai.fakeopen.com/api/accounts/check", nil)
44 | req.Header.Set("Authorization", "Bearer "+token)
45 | client := &http.Client{}
46 | resp, err := client.Do(req)
47 | if err != nil {
48 | panic(err)
49 | }
50 | defer resp.Body.Close()
51 | if resp.StatusCode == 200 {
52 | // Parse response body as JSON
53 | var result map[string]interface{}
54 | json.NewDecoder(resp.Body).Decode(&result)
55 | // Check if "tool1", "tool2", or "tool3" is in the features array
56 | for _, feature := range result["features"].([]interface{}) {
57 | if feature == "tools1" || feature == "tools2" || feature == "tools3" {
58 | return true
59 | }
60 | }
61 | return false
62 | }
63 | println(resp.StatusCode)
64 | return false
65 | }
66 |
--------------------------------------------------------------------------------
/API/go-chatgpt-api/api/platform/constant.go:
--------------------------------------------------------------------------------
1 | package platform
2 |
3 | import "github.com/linweiyuan/go-chatgpt-api/api"
4 |
5 | //goland:noinspection SpellCheckingInspection
6 | const (
7 | apiUrl = "https://api.openai.com"
8 |
9 | apiListModels = apiUrl + "/v1/models"
10 | apiRetrieveModel = apiUrl + "/v1/models/%s"
11 | apiCreateCompletions = apiUrl + "/v1/completions"
12 | apiCreataeChatCompletions = apiUrl + "/v1/chat/completions"
13 | apiCreateEdit = apiUrl + "/v1/edits"
14 | apiCreateImage = apiUrl + "/v1/images/generations"
15 | apiCreateEmbeddings = apiUrl + "/v1/embeddings"
16 | apiListFiles = apiUrl + "/v1/files"
17 |
18 | apiGetCreditGrants = apiUrl + "/dashboard/billing/credit_grants"
19 | apiGetSubscription = apiUrl + "/dashboard/billing/subscription"
20 | apiGetApiKeys = apiUrl + "/dashboard/user/api_keys"
21 |
22 | platformAuthClientID = "DRivsnm2Mu42T3KOpqdtwB3NYviHYzwD"
23 | platformAuthAudience = "https://api.openai.com/v1"
24 | platformAuthRedirectURL = "https://platform.openai.com/auth/callback"
25 | platformAuthScope = "openid profile email offline_access"
26 | platformAuthResponseType = "code"
27 | platformAuthGrantType = "authorization_code"
28 | platformAuth0Url = api.Auth0Url + "/authorize?"
29 | getTokenUrl = api.Auth0Url + "/oauth/token"
30 | auth0Client = "eyJuYW1lIjoiYXV0aDAtc3BhLWpzIiwidmVyc2lvbiI6IjEuMjEuMCJ9" // '{"name":"auth0-spa-js","version":"1.21.0"}'
31 | auth0LogoutUrl = api.Auth0Url + "/v2/logout?returnTo=https%3A%2F%2Fplatform.openai.com%2Floggedout&client_id=" + platformAuthClientID + "&auth0Client=" + auth0Client
32 | dashboardLoginUrl = "https://api.openai.com/dashboard/onboarding/login"
33 | getSessionKeyErrorMessage = "Failed to get session key."
34 | )
35 |
--------------------------------------------------------------------------------
/API/ChatGPT-to-API/go.mod:
--------------------------------------------------------------------------------
1 | module freechatgpt
2 |
3 | go 1.20
4 |
5 | require (
6 | github.com/acheong08/endless v0.0.0-20230522010333-1359fd84c836
7 | github.com/bogdanfinn/fhttp v0.5.22
8 | github.com/bogdanfinn/tls-client v1.3.12
9 | github.com/gin-gonic/gin v1.9.0
10 | github.com/google/uuid v1.3.0
11 | )
12 |
13 | require (
14 | github.com/andybalholm/brotli v1.0.5 // indirect
15 | github.com/bogdanfinn/utls v1.5.16 // indirect
16 | github.com/bytedance/sonic v1.8.9 // indirect
17 | github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
18 | github.com/gabriel-vasile/mimetype v1.4.2 // indirect
19 | github.com/gin-contrib/sse v0.1.0 // indirect
20 | github.com/go-playground/locales v0.14.1 // indirect
21 | github.com/go-playground/universal-translator v0.18.1 // indirect
22 | github.com/go-playground/validator/v10 v10.14.0 // indirect
23 | github.com/goccy/go-json v0.10.2 // indirect
24 | github.com/json-iterator/go v1.1.12 // indirect
25 | github.com/klauspost/compress v1.16.5 // indirect
26 | github.com/klauspost/cpuid/v2 v2.2.4 // indirect
27 | github.com/leodido/go-urn v1.2.4 // indirect
28 | github.com/mattn/go-isatty v0.0.19 // indirect
29 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
30 | github.com/modern-go/reflect2 v1.0.2 // indirect
31 | github.com/pelletier/go-toml/v2 v2.0.7 // indirect
32 | github.com/tam7t/hpkp v0.0.0-20160821193359-2b70b4024ed5 // indirect
33 | github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
34 | github.com/ugorji/go/codec v1.2.11 // indirect
35 | golang.org/x/arch v0.3.0 // indirect
36 | golang.org/x/crypto v0.9.0 // indirect
37 | golang.org/x/net v0.10.0 // indirect
38 | golang.org/x/sys v0.8.0 // indirect
39 | golang.org/x/text v0.9.0 // indirect
40 | google.golang.org/protobuf v1.30.0 // indirect
41 | gopkg.in/yaml.v3 v3.0.1 // indirect
42 | )
43 |
--------------------------------------------------------------------------------
/API/pandora/src/pandora/exts/token.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | from jwt import decode
4 |
5 | from ..openai.utils import Console
6 |
7 | __public_key = b'-----BEGIN PUBLIC KEY-----\n' \
8 | b'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA27rOErDOPvPc3mOADYtQ\n' \
9 | b'BeenQm5NS5VHVaoO/Zmgsf1M0Wa/2WgLm9jX65Ru/K8Az2f4MOdpBxxLL686ZS+K\n' \
10 | b'7eJC/oOnrxCRzFYBqQbYo+JMeqNkrCn34yed4XkX4ttoHi7MwCEpVfb05Qf/ZAmN\n' \
11 | b'I1XjecFYTyZQFrd9LjkX6lr05zY6aM/+MCBNeBWp35pLLKhiq9AieB1wbDPcGnqx\n' \
12 | b'lXuU/bLgIyqUltqLkr9JHsf/2T4VrXXNyNeQyBq5wjYlRkpBQDDDNOcdGpx1buRr\n' \
13 | b'Z2hFyYuXDRrMcR6BQGC0ur9hI5obRYlchDFhlb0ElsJ2bshDDGRk5k3doHqbhj2I\n' \
14 | b'gQIDAQAB\n' \
15 | b'-----END PUBLIC KEY-----'
16 |
17 |
18 | def check_access_token(access_token, api=False):
19 | if api and access_token.startswith('sk-'):
20 | return True
21 |
22 | payload = (decode(access_token, key=__public_key, algorithms='RS256', audience=[
23 | "https://api.openai.com/v1",
24 | "https://openai.openai.auth0app.com/userinfo"
25 | ], issuer='https://auth0.openai.com/'))
26 |
27 | if 'scope' not in payload:
28 | raise Exception('miss scope')
29 |
30 | scope = payload['scope']
31 | if 'model.read' not in scope or 'model.request' not in scope:
32 | raise Exception('invalid scope')
33 |
34 | if 'https://api.openai.com/auth' not in payload or 'https://api.openai.com/profile' not in payload:
35 | raise Exception('belonging to an unregistered user.')
36 |
37 | return payload
38 |
39 |
40 | def check_access_token_out(access_token, api=False):
41 | try:
42 | return check_access_token(access_token, api)
43 | except Exception as e:
44 | Console.error('### Invalid access token: {}'.format(str(e)))
45 | return False
46 |
--------------------------------------------------------------------------------
/API/ChatGPT-to-API/README.md:
--------------------------------------------------------------------------------
1 | # ChatGPT-to-API
2 | Create a fake API using ChatGPT's website
3 |
4 | **API endpoint: http://127.0.0.1:8080/v1/chat/completions.**
5 |
6 | [中文文档(Chinese Docs)](README_CN.md)
7 |
8 | ## Help needed
9 | - Documentation.
10 |
11 | ## Setup
12 |
13 |
14 |
15 |
16 | ### Authentication
17 |
18 |
19 | Access token retrieval has been automated:
20 | https://github.com/acheong08/ChatGPT-to-API/tree/master/tools/authenticator
21 |
22 | Converting from a newline delimited list of access tokens to `access_tokens.json`
23 | ```bash
24 | #!/bin/bash
25 |
26 | START="["
27 | END="]"
28 |
29 | TOKENS=""
30 |
31 | while read -r line; do
32 | if [ -z "$TOKENS" ]; then
33 | TOKENS="\"$line\""
34 | else
35 | TOKENS+=",\"$line\""
36 | fi
37 | done < access_tokens.txt
38 |
39 | echo "$START$TOKENS$END" > access_tokens.json
40 | ```
41 |
42 |
43 |
44 | ## Getting set up
45 |
46 | `git clone https://github.com/acheong08/ChatGPT-to-API`
47 | `cd ChatGPT-to-API`
48 | `go build`
49 | `./freechatgpt`
50 |
51 | ### Environment variables
52 | - `PUID` - A cookie found on chat.openai.com for Plus users. This gets around Cloudflare rate limits
53 | - `http_proxy` - SOCKS5 or HTTP proxy. `socks5://HOST:PORT`
54 | - `SERVER_HOST` - Set to 127.0.0.1 by default
55 | - `SERVER_PORT` - Set to 8080 by default
56 |
57 | ### Files (Optional)
58 | - `access_tokens.json` - A JSON array of access tokens for cycling (Alternatively, send a PATCH request to the [correct endpoint](https://github.com/acheong08/ChatGPT-to-API/blob/master/docs/admin.md))
59 | - `proxies.txt` - A list of proxies separated by new line (Format: `USERNAME:PASSWORD:HOST:PORT`)
60 |
61 |
62 |
63 | ## Admin API docs
64 | https://github.com/acheong08/ChatGPT-to-API/blob/master/docs/admin.md
65 |
66 | ## API usage docs
67 | https://platform.openai.com/docs/api-reference/chat
68 |
--------------------------------------------------------------------------------
/API/go-chatgpt-api/go.mod:
--------------------------------------------------------------------------------
1 | module github.com/linweiyuan/go-chatgpt-api
2 |
3 | go 1.20
4 |
5 | require (
6 | github.com/PuerkitoBio/goquery v1.8.1
7 | github.com/bogdanfinn/fhttp v0.5.22
8 | github.com/bogdanfinn/tls-client v1.3.11
9 | github.com/gin-gonic/gin v1.9.0
10 | github.com/joho/godotenv v1.5.1
11 | github.com/sirupsen/logrus v1.9.0
12 | )
13 |
14 | require (
15 | github.com/andybalholm/brotli v1.0.4 // indirect
16 | github.com/andybalholm/cascadia v1.3.1 // indirect
17 | github.com/bogdanfinn/utls v1.5.16 // indirect
18 | github.com/bytedance/sonic v1.8.0 // indirect
19 | github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
20 | github.com/gin-contrib/sse v0.1.0 // indirect
21 | github.com/go-playground/locales v0.14.1 // indirect
22 | github.com/go-playground/universal-translator v0.18.1 // indirect
23 | github.com/go-playground/validator/v10 v10.11.2 // indirect
24 | github.com/goccy/go-json v0.10.0 // indirect
25 | github.com/json-iterator/go v1.1.12 // indirect
26 | github.com/klauspost/compress v1.15.12 // indirect
27 | github.com/klauspost/cpuid/v2 v2.0.9 // indirect
28 | github.com/leodido/go-urn v1.2.1 // indirect
29 | github.com/mattn/go-isatty v0.0.17 // indirect
30 | github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect
31 | github.com/modern-go/reflect2 v1.0.2 // indirect
32 | github.com/pelletier/go-toml/v2 v2.0.6 // indirect
33 | github.com/tam7t/hpkp v0.0.0-20160821193359-2b70b4024ed5 // indirect
34 | github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
35 | github.com/ugorji/go/codec v1.2.9 // indirect
36 | golang.org/x/arch v0.0.0-20210923205945-b76863e36670 // indirect
37 | golang.org/x/crypto v0.5.0 // indirect
38 | golang.org/x/net v0.7.0 // indirect
39 | golang.org/x/sys v0.5.0 // indirect
40 | golang.org/x/text v0.7.0 // indirect
41 | google.golang.org/protobuf v1.28.1 // indirect
42 | gopkg.in/yaml.v3 v3.0.1 // indirect
43 | )
44 |
--------------------------------------------------------------------------------
/API/ChatGPT-to-API/docs/Docker_CN.md:
--------------------------------------------------------------------------------
1 | # 使用阿里源实现Docker安装
2 |
3 | 移除旧的
4 |
5 | ```yum remove -y docker docker-common docker-selinux docker-engine```
6 |
7 | 安装依赖
8 |
9 | ```yum install -y yum-utils device-mapper-persistent-data lvm2```
10 |
11 | 配置Docker安装源(阿里)
12 |
13 | ```yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo```
14 |
15 | 检查可用的Docker-CE版本
16 |
17 | ```yum list docker-ce --showduplicates | sort -r```
18 |
19 | 安装Docker-CE
20 |
21 | ```yum -y install docker-ce```
22 |
23 | 运行Docker(默认不运行)
24 |
25 | ```systemctl start docker```
26 |
27 | 配置开机启动Docker
28 |
29 | ```systemctl enable docker```
30 |
31 | # 使用官方二进制包安装Docker-Compase
32 |
33 | 下载 Docker-Compose 的二进制文件
34 | ```sudo curl -L "https://github.com/docker/compose/releases/download/v2.18.1/docker-compose-linux-x86_64" -o /usr/local/bin/docker-compose```
35 |
36 | 添加可执行权限
37 |
38 | ```sudo chmod +x /usr/local/bin/docker-compose```
39 |
40 | 验证 Docker-Compose 是否安装成功
41 |
42 | ```docker-compose --version```
43 |
44 | 启动容器
45 |
46 | ```docker-compose up -d```
47 |
48 | 关闭容器
49 |
50 | ```docker-compose down```
51 |
52 | 查看容器(如果启动了这里没有说明启动失败)
53 |
54 | ```docker ps```
55 |
56 | # ChatGPT-TO-API的Docker-Compase文件
57 |
58 | ```
59 | ports:
60 | - '31480:31480'
61 | environment:
62 | SERVER_HOST: 0.0.0.0
63 | SERVER_PORT: 31480
64 | ADMIN_PASSWORD: TotallySecurePassword
65 | # Reverse Proxy - Available on accessToken
66 | #API_REVERSE_PROXY: https://bypass.churchless.tech/api/conversation
67 | #API_REVERSE_PROXY: https://ai.fakeopen.com/api/conversation
68 | PUID: user-7J4tdvHySlcilVgjFIrAtK1k
69 |
70 | ```
71 |
72 | - 这里的ports,左边是外部端口,用于外部访问。右边的Docker端口,需要匹配下面程序设置的监听Port。
73 | - 如果参数`API_REVERSE_PROXY`为空,则默认的请求URL为`https://chat.openai.com/backend-api/conversation`,并且需要提供PUID。PUID的获取参考 [README_CN.md](README_CN.md)
74 | - 这个密码需要自定义,我们构建请求的时候需要它来鉴权。默认是```TotallySecurePassword```
75 |
76 |
--------------------------------------------------------------------------------
/API/ChatGPT-to-API/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "encoding/json"
5 | "freechatgpt/internal/tokens"
6 | "os"
7 | "strings"
8 |
9 | "github.com/acheong08/endless"
10 | "github.com/gin-gonic/gin"
11 | )
12 |
13 | var HOST string
14 | var PORT string
15 | var ACCESS_TOKENS tokens.AccessToken
16 |
17 | func init() {
18 | HOST = os.Getenv("SERVER_HOST")
19 | PORT = os.Getenv("SERVER_PORT")
20 | if HOST == "" {
21 | HOST = "127.0.0.1"
22 | }
23 | if PORT == "" {
24 | PORT = "8080"
25 | }
26 | accessToken := os.Getenv("ACCESS_TOKENS")
27 | if accessToken != "" {
28 | accessTokens := strings.Split(accessToken, ",")
29 | ACCESS_TOKENS = tokens.NewAccessToken(accessTokens)
30 | }
31 | // Check if access_tokens.json exists
32 | if _, err := os.Stat("access_tokens.json"); os.IsNotExist(err) {
33 | // Create the file
34 | file, err := os.Create("access_tokens.json")
35 | if err != nil {
36 | panic(err)
37 | }
38 | defer file.Close()
39 | } else {
40 | // Load the tokens
41 | file, err := os.Open("access_tokens.json")
42 | if err != nil {
43 | panic(err)
44 | }
45 | defer file.Close()
46 | decoder := json.NewDecoder(file)
47 | var token_list []string
48 | err = decoder.Decode(&token_list)
49 | if err != nil {
50 | return
51 | }
52 | ACCESS_TOKENS = tokens.NewAccessToken(token_list)
53 | }
54 | }
55 |
56 | func main() {
57 | router := gin.Default()
58 |
59 | router.Use(cors)
60 |
61 | router.GET("/ping", func(c *gin.Context) {
62 | c.JSON(200, gin.H{
63 | "message": "pong",
64 | })
65 | })
66 |
67 | admin_routes := router.Group("/admin")
68 | admin_routes.Use(adminCheck)
69 |
70 | /// Admin routes
71 | admin_routes.PATCH("/password", passwordHandler)
72 | admin_routes.PATCH("/tokens", tokensHandler)
73 | admin_routes.PATCH("/puid", puidHandler)
74 | /// Public routes
75 | router.OPTIONS("/v1/chat/completions", optionsHandler)
76 | router.POST("/v1/chat/completions", Authorization, nightmare)
77 | endless.ListenAndServe(HOST+":"+PORT, router)
78 | }
79 |
--------------------------------------------------------------------------------
/API/ChatGPT-to-API/tools/authenticator/go.sum:
--------------------------------------------------------------------------------
1 | github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs=
2 | github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
3 | github.com/bogdanfinn/fhttp v0.5.22 h1:U1jhZRtuaOanWWcm1WdMFnwMvSxUQgvO6berqAVTc5o=
4 | github.com/bogdanfinn/fhttp v0.5.22/go.mod h1:brqi5woc5eSCVHdKYBV8aZLbO7HGqpwyDLeXW+fT18I=
5 | github.com/bogdanfinn/tls-client v1.3.12 h1:jpNj7owMY/oULUQyAhAv6tRFkliFGLyr8Qx1ZZY/gp8=
6 | github.com/bogdanfinn/tls-client v1.3.12/go.mod h1:Q46nwIm0wPCweDM3XZcupxEIsTOWo3HVYSSsDj02/Qo=
7 | github.com/bogdanfinn/utls v1.5.16 h1:NhhWkegEcYETBMj9nvgO4lwvc6NcLH+znrXzO3gnw4M=
8 | github.com/bogdanfinn/utls v1.5.16/go.mod h1:mHeRCi69cUiEyVBkKONB1cAbLjRcZnlJbGzttmiuK4o=
9 | github.com/klauspost/compress v1.16.5 h1:IFV2oUNUzZaz+XyusxpLzpzS8Pt5rh0Z16For/djlyI=
10 | github.com/klauspost/compress v1.16.5/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
11 | github.com/nirasan/go-oauth-pkce-code-verifier v0.0.0-20220510032225-4f9f17eaec4c h1:4RYnE0ISVwRxm9Dfo7utw1dh0kdRDEmVYq2MFVLy5zI=
12 | github.com/nirasan/go-oauth-pkce-code-verifier v0.0.0-20220510032225-4f9f17eaec4c/go.mod h1:DvuJJ/w1Y59rG8UTDxsMk5U+UJXJwuvUgbiJSm9yhX8=
13 | github.com/tam7t/hpkp v0.0.0-20160821193359-2b70b4024ed5 h1:YqAladjX7xpA6BM04leXMWAEjS0mTZ5kUU9KRBriQJc=
14 | github.com/tam7t/hpkp v0.0.0-20160821193359-2b70b4024ed5/go.mod h1:2JjD2zLQYH5HO74y5+aE3remJQvl6q4Sn6aWA2wD1Ng=
15 | golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g=
16 | golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0=
17 | golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M=
18 | golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
19 | golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
20 | golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
21 | golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
22 | golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
23 |
--------------------------------------------------------------------------------
/API/ChatGPT-to-API/tools/proxy_check/proxy_check.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "bufio"
5 | "fmt"
6 | "os"
7 | "strings"
8 | "sync"
9 |
10 | tls_client "github.com/bogdanfinn/tls-client"
11 | )
12 |
13 | var proxies []string
14 |
15 | // Read proxies.txt and check if they work
16 | func init() {
17 | // Check for proxies.txt
18 | if _, err := os.Stat("proxies.txt"); err == nil {
19 | // Each line is a proxy, put in proxies array
20 | file, _ := os.Open("proxies.txt")
21 | defer file.Close()
22 | scanner := bufio.NewScanner(file)
23 | for scanner.Scan() {
24 | // Split line by :
25 | proxy := scanner.Text()
26 | proxy_parts := strings.Split(proxy, ":")
27 | if len(proxy_parts) == 2 {
28 | proxy = "socks5://" + proxy
29 | } else if len(proxy_parts) == 4 {
30 | proxy = "socks5://" + proxy_parts[2] + ":" + proxy_parts[3] + "@" + proxy_parts[0] + ":" + proxy_parts[1]
31 | } else {
32 | continue
33 | }
34 | proxies = append(proxies, proxy)
35 | }
36 | }
37 |
38 | }
39 |
40 | func main() {
41 | wg := sync.WaitGroup{}
42 | for _, proxy := range proxies {
43 | wg.Add(1)
44 | go func(proxy string) {
45 | defer wg.Done()
46 | jar := tls_client.NewCookieJar()
47 | options := []tls_client.HttpClientOption{
48 | tls_client.WithTimeoutSeconds(360),
49 | tls_client.WithClientProfile(tls_client.Chrome_110),
50 | tls_client.WithNotFollowRedirects(),
51 | tls_client.WithCookieJar(jar), // create cookieJar instance and pass it as argument
52 | // Disable SSL verification
53 | tls_client.WithInsecureSkipVerify(),
54 | }
55 | client, _ := tls_client.NewHttpClient(tls_client.NewNoopLogger(), options...)
56 |
57 | client.SetProxy(proxy)
58 | resp, err := client.Get("https://example.com")
59 | if err != nil {
60 | fmt.Println("Error: ", err)
61 | fmt.Println("Proxy: ", proxy)
62 | return
63 | }
64 | if resp.StatusCode != 200 {
65 | fmt.Println("Error: ", resp.StatusCode)
66 | fmt.Println("Proxy: ", proxy)
67 | return
68 | } else {
69 | fmt.Println(".")
70 | }
71 | }(proxy)
72 | }
73 | wg.Wait()
74 | }
75 |
--------------------------------------------------------------------------------
/API/pandora/doc/HTTP-API.md:
--------------------------------------------------------------------------------
1 | # Pandora HTTP API
2 |
3 | ### 特殊说明:如果有多个`Access Token`,可以使用`X-Use-Token: token_name` 头指定使用哪个。
4 |
5 | ### `/api/models`
6 |
7 | * **HTTP方法:** `GET`
8 | * **URL参数:** `无`
9 | * **接口描述:** 列出账号可用的模型。
10 |
11 | ### `/api/conversations`
12 |
13 | * **HTTP方法:** `GET`
14 | * **URL参数:**
15 | * `offset` 数字类型,默认为:`1`。
16 | * `limit` 数字类型,默认为:`20`。
17 | * **接口描述:** 以分页方式列出会话列表。
18 |
19 | ### `/api/conversations`
20 |
21 | * **HTTP方法:** `DELETE`
22 | * **URL参数:** `无`
23 | * **接口描述:** 删除所有会话。
24 |
25 | ### `/api/conversation/`
26 |
27 | * **HTTP方法:** `GET`
28 | * **URL参数:** `无`
29 | * **接口描述:** 通过会话ID获取指定会话详情。
30 |
31 | ### `/api/conversation/`
32 |
33 | * **HTTP方法:** `DELETE`
34 | * **URL参数:** `无`
35 | * **接口描述:** 通过会话ID删除指定会话。
36 |
37 | ### `/api/conversation/`
38 |
39 | * **HTTP方法:** `PATCH`
40 | * **JSON字段:**
41 | * `title` 新标题。
42 | * **接口描述:** 通过会话ID设置指定的会话标题。
43 |
44 | ### `/api/conversation/gen_title/`
45 |
46 | * **HTTP方法:** `POST`
47 | * **JSON字段:**
48 | * `model` 对话所使用的模型。
49 | * `message_id` `ChatGPT`回复的那条消息的ID。
50 | * **接口描述:** 自动生成指定新会话的标题,通常首次问答后调用。
51 |
52 | ### `/api/conversation/talk`
53 |
54 | * **HTTP方法:** `POST`
55 | * **JSON字段:**
56 | * `prompt` 提问的内容。
57 | * `model` 对话使用的模型,通常整个会话中保持不变。
58 | * `message_id` 消息ID,通常使用`str(uuid.uuid4())`来生成一个。
59 | * `parent_message_id` 父消息ID,首次同样需要生成。之后获取上一条回复的消息ID即可。
60 | * `conversation_id` 首次对话可不传。`ChatGPT`回复时可获取。
61 | * `stream` 是否使用流的方式输出内容,默认为:`True`
62 | * **接口描述:** 向`ChatGPT`提问,等待其回复。
63 |
64 | ### `/api/conversation/regenerate`
65 |
66 | * **HTTP方法:** `POST`
67 | * **JSON字段:**
68 | * `prompt` 提问的内容。
69 | * `model` 对话使用的模型,通常整个会话中保持不变。
70 | * `message_id` 上一条用户发送消息的ID。
71 | * `parent_message_id` 上一条用户发送消息的父消息ID。
72 | * `conversation_id` 会话ID,在这个接口不可不传。
73 | * `stream` 是否使用流的方式输出内容,默认为:`True`
74 | * **接口描述:** 让`ChatGPT`重新生成回复。
75 |
76 | ### `/api/conversation/goon`
77 |
78 | * **HTTP方法:** `POST`
79 | * **JSON字段:**
80 | * `model` 对话使用的模型,通常整个会话中保持不变。
81 | * `parent_message_id` 父消息ID,上一次`ChatGPT`应答的消息ID。
82 | * `conversation_id` 会话ID。
83 | * `stream` 是否使用流的方式输出内容,默认为:`True`
84 | * **接口描述:** 让`ChatGPT`讲之前的恢复继续下去。
85 |
86 |
--------------------------------------------------------------------------------
/API/pandora/src/pandora/flask/static/_next/static/olf4sv64FWIcQ_zCGl90t/_buildManifest.js:
--------------------------------------------------------------------------------
1 | self.__BUILD_MANIFEST=function(a,c,s,t,e,u,n,h){return{__rewrites:{beforeFiles:[],afterFiles:[],fallback:[]},"/":[t,a,e,"static/chunks/pages/index-f5560462cc9a5a86.js"],"/_error":["static/chunks/pages/_error-786d27d84962122a.js"],"/account/cancel":["static/chunks/pages/account/cancel-1c0d62f7e98cea5a.js"],"/account/manage":["static/chunks/pages/account/manage-515510f9fdcd7b92.js"],"/account/upgrade":[a,c,u,s,n,"static/chunks/pages/account/upgrade-0c6c79f25e11ac2f.js"],"/aip/[pluginId]/oauth/callback":[a,c,s,"static/chunks/pages/aip/[pluginId]/oauth/callback-8bae9003d60a57e1.js"],"/auth/error":["static/chunks/pages/auth/error-31ef8e5e6df49f9f.js"],"/auth/ext_callback":["static/chunks/pages/auth/ext_callback-8a3dba350878939d.js"],"/auth/ext_callback_refresh":["static/chunks/pages/auth/ext_callback_refresh-4cd753ececf58a64.js"],"/auth/login":[c,s,h,"static/chunks/pages/auth/login-7495d2c866b44897.js"],"/auth/logout":[a,"static/chunks/pages/auth/logout-0abf409a2bbf22c9.js"],"/auth/mocked_login":[a,"static/chunks/pages/auth/mocked_login-28119a8b1a5c2bce.js"],"/bypass":["static/chunks/pages/bypass-df27e0f8a3e360f1.js"],"/chat/[[...chatId]]":[t,"static/chunks/1f110208-44a6f43ddc5e9011.js","static/chunks/bd26816a-981e1ddc27b37cc6.js",a,c,e,u,"static/chunks/113-23682f80a24dd00d.js",s,n,"static/chunks/pages/chat/[[...chatId]]-76751174916fa3f7.js"],"/error":[t,a,e,"static/chunks/pages/error-1e886758cd4aa96f.js"],"/payments/success":[a,c,"static/chunks/882-025bd3b738a692ef.js",s,"static/chunks/pages/payments/success-5424184b119a4b94.js"],"/status":[c,s,h,"static/chunks/pages/status-696d2aa0dcc8e977.js"],sortedPages:["/","/_app","/_error","/account/cancel","/account/manage","/account/upgrade","/aip/[pluginId]/oauth/callback","/auth/error","/auth/ext_callback","/auth/ext_callback_refresh","/auth/login","/auth/logout","/auth/mocked_login","/bypass","/chat/[[...chatId]]","/error","/payments/success","/status"]}}("static/chunks/762-222df1028c0c1555.js","static/chunks/424-d1d3bfe6a3ca6c4a.js","static/chunks/264-13e92c51b0315184.js","static/chunks/68a27ff6-1185184b61bc22d0.js","static/chunks/174-bd28069f281ef76f.js","static/chunks/360-442b869f1ba4bb1b.js","static/chunks/14-0cb0d20affbd720d.js","static/chunks/417-2ccfee5029bb2a8b.js"),self.__BUILD_MANIFEST_CB&&self.__BUILD_MANIFEST_CB();
--------------------------------------------------------------------------------
/API/pandora/src/pandora/flask/static/_next/static/chunks/949.1a6eb804b5e91f61.js:
--------------------------------------------------------------------------------
1 | "use strict";(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[949],{93949:function(e,n,t){t.r(n),t.d(n,{SANDBOX_LINK_PREFIX:function(){return s},default:function(){return f},handleSandboxLinkClick:function(){return d}});var r=t(61706),a=t(45813),i=t(35250),c=t(70079),l=t(33264);function o(e){var n=e.accept,t=e.children,r=e.onFilePicked,a=(0,c.useRef)(null),l=(0,c.useCallback)(function(){var e;null===(e=a.current)||void 0===e||e.click()},[]),o=(0,c.useCallback)(function(e){var n,t=null===(n=e.target.files)||void 0===n?void 0:n[0];t&&(r(t),e.target.value="")},[r]);return(0,i.jsxs)(i.Fragment,{children:["function"==typeof t?t({onClick:l}):(0,i.jsx)("span",{role:"button",onClick:l,children:t}),(0,i.jsx)("input",{type:"file",accept:n,ref:a,className:"hidden",onChange:o})]})}var u=t(74516),s="sandbox:";function d(e,n,t){var i;return i=(0,r.Z)(function(r){var i,c,o,s,d,f,h,p,b,v;return(0,a.__generator)(this,function(a){switch(a.label){case 0:if(!(e.has("tools2")&&(null==n?void 0:null===(i=n.enabledTools)||void 0===i?void 0:i.includes("tools2"))))return[2];return c=r.substring(8),[4,l.ZP.checkFile(t.current,c)];case 1:if((o=a.sent()).exists)return[3,2];return u.m.warning("File does not exist: ".concat(c)),[3,6];case 2:if(!o.too_large)return[3,3];return s=(o.size/1024/1024).toFixed(0),d="100",u.m.warning("File is larger than download limit: ".concat(s," MB vs ").concat(d," MB")),[3,6];case 3:return[4,l.ZP.fetchFileForDownload(t.current,c)];case 4:return[4,a.sent().blob()];case 5:h=a.sent(),p=window.URL.createObjectURL(h),(b=document.createElement("a")).href=p,v=c.split("/").pop(),b.download=v,b.click(),a.label=6;case 6:return[2]}})}),function(e){return i.apply(this,arguments)}}function f(e){var n,t=e.onFileUpload,s=e.threadId,d=e.currentLeafId,f=e.modelBackend,h=e.disabled,p=e.children,b=(0,c.useState)(!1),v=b[0],k=b[1],g=(0,c.useCallback)((n=(0,r.Z)(function(e){var n,r,i;return(0,a.__generator)(this,function(a){switch(a.label){case 0:k(!0),a.label=1;case 1:if(a.trys.push([1,,3,4]),e.size>104857600)return n=(e.size/1024/1024).toFixed(0),r="100",u.m.warning("File is larger than upload limit: ".concat(n," MB vs ").concat(r," MB"),{hasCloseButton:!0,duration:15}),[2];return[4,l.ZP.upload(d,s,f,e)];case 2:return t(a.sent()),[3,4];case 3:return k(!1),[7];case 4:return[2]}})}),function(e){return n.apply(this,arguments)}),[t,s,d,f]);return h||v?p(v):(0,i.jsx)(o,{onFilePicked:g,children:p(v)})}}}]);
--------------------------------------------------------------------------------
/API/pandora/src/pandora/cloud_launcher.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | import argparse
4 |
5 | from loguru import logger
6 |
7 | from . import __version__
8 | from .exts import sentry
9 | from .exts.hooks import hook_except_handle
10 | from .openai.utils import Console
11 |
12 | __show_verbose = False
13 |
14 |
15 | def main():
16 | global __show_verbose
17 |
18 | Console.debug_b(
19 | '''
20 | Pandora-Cloud - A web interface to ChatGPT
21 | Github: https://github.com/pengzhile/pandora
22 | Version: {}, Mode: cloud, Engine: free
23 | '''.format(__version__)
24 | )
25 |
26 | parser = argparse.ArgumentParser()
27 | parser.add_argument(
28 | '-p',
29 | '--proxy',
30 | help='Use a proxy. Format: protocol://user:pass@ip:port',
31 | required=False,
32 | type=str,
33 | default=None,
34 | )
35 | parser.add_argument(
36 | '-s',
37 | '--server',
38 | help='Specific server bind. Format: ip:port, default: 127.0.0.1:8018',
39 | required=False,
40 | type=str,
41 | default='127.0.0.1:8018',
42 | )
43 | parser.add_argument(
44 | '--threads',
45 | help='Define the number of server workers, default: 4',
46 | required=False,
47 | type=int,
48 | default=4,
49 | )
50 | parser.add_argument(
51 | '--sentry',
52 | help='Enable sentry to send error reports when errors occur.',
53 | action='store_true',
54 | )
55 | parser.add_argument(
56 | '-v',
57 | '--verbose',
58 | help='Show exception traceback.',
59 | action='store_true',
60 | )
61 | args, _ = parser.parse_known_args()
62 | __show_verbose = args.verbose
63 |
64 | if args.sentry:
65 | sentry.init(args.proxy)
66 |
67 | try:
68 | from pandora_cloud.server import ChatBot as CloudServer
69 |
70 | return CloudServer(args.proxy, args.verbose, args.sentry, True).run(args.server, args.threads)
71 | except (ImportError, ModuleNotFoundError):
72 | Console.error_bh('### You need `pip install Pandora-ChatGPT[cloud]` to support cloud mode.')
73 |
74 |
75 | def run():
76 | hook_except_handle()
77 |
78 | try:
79 | main()
80 | except Exception as e:
81 | Console.error_bh('### Error occurred: ' + str(e))
82 |
83 | if __show_verbose:
84 | logger.exception('Exception occurred.')
85 |
86 | sentry.capture(e)
87 |
--------------------------------------------------------------------------------
/API/pandora/.gitignore:
--------------------------------------------------------------------------------
1 | # Byte-compiled / optimized / DLL files
2 | __pycache__/
3 | *.py[cod]
4 | *$py.class
5 |
6 | # C extensions
7 | *.so
8 |
9 | # Distribution / packaging
10 | .Python
11 | build/
12 | develop-eggs/
13 | dist/
14 | downloads/
15 | eggs/
16 | .eggs/
17 | lib/
18 | lib64/
19 | parts/
20 | sdist/
21 | var/
22 | wheels/
23 | pip-wheel-metadata/
24 | share/python-wheels/
25 | *.egg-info/
26 | .installed.cfg
27 | *.egg
28 | MANIFEST
29 |
30 | # PyInstaller
31 | #Usually these files are written by a python script from a template
32 | #before PyInstaller builds the exe, so as to inject date/other infos into it.
33 | *.manifest
34 | *.spec
35 |
36 | # Installer logs
37 | pip-log.txt
38 | pip-delete-this-directory.txt
39 |
40 | # Unit test / coverage reports
41 | htmlcov/
42 | .tox/
43 | .nox/
44 | .coverage
45 | .coverage.*
46 | .cache
47 | nosetests.xml
48 | coverage.xml
49 | *.cover
50 | *.py,cover
51 | .hypothesis/
52 | .pytest_cache/
53 |
54 | # Translations
55 | *.mo
56 | *.pot
57 |
58 | # Django stuff:
59 | *.log
60 | local_settings.py
61 | db.sqlite3
62 | db.sqlite3-journal
63 |
64 | # Flask stuff:
65 | instance/
66 | .webassets-cache
67 |
68 | # Scrapy stuff:
69 | .scrapy
70 |
71 | # Sphinx documentation
72 | docs/_build/
73 |
74 | # PyBuilder
75 | target/
76 |
77 | # Jupyter Notebook
78 | .ipynb_checkpoints
79 |
80 | # IPython
81 | profile_default/
82 | ipython_config.py
83 |
84 | # pyenv
85 | .python-version
86 |
87 | # pipenv
88 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
89 | # However, in case of collaboration, if having platform-specific dependencies or dependencies
90 | # having no cross-platform support, pipenv may install dependencies that don't work, or not
91 | # install all needed dependencies.
92 | # Pipfile.lock
93 |
94 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow
95 | __pypackages__/
96 |
97 | # Celery stuff
98 | celerybeat-schedule
99 | celerybeat.pid
100 |
101 | # SageMath parsed files
102 | *.sage.py
103 |
104 | # Environments
105 | .env
106 | .venv
107 | env/
108 | venv/
109 | ENV/
110 | env.bak/
111 | venv.bak/
112 |
113 | # Spyder project settings
114 | .spyderproject
115 | .spyproject
116 |
117 | # Rope project settings
118 | .ropeproject
119 |
120 | # mkdocs documentation
121 | /site
122 |
123 | # mypy
124 | .mypy_cache/
125 | .dmypy.json
126 | dmypy.json
127 |
128 | # Pyre type checker
129 | .pyre/
130 |
131 | # JetBrains IDEs configuration
132 | .idea/
133 |
134 | # macOS
135 | .DS_Store
136 |
--------------------------------------------------------------------------------
/API/pandora/setup.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | from setuptools import setup, find_packages
4 |
5 | from src.pandora import __version__
6 |
7 | with open('README.md', 'r', encoding='utf-8') as f:
8 | long_description = f.read()
9 |
10 | with open('requirements.txt', 'r', encoding='utf-8') as f:
11 | requirements = f.read().split('\n')
12 |
13 | with open('requirements_api.txt', 'r', encoding='utf-8') as f:
14 | requirements_api = f.read().split('\n')
15 |
16 | setup(
17 | name='Pandora-ChatGPT',
18 | version=__version__,
19 | python_requires='>=3.7',
20 | author='Neo Peng',
21 | author_email='pengzhile@gmail.com',
22 | keywords='OpenAI ChatGPT ChatGPT-Plus gpt-3.5-turbo gpt-3.5-turbo-0301',
23 | description='A command-line interface to ChatGPT',
24 | long_description=long_description,
25 | long_description_content_type='text/markdown',
26 | url='https://github.com/pengzhile/pandora',
27 | packages=find_packages('src'),
28 | package_dir={'pandora': 'src/pandora'},
29 | include_package_data=True,
30 | install_requires=requirements,
31 | extras_require={
32 | 'api': requirements_api,
33 | 'cloud': ['pandora-cloud~=0.3.2'],
34 | },
35 | entry_points={
36 | 'console_scripts': [
37 | 'pandora = pandora.launcher:run',
38 | 'pandora-cloud = pandora.cloud_launcher:run',
39 | ]
40 | },
41 | project_urls={
42 | 'Source': 'https://github.com/pengzhile/pandora',
43 | 'Tracker': 'https://github.com/pengzhile/pandora/issues',
44 | },
45 | classifiers=[
46 | 'Development Status :: 5 - Production/Stable',
47 |
48 | 'Environment :: Console',
49 | 'Environment :: Web Environment',
50 |
51 | 'Framework :: Flask',
52 |
53 | 'Intended Audience :: Developers',
54 | 'Intended Audience :: End Users/Desktop',
55 |
56 | 'License :: OSI Approved :: GNU General Public License v2 (GPLv2)',
57 |
58 | 'Natural Language :: English',
59 | 'Natural Language :: Chinese (Simplified)',
60 |
61 | 'Operating System :: MacOS',
62 | 'Operating System :: Microsoft :: Windows',
63 | 'Operating System :: POSIX :: Linux',
64 |
65 | 'Programming Language :: SQL',
66 | 'Programming Language :: JavaScript',
67 | 'Programming Language :: Python :: 3.7',
68 | 'Programming Language :: Python :: 3.8',
69 | 'Programming Language :: Python :: 3.9',
70 | 'Programming Language :: Python :: 3.10',
71 | 'Programming Language :: Python :: 3.11',
72 |
73 | 'Topic :: Communications :: Chat',
74 | 'Topic :: Internet :: WWW/HTTP',
75 | ],
76 | )
77 |
--------------------------------------------------------------------------------
/API/ChatGPT-to-API/internal/chatgpt/request.go:
--------------------------------------------------------------------------------
1 | package chatgpt
2 |
3 | import (
4 | "bufio"
5 | "bytes"
6 | "encoding/json"
7 | "math/rand"
8 | "os"
9 | "strings"
10 |
11 | http "github.com/bogdanfinn/fhttp"
12 | tls_client "github.com/bogdanfinn/tls-client"
13 | )
14 |
15 | var proxies []string
16 |
17 | var (
18 | jar = tls_client.NewCookieJar()
19 | options = []tls_client.HttpClientOption{
20 | tls_client.WithTimeoutSeconds(360),
21 | tls_client.WithClientProfile(tls_client.Firefox_110),
22 | tls_client.WithNotFollowRedirects(),
23 | tls_client.WithCookieJar(jar), // create cookieJar instance and pass it as argument
24 | // Disable SSL verification
25 | tls_client.WithInsecureSkipVerify(),
26 | }
27 | client, _ = tls_client.NewHttpClient(tls_client.NewNoopLogger(), options...)
28 | http_proxy = os.Getenv("http_proxy")
29 | API_REVERSE_PROXY = os.Getenv("API_REVERSE_PROXY")
30 | )
31 |
32 | func init() {
33 | // Check for proxies.txt
34 | if _, err := os.Stat("proxies.txt"); err == nil {
35 | // Each line is a proxy, put in proxies array
36 | file, _ := os.Open("proxies.txt")
37 | defer file.Close()
38 | scanner := bufio.NewScanner(file)
39 | for scanner.Scan() {
40 | // Split line by :
41 | proxy := scanner.Text()
42 | proxy_parts := strings.Split(proxy, ":")
43 | if len(proxy_parts) == 2 {
44 | proxy = "socks5://" + proxy
45 | } else if len(proxy_parts) == 4 {
46 | proxy = "socks5://" + proxy_parts[2] + ":" + proxy_parts[3] + "@" + proxy_parts[0] + ":" + proxy_parts[1]
47 | } else {
48 | continue
49 | }
50 | proxies = append(proxies, proxy)
51 | }
52 | }
53 | }
54 |
55 | func random_int(min int, max int) int {
56 | return min + rand.Intn(max-min)
57 | }
58 |
59 | func SendRequest(message ChatGPTRequest, access_token string) (*http.Response, error) {
60 | if http_proxy != "" && len(proxies) == 0 {
61 | client.SetProxy(http_proxy)
62 | }
63 | // Take random proxy from proxies.txt
64 | if len(proxies) > 0 {
65 | client.SetProxy(proxies[random_int(0, len(proxies))])
66 | }
67 |
68 | apiUrl := "https://chat.openai.com/backend-api/conversation"
69 | if API_REVERSE_PROXY != "" {
70 | apiUrl = API_REVERSE_PROXY
71 | }
72 |
73 | // JSONify the body and add it to the request
74 | body_json, err := json.Marshal(message)
75 | if err != nil {
76 | return &http.Response{}, err
77 | }
78 |
79 | request, err := http.NewRequest(http.MethodPost, apiUrl, bytes.NewBuffer(body_json))
80 | if err != nil {
81 | return &http.Response{}, err
82 | }
83 | // Clear cookies
84 | if os.Getenv("PUID") != "" {
85 | request.Header.Set("Cookie", "_puid="+os.Getenv("PUID")+";")
86 | }
87 | request.Header.Set("Content-Type", "application/json")
88 | request.Header.Set("User-Agent", "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36")
89 | request.Header.Set("Accept", "*/*")
90 | if access_token != "" {
91 | request.Header.Set("Authorization", "Bearer "+access_token)
92 | }
93 | if err != nil {
94 | return &http.Response{}, err
95 | }
96 | response, err := client.Do(request)
97 | return response, err
98 | }
99 |
--------------------------------------------------------------------------------
/API/pandora/src/pandora/flask/static/_next/static/chunks/554.9b8bfd0762461d74.js:
--------------------------------------------------------------------------------
1 | "use strict";(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[554],{76554:function(t,e,n){n.r(e),n.d(e,{getLocalhostPluginHttpApiCallData:function(){return l},makeLocalhostPluginHttpApiCall:function(){return c}});var r=n(61706),a=n(31501),o=n(45813),s=n(8844),i=n(68619);function l(t){var e,n=null===(e=t.metadata)||void 0===e?void 0:e.http_api_call_data;if(void 0!==n){if(t.author.role!==i.uU.Assistant){console.error("Refusing to make localhost plugin HTTP call from non-assistant message",t);return}if("object"!=typeof n||"string"!=typeof n.namespace||0===n.namespace.length||"string"!=typeof n.function_name||0===n.function_name.length||"string"!=typeof n.parent_message_id||0===n.parent_message_id.length||"string"!=typeof n.url||0===n.url.length||"string"!=typeof n.method||!["get","post","put","delete","patch"].includes(n.method)||!Array.isArray(n.qs_params)||n.qs_params.some(function(t){return!Array.isArray(t)||2!==t.length||"string"!=typeof t[0]||"string"!=typeof t[1]})||"object"!=typeof n.headers||Object.keys(n.headers).some(function(t){return"string"!=typeof t})||Object.values(n.headers).some(function(t){return"string"!=typeof t})||!(null===n.body||"object"==typeof n.body&&Object.keys(n.body).every(function(t){return"string"==typeof t}))||"string"!=typeof n.api_function_type||!["kwargs","chat"].includes(n.api_function_type)){console.error("Refusing to make localhost plugin HTTP call with invalid metadata",t);return}if(!/^https?:\/\/localhost:/.test(n.url)){console.error("Refusing to make localhost plugin HTTP call with non-localhost URL",t);return}return n}}function c(t){return u.apply(this,arguments)}function u(){return(u=(0,r.Z)(function(t){var e,n;return(0,o.__generator)(this,function(n){switch(n.label){case 0:return n.trys.push([0,2,,3]),[4,function(t){return p.apply(this,arguments)}(t)];case 1:return[2,n.sent()];case 2:return e=n.sent(),console.error("Error making localhost plugin HTTP call",e),[2,[{id:(0,s.Z)(),author:{role:i.uU.System},role:i.uU.Tool,content:{content_type:"text",parts:["Error making localhost plugin HTTP call: ".concat(e)]},metadata:{parent_message_id:t.parent_message_id,is_complete:!0}}]];case 3:return[2]}})})).apply(this,arguments)}function p(){return(p=(0,r.Z)(function(t){var e,n,r,l,c,u;function p(t){return Object.keys(t).map(function(t){return t.toLowerCase()})}return(0,o.__generator)(this,function(o){switch(o.label){case 0:var l,u;if(e={"content-type":"application/json"},u=(l=[p(t.headers),p(e)]).flat(),new Set(u).size!==u.length)throw Error("Refusing to make localhost plugin HTTP call with duplicate header keys");return n=t.url,t.qs_params.length>0&&(n=n+"?"+new URLSearchParams(t.qs_params)),r=void 0,null!==t.body&&(r=JSON.stringify(t.body)),[4,fetch(n,{method:t.method,headers:(0,a.Z)({},e,t.headers),body:r})];case 1:return[4,o.sent().text()];case 2:if(c=o.sent(),"chat"===t.api_function_type)return[2,[JSON.parse(c)]];if("kwargs"===t.api_function_type)return[2,[{id:(0,s.Z)(),author:{role:i.uU.Tool,name:"".concat(t.namespace,".").concat(t.function_name)},role:i.uU.Tool,content:{content_type:"text",parts:[c]},metadata:{parent_message_id:t.parent_message_id,is_complete:!0}}]];throw Error("Not implemented")}})})).apply(this,arguments)}}}]);
--------------------------------------------------------------------------------
/API/go-chatgpt-api/api/common.go:
--------------------------------------------------------------------------------
1 | package api
2 |
3 | //goland:noinspection GoSnakeCaseUsage
4 | import (
5 | "bufio"
6 | "os"
7 | "strings"
8 |
9 | "github.com/gin-gonic/gin"
10 | _ "github.com/linweiyuan/go-chatgpt-api/env"
11 |
12 | http "github.com/bogdanfinn/fhttp"
13 | tls_client "github.com/bogdanfinn/tls-client"
14 | )
15 |
16 | const (
17 | defaultErrorMessageKey = "errorMessage"
18 | AuthorizationHeader = "Authorization"
19 | ContentType = "application/x-www-form-urlencoded"
20 | UserAgent = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36"
21 | Auth0Url = "https://auth0.openai.com"
22 | LoginUsernameUrl = Auth0Url + "/u/login/identifier?state="
23 | LoginPasswordUrl = Auth0Url + "/u/login/password?state="
24 | ParseUserInfoErrorMessage = "Failed to parse user login info."
25 | GetAuthorizedUrlErrorMessage = "Failed to get authorized url."
26 | GetStateErrorMessage = "Failed to get state."
27 | EmailInvalidErrorMessage = "Email is not valid."
28 | EmailOrPasswordInvalidErrorMessage = "Email or password is not correct."
29 | GetAccessTokenErrorMessage = "Failed to get access token."
30 | defaultTimeoutSeconds = 300 // 5 minutes
31 | )
32 |
33 | var Client tls_client.HttpClient
34 |
35 | type LoginInfo struct {
36 | Username string `json:"username"`
37 | Password string `json:"password"`
38 | }
39 |
40 | type AuthLogin interface {
41 | GetAuthorizedUrl(csrfToken string) (string, int, error)
42 | GetState(authorizedUrl string) (string, int, error)
43 | CheckUsername(state string, username string) (int, error)
44 | CheckPassword(state string, username string, password string) (string, int, error)
45 | GetAccessToken(code string) (string, int, error)
46 | }
47 |
48 | //goland:noinspection GoUnhandledErrorResult
49 | func init() {
50 | Client, _ = tls_client.NewHttpClient(tls_client.NewNoopLogger(), []tls_client.HttpClientOption{
51 | tls_client.WithCookieJar(tls_client.NewCookieJar()),
52 | tls_client.WithTimeoutSeconds(defaultTimeoutSeconds),
53 | }...)
54 | }
55 |
56 | func ReturnMessage(msg string) gin.H {
57 | return gin.H{
58 | defaultErrorMessageKey: msg,
59 | }
60 | }
61 |
62 | func GetAccessToken(accessToken string) string {
63 | if !strings.HasPrefix(accessToken, "Bearer") {
64 | return "Bearer " + accessToken
65 | }
66 | return accessToken
67 | }
68 |
69 | //goland:noinspection GoUnhandledErrorResult
70 | func HandleConversationResponse(c *gin.Context, resp *http.Response) {
71 | reader := bufio.NewReader(resp.Body)
72 | for {
73 | if c.Request.Context().Err() != nil {
74 | break
75 | }
76 |
77 | line, err := reader.ReadString('\n')
78 | if err != nil {
79 | break
80 | }
81 |
82 | line = strings.TrimSpace(line)
83 | if strings.HasPrefix(line, "event") ||
84 | strings.HasPrefix(line, "data: 20") ||
85 | line == "" {
86 | continue
87 | }
88 |
89 | c.Writer.Write([]byte(line + "\n\n"))
90 | c.Writer.Flush()
91 | }
92 | }
93 |
94 | //goland:noinspection GoUnhandledErrorResult
95 | func NewHttpClient() tls_client.HttpClient {
96 | client, _ := tls_client.NewHttpClient(tls_client.NewNoopLogger(), []tls_client.HttpClientOption{
97 | tls_client.WithCookieJar(tls_client.NewCookieJar()),
98 | }...)
99 |
100 | proxyUrl := os.Getenv("GO_CHATGPT_API_PROXY")
101 | if proxyUrl != "" {
102 | client.SetProxy(proxyUrl)
103 | }
104 |
105 | return client
106 | }
107 |
--------------------------------------------------------------------------------
/API/go-chatgpt-api/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "log"
5 | "net/http"
6 | "os"
7 | "strings"
8 |
9 | "github.com/gin-gonic/gin"
10 | "github.com/linweiyuan/go-chatgpt-api/api/chatgpt"
11 | "github.com/linweiyuan/go-chatgpt-api/api/platform"
12 | _ "github.com/linweiyuan/go-chatgpt-api/env"
13 | "github.com/linweiyuan/go-chatgpt-api/middleware"
14 | )
15 |
16 | func init() {
17 | gin.ForceConsoleColor()
18 | gin.SetMode(gin.ReleaseMode)
19 | }
20 |
21 | func main() {
22 | router := gin.Default()
23 | router.Use(middleware.CORSMiddleware())
24 | router.Use(middleware.CheckHeaderMiddleware())
25 |
26 | setupChatGPTAPIs(router)
27 |
28 | setupPlatformAPIs(router)
29 |
30 | router.NoRoute(handleFallbackRoute)
31 |
32 | port := os.Getenv("GO_CHATGPT_API_PORT")
33 | if port == "" {
34 | port = "8080"
35 | }
36 | err := router.Run(":" + port)
37 | if err != nil {
38 | log.Fatal("Failed to start server: " + err.Error())
39 | }
40 | }
41 |
42 | func setupChatGPTAPIs(router *gin.Engine) {
43 | chatgptGroup := router.Group("/chatgpt")
44 | {
45 | chatgptGroup.POST("/login", chatgpt.Login)
46 |
47 | conversationsGroup := chatgptGroup.Group("/conversations")
48 | {
49 | conversationsGroup.GET("", chatgpt.GetConversations)
50 |
51 | // PATCH is official method, POST is added for Java support
52 | conversationsGroup.PATCH("", chatgpt.ClearConversations)
53 | conversationsGroup.POST("", chatgpt.ClearConversations)
54 | }
55 |
56 | conversationGroup := chatgptGroup.Group("/conversation")
57 | {
58 | conversationGroup.POST("", chatgpt.CreateConversation)
59 | conversationGroup.POST("/gen_title/:id", chatgpt.GenerateTitle)
60 | conversationGroup.GET("/:id", chatgpt.GetConversation)
61 |
62 | // rename or delete conversation use a same API with different parameters
63 | conversationGroup.PATCH("/:id", chatgpt.UpdateConversation)
64 | conversationGroup.POST("/:id", chatgpt.UpdateConversation)
65 |
66 | conversationGroup.POST("/message_feedback", chatgpt.FeedbackMessage)
67 | }
68 |
69 | // misc
70 | chatgptGroup.GET("/models", chatgpt.GetModels)
71 | chatgptGroup.GET("/accounts/check", chatgpt.GetAccountCheck)
72 | }
73 | }
74 |
75 | func setupPlatformAPIs(router *gin.Engine) {
76 | platformGroup := router.Group("/platform")
77 | {
78 | platformGroup.POST("/login", platform.Login)
79 |
80 | apiGroup := platformGroup.Group("/v1")
81 | {
82 | apiGroup.GET("/models", platform.ListModels)
83 | apiGroup.GET("/models/:model", platform.RetrieveModel)
84 | apiGroup.POST("/completions", platform.CreateCompletions)
85 | apiGroup.POST("/chat/completions", platform.CreateChatCompletions)
86 | apiGroup.POST("/edits", platform.CreateEdit)
87 | apiGroup.POST("/images/generations", platform.CreateImage)
88 | apiGroup.POST("/embeddings", platform.CreateEmbeddings)
89 | apiGroup.GET("/files", platform.ListFiles)
90 | }
91 |
92 | dashboardGroup := platformGroup.Group("/dashboard")
93 | {
94 | billingGroup := dashboardGroup.Group("/billing")
95 | {
96 | billingGroup.GET("/credit_grants", platform.GetCreditGrants)
97 | billingGroup.GET("/subscription", platform.GetSubscription)
98 | }
99 |
100 | userGroup := dashboardGroup.Group("/user")
101 | {
102 | userGroup.GET("/api_keys", platform.GetApiKeys)
103 | }
104 | }
105 | }
106 | }
107 |
108 | func handleFallbackRoute(c *gin.Context) {
109 | path := c.Request.URL.Path
110 |
111 | if strings.HasPrefix(path, "/chatgpt") {
112 | trimmedPath := strings.TrimPrefix(path, "/chatgpt")
113 | c.Request.URL.Path = trimmedPath
114 | chatgpt.Fallback(c)
115 | } else {
116 | c.JSON(http.StatusNotFound, gin.H{"message": "Route not found"})
117 | }
118 | }
119 |
--------------------------------------------------------------------------------
/API/go-chatgpt-api/api/platform/typings.go:
--------------------------------------------------------------------------------
1 | package platform
2 |
3 | //goland:noinspection GoSnakeCaseUsage
4 | import tls_client "github.com/bogdanfinn/tls-client"
5 |
6 | type UserLogin struct {
7 | client tls_client.HttpClient
8 | }
9 |
10 | type GetAccessTokenRequest struct {
11 | ClientID string `json:"client_id"`
12 | GrantType string `json:"grant_type"`
13 | Code string `json:"code"`
14 | RedirectURI string `json:"redirect_uri"`
15 | }
16 |
17 | type GetAccessTokenResponse struct {
18 | AccessToken string `json:"access_token"`
19 | RefreshToken string `json:"refresh_token"`
20 | IDToken string `json:"id_token"`
21 | Scope string `json:"scope"`
22 | ExpiresIn int `json:"expires_in"`
23 | TokenType string `json:"token_type"`
24 | }
25 |
26 | //goland:noinspection SpellCheckingInspection
27 | type CreateCompletionsRequest struct {
28 | Model string `json:"model"`
29 | Prompt string `json:"prompt,omitempty"`
30 | Suffix string `json:"suffix,omitempty"`
31 | MaxTokens int `json:"max_tokens,omitempty"`
32 | Temperature int `json:"temperature,omitempty"`
33 | TopP int `json:"top_p,omitempty"`
34 | N int `json:"n,omitempty"`
35 | Stream bool `json:"stream,omitempty"`
36 | Logprobs int `json:"logprobs,omitempty"`
37 | Echo bool `json:"echo,omitempty"`
38 | Stop string `json:"stop,omitempty"`
39 | PresencePenalty int `json:"presence_penalty,omitempty"`
40 | FrequencyPenalty int `json:"frequency_penalty,omitempty"`
41 | BestOf int `json:"best_of,omitempty"`
42 | LogitBias map[string]interface{} `json:"logit_bias,omitempty"`
43 | User string `json:"user,omitempty"`
44 | }
45 |
46 | type ChatCompletionsRequest struct {
47 | Model string `json:"model"`
48 | Messages []ChatCompletionsMessage `json:"messages"`
49 | Temperature int `json:"temperature,omitempty"`
50 | TopP int `json:"top_p,omitempty"`
51 | N int `json:"n,omitempty"`
52 | Stream bool `json:"stream,omitempty"`
53 | Stop string `json:"stop,omitempty"`
54 | MaxTokens int `json:"max_tokens,omitempty"`
55 | PresencePenalty int `json:"presence_penalty,omitempty"`
56 | FrequencyPenalty int `json:"frequency_penalty,omitempty"`
57 | LogitBias map[string]interface{} `json:"logit_bias,omitempty"`
58 | User string `json:"user,omitempty"`
59 | }
60 |
61 | type ChatCompletionsMessage struct {
62 | Role string `json:"role"`
63 | Content string `json:"content"`
64 | Name string `json:"name,omitempty"`
65 | }
66 |
67 | type CreateEditRequest struct {
68 | Model string `json:"model"`
69 | Input string `json:"input"`
70 | Instruction string `json:"instruction"`
71 | N int `json:"n,omitempty"`
72 | Temperature int `json:"temperature,omitempty"`
73 | TopP int `json:"top_p,omitempty"`
74 | }
75 |
76 | type CreateImageRequest struct {
77 | Prompt string `json:"prompt"`
78 | N int `json:"n,omitempty"`
79 | Size string `json:"size,omitempty"`
80 | ResponseFormat string `json:"response_format,omitempty"`
81 | User string `json:"user,omitempty"`
82 | }
83 |
84 | type CreateEmbeddingsRequest struct {
85 | Model string `json:"model"`
86 | Input string `json:"input"`
87 | User string `json:"user,omitempty"`
88 | }
89 |
--------------------------------------------------------------------------------
/API/pandora/src/pandora/flask/static/_next/static/chunks/webpack-c9a868e8e0796ec6.js:
--------------------------------------------------------------------------------
1 | !function(){"use strict";var e,t,r,n,o,i,u,c={},a={};function d(e){var t=a[e];if(void 0!==t)return t.exports;var r=a[e]={id:e,loaded:!1,exports:{}},n=!0;try{c[e].call(r.exports,r,r.exports,d),n=!1}finally{n&&delete a[e]}return r.loaded=!0,r.exports}d.m=c,d.amdD=function(){throw Error("define cannot be used indirect")},d.amdO={},e=[],d.O=function(t,r,n,o){if(r){o=o||0;for(var i=e.length;i>0&&e[i-1][2]>o;i--)e[i]=e[i-1];e[i]=[r,n,o];return}for(var u=1/0,i=0;i=o&&Object.keys(d.O).every(function(e){return d.O[e](r[a])})?r.splice(a--,1):(c=!1,o {
2 | event.respondWith(handleRequest(event.request))
3 | })
4 | // More: https://www.blueskyxn.com/202408/7089.html
5 | async function handleRequest(request) {
6 | try {
7 | // 解析请求体
8 | const requestData = await request.json()
9 | const messages = requestData.messages || []
10 |
11 | // 构建要发送到 talkx API 的请求体
12 | const talkxPayload = {
13 | roleType: '0',
14 | productId: 0,
15 | sessionId: generateUUID(),
16 | messages: messages.map(msg => ({
17 | role: msg.role,
18 | content: msg.content
19 | }))
20 | }
21 |
22 | // 向 talkx API 发送请求
23 | const talkxResponse = await fetch('https://api.talkx.cn/gpt/chat', {
24 | method: 'POST',
25 | headers: {
26 | 'accept': '*/*',
27 | 'accept-language': 'zh-CN,zh;q=0.9',
28 | 'content-type': 'application/json;charset=utf-8',
29 | 'origin': 'https://web.talkx.cn',
30 | 'referer': 'https://web.talkx.cn/',
31 | 'sec-ch-ua': '"Google Chrome";v="123", "Not:A-Brand";v="8", "Chromium";v="123"',
32 | 'sec-ch-ua-mobile': '?0',
33 | 'sec-ch-ua-platform': '"Windows"',
34 | 'sec-fetch-dest': 'empty',
35 | 'sec-fetch-mode': 'cors',
36 | 'sec-fetch-site': 'same-site',
37 | 'talkx-token': '',
38 | 'user-agent': generateUserAgent(),
39 | },
40 | body: JSON.stringify(talkxPayload)
41 | })
42 |
43 | // 处理 talkx API 的响应
44 | const contentType = talkxResponse.headers.get('Content-Type') || ''
45 | let talkxData
46 |
47 | if (contentType.includes('application/json')) {
48 | talkxData = await talkxResponse.json()
49 | } else {
50 | const textResponse = await talkxResponse.text()
51 | talkxData = {
52 | choices: [
53 | {
54 | message: {
55 | role: 'assistant',
56 | content: textResponse
57 | }
58 | }
59 | ]
60 | }
61 | }
62 |
63 | // 构建 OpenAI 标准格式的响应
64 | const openaiResponse = {
65 | id: generateUUID(),
66 | object: 'chat.completion',
67 | created: Math.floor(Date.now() / 1000),
68 | model: 'gpt-3.5-turbo',
69 | choices: talkxData.choices || [],
70 | usage: {
71 | prompt_tokens: messages.length,
72 | completion_tokens: talkxData.choices.length,
73 | total_tokens: messages.length + talkxData.choices.length
74 | }
75 | }
76 |
77 | // 返回响应
78 | return new Response(JSON.stringify(openaiResponse), {
79 | headers: { 'Content-Type': 'application/json' }
80 | })
81 |
82 | } catch (error) {
83 | return new Response(JSON.stringify({ error: 'Internal Server Error' }), {
84 | status: 500,
85 | headers: { 'Content-Type': 'application/json' }
86 | })
87 | }
88 | }
89 |
90 | // 生成随机 UUID
91 | function generateUUID() {
92 | return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
93 | const r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8)
94 | return v.toString(16)
95 | })
96 | }
97 |
98 | // 生成随机 User-Agent
99 | function generateUserAgent() {
100 | const osList = [
101 | 'Windows NT 10.0; Win64; x64',
102 | 'Macintosh; Intel Mac OS X 10_15_7',
103 | 'X11; Linux x86_64'
104 | ]
105 |
106 | const browserList = [
107 | `Chrome/${getRandomInt(90, 122)}.${getRandomInt(0, 9)}.${getRandomInt(0, 99)}.${getRandomInt(0, 99)}`,
108 | `Firefox/${getRandomInt(90, 122)}.${getRandomInt(0, 9)}.${getRandomInt(0, 99)}`,
109 | `Safari/605.1.15`
110 | ]
111 |
112 | const os = osList[Math.floor(Math.random() * osList.length)]
113 | const browser = browserList[Math.floor(Math.random() * browserList.length)]
114 |
115 | return `Mozilla/5.0 (${os}) AppleWebKit/537.36 (KHTML, like Gecko) ${browser} Safari/537.36`
116 | }
117 |
118 | // 生成随机整数
119 | function getRandomInt(min, max) {
120 | min = Math.ceil(min)
121 | max = Math.floor(max)
122 | return Math.floor(Math.random() * (max - min + 1)) + min
123 | }
124 |
--------------------------------------------------------------------------------
/API/go-chatgpt-api/api/platform/access_token.go:
--------------------------------------------------------------------------------
1 | package platform
2 |
3 | import (
4 | "encoding/json"
5 | "errors"
6 | "fmt"
7 | "io"
8 | "net/url"
9 | "strings"
10 |
11 | "github.com/linweiyuan/go-chatgpt-api/api"
12 |
13 | http "github.com/bogdanfinn/fhttp"
14 | )
15 |
16 | //goland:noinspection GoUnhandledErrorResult,GoErrorStringFormat,GoUnusedParameter
17 | func (userLogin *UserLogin) GetAuthorizedUrl(csrfToken string) (string, int, error) {
18 | urlParams := url.Values{
19 | "client_id": {platformAuthClientID},
20 | "audience": {platformAuthAudience},
21 | "redirect_uri": {platformAuthRedirectURL},
22 | "scope": {platformAuthScope},
23 | "response_type": {platformAuthResponseType},
24 | }
25 | req, _ := http.NewRequest(http.MethodGet, platformAuth0Url+urlParams.Encode(), nil)
26 | req.Header.Set("Content-Type", api.ContentType)
27 | req.Header.Set("User-Agent", api.UserAgent)
28 | resp, err := userLogin.client.Do(req)
29 | if err != nil {
30 | return "", http.StatusInternalServerError, err
31 | }
32 |
33 | defer resp.Body.Close()
34 | if resp.StatusCode != http.StatusOK {
35 | return "", resp.StatusCode, errors.New(api.GetAuthorizedUrlErrorMessage)
36 | }
37 |
38 | return resp.Request.URL.String(), http.StatusOK, nil
39 | }
40 |
41 | func (userLogin *UserLogin) GetState(authorizedUrl string) (string, int, error) {
42 | split := strings.Split(authorizedUrl, "=")
43 | return split[1], http.StatusOK, nil
44 | }
45 |
46 | //goland:noinspection GoUnhandledErrorResult,GoErrorStringFormat
47 | func (userLogin *UserLogin) CheckUsername(state string, username string) (int, error) {
48 | formParams := fmt.Sprintf(
49 | "state=%s&username=%s&js-available=true&webauthn-available=true&is-brave=false&webauthn-platform-available=false&action=default",
50 | state,
51 | username,
52 | )
53 | req, err := http.NewRequest(http.MethodPost, api.LoginUsernameUrl+state, strings.NewReader(formParams))
54 | req.Header.Set("Content-Type", api.ContentType)
55 | req.Header.Set("User-Agent", api.UserAgent)
56 | resp, err := userLogin.client.Do(req)
57 | if err != nil {
58 | return http.StatusInternalServerError, err
59 | }
60 |
61 | defer resp.Body.Close()
62 | if resp.StatusCode != http.StatusOK {
63 | return resp.StatusCode, errors.New(api.EmailInvalidErrorMessage)
64 | }
65 |
66 | return http.StatusOK, nil
67 | }
68 |
69 | //goland:noinspection GoUnhandledErrorResult,GoErrorStringFormat
70 | func (userLogin *UserLogin) CheckPassword(state string, username string, password string) (string, int, error) {
71 | formParams := fmt.Sprintf(
72 | "state=%s&username=%s&password=%s&action=default",
73 | state,
74 | username,
75 | password,
76 | )
77 | req, err := http.NewRequest(http.MethodPost, api.LoginPasswordUrl+state, strings.NewReader(formParams))
78 | req.Header.Set("Content-Type", api.ContentType)
79 | req.Header.Set("User-Agent", api.UserAgent)
80 | resp, err := userLogin.client.Do(req)
81 | if err != nil {
82 | return "", http.StatusInternalServerError, err
83 | }
84 |
85 | defer resp.Body.Close()
86 | if resp.StatusCode != http.StatusOK {
87 | return "", resp.StatusCode, errors.New(api.EmailOrPasswordInvalidErrorMessage)
88 | }
89 |
90 | return resp.Request.URL.Query().Get("code"), http.StatusOK, nil
91 | }
92 |
93 | //goland:noinspection GoUnhandledErrorResult,GoErrorStringFormat
94 | func (userLogin *UserLogin) GetAccessToken(code string) (string, int, error) {
95 | jsonBytes, _ := json.Marshal(GetAccessTokenRequest{
96 | ClientID: platformAuthClientID,
97 | Code: code,
98 | GrantType: platformAuthGrantType,
99 | RedirectURI: platformAuthRedirectURL,
100 | })
101 | req, err := http.NewRequest(http.MethodPost, getTokenUrl, strings.NewReader(string(jsonBytes)))
102 | req.Header.Set("Content-Type", "application/json")
103 | req.Header.Set("User-Agent", api.UserAgent)
104 | resp, err := userLogin.client.Do(req)
105 | if err != nil {
106 | return "", http.StatusInternalServerError, err
107 | }
108 |
109 | defer resp.Body.Close()
110 | if resp.StatusCode != http.StatusOK {
111 | return "", resp.StatusCode, errors.New(api.GetAccessTokenErrorMessage)
112 | }
113 |
114 | data, _ := io.ReadAll(resp.Body)
115 | return string(data), http.StatusOK, nil
116 | }
117 |
--------------------------------------------------------------------------------
/API/cerebras2api/cerebras2api.py:
--------------------------------------------------------------------------------
1 | import random
2 | import json
3 | import aiohttp
4 | import asyncio
5 | from aiohttp import web
6 | from datetime import datetime
7 |
8 | # More: https://www.blueskyxn.com/202408/7089.html
9 | # llama3.1-8b、llama3.1-70b
10 | # 调试信息开关
11 | DEBUG_MODE = False # 设置为 True 可以打印详细的调试信息
12 |
13 | # 定义固定的模型信息
14 | DEFAULT_MODEL = "llama3.1-8b"
15 | ALTERNATE_MODEL = "llama3.1-70b"
16 | FIXED_URL = "https://api.cerebras.ai/v1/chat/completions"
17 | FIXED_TEMPERATURE = 0.2
18 | FIXED_TOP_P = 1
19 | FIXED_MAX_TOKENS = 4096
20 |
21 | # 记录基本信息的日志函数
22 | def log_basic_info(message):
23 | timestamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
24 | print(f"[{timestamp}] {message}")
25 |
26 | # 异步发送请求并打印调试信息
27 | async def send_request(auth_tokens, data):
28 | try:
29 | headers = {
30 | "accept": "application/json",
31 | "authorization": f"Bearer {auth_tokens[0]}",
32 | "content-type": "application/json"
33 | }
34 |
35 | # 检查传入的数据是否指定了 llama3.1-70b 模型
36 | requested_model = data.get("model", DEFAULT_MODEL)
37 | model_to_use = DEFAULT_MODEL
38 | if requested_model == ALTERNATE_MODEL:
39 | model_to_use = ALTERNATE_MODEL
40 |
41 | # 记录收到的模型请求以及实际使用的模型
42 | log_basic_info(f"Requested model: {requested_model}, Using model: {model_to_use}")
43 |
44 | # 构造请求体
45 | payload = {
46 | "messages": data.get("messages", []),
47 | "model": model_to_use,
48 | "temperature": FIXED_TEMPERATURE,
49 | "top_p": FIXED_TOP_P,
50 | "max_tokens": FIXED_MAX_TOKENS
51 | }
52 |
53 | if DEBUG_MODE:
54 | print("Request Payload:", json.dumps(payload, indent=4))
55 | print("Request Headers:", headers)
56 |
57 | async with aiohttp.ClientSession() as session:
58 | async with session.post(FIXED_URL, headers=headers, json=payload) as resp:
59 | response_text = await resp.text()
60 |
61 | # 尝试解析响应体
62 | response_json = json.loads(response_text)
63 |
64 | # 提取total_time和total_tokens信息
65 | total_tokens = response_json.get('usage', {}).get('total_tokens', 'N/A')
66 | total_time = response_json.get('time_info', {}).get('total_time', 'N/A')
67 |
68 | # 打印所有关键信息到同一行
69 | log_basic_info(f"Path: {FIXED_URL}, Status Code: {resp.status}, Total Tokens Used: {total_tokens}, Total Time: {total_time:.3f} seconds")
70 |
71 | return response_text
72 |
73 | except Exception as e:
74 | log_basic_info(f"Exception occurred: {str(e)}")
75 |
76 | # 主函数
77 | async def handle_request(request):
78 | try:
79 | # 获取请求数据
80 | request_data = await request.json()
81 | headers = dict(request.headers)
82 |
83 | # 检查并处理 Authorization 头
84 | authorization_header = headers.get('Authorization', '')
85 | auth_tokens = [auth.strip() for auth in authorization_header.replace('Bearer ', '').split(',')]
86 |
87 | if not auth_tokens:
88 | return web.json_response({"error": "Missing Authorization token"}, status=400)
89 |
90 | # 如果有多个 auth token,随机选择一个
91 | auth_token = random.choice(auth_tokens)
92 | headers['Authorization'] = f"Bearer {auth_token}"
93 |
94 | # 打印传入请求的基本信息
95 | log_basic_info(f"Received request for path: {request.path}")
96 |
97 | if DEBUG_MODE:
98 | print("Received Request Data:", json.dumps(request_data, indent=4))
99 | print("Received Headers:", headers)
100 |
101 | # 发送请求并获取响应
102 | response_text = await send_request(auth_tokens, request_data)
103 |
104 | # 返回最终的响应
105 | return web.json_response(json.loads(response_text))
106 |
107 | except Exception as e:
108 | log_basic_info(f"Exception occurred in handling request: {str(e)}")
109 | return web.json_response({"error": str(e)}, status=500)
110 |
111 | # 设置路由
112 | app = web.Application()
113 | app.router.add_post('/v1/chat/completions', handle_request)
114 |
115 | # 运行服务器,监听5804端口
116 | if __name__ == '__main__':
117 | web.run_app(app, port=5804)
118 |
--------------------------------------------------------------------------------
/API/pandora/README.md:
--------------------------------------------------------------------------------
1 | # Pandora
2 |
3 | 潘多拉 (Pandora),一个让你呼吸顺畅的 ChatGPT。
4 |
5 | 潘多拉实现了网页版 ChatGPT 的主要操作。后端优化,绕过 Cloudflare,速度喜人。
6 |
7 |
8 |
9 | 
10 | [](https://github.com/pengzhile/pandora/issues)
11 | [](https://github.com/pengzhile/pandora/commits/master)
12 | [](https://pypi.python.org/pypi/pandora-chatgpt)
13 | [](https://pypi.python.org/pypi/pandora-chatgpt)
14 | [](https://github.com/pengzhile/pandora/actions/workflows/python-publish.yml)
15 | [](https://github.com/pengzhile/pandora/actions/workflows/docker-publish.yml)
16 | [](https://discord.gg/QBkd9JAaWa)
17 |
18 | ## 体验地址
19 | * 点击 https://chat.zhile.io
20 | * 最新拿 `Access Token` 的技术原理,我记录在[这里](https://zhile.io/2023/05/19/how-to-get-chatgpt-access-token-via-pkce.html)了。
21 | * 可以访问 [这里](http://ai.fakeopen.com/auth) 拿 `Access Token`
22 | * 也可以官方登录,然后访问 [这里](http://chat.openai.com/api/auth/session) 拿 `Access Token`
23 | * `Access Token` 有效期 `14` 天,期间访问**不需要梯子**。这意味着你在手机上也可随意使用。
24 | * 这个页面上还包含一个共享账号的链接,**没有账号**的可以点进去体验一下。
25 |
26 | ## ChatGPT使用时可能会遇到:
27 |
28 | ### 1. Please stand by, while we are checking your browser...
29 | ### 动不动来一下,有时候还不动或者出人机验证。痛!
30 | 
31 |
32 | ### 2. Access denied. Sorry, you have been blocked
33 | ### 经典问题,只能到处找可用VPN,费时费力,更费钱。移动端访问更难。痛!
34 | 
35 |
36 | ### 3. ChatGPT is at capacity right now
37 | ### 系统负载高,白嫖用户不给用。痛!
38 | 
39 |
40 | ### 4. This content may violate our content policy .
41 | ### 道德审查,多触发几次可能就封号了。痛!!!
42 | 
43 |
44 | ### 5. Something went wrong.
45 | ### 吃着火锅唱着歌,突然就出故障了。痛!
46 | 
47 |
48 | ### 6. 手机和电脑的模型不通用,顾这个就顾不到那个,痛!
49 | 
50 |
51 | ### 7. 蹦字慢吞吞,卡顿不流畅,不知道的甚至想换电脑。痛!
52 | ### 8. 想把 `ChatGPT` 接到其他系统,结果只能接个差强人意的 `gpt-3.5-turbo`。痛!
53 |
54 | ### _一次看完上面的噩梦,血压上来了,拳头硬了!太痛了!!!以上痛点,`Pandora` 一次全部解决。_
55 |
56 | ## 界面截图
57 |
58 |
59 |
60 |
61 |
62 | 
63 | 
64 |
65 |
66 |
67 | 
68 | 
69 | 
70 | 
71 | 
72 | 
73 |
74 |
75 |
76 | ## 如何搭建运行
77 |
78 | * 访问 [doc/wiki.md](https://github.com/pengzhile/pandora/blob/master/doc/wiki.md) 获得详细指导。
79 |
80 | ## 其他说明
81 |
82 | * `开源项目可以魔改,但请保留原作者信息。确需去除,请联系作者,以免失去技术支持。`
83 | * 项目是站在其他巨人的肩膀上,感谢!
84 | * 报错、BUG之类的提出`Issue`,我会修复。
85 | * 因为之后`ChatGPT`的API变动,我可能不会跟进修复。
86 | * 喜欢的可以给颗星,都是老朋友了。
87 | * 不影响`PHP是世界上最好的编程语言!`
88 |
89 | ## 贡献者们
90 |
91 | > 感谢所有让这个项目变得更好的贡献者们!
92 |
93 | [](https://github.com/pengzhile/pandora/graphs/contributors)
94 |
95 | ## Star历史
96 |
97 | 
98 |
--------------------------------------------------------------------------------
/API/talkx2api/talkx2api.py:
--------------------------------------------------------------------------------
1 | from flask import Flask, request, jsonify
2 | import uuid
3 | import requests
4 | import random
5 | import time
6 |
7 | # More: https://www.blueskyxn.com/202408/7089.html
8 |
9 | app = Flask(__name__)
10 |
11 | def generate_user_agent():
12 | os_list = [
13 | 'Windows NT 10.0; Win64; x64',
14 | 'Macintosh; Intel Mac OS X 10_15_7',
15 | 'X11; Linux x86_64'
16 | ]
17 |
18 | browser_list = [
19 | ('Chrome', 'AppleWebKit/537.36 (KHTML, like Gecko) Chrome/{}.{}.{}.{} Safari/537.36'),
20 | ('Firefox', 'Gecko/20100101 Firefox/{}.{}.{}'),
21 | ('Safari', 'AppleWebKit/605.1.15 (KHTML, like Gecko) Version/{}.{}.{} Safari/605.1.15'),
22 | ('Edge', 'Edge/{}.{}.{}.{}')
23 | ]
24 |
25 | os_choice = random.choice(os_list)
26 | browser_name, browser_format = random.choice(browser_list)
27 |
28 | major_version = random.randint(90, 122)
29 | minor_version = random.randint(0, 9)
30 | build_version = random.randint(0, 99)
31 | patch_version = random.randint(0, 99)
32 |
33 | if browser_name == 'Chrome':
34 | user_agent = f'Mozilla/5.0 ({os_choice}) {browser_format.format(major_version, minor_version, build_version, patch_version)}'
35 | elif browser_name == 'Firefox':
36 | user_agent = f'Mozilla/5.0 ({os_choice}; rv:{major_version}.0) {browser_format.format(major_version, minor_version, build_version)}'
37 | elif browser_name == 'Safari':
38 | user_agent = f'Mozilla/5.0 ({os_choice}) {browser_format.format(major_version, minor_version, build_version)}'
39 | else:
40 | user_agent = f'Mozilla/5.0 ({os_choice}) {browser_format.format(major_version, minor_version, build_version, patch_version)}'
41 | return user_agent
42 |
43 | def get_header():
44 | headers = {
45 | 'accept': '*/*',
46 | 'accept-language': 'zh-CN,zh;q=0.9',
47 | 'content-type': 'application/json;charset=utf-8',
48 | 'origin': 'https://web.talkx.cn',
49 | 'referer': 'https://web.talkx.cn/',
50 | 'sec-ch-ua': '"Google Chrome";v="123", "Not:A-Brand";v="8", "Chromium";v="123"',
51 | 'sec-ch-ua-mobile': '?0',
52 | 'sec-ch-ua-platform': '"Windows"',
53 | 'sec-fetch-dest': 'empty',
54 | 'sec-fetch-mode': 'cors',
55 | 'sec-fetch-site': 'same-site',
56 | 'talkx-token': '', # 在这里填入有效的 token
57 | 'Accept-Charset': 'utf-8',
58 | 'user-agent': generate_user_agent(),
59 | }
60 | return headers
61 |
62 | def forward_request_to_talkx(messages):
63 | json_data = {
64 | 'roleType': '0',
65 | 'productId': 0,
66 | 'sessionId': str(uuid.uuid4()),
67 | 'messages': messages,
68 | }
69 |
70 | response = requests.post('https://api.talkx.cn/gpt/chat', headers=get_header(), json=json_data)
71 | response.encoding = 'utf-8'
72 |
73 | content_type = response.headers.get('Content-Type', '')
74 |
75 | if response.status_code == 200:
76 | if 'application/json' in content_type:
77 | return response.json()
78 | else:
79 | return {"choices": [{"message": {"role": "assistant", "content": response.text}}]}
80 | else:
81 | return {"error": "Failed to fetch response from talkx API", "status_code": response.status_code, "content": response.text}
82 |
83 | @app.route("/v1/chat/completions", methods=["POST"])
84 | def chat_completions():
85 | openai_request = request.json
86 | messages = [{"role": message["role"], "content": message["content"]} for message in openai_request.get("messages", [])]
87 |
88 | talkx_response = forward_request_to_talkx(messages)
89 |
90 | openai_response = {
91 | "id": str(uuid.uuid4()),
92 | "object": "chat.completion",
93 | "created": int(time.time()),
94 | "model": "gpt-3.5-turbo",
95 | "choices": talkx_response.get("choices", []),
96 | "usage": {
97 | "prompt_tokens": len(openai_request.get("messages", [])),
98 | "completion_tokens": len(talkx_response.get("choices", [])),
99 | "total_tokens": len(openai_request.get("messages", [])) + len(talkx_response.get("choices", []))
100 | }
101 | }
102 |
103 | return jsonify(openai_response)
104 |
105 | if __name__ == "__main__":
106 | app.run(host="0.0.0.0", port=5000)
107 |
--------------------------------------------------------------------------------
/API/pandora/src/pandora/migrations/models.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | from datetime import datetime as dt
4 |
5 | from sqlalchemy import func, Column, Text, Integer
6 | from sqlalchemy.orm import DeclarativeBase
7 |
8 | from ..migrations.database import session
9 |
10 |
11 | class Base(DeclarativeBase):
12 | pass
13 |
14 |
15 | class ConversationOfficial(Base):
16 | __tablename__ = 'conversation_official'
17 |
18 | conversation_id = Column(Text, primary_key=True, autoincrement=False)
19 | title = Column(Text, nullable=False)
20 | create_time = Column(Integer, nullable=False)
21 |
22 | @staticmethod
23 | def get_list(offset, limit):
24 | total = session.query(func.count(ConversationOfficial.conversation_id)).scalar()
25 | return total, session.query(ConversationOfficial).order_by(ConversationOfficial.create_time.desc()).limit(
26 | limit).offset(offset).all()
27 |
28 | @staticmethod
29 | def get(conversation_id):
30 | return session.query(ConversationOfficial).get(conversation_id)
31 |
32 | def save(self):
33 | session.commit()
34 | return self
35 |
36 | def new(self):
37 | session.add(self)
38 | session.commit()
39 |
40 | return self
41 |
42 | @staticmethod
43 | def delete(conversation_id):
44 | session.query(ConversationOfficial).filter(ConversationOfficial.conversation_id == conversation_id).delete()
45 | session.commit()
46 |
47 | @staticmethod
48 | def clear():
49 | session.query(ConversationOfficial).delete()
50 | session.commit()
51 |
52 | @staticmethod
53 | def new_conversation(conversation_id, title=None):
54 | conv = ConversationOfficial.get(conversation_id)
55 |
56 | if not conv:
57 | conv = ConversationOfficial()
58 | conv.conversation_id = conversation_id
59 | conv.title = title or 'New chat'
60 | conv.create_time = dt.now().timestamp()
61 | conv.new()
62 | else:
63 | conv.title = title or 'New chat'
64 | conv.save()
65 |
66 | @staticmethod
67 | def wrap_conversation_list(offset, limit):
68 | total, items = ConversationOfficial.get_list(offset, limit)
69 |
70 | stripped = []
71 | for item in items:
72 | stripped.append({
73 | 'id': item.conversation_id,
74 | 'title': item.title,
75 | 'create_time': dt.utcfromtimestamp(item.create_time).isoformat(),
76 | })
77 |
78 | return {'items': stripped, 'total': total, 'limit': limit, 'offset': offset}
79 |
80 |
81 | class ConversationInfo(Base):
82 | __tablename__ = 'conversation_info'
83 |
84 | conversation_id = Column(Text, primary_key=True, autoincrement=False)
85 | title = Column(Text, nullable=False)
86 | create_time = Column(Integer, nullable=False)
87 | current_node = Column(Text, nullable=True)
88 |
89 | @staticmethod
90 | def get_list(offset, limit):
91 | total = session.query(func.count(ConversationInfo.conversation_id)).scalar()
92 | return total, session.query(ConversationInfo).order_by(ConversationInfo.create_time.desc()).limit(
93 | limit).offset(offset).all()
94 |
95 | @staticmethod
96 | def get(conversation_id):
97 | return session.query(ConversationInfo).get(conversation_id)
98 |
99 | def new(self):
100 | session.add(self)
101 | session.commit()
102 |
103 | return self
104 |
105 | @staticmethod
106 | def delete(conversation_id):
107 | session.query(ConversationInfo).filter(ConversationInfo.conversation_id == conversation_id).delete()
108 | session.commit()
109 |
110 | @staticmethod
111 | def clear():
112 | session.query(ConversationInfo).delete()
113 | session.commit()
114 |
115 |
116 | class PromptInfo(Base):
117 | __tablename__ = 'prompt_info'
118 |
119 | prompt_id = Column(Text, primary_key=True, autoincrement=False)
120 | conversation_id = Column(Text, primary_key=True, autoincrement=False)
121 | model = Column(Text, nullable=True)
122 | parent_id = Column(Text, nullable=True)
123 | role = Column(Text, nullable=True)
124 | content = Column(Text, nullable=True)
125 | create_time = Column(Integer, nullable=False)
126 |
127 | @staticmethod
128 | def list_by_conversation_id(conversation_id):
129 | return session.query(PromptInfo).filter(PromptInfo.conversation_id == conversation_id).all()
130 |
131 | def new(self):
132 | session.add(self)
133 | session.commit()
134 |
135 | return self
136 |
137 | @staticmethod
138 | def clear():
139 | session.query(PromptInfo).delete()
140 | session.commit()
141 |
--------------------------------------------------------------------------------
/API/ChatGPT-to-API/tools/authenticator/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "bufio"
5 | "fmt"
6 | "os"
7 | "os/exec"
8 | "strings"
9 | "time"
10 |
11 | "authenticator/auth"
12 | )
13 |
14 | type Account struct {
15 | Email string `json:"username"`
16 | Password string `json:"password"`
17 | }
18 | type Proxy struct {
19 | IP string `json:"ip"`
20 | Port string `json:"port"`
21 | User string `json:"user"`
22 | Pass string `json:"pass"`
23 | }
24 |
25 | func (p Proxy) Socks5URL() string {
26 | // Returns proxy URL (socks5)
27 | if p.User == "" && p.Pass == "" {
28 | return fmt.Sprintf("socks5://%s:%s", p.IP, p.Port)
29 | }
30 | return fmt.Sprintf("socks5://%s:%s@%s:%s", p.User, p.Pass, p.IP, p.Port)
31 | }
32 |
33 | // Read accounts.txt and create a list of accounts
34 | func readAccounts() []Account {
35 | accounts := []Account{}
36 | // Read accounts.txt and create a list of accounts
37 | file, err := os.Open("accounts.txt")
38 | if err != nil {
39 | panic(err)
40 | }
41 | defer file.Close()
42 | // Loop through each line in the file
43 | scanner := bufio.NewScanner(file)
44 | for scanner.Scan() {
45 | // Split by :
46 | line := strings.Split(scanner.Text(), ":")
47 | // Create an account
48 | account := Account{
49 | Email: line[0],
50 | Password: line[1],
51 | }
52 | // Append to accounts
53 | accounts = append(accounts, account)
54 | }
55 | return accounts
56 | }
57 |
58 | // Read proxies from proxies.txt and create a list of proxies
59 | func readProxies() []Proxy {
60 | proxies := []Proxy{}
61 | // Read proxies.txt and create a list of proxies
62 | file, err := os.Open("proxies.txt")
63 | if err != nil {
64 | return []Proxy{}
65 | }
66 | defer file.Close()
67 | // Loop through each line in the file
68 | scanner := bufio.NewScanner(file)
69 | for scanner.Scan() {
70 | // Split by :
71 | lines := strings.Split(scanner.Text(), ":")
72 | var proxy Proxy
73 | if len(lines) == 4 {
74 | // Create a proxy
75 | proxy = Proxy{
76 | IP: lines[0],
77 | Port: lines[1],
78 | User: lines[2],
79 | Pass: lines[3],
80 | }
81 | } else if len(lines) == 2 {
82 | proxy = Proxy{
83 | IP: lines[0],
84 | Port: lines[1],
85 | }
86 | } else {
87 | continue
88 | }
89 | // Append to proxies
90 | proxies = append(proxies, proxy)
91 | }
92 | return proxies
93 | }
94 |
95 | func main() {
96 | // Read accounts and proxies
97 | accounts := readAccounts()
98 | proxies := readProxies()
99 |
100 | // Loop through each account
101 | for _, account := range accounts {
102 | if os.Getenv("CF_PROXY") != "" {
103 | // exec warp-cli disconnect and connect
104 | exec.Command("warp-cli", "disconnect").Run()
105 | exec.Command("warp-cli", "connect").Run()
106 | time.Sleep(5 * time.Second)
107 | }
108 | println(account.Email)
109 | println(account.Password)
110 | var proxy_url string
111 | if len(proxies) == 0 {
112 | if os.Getenv("http_proxy") != "" {
113 | proxy_url = os.Getenv("http_proxy")
114 | }
115 | } else {
116 | proxy_url = proxies[0].Socks5URL()
117 | // Push used proxy to the back of the list
118 | proxies = append(proxies[1:], proxies[0])
119 | }
120 | println(proxy_url)
121 | authenticator := auth.NewAuthenticator(account.Email, account.Password, proxy_url)
122 | err := authenticator.Begin()
123 | if err.Error != nil {
124 | // println("Error: " + err.Details)
125 | println("Location: " + err.Location)
126 | println("Status code: " + fmt.Sprint(err.StatusCode))
127 | println("Details: " + err.Details)
128 | println("Embedded error: " + err.Error.Error())
129 | return
130 | }
131 | access_token, err := authenticator.GetAccessToken()
132 | if err.Error != nil {
133 | // println("Error: " + err.Details)
134 | println("Location: " + err.Location)
135 | println("Status code: " + fmt.Sprint(err.StatusCode))
136 | println("Details: " + err.Details)
137 | println("Embedded error: " + err.Error.Error())
138 | return
139 | }
140 | // Append access token to access_tokens.txt
141 | f, go_err := os.OpenFile("access_tokens.txt", os.O_APPEND|os.O_WRONLY, 0600)
142 | if go_err != nil {
143 | continue
144 | }
145 | defer f.Close()
146 | if _, go_err = f.WriteString(access_token + "\n"); go_err != nil {
147 | continue
148 | }
149 | // Write authenticated account to authenticated_accounts.txt
150 | f, go_err = os.OpenFile("authenticated_accounts.txt", os.O_APPEND|os.O_WRONLY, 0600)
151 | if go_err != nil {
152 | continue
153 | }
154 | defer f.Close()
155 | if _, go_err = f.WriteString(account.Email + ":" + account.Password + "\n"); go_err != nil {
156 | continue
157 | }
158 | // Remove accounts.txt
159 | os.Remove("accounts.txt")
160 | // Create accounts.txt
161 | f, go_err = os.Create("accounts.txt")
162 | if go_err != nil {
163 | continue
164 | }
165 | defer f.Close()
166 | // Remove account from accounts
167 | accounts = accounts[1:]
168 | // Write unauthenticated accounts to accounts.txt
169 | for _, acc := range accounts {
170 | // Check if account is authenticated
171 | if acc.Email == account.Email {
172 | continue
173 | }
174 | if _, go_err = f.WriteString(acc.Email + ":" + acc.Password + "\n"); go_err != nil {
175 | continue
176 | }
177 | }
178 |
179 | }
180 | }
181 |
--------------------------------------------------------------------------------
/API/go-chatgpt-api/api/chatgpt/health_check.go:
--------------------------------------------------------------------------------
1 | package chatgpt
2 |
3 | import (
4 | "encoding/json"
5 | "os"
6 | "strings"
7 | "time"
8 |
9 | "github.com/PuerkitoBio/goquery"
10 | "github.com/linweiyuan/go-chatgpt-api/api"
11 | "github.com/linweiyuan/go-chatgpt-api/util/logger"
12 |
13 | http "github.com/bogdanfinn/fhttp"
14 | )
15 |
16 | const (
17 | healthCheckUrl = "https://chat.openai.com/backend-api/accounts/check"
18 | readyHint = "Service go-chatgpt-api is ready."
19 | defaultCookiesApiUrl = "https://chatgpt.linweiyuan.com/cookies"
20 | errorHint403 = "If you still hit 403, do not raise new issue (will be closed directly without comment), change to a new clean IP or use legacy version first."
21 | errorHintBlock = "You have been blocked to use cookies api because your IP is detected by Cloudflare WAF."
22 | cookieName = "__cf_bm"
23 | )
24 |
25 | //goland:noinspection GoSnakeCaseUsage
26 | var cfbm *Cookie
27 | var firstTime = true
28 |
29 | //goland:noinspection GoUnhandledErrorResult
30 | func init() {
31 | proxyUrl := os.Getenv("GO_CHATGPT_API_PROXY")
32 | if proxyUrl != "" {
33 | logger.Info("GO_CHATGPT_API_PROXY: " + proxyUrl)
34 | api.Client.SetProxy(proxyUrl)
35 |
36 | for {
37 | resp, err := healthCheck()
38 | if err != nil {
39 | // wait for proxy to be ready
40 | time.Sleep(time.Second)
41 | continue
42 | }
43 |
44 | checkHealthCheckStatus(resp)
45 | break
46 | }
47 | } else {
48 | resp, err := healthCheck()
49 | if err != nil {
50 | logger.Error("Health check failed: " + err.Error())
51 | os.Exit(1)
52 | }
53 |
54 | checkHealthCheckStatus(resp)
55 | }
56 | }
57 |
58 | func healthCheck() (resp *http.Response, err error) {
59 | req, _ := http.NewRequest(http.MethodGet, healthCheckUrl, nil)
60 | req.Header.Set("User-Agent", api.UserAgent)
61 | if !firstTime {
62 | injectCookies(req)
63 | }
64 | resp, err = api.Client.Do(req)
65 | return
66 | }
67 |
68 | //goland:noinspection GoUnhandledErrorResult
69 | func checkHealthCheckStatus(resp *http.Response) {
70 | defer resp.Body.Close()
71 | if resp != nil && resp.StatusCode == http.StatusUnauthorized {
72 | logger.Info(readyHint)
73 | firstTime = false
74 | } else {
75 | doc, _ := goquery.NewDocumentFromReader(resp.Body)
76 | alert := doc.Find(".message").Text()
77 | if alert != "" {
78 | logger.Error(strings.TrimSpace(alert) + " by OpenAI.")
79 | time.Sleep(time.Hour)
80 | os.Exit(1)
81 | } else {
82 | getCookies()
83 | }
84 | }
85 | }
86 |
87 | func getCookiesApiUrl() string {
88 | cookiesApiUrl := os.Getenv("GO_CHATGPT_API_COOKIES_API_URL")
89 | if cookiesApiUrl == "" {
90 | cookiesApiUrl = defaultCookiesApiUrl
91 | }
92 | return cookiesApiUrl
93 | }
94 |
95 | //goland:noinspection GoUnhandledErrorResult
96 | func getCookies() {
97 | req, _ := http.NewRequest(http.MethodGet, getCookiesApiUrl(), nil)
98 | resp, err := api.Client.Do(req)
99 | if err != nil || resp.StatusCode != http.StatusOK {
100 | if resp != nil && resp.StatusCode == http.StatusForbidden {
101 | logger.Error(errorHintBlock)
102 | time.Sleep(time.Hour)
103 | os.Exit(1)
104 | }
105 |
106 | logger.Error("Failed to get cookies, please try again later.")
107 | return
108 | }
109 |
110 | defer resp.Body.Close()
111 | var cookies []*Cookie
112 | err = json.NewDecoder(resp.Body).Decode(&cookies)
113 | if err != nil {
114 | logger.Error("Failed to parse cookies, please retry later.")
115 | return
116 | }
117 |
118 | for _, cookie := range cookies {
119 | if cookie.Name == cookieName {
120 | cfbm = cookie
121 | break
122 | }
123 | }
124 |
125 | if firstTime {
126 | logger.Info(readyHint)
127 | logger.Error(errorHint403)
128 | firstTime = false
129 |
130 | go func() {
131 | keepCheckingCookies()
132 | }()
133 | }
134 | }
135 |
136 | func injectCookies(req *http.Request) {
137 | if cfbm != nil {
138 | req.Header.Set("Cookie", cookieName+"="+cfbm.Value)
139 | }
140 | }
141 |
142 | //goland:noinspection GoUnhandledErrorResult
143 | func keepCheckingCookies() {
144 | for {
145 | now := time.Now()
146 | refreshTime := now.Add(time.Minute * 5) // // refresh cookie 5 minutes before it is expired
147 | if refreshTime.Minute() == time.Unix(cfbm.Expiry, 0).Minute() {
148 | // use old cookie to get back new cookie
149 | resp, err := healthCheck()
150 | if err == nil && resp.StatusCode == http.StatusUnauthorized {
151 | oldValue := cfbm.Value
152 | for _, cookie := range resp.Cookies() {
153 | if cookie.Name == cookieName {
154 | cfbm = &Cookie{
155 | Name: cookie.Name,
156 | Value: cookie.Value,
157 | }
158 | break
159 | }
160 | }
161 |
162 | newValue := cfbm.Value
163 | if oldValue == newValue {
164 | go func() {
165 | for {
166 | time.Sleep(time.Minute * 20)
167 | getCookies()
168 | }
169 | }()
170 | } else {
171 | // if new cfbm is set, go-chatgpt-api itself will take over the task of refreshing cookie from external cookies api
172 | go func() {
173 | for {
174 | time.Sleep(time.Minute * 25)
175 | resp, err := healthCheck()
176 | if err != nil {
177 | logger.Error("Health check failed: " + err.Error())
178 | os.Exit(1)
179 | }
180 |
181 | for _, cookie := range resp.Cookies() {
182 | if cookie.Name == cookieName {
183 | cfbm = &Cookie{
184 | Name: cookie.Name,
185 | Value: cookie.Value,
186 | }
187 | }
188 | }
189 | resp.Body.Close()
190 | }
191 | }()
192 | }
193 | break
194 | }
195 | }
196 |
197 | time.Sleep(time.Minute)
198 | }
199 | }
200 |
--------------------------------------------------------------------------------
/API/pandora/doc/wiki_en.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
Pandora
5 |
6 | Pandora, talking with ChatGPT in command lines, and with more surprises.
7 |
8 | Wiki in 中文 »
9 |
10 |
11 | Demo View
12 | ·
13 | Bug Report
14 | ·
15 | Feature Request
16 |
17 |
18 |
19 | ## Table of Contents
20 |
21 | - [Make it run](#make-it-run)
22 | - [Start parameters](#start-parameters)
23 | - [Docker](#docker)
24 | - [Access Token things](#access-token-things)
25 | - [HTTP RESTful API](#http-restful-api)
26 | - [Commands](#commands)
27 | - [Cloud mode](#cloud-mode)
28 |
29 | ## Make it run
30 |
31 | * Python version no less than `3.7`
32 |
33 | * install from `pip`
34 |
35 | ```shell
36 | pip install pandora-chatgpt
37 | pandora
38 | ```
39 | * `gpt-3.5-turbo` mode:
40 |
41 | ```shell
42 | pip install 'pandora-chatgpt[api]'
43 | // OR
44 | pip install pandora-chatgpt[api]
45 | pandora
46 | ```
47 | * `cloud` mode:
48 |
49 | ```shell
50 | pip install 'pandora-chatgpt[cloud]'
51 | // OR
52 | pip install pandora-chatgpt[cloud]
53 | pandora-cloud
54 | ```
55 |
56 | * install from source
57 |
58 | ```shell
59 | pip install .
60 | pandora
61 | ```
62 |
63 | * `gpt-3.5-turbo` mode:
64 |
65 | ```shell
66 | pip install '.[api]'
67 | // OR
68 | pip install .[api]
69 | pandora
70 | ```
71 |
72 | * `cloud` mode:
73 |
74 | ```shell
75 | pip install '.[cloud]'
76 | // OR
77 | pip install .[cloud]
78 | pandora-cloud
79 | ```
80 |
81 | * Docker Hub
82 |
83 | ```shell
84 | docker pull pengzhile/pandora
85 | docker run -it --rm pengzhile/pandora
86 | ```
87 |
88 | * Docker build
89 |
90 | ```shell
91 | docker build -t pandora .
92 | docker run -it --rm pandora
93 | ```
94 |
95 | * login with your credentials
96 |
97 | * stay simple, stay naive, stay elegant
98 |
99 | ## Start parameters
100 |
101 | * `pandora --help` for help text.
102 | * `-p` or `--proxy` for setting the proxy. the value should be`protocol://user:pass@ip:port`.
103 | * `-t` or `--token_file` for indicating the file that stores `Access Token`. You will login with access token if this option is in use.
104 | * `-s` or `--server` starts the HTTP server, by which you could open a web page and interact with it in a fancy UI. the value should be`ip:port`.
105 | * `-a` or `--api` use `gpt-3.5-turbo` API in backend. **NOTICE: you will be charged if this option is in use.**
106 | * `--tokens_file` indicating a file storing multiple `Access Token`s. The file content should be like`{"key": "token"}`.
107 | * `--threads` specify the number of server workers, default is `8`, and for cloud mode, it is `4`.
108 | * `--sentry` sending error messages to author for improving Pandora. **Sensitive information won't be leaked.**
109 | * `-v` or `--verbose` for verbose debugging messages.
110 |
111 | ## Docker
112 |
113 | These docker environment variables will override start parameters.
114 |
115 | * `PANDORA_ACCESS_TOKEN` =`Access Token` string.
116 | * `PANDORA_TOKENS_FILE` = the path of file which keeps `Access Token`s.
117 | * `PANDORA_PROXY` =`protocol://user:pass@ip:port`.
118 | * `PANDORA_SERVER` =`ip:port`.
119 | * `PANDORA_API` for using `gpt-3.5-turbo` API. **NOTICE: you will be charged if this option is in use.**
120 | * `PANDORA_SENTRY` for sending error messages to author to improve Pandora. **Sensitive information won't be leaked.**
121 | * `PANDORA_VERBOSE` for verbose debugging messages.
122 |
123 | ## Access Token things
124 |
125 | * no need for proxy if login with `Access Token`.
126 | * you could obtain your access token safely with [this service](https://ai.fakeopen.com/auth).
127 | * `Access Token` has a expiration time as `14 days`, you could save it and keep using within this period.
128 | * leaking your `Access Token` will lead to loss of your account.
129 |
130 | ## HTTP RESTFUL API
131 |
132 | * if you start Pandora with `-s`/`--server`/`PANDORA_SERVER`, you could access a web UI with `http://ip:port`.
133 | * you could switch access token by passing a different one with `http://ip:port/?token=xxx`.
134 | * API documents: [doc/HTTP-API.md](https://github.com/pengzhile/pandora/blob/master/doc/HTTP-API.md)
135 |
136 | ## Commands
137 |
138 | * **double** `Enter` to send prompt to `ChatGPT`.
139 | * `/?` for help text.
140 | * `/title` for setting the title of current conversation.
141 | * `/select` back to conversation choosing page.
142 | * `/reload` for refreshing.
143 | * `/regen` for regenerating answers if you are not satisfied with the last one.
144 | * `/continue` make `ChatGPT` to append responses.
145 | * `/edit` for editing your previous prompt.
146 | * `/new` to start a new conversation.
147 | * `/del` to delete current conversation and back to conversation choosing page.
148 | * `/token` for printing current access token.
149 | * `/copy` for copying the last response of `ChatGPT` to pasteboard.
150 | * `/copy_code` for copying the code in the last response of `ChatGPT` to pasteboard.
151 | * `/clear` for cleaning the screen.
152 | * `/version` for printing the version of Pandora.
153 | * `/exit` to exit Pandora.
154 |
155 | ## Cloud mode
156 |
157 | - setting up a service just like official `ChatGPT` website. it's so same as only jesus could tell it apart.
158 |
159 | * you need to use `pandora-cloud` instead of `pandora` to start Pandora.
160 | * enabling `PANDORA_CLOUD` if you are using Docker to start Pandora.
161 | * Other parameters are same as these guys in normal mode.
162 |
--------------------------------------------------------------------------------
/API/pandora/doc/wiki.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
潘多拉 Pandora
5 |
6 | 一个不只是命令行的 "ChatGPT"
7 |
8 | Wiki in English »
9 |
10 |
11 | 查看Demo
12 | ·
13 | 报告Bug
14 | ·
15 | 提出新特性
16 |
17 |
18 |
19 | ## 目录
20 |
21 | - [如何运行](#如何运行)
22 | - [程序参数](#程序参数)
23 | - [Docker环境变量](#docker环境变量)
24 | - [关于 Access Token](#关于-access-token)
25 | - [HTTP服务文档](#http服务文档)
26 | - [操作命令](#操作命令)
27 | - [高阶设置](#高阶设置)
28 | - [Cloud模式](#cloud模式)
29 | - [使用Cloudflare Workers代理](#使用cloudflare-workers代理)
30 |
31 | ## 如何运行
32 |
33 | * Python版本目测起码要`3.7`
34 |
35 | * pip安装运行
36 |
37 | ```shell
38 | pip install pandora-chatgpt
39 | pandora
40 | ```
41 | * 如果你想支持`gpt-3.5-turbo`模式:
42 |
43 | ```shell
44 | pip install 'pandora-chatgpt[api]'
45 | // 或者
46 | pip install pandora-chatgpt[api]
47 | pandora
48 | ```
49 | * 如果你想启用`cloud`模式:
50 |
51 | ```shell
52 | pip install 'pandora-chatgpt[cloud]'
53 | // 或者
54 | pip install pandora-chatgpt[cloud]
55 | pandora-cloud
56 | ```
57 |
58 | * 编译运行
59 |
60 | ```shell
61 | pip install .
62 | pandora
63 | ```
64 |
65 | * 如果你想支持`gpt-3.5-turbo`模式:
66 |
67 | ```shell
68 | pip install '.[api]'
69 | // 或者
70 | pip install .[api]
71 | pandora
72 | ```
73 |
74 | * 如果你想启用`cloud`模式:
75 |
76 | ```shell
77 | pip install '.[cloud]'
78 | // 或者
79 | pip install .[cloud]
80 | pandora-cloud
81 | ```
82 |
83 | * Docker Hub运行
84 |
85 | ```shell
86 | docker pull pengzhile/pandora
87 | docker run -it --rm pengzhile/pandora
88 | ```
89 |
90 | * Docker编译运行
91 |
92 | ```shell
93 | docker build -t pandora .
94 | docker run -it --rm pandora
95 | ```
96 |
97 | * 输入用户名密码登录即可,登录密码理论上不显示出来,莫慌。
98 | * 简单而粗暴,不失优雅。
99 |
100 | ## 程序参数
101 |
102 | * 可通过 `pandora --help` 查看。
103 | * `-p` 或 `--proxy` 指定代理,格式:`protocol://user:pass@ip:port`。
104 | * `-t` 或 `--token_file` 指定一个存放`Access Token`的文件,使用`Access Token`登录。
105 | * `-s` 或 `--server` 以`http`服务方式启动,格式:`ip:port`。
106 | * `-a` 或 `--api` 使用`gpt-3.5-turbo`API请求,**你可能需要向`OpenAI`支付费用**。
107 | * `--tokens_file` 指定一个存放多`Access Token`的文件,内容为`{"key": "token"}`的形式。
108 | * `--threads` 指定服务启动的线程数,默认为 `8`,Cloud模式为 `4`。
109 | * `--sentry` 启用`sentry`框架来发送错误报告供作者查错,敏感信息**不会被发送**。
110 | * `-v` 或 `--verbose` 显示调试信息,且出错时打印异常堆栈信息,供查错使用。
111 |
112 | ## Docker环境变量
113 |
114 | * `PANDORA_ACCESS_TOKEN` 指定`Access Token`字符串。
115 | * `PANDORA_TOKENS_FILE` 指定一个存放多`Access Token`的文件路径。
116 | * `PANDORA_PROXY` 指定代理,格式:`protocol://user:pass@ip:port`。
117 | * `PANDORA_SERVER` 以`http`服务方式启动,格式:`ip:port`。
118 | * `PANDORA_API` 使用`gpt-3.5-turbo`API请求,**你可能需要向`OpenAI`支付费用**。
119 | * `PANDORA_SENTRY` 启用`sentry`框架来发送错误报告供作者查错,敏感信息**不会被发送**。
120 | * `PANDORA_VERBOSE` 显示调试信息,且出错时打印异常堆栈信息,供查错使用。
121 | * 使用Docker方式,设置环境变量即可,无视上述`程序参数`。
122 |
123 | ## 关于 Access Token
124 |
125 | * 使用`Access Token`方式登录,可以无代理直连。
126 | * [这个服务](https://ai.fakeopen.com/auth) 可以帮你安全有效拿到`Access Token`,无论是否第三方登录。
127 | * 其中`accessToken`字段的那一长串内容即是`Access Token`。
128 | * `Access Token`可以复制保存,其有效期目前为`14天`。
129 | * 不要泄露你的`Access Token`,使用它可以操纵你的账号。
130 |
131 | ## HTTP服务文档
132 |
133 | * 如果你以`http`服务方式启动,现在你可以打开一个极简版的`ChatGPT`了。通过你指定的`http://ip:port`来访问。
134 | * 通过`http://ip:port/?token=xxx`,传递一个Token的名字,可以切换到对应的`Access Token`。
135 | * API文档见:[doc/HTTP-API.md](https://github.com/pengzhile/pandora/blob/master/doc/HTTP-API.md)
136 |
137 | ## 操作命令
138 |
139 | * 对话界面**连敲两次**`Enter`发送你的输入给`ChatGPT`。
140 | * 对话界面使用`/?`可以打印支持的操作命令。
141 | * `/title` 重新设置当前对话的标题。
142 | * `/select` 回到选择会话界面。
143 | * `/reload` 重新加载当前会话所有内容,`F5`你能懂吧。
144 | * `/regen` 如果对`ChatGPT`当前回答不满意,可以让它重新回答。
145 | * `/continue` 让`ChatGPT`继续输出回复的剩余部分。
146 | * `/edit` 编辑你之前的一个提问。
147 | * `/new` 直接开启一个新会话。
148 | * `/del` 删除当前会话,回到会话选择界面。
149 | * `/token` 打印当前的`Access Token`,也许你用得上,但不要泄露。
150 | * `/copy` 复制`ChatGPT`上一次回复的内容到剪贴板。
151 | * `/copy_code` 复制`ChatGPT`上一次回复的代码到剪贴板
152 | * `/clear` 清屏,应该不用解释。
153 | * `/version` 打印`Pandora`的版本信息。
154 | * `/exit` 退出`潘多拉`。
155 |
156 | ## 高阶设置
157 |
158 | * 本部分内容不理解的朋友,**请勿擅动!**
159 | * 环境变量 `OPENAI_API_PREFIX` 可以替换OpenAI Api的前缀`https://api.openai.com`。
160 | * 环境变量 `CHATGPT_API_PREFIX` 可以替换ChatGPT Api的前缀`https://ai.fakeopen.com`。
161 | * 如果你想持久存储`Docker`中`Pandora`产生的数据,你可以挂载宿主机目录至`/data`。
162 | * 如果你在国内使用`pip`安装缓慢,可以考虑切换至腾讯的源:```pip config set global.index-url https://mirrors.cloud.tencent.com/pypi/simple```
163 | * 镜像同步版本可能不及时,如果出现这种情况建议切换至官方源:```pip config set global.index-url https://pypi.org/simple```
164 | * 默认使用`sqlite3`存储会话数据,如果你希望更换至`mysql`,可以这么做:
165 | * 执行```pip install PyMySQL```安装驱动。
166 | * 设置环境变量:`DATABASE_URI`为类似`mysql+pymysql://user:pass@localhost/dbname`的连接字符串。
167 | * 环境变量指定`OPENAI_EMAIL`可以替代登录输入用户名,`OPENAI_PASSWORD`则可以替代输入密码, `OPENAI_MFA_CODE`则可以替代输入二次验证。
168 | * 环境变量`API_SYSTEM_PROMPT`可以替换`api`模式下的系统`prompt`。
169 |
170 | ## Cloud模式
171 |
172 | * 搭建一个跟官方很像的`ChatGPT`服务,不能说很像,只能说一样。
173 | * 该模式使用`pandora-cloud`启动,前提是你如前面所说安装好了。
174 | * Docker环境变量:`PANDORA_CLOUD` 启动`cloud`模式。
175 | * 该模式参数含义与普通模式相同,可`--help`查看。
176 |
177 | ## 使用Cloudflare Workers代理
178 |
179 | * 如果你感觉默认的`https://ai.fakeopen.com`在你那里可能被墙了,可以使用如下方法自行代理。
180 | * 你需要一个`Cloudflare`账号,如果没有,可以[注册](https://dash.cloudflare.com/sign-up)一个。
181 | * 登录后,点击`Workers`,然后点击`Create a Worker`,填入服务名称后点击`创建服务`。
182 | * 点开你刚才创建的服务,点击`快速编辑`按钮,贴入下面的代码,然后点击`保存并部署`。
183 |
184 | ```javascript
185 | export default {
186 | async fetch(request, env) {
187 | const url = new URL(request.url);
188 | url.host = 'ai.fakeopen.com';
189 | return fetch(new Request(url, request))
190 | }
191 | }
192 | ```
193 |
194 | * 点击`触发器`选项卡,可以添加自定义访问域名。
195 | * 参考`高阶设置`中的环境变量使用你的服务地址进行替换。
196 |
--------------------------------------------------------------------------------
/API/go-chatgpt-api/api/platform/api.go:
--------------------------------------------------------------------------------
1 | package platform
2 |
3 | import (
4 | "bytes"
5 | "encoding/json"
6 | "fmt"
7 | "io"
8 | "strings"
9 |
10 | "github.com/gin-gonic/gin"
11 | "github.com/linweiyuan/go-chatgpt-api/api"
12 |
13 | http "github.com/bogdanfinn/fhttp"
14 | )
15 |
16 | func ListModels(c *gin.Context) {
17 | handleGet(c, apiListModels)
18 | }
19 |
20 | func RetrieveModel(c *gin.Context) {
21 | model := c.Param("model")
22 | handleGet(c, fmt.Sprintf(apiRetrieveModel, model))
23 | }
24 |
25 | //goland:noinspection GoUnhandledErrorResult
26 | func CreateCompletions(c *gin.Context) {
27 | var request CreateCompletionsRequest
28 | c.ShouldBindJSON(&request)
29 | data, _ := json.Marshal(request)
30 | resp, err := handlePost(c, apiCreateCompletions, data, request.Stream)
31 | if err != nil {
32 | return
33 | }
34 |
35 | defer resp.Body.Close()
36 | if request.Stream {
37 | api.HandleConversationResponse(c, resp)
38 | } else {
39 | io.Copy(c.Writer, resp.Body)
40 | }
41 | }
42 |
43 | //goland:noinspection GoUnhandledErrorResult
44 | func CreateChatCompletions(c *gin.Context) {
45 | var request ChatCompletionsRequest
46 | c.ShouldBindJSON(&request)
47 | data, _ := json.Marshal(request)
48 | resp, err := handlePost(c, apiCreataeChatCompletions, data, request.Stream)
49 | if err != nil {
50 | return
51 | }
52 |
53 | defer resp.Body.Close()
54 | if request.Stream {
55 | api.HandleConversationResponse(c, resp)
56 | } else {
57 | io.Copy(c.Writer, resp.Body)
58 | }
59 | }
60 |
61 | //goland:noinspection GoUnhandledErrorResult
62 | func CreateEdit(c *gin.Context) {
63 | var request CreateEditRequest
64 | c.ShouldBindJSON(&request)
65 | data, _ := json.Marshal(request)
66 | resp, err := handlePost(c, apiCreateEdit, data, false)
67 | if err != nil {
68 | return
69 | }
70 |
71 | defer resp.Body.Close()
72 | io.Copy(c.Writer, resp.Body)
73 | }
74 |
75 | //goland:noinspection GoUnhandledErrorResult
76 | func CreateImage(c *gin.Context) {
77 | var request CreateImageRequest
78 | c.ShouldBindJSON(&request)
79 | data, _ := json.Marshal(request)
80 | resp, err := handlePost(c, apiCreateImage, data, false)
81 | if err != nil {
82 | return
83 | }
84 |
85 | defer resp.Body.Close()
86 | io.Copy(c.Writer, resp.Body)
87 | }
88 |
89 | //goland:noinspection GoUnhandledErrorResult
90 | func CreateEmbeddings(c *gin.Context) {
91 | var request CreateEmbeddingsRequest
92 | c.ShouldBindJSON(&request)
93 | data, _ := json.Marshal(request)
94 | resp, err := handlePost(c, apiCreateEmbeddings, data, false)
95 | if err != nil {
96 | return
97 | }
98 |
99 | defer resp.Body.Close()
100 | io.Copy(c.Writer, resp.Body)
101 | }
102 |
103 | func ListFiles(c *gin.Context) {
104 | handleGet(c, apiListFiles)
105 | }
106 |
107 | func GetCreditGrants(c *gin.Context) {
108 | handleGet(c, apiGetCreditGrants)
109 | }
110 |
111 | //goland:noinspection GoUnhandledErrorResult
112 | func Login(c *gin.Context) {
113 | var loginInfo api.LoginInfo
114 | if err := c.ShouldBindJSON(&loginInfo); err != nil {
115 | c.AbortWithStatusJSON(http.StatusBadRequest, api.ReturnMessage(api.ParseUserInfoErrorMessage))
116 | return
117 | }
118 |
119 | userLogin := UserLogin{
120 | client: api.NewHttpClient(),
121 | }
122 |
123 | // hard refresh cookies
124 | resp, _ := userLogin.client.Get(auth0LogoutUrl)
125 | defer resp.Body.Close()
126 |
127 | // get authorized url
128 | authorizedUrl, statusCode, err := userLogin.GetAuthorizedUrl("")
129 | if err != nil {
130 | c.AbortWithStatusJSON(statusCode, api.ReturnMessage(err.Error()))
131 | return
132 | }
133 |
134 | // get state
135 | state, _, _ := userLogin.GetState(authorizedUrl)
136 |
137 | // check username
138 | statusCode, err = userLogin.CheckUsername(state, loginInfo.Username)
139 | if err != nil {
140 | c.AbortWithStatusJSON(statusCode, api.ReturnMessage(err.Error()))
141 | return
142 | }
143 |
144 | // check password
145 | code, statusCode, err := userLogin.CheckPassword(state, loginInfo.Username, loginInfo.Password)
146 | if err != nil {
147 | c.AbortWithStatusJSON(statusCode, api.ReturnMessage(err.Error()))
148 | return
149 | }
150 |
151 | // get access token
152 | accessToken, statusCode, err := userLogin.GetAccessToken(code)
153 | if err != nil {
154 | c.AbortWithStatusJSON(statusCode, api.ReturnMessage(err.Error()))
155 | return
156 | }
157 |
158 | // get session key
159 | var getAccessTokenResponse GetAccessTokenResponse
160 | json.Unmarshal([]byte(accessToken), &getAccessTokenResponse)
161 | req, _ := http.NewRequest(http.MethodPost, dashboardLoginUrl, strings.NewReader("{}"))
162 | req.Header.Set("Content-Type", "application/json")
163 | req.Header.Set("User-Agent", api.UserAgent)
164 | req.Header.Set("Authorization", api.GetAccessToken(getAccessTokenResponse.AccessToken))
165 | resp, err = userLogin.client.Do(req)
166 | if err != nil {
167 | c.AbortWithStatusJSON(http.StatusInternalServerError, api.ReturnMessage(err.Error()))
168 | return
169 | }
170 |
171 | defer resp.Body.Close()
172 | if resp.StatusCode != http.StatusOK {
173 | c.AbortWithStatusJSON(resp.StatusCode, api.ReturnMessage(getSessionKeyErrorMessage))
174 | return
175 | }
176 |
177 | io.Copy(c.Writer, resp.Body)
178 | }
179 |
180 | func GetSubscription(c *gin.Context) {
181 | handleGet(c, apiGetSubscription)
182 | }
183 |
184 | func GetApiKeys(c *gin.Context) {
185 | handleGet(c, apiGetApiKeys)
186 | }
187 |
188 | //goland:noinspection GoUnhandledErrorResult
189 | func handleGet(c *gin.Context, url string) {
190 | req, _ := http.NewRequest(http.MethodGet, url, nil)
191 | req.Header.Set("Authorization", api.GetAccessToken(c.GetHeader(api.AuthorizationHeader)))
192 | resp, _ := api.Client.Do(req)
193 | defer resp.Body.Close()
194 | io.Copy(c.Writer, resp.Body)
195 | }
196 |
197 | func handlePost(c *gin.Context, url string, data []byte, stream bool) (*http.Response, error) {
198 | req, _ := http.NewRequest(http.MethodPost, url, bytes.NewBuffer(data))
199 | req.Header.Set("Authorization", api.GetAccessToken(c.GetHeader(api.AuthorizationHeader)))
200 | if stream {
201 | req.Header.Set("Accept", "text/event-stream")
202 | }
203 | req.Header.Set("Content-Type", "application/json")
204 | resp, err := api.Client.Do(req)
205 | if err != nil {
206 | c.AbortWithStatusJSON(http.StatusInternalServerError, api.ReturnMessage(err.Error()))
207 | return nil, err
208 | }
209 |
210 | return resp, nil
211 | }
212 |
--------------------------------------------------------------------------------
/API/snova2api/snova-api.js:
--------------------------------------------------------------------------------
1 | const TARGET_URL = 'https://fast-api.snova.ai/v1/chat/completions';
2 | const MODEL_OVERRIDE = ''; // Set this to override the model
3 |
4 | // More: https://www.blueskyxn.com/202408/7089.html
5 | // 和 https://github.com/BlueSkyXN/OpenAI-Quick-DEV/blob/main/API/snova2api/snova2api.js 的逆向API的区别有且仅有目标URL不同
6 | // 有人发的 https://github.com/GrayXu/sambanova-api-ai-proxy/blob/main/cf-worker.js 实际上连oneapi都无法过测,我不知道为什么好意思发出来,问题和 https://github.com/lingo34/sambanova-ai-proxy/blob/main/cf-worker.js 基本半斤八两
7 |
8 | export default {
9 | async fetch(request) {
10 | if (request.method === 'POST' && request.url.endsWith('/v1/chat/completions')) {
11 | try {
12 | const originalPayload = await request.json();
13 | const isStreamMode = originalPayload.stream === true; // 检查用户是否指定了流模式
14 |
15 | // Override the model if MODEL_OVERRIDE is set
16 | if (MODEL_OVERRIDE && MODEL_OVERRIDE.trim() !== '') {
17 | originalPayload.model = MODEL_OVERRIDE;
18 | }
19 |
20 | // 强制添加 "stream": true 到目标API请求中,因为目标API只支持流模式
21 | originalPayload.stream = true;
22 |
23 | const modifiedPayload = {
24 | body: {
25 | ...originalPayload,
26 | stop: ["<|eot_id|>"]
27 | },
28 | env_type: "tp16405b"
29 | };
30 |
31 | const options = {
32 | method: 'POST',
33 | headers: {
34 | 'Content-Type': 'application/json'
35 | },
36 | body: JSON.stringify(modifiedPayload)
37 | };
38 |
39 | // 发送请求到目标API
40 | const response = await fetch(TARGET_URL, options);
41 |
42 | // 如果用户请求了流模式
43 | if (isStreamMode) {
44 | // 直接将流数据逐步传输给客户端
45 | const streamResponse = new ReadableStream({
46 | async start(controller) {
47 | const reader = response.body.getReader();
48 | const decoder = new TextDecoder();
49 |
50 | while (true) {
51 | const { done, value } = await reader.read();
52 | if (done) {
53 | controller.close();
54 | break;
55 | }
56 | // 将流数据发送给客户端
57 | const chunk = decoder.decode(value, { stream: true });
58 | const lines = chunk.split('\n');
59 | for (const line of lines) {
60 | if (line.startsWith('data:')) {
61 | const data = line.replace(/^data: /, '').trim();
62 | if (data) {
63 | controller.enqueue(new TextEncoder().encode(`data: ${data}\n\n`));
64 | }
65 | }
66 | }
67 | }
68 | }
69 | });
70 |
71 | return new Response(streamResponse, {
72 | status: 200,
73 | headers: {
74 | 'Content-Type': 'text/event-stream',
75 | 'Cache-Control': 'no-cache',
76 | 'Access-Control-Allow-Origin': '*',
77 | 'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
78 | 'Access-Control-Allow-Headers': 'Content-Type, Authorization'
79 | }
80 | });
81 |
82 | } else {
83 | // 非流模式:拼接流数据,并一次性返回完整响应
84 | const reader = response.body.getReader();
85 | const decoder = new TextDecoder();
86 | let completeResponse = '';
87 | let isDone = false;
88 | let finishReason = null;
89 | let statistics = {};
90 |
91 | while (!isDone) {
92 | const { done, value } = await reader.read();
93 | if (done) break;
94 |
95 | const chunk = decoder.decode(value, { stream: true });
96 | const lines = chunk.split('\n');
97 |
98 | for (const line of lines) {
99 | if (line.startsWith('data:')) {
100 | const data = line.replace(/^data: /, '').trim();
101 |
102 | if (data === '[DONE]') {
103 | isDone = true;
104 | break;
105 | }
106 |
107 | if (data) {
108 | try {
109 | const jsonChunk = JSON.parse(data);
110 | if (jsonChunk.choices && jsonChunk.choices[0].delta && jsonChunk.choices[0].delta.content) {
111 | completeResponse += jsonChunk.choices[0].delta.content;
112 | }
113 |
114 | if (jsonChunk.choices && jsonChunk.choices[0].finish_reason) {
115 | finishReason = jsonChunk.choices[0].finish_reason;
116 | }
117 |
118 | if (jsonChunk.usage) {
119 | statistics = jsonChunk.usage;
120 | }
121 |
122 | } catch (err) {
123 | console.error('Failed to parse JSON chunk:', err);
124 | }
125 | }
126 | }
127 | }
128 | }
129 |
130 | return new Response(JSON.stringify({
131 | id: "complete-id",
132 | object: "chat.completion",
133 | created: Date.now(),
134 | model: originalPayload.model || "default-model",
135 | choices: [{
136 | index: 0,
137 | message: {
138 | role: "assistant",
139 | content: completeResponse
140 | },
141 | finish_reason: finishReason || "stop"
142 | }],
143 | usage: statistics
144 | }), {
145 | status: 200,
146 | headers: {
147 | 'Content-Type': 'application/json',
148 | 'Access-Control-Allow-Origin': '*',
149 | 'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
150 | 'Access-Control-Allow-Headers': 'Content-Type, Authorization'
151 | }
152 | });
153 | }
154 |
155 | } catch (error) {
156 | console.error('Error processing request:', error);
157 | return new Response(JSON.stringify({ error: 'Bad Request' }), { status: 400, headers: { 'Content-Type': 'application/json' } });
158 | }
159 | } else {
160 | return new Response(JSON.stringify({ error: 'Not Found' }), { status: 404, headers: { 'Content-Type': 'application/json' } });
161 | }
162 | }
163 | };
164 |
--------------------------------------------------------------------------------
/API/snova2api/snova2api.js:
--------------------------------------------------------------------------------
1 | // 参考了 https://github.com/lingo34/sambanova-ai-proxy/blob/main/cf-worker.js 但是那玩意不可用,无法过oneapi测试,因为目标接口不支持非流模式,所以我要进行一个转换
2 | // Meta-Llama-3.1-8B-Instruct、Meta-Llama-3.1-70B-Instruct、Meta-Llama-3.1-405B-Instruct、ignos/Mistral-T5-7B-v1、v1olet/v1olet_merged_dpo_7B、macadeliccc/WestLake-7B-v2-laser-truthy-dpo、cookinai/DonutLM-v1
3 | // More: https://www.blueskyxn.com/202408/7089.html
4 | const TARGET_URL = 'https://fast.snova.ai/api/completion';
5 | const MODEL_OVERRIDE = ''; // Set this to override the model
6 |
7 | export default {
8 | async fetch(request) {
9 | if (request.method === 'POST' && request.url.endsWith('/v1/chat/completions')) {
10 | try {
11 | const originalPayload = await request.json();
12 | const isStreamMode = originalPayload.stream === true; // 检查用户是否指定了流模式
13 |
14 | // Override the model if MODEL_OVERRIDE is set
15 | if (MODEL_OVERRIDE && MODEL_OVERRIDE.trim() !== '') {
16 | originalPayload.model = MODEL_OVERRIDE;
17 | }
18 |
19 | // 强制添加 "stream": true 到目标API请求中,因为目标API只支持流模式
20 | originalPayload.stream = true;
21 |
22 | const modifiedPayload = {
23 | body: {
24 | ...originalPayload,
25 | stop: ["<|eot_id|>"]
26 | },
27 | env_type: "tp16405b"
28 | };
29 |
30 | const options = {
31 | method: 'POST',
32 | headers: {
33 | 'Content-Type': 'application/json'
34 | },
35 | body: JSON.stringify(modifiedPayload)
36 | };
37 |
38 | // 发送请求到目标API
39 | const response = await fetch(TARGET_URL, options);
40 |
41 | // 如果用户请求了流模式
42 | if (isStreamMode) {
43 | // 直接将流数据逐步传输给客户端
44 | const streamResponse = new ReadableStream({
45 | async start(controller) {
46 | const reader = response.body.getReader();
47 | const decoder = new TextDecoder();
48 |
49 | while (true) {
50 | const { done, value } = await reader.read();
51 | if (done) {
52 | controller.close();
53 | break;
54 | }
55 | // 将流数据发送给客户端
56 | const chunk = decoder.decode(value, { stream: true });
57 | const lines = chunk.split('\n');
58 | for (const line of lines) {
59 | if (line.startsWith('data:')) {
60 | const data = line.replace(/^data: /, '').trim();
61 | if (data) {
62 | controller.enqueue(new TextEncoder().encode(`data: ${data}\n\n`));
63 | }
64 | }
65 | }
66 | }
67 | }
68 | });
69 |
70 | return new Response(streamResponse, {
71 | status: 200,
72 | headers: {
73 | 'Content-Type': 'text/event-stream',
74 | 'Cache-Control': 'no-cache',
75 | 'Access-Control-Allow-Origin': '*',
76 | 'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
77 | 'Access-Control-Allow-Headers': 'Content-Type, Authorization'
78 | }
79 | });
80 |
81 | } else {
82 | // 非流模式:拼接流数据,并一次性返回完整响应
83 | const reader = response.body.getReader();
84 | const decoder = new TextDecoder();
85 | let completeResponse = '';
86 | let isDone = false;
87 | let finishReason = null;
88 | let statistics = {};
89 |
90 | while (!isDone) {
91 | const { done, value } = await reader.read();
92 | if (done) break;
93 |
94 | const chunk = decoder.decode(value, { stream: true });
95 | const lines = chunk.split('\n');
96 |
97 | for (const line of lines) {
98 | if (line.startsWith('data:')) {
99 | const data = line.replace(/^data: /, '').trim();
100 |
101 | if (data === '[DONE]') {
102 | isDone = true;
103 | break;
104 | }
105 |
106 | if (data) {
107 | try {
108 | const jsonChunk = JSON.parse(data);
109 | if (jsonChunk.choices && jsonChunk.choices[0].delta && jsonChunk.choices[0].delta.content) {
110 | completeResponse += jsonChunk.choices[0].delta.content;
111 | }
112 |
113 | if (jsonChunk.choices && jsonChunk.choices[0].finish_reason) {
114 | finishReason = jsonChunk.choices[0].finish_reason;
115 | }
116 |
117 | if (jsonChunk.usage) {
118 | statistics = jsonChunk.usage;
119 | }
120 |
121 | } catch (err) {
122 | console.error('Failed to parse JSON chunk:', err);
123 | }
124 | }
125 | }
126 | }
127 | }
128 |
129 | return new Response(JSON.stringify({
130 | id: "complete-id",
131 | object: "chat.completion",
132 | created: Date.now(),
133 | model: originalPayload.model || "default-model",
134 | choices: [{
135 | index: 0,
136 | message: {
137 | role: "assistant",
138 | content: completeResponse
139 | },
140 | finish_reason: finishReason || "stop"
141 | }],
142 | usage: statistics
143 | }), {
144 | status: 200,
145 | headers: {
146 | 'Content-Type': 'application/json',
147 | 'Access-Control-Allow-Origin': '*',
148 | 'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
149 | 'Access-Control-Allow-Headers': 'Content-Type, Authorization'
150 | }
151 | });
152 | }
153 |
154 | } catch (error) {
155 | console.error('Error processing request:', error);
156 | return new Response(JSON.stringify({ error: 'Bad Request' }), { status: 400, headers: { 'Content-Type': 'application/json' } });
157 | }
158 | } else {
159 | return new Response(JSON.stringify({ error: 'Not Found' }), { status: 404, headers: { 'Content-Type': 'application/json' } });
160 | }
161 | }
162 | };
163 |
--------------------------------------------------------------------------------
/API/ChatGPT-to-API/handlers.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "bufio"
5 | "encoding/json"
6 | "freechatgpt/internal/chatgpt"
7 | "freechatgpt/internal/tokens"
8 | typings "freechatgpt/internal/typings"
9 | "freechatgpt/internal/typings/responses"
10 | "io"
11 | "os"
12 | "strings"
13 |
14 | "github.com/gin-gonic/gin"
15 | )
16 |
17 | func passwordHandler(c *gin.Context) {
18 | // Get the password from the request (json) and update the password
19 | type password_struct struct {
20 | Password string `json:"password"`
21 | }
22 | var password password_struct
23 | err := c.BindJSON(&password)
24 | if err != nil {
25 | c.String(400, "password not provided")
26 | return
27 | }
28 | ADMIN_PASSWORD = password.Password
29 | // Set environment variable
30 | os.Setenv("ADMIN_PASSWORD", ADMIN_PASSWORD)
31 | c.String(200, "password updated")
32 | }
33 |
34 | func puidHandler(c *gin.Context) {
35 | // Get the password from the request (json) and update the password
36 | type puid_struct struct {
37 | PUID string `json:"puid"`
38 | }
39 | var puid puid_struct
40 | err := c.BindJSON(&puid)
41 | if err != nil {
42 | c.String(400, "puid not provided")
43 | return
44 | }
45 | // Set environment variable
46 | os.Setenv("PUID", puid.PUID)
47 | c.String(200, "puid updated")
48 | }
49 |
50 | func tokensHandler(c *gin.Context) {
51 | // Get the request_tokens from the request (json) and update the request_tokens
52 | var request_tokens []string
53 | err := c.BindJSON(&request_tokens)
54 | if err != nil {
55 | c.String(400, "tokens not provided")
56 | return
57 | }
58 | ACCESS_TOKENS = tokens.NewAccessToken(request_tokens)
59 | c.String(200, "tokens updated")
60 | }
61 | func optionsHandler(c *gin.Context) {
62 | // Set headers for CORS
63 | c.Header("Access-Control-Allow-Origin", "*")
64 | c.Header("Access-Control-Allow-Methods", "POST")
65 | c.Header("Access-Control-Allow-Headers", "*")
66 | c.JSON(200, gin.H{
67 | "message": "pong",
68 | })
69 | }
70 | func nightmare(c *gin.Context) {
71 | var original_request typings.APIRequest
72 | err := c.BindJSON(&original_request)
73 | if err != nil {
74 | c.JSON(400, gin.H{"error": gin.H{
75 | "message": "Request must be proper JSON",
76 | "type": "invalid_request_error",
77 | "param": nil,
78 | "code": err.Error(),
79 | }})
80 | }
81 | // Convert the chat request to a ChatGPT request
82 | translated_request := chatgpt.ConvertAPIRequest(original_request)
83 |
84 | authHeader := c.GetHeader("Authorization")
85 | token := ACCESS_TOKENS.GetToken()
86 | if authHeader != "" {
87 | customAccessToken := strings.Replace(authHeader, "Bearer ", "", 1)
88 | // Check if customAccessToken starts with sk-
89 | if strings.HasPrefix(customAccessToken, "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ik1UaEVOVUpHTkVNMVFURTRNMEZCTWpkQ05UZzVNRFUxUlRVd1FVSkRNRU13UmtGRVFrRXpSZyJ9") {
90 | token = customAccessToken
91 | }
92 | }
93 |
94 | response, err := chatgpt.SendRequest(translated_request, token)
95 | if err != nil {
96 | c.JSON(response.StatusCode, gin.H{
97 | "error": "error sending request",
98 | "message": response.Status,
99 | })
100 | return
101 | }
102 | defer response.Body.Close()
103 | if response.StatusCode != 200 {
104 | // Try read response body as JSON
105 | var error_response map[string]interface{}
106 | err = json.NewDecoder(response.Body).Decode(&error_response)
107 | if err != nil {
108 | // Read response body
109 | body, _ := io.ReadAll(response.Body)
110 | c.JSON(500, gin.H{"error": gin.H{
111 | "message": "Unknown error",
112 | "type": "internal_server_error",
113 | "param": nil,
114 | "code": "500",
115 | "details": string(body),
116 | }})
117 | return
118 | }
119 | c.JSON(response.StatusCode, gin.H{"error": gin.H{
120 | "message": error_response["detail"],
121 | "type": response.Status,
122 | "param": nil,
123 | "code": "error",
124 | }})
125 | return
126 | }
127 | // Create a bufio.Reader from the response body
128 | reader := bufio.NewReader(response.Body)
129 |
130 | var fulltext string
131 |
132 | // Read the response byte by byte until a newline character is encountered
133 | if original_request.Stream {
134 | // Response content type is text/event-stream
135 | c.Header("Content-Type", "text/event-stream")
136 | } else {
137 | // Response content type is application/json
138 | c.Header("Content-Type", "application/json")
139 | }
140 | for {
141 | line, err := reader.ReadString('\n')
142 | if err != nil {
143 | if err == io.EOF {
144 | break
145 | }
146 | return
147 | }
148 | if len(line) < 6 {
149 | continue
150 | }
151 | // Remove "data: " from the beginning of the line
152 | line = line[6:]
153 | // Check if line starts with [DONE]
154 | if !strings.HasPrefix(line, "[DONE]") {
155 | // Parse the line as JSON
156 | var original_response responses.Data
157 | err = json.Unmarshal([]byte(line), &original_response)
158 | if err != nil {
159 | continue
160 | }
161 | if original_response.Error != nil {
162 | return
163 | }
164 | if original_response.Message.Content.Parts == nil {
165 | continue
166 | }
167 | if original_response.Message.Content.Parts[0] == "" || original_response.Message.Author.Role != "assistant" {
168 | continue
169 | }
170 | if original_response.Message.Metadata.Timestamp == "absolute" {
171 | continue
172 | }
173 | tmp_fulltext := original_response.Message.Content.Parts[0]
174 | original_response.Message.Content.Parts[0] = strings.ReplaceAll(original_response.Message.Content.Parts[0], fulltext, "")
175 | translated_response := responses.NewChatCompletionChunk(original_response.Message.Content.Parts[0])
176 |
177 | // Stream the response to the client
178 | response_string := translated_response.String()
179 | if original_request.Stream {
180 | _, err = c.Writer.WriteString("data: " + string(response_string) + "\n\n")
181 | if err != nil {
182 | return
183 | }
184 | }
185 |
186 | // Flush the response writer buffer to ensure that the client receives each line as it's written
187 | c.Writer.Flush()
188 | fulltext = tmp_fulltext
189 | } else {
190 | if !original_request.Stream {
191 | full_response := responses.NewChatCompletion(fulltext)
192 | if err != nil {
193 | return
194 | }
195 | c.JSON(200, full_response)
196 | return
197 | }
198 | final_line := responses.StopChunk()
199 | c.Writer.WriteString("data: " + final_line.String() + "\n\n")
200 |
201 | c.String(200, "data: [DONE]\n\n")
202 | return
203 |
204 | }
205 | }
206 |
207 | }
208 |
--------------------------------------------------------------------------------
/API/go-chatgpt-api/api/chatgpt/access_token.go:
--------------------------------------------------------------------------------
1 | package chatgpt
2 |
3 | import (
4 | "encoding/json"
5 | "errors"
6 | "fmt"
7 | "io"
8 | "strings"
9 |
10 | "github.com/PuerkitoBio/goquery"
11 | "github.com/linweiyuan/go-chatgpt-api/api"
12 |
13 | http "github.com/bogdanfinn/fhttp"
14 | )
15 |
16 | //goland:noinspection GoUnhandledErrorResult,GoErrorStringFormat
17 | func (userLogin *UserLogin) GetAuthorizedUrl(csrfToken string) (string, int, error) {
18 | params := fmt.Sprintf(
19 | "callbackUrl=/&csrfToken=%s&json=true",
20 | csrfToken,
21 | )
22 | req, err := http.NewRequest(http.MethodPost, promptLoginUrl, strings.NewReader(params))
23 | req.Header.Set("Content-Type", api.ContentType)
24 | req.Header.Set("User-Agent", api.UserAgent)
25 | injectCookies(req)
26 | resp, err := userLogin.client.Do(req)
27 | if err != nil {
28 | return "", http.StatusInternalServerError, err
29 | }
30 |
31 | defer resp.Body.Close()
32 | if resp.StatusCode != http.StatusOK {
33 | return "", resp.StatusCode, errors.New(api.GetAuthorizedUrlErrorMessage)
34 | }
35 |
36 | responseMap := make(map[string]string)
37 | json.NewDecoder(resp.Body).Decode(&responseMap)
38 | return responseMap["url"], http.StatusOK, nil
39 | }
40 |
41 | //goland:noinspection GoUnhandledErrorResult,GoErrorStringFormat
42 | func (userLogin *UserLogin) GetState(authorizedUrl string) (string, int, error) {
43 | req, err := http.NewRequest(http.MethodGet, authorizedUrl, nil)
44 | req.Header.Set("Content-Type", api.ContentType)
45 | req.Header.Set("User-Agent", api.UserAgent)
46 | resp, err := userLogin.client.Do(req)
47 | if err != nil {
48 | return "", http.StatusInternalServerError, err
49 | }
50 |
51 | defer resp.Body.Close()
52 | if resp.StatusCode != http.StatusOK {
53 | return "", resp.StatusCode, errors.New(api.GetStateErrorMessage)
54 | }
55 |
56 | doc, _ := goquery.NewDocumentFromReader(resp.Body)
57 | state, _ := doc.Find("input[name=state]").Attr("value")
58 | return state, http.StatusOK, nil
59 | }
60 |
61 | //goland:noinspection GoUnhandledErrorResult,GoErrorStringFormat
62 | func (userLogin *UserLogin) CheckUsername(state string, username string) (int, error) {
63 | formParams := fmt.Sprintf(
64 | "state=%s&username=%s&js-available=true&webauthn-available=true&is-brave=false&webauthn-platform-available=false&action=default",
65 | state,
66 | username,
67 | )
68 | req, _ := http.NewRequest(http.MethodPost, api.LoginUsernameUrl+state, strings.NewReader(formParams))
69 | req.Header.Set("Content-Type", api.ContentType)
70 | req.Header.Set("User-Agent", api.UserAgent)
71 | resp, err := userLogin.client.Do(req)
72 | if err != nil {
73 | return http.StatusInternalServerError, err
74 | }
75 |
76 | defer resp.Body.Close()
77 | if resp.StatusCode != http.StatusOK {
78 | return resp.StatusCode, errors.New(api.EmailInvalidErrorMessage)
79 | }
80 |
81 | return http.StatusOK, nil
82 | }
83 |
84 | //goland:noinspection GoUnhandledErrorResult,GoErrorStringFormat
85 | func (userLogin *UserLogin) CheckPassword(state string, username string, password string) (string, int, error) {
86 | formParams := fmt.Sprintf(
87 | "state=%s&username=%s&password=%s&action=default",
88 | state,
89 | username,
90 | password,
91 | )
92 | req, err := http.NewRequest(http.MethodPost, api.LoginPasswordUrl+state, strings.NewReader(formParams))
93 | req.Header.Set("Content-Type", api.ContentType)
94 | req.Header.Set("User-Agent", api.UserAgent)
95 | userLogin.client.SetFollowRedirect(false) // make sure the cookie is injected with host chat.openai.com
96 | resp, err := userLogin.client.Do(req)
97 | if err != nil {
98 | return "", http.StatusInternalServerError, err
99 | }
100 |
101 | defer resp.Body.Close()
102 | if resp.StatusCode == http.StatusBadRequest {
103 | doc, _ := goquery.NewDocumentFromReader(resp.Body)
104 | alert := doc.Find("#prompt-alert").Text()
105 | if alert != "" {
106 | return "", resp.StatusCode, errors.New(strings.TrimSpace(alert))
107 | }
108 |
109 | return "", resp.StatusCode, errors.New(api.EmailOrPasswordInvalidErrorMessage)
110 | }
111 |
112 | if resp.StatusCode == http.StatusFound {
113 | req, _ := http.NewRequest(http.MethodGet, api.Auth0Url+resp.Header.Get("Location"), nil)
114 | req.Header.Set("User-Agent", api.UserAgent)
115 | resp, err := userLogin.client.Do(req)
116 | if err != nil {
117 | return "", http.StatusInternalServerError, err
118 | }
119 |
120 | defer resp.Body.Close()
121 | if resp.StatusCode == http.StatusFound {
122 | location := resp.Header.Get("Location")
123 | if strings.HasPrefix(location, "/u/mfa-otp-challenge") {
124 | return "", http.StatusBadRequest, errors.New("Login with two-factor authentication enabled is not supported currently.")
125 | }
126 |
127 | req, _ := http.NewRequest(http.MethodGet, location, nil)
128 | req.Header.Set("User-Agent", api.UserAgent)
129 | injectCookies(req) // if not set this, will get 403 in some IPs
130 | resp, err := userLogin.client.Do(req)
131 | if err != nil {
132 | return "", http.StatusInternalServerError, err
133 | }
134 |
135 | defer resp.Body.Close()
136 | if resp.StatusCode == http.StatusFound {
137 | return "", http.StatusOK, nil
138 | }
139 |
140 | if resp.StatusCode == http.StatusTemporaryRedirect {
141 | errorDescription := req.URL.Query().Get("error_description")
142 | if errorDescription != "" {
143 | return "", resp.StatusCode, errors.New(errorDescription)
144 | }
145 | }
146 |
147 | return "", resp.StatusCode, errors.New(api.GetAccessTokenErrorMessage)
148 | }
149 |
150 | return "", resp.StatusCode, errors.New(api.EmailOrPasswordInvalidErrorMessage)
151 | }
152 |
153 | return "", resp.StatusCode, nil
154 | }
155 |
156 | //goland:noinspection GoUnhandledErrorResult,GoErrorStringFormat,GoUnusedParameter
157 | func (userLogin *UserLogin) GetAccessToken(code string) (string, int, error) {
158 | req, err := http.NewRequest(http.MethodGet, authSessionUrl, nil)
159 | req.Header.Set("User-Agent", api.UserAgent)
160 | injectCookies(req)
161 | resp, err := userLogin.client.Do(req)
162 | if err != nil {
163 | return "", http.StatusInternalServerError, err
164 | }
165 |
166 | defer resp.Body.Close()
167 | if resp.StatusCode != http.StatusOK {
168 | if resp.StatusCode == http.StatusTooManyRequests {
169 | responseMap := make(map[string]string)
170 | json.NewDecoder(resp.Body).Decode(&responseMap)
171 | return "", resp.StatusCode, errors.New(responseMap["detail"])
172 | }
173 |
174 | return "", resp.StatusCode, errors.New(api.GetAccessTokenErrorMessage)
175 | }
176 |
177 | data, _ := io.ReadAll(resp.Body)
178 | return string(data), http.StatusOK, nil
179 | }
180 |
--------------------------------------------------------------------------------
/API/pandora/src/pandora/turbo/base.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | import uuid
4 | from datetime import datetime as dt
5 |
6 |
7 | class Prompt:
8 | def __init__(self, prompt_id=None, role=None, content=None, parent=None):
9 | self.prompt_id = prompt_id or str(uuid.uuid4())
10 | self.parent_id = None
11 | self.role = role
12 | self.content = content
13 | self.children = []
14 | self.create_time = dt.now().timestamp()
15 |
16 | if parent:
17 | self.parent_id = parent.prompt_id
18 | parent.add_child(self.prompt_id)
19 |
20 | def add_child(self, prompt_id):
21 | self.children.append(prompt_id)
22 |
23 | def get_message(self, end=True):
24 | return None
25 |
26 | def get_info(self):
27 | return {
28 | 'id': self.prompt_id,
29 | 'message': self.get_message(),
30 | 'parent': self.parent_id,
31 | 'children': self.children
32 | }
33 |
34 |
35 | class SystemPrompt(Prompt):
36 | def __init__(self, content, parent):
37 | super().__init__(role='system', content=content, parent=parent)
38 |
39 | def get_message(self, end=True):
40 | return {
41 | 'id': self.prompt_id,
42 | 'author': {
43 | 'role': self.role,
44 | 'name': None,
45 | 'metadata': {}
46 | },
47 | 'create_time': self.create_time,
48 | 'update_time': None,
49 | 'content': {
50 | 'content_type': 'text',
51 | 'parts': ['']
52 | },
53 | 'end_turn': True,
54 | 'weight': 1.0,
55 | 'metadata': {},
56 | 'recipient': 'all'
57 | }
58 |
59 |
60 | class UserPrompt(Prompt):
61 | def __init__(self, prompt_id, content, parent):
62 | super().__init__(prompt_id=prompt_id, role='user', content=content, parent=parent)
63 |
64 | def get_message(self, end=True):
65 | return {
66 | 'id': self.prompt_id,
67 | 'author': {
68 | 'role': self.role,
69 | 'name': None,
70 | 'metadata': {}
71 | },
72 | 'create_time': self.create_time,
73 | 'update_time': None,
74 | 'content': {
75 | 'content_type': 'text',
76 | 'parts': [self.content]
77 | },
78 | 'end_turn': None,
79 | 'weight': 1.0,
80 | 'metadata': {
81 | 'timestamp_': 'absolute',
82 | 'message_type': None
83 | },
84 | 'recipient': 'all'
85 | }
86 |
87 |
88 | class GptPrompt(Prompt):
89 | def __init__(self, parent, model):
90 | super().__init__(role='assistant', content='', parent=parent)
91 | self.model = model
92 |
93 | def append_content(self, content):
94 | self.content += content
95 |
96 | return self
97 |
98 | def get_message(self, end=True):
99 | return {
100 | 'id': self.prompt_id,
101 | 'author': {
102 | 'role': self.role,
103 | 'name': None,
104 | 'metadata': {}
105 | },
106 | 'create_time': self.create_time,
107 | 'update_time': None,
108 | 'content': {
109 | 'content_type': 'text',
110 | 'parts': [self.content]
111 | },
112 | 'end_turn': False if end else None,
113 | 'weight': 1.0,
114 | 'metadata': {
115 | 'message_type': None,
116 | 'model_slug': self.model,
117 | 'finish_details': {
118 | 'type': 'stop'
119 | } if end else None,
120 | 'timestamp_': 'absolute'
121 | },
122 | 'recipient': 'all'
123 | }
124 |
125 |
126 | class Conversation:
127 | def __init__(self):
128 | self.conversation_id = str(uuid.uuid4())
129 | self.title = 'New chat'
130 | self.create_time = dt.now().timestamp()
131 | self.current_node = None
132 | self.prompts = {}
133 |
134 | def add_prompt(self, prompt):
135 | self.prompts[prompt.prompt_id] = prompt
136 | self.current_node = prompt.prompt_id
137 |
138 | return prompt
139 |
140 | def get_prompt(self, prompt_id):
141 | return self.prompts.get(prompt_id)
142 |
143 | def get_prompts(self):
144 | return self.prompts
145 |
146 | def set_title(self, title):
147 | self.title = title
148 |
149 | def get_title(self):
150 | return self.title
151 |
152 | def get_messages_directly(self, message_id):
153 | messages = []
154 | while True:
155 | prompt = self.get_prompt(message_id)
156 | if not prompt.parent_id:
157 | break
158 |
159 | messages.insert(0, {
160 | 'role': prompt.role,
161 | 'content': prompt.content
162 | })
163 | message_id = prompt.parent_id
164 |
165 | return messages
166 |
167 | def get_messages(self, message_id, model):
168 | messages = []
169 | user_prompt = None
170 | while True:
171 | prompt = self.get_prompt(message_id)
172 | if not prompt.parent_id:
173 | break
174 |
175 | if not user_prompt and isinstance(prompt, UserPrompt):
176 | user_prompt = prompt
177 |
178 | messages.insert(0, {
179 | 'role': prompt.role,
180 | 'content': prompt.content
181 | })
182 | message_id = prompt.parent_id
183 |
184 | return user_prompt, self.add_prompt(GptPrompt(user_prompt, model)), messages
185 |
186 | def get_info(self):
187 | mapping = {}
188 | for prompt_id in self.prompts:
189 | mapping[prompt_id] = self.prompts[prompt_id].get_info()
190 |
191 | return {
192 | 'title': self.title,
193 | 'create_time': self.create_time,
194 | 'mapping': mapping,
195 | 'moderation_results': [],
196 | 'current_node': self.current_node,
197 | }
198 |
199 |
200 | class Conversations:
201 | def __init__(self):
202 | self.__data = []
203 |
204 | def list(self, offset, limit):
205 | return len(self.__data), self.__data[offset: limit]
206 |
207 | def clear(self):
208 | self.__data = []
209 |
210 | def delete(self, conversation):
211 | self.__data = [x for x in self.__data if conversation.conversation_id != x.conversation_id]
212 |
213 | def new(self):
214 | conversation = Conversation()
215 | self.__data.insert(0, conversation)
216 |
217 | return conversation
218 |
219 | def get(self, conversation_id):
220 | for x in self.__data:
221 | if x.conversation_id == conversation_id:
222 | return x
223 |
224 | return None
225 |
226 | def guard_get(self, conversation_id):
227 | conversation = self.get(conversation_id)
228 | if not conversation:
229 | raise Exception('Can\'t load conversation {}'.format(conversation_id))
230 |
231 | return conversation
232 |
--------------------------------------------------------------------------------
/Quick-ASK.py:
--------------------------------------------------------------------------------
1 | import requests
2 | import json
3 | import threading
4 | import time
5 | from tkinter import Tk, Text, Button, StringVar, Label, Menu, Toplevel, END, Scrollbar, Entry, OptionMenu, Y, BOTH, Frame, RIGHT, LEFT
6 |
7 | def send_request(content, url, auth, model):
8 | headers = {
9 | 'Content-Type': 'application/json',
10 | 'Authorization': auth
11 | }
12 | data = {
13 | "model": model,
14 | "messages": [{"role": "user", "content": content}]
15 | }
16 | try:
17 | response = requests.post(url, headers=headers, data=json.dumps(data), timeout=150)
18 | response.raise_for_status() # 将在HTTP错误时引发异常
19 | except requests.exceptions.RequestException as err:
20 | return f"可能触发150s超时或其他原因,目前请求发送错误: {err}"
21 |
22 | try:
23 | json_response = response.json()
24 | except json.JSONDecodeError as err:
25 | return f"无法解析JSON响应: {err}"
26 |
27 | if 'choices' in json_response and json_response['choices']:
28 | return json_response['choices'][0]['message']['content']
29 | else:
30 | return "响应中没有 'choices' 键或 'choices' 为空"
31 |
32 |
33 |
34 | def create_url_settings_window(url_var):
35 | url_settings_window = Toplevel()
36 | url_settings_window.title("设置请求URL")
37 | url_settings_window.geometry("500x200")
38 | Label(url_settings_window, text="请输入请求的URL:").pack(pady=5)
39 | Label(url_settings_window, text="默认的Endpoint端点是 /v1/chat/completions").pack(pady=5)
40 | current_url_label = Label(url_settings_window, textvariable=url_var)
41 | current_url_label.pack(pady=5)
42 | new_url_var = StringVar()
43 | url_entry = Entry(url_settings_window, textvariable=new_url_var, width=50)
44 | url_entry.pack(pady=5)
45 | Button(url_settings_window, text='提交修改', command=lambda: [url_var.set(new_url_var.get()), url_settings_window.destroy()]).pack(pady=10)
46 |
47 |
48 | def create_auth_settings_window(auth_var):
49 | auth_settings_window = Toplevel()
50 | auth_settings_window.title("设置认证信息")
51 | auth_settings_window.geometry("500x200")
52 | Label(auth_settings_window, text="请输入请求的认证信息(Authorization):").pack(pady=5)
53 | Label(auth_settings_window, text="FAKEAPI默认的认证信息是 TotallySecurePassword").pack(pady=5)
54 | current_auth_label = Label(auth_settings_window, textvariable=auth_var)
55 | current_auth_label.pack(pady=5)
56 | new_auth_var = StringVar()
57 | auth_entry = Entry(auth_settings_window, textvariable=new_auth_var, width=50)
58 | auth_entry.pack(pady=5)
59 | Button(auth_settings_window, text='提交修改', command=lambda: [auth_var.set(new_auth_var.get()), auth_settings_window.destroy()]).pack(pady=10)
60 |
61 |
62 | def create_model_settings_window(model_var):
63 | settings_window = Toplevel()
64 | settings_window.title("模型设置")
65 | settings_window.geometry("500x200")
66 |
67 | settings_window.columnconfigure(0, weight=1) # center all elements
68 |
69 | Label(settings_window, text="请选择使用的模型:").grid(row=0, padx=10, pady=10)
70 |
71 | current_model_label = Label(settings_window, textvariable=model_var)
72 | current_model_label.grid(row=1, padx=10, pady=5)
73 |
74 | model_mapping = {
75 | 'GPT-3.5': 'text-davinci-002-render-sha',
76 | 'GPT-3.5 Mobile': 'text-davinci-002-render-sha-mobile',
77 | 'GPT-4 Mobile': 'gpt-4-mobile',
78 | 'GPT-4': 'gpt-4',
79 | 'GPT-4 Browsing': 'gpt-4-browsing',
80 | 'GPT-4 Plugins': 'gpt-4-plugins',
81 | '自定义': '自定义',
82 | }
83 |
84 | # Flip the model_mapping for reverse lookup
85 | reverse_model_mapping = {v: k for k, v in model_mapping.items()}
86 |
87 | display_var = StringVar()
88 | display_var.set(reverse_model_mapping[model_var.get()]) # Load the previous setting
89 |
90 | custom_model_var = StringVar()
91 |
92 | if model_var.get() == "自定义":
93 | custom_model_var.set(model_var.get())
94 |
95 | custom_model_entry = Entry(settings_window, textvariable=custom_model_var, width=50)
96 | custom_model_entry.grid(row=3, padx=10, pady=10)
97 | custom_model_entry.grid_remove() # Initially hide the entry box
98 |
99 | def update_entry(option):
100 | if option == '自定义':
101 | custom_model_entry.grid()
102 | model_var.set(custom_model_var.get())
103 | else:
104 | custom_model_entry.grid_remove()
105 | model_var.set(model_mapping[option]) # Update the model name immediately
106 |
107 | model_menu = OptionMenu(settings_window, display_var, *model_mapping.keys(), command=update_entry)
108 | model_menu.grid(row=2, padx=10, pady=10)
109 |
110 | Button(settings_window, text='提交修改', command=lambda: submit_model_changes(settings_window, model_var, custom_model_var)).grid(row=4, padx=10, pady=10)
111 |
112 |
113 | def submit_model_changes(settings_window, model_var, custom_model_var):
114 | if custom_model_var.get():
115 | model_var.set(custom_model_var.get())
116 | settings_window.destroy()
117 |
118 |
119 | def create_window():
120 | window = Tk()
121 | window.title("快速向GPT提问")
122 | window.geometry("600x400") # 修改一下窗口大小
123 |
124 | url_var = StringVar()
125 | url_var.set("http://127.0.0.1:31480/v1/chat/completions")
126 | auth_var = StringVar()
127 | auth_var.set("TotallySecurePassword")
128 | model_var = StringVar()
129 | model_var.set("gpt-4-mobile")
130 |
131 | title_label = Label(window, text="请输入您的问题:")
132 | title_label.pack(pady=10)
133 | entry = Text(window, width=60, height=5)
134 | entry.pack(pady=10)
135 |
136 | button_frame = Frame(window)
137 | button_frame.pack(pady=10)
138 |
139 | window.button = Button(button_frame, text='提问', command=lambda: on_button_click(window, entry, url_var.get(), auth_var.get(), model_var.get()))
140 | window.button.pack(pady=10, side=LEFT)
141 |
142 | window.time_label = Label(button_frame, text="请求耗时:")
143 | window.time_label.pack(pady=10, side=RIGHT)
144 |
145 | result_frame = Frame(window)
146 | result_frame.pack(pady=10, fill=BOTH, expand=True)
147 |
148 | scrollbar = Scrollbar(result_frame)
149 | scrollbar.pack(side=RIGHT, fill=Y)
150 |
151 | window.result_text = Text(result_frame, wrap="word", yscrollcommand=scrollbar.set)
152 | window.result_text.pack(side=LEFT, fill=BOTH, expand=True)
153 | scrollbar.config(command=window.result_text.yview)
154 |
155 | menubar = Menu(window)
156 | settings_menu = Menu(menubar, tearoff=0)
157 | settings_menu.add_command(label="更改请求URL", command=lambda: create_url_settings_window(url_var))
158 | settings_menu.add_command(label="更改认证信息", command=lambda: create_auth_settings_window(auth_var))
159 | settings_menu.add_command(label="自定义模型", command=lambda: create_model_settings_window(model_var))
160 | menubar.add_cascade(label="设置", menu=settings_menu)
161 | window.config(menu=menubar)
162 |
163 | window.mainloop()
164 |
165 |
166 |
167 | def on_button_click(window, entry, url, auth, model):
168 | content = entry.get("1.0", END).strip() # 获取文本框的全部内容
169 |
170 | def update_result_text(response):
171 | window.result_text.delete("1.0", END)
172 | window.result_text.insert(END, response)
173 |
174 | def send_request_thread():
175 | start_time = time.time()
176 | response = send_request(content, url, auth, model)
177 | formatted_response = "GPT: " + response
178 | window.after(0, update_result_text, formatted_response)
179 | window.button['text'] = "提问" # change the button text back when the request finishes
180 |
181 | # stop the timer
182 | window.is_requesting = False
183 |
184 | def timer_thread():
185 | start_time = time.time()
186 | while window.is_requesting:
187 | elapsed_time = time.time() - start_time
188 | window.time_label['text'] = "请求耗时:{:.3f}s".format(elapsed_time)
189 | time.sleep(0.1) # update every 100ms
190 |
191 | # indicate that a request is in progress
192 | window.is_requesting = True
193 | window.button['text'] = "提问中..."
194 |
195 | threading.Thread(target=send_request_thread).start()
196 | threading.Thread(target=timer_thread).start()
197 |
198 |
199 | if __name__ == "__main__":
200 | create_window()
201 |
--------------------------------------------------------------------------------