Alcex
commited on
Commit
·
dca6a23
1
Parent(s):
1b33bd6
Add application file
Browse filesThis view is limited to 50 files because it contains too many changes.
See raw diff
- .chglog/CHANGELOG.tpl.md +42 -0
- .chglog/config.yml +28 -0
- .gitattributes +0 -1
- .github/workflows/Auto Release.yml +89 -0
- .github/workflows/Build Docker Image.yml +67 -0
- .gitignore +183 -13
- Dockerfile +4 -13
- FreeGpt35/FreeGpt35.go +231 -0
- FreeGpt35Pool/FreeGpt35Pool.go +128 -0
- LICENSE +0 -21
- Procfile +0 -1
- ProofWork/ProofWork.go +55 -0
- ProxyPool/ProxyPool.go +87 -0
- README.md +63 -59
- RequestClient/RequestClient.go +10 -0
- RequestClient/TlsClient.go +77 -0
- VERSION +0 -1
- api/router.go +0 -18
- build.sh +0 -41
- common/common.go +285 -0
- config/config.go +74 -0
- constant/constant.go +11 -0
- conversion/requests/duckgo/convert.go +0 -30
- docker-compose.yml +0 -9
- env.template +8 -8
- go.mod +19 -25
- go.sum +42 -96
- httpclient/Iaurorahttpclient.go +0 -28
- httpclient/bogdanfinn/tls_client.go +0 -101
- httpclient/bogdanfinn/tls_client_test.go +0 -101
- httpclient/resty/resty_client.go +0 -72
- initialize/handlers.go +0 -110
- initialize/proxy.go +0 -48
- initialize/router.go +0 -35
- internal/duckgo/request.go +0 -188
- internal/proxys/proxys.go +0 -35
- main.go +24 -39
- middlewares/auth.go +0 -31
- middlewares/cors.go +0 -10
- queue/queue.go +106 -0
- release.bat +2 -2
- render.yaml +0 -7
- router/middleware.go +63 -0
- router/router.go +25 -0
- service/v1/tokens.go +20 -0
- service/v1/util.go +65 -0
- service/v1Chat/completions.go +19 -0
- service/v1Chat/gpt35Completions.go +231 -0
- service/v1Chat/reqModel/apiReq.go +14 -0
- service/v1Chat/reqModel/chatReq.go +31 -0
.chglog/CHANGELOG.tpl.md
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{{ range .Versions }}
|
| 2 |
+
<a name="{{ .Tag.Name }}"></a>
|
| 3 |
+
## {{ if .Tag.Previous }}[{{ .Tag.Name }}]{{ else }}{{ .Tag.Name }}{{ end }} - {{ datetime "2006-01-02" .Tag.Date }}
|
| 4 |
+
{{ range .CommitGroups -}}
|
| 5 |
+
### {{ .Title }}
|
| 6 |
+
{{ range .Commits -}}
|
| 7 |
+
- {{ if .Scope }}**{{ .Scope }}:** {{ end }}{{ .Subject }}
|
| 8 |
+
{{ end }}
|
| 9 |
+
{{ end -}}
|
| 10 |
+
|
| 11 |
+
{{- if .RevertCommits -}}
|
| 12 |
+
### Reverts
|
| 13 |
+
{{ range .RevertCommits -}}
|
| 14 |
+
- {{ .Revert.Header }}
|
| 15 |
+
{{ end }}
|
| 16 |
+
{{ end -}}
|
| 17 |
+
|
| 18 |
+
{{- if .MergeCommits -}}
|
| 19 |
+
### Pull Requests
|
| 20 |
+
{{ range .MergeCommits -}}
|
| 21 |
+
- {{ .Header }}
|
| 22 |
+
{{ end }}
|
| 23 |
+
{{ end -}}
|
| 24 |
+
|
| 25 |
+
{{- if .NoteGroups -}}
|
| 26 |
+
{{ range .NoteGroups -}}
|
| 27 |
+
### {{ .Title }}
|
| 28 |
+
{{ range .Notes }}
|
| 29 |
+
{{ .Body }}
|
| 30 |
+
{{ end }}
|
| 31 |
+
{{ end -}}
|
| 32 |
+
{{ end -}}
|
| 33 |
+
{{ end -}}
|
| 34 |
+
|
| 35 |
+
{{- if .Versions }}
|
| 36 |
+
[Unreleased]: {{ .Info.RepositoryURL }}/compare/{{ $latest := index .Versions 0 }}{{ $latest.Tag.Name }}...HEAD
|
| 37 |
+
{{ range .Versions -}}
|
| 38 |
+
{{ if .Tag.Previous -}}
|
| 39 |
+
[{{ .Tag.Name }}]: {{ $.Info.RepositoryURL }}/compare/{{ .Tag.Previous.Name }}...{{ .Tag.Name }}
|
| 40 |
+
{{ end -}}
|
| 41 |
+
{{ end -}}
|
| 42 |
+
{{ end -}}
|
.chglog/config.yml
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
style: github
|
| 2 |
+
template: CHANGELOG.tpl.md
|
| 3 |
+
info:
|
| 4 |
+
title: CHANGELOG
|
| 5 |
+
repository_url: https://github.com/aurorax-neo/free-gpt3.5-2api
|
| 6 |
+
options:
|
| 7 |
+
commits:
|
| 8 |
+
# filters:
|
| 9 |
+
# Type:
|
| 10 |
+
# - feat
|
| 11 |
+
# - fix
|
| 12 |
+
# - perf
|
| 13 |
+
# - refactor
|
| 14 |
+
commit_groups:
|
| 15 |
+
# title_maps:
|
| 16 |
+
# feat: Features
|
| 17 |
+
# fix: Bug Fixes
|
| 18 |
+
# perf: Performance Improvements
|
| 19 |
+
# refactor: Code Refactoring
|
| 20 |
+
header:
|
| 21 |
+
pattern: "^(\\w*)(?:\\(([\\w\\$\\.\\-\\*\\s]*)\\))?\\:\\s(.*)$"
|
| 22 |
+
pattern_maps:
|
| 23 |
+
- Type
|
| 24 |
+
- Scope
|
| 25 |
+
- Subject
|
| 26 |
+
notes:
|
| 27 |
+
keywords:
|
| 28 |
+
- BREAKING CHANGE
|
.gitattributes
DELETED
|
@@ -1 +0,0 @@
|
|
| 1 |
-
*.html linguist-language=Go
|
|
|
|
|
|
.github/workflows/Auto Release.yml
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
name: Auto Release
|
| 2 |
+
|
| 3 |
+
on:
|
| 4 |
+
push:
|
| 5 |
+
tags:
|
| 6 |
+
- 'release-v*'
|
| 7 |
+
|
| 8 |
+
env:
|
| 9 |
+
APP_NAME: free-gpt3.5-2api
|
| 10 |
+
|
| 11 |
+
jobs:
|
| 12 |
+
release:
|
| 13 |
+
runs-on: ubuntu-latest
|
| 14 |
+
steps:
|
| 15 |
+
|
| 16 |
+
- name: Checkout code
|
| 17 |
+
uses: actions/checkout@v4
|
| 18 |
+
with:
|
| 19 |
+
fetch-depth: 0
|
| 20 |
+
|
| 21 |
+
- name: Set up Go
|
| 22 |
+
uses: actions/setup-go@v5
|
| 23 |
+
with:
|
| 24 |
+
go-version: 'stable'
|
| 25 |
+
check-latest: true
|
| 26 |
+
|
| 27 |
+
- name: Build Binary
|
| 28 |
+
run: |
|
| 29 |
+
GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -o ${{ env.APP_NAME }} -a -ldflags '-s -w -extldflags "-static"' . && rm -rf artifact && mkdir -p artifact && cp ${{ env.APP_NAME }} artifact/${{ env.APP_NAME }} && cd artifact && tar -czvf ../${{ env.APP_NAME }}-linux-amd64.tar.gz * && cd ..
|
| 30 |
+
GOOS=darwin GOARCH=amd64 CGO_ENABLED=0 go build -o ${{ env.APP_NAME }} -a -ldflags '-s -w -extldflags "-static"' . && rm -rf artifact && mkdir -p artifact && cp ${{ env.APP_NAME }} artifact/${{ env.APP_NAME }} && cd artifact && tar -czvf ../${{ env.APP_NAME }}-darwin-amd64.tar.gz * && cd ..
|
| 31 |
+
GOOS=freebsd GOARCH=amd64 CGO_ENABLED=0 go build -o ${{ env.APP_NAME }} -a -ldflags '-s -w -extldflags "-static"' . && rm -rf artifact && mkdir -p artifact && cp ${{ env.APP_NAME }} artifact/${{ env.APP_NAME }} && cd artifact && tar -czvf ../${{ env.APP_NAME }}-freebsd-amd64.tar.gz * && cd ..
|
| 32 |
+
GOOS=windows GOARCH=amd64 CGO_ENABLED=0 go build -o ${{ env.APP_NAME }} -a -ldflags '-s -w -extldflags "-static"' . && rm -rf artifact && mkdir -p artifact && cp ${{ env.APP_NAME }} artifact/${{ env.APP_NAME }}.exe && cd artifact && tar -czvf ../${{ env.APP_NAME }}-windows-amd64.tar.gz * && cd ..
|
| 33 |
+
|
| 34 |
+
- name: Upload Artifact
|
| 35 |
+
uses: actions/upload-artifact@main
|
| 36 |
+
with:
|
| 37 |
+
name: ${{ env.APP_NAME }}-pre-built.zip
|
| 38 |
+
path: |
|
| 39 |
+
${{ env.APP_NAME }}-windows-amd64.tar.gz
|
| 40 |
+
${{ env.APP_NAME }}-linux-amd64.tar.gz
|
| 41 |
+
${{ env.APP_NAME }}-darwin-amd64.tar.gz
|
| 42 |
+
${{ env.APP_NAME }}-freebsd-amd64.tar.gz
|
| 43 |
+
|
| 44 |
+
- name: Get Release Name
|
| 45 |
+
shell: bash
|
| 46 |
+
id: grn
|
| 47 |
+
run: echo "tag=$(echo $GITHUB_REF | sed 's|refs/tags/||')" >> $GITHUB_OUTPUT
|
| 48 |
+
|
| 49 |
+
- name: Generate Changelog
|
| 50 |
+
id: changelog
|
| 51 |
+
run: |
|
| 52 |
+
export PATH=$PATH:$HOME/go/bin
|
| 53 |
+
go install github.com/git-chglog/git-chglog/cmd/git-chglog@latest
|
| 54 |
+
git-chglog -o CHANGELOG.md ${{ steps.grn.outputs.tag }}
|
| 55 |
+
|
| 56 |
+
- name: Release
|
| 57 |
+
id: release
|
| 58 |
+
uses: softprops/action-gh-release@v2
|
| 59 |
+
if: startsWith(github.ref, 'refs/tags/')
|
| 60 |
+
env:
|
| 61 |
+
# GITHUB_TOKEN
|
| 62 |
+
GITHUB_TOKEN: ${{ secrets.GB_TOKEN }}
|
| 63 |
+
with:
|
| 64 |
+
# tag_name: 使用 tag
|
| 65 |
+
tag_name: ${{ github.ref }}
|
| 66 |
+
# release_name: 使用 tag
|
| 67 |
+
name: ${{ steps.grn.outputs.tag }}
|
| 68 |
+
# body: 使用 changelog
|
| 69 |
+
body_path: CHANGELOG.md
|
| 70 |
+
# 草稿
|
| 71 |
+
draft: false
|
| 72 |
+
# 预发布
|
| 73 |
+
prerelease: false
|
| 74 |
+
# 自动生成 release notes
|
| 75 |
+
generate_release_notes: true
|
| 76 |
+
# 上传文件
|
| 77 |
+
files: |
|
| 78 |
+
${{ env.APP_NAME }}-linux-amd64.tar.gz
|
| 79 |
+
${{ env.APP_NAME }}-windows-amd64.tar.gz
|
| 80 |
+
${{ env.APP_NAME }}-darwin-amd64.tar.gz
|
| 81 |
+
${{ env.APP_NAME }}-freebsd-amd64.tar.gz
|
| 82 |
+
|
| 83 |
+
- name: Delete Workflow Runs
|
| 84 |
+
uses: Mattraks/delete-workflow-runs@v2
|
| 85 |
+
with:
|
| 86 |
+
token: ${{ secrets.GB_TOKEN }}
|
| 87 |
+
repository: ${{ github.repository }}
|
| 88 |
+
retain_days: 1
|
| 89 |
+
keep_minimum_runs: 8
|
.github/workflows/Build Docker Image.yml
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
name: Build Docker Image
|
| 2 |
+
|
| 3 |
+
on:
|
| 4 |
+
push:
|
| 5 |
+
tags:
|
| 6 |
+
- 'release-v*'
|
| 7 |
+
workflow_dispatch:
|
| 8 |
+
|
| 9 |
+
env:
|
| 10 |
+
GHCR_REPO: ghcr.io/aurorax-neo/free-gpt3.5-2api
|
| 11 |
+
|
| 12 |
+
jobs:
|
| 13 |
+
main:
|
| 14 |
+
runs-on: ubuntu-latest
|
| 15 |
+
steps:
|
| 16 |
+
- name: Checkout
|
| 17 |
+
uses: actions/checkout@v4
|
| 18 |
+
with:
|
| 19 |
+
fetch-depth: 0
|
| 20 |
+
|
| 21 |
+
- name: Get Docker Image Tag
|
| 22 |
+
shell: bash
|
| 23 |
+
id: get_docker_image_tag
|
| 24 |
+
run: echo "tag=$(echo $GITHUB_REF | sed 's|refs/tags/release-v||')" >> $GITHUB_OUTPUT
|
| 25 |
+
|
| 26 |
+
- name: Set Up QEMU
|
| 27 |
+
uses: docker/setup-qemu-action@v3
|
| 28 |
+
|
| 29 |
+
- name: Set Up Docker Buildx
|
| 30 |
+
uses: docker/setup-buildx-action@v3
|
| 31 |
+
|
| 32 |
+
- name: Login To GitHub Container Registry
|
| 33 |
+
uses: docker/login-action@v3
|
| 34 |
+
with:
|
| 35 |
+
registry: ghcr.io
|
| 36 |
+
username: ${{ github.repository_owner }}
|
| 37 |
+
password: ${{ secrets.GB_TOKEN }}
|
| 38 |
+
|
| 39 |
+
- name: Cache Docker Layers
|
| 40 |
+
uses: actions/cache@v4
|
| 41 |
+
with:
|
| 42 |
+
path: /tmp/.buildx-cache
|
| 43 |
+
key: "${{ runner.os }}-buildx-${{ github.sha }}"
|
| 44 |
+
restore-keys: |
|
| 45 |
+
${{ runner.os }}-buildx-
|
| 46 |
+
|
| 47 |
+
- name: Build Docker Image And Push To GHCR
|
| 48 |
+
uses: docker/build-push-action@v5
|
| 49 |
+
with:
|
| 50 |
+
push: true
|
| 51 |
+
context: .
|
| 52 |
+
platforms: linux/amd64,linux/arm64
|
| 53 |
+
file: Dockerfile
|
| 54 |
+
tags: |
|
| 55 |
+
${{ env.GHCR_REPO }}:latest
|
| 56 |
+
${{ env.GHCR_REPO }}:${{ steps.get_docker_image_tag.outputs.tag }}
|
| 57 |
+
${{ env.GHCR_REPO }}:${{ github.sha }}
|
| 58 |
+
cache-from: type=local,src=/tmp/.buildx-cache
|
| 59 |
+
cache-to: type=local,dest=/tmp/.buildx-cache,mode=max
|
| 60 |
+
|
| 61 |
+
- name: Delete Workflow Runs
|
| 62 |
+
uses: Mattraks/delete-workflow-runs@v2
|
| 63 |
+
with:
|
| 64 |
+
token: ${{ secrets.GB_TOKEN }}
|
| 65 |
+
repository: ${{ github.repository }}
|
| 66 |
+
retain_days: 1
|
| 67 |
+
keep_minimum_runs: 8
|
.gitignore
CHANGED
|
@@ -1,15 +1,185 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
.
|
| 11 |
-
|
| 12 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 13 |
/logs/
|
|
|
|
| 14 |
/target/
|
| 15 |
-
/
|
|
|
|
| 1 |
+
### JetBrains template
|
| 2 |
+
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
|
| 3 |
+
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
|
| 4 |
+
|
| 5 |
+
# User-specific stuff
|
| 6 |
+
.idea/**/workspace.xml
|
| 7 |
+
.idea/**/tasks.xml
|
| 8 |
+
.idea/**/usage.statistics.xml
|
| 9 |
+
.idea/**/dictionaries
|
| 10 |
+
.idea/**/shelf
|
| 11 |
+
|
| 12 |
+
# AWS User-specific
|
| 13 |
+
.idea/**/aws.xml
|
| 14 |
+
|
| 15 |
+
# Generated files
|
| 16 |
+
.idea/**/contentModel.xml
|
| 17 |
+
|
| 18 |
+
# Sensitive or high-churn files
|
| 19 |
+
.idea/**/dataSources/
|
| 20 |
+
.idea/**/dataSources.ids
|
| 21 |
+
.idea/**/dataSources.local.xml
|
| 22 |
+
.idea/**/sqlDataSources.xml
|
| 23 |
+
.idea/**/dynamic.xml
|
| 24 |
+
.idea/**/uiDesigner.xml
|
| 25 |
+
.idea/**/dbnavigator.xml
|
| 26 |
+
|
| 27 |
+
# Gradle
|
| 28 |
+
.idea/**/gradle.xml
|
| 29 |
+
.idea/**/libraries
|
| 30 |
+
|
| 31 |
+
# Gradle and Maven with auto-import
|
| 32 |
+
# When using Gradle or Maven with auto-import, you should exclude module files,
|
| 33 |
+
# since they will be recreated, and may cause churn. Uncomment if using
|
| 34 |
+
# auto-import.
|
| 35 |
+
# .idea/artifacts
|
| 36 |
+
# .idea/compiler.xml
|
| 37 |
+
# .idea/jarRepositories.xml
|
| 38 |
+
# .idea/modules.xml
|
| 39 |
+
# .idea/*.iml
|
| 40 |
+
# .idea/modules
|
| 41 |
+
# *.iml
|
| 42 |
+
# *.ipr
|
| 43 |
+
|
| 44 |
+
# CMake
|
| 45 |
+
cmake-build-*/
|
| 46 |
+
|
| 47 |
+
# Mongo Explorer plugin
|
| 48 |
+
.idea/**/mongoSettings.xml
|
| 49 |
+
|
| 50 |
+
# File-based project format
|
| 51 |
+
*.iws
|
| 52 |
+
|
| 53 |
+
# IntelliJ
|
| 54 |
+
out/
|
| 55 |
+
|
| 56 |
+
# mpeltonen/sbt-idea plugin
|
| 57 |
+
.idea_modules/
|
| 58 |
+
|
| 59 |
+
# JIRA plugin
|
| 60 |
+
atlassian-ide-plugin.xml
|
| 61 |
+
|
| 62 |
+
# Cursive Clojure plugin
|
| 63 |
+
.idea/replstate.xml
|
| 64 |
+
|
| 65 |
+
# SonarLint plugin
|
| 66 |
+
.idea/sonarlint/
|
| 67 |
+
|
| 68 |
+
# Crashlytics plugin (for Android Studio and IntelliJ)
|
| 69 |
+
com_crashlytics_export_strings.xml
|
| 70 |
+
crashlytics.properties
|
| 71 |
+
crashlytics-build.properties
|
| 72 |
+
fabric.properties
|
| 73 |
+
|
| 74 |
+
# Editor-based Rest Client
|
| 75 |
+
.idea/httpRequests
|
| 76 |
+
|
| 77 |
+
# Android studio 3.1+ serialized cache file
|
| 78 |
+
.idea/caches/build_file_checksums.ser
|
| 79 |
+
|
| 80 |
+
### Go template
|
| 81 |
+
# If you prefer the allow list template instead of the deny list, see community template:
|
| 82 |
+
# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore
|
| 83 |
+
#
|
| 84 |
+
# Binaries for programs and plugins
|
| 85 |
+
*.exe
|
| 86 |
+
*.exe~
|
| 87 |
+
*.dll
|
| 88 |
+
*.so
|
| 89 |
+
*.dylib
|
| 90 |
+
|
| 91 |
+
# Test binary, built with `go test -c`
|
| 92 |
+
*.test
|
| 93 |
+
|
| 94 |
+
# Output of the go coverage tool, specifically when used with LiteIDE
|
| 95 |
+
*.out
|
| 96 |
+
|
| 97 |
+
# Dependency directories (remove the comment below to include it)
|
| 98 |
+
# vendor/
|
| 99 |
+
|
| 100 |
+
# Go workspace file
|
| 101 |
+
go.work
|
| 102 |
+
|
| 103 |
+
### GoLand template
|
| 104 |
+
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
|
| 105 |
+
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
|
| 106 |
+
|
| 107 |
+
# User-specific stuff
|
| 108 |
+
.idea/**/workspace.xml
|
| 109 |
+
.idea/**/tasks.xml
|
| 110 |
+
.idea/**/usage.statistics.xml
|
| 111 |
+
.idea/**/dictionaries
|
| 112 |
+
.idea/**/shelf
|
| 113 |
+
|
| 114 |
+
# AWS User-specific
|
| 115 |
+
.idea/**/aws.xml
|
| 116 |
+
|
| 117 |
+
# Generated files
|
| 118 |
+
.idea/**/contentModel.xml
|
| 119 |
+
|
| 120 |
+
# Sensitive or high-churn files
|
| 121 |
+
.idea/**/dataSources/
|
| 122 |
+
.idea/**/dataSources.ids
|
| 123 |
+
.idea/**/dataSources.local.xml
|
| 124 |
+
.idea/**/sqlDataSources.xml
|
| 125 |
+
.idea/**/dynamic.xml
|
| 126 |
+
.idea/**/uiDesigner.xml
|
| 127 |
+
.idea/**/dbnavigator.xml
|
| 128 |
+
|
| 129 |
+
# Gradle
|
| 130 |
+
.idea/**/gradle.xml
|
| 131 |
+
.idea/**/libraries
|
| 132 |
+
|
| 133 |
+
# Gradle and Maven with auto-import
|
| 134 |
+
# When using Gradle or Maven with auto-import, you should exclude module files,
|
| 135 |
+
# since they will be recreated, and may cause churn. Uncomment if using
|
| 136 |
+
# auto-import.
|
| 137 |
+
# .idea/artifacts
|
| 138 |
+
# .idea/compiler.xml
|
| 139 |
+
# .idea/jarRepositories.xml
|
| 140 |
+
# .idea/modules.xml
|
| 141 |
+
# .idea/*.iml
|
| 142 |
+
# .idea/modules
|
| 143 |
+
# *.iml
|
| 144 |
+
# *.ipr
|
| 145 |
+
|
| 146 |
+
# CMake
|
| 147 |
+
cmake-build-*/
|
| 148 |
+
|
| 149 |
+
# Mongo Explorer plugin
|
| 150 |
+
.idea/**/mongoSettings.xml
|
| 151 |
+
|
| 152 |
+
# File-based project format
|
| 153 |
+
*.iws
|
| 154 |
+
|
| 155 |
+
# IntelliJ
|
| 156 |
+
out/
|
| 157 |
+
|
| 158 |
+
# mpeltonen/sbt-idea plugin
|
| 159 |
+
.idea_modules/
|
| 160 |
+
|
| 161 |
+
# JIRA plugin
|
| 162 |
+
atlassian-ide-plugin.xml
|
| 163 |
+
|
| 164 |
+
# Cursive Clojure plugin
|
| 165 |
+
.idea/replstate.xml
|
| 166 |
+
|
| 167 |
+
# SonarLint plugin
|
| 168 |
+
.idea/sonarlint/
|
| 169 |
+
|
| 170 |
+
# Crashlytics plugin (for Android Studio and IntelliJ)
|
| 171 |
+
com_crashlytics_export_strings.xml
|
| 172 |
+
crashlytics.properties
|
| 173 |
+
crashlytics-build.properties
|
| 174 |
+
fabric.properties
|
| 175 |
+
|
| 176 |
+
# Editor-based Rest Client
|
| 177 |
+
.idea/httpRequests
|
| 178 |
+
|
| 179 |
+
# Android studio 3.1+ serialized cache file
|
| 180 |
+
.idea/caches/build_file_checksums.ser
|
| 181 |
+
|
| 182 |
/logs/
|
| 183 |
+
/.env
|
| 184 |
/target/
|
| 185 |
+
/CHANGELOG.md
|
Dockerfile
CHANGED
|
@@ -1,30 +1,21 @@
|
|
| 1 |
-
# 使用 Go 1.21 官方镜像作为构建环境
|
| 2 |
FROM golang:1.21 AS builder
|
| 3 |
|
| 4 |
-
# 禁用 CGO
|
| 5 |
ENV CGO_ENABLED=0
|
| 6 |
|
| 7 |
-
# 设置工作目录
|
| 8 |
WORKDIR /app
|
| 9 |
|
| 10 |
-
# 复制 go.mod 和 go.sum 并下载依赖
|
| 11 |
COPY go.mod go.sum ./
|
| 12 |
RUN go mod download
|
| 13 |
|
| 14 |
-
# 复制源代码并构建应用
|
| 15 |
COPY . .
|
| 16 |
-
RUN go build -
|
| 17 |
|
| 18 |
-
# 使用 Alpine Linux 作为最终镜像
|
| 19 |
FROM alpine:latest
|
| 20 |
|
| 21 |
-
# 设置工作目录
|
| 22 |
WORKDIR /app
|
| 23 |
|
| 24 |
-
|
| 25 |
-
COPY --from=builder /app/duck2api /app/duck2api
|
| 26 |
|
| 27 |
-
|
| 28 |
-
EXPOSE 8080
|
| 29 |
|
| 30 |
-
CMD ["
|
|
|
|
|
|
|
| 1 |
FROM golang:1.21 AS builder
|
| 2 |
|
|
|
|
| 3 |
ENV CGO_ENABLED=0
|
| 4 |
|
|
|
|
| 5 |
WORKDIR /app
|
| 6 |
|
|
|
|
| 7 |
COPY go.mod go.sum ./
|
| 8 |
RUN go mod download
|
| 9 |
|
|
|
|
| 10 |
COPY . .
|
| 11 |
+
RUN go build -o /app/free-gpt3.5-2api .
|
| 12 |
|
|
|
|
| 13 |
FROM alpine:latest
|
| 14 |
|
|
|
|
| 15 |
WORKDIR /app
|
| 16 |
|
| 17 |
+
COPY --from=builder /app/free-gpt3.5-2api /app/free-gpt3.5-2api
|
|
|
|
| 18 |
|
| 19 |
+
EXPOSE 3040
|
|
|
|
| 20 |
|
| 21 |
+
CMD [ "./free-gpt3.5-2api" ]
|
FreeGpt35/FreeGpt35.go
ADDED
|
@@ -0,0 +1,231 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package FreeGpt35
|
| 2 |
+
|
| 3 |
+
import (
|
| 4 |
+
"encoding/json"
|
| 5 |
+
"fmt"
|
| 6 |
+
ProofWork2 "free-gpt3.5-2api/ProofWork"
|
| 7 |
+
"free-gpt3.5-2api/ProxyPool"
|
| 8 |
+
"free-gpt3.5-2api/RequestClient"
|
| 9 |
+
"free-gpt3.5-2api/common"
|
| 10 |
+
"free-gpt3.5-2api/config"
|
| 11 |
+
"free-gpt3.5-2api/constant"
|
| 12 |
+
"github.com/aurorax-neo/go-logger"
|
| 13 |
+
fhttp "github.com/bogdanfinn/fhttp"
|
| 14 |
+
"github.com/google/uuid"
|
| 15 |
+
"io"
|
| 16 |
+
)
|
| 17 |
+
|
| 18 |
+
var (
|
| 19 |
+
BaseUrl = config.BaseUrl
|
| 20 |
+
ChatUrl = BaseUrl + "/backend-anon/conversation"
|
| 21 |
+
AuthUrl = BaseUrl + "/backend-anon/sentinel/chat-requirements"
|
| 22 |
+
OfficialBaseURLS = []string{"https://chat.openai.com", "https://chatgpt.com"}
|
| 23 |
+
)
|
| 24 |
+
|
| 25 |
+
// NewFreeAuthType 定义一个枚举类型
|
| 26 |
+
type NewFreeAuthType int
|
| 27 |
+
|
| 28 |
+
const (
|
| 29 |
+
NewFreeAuthNormal NewFreeAuthType = 0 //正常获取
|
| 30 |
+
NewFreeAuthRefresh NewFreeAuthType = 1 // 刷新获取
|
| 31 |
+
)
|
| 32 |
+
|
| 33 |
+
type FreeGpt35 struct {
|
| 34 |
+
RequestClient RequestClient.RequestClient
|
| 35 |
+
Proxy *ProxyPool.Proxy
|
| 36 |
+
MaxUseCount int
|
| 37 |
+
ExpiresAt int64
|
| 38 |
+
FreeAuth *freeAuth
|
| 39 |
+
Ua string
|
| 40 |
+
Cookies []*fhttp.Cookie
|
| 41 |
+
}
|
| 42 |
+
|
| 43 |
+
type freeAuth struct {
|
| 44 |
+
OaiDeviceId string `json:"-"`
|
| 45 |
+
Persona string `json:"persona"`
|
| 46 |
+
Arkose arkose `json:"arkose"`
|
| 47 |
+
Turnstile turnstile `json:"turnstile"`
|
| 48 |
+
ProofWork ProofWork2.ProofWork `json:"proofofwork"`
|
| 49 |
+
Token string `json:"token"`
|
| 50 |
+
}
|
| 51 |
+
|
| 52 |
+
type arkose struct {
|
| 53 |
+
Required bool `json:"required"`
|
| 54 |
+
Dx string `json:"dx"`
|
| 55 |
+
}
|
| 56 |
+
|
| 57 |
+
type turnstile struct {
|
| 58 |
+
Required bool `json:"required"`
|
| 59 |
+
}
|
| 60 |
+
|
| 61 |
+
// NewFreeGpt35 创建 FreeGpt35 实例 0 无论网络是否被标记限制都获取 1 在网络未标记时才能获取
|
| 62 |
+
func NewFreeGpt35(newType NewFreeAuthType, maxUseCount int, expiresAt int64) *FreeGpt35 {
|
| 63 |
+
// 创建 FreeGpt35 实例
|
| 64 |
+
freeGpt35 := &FreeGpt35{
|
| 65 |
+
MaxUseCount: maxUseCount,
|
| 66 |
+
ExpiresAt: expiresAt,
|
| 67 |
+
FreeAuth: &freeAuth{},
|
| 68 |
+
}
|
| 69 |
+
// 获取请求客户端
|
| 70 |
+
err := freeGpt35.newRequestClient()
|
| 71 |
+
if err != nil {
|
| 72 |
+
logger.Logger.Debug(err.Error())
|
| 73 |
+
return nil
|
| 74 |
+
}
|
| 75 |
+
// 获取并设置代理
|
| 76 |
+
err = freeGpt35.getProxy(newType)
|
| 77 |
+
if err != nil {
|
| 78 |
+
logger.Logger.Debug(err.Error())
|
| 79 |
+
return nil
|
| 80 |
+
}
|
| 81 |
+
// 获取cookies
|
| 82 |
+
if common.IsStrInArray(BaseUrl, OfficialBaseURLS) {
|
| 83 |
+
err = freeGpt35.getCookies()
|
| 84 |
+
if err != nil {
|
| 85 |
+
logger.Logger.Debug(err.Error())
|
| 86 |
+
return nil
|
| 87 |
+
}
|
| 88 |
+
}
|
| 89 |
+
// 获取 FreeAuth
|
| 90 |
+
err = freeGpt35.newFreeAuth(newType)
|
| 91 |
+
if err != nil {
|
| 92 |
+
logger.Logger.Debug(err.Error())
|
| 93 |
+
return nil
|
| 94 |
+
}
|
| 95 |
+
return freeGpt35
|
| 96 |
+
}
|
| 97 |
+
|
| 98 |
+
func (FG *FreeGpt35) NewRequest(method, url string, body io.Reader) (*fhttp.Request, error) {
|
| 99 |
+
request, err := RequestClient.NewRequest(method, url, body)
|
| 100 |
+
if err != nil {
|
| 101 |
+
return nil, err
|
| 102 |
+
}
|
| 103 |
+
request.Header.Set("accept", "*/*")
|
| 104 |
+
request.Header.Set("accept-language", "zh-CN,zh;q=0.9,zh-Hans;q=0.8,en;q=0.7")
|
| 105 |
+
for _, cookie := range FG.Cookies {
|
| 106 |
+
request.AddCookie(cookie)
|
| 107 |
+
}
|
| 108 |
+
request.Header.Set("oai-language", "en-US")
|
| 109 |
+
request.Header.Set("origin", common.GetOrigin(url))
|
| 110 |
+
request.Header.Set("referer", common.GetOrigin(url))
|
| 111 |
+
request.Header.Set("sec-ch-ua", `"Microsoft Edge";v="123", "Not:A-Brand";v="8", "Chromium";v="123"`)
|
| 112 |
+
request.Header.Set("sec-ch-ua-mobile", "?0")
|
| 113 |
+
request.Header.Set("sec-ch-ua-platform", `"Windows"`)
|
| 114 |
+
request.Header.Set("sec-fetch-dest", "empty")
|
| 115 |
+
request.Header.Set("sec-fetch-mode", "cors")
|
| 116 |
+
request.Header.Set("sec-fetch-site", "same-origin")
|
| 117 |
+
request.Header.Set("user-agent", FG.Ua)
|
| 118 |
+
return request, nil
|
| 119 |
+
}
|
| 120 |
+
|
| 121 |
+
func (FG *FreeGpt35) newRequestClient() error {
|
| 122 |
+
// 请求客户端
|
| 123 |
+
FG.RequestClient = RequestClient.NewTlsClient(300, constant.ClientProfile)
|
| 124 |
+
if FG.RequestClient == nil {
|
| 125 |
+
errStr := fmt.Sprint("RequestClient is nil")
|
| 126 |
+
logger.Logger.Debug(errStr)
|
| 127 |
+
return fmt.Errorf(errStr)
|
| 128 |
+
}
|
| 129 |
+
return nil
|
| 130 |
+
}
|
| 131 |
+
|
| 132 |
+
func (FG *FreeGpt35) getProxy(newFreeAuthType NewFreeAuthType) error {
|
| 133 |
+
// 获取代理池
|
| 134 |
+
ProxyPoolInstance := ProxyPool.GetProxyPoolInstance()
|
| 135 |
+
// 获取代理
|
| 136 |
+
FG.Proxy = ProxyPoolInstance.GetProxy()
|
| 137 |
+
// 判断代理是否可用
|
| 138 |
+
if FG.Proxy.CanUseAt > common.GetTimestampSecond(0) && newFreeAuthType == NewFreeAuthRefresh {
|
| 139 |
+
errStr := fmt.Sprint(FG.Proxy.Link, ": Proxy restricted, Reuse at ", FG.Proxy.CanUseAt)
|
| 140 |
+
return fmt.Errorf(errStr)
|
| 141 |
+
}
|
| 142 |
+
// Ua
|
| 143 |
+
FG.Ua = FG.Proxy.Ua
|
| 144 |
+
// 补全cookies
|
| 145 |
+
FG.Cookies = append(FG.Cookies, FG.Proxy.Cookies...)
|
| 146 |
+
// 设置代理
|
| 147 |
+
err := FG.RequestClient.SetProxy(FG.Proxy.Link.String())
|
| 148 |
+
if err != nil {
|
| 149 |
+
errStr := fmt.Sprint("SetProxy Error: ", err)
|
| 150 |
+
logger.Logger.Debug(errStr)
|
| 151 |
+
}
|
| 152 |
+
return nil
|
| 153 |
+
}
|
| 154 |
+
|
| 155 |
+
func (FG *FreeGpt35) getCookies() error {
|
| 156 |
+
// 获取cookies
|
| 157 |
+
request, err := FG.NewRequest("GET", fmt.Sprint(BaseUrl, "/?oai-dm=1"), nil)
|
| 158 |
+
if err != nil {
|
| 159 |
+
return err
|
| 160 |
+
}
|
| 161 |
+
// 设置请求头
|
| 162 |
+
request.Header.Set("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7")
|
| 163 |
+
// 发送 GET 请求
|
| 164 |
+
response, err := FG.RequestClient.Do(request)
|
| 165 |
+
if err != nil {
|
| 166 |
+
return err
|
| 167 |
+
}
|
| 168 |
+
defer func(Body io.ReadCloser) {
|
| 169 |
+
_ = Body.Close()
|
| 170 |
+
}(response.Body)
|
| 171 |
+
if response.StatusCode != 200 {
|
| 172 |
+
return fmt.Errorf("StatusCode: %d", response.StatusCode)
|
| 173 |
+
}
|
| 174 |
+
// 获取cookies
|
| 175 |
+
cookies := response.Cookies()
|
| 176 |
+
for i, cookie := range cookies {
|
| 177 |
+
if cookie.Name == "oai-did" {
|
| 178 |
+
FG.FreeAuth.OaiDeviceId = cookie.Value
|
| 179 |
+
cookies = append(cookies[:i], cookies[i+1:]...)
|
| 180 |
+
}
|
| 181 |
+
if cookie.Name == "__Secure-next-auth.callback-url" {
|
| 182 |
+
cookie.Value = BaseUrl
|
| 183 |
+
}
|
| 184 |
+
}
|
| 185 |
+
// 设置cookies
|
| 186 |
+
FG.Cookies = append(FG.Cookies, cookies...)
|
| 187 |
+
return nil
|
| 188 |
+
}
|
| 189 |
+
|
| 190 |
+
func (FG *FreeGpt35) newFreeAuth(newFreeAuthType NewFreeAuthType) error {
|
| 191 |
+
// 生成新的设备 ID
|
| 192 |
+
if FG.FreeAuth.OaiDeviceId == "" {
|
| 193 |
+
FG.FreeAuth.OaiDeviceId = uuid.New().String()
|
| 194 |
+
}
|
| 195 |
+
// 创建请求
|
| 196 |
+
request, err := FG.NewRequest("POST", AuthUrl, nil)
|
| 197 |
+
if err != nil {
|
| 198 |
+
return err
|
| 199 |
+
}
|
| 200 |
+
// 设置请求头
|
| 201 |
+
request.Header.Set("Content-Type", "application/json")
|
| 202 |
+
request.Header.Set("oai-device-id", FG.FreeAuth.OaiDeviceId)
|
| 203 |
+
// 发送 POST 请求
|
| 204 |
+
response, err := FG.RequestClient.Do(request)
|
| 205 |
+
if err != nil {
|
| 206 |
+
return err
|
| 207 |
+
}
|
| 208 |
+
if response.StatusCode != 200 {
|
| 209 |
+
logger.Logger.Debug(fmt.Sprint("newFreeAuth: StatusCode: ", response.StatusCode))
|
| 210 |
+
if (response.StatusCode == 429 || response.StatusCode == 403) && newFreeAuthType == NewFreeAuthRefresh {
|
| 211 |
+
FG.Proxy.CanUseAt = common.GetTimestampSecond(300)
|
| 212 |
+
logger.Logger.Debug(fmt.Sprint("newFreeAuth: Proxy(", FG.Proxy.Link, ")restricted, Reuse at ", FG.Proxy.CanUseAt))
|
| 213 |
+
}
|
| 214 |
+
return fmt.Errorf("StatusCode: %d", response.StatusCode)
|
| 215 |
+
} else if newFreeAuthType == 0 {
|
| 216 |
+
// 成功后更新代理的可用时间
|
| 217 |
+
FG.Proxy.CanUseAt = common.GetTimestampSecond(0)
|
| 218 |
+
logger.Logger.Debug(fmt.Sprint("newFreeAuth: Proxy(", FG.Proxy.Link, ")Reuse at ", FG.Proxy.CanUseAt))
|
| 219 |
+
}
|
| 220 |
+
defer func(Body io.ReadCloser) {
|
| 221 |
+
_ = Body.Close()
|
| 222 |
+
}(response.Body)
|
| 223 |
+
if err := json.NewDecoder(response.Body).Decode(&FG.FreeAuth); err != nil {
|
| 224 |
+
return err
|
| 225 |
+
}
|
| 226 |
+
// ProofWork
|
| 227 |
+
if FG.FreeAuth.ProofWork.Required {
|
| 228 |
+
FG.FreeAuth.ProofWork.Ospt = ProofWork2.CalcProofToken(FG.FreeAuth.ProofWork.Seed, FG.FreeAuth.ProofWork.Difficulty, request.Header.Get("User-Agent"))
|
| 229 |
+
}
|
| 230 |
+
return nil
|
| 231 |
+
}
|
FreeGpt35Pool/FreeGpt35Pool.go
ADDED
|
@@ -0,0 +1,128 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package FreeGpt35Pool
|
| 2 |
+
|
| 3 |
+
import (
|
| 4 |
+
"fmt"
|
| 5 |
+
"free-gpt3.5-2api/FreeGpt35"
|
| 6 |
+
"free-gpt3.5-2api/common"
|
| 7 |
+
"free-gpt3.5-2api/config"
|
| 8 |
+
"free-gpt3.5-2api/queue"
|
| 9 |
+
"github.com/aurorax-neo/go-logger"
|
| 10 |
+
"sync"
|
| 11 |
+
"time"
|
| 12 |
+
)
|
| 13 |
+
|
| 14 |
+
var (
|
| 15 |
+
instance *FreeGpt35Pool
|
| 16 |
+
once sync.Once
|
| 17 |
+
)
|
| 18 |
+
|
| 19 |
+
type FreeGpt35Pool struct {
|
| 20 |
+
queue *queue.Queue
|
| 21 |
+
capacity int // 队列容量
|
| 22 |
+
}
|
| 23 |
+
|
| 24 |
+
func newFreeGpt35Pool(capacity int) *FreeGpt35Pool {
|
| 25 |
+
return &FreeGpt35Pool{
|
| 26 |
+
queue: queue.New(),
|
| 27 |
+
capacity: capacity,
|
| 28 |
+
}
|
| 29 |
+
}
|
| 30 |
+
|
| 31 |
+
func GetFreeGpt35PoolInstance() *FreeGpt35Pool {
|
| 32 |
+
once.Do(func() {
|
| 33 |
+
logger.Logger.Info(fmt.Sprint("Init FreeGpt35Pool..."))
|
| 34 |
+
// 初始化 FreeGpt35Pool
|
| 35 |
+
instance = newFreeGpt35Pool(config.PoolMaxCount)
|
| 36 |
+
// 定时刷新 FreeGpt35Pool
|
| 37 |
+
instance.refreshFreeGpt35Pool(time.Millisecond * 256)
|
| 38 |
+
//
|
| 39 |
+
logger.Logger.Info(fmt.Sprint("Init FreeGpt35Pool Success", ", PoolMaxCount: ", config.PoolMaxCount, ", AuthExpirationDate: ", config.AuthED))
|
| 40 |
+
})
|
| 41 |
+
return instance
|
| 42 |
+
}
|
| 43 |
+
|
| 44 |
+
func (G *FreeGpt35Pool) refreshFreeGpt35Pool(sleep time.Duration) {
|
| 45 |
+
// 检测 FreeGpt35Pool 是否已满
|
| 46 |
+
common.AsyncLoopTask(sleep, func() {
|
| 47 |
+
// 判断 FreeGpt35Pool 是否已满
|
| 48 |
+
if G.IsFull() {
|
| 49 |
+
return
|
| 50 |
+
}
|
| 51 |
+
// 获取新 FreeGpt35 实例
|
| 52 |
+
gpt35 := FreeGpt35.NewFreeGpt35(FreeGpt35.NewFreeAuthRefresh, 1, common.GetTimestampSecond(config.AuthED))
|
| 53 |
+
// 判断 FreeGpt35 实例是否有效
|
| 54 |
+
if G.isLiveGpt35(gpt35) {
|
| 55 |
+
// 入队新 FreeGpt35 实例
|
| 56 |
+
G.AddFreeGpt35(gpt35)
|
| 57 |
+
}
|
| 58 |
+
})
|
| 59 |
+
// 检测并移除无效 FreeGpt35 实例
|
| 60 |
+
common.AsyncLoopTask(sleep, func() {
|
| 61 |
+
// 遍历队列中的所有元素
|
| 62 |
+
G.queue.Traverse(func(n *queue.Node) {
|
| 63 |
+
// 判断是否为无效 FreeGpt35 实例
|
| 64 |
+
if !G.isLiveGpt35(n.Value.(*FreeGpt35.FreeGpt35)) {
|
| 65 |
+
// 移除无效 FreeGpt35 实例
|
| 66 |
+
G.queue.Remove(n)
|
| 67 |
+
}
|
| 68 |
+
})
|
| 69 |
+
})
|
| 70 |
+
}
|
| 71 |
+
|
| 72 |
+
func (G *FreeGpt35Pool) isLiveGpt35(gpt35 *FreeGpt35.FreeGpt35) bool {
|
| 73 |
+
//判断是否为空
|
| 74 |
+
if gpt35 == nil ||
|
| 75 |
+
gpt35.MaxUseCount <= 0 || //无可用次数
|
| 76 |
+
gpt35.ExpiresAt <= common.GetTimestampSecond(0) {
|
| 77 |
+
return false
|
| 78 |
+
}
|
| 79 |
+
return true
|
| 80 |
+
}
|
| 81 |
+
|
| 82 |
+
func (G *FreeGpt35Pool) GetFreeGpt35(retry int) *FreeGpt35.FreeGpt35 {
|
| 83 |
+
// 获取 FreeGpt35 实例
|
| 84 |
+
n := G.queue.Peek()
|
| 85 |
+
if n != nil {
|
| 86 |
+
gpt35 := n.Value.(*FreeGpt35.FreeGpt35)
|
| 87 |
+
if G.isLiveGpt35(gpt35) { //有缓存
|
| 88 |
+
// 深拷贝
|
| 89 |
+
gpt35_ := common.DeepCopyStruct(gpt35).(*FreeGpt35.FreeGpt35)
|
| 90 |
+
// 减少 FreeGpt35 实例的最大使用次数
|
| 91 |
+
gpt35.MaxUseCount--
|
| 92 |
+
// 判断 FreeGpt35 实例是否有效 无效则移除
|
| 93 |
+
if !G.isLiveGpt35(gpt35) {
|
| 94 |
+
G.queue.Dequeue()
|
| 95 |
+
}
|
| 96 |
+
return gpt35_
|
| 97 |
+
} else if retry > 0 {
|
| 98 |
+
time.Sleep(time.Millisecond * 128)
|
| 99 |
+
return G.GetFreeGpt35(retry - 1)
|
| 100 |
+
}
|
| 101 |
+
}
|
| 102 |
+
// 缓存内无可用 FreeGpt35 实例,返回新 FreeGpt35 实例
|
| 103 |
+
return FreeGpt35.NewFreeGpt35(FreeGpt35.NewFreeAuthNormal, 1, common.GetTimestampSecond(config.AuthED))
|
| 104 |
+
}
|
| 105 |
+
|
| 106 |
+
// GetSize 获取队列当前元素个数
|
| 107 |
+
func (G *FreeGpt35Pool) GetSize() int {
|
| 108 |
+
return G.queue.Len()
|
| 109 |
+
}
|
| 110 |
+
|
| 111 |
+
// GetCapacity 获取队列容量
|
| 112 |
+
func (G *FreeGpt35Pool) GetCapacity() int {
|
| 113 |
+
return G.capacity
|
| 114 |
+
}
|
| 115 |
+
|
| 116 |
+
// IsFull 检查队列是否已满
|
| 117 |
+
func (G *FreeGpt35Pool) IsFull() bool {
|
| 118 |
+
return G.GetSize() == G.capacity
|
| 119 |
+
}
|
| 120 |
+
|
| 121 |
+
// AddFreeGpt35 入队
|
| 122 |
+
func (G *FreeGpt35Pool) AddFreeGpt35(v *FreeGpt35.FreeGpt35) bool {
|
| 123 |
+
if G.IsFull() || v == nil {
|
| 124 |
+
return false
|
| 125 |
+
}
|
| 126 |
+
G.queue.Enqueue(v)
|
| 127 |
+
return true
|
| 128 |
+
}
|
LICENSE
DELETED
|
@@ -1,21 +0,0 @@
|
|
| 1 |
-
MIT License
|
| 2 |
-
|
| 3 |
-
Copyright (c) 2024 aurora-develop
|
| 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.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Procfile
DELETED
|
@@ -1 +0,0 @@
|
|
| 1 |
-
web: aurora
|
|
|
|
|
|
ProofWork/ProofWork.go
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package ProofWork
|
| 2 |
+
|
| 3 |
+
import (
|
| 4 |
+
"encoding/base64"
|
| 5 |
+
"encoding/hex"
|
| 6 |
+
"encoding/json"
|
| 7 |
+
"golang.org/x/crypto/sha3"
|
| 8 |
+
"math/rand"
|
| 9 |
+
"time"
|
| 10 |
+
)
|
| 11 |
+
|
| 12 |
+
var (
|
| 13 |
+
numberCollisions = 100000
|
| 14 |
+
cores = []int{8, 12, 16, 24}
|
| 15 |
+
screens = []int{3000, 4000, 6000}
|
| 16 |
+
timeLayout = "Mon Jan 2 2006 15:04:05"
|
| 17 |
+
)
|
| 18 |
+
|
| 19 |
+
type ProofWork struct {
|
| 20 |
+
Difficulty string `json:"difficulty,omitempty"`
|
| 21 |
+
Required bool `json:"required"`
|
| 22 |
+
Seed string `json:"seed,omitempty"`
|
| 23 |
+
Ospt string `json:"-"`
|
| 24 |
+
}
|
| 25 |
+
|
| 26 |
+
func getParseTime() string {
|
| 27 |
+
now := time.Now()
|
| 28 |
+
return now.Format(timeLayout) + " GMT" + now.Format("-0700 MST (MST)")
|
| 29 |
+
}
|
| 30 |
+
|
| 31 |
+
func getConfig(userAgent string) []interface{} {
|
| 32 |
+
rand.New(rand.NewSource(time.Now().UnixNano()))
|
| 33 |
+
core := cores[rand.Intn(4)]
|
| 34 |
+
rand.New(rand.NewSource(time.Now().UnixNano()))
|
| 35 |
+
screen := screens[rand.Intn(3)]
|
| 36 |
+
return []interface{}{core + screen, getParseTime(), int64(4294705152), 0, userAgent}
|
| 37 |
+
|
| 38 |
+
}
|
| 39 |
+
|
| 40 |
+
func CalcProofToken(seed string, diff string, userAgent string) string {
|
| 41 |
+
config := getConfig(userAgent)
|
| 42 |
+
hasher := sha3.New512()
|
| 43 |
+
for i := 0; i < numberCollisions; i++ {
|
| 44 |
+
config[3] = i
|
| 45 |
+
jsonStr, _ := json.Marshal(config)
|
| 46 |
+
base := base64.StdEncoding.EncodeToString(jsonStr)
|
| 47 |
+
hasher.Write([]byte(seed + base))
|
| 48 |
+
hash := hasher.Sum(nil)
|
| 49 |
+
hasher.Reset()
|
| 50 |
+
if hex.EncodeToString(hash[:len(diff)]) <= diff {
|
| 51 |
+
return "gAAAAAB" + base
|
| 52 |
+
}
|
| 53 |
+
}
|
| 54 |
+
return "gAAAAABwQ8Lk5FbGpA2NcR9dShT6gYjU7VxZ4D" + base64.StdEncoding.EncodeToString([]byte(`"`+seed+`"`))
|
| 55 |
+
}
|
ProxyPool/ProxyPool.go
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package ProxyPool
|
| 2 |
+
|
| 3 |
+
import (
|
| 4 |
+
"fmt"
|
| 5 |
+
"free-gpt3.5-2api/common"
|
| 6 |
+
"free-gpt3.5-2api/config"
|
| 7 |
+
"free-gpt3.5-2api/constant"
|
| 8 |
+
"github.com/aurorax-neo/go-logger"
|
| 9 |
+
fhttp "github.com/bogdanfinn/fhttp"
|
| 10 |
+
"net/url"
|
| 11 |
+
"sync"
|
| 12 |
+
"time"
|
| 13 |
+
)
|
| 14 |
+
|
| 15 |
+
var (
|
| 16 |
+
Instance *ProxyPool
|
| 17 |
+
Once sync.Once
|
| 18 |
+
)
|
| 19 |
+
|
| 20 |
+
type ProxyPool struct {
|
| 21 |
+
Proxies []*Proxy
|
| 22 |
+
Index int
|
| 23 |
+
}
|
| 24 |
+
|
| 25 |
+
type Proxy struct {
|
| 26 |
+
Link *url.URL
|
| 27 |
+
CanUseAt int64
|
| 28 |
+
Ua string
|
| 29 |
+
Cookies []*fhttp.Cookie
|
| 30 |
+
}
|
| 31 |
+
|
| 32 |
+
func GetProxyPoolInstance() *ProxyPool {
|
| 33 |
+
Once.Do(func() {
|
| 34 |
+
logger.Logger.Info(fmt.Sprint("Init ProxyPool..."))
|
| 35 |
+
// 初始化 ProxyPool
|
| 36 |
+
Instance = NewProxyPool(nil)
|
| 37 |
+
// 遍历配置文件中的代理 添加到代理池
|
| 38 |
+
for _, px := range config.Proxy {
|
| 39 |
+
proxy := NewProxy(px, common.GetTimestampSecond(0), constant.Ua)
|
| 40 |
+
_ = proxy.getCookies()
|
| 41 |
+
Instance.AddProxy(proxy)
|
| 42 |
+
}
|
| 43 |
+
//定时刷新代理cookies
|
| 44 |
+
common.AsyncLoopTask(1*time.Minute, func() {
|
| 45 |
+
for _, proxy := range Instance.Proxies {
|
| 46 |
+
_ = proxy.getCookies()
|
| 47 |
+
}
|
| 48 |
+
})
|
| 49 |
+
logger.Logger.Info(fmt.Sprint("Init ProxyPool Success"))
|
| 50 |
+
})
|
| 51 |
+
return Instance
|
| 52 |
+
}
|
| 53 |
+
|
| 54 |
+
func NewProxyPool(proxies []*Proxy) *ProxyPool {
|
| 55 |
+
proxy := NewProxy("", common.GetTimestampSecond(0), constant.Ua)
|
| 56 |
+
_ = proxy.getCookies()
|
| 57 |
+
return &ProxyPool{
|
| 58 |
+
Proxies: append([]*Proxy{proxy}, proxies...),
|
| 59 |
+
Index: 0,
|
| 60 |
+
}
|
| 61 |
+
}
|
| 62 |
+
|
| 63 |
+
func (PP *ProxyPool) GetProxy() *Proxy {
|
| 64 |
+
PP.Index = (PP.Index + 1) % len(PP.Proxies)
|
| 65 |
+
// 如果配置了代理 不会使用无代理
|
| 66 |
+
if PP.Index == 0 && len(PP.Proxies) > 1 {
|
| 67 |
+
PP.Index = 1
|
| 68 |
+
}
|
| 69 |
+
// 返回代理
|
| 70 |
+
return PP.Proxies[PP.Index]
|
| 71 |
+
}
|
| 72 |
+
|
| 73 |
+
func (PP *ProxyPool) AddProxy(proxy *Proxy) {
|
| 74 |
+
PP.Proxies = append(PP.Proxies, proxy)
|
| 75 |
+
}
|
| 76 |
+
|
| 77 |
+
func NewProxy(link string, cannotUseTime int64, ua string) *Proxy {
|
| 78 |
+
return &Proxy{
|
| 79 |
+
Link: common.ParseUrl(link),
|
| 80 |
+
CanUseAt: cannotUseTime,
|
| 81 |
+
Ua: ua,
|
| 82 |
+
}
|
| 83 |
+
}
|
| 84 |
+
|
| 85 |
+
func (P *Proxy) getCookies() error {
|
| 86 |
+
return nil
|
| 87 |
+
}
|
README.md
CHANGED
|
@@ -1,90 +1,94 @@
|
|
| 1 |
-
#
|
| 2 |
|
|
|
|
| 3 |
|
|
|
|
| 4 |
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
访问http://你的服务器ip:8080/web
|
| 11 |
-
|
| 12 |
-

|
| 13 |
|
| 14 |
-
|
| 15 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 16 |
|
| 17 |
-
|
| 18 |
-
[](https://render.com/deploy)
|
| 19 |
|
| 20 |
-
|
| 21 |
|
| 22 |
-
```
|
| 23 |
-
|
| 24 |
-
cd duck2api
|
| 25 |
-
go build -o duck2api
|
| 26 |
-
chmod +x ./duck2api
|
| 27 |
-
./duck2api
|
| 28 |
```
|
| 29 |
|
| 30 |
-
|
| 31 |
-
## Docker部署
|
| 32 |
-
您需要安装Docker和Docker Compose。
|
| 33 |
|
| 34 |
-
```bash
|
| 35 |
-
docker run -d \
|
| 36 |
-
--name duck2api \
|
| 37 |
-
-p 8080:8080 \
|
| 38 |
-
ghcr.io/aurora-develop/duck2api:latest
|
| 39 |
```
|
| 40 |
-
|
| 41 |
-
## Docker Compose部署
|
| 42 |
-
创建一个新的目录,例如duck2api,并进入该目录:
|
| 43 |
-
```bash
|
| 44 |
-
mkdir duck2api
|
| 45 |
-
cd duck2api
|
| 46 |
```
|
| 47 |
-
在此目录中下载库中的docker-compose.yml文件:
|
| 48 |
|
| 49 |
-
```bash
|
| 50 |
-
docker-compose up -d
|
| 51 |
```
|
| 52 |
-
|
| 53 |
-
|
| 54 |
-
|
| 55 |
-
```bash
|
| 56 |
-
curl --location 'http://你的服务器ip:8080/v1/chat/completions' \
|
| 57 |
--header 'Content-Type: application/json' \
|
| 58 |
-
--data '{
|
| 59 |
-
|
| 60 |
-
|
| 61 |
-
|
| 62 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 63 |
```
|
| 64 |
-
支持claude和gpt-3.5-turbo
|
| 65 |
-
## 高级设置
|
| 66 |
|
| 67 |
-
|
| 68 |
|
| 69 |
### 环境变量
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 70 |
```
|
| 71 |
|
| 72 |
-
|
| 73 |
-
|
| 74 |
-
|
| 75 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 76 |
```
|
| 77 |
|
| 78 |
-
|
| 79 |
|
| 80 |
-
|
|
|
|
|
|
|
| 81 |
|
|
|
|
| 82 |
|
| 83 |
-
|
|
|
|
|
|
|
| 84 |
|
|
|
|
| 85 |
|
| 86 |
-
|
| 87 |
|
| 88 |
-
|
| 89 |
|
| 90 |
-
MIT License
|
|
|
|
| 1 |
+
# [free-gpt3.5-2api](https://github.com/aurorax-neo/free-gpt3.5-2api)
|
| 2 |
|
| 3 |
+
## 接口
|
| 4 |
|
| 5 |
+
#### /v1/tokens
|
| 6 |
|
| 7 |
+
```
|
| 8 |
+
curl --location --request GET 'http://127.0.0.1:9846/v1/tokens' \
|
| 9 |
+
--header 'Authorization: Bearer abc'
|
| 10 |
+
```
|
|
|
|
|
|
|
|
|
|
|
|
|
| 11 |
|
| 12 |
+
返回示例说明:`count`为授权池中可用授权数,如果`count` 为 `0`请检查`ip`是否支持 `openai`
|
| 13 |
|
| 14 |
+
```
|
| 15 |
+
{
|
| 16 |
+
"count": 0
|
| 17 |
+
}
|
| 18 |
+
```
|
| 19 |
|
| 20 |
+
#### /v1/chat/completions
|
|
|
|
| 21 |
|
| 22 |
+
###### 支持返回stream和json
|
| 23 |
|
| 24 |
+
```
|
| 25 |
+
http://<ip>:<port>/v1/chat/completions
|
|
|
|
|
|
|
|
|
|
|
|
|
| 26 |
```
|
| 27 |
|
| 28 |
+
##### 示例
|
|
|
|
|
|
|
| 29 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 30 |
```
|
| 31 |
+
curl http://127.0.0.1:9846
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 32 |
```
|
|
|
|
| 33 |
|
|
|
|
|
|
|
| 34 |
```
|
| 35 |
+
curl --location --request POST 'http://127.0.0.1:9846/v1/chat/completions' \
|
| 36 |
+
--header 'Authorization: Bearer abc' \
|
|
|
|
|
|
|
|
|
|
| 37 |
--header 'Content-Type: application/json' \
|
| 38 |
+
--data-raw '{
|
| 39 |
+
"model": "gpt-3.5-turbo",
|
| 40 |
+
"messages": [
|
| 41 |
+
{
|
| 42 |
+
"role": "user",
|
| 43 |
+
"content": "西红柿炒钢丝球怎么做?"
|
| 44 |
+
}
|
| 45 |
+
],
|
| 46 |
+
"stream": false
|
| 47 |
+
}'
|
| 48 |
```
|
|
|
|
|
|
|
| 49 |
|
| 50 |
+
## 配置
|
| 51 |
|
| 52 |
### 环境变量
|
| 53 |
+
|
| 54 |
+
```
|
| 55 |
+
LOG_LEVEL=info # debug, info, warn, error
|
| 56 |
+
LOG_PATH= # 日志文件路径,默认为空(不生成日志文件)
|
| 57 |
+
BIND=0.0.0.0 # 127.0.0.1
|
| 58 |
+
PORT=3040
|
| 59 |
+
PROXY= # http://127.0.0.1:7890,http://127.0.0.1:7890 已支持多个代理(英文 "," 分隔)
|
| 60 |
+
AUTHORIZATIONS= # abc,bac (英文 "," 分隔)
|
| 61 |
+
BASE_URL= # 默认:https://chat.openai.com
|
| 62 |
+
POOL_MAX_COUNT=64 # max number of connections to keep in the pool 默认:64
|
| 63 |
+
AUTH_ED=600 # expiration time for the authorization in seconds 默认:600
|
| 64 |
```
|
| 65 |
|
| 66 |
+
###### 也可使用与程序同目录下 `.env` 文件配置上述字段
|
| 67 |
+
|
| 68 |
+
|
| 69 |
+
### docker部署
|
| 70 |
+
|
| 71 |
+
##### 1 .创建文件夹
|
| 72 |
+
|
| 73 |
+
```
|
| 74 |
+
mkdir -p $PWD/free-gpt3.5-2api
|
| 75 |
```
|
| 76 |
|
| 77 |
+
##### 2.拉取镜像启动
|
| 78 |
|
| 79 |
+
```
|
| 80 |
+
docker run -itd --name=free-gpt3.5-2api -p 9846:3040 ghcr.io/aurorax-neo/free-gpt3.5-2api
|
| 81 |
+
```
|
| 82 |
|
| 83 |
+
##### 3.更新容器
|
| 84 |
|
| 85 |
+
```
|
| 86 |
+
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock containrrr/watchtower -cR free-gpt3.5-2api --debug
|
| 87 |
+
```
|
| 88 |
|
| 89 |
+
### Koyeb部署
|
| 90 |
|
| 91 |
+
###### 注意:`Regions`请选择支持`openai`免登的区域!!!
|
| 92 |
|
| 93 |
+
[](https://app.koyeb.com/deploy?type=docker&name=free-gpt3-5-2api®ion=par&ports=3040;http;/&image=ghcr.io/aurorax-neo/free-gpt3.5-2api)
|
| 94 |
|
|
|
RequestClient/RequestClient.go
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package RequestClient
|
| 2 |
+
|
| 3 |
+
import (
|
| 4 |
+
fhttp "github.com/bogdanfinn/fhttp"
|
| 5 |
+
)
|
| 6 |
+
|
| 7 |
+
type RequestClient interface {
|
| 8 |
+
Do(req *fhttp.Request) (*fhttp.Response, error)
|
| 9 |
+
SetProxy(link string) error
|
| 10 |
+
}
|
RequestClient/TlsClient.go
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package RequestClient
|
| 2 |
+
|
| 3 |
+
import (
|
| 4 |
+
fhttp "github.com/bogdanfinn/fhttp"
|
| 5 |
+
tlsClient "github.com/bogdanfinn/tls-client"
|
| 6 |
+
"github.com/bogdanfinn/tls-client/profiles"
|
| 7 |
+
"io"
|
| 8 |
+
"math/rand"
|
| 9 |
+
"time"
|
| 10 |
+
)
|
| 11 |
+
|
| 12 |
+
type TlsClient struct {
|
| 13 |
+
client tlsClient.HttpClient
|
| 14 |
+
}
|
| 15 |
+
|
| 16 |
+
func NewTlsClient(timeoutSeconds int, clientProfile profiles.ClientProfile) *TlsClient {
|
| 17 |
+
jar := tlsClient.NewCookieJar()
|
| 18 |
+
options := []tlsClient.HttpClientOption{
|
| 19 |
+
tlsClient.WithTimeoutSeconds(timeoutSeconds),
|
| 20 |
+
tlsClient.WithClientProfile(clientProfile),
|
| 21 |
+
tlsClient.WithNotFollowRedirects(),
|
| 22 |
+
tlsClient.WithCookieJar(jar),
|
| 23 |
+
}
|
| 24 |
+
client, err := tlsClient.NewHttpClient(tlsClient.NewNoopLogger(), options...)
|
| 25 |
+
if err != nil {
|
| 26 |
+
return nil
|
| 27 |
+
}
|
| 28 |
+
return &TlsClient{
|
| 29 |
+
client: client,
|
| 30 |
+
}
|
| 31 |
+
}
|
| 32 |
+
|
| 33 |
+
func RandomClientProfile() profiles.ClientProfile {
|
| 34 |
+
// 初始化随机数生成器
|
| 35 |
+
seed := time.Now().UnixNano()
|
| 36 |
+
rng := rand.New(rand.NewSource(seed))
|
| 37 |
+
clientProfiles := []profiles.ClientProfile{
|
| 38 |
+
profiles.Firefox_102,
|
| 39 |
+
profiles.Safari_15_6_1,
|
| 40 |
+
profiles.Safari_16_0,
|
| 41 |
+
profiles.Chrome_110,
|
| 42 |
+
profiles.Okhttp4Android13,
|
| 43 |
+
profiles.CloudflareCustom,
|
| 44 |
+
profiles.Firefox_117,
|
| 45 |
+
}
|
| 46 |
+
// 随机选择一个
|
| 47 |
+
randomIndex := rng.Intn(len(clientProfiles))
|
| 48 |
+
return clientProfiles[randomIndex]
|
| 49 |
+
}
|
| 50 |
+
|
| 51 |
+
func NewRequest(method, url string, body io.Reader) (*fhttp.Request, error) {
|
| 52 |
+
request, err := fhttp.NewRequest(method, url, body)
|
| 53 |
+
if err != nil {
|
| 54 |
+
return nil, err
|
| 55 |
+
}
|
| 56 |
+
return request, nil
|
| 57 |
+
|
| 58 |
+
}
|
| 59 |
+
|
| 60 |
+
func (T *TlsClient) Do(req *fhttp.Request) (*fhttp.Response, error) {
|
| 61 |
+
response, err := T.client.Do(req)
|
| 62 |
+
if err != nil {
|
| 63 |
+
return nil, err
|
| 64 |
+
}
|
| 65 |
+
return response, nil
|
| 66 |
+
}
|
| 67 |
+
|
| 68 |
+
func (T *TlsClient) SetProxy(link string) error {
|
| 69 |
+
if link == "" {
|
| 70 |
+
return nil
|
| 71 |
+
}
|
| 72 |
+
err := T.client.SetProxy(link)
|
| 73 |
+
if err != nil {
|
| 74 |
+
return err
|
| 75 |
+
}
|
| 76 |
+
return nil
|
| 77 |
+
}
|
VERSION
DELETED
|
@@ -1 +0,0 @@
|
|
| 1 |
-
2.0.0
|
|
|
|
|
|
api/router.go
DELETED
|
@@ -1,18 +0,0 @@
|
|
| 1 |
-
package api
|
| 2 |
-
|
| 3 |
-
import (
|
| 4 |
-
"aurora/initialize"
|
| 5 |
-
"github.com/gin-gonic/gin"
|
| 6 |
-
"net/http"
|
| 7 |
-
)
|
| 8 |
-
|
| 9 |
-
var router *gin.Engine
|
| 10 |
-
|
| 11 |
-
func init() {
|
| 12 |
-
// 初始化gin
|
| 13 |
-
router = initialize.RegisterRouter()
|
| 14 |
-
}
|
| 15 |
-
|
| 16 |
-
func Listen(w http.ResponseWriter, r *http.Request) {
|
| 17 |
-
router.ServeHTTP(w, r)
|
| 18 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
build.sh
DELETED
|
@@ -1,41 +0,0 @@
|
|
| 1 |
-
#!/bin/bash
|
| 2 |
-
|
| 3 |
-
export GOPROXY=https://goproxy.io
|
| 4 |
-
|
| 5 |
-
go get
|
| 6 |
-
|
| 7 |
-
export CGO_ENABLED=0
|
| 8 |
-
PKG=aurora
|
| 9 |
-
|
| 10 |
-
targets=(
|
| 11 |
-
"windows/amd64"
|
| 12 |
-
"linux/amd64"
|
| 13 |
-
"darwin/amd64"
|
| 14 |
-
"windows/386"
|
| 15 |
-
"linux/386"
|
| 16 |
-
"darwin/386"
|
| 17 |
-
"linux/arm"
|
| 18 |
-
"linux/arm64"
|
| 19 |
-
"linux/s390x"
|
| 20 |
-
)
|
| 21 |
-
|
| 22 |
-
upxPath=$(command -v upx)
|
| 23 |
-
|
| 24 |
-
for target in "${targets[@]}"; do
|
| 25 |
-
GOOS=${target%/*}
|
| 26 |
-
GOARCH=${target#*/}
|
| 27 |
-
outputDir="bin/${GOOS}_${GOARCH}"
|
| 28 |
-
outputFile="${outputDir}/${PKG}"
|
| 29 |
-
archiveName="${PKG}-${GOOS}-${GOARCH}.tar.gz"
|
| 30 |
-
mkdir -p $(dirname ${outputFile})
|
| 31 |
-
GOOS=$GOOS GOARCH=$GOARCH go build -ldflags="-s -w -extldflags '-static'" -o ${outputFile} *.go
|
| 32 |
-
if [ -n "$upxPath" ]; then
|
| 33 |
-
$upxPath -9 ${outputFile}
|
| 34 |
-
fi
|
| 35 |
-
# Archive the binary
|
| 36 |
-
if [ "$GOOS" = "windows" ]; then
|
| 37 |
-
zip -j "${outputDir}/${PKG}-${GOOS}-${GOARCH}.zip" "${outputFile}"
|
| 38 |
-
else
|
| 39 |
-
tar -C "${outputDir}" -czf "${outputDir}/${archiveName}" "${PKG}"
|
| 40 |
-
fi
|
| 41 |
-
done
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
common/common.go
ADDED
|
@@ -0,0 +1,285 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package common
|
| 2 |
+
|
| 3 |
+
import (
|
| 4 |
+
"bytes"
|
| 5 |
+
"encoding/json"
|
| 6 |
+
"fmt"
|
| 7 |
+
fhttp "github.com/bogdanfinn/fhttp"
|
| 8 |
+
"github.com/bogdanfinn/fhttp/httputil"
|
| 9 |
+
"github.com/gin-gonic/gin"
|
| 10 |
+
jsoniter "github.com/json-iterator/go"
|
| 11 |
+
"math/rand"
|
| 12 |
+
"net/url"
|
| 13 |
+
"os"
|
| 14 |
+
"path/filepath"
|
| 15 |
+
"reflect"
|
| 16 |
+
"strings"
|
| 17 |
+
"time"
|
| 18 |
+
)
|
| 19 |
+
|
| 20 |
+
func ErrorResponse(c *gin.Context, code int, msg interface{}, err interface{}) {
|
| 21 |
+
c.AbortWithStatusJSON(code, gin.H{
|
| 22 |
+
"detail": struct {
|
| 23 |
+
Code int `json:"code"`
|
| 24 |
+
Msg interface{} `json:"msg"`
|
| 25 |
+
Error interface{} `json:"error"`
|
| 26 |
+
}{
|
| 27 |
+
Code: code,
|
| 28 |
+
Msg: msg,
|
| 29 |
+
Error: err,
|
| 30 |
+
},
|
| 31 |
+
})
|
| 32 |
+
return
|
| 33 |
+
}
|
| 34 |
+
|
| 35 |
+
// GetTimestampSecond 获取当前时间戳 + 指定 秒
|
| 36 |
+
func GetTimestampSecond(second int) int64 {
|
| 37 |
+
return time.Now().Add(time.Second * time.Duration(second)).Unix()
|
| 38 |
+
}
|
| 39 |
+
|
| 40 |
+
func ParseUrl(link string) *url.URL {
|
| 41 |
+
if link == "" {
|
| 42 |
+
return &url.URL{}
|
| 43 |
+
}
|
| 44 |
+
u, err := url.Parse(link)
|
| 45 |
+
if err != nil {
|
| 46 |
+
return &url.URL{}
|
| 47 |
+
}
|
| 48 |
+
return u
|
| 49 |
+
}
|
| 50 |
+
|
| 51 |
+
func GetOrigin(link string) string {
|
| 52 |
+
u := ParseUrl(link)
|
| 53 |
+
if u == nil {
|
| 54 |
+
return ""
|
| 55 |
+
}
|
| 56 |
+
return u.Scheme + "://" + u.Host
|
| 57 |
+
}
|
| 58 |
+
|
| 59 |
+
func Struct2BytesBuffer(v interface{}) (*bytes.Buffer, error) {
|
| 60 |
+
data := new(bytes.Buffer)
|
| 61 |
+
err := json.NewEncoder(data).Encode(v)
|
| 62 |
+
if err != nil {
|
| 63 |
+
return nil, err
|
| 64 |
+
}
|
| 65 |
+
return data, nil
|
| 66 |
+
}
|
| 67 |
+
|
| 68 |
+
func Struct2Bytes(v interface{}) ([]byte, error) {
|
| 69 |
+
// 创建一个jsonIter的Encoder
|
| 70 |
+
configCompatibleWithStandardLibrary := jsoniter.ConfigCompatibleWithStandardLibrary
|
| 71 |
+
// 将结构体转换为JSON文本并保持顺序
|
| 72 |
+
bytes_, err := configCompatibleWithStandardLibrary.Marshal(v)
|
| 73 |
+
if err != nil {
|
| 74 |
+
return nil, err
|
| 75 |
+
}
|
| 76 |
+
return bytes_, nil
|
| 77 |
+
}
|
| 78 |
+
|
| 79 |
+
func SplitAndAddBearer(authTokens string) []string {
|
| 80 |
+
var authTokenList []string
|
| 81 |
+
for _, v := range strings.Split(authTokens, ",") {
|
| 82 |
+
authTokenList = append(authTokenList, "Bearer "+v)
|
| 83 |
+
}
|
| 84 |
+
return authTokenList
|
| 85 |
+
}
|
| 86 |
+
|
| 87 |
+
func GetRand() rand.Rand {
|
| 88 |
+
// 初始化随机数生成器
|
| 89 |
+
seed := time.Now().UnixNano()
|
| 90 |
+
rng := rand.New(rand.NewSource(seed))
|
| 91 |
+
return *rng
|
| 92 |
+
}
|
| 93 |
+
|
| 94 |
+
func RandomLanguage() string {
|
| 95 |
+
// 初始化随机数生成器
|
| 96 |
+
rng := GetRand()
|
| 97 |
+
// 语言列表
|
| 98 |
+
languages := []string{"af", "am", "ar-sa", "as", "az-Latn", "be", "bg", "bn-BD", "bn-IN", "bs", "ca", "ca-ES-valencia", "cs", "cy", "da", "de", "de-de", "el", "en-GB", "en-US", "es", "es-ES", "es-US", "es-MX", "et", "eu", "fa", "fi", "fil-Latn", "fr", "fr-FR", "fr-CA", "ga", "gd-Latn", "gl", "gu", "ha-Latn", "he", "hi", "hr", "hu", "hy", "id", "ig-Latn", "is", "it", "it-it", "ja", "ka", "kk", "km", "kn", "ko", "kok", "ku-Arab", "ky-Cyrl", "lb", "lt", "lv", "mi-Latn", "mk", "ml", "mn-Cyrl", "mr", "ms", "mt", "nb", "ne", "nl", "nl-BE", "nn", "nso", "or", "pa", "pa-Arab", "pl", "prs-Arab", "pt-BR", "pt-PT", "qut-Latn", "quz", "ro", "ru", "rw", "sd-Arab", "si", "sk", "sl", "sq", "sr-Cyrl-BA", "sr-Cyrl-RS", "sr-Latn-RS", "sv", "sw", "ta", "te", "tg-Cyrl", "th", "ti", "tk-Latn", "tn", "tr", "tt-Cyrl", "ug-Arab", "uk", "ur", "uz-Latn", "vi", "wo", "xh", "yo-Latn", "zh-Hans", "zh-Hant", "zu"}
|
| 99 |
+
// 随机选择一个语言
|
| 100 |
+
randomIndex := rng.Intn(len(languages))
|
| 101 |
+
return languages[randomIndex]
|
| 102 |
+
}
|
| 103 |
+
|
| 104 |
+
// GetAbsPathAndGenerate 获取绝对路径并生成文件或文件夹
|
| 105 |
+
func GetAbsPathAndGenerate(path string, isFilePath bool, content string) string {
|
| 106 |
+
// 获取绝对路径
|
| 107 |
+
path = GetAbsPath(path)
|
| 108 |
+
if isFilePath {
|
| 109 |
+
// 判断文件是否存在
|
| 110 |
+
if isExist := fileIsExistAndCreat(path, content); isExist {
|
| 111 |
+
return path
|
| 112 |
+
}
|
| 113 |
+
} else {
|
| 114 |
+
// 判断文件夹是否存在
|
| 115 |
+
if isExist := dirIsExistAndMkdir(path, false); isExist {
|
| 116 |
+
return path
|
| 117 |
+
}
|
| 118 |
+
}
|
| 119 |
+
return path
|
| 120 |
+
}
|
| 121 |
+
|
| 122 |
+
// GetAbsPath 获取绝对路径
|
| 123 |
+
func GetAbsPath(path string) string {
|
| 124 |
+
if !filepath.IsAbs(path) {
|
| 125 |
+
absPath, err := filepath.Abs(path)
|
| 126 |
+
if err != nil {
|
| 127 |
+
return ""
|
| 128 |
+
}
|
| 129 |
+
return absPath
|
| 130 |
+
}
|
| 131 |
+
return path
|
| 132 |
+
}
|
| 133 |
+
|
| 134 |
+
func dirIsExistAndMkdir(dirPath string, isFile bool) bool {
|
| 135 |
+
// 判断路径是否存在
|
| 136 |
+
_, err := os.Stat(dirPath)
|
| 137 |
+
dir := dirPath
|
| 138 |
+
if err != nil {
|
| 139 |
+
if isFile {
|
| 140 |
+
dir = filepath.Dir(dirPath)
|
| 141 |
+
}
|
| 142 |
+
// 创建路径
|
| 143 |
+
err := os.MkdirAll(dir, os.ModePerm)
|
| 144 |
+
if err != nil {
|
| 145 |
+
return false
|
| 146 |
+
}
|
| 147 |
+
}
|
| 148 |
+
return true
|
| 149 |
+
}
|
| 150 |
+
|
| 151 |
+
func fileIsExistAndCreat(filePath string, content string) bool {
|
| 152 |
+
//判断文件是否存在
|
| 153 |
+
_, err := os.Stat(filePath)
|
| 154 |
+
if err != nil {
|
| 155 |
+
// 判断文件夹是否存在
|
| 156 |
+
if isExist := dirIsExistAndMkdir(filePath, true); !isExist {
|
| 157 |
+
return false
|
| 158 |
+
}
|
| 159 |
+
// 创建文件
|
| 160 |
+
_, err := os.Create(filePath)
|
| 161 |
+
if err != nil {
|
| 162 |
+
return false
|
| 163 |
+
}
|
| 164 |
+
if content != "" {
|
| 165 |
+
// 写入content
|
| 166 |
+
file, _ := os.OpenFile(filePath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0777)
|
| 167 |
+
_, _ = file.Write([]byte(content))
|
| 168 |
+
defer func(file *os.File) {
|
| 169 |
+
_ = file.Close()
|
| 170 |
+
}(file)
|
| 171 |
+
}
|
| 172 |
+
}
|
| 173 |
+
return true
|
| 174 |
+
}
|
| 175 |
+
|
| 176 |
+
// AsyncTimingTask 定时任务 参数含函数
|
| 177 |
+
func AsyncTimingTask(nanosecond time.Duration, fun func()) {
|
| 178 |
+
go func() {
|
| 179 |
+
timerChan := time.After(nanosecond)
|
| 180 |
+
// 使用for循环阻塞等待定时器的信号
|
| 181 |
+
for {
|
| 182 |
+
// 通过select语句监听定时器通道和其他事件
|
| 183 |
+
select {
|
| 184 |
+
case <-timerChan:
|
| 185 |
+
fun()
|
| 186 |
+
// 重新设置定时器,以便下一次执行
|
| 187 |
+
timerChan = time.After(nanosecond)
|
| 188 |
+
}
|
| 189 |
+
time.Sleep(time.Millisecond * 100)
|
| 190 |
+
}
|
| 191 |
+
}()
|
| 192 |
+
}
|
| 193 |
+
|
| 194 |
+
// AsyncLoopTask AsyncTimingTask 定时任务 参数含函数
|
| 195 |
+
func AsyncLoopTask(sleep time.Duration, fun func()) {
|
| 196 |
+
go func() {
|
| 197 |
+
for {
|
| 198 |
+
fun()
|
| 199 |
+
time.Sleep(sleep)
|
| 200 |
+
}
|
| 201 |
+
}()
|
| 202 |
+
}
|
| 203 |
+
|
| 204 |
+
// DeepCopyStruct 深拷贝函数
|
| 205 |
+
func DeepCopyStruct(src interface{}) interface{} {
|
| 206 |
+
// 获取源对象的类型信息
|
| 207 |
+
srcType := reflect.TypeOf(src)
|
| 208 |
+
// 创建目标对象
|
| 209 |
+
dst := reflect.New(srcType).Elem()
|
| 210 |
+
|
| 211 |
+
// 深拷贝过程
|
| 212 |
+
deepCopyValue(reflect.ValueOf(src), dst)
|
| 213 |
+
|
| 214 |
+
return dst.Interface()
|
| 215 |
+
}
|
| 216 |
+
|
| 217 |
+
// 递归进行深拷贝
|
| 218 |
+
func deepCopyValue(src, dst reflect.Value) {
|
| 219 |
+
switch src.Kind() {
|
| 220 |
+
case reflect.Ptr:
|
| 221 |
+
if src.IsNil() {
|
| 222 |
+
dst.Set(src)
|
| 223 |
+
return
|
| 224 |
+
}
|
| 225 |
+
// 递归处理指针指向的内容
|
| 226 |
+
newDst := reflect.New(src.Elem().Type())
|
| 227 |
+
deepCopyValue(src.Elem(), newDst.Elem())
|
| 228 |
+
dst.Set(newDst)
|
| 229 |
+
case reflect.Struct:
|
| 230 |
+
for i := 0; i < src.NumField(); i++ {
|
| 231 |
+
// 递归处理结构体的字段
|
| 232 |
+
deepCopyValue(src.Field(i), dst.Field(i))
|
| 233 |
+
}
|
| 234 |
+
default:
|
| 235 |
+
// 检查目标值是否支持设置
|
| 236 |
+
if dst.CanSet() {
|
| 237 |
+
// 处理基本类型和数组、切片、映射等
|
| 238 |
+
dst.Set(src)
|
| 239 |
+
}
|
| 240 |
+
}
|
| 241 |
+
}
|
| 242 |
+
|
| 243 |
+
func RandomHexadecimalString() string {
|
| 244 |
+
rng := GetRand()
|
| 245 |
+
const charset = "0123456789abcdef"
|
| 246 |
+
const length = 16 // The length of the string you want to generate
|
| 247 |
+
b := make([]byte, length)
|
| 248 |
+
for i := range b {
|
| 249 |
+
b[i] = charset[rng.Intn(len(charset))]
|
| 250 |
+
}
|
| 251 |
+
return string(b)
|
| 252 |
+
}
|
| 253 |
+
|
| 254 |
+
// OutRequest 打印请求.
|
| 255 |
+
func OutRequest(req *fhttp.Request) {
|
| 256 |
+
dump, err := httputil.DumpRequestOut(req, true)
|
| 257 |
+
if err != nil {
|
| 258 |
+
fmt.Println("Error dumping request:", err)
|
| 259 |
+
} else {
|
| 260 |
+
fmt.Println(string(dump))
|
| 261 |
+
}
|
| 262 |
+
}
|
| 263 |
+
|
| 264 |
+
// OutResponse 打印响应.
|
| 265 |
+
func OutResponse(res *fhttp.Response) {
|
| 266 |
+
dump, err := httputil.DumpResponse(res, true)
|
| 267 |
+
if err != nil {
|
| 268 |
+
fmt.Println("Error dumping response:", err)
|
| 269 |
+
} else {
|
| 270 |
+
fmt.Println(string(dump))
|
| 271 |
+
}
|
| 272 |
+
}
|
| 273 |
+
|
| 274 |
+
func IsStrInArray(str string, strS []string) bool {
|
| 275 |
+
// 如果 strS 为空,直接返回 true
|
| 276 |
+
if len(strS) == 0 {
|
| 277 |
+
return true
|
| 278 |
+
}
|
| 279 |
+
for _, v := range strS {
|
| 280 |
+
if v == str {
|
| 281 |
+
return true
|
| 282 |
+
}
|
| 283 |
+
}
|
| 284 |
+
return false
|
| 285 |
+
}
|
config/config.go
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package config
|
| 2 |
+
|
| 3 |
+
import (
|
| 4 |
+
"free-gpt3.5-2api/common"
|
| 5 |
+
"github.com/joho/godotenv"
|
| 6 |
+
"os"
|
| 7 |
+
"strconv"
|
| 8 |
+
"strings"
|
| 9 |
+
)
|
| 10 |
+
|
| 11 |
+
var (
|
| 12 |
+
Bind string
|
| 13 |
+
Port string
|
| 14 |
+
Proxy []string
|
| 15 |
+
AUTHORIZATIONS []string
|
| 16 |
+
BaseUrl string
|
| 17 |
+
PoolMaxCount int
|
| 18 |
+
AuthED int
|
| 19 |
+
)
|
| 20 |
+
|
| 21 |
+
func init() {
|
| 22 |
+
_ = godotenv.Load()
|
| 23 |
+
// Bind
|
| 24 |
+
Bind = os.Getenv("BIND")
|
| 25 |
+
if Bind == "" {
|
| 26 |
+
Bind = "0.0.0.0"
|
| 27 |
+
}
|
| 28 |
+
// PORT
|
| 29 |
+
Port = os.Getenv("PORT")
|
| 30 |
+
if Port == "" {
|
| 31 |
+
Port = "3040"
|
| 32 |
+
}
|
| 33 |
+
// PROXY
|
| 34 |
+
proxy := os.Getenv("PROXY")
|
| 35 |
+
if proxy != "" {
|
| 36 |
+
Proxy = strings.Split(proxy, ",")
|
| 37 |
+
}
|
| 38 |
+
// AUTH_TOKEN
|
| 39 |
+
authorizations := os.Getenv("AUTHORIZATIONS")
|
| 40 |
+
if authorizations == "" {
|
| 41 |
+
AUTHORIZATIONS = []string{}
|
| 42 |
+
} else {
|
| 43 |
+
//以,分割 AUTH_TOKEN 并且为每个AUTH_TOKEN前面加上Bearer
|
| 44 |
+
AUTHORIZATIONS = common.SplitAndAddBearer(authorizations)
|
| 45 |
+
}
|
| 46 |
+
// BASE_URL
|
| 47 |
+
BaseUrl = os.Getenv("BASE_URL")
|
| 48 |
+
if BaseUrl == "" {
|
| 49 |
+
BaseUrl = "https://chatgpt.com"
|
| 50 |
+
} else {
|
| 51 |
+
BaseUrl = strings.TrimRight(BaseUrl, "/")
|
| 52 |
+
}
|
| 53 |
+
// POOL_MAX_COUNT
|
| 54 |
+
poolMaxCount := os.Getenv("POOL_MAX_COUNT")
|
| 55 |
+
var err error
|
| 56 |
+
if poolMaxCount == "" {
|
| 57 |
+
PoolMaxCount = 64
|
| 58 |
+
} else {
|
| 59 |
+
PoolMaxCount, err = strconv.Atoi(poolMaxCount)
|
| 60 |
+
if err != nil {
|
| 61 |
+
PoolMaxCount = 64
|
| 62 |
+
}
|
| 63 |
+
}
|
| 64 |
+
// AUTH_ED
|
| 65 |
+
authED := os.Getenv("AUTH_ED")
|
| 66 |
+
if authED == "" {
|
| 67 |
+
AuthED = 600
|
| 68 |
+
} else {
|
| 69 |
+
AuthED, err = strconv.Atoi(authED)
|
| 70 |
+
if err != nil {
|
| 71 |
+
AuthED = 600
|
| 72 |
+
}
|
| 73 |
+
}
|
| 74 |
+
}
|
constant/constant.go
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package constant
|
| 2 |
+
|
| 3 |
+
import "github.com/bogdanfinn/tls-client/profiles"
|
| 4 |
+
|
| 5 |
+
var (
|
| 6 |
+
ClientProfile = profiles.Safari_15_6_1
|
| 7 |
+
)
|
| 8 |
+
|
| 9 |
+
const (
|
| 10 |
+
Ua = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36"
|
| 11 |
+
)
|
conversion/requests/duckgo/convert.go
DELETED
|
@@ -1,30 +0,0 @@
|
|
| 1 |
-
package duckgo
|
| 2 |
-
|
| 3 |
-
import (
|
| 4 |
-
duckgotypes "aurora/typings/duckgo"
|
| 5 |
-
officialtypes "aurora/typings/official"
|
| 6 |
-
"strings"
|
| 7 |
-
)
|
| 8 |
-
|
| 9 |
-
func ConvertAPIRequest(api_request officialtypes.APIRequest) duckgotypes.ApiRequest {
|
| 10 |
-
// 默认模型3.5
|
| 11 |
-
duckgo_request := duckgotypes.NewApiRequest("gpt-3.5-turbo-0125")
|
| 12 |
-
// 检查并更新模型为 claude- 开头的情况
|
| 13 |
-
if strings.HasPrefix(strings.ToLower(api_request.Model), "claude") {
|
| 14 |
-
duckgo_request.Model = "claude-3-haiku-20240307"
|
| 15 |
-
}
|
| 16 |
-
content := buildContent(&api_request)
|
| 17 |
-
duckgo_request.AddMessage("user", content)
|
| 18 |
-
return duckgo_request
|
| 19 |
-
}
|
| 20 |
-
|
| 21 |
-
func buildContent(api_request *officialtypes.APIRequest) string {
|
| 22 |
-
var content strings.Builder
|
| 23 |
-
for _, apiMessage := range api_request.Messages {
|
| 24 |
-
role := apiMessage.Role
|
| 25 |
-
if role == "user" || role == "system" || role == "assistant" {
|
| 26 |
-
content.WriteString(role + ":" + apiMessage.Content + ";\r\n")
|
| 27 |
-
}
|
| 28 |
-
}
|
| 29 |
-
return content.String()
|
| 30 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
docker-compose.yml
DELETED
|
@@ -1,9 +0,0 @@
|
|
| 1 |
-
version: '3'
|
| 2 |
-
|
| 3 |
-
services:
|
| 4 |
-
app:
|
| 5 |
-
image: ghcr.io/aurora-develop/duck2api:latest
|
| 6 |
-
container_name: duck2api
|
| 7 |
-
restart: unless-stopped
|
| 8 |
-
ports:
|
| 9 |
-
- '8080:8080'
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
env.template
CHANGED
|
@@ -1,8 +1,8 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
|
|
|
| 1 |
+
LOG_LEVEL=info # debug, info, warn, error
|
| 2 |
+
BIND=127.0.0.1 #
|
| 3 |
+
PORT=8080
|
| 4 |
+
PROXY=
|
| 5 |
+
AUTHORIZATIONS=
|
| 6 |
+
POOL_MAX_COUNT=5 # max number of connections to keep in the pool
|
| 7 |
+
AUTH_ED=180 # expiration time for the authorization in seconds
|
| 8 |
+
AUTH_USE_COUNT=5 # number of times an authorization can be used
|
go.mod
CHANGED
|
@@ -1,56 +1,50 @@
|
|
| 1 |
-
module
|
| 2 |
|
| 3 |
go 1.21
|
| 4 |
|
| 5 |
require (
|
| 6 |
-
github.com/
|
| 7 |
-
github.com/
|
| 8 |
-
github.com/bogdanfinn/fhttp v0.5.27
|
| 9 |
github.com/bogdanfinn/tls-client v1.7.2
|
| 10 |
github.com/gin-gonic/gin v1.9.1
|
| 11 |
-
github.com/go-resty/resty/v2 v2.12.0
|
| 12 |
github.com/google/uuid v1.6.0
|
| 13 |
-
github.com/gorilla/websocket v1.5.1
|
| 14 |
github.com/joho/godotenv v1.5.1
|
| 15 |
-
github.com/
|
| 16 |
-
github.com/
|
|
|
|
| 17 |
)
|
| 18 |
|
| 19 |
require (
|
| 20 |
-
github.com/PuerkitoBio/goquery v1.9.1 // indirect
|
| 21 |
github.com/andybalholm/brotli v1.0.5 // indirect
|
| 22 |
-
github.com/andybalholm/cascadia v1.3.2 // indirect
|
| 23 |
github.com/bogdanfinn/utls v1.6.1 // indirect
|
| 24 |
-
github.com/bytedance/sonic v1.
|
| 25 |
-
github.com/chenzhuoyu/base64x v0.0.0-
|
| 26 |
-
github.com/
|
| 27 |
-
github.com/cloudflare/circl v1.3.6 // indirect
|
| 28 |
-
github.com/dlclark/regexp2 v1.10.0 // indirect
|
| 29 |
github.com/gabriel-vasile/mimetype v1.4.2 // indirect
|
| 30 |
github.com/gin-contrib/sse v0.1.0 // indirect
|
| 31 |
github.com/go-playground/locales v0.14.1 // indirect
|
| 32 |
github.com/go-playground/universal-translator v0.18.1 // indirect
|
| 33 |
-
github.com/go-playground/validator/v10 v10.
|
| 34 |
github.com/goccy/go-json v0.10.2 // indirect
|
| 35 |
-
github.com/
|
| 36 |
-
github.com/klauspost/
|
| 37 |
-
github.com/klauspost/cpuid/v2 v2.2.5 // indirect
|
| 38 |
-
github.com/kr/text v0.2.0 // indirect
|
| 39 |
github.com/leodido/go-urn v1.2.4 // indirect
|
| 40 |
github.com/mattn/go-isatty v0.0.19 // indirect
|
| 41 |
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
| 42 |
github.com/modern-go/reflect2 v1.0.2 // indirect
|
| 43 |
-
github.com/pelletier/go-toml/v2 v2.
|
| 44 |
-
github.com/quic-go/quic-go v0.
|
| 45 |
github.com/rogpeppe/go-internal v1.12.0 // indirect
|
| 46 |
github.com/tam7t/hpkp v0.0.0-20160821193359-2b70b4024ed5 // indirect
|
| 47 |
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
| 48 |
github.com/ugorji/go/codec v1.2.11 // indirect
|
| 49 |
-
|
| 50 |
-
|
|
|
|
|
|
|
| 51 |
golang.org/x/net v0.22.0 // indirect
|
| 52 |
golang.org/x/sys v0.18.0 // indirect
|
| 53 |
golang.org/x/text v0.14.0 // indirect
|
| 54 |
-
google.golang.org/protobuf v1.
|
| 55 |
gopkg.in/yaml.v3 v3.0.1 // indirect
|
| 56 |
)
|
|
|
|
| 1 |
+
module free-gpt3.5-2api
|
| 2 |
|
| 3 |
go 1.21
|
| 4 |
|
| 5 |
require (
|
| 6 |
+
github.com/aurorax-neo/go-logger v0.0.0-20240421094709-1eb4bda786d5
|
| 7 |
+
github.com/bogdanfinn/fhttp v0.5.28
|
|
|
|
| 8 |
github.com/bogdanfinn/tls-client v1.7.2
|
| 9 |
github.com/gin-gonic/gin v1.9.1
|
|
|
|
| 10 |
github.com/google/uuid v1.6.0
|
|
|
|
| 11 |
github.com/joho/godotenv v1.5.1
|
| 12 |
+
github.com/json-iterator/go v1.1.12
|
| 13 |
+
github.com/launchdarkly/eventsource v1.7.1
|
| 14 |
+
golang.org/x/crypto v0.21.0
|
| 15 |
)
|
| 16 |
|
| 17 |
require (
|
|
|
|
| 18 |
github.com/andybalholm/brotli v1.0.5 // indirect
|
|
|
|
| 19 |
github.com/bogdanfinn/utls v1.6.1 // indirect
|
| 20 |
+
github.com/bytedance/sonic v1.9.1 // indirect
|
| 21 |
+
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
|
| 22 |
+
github.com/cloudflare/circl v1.3.7 // indirect
|
|
|
|
|
|
|
| 23 |
github.com/gabriel-vasile/mimetype v1.4.2 // indirect
|
| 24 |
github.com/gin-contrib/sse v0.1.0 // indirect
|
| 25 |
github.com/go-playground/locales v0.14.1 // indirect
|
| 26 |
github.com/go-playground/universal-translator v0.18.1 // indirect
|
| 27 |
+
github.com/go-playground/validator/v10 v10.14.0 // indirect
|
| 28 |
github.com/goccy/go-json v0.10.2 // indirect
|
| 29 |
+
github.com/klauspost/compress v1.16.7 // indirect
|
| 30 |
+
github.com/klauspost/cpuid/v2 v2.2.4 // indirect
|
|
|
|
|
|
|
| 31 |
github.com/leodido/go-urn v1.2.4 // indirect
|
| 32 |
github.com/mattn/go-isatty v0.0.19 // indirect
|
| 33 |
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
| 34 |
github.com/modern-go/reflect2 v1.0.2 // indirect
|
| 35 |
+
github.com/pelletier/go-toml/v2 v2.0.8 // indirect
|
| 36 |
+
github.com/quic-go/quic-go v0.42.0 // indirect
|
| 37 |
github.com/rogpeppe/go-internal v1.12.0 // indirect
|
| 38 |
github.com/tam7t/hpkp v0.0.0-20160821193359-2b70b4024ed5 // indirect
|
| 39 |
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
| 40 |
github.com/ugorji/go/codec v1.2.11 // indirect
|
| 41 |
+
go.uber.org/multierr v1.11.0 // indirect
|
| 42 |
+
go.uber.org/zap v1.27.0 // indirect
|
| 43 |
+
golang.org/x/arch v0.3.0 // indirect
|
| 44 |
+
golang.org/x/exp v0.0.0-20221205204356-47842c84f3db // indirect
|
| 45 |
golang.org/x/net v0.22.0 // indirect
|
| 46 |
golang.org/x/sys v0.18.0 // indirect
|
| 47 |
golang.org/x/text v0.14.0 // indirect
|
| 48 |
+
google.golang.org/protobuf v1.33.0 // indirect
|
| 49 |
gopkg.in/yaml.v3 v3.0.1 // indirect
|
| 50 |
)
|
go.sum
CHANGED
|
@@ -1,37 +1,24 @@
|
|
| 1 |
-
github.com/EDDYCJY/fake-useragent v0.2.0 h1:Jcnkk2bgXmDpX0z+ELlUErTkoLb/mxFBNd2YdcpvJBs=
|
| 2 |
-
github.com/EDDYCJY/fake-useragent v0.2.0/go.mod h1:5wn3zzlDxhKW6NYknushqinPcAqZcAPHy8lLczCdJdc=
|
| 3 |
-
github.com/PuerkitoBio/goquery v1.9.1 h1:mTL6XjbJTZdpfL+Gwl5U2h1l9yEkJjhmlTeV9VPW7UI=
|
| 4 |
-
github.com/PuerkitoBio/goquery v1.9.1/go.mod h1:cW1n6TmIMDoORQU5IU/P1T3tGFunOeXEpGP2WHRwkbY=
|
| 5 |
-
github.com/acheong08/endless v0.0.0-20230615162514-90545c7793fd h1:oIpfrRhD7Jus41dotbK+SQjWSFRnf1cLZUYCZpF/o/4=
|
| 6 |
-
github.com/acheong08/endless v0.0.0-20230615162514-90545c7793fd/go.mod h1:0yO7neMeJLvKk/B/fq5votDY8rByrOPDubpvU+6saKo=
|
| 7 |
github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs=
|
| 8 |
github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
|
| 9 |
-
github.com/
|
| 10 |
-
github.com/
|
| 11 |
-
github.com/bogdanfinn/fhttp v0.5.
|
| 12 |
-
github.com/bogdanfinn/fhttp v0.5.
|
| 13 |
github.com/bogdanfinn/tls-client v1.7.2 h1:vpL5qBYUfT9ueygEf1yLfymrXyUEZQatL25amfqGV8M=
|
| 14 |
github.com/bogdanfinn/tls-client v1.7.2/go.mod h1:pOGa2euqTbEkGNqE5idx5jKKfs9ytlyn3fwEw8RSP+g=
|
| 15 |
github.com/bogdanfinn/utls v1.6.1 h1:dKDYAcXEyFFJ3GaWaN89DEyjyRraD1qb4osdEK89ass=
|
| 16 |
github.com/bogdanfinn/utls v1.6.1/go.mod h1:VXIbRZaiY/wHZc6Hu+DZ4O2CgTzjhjCg/Ou3V4r/39Y=
|
| 17 |
github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM=
|
| 18 |
-
github.com/bytedance/sonic v1.
|
| 19 |
-
github.com/bytedance/sonic v1.
|
| 20 |
-
github.com/bytedance/sonic v1.10.1/go.mod h1:iZcSUejdk5aukTND/Eu/ivjQuEL0Cu9/rf50Hi0u/g4=
|
| 21 |
github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY=
|
|
|
|
| 22 |
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk=
|
| 23 |
-
github.com/
|
| 24 |
-
github.com/
|
| 25 |
-
github.com/chenzhuoyu/iasm v0.9.0 h1:9fhXjVzq5hUy2gkhhgHl95zG2cEAhw9OSGs8toWWAwo=
|
| 26 |
-
github.com/chenzhuoyu/iasm v0.9.0/go.mod h1:Xjy2NpN3h7aUqeqM+woSuuvxmIe6+DDsiNLIrkAmYog=
|
| 27 |
-
github.com/cloudflare/circl v1.3.6 h1:/xbKIqSHbZXHwkhbrhrt2YOHIwYJlXH94E3tI/gDlUg=
|
| 28 |
-
github.com/cloudflare/circl v1.3.6/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA=
|
| 29 |
-
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
| 30 |
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
| 31 |
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
| 32 |
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
| 33 |
-
github.com/dlclark/regexp2 v1.10.0 h1:+/GIL799phkJqYW+3YbOd8LCcbHzT0Pbo8zl70MHsq0=
|
| 34 |
-
github.com/dlclark/regexp2 v1.10.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
|
| 35 |
github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU=
|
| 36 |
github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA=
|
| 37 |
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
|
|
@@ -46,16 +33,12 @@ github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/o
|
|
| 46 |
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
|
| 47 |
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
|
| 48 |
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
|
| 49 |
-
github.com/go-playground/validator/v10 v10.
|
| 50 |
-
github.com/go-playground/validator/v10 v10.
|
| 51 |
-
github.com/go-resty/resty/v2 v2.12.0 h1:rsVL8P90LFvkUYq/V5BTVe203WfRIU4gvcf+yfzJzGA=
|
| 52 |
-
github.com/go-resty/resty/v2 v2.12.0/go.mod h1:o0yGPrkS3lOe1+eFajk6kBW8ScXzwU3hD69/gt2yB/0=
|
| 53 |
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
|
| 54 |
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
|
| 55 |
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
|
| 56 |
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
| 57 |
-
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
| 58 |
-
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
| 59 |
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
| 60 |
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
| 61 |
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
|
@@ -63,22 +46,23 @@ github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 h1:yAJXTCF9TqKcTiHJAE
|
|
| 63 |
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
| 64 |
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
| 65 |
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
| 66 |
-
github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY=
|
| 67 |
-
github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY=
|
| 68 |
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
|
| 69 |
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
|
| 70 |
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
| 71 |
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
| 72 |
-
github.com/klauspost/compress v1.
|
| 73 |
-
github.com/klauspost/compress v1.
|
| 74 |
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
| 75 |
-
github.com/klauspost/cpuid/v2 v2.2.
|
| 76 |
-
github.com/klauspost/cpuid/v2 v2.2.
|
| 77 |
-
github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
|
| 78 |
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
| 79 |
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
| 80 |
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
| 81 |
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
|
|
|
|
|
|
|
|
|
|
|
|
| 82 |
github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q=
|
| 83 |
github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4=
|
| 84 |
github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
|
|
@@ -92,102 +76,64 @@ github.com/onsi/ginkgo/v2 v2.9.5 h1:+6Hr4uxzP4XIUyAkg61dWBw8lb/gc4/X5luuxN/EC+Q=
|
|
| 92 |
github.com/onsi/ginkgo/v2 v2.9.5/go.mod h1:tvAoo1QUJwNEU2ITftXTpR7R1RbCzoZUOs3RonqW57k=
|
| 93 |
github.com/onsi/gomega v1.27.6 h1:ENqfyGeS5AX/rlXDd/ETokDz93u0YufY1Pgxuy/PvWE=
|
| 94 |
github.com/onsi/gomega v1.27.6/go.mod h1:PIQNjfQwkP3aQAH7lf7j87O/5FiNr+ZR8+ipb+qQlhg=
|
| 95 |
-
github.com/pelletier/go-toml/v2 v2.
|
| 96 |
-
github.com/pelletier/go-toml/v2 v2.
|
| 97 |
-
github.com/pkoukk/tiktoken-go v0.1.6 h1:JF0TlJzhTbrI30wCvFuiw6FzP2+/bR+FIxUdgEAcUsw=
|
| 98 |
-
github.com/pkoukk/tiktoken-go v0.1.6/go.mod h1:9NiV+i9mJKGj1rYOT+njbv+ZwA/zJxYdewGl6qVatpg=
|
| 99 |
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
| 100 |
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
| 101 |
-
github.com/quic-go/quic-go v0.
|
| 102 |
-
github.com/quic-go/quic-go v0.
|
| 103 |
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
|
| 104 |
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
|
| 105 |
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
| 106 |
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
| 107 |
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
| 108 |
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
|
|
|
|
|
|
| 109 |
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
| 110 |
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
| 111 |
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
| 112 |
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
| 113 |
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
| 114 |
-
github.com/stretchr/testify v1.8.
|
| 115 |
-
github.com/stretchr/testify v1.8.
|
| 116 |
github.com/tam7t/hpkp v0.0.0-20160821193359-2b70b4024ed5 h1:YqAladjX7xpA6BM04leXMWAEjS0mTZ5kUU9KRBriQJc=
|
| 117 |
github.com/tam7t/hpkp v0.0.0-20160821193359-2b70b4024ed5/go.mod h1:2JjD2zLQYH5HO74y5+aE3remJQvl6q4Sn6aWA2wD1Ng=
|
| 118 |
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
|
| 119 |
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
|
| 120 |
github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU=
|
| 121 |
github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
|
| 122 |
-
|
| 123 |
-
|
| 124 |
-
|
|
|
|
|
|
|
|
|
|
| 125 |
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
|
| 126 |
-
golang.org/x/arch v0.
|
| 127 |
-
golang.org/x/arch v0.
|
| 128 |
-
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
| 129 |
-
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
| 130 |
-
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
| 131 |
golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
|
| 132 |
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
|
| 133 |
-
golang.org/x/
|
| 134 |
-
golang.org/x/
|
| 135 |
-
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
| 136 |
-
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
| 137 |
-
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
| 138 |
-
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
| 139 |
-
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
|
| 140 |
-
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
| 141 |
-
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
| 142 |
golang.org/x/net v0.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc=
|
| 143 |
golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
|
| 144 |
-
golang.org/x/
|
| 145 |
-
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
| 146 |
-
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
| 147 |
-
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
| 148 |
-
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
| 149 |
-
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
| 150 |
-
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
| 151 |
-
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
| 152 |
-
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
| 153 |
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
| 154 |
-
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
| 155 |
-
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
| 156 |
-
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
| 157 |
golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
|
| 158 |
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
| 159 |
-
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
| 160 |
-
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
| 161 |
-
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
| 162 |
-
golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
|
| 163 |
-
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
| 164 |
-
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
|
| 165 |
-
golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58=
|
| 166 |
-
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
| 167 |
-
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
| 168 |
-
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
| 169 |
-
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
| 170 |
-
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
| 171 |
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
| 172 |
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
| 173 |
-
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
|
| 174 |
-
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
| 175 |
-
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
| 176 |
-
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
| 177 |
-
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
| 178 |
-
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
| 179 |
golang.org/x/tools v0.9.1 h1:8WMNJAz3zrtPmnYC7ISf5dEn3MT0gY7jBJfw27yrrLo=
|
| 180 |
golang.org/x/tools v0.9.1/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc=
|
| 181 |
-
golang.org/
|
| 182 |
-
golang.org/
|
| 183 |
-
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
| 184 |
-
google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
|
| 185 |
-
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
| 186 |
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
| 187 |
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
| 188 |
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
|
|
|
|
|
|
| 189 |
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
| 190 |
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
| 191 |
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
| 192 |
-
nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
|
| 193 |
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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/aurorax-neo/go-logger v0.0.0-20240421094709-1eb4bda786d5 h1:L1ei0BPLvE/ld4KAh4bKVAn5tDYOdJz0SuxlbuzfKzQ=
|
| 4 |
+
github.com/aurorax-neo/go-logger v0.0.0-20240421094709-1eb4bda786d5/go.mod h1:BJsRG1ECcXTHwiz2zaMYxFkeXh+MpQVs6nWYphLT244=
|
| 5 |
+
github.com/bogdanfinn/fhttp v0.5.28 h1:G6thT8s8v6z1IuvXMUsX9QKy3ZHseTQTzxuIhSiaaAw=
|
| 6 |
+
github.com/bogdanfinn/fhttp v0.5.28/go.mod h1:oJiYPG3jQTKzk/VFmogH8jxjH5yiv2rrOH48Xso2lrE=
|
| 7 |
github.com/bogdanfinn/tls-client v1.7.2 h1:vpL5qBYUfT9ueygEf1yLfymrXyUEZQatL25amfqGV8M=
|
| 8 |
github.com/bogdanfinn/tls-client v1.7.2/go.mod h1:pOGa2euqTbEkGNqE5idx5jKKfs9ytlyn3fwEw8RSP+g=
|
| 9 |
github.com/bogdanfinn/utls v1.6.1 h1:dKDYAcXEyFFJ3GaWaN89DEyjyRraD1qb4osdEK89ass=
|
| 10 |
github.com/bogdanfinn/utls v1.6.1/go.mod h1:VXIbRZaiY/wHZc6Hu+DZ4O2CgTzjhjCg/Ou3V4r/39Y=
|
| 11 |
github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM=
|
| 12 |
+
github.com/bytedance/sonic v1.9.1 h1:6iJ6NqdoxCDr6mbY8h18oSO+cShGSMRGCEo7F2h0x8s=
|
| 13 |
+
github.com/bytedance/sonic v1.9.1/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U=
|
|
|
|
| 14 |
github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY=
|
| 15 |
+
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 h1:qSGYFH7+jGhDF8vLC+iwCD4WpbV1EBDSzWkJODFLams=
|
| 16 |
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk=
|
| 17 |
+
github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU=
|
| 18 |
+
github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA=
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 19 |
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
| 20 |
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
| 21 |
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
|
|
|
|
|
|
| 22 |
github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU=
|
| 23 |
github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA=
|
| 24 |
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
|
|
|
|
| 33 |
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
|
| 34 |
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
|
| 35 |
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
|
| 36 |
+
github.com/go-playground/validator/v10 v10.14.0 h1:vgvQWe3XCz3gIeFDm/HnTIbj6UGmg/+t63MyGU2n5js=
|
| 37 |
+
github.com/go-playground/validator/v10 v10.14.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU=
|
|
|
|
|
|
|
| 38 |
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
|
| 39 |
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
|
| 40 |
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
|
| 41 |
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
|
|
|
|
|
|
| 42 |
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
| 43 |
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
| 44 |
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
|
|
|
| 46 |
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
| 47 |
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
| 48 |
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
|
|
|
|
|
|
| 49 |
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
|
| 50 |
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
|
| 51 |
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
| 52 |
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
| 53 |
+
github.com/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I=
|
| 54 |
+
github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
|
| 55 |
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
| 56 |
+
github.com/klauspost/cpuid/v2 v2.2.4 h1:acbojRNwl3o09bUq+yDCtZFc1aiwaAAxtcn8YkZXnvk=
|
| 57 |
+
github.com/klauspost/cpuid/v2 v2.2.4/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY=
|
|
|
|
| 58 |
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
| 59 |
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
| 60 |
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
| 61 |
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
| 62 |
+
github.com/launchdarkly/eventsource v1.7.1 h1:StoRQeiPyrcQIXjlQ7b5jWMzHW4p+GGczN2r2oBhujg=
|
| 63 |
+
github.com/launchdarkly/eventsource v1.7.1/go.mod h1:LHxSeb4OnqznNZxCSXbFghxS/CjIQfzHovNoAqbO/Wk=
|
| 64 |
+
github.com/launchdarkly/go-test-helpers/v2 v2.2.0 h1:L3kGILP/6ewikhzhdNkHy1b5y4zs50LueWenVF0sBbs=
|
| 65 |
+
github.com/launchdarkly/go-test-helpers/v2 v2.2.0/go.mod h1:L7+th5govYp5oKU9iN7To5PgznBuIjBPn+ejqKR0avw=
|
| 66 |
github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q=
|
| 67 |
github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4=
|
| 68 |
github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
|
|
|
|
| 76 |
github.com/onsi/ginkgo/v2 v2.9.5/go.mod h1:tvAoo1QUJwNEU2ITftXTpR7R1RbCzoZUOs3RonqW57k=
|
| 77 |
github.com/onsi/gomega v1.27.6 h1:ENqfyGeS5AX/rlXDd/ETokDz93u0YufY1Pgxuy/PvWE=
|
| 78 |
github.com/onsi/gomega v1.27.6/go.mod h1:PIQNjfQwkP3aQAH7lf7j87O/5FiNr+ZR8+ipb+qQlhg=
|
| 79 |
+
github.com/pelletier/go-toml/v2 v2.0.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZR9tGQ=
|
| 80 |
+
github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4=
|
|
|
|
|
|
|
| 81 |
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
| 82 |
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
| 83 |
+
github.com/quic-go/quic-go v0.42.0 h1:uSfdap0eveIl8KXnipv9K7nlwZ5IqLlYOpJ58u5utpM=
|
| 84 |
+
github.com/quic-go/quic-go v0.42.0/go.mod h1:132kz4kL3F9vxhW3CtQJLDVwcFe5wdWeJXXijhsO57M=
|
| 85 |
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
|
| 86 |
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
|
| 87 |
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
| 88 |
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
| 89 |
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
| 90 |
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
| 91 |
+
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
| 92 |
+
github.com/stretchr/testify v1.6.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
| 93 |
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
| 94 |
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
| 95 |
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
| 96 |
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
| 97 |
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
| 98 |
+
github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY=
|
| 99 |
+
github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
| 100 |
github.com/tam7t/hpkp v0.0.0-20160821193359-2b70b4024ed5 h1:YqAladjX7xpA6BM04leXMWAEjS0mTZ5kUU9KRBriQJc=
|
| 101 |
github.com/tam7t/hpkp v0.0.0-20160821193359-2b70b4024ed5/go.mod h1:2JjD2zLQYH5HO74y5+aE3remJQvl6q4Sn6aWA2wD1Ng=
|
| 102 |
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
|
| 103 |
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
|
| 104 |
github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU=
|
| 105 |
github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
|
| 106 |
+
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
| 107 |
+
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
| 108 |
+
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
|
| 109 |
+
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
| 110 |
+
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
|
| 111 |
+
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
|
| 112 |
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
|
| 113 |
+
golang.org/x/arch v0.3.0 h1:02VY4/ZcO/gBOH6PUaoiptASxtXU10jazRCP865E97k=
|
| 114 |
+
golang.org/x/arch v0.3.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
|
|
|
|
|
|
|
|
|
|
| 115 |
golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
|
| 116 |
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
|
| 117 |
+
golang.org/x/exp v0.0.0-20221205204356-47842c84f3db h1:D/cFflL63o2KSLJIwjlcIt8PR064j/xsmdEJL/YvY/o=
|
| 118 |
+
golang.org/x/exp v0.0.0-20221205204356-47842c84f3db/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 119 |
golang.org/x/net v0.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc=
|
| 120 |
golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
|
| 121 |
+
golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 122 |
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
|
|
|
|
|
|
|
|
| 123 |
golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
|
| 124 |
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 125 |
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
| 126 |
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 127 |
golang.org/x/tools v0.9.1 h1:8WMNJAz3zrtPmnYC7ISf5dEn3MT0gY7jBJfw27yrrLo=
|
| 128 |
golang.org/x/tools v0.9.1/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc=
|
| 129 |
+
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
|
| 130 |
+
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
|
|
|
|
|
|
|
|
|
| 131 |
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
| 132 |
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
| 133 |
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
| 134 |
+
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
| 135 |
+
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
| 136 |
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
| 137 |
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
| 138 |
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
|
|
|
| 139 |
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
|
httpclient/Iaurorahttpclient.go
DELETED
|
@@ -1,28 +0,0 @@
|
|
| 1 |
-
package httpclient
|
| 2 |
-
|
| 3 |
-
import (
|
| 4 |
-
"io"
|
| 5 |
-
"net/http"
|
| 6 |
-
)
|
| 7 |
-
|
| 8 |
-
type AuroraHttpClient interface {
|
| 9 |
-
Request(method HttpMethod, url string, headers AuroraHeaders, cookies []*http.Cookie, body io.Reader) (*http.Response, error)
|
| 10 |
-
SetProxy(url string) error
|
| 11 |
-
}
|
| 12 |
-
|
| 13 |
-
type HttpMethod string
|
| 14 |
-
|
| 15 |
-
const (
|
| 16 |
-
GET HttpMethod = "GET"
|
| 17 |
-
POST HttpMethod = "POST"
|
| 18 |
-
PUT HttpMethod = "PUT"
|
| 19 |
-
HEAD HttpMethod = "HEAD"
|
| 20 |
-
DELETE HttpMethod = "DELETE"
|
| 21 |
-
OPTIONS HttpMethod = "OPTIONS"
|
| 22 |
-
)
|
| 23 |
-
|
| 24 |
-
type AuroraHeaders map[string]string
|
| 25 |
-
|
| 26 |
-
func (a AuroraHeaders) Set(key, value string) {
|
| 27 |
-
a[key] = value
|
| 28 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
httpclient/bogdanfinn/tls_client.go
DELETED
|
@@ -1,101 +0,0 @@
|
|
| 1 |
-
package bogdanfinn
|
| 2 |
-
|
| 3 |
-
import (
|
| 4 |
-
"aurora/httpclient"
|
| 5 |
-
"io"
|
| 6 |
-
"net/http"
|
| 7 |
-
|
| 8 |
-
fhttp "github.com/bogdanfinn/fhttp"
|
| 9 |
-
tls_client "github.com/bogdanfinn/tls-client"
|
| 10 |
-
"github.com/bogdanfinn/tls-client/profiles"
|
| 11 |
-
)
|
| 12 |
-
|
| 13 |
-
type TlsClient struct {
|
| 14 |
-
Client tls_client.HttpClient
|
| 15 |
-
ReqBefore handler
|
| 16 |
-
}
|
| 17 |
-
|
| 18 |
-
type handler func(r *fhttp.Request) error
|
| 19 |
-
|
| 20 |
-
func NewStdClient() *TlsClient {
|
| 21 |
-
client, _ := tls_client.NewHttpClient(tls_client.NewNoopLogger(), []tls_client.HttpClientOption{
|
| 22 |
-
tls_client.WithCookieJar(tls_client.NewCookieJar()),
|
| 23 |
-
tls_client.WithTimeoutSeconds(600),
|
| 24 |
-
tls_client.WithClientProfile(profiles.Safari_15_6_1),
|
| 25 |
-
}...)
|
| 26 |
-
|
| 27 |
-
stdClient := &TlsClient{Client: client}
|
| 28 |
-
return stdClient
|
| 29 |
-
}
|
| 30 |
-
|
| 31 |
-
func convertResponse(resp *fhttp.Response) *http.Response {
|
| 32 |
-
response := &http.Response{
|
| 33 |
-
Status: resp.Status,
|
| 34 |
-
StatusCode: resp.StatusCode,
|
| 35 |
-
Proto: resp.Proto,
|
| 36 |
-
ProtoMajor: resp.ProtoMajor,
|
| 37 |
-
ProtoMinor: resp.ProtoMinor,
|
| 38 |
-
Header: http.Header(resp.Header),
|
| 39 |
-
Body: resp.Body,
|
| 40 |
-
ContentLength: resp.ContentLength,
|
| 41 |
-
TransferEncoding: resp.TransferEncoding,
|
| 42 |
-
Close: resp.Close,
|
| 43 |
-
Uncompressed: resp.Uncompressed,
|
| 44 |
-
Trailer: http.Header(resp.Trailer),
|
| 45 |
-
}
|
| 46 |
-
return response
|
| 47 |
-
}
|
| 48 |
-
|
| 49 |
-
func (t *TlsClient) handleHeaders(req *fhttp.Request, headers httpclient.AuroraHeaders) {
|
| 50 |
-
if headers == nil {
|
| 51 |
-
return
|
| 52 |
-
}
|
| 53 |
-
for k, v := range headers {
|
| 54 |
-
req.Header.Set(k, v)
|
| 55 |
-
}
|
| 56 |
-
}
|
| 57 |
-
|
| 58 |
-
func (t *TlsClient) handleCookies(req *fhttp.Request, cookies []*http.Cookie) {
|
| 59 |
-
if cookies == nil {
|
| 60 |
-
return
|
| 61 |
-
}
|
| 62 |
-
for _, c := range cookies {
|
| 63 |
-
req.AddCookie(&fhttp.Cookie{
|
| 64 |
-
Name: c.Name,
|
| 65 |
-
Value: c.Value,
|
| 66 |
-
Path: c.Path,
|
| 67 |
-
Domain: c.Domain,
|
| 68 |
-
Expires: c.Expires,
|
| 69 |
-
RawExpires: c.RawExpires,
|
| 70 |
-
MaxAge: c.MaxAge,
|
| 71 |
-
Secure: c.Secure,
|
| 72 |
-
HttpOnly: c.HttpOnly,
|
| 73 |
-
SameSite: fhttp.SameSite(c.SameSite),
|
| 74 |
-
Raw: c.Raw,
|
| 75 |
-
Unparsed: c.Unparsed,
|
| 76 |
-
})
|
| 77 |
-
}
|
| 78 |
-
}
|
| 79 |
-
|
| 80 |
-
func (t *TlsClient) Request(method httpclient.HttpMethod, url string, headers httpclient.AuroraHeaders, cookies []*http.Cookie, body io.Reader) (*http.Response, error) {
|
| 81 |
-
req, err := fhttp.NewRequest(string(method), url, body)
|
| 82 |
-
if err != nil {
|
| 83 |
-
return nil, err
|
| 84 |
-
}
|
| 85 |
-
t.handleHeaders(req, headers)
|
| 86 |
-
t.handleCookies(req, cookies)
|
| 87 |
-
if t.ReqBefore != nil {
|
| 88 |
-
if err := t.ReqBefore(req); err != nil {
|
| 89 |
-
return nil, err
|
| 90 |
-
}
|
| 91 |
-
}
|
| 92 |
-
do, err := t.Client.Do(req)
|
| 93 |
-
if err != nil {
|
| 94 |
-
return nil, err
|
| 95 |
-
}
|
| 96 |
-
return convertResponse(do), nil
|
| 97 |
-
}
|
| 98 |
-
|
| 99 |
-
func (t *TlsClient) SetProxy(url string) error {
|
| 100 |
-
return t.Client.SetProxy(url)
|
| 101 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
httpclient/bogdanfinn/tls_client_test.go
DELETED
|
@@ -1,101 +0,0 @@
|
|
| 1 |
-
package bogdanfinn
|
| 2 |
-
|
| 3 |
-
import (
|
| 4 |
-
"aurora/httpclient"
|
| 5 |
-
"fmt"
|
| 6 |
-
"io"
|
| 7 |
-
"net/http"
|
| 8 |
-
"os"
|
| 9 |
-
"strings"
|
| 10 |
-
"testing"
|
| 11 |
-
|
| 12 |
-
"github.com/joho/godotenv"
|
| 13 |
-
)
|
| 14 |
-
|
| 15 |
-
var BaseURL string
|
| 16 |
-
|
| 17 |
-
func init() {
|
| 18 |
-
_ = godotenv.Load(".env")
|
| 19 |
-
BaseURL = os.Getenv("BASE_URL")
|
| 20 |
-
if BaseURL == "" {
|
| 21 |
-
BaseURL = "https://chat.openai.com/backend-anon"
|
| 22 |
-
}
|
| 23 |
-
}
|
| 24 |
-
func TestTlsClient_Request(t *testing.T) {
|
| 25 |
-
client := NewStdClient()
|
| 26 |
-
userAgent := "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36"
|
| 27 |
-
proxy := "http://127.0.0.1:7990"
|
| 28 |
-
client.SetProxy(proxy)
|
| 29 |
-
|
| 30 |
-
apiUrl := BaseURL + "/sentinel/chat-requirements"
|
| 31 |
-
payload := strings.NewReader(`{"conversation_mode_kind":"primary_assistant"}`)
|
| 32 |
-
header := make(httpclient.AuroraHeaders)
|
| 33 |
-
header.Set("Content-Type", "application/json")
|
| 34 |
-
header.Set("User-Agent", userAgent)
|
| 35 |
-
header.Set("Accept", "*/*")
|
| 36 |
-
header.Set("oai-language", "en-US")
|
| 37 |
-
header.Set("origin", "https://chat.openai.com")
|
| 38 |
-
header.Set("referer", "https://chat.openai.com/")
|
| 39 |
-
header.Set("oai-device-id", "c83b24f0-5a9e-4c43-8915-3f67d4332609")
|
| 40 |
-
response, err := client.Request(http.MethodPost, apiUrl, header, nil, payload)
|
| 41 |
-
if err != nil {
|
| 42 |
-
return
|
| 43 |
-
}
|
| 44 |
-
defer response.Body.Close()
|
| 45 |
-
fmt.Println(response.StatusCode)
|
| 46 |
-
if response.StatusCode != 200 {
|
| 47 |
-
fmt.Println("Error: ", response.StatusCode)
|
| 48 |
-
}
|
| 49 |
-
}
|
| 50 |
-
|
| 51 |
-
func TestChatGPTModel(t *testing.T) {
|
| 52 |
-
client := NewStdClient()
|
| 53 |
-
userAgent := "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36"
|
| 54 |
-
proxy := "http://127.0.0.1:7990"
|
| 55 |
-
client.SetProxy(proxy)
|
| 56 |
-
apiUrl := "https://chat.openai.com/backend-anon/models"
|
| 57 |
-
|
| 58 |
-
header := make(httpclient.AuroraHeaders)
|
| 59 |
-
header.Set("Content-Type", "application/json")
|
| 60 |
-
header.Set("User-Agent", userAgent)
|
| 61 |
-
header.Set("Accept", "*/*")
|
| 62 |
-
header.Set("oai-language", "en-US")
|
| 63 |
-
header.Set("origin", "https://chat.openai.com")
|
| 64 |
-
header.Set("referer", "https://chat.openai.com/")
|
| 65 |
-
header.Set("oai-device-id", "c83b24f0-5a9e-4c43-8915-3f67d4332609")
|
| 66 |
-
response, err := client.Request(http.MethodGet, apiUrl, header, nil, nil)
|
| 67 |
-
if err != nil {
|
| 68 |
-
return
|
| 69 |
-
}
|
| 70 |
-
defer response.Body.Close()
|
| 71 |
-
fmt.Println(response.StatusCode)
|
| 72 |
-
if response.StatusCode != 200 {
|
| 73 |
-
fmt.Println("Error: ", response.StatusCode)
|
| 74 |
-
body, _ := io.ReadAll(response.Body)
|
| 75 |
-
fmt.Println(string(body))
|
| 76 |
-
return
|
| 77 |
-
}
|
| 78 |
-
|
| 79 |
-
type EnginesData struct {
|
| 80 |
-
Models []struct {
|
| 81 |
-
Slug string `json:"slug"`
|
| 82 |
-
MaxTokens int `json:"max_tokens"`
|
| 83 |
-
Title string `json:"title"`
|
| 84 |
-
Description string `json:"description"`
|
| 85 |
-
Tags []string `json:"tags"`
|
| 86 |
-
Capabilities struct {
|
| 87 |
-
} `json:"capabilities,omitempty"`
|
| 88 |
-
ProductFeatures struct {
|
| 89 |
-
} `json:"product_features,omitempty"`
|
| 90 |
-
} `json:"models"`
|
| 91 |
-
Categories []struct {
|
| 92 |
-
Category string `json:"category"`
|
| 93 |
-
HumanCategoryName string `json:"human_category_name"`
|
| 94 |
-
SubscriptionLevel string `json:"subscription_level"`
|
| 95 |
-
DefaultModel string `json:"default_model"`
|
| 96 |
-
CodeInterpreterModel string `json:"code_interpreter_model,omitempty"`
|
| 97 |
-
PluginsModel string `json:"plugins_model"`
|
| 98 |
-
} `json:"categories"`
|
| 99 |
-
}
|
| 100 |
-
|
| 101 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
httpclient/resty/resty_client.go
DELETED
|
@@ -1,72 +0,0 @@
|
|
| 1 |
-
package resty
|
| 2 |
-
|
| 3 |
-
import (
|
| 4 |
-
"aurora/util"
|
| 5 |
-
"crypto/tls"
|
| 6 |
-
browser "github.com/EDDYCJY/fake-useragent"
|
| 7 |
-
"github.com/go-resty/resty/v2"
|
| 8 |
-
"net/http"
|
| 9 |
-
"time"
|
| 10 |
-
)
|
| 11 |
-
|
| 12 |
-
type RestyClient struct {
|
| 13 |
-
Client *resty.Client
|
| 14 |
-
}
|
| 15 |
-
|
| 16 |
-
func NewStdClient() *RestyClient {
|
| 17 |
-
client := &RestyClient{
|
| 18 |
-
Client: resty.NewWithClient(&http.Client{
|
| 19 |
-
Transport: &http.Transport{
|
| 20 |
-
// 禁用长连接
|
| 21 |
-
DisableKeepAlives: true,
|
| 22 |
-
// 配置TLS设置,跳过证书验证
|
| 23 |
-
TLSClientConfig: &tls.Config{
|
| 24 |
-
InsecureSkipVerify: true,
|
| 25 |
-
},
|
| 26 |
-
},
|
| 27 |
-
}),
|
| 28 |
-
}
|
| 29 |
-
client.Client.SetBaseURL("https://chat.openai.com")
|
| 30 |
-
client.Client.SetRetryCount(3)
|
| 31 |
-
client.Client.SetRetryWaitTime(5 * time.Second)
|
| 32 |
-
client.Client.SetRetryMaxWaitTime(20 * time.Second)
|
| 33 |
-
|
| 34 |
-
client.Client.SetTimeout(600 * time.Second)
|
| 35 |
-
client.Client.SetHeader("user-agent", browser.Random()).
|
| 36 |
-
SetHeader("accept", "*/*").
|
| 37 |
-
SetHeader("accept-language", "en-US,en;q=0.9").
|
| 38 |
-
SetHeader("cache-control", "no-cache").
|
| 39 |
-
SetHeader("content-type", "application/json").
|
| 40 |
-
SetHeader("oai-language", util.RandomLanguage()).
|
| 41 |
-
SetHeader("pragma", "no-cache").
|
| 42 |
-
SetHeader("sec-ch-ua", `"Google Chrome";v="123", "Not:A-Brand";v="8", "Chromium";v="123"`).
|
| 43 |
-
SetHeader("sec-ch-ua-mobile", "?0").
|
| 44 |
-
SetHeader("sec-ch-ua-platform", "Windows").
|
| 45 |
-
SetHeader("sec-fetch-dest", "empty").
|
| 46 |
-
SetHeader("sec-fetch-mode", "cors").
|
| 47 |
-
SetHeader("sec-fetch-site", "same-origin")
|
| 48 |
-
return client
|
| 49 |
-
}
|
| 50 |
-
|
| 51 |
-
//func (c *RestyClient) Request(method string, url string, headers map[string]string, cookies []*http.Cookie, body io.Reader) (*http.Response, error) {
|
| 52 |
-
//}
|
| 53 |
-
|
| 54 |
-
//func (c *RestyClient) Post(url string, headers map[string]string, cookies []*http.Cookie, body io.Reader) (*http.Response, error) {
|
| 55 |
-
//}
|
| 56 |
-
//
|
| 57 |
-
//func (c *RestyClient) Get(url string, headers map[string]string, cookies []*http.Cookie, body io.Reader) (*http.Response, error) {
|
| 58 |
-
//}
|
| 59 |
-
//
|
| 60 |
-
//func (c *RestyClient) Head(url string, headers map[string]string, cookies []*http.Cookie, body io.Reader) (*http.Response, error) {
|
| 61 |
-
//}
|
| 62 |
-
//
|
| 63 |
-
//func (c *RestyClient) Options(url string, headers map[string]string, cookies []*http.Cookie, body io.Reader) (*http.Response, error) {
|
| 64 |
-
//}
|
| 65 |
-
//
|
| 66 |
-
//func (c *RestyClient) Put(url string, headers map[string]string, cookies []*http.Cookie, body io.Reader) (*http.Response, error) {
|
| 67 |
-
//}
|
| 68 |
-
//
|
| 69 |
-
//func (c *RestyClient) Delete(url string, headers map[string]string, cookies []*http.Cookie, body io.Reader) (*http.Response, error) {
|
| 70 |
-
//}
|
| 71 |
-
//
|
| 72 |
-
//func (c *RestyClient) SetProxy(url string) error {}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
initialize/handlers.go
DELETED
|
@@ -1,110 +0,0 @@
|
|
| 1 |
-
package initialize
|
| 2 |
-
|
| 3 |
-
import (
|
| 4 |
-
duckgoConvert "aurora/conversion/requests/duckgo"
|
| 5 |
-
"aurora/httpclient/bogdanfinn"
|
| 6 |
-
"aurora/internal/duckgo"
|
| 7 |
-
"aurora/internal/proxys"
|
| 8 |
-
officialtypes "aurora/typings/official"
|
| 9 |
-
|
| 10 |
-
"github.com/gin-gonic/gin"
|
| 11 |
-
)
|
| 12 |
-
|
| 13 |
-
type Handler struct {
|
| 14 |
-
proxy *proxys.IProxy
|
| 15 |
-
}
|
| 16 |
-
|
| 17 |
-
func NewHandle(proxy *proxys.IProxy) *Handler {
|
| 18 |
-
return &Handler{proxy: proxy}
|
| 19 |
-
}
|
| 20 |
-
|
| 21 |
-
func optionsHandler(c *gin.Context) {
|
| 22 |
-
// Set headers for CORS
|
| 23 |
-
c.Header("Access-Control-Allow-Origin", "*")
|
| 24 |
-
c.Header("Access-Control-Allow-Methods", "POST")
|
| 25 |
-
c.Header("Access-Control-Allow-Headers", "*")
|
| 26 |
-
c.JSON(200, gin.H{
|
| 27 |
-
"message": "pong",
|
| 28 |
-
})
|
| 29 |
-
}
|
| 30 |
-
|
| 31 |
-
func (h *Handler) duckduckgo(c *gin.Context) {
|
| 32 |
-
var original_request officialtypes.APIRequest
|
| 33 |
-
err := c.BindJSON(&original_request)
|
| 34 |
-
if err != nil {
|
| 35 |
-
c.JSON(400, gin.H{"error": gin.H{
|
| 36 |
-
"message": "Request must be proper JSON",
|
| 37 |
-
"type": "invalid_request_error",
|
| 38 |
-
"param": nil,
|
| 39 |
-
"code": err.Error(),
|
| 40 |
-
}})
|
| 41 |
-
return
|
| 42 |
-
}
|
| 43 |
-
proxyUrl := h.proxy.GetProxyIP()
|
| 44 |
-
client := bogdanfinn.NewStdClient()
|
| 45 |
-
token, err := duckgo.InitXVQD(client, proxyUrl)
|
| 46 |
-
if err != nil {
|
| 47 |
-
c.JSON(500, gin.H{
|
| 48 |
-
"error": err.Error(),
|
| 49 |
-
})
|
| 50 |
-
return
|
| 51 |
-
}
|
| 52 |
-
|
| 53 |
-
translated_request := duckgoConvert.ConvertAPIRequest(original_request)
|
| 54 |
-
response, err := duckgo.POSTconversation(client, translated_request, token, proxyUrl)
|
| 55 |
-
if err != nil {
|
| 56 |
-
c.JSON(500, gin.H{
|
| 57 |
-
"error": "request conversion error",
|
| 58 |
-
})
|
| 59 |
-
return
|
| 60 |
-
}
|
| 61 |
-
|
| 62 |
-
defer response.Body.Close()
|
| 63 |
-
if duckgo.Handle_request_error(c, response) {
|
| 64 |
-
return
|
| 65 |
-
}
|
| 66 |
-
var response_part string
|
| 67 |
-
response_part = duckgo.Handler(c, response, translated_request, original_request.Stream)
|
| 68 |
-
if c.Writer.Status() != 200 {
|
| 69 |
-
return
|
| 70 |
-
}
|
| 71 |
-
if !original_request.Stream {
|
| 72 |
-
c.JSON(200, officialtypes.NewChatCompletionWithModel(response_part, translated_request.Model))
|
| 73 |
-
} else {
|
| 74 |
-
c.String(200, "data: [DONE]\n\n")
|
| 75 |
-
}
|
| 76 |
-
}
|
| 77 |
-
|
| 78 |
-
func (h *Handler) engines(c *gin.Context) {
|
| 79 |
-
type ResData struct {
|
| 80 |
-
ID string `json:"id"`
|
| 81 |
-
Object string `json:"object"`
|
| 82 |
-
Created int `json:"created"`
|
| 83 |
-
OwnedBy string `json:"owned_by"`
|
| 84 |
-
}
|
| 85 |
-
|
| 86 |
-
type JSONData struct {
|
| 87 |
-
Object string `json:"object"`
|
| 88 |
-
Data []ResData `json:"data"`
|
| 89 |
-
}
|
| 90 |
-
|
| 91 |
-
modelS := JSONData{
|
| 92 |
-
Object: "list",
|
| 93 |
-
}
|
| 94 |
-
var resModelList []ResData
|
| 95 |
-
|
| 96 |
-
resModelList = append(resModelList, ResData{
|
| 97 |
-
ID: "gpt-3.5-turbo-0125",
|
| 98 |
-
Object: "model",
|
| 99 |
-
Created: 1685474247,
|
| 100 |
-
OwnedBy: "duckgo",
|
| 101 |
-
})
|
| 102 |
-
resModelList = append(resModelList, ResData{
|
| 103 |
-
ID: "claude-3-haiku-20240307",
|
| 104 |
-
Object: "model",
|
| 105 |
-
Created: 1685474247,
|
| 106 |
-
OwnedBy: "duckgo",
|
| 107 |
-
})
|
| 108 |
-
modelS.Data = resModelList
|
| 109 |
-
c.JSON(200, modelS)
|
| 110 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
initialize/proxy.go
DELETED
|
@@ -1,48 +0,0 @@
|
|
| 1 |
-
package initialize
|
| 2 |
-
|
| 3 |
-
import (
|
| 4 |
-
"aurora/internal/proxys"
|
| 5 |
-
"bufio"
|
| 6 |
-
"log/slog"
|
| 7 |
-
"net/url"
|
| 8 |
-
"os"
|
| 9 |
-
)
|
| 10 |
-
|
| 11 |
-
func checkProxy() *proxys.IProxy {
|
| 12 |
-
var proxies []string
|
| 13 |
-
proxyUrl := os.Getenv("PROXY_URL")
|
| 14 |
-
if proxyUrl != "" {
|
| 15 |
-
proxies = append(proxies, proxyUrl)
|
| 16 |
-
}
|
| 17 |
-
|
| 18 |
-
if _, err := os.Stat("proxies.txt"); err == nil {
|
| 19 |
-
file, _ := os.Open("proxies.txt")
|
| 20 |
-
defer file.Close()
|
| 21 |
-
scanner := bufio.NewScanner(file)
|
| 22 |
-
for scanner.Scan() {
|
| 23 |
-
proxy := scanner.Text()
|
| 24 |
-
parsedURL, err := url.Parse(proxy)
|
| 25 |
-
if err != nil {
|
| 26 |
-
slog.Warn("proxy url is invalid", "url", proxy, "err", err)
|
| 27 |
-
continue
|
| 28 |
-
}
|
| 29 |
-
|
| 30 |
-
// 如果缺少端口信息,不是完整的代理链接
|
| 31 |
-
if parsedURL.Port() != "" {
|
| 32 |
-
proxies = append(proxies, proxy)
|
| 33 |
-
} else {
|
| 34 |
-
continue
|
| 35 |
-
}
|
| 36 |
-
}
|
| 37 |
-
}
|
| 38 |
-
|
| 39 |
-
if len(proxies) == 0 {
|
| 40 |
-
proxy := os.Getenv("http_proxy")
|
| 41 |
-
if proxy != "" {
|
| 42 |
-
proxies = append(proxies, proxy)
|
| 43 |
-
}
|
| 44 |
-
}
|
| 45 |
-
|
| 46 |
-
proxyIP := proxys.NewIProxyIP(proxies)
|
| 47 |
-
return &proxyIP
|
| 48 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
initialize/router.go
DELETED
|
@@ -1,35 +0,0 @@
|
|
| 1 |
-
package initialize
|
| 2 |
-
|
| 3 |
-
import (
|
| 4 |
-
"aurora/middlewares"
|
| 5 |
-
|
| 6 |
-
"github.com/gin-gonic/gin"
|
| 7 |
-
)
|
| 8 |
-
|
| 9 |
-
func RegisterRouter() *gin.Engine {
|
| 10 |
-
handler := NewHandle(
|
| 11 |
-
checkProxy(),
|
| 12 |
-
)
|
| 13 |
-
|
| 14 |
-
router := gin.Default()
|
| 15 |
-
router.Use(middlewares.Cors)
|
| 16 |
-
|
| 17 |
-
router.GET("/", func(c *gin.Context) {
|
| 18 |
-
c.JSON(200, gin.H{
|
| 19 |
-
"message": "Hello, world!",
|
| 20 |
-
})
|
| 21 |
-
})
|
| 22 |
-
|
| 23 |
-
router.GET("/ping", func(c *gin.Context) {
|
| 24 |
-
c.JSON(200, gin.H{
|
| 25 |
-
"message": "pong",
|
| 26 |
-
})
|
| 27 |
-
})
|
| 28 |
-
|
| 29 |
-
router.OPTIONS("/v1/chat/completions", optionsHandler)
|
| 30 |
-
router.OPTIONS("/v1/chat/models", optionsHandler)
|
| 31 |
-
authGroup := router.Group("").Use(middlewares.Authorization)
|
| 32 |
-
authGroup.POST("/v1/chat/completions", handler.duckduckgo)
|
| 33 |
-
authGroup.GET("/v1/models", handler.engines)
|
| 34 |
-
return router
|
| 35 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
internal/duckgo/request.go
DELETED
|
@@ -1,188 +0,0 @@
|
|
| 1 |
-
package duckgo
|
| 2 |
-
|
| 3 |
-
import (
|
| 4 |
-
"aurora/httpclient"
|
| 5 |
-
duckgotypes "aurora/typings/duckgo"
|
| 6 |
-
officialtypes "aurora/typings/official"
|
| 7 |
-
"bufio"
|
| 8 |
-
"bytes"
|
| 9 |
-
"encoding/json"
|
| 10 |
-
"errors"
|
| 11 |
-
"github.com/gin-gonic/gin"
|
| 12 |
-
"io"
|
| 13 |
-
"net/http"
|
| 14 |
-
"strings"
|
| 15 |
-
"sync"
|
| 16 |
-
"time"
|
| 17 |
-
)
|
| 18 |
-
|
| 19 |
-
var (
|
| 20 |
-
Token *XqdgToken
|
| 21 |
-
UA = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
|
| 22 |
-
)
|
| 23 |
-
|
| 24 |
-
type XqdgToken struct {
|
| 25 |
-
Token string `json:"token"`
|
| 26 |
-
M sync.Mutex `json:"-"`
|
| 27 |
-
ExpireAt time.Time `json:"expire"`
|
| 28 |
-
}
|
| 29 |
-
|
| 30 |
-
func InitXVQD(client httpclient.AuroraHttpClient, proxyUrl string) (string, error) {
|
| 31 |
-
if Token == nil {
|
| 32 |
-
Token = &XqdgToken{
|
| 33 |
-
Token: "",
|
| 34 |
-
M: sync.Mutex{},
|
| 35 |
-
}
|
| 36 |
-
}
|
| 37 |
-
Token.M.Lock()
|
| 38 |
-
defer Token.M.Unlock()
|
| 39 |
-
if Token.Token == "" || Token.ExpireAt.Before(time.Now()) {
|
| 40 |
-
status, err := postStatus(client, proxyUrl)
|
| 41 |
-
if err != nil {
|
| 42 |
-
return "", err
|
| 43 |
-
}
|
| 44 |
-
defer status.Body.Close()
|
| 45 |
-
token := status.Header.Get("x-vqd-4")
|
| 46 |
-
if token == "" {
|
| 47 |
-
return "", errors.New("no x-vqd-4 token")
|
| 48 |
-
}
|
| 49 |
-
Token.Token = token
|
| 50 |
-
Token.ExpireAt = time.Now().Add(time.Minute * 5)
|
| 51 |
-
}
|
| 52 |
-
|
| 53 |
-
return Token.Token, nil
|
| 54 |
-
}
|
| 55 |
-
|
| 56 |
-
func postStatus(client httpclient.AuroraHttpClient, proxyUrl string) (*http.Response, error) {
|
| 57 |
-
if proxyUrl != "" {
|
| 58 |
-
client.SetProxy(proxyUrl)
|
| 59 |
-
}
|
| 60 |
-
header := createHeader()
|
| 61 |
-
header.Set("accept", "*/*")
|
| 62 |
-
header.Set("x-vqd-accept", "1")
|
| 63 |
-
response, err := client.Request(httpclient.GET, "https://duckduckgo.com/duckchat/v1/status", header, nil, nil)
|
| 64 |
-
if err != nil {
|
| 65 |
-
return nil, err
|
| 66 |
-
}
|
| 67 |
-
return response, nil
|
| 68 |
-
}
|
| 69 |
-
|
| 70 |
-
func POSTconversation(client httpclient.AuroraHttpClient, request duckgotypes.ApiRequest, token string, proxyUrl string) (*http.Response, error) {
|
| 71 |
-
if proxyUrl != "" {
|
| 72 |
-
client.SetProxy(proxyUrl)
|
| 73 |
-
}
|
| 74 |
-
body_json, err := json.Marshal(request)
|
| 75 |
-
if err != nil {
|
| 76 |
-
return &http.Response{}, err
|
| 77 |
-
}
|
| 78 |
-
header := createHeader()
|
| 79 |
-
header.Set("accept", "text/event-stream")
|
| 80 |
-
header.Set("x-vqd-4", token)
|
| 81 |
-
response, err := client.Request(httpclient.POST, "https://duckduckgo.com/duckchat/v1/chat", header, nil, bytes.NewBuffer(body_json))
|
| 82 |
-
if err != nil {
|
| 83 |
-
return nil, err
|
| 84 |
-
}
|
| 85 |
-
return response, nil
|
| 86 |
-
}
|
| 87 |
-
|
| 88 |
-
func Handle_request_error(c *gin.Context, response *http.Response) bool {
|
| 89 |
-
if response.StatusCode != 200 {
|
| 90 |
-
// Try read response body as JSON
|
| 91 |
-
var error_response map[string]interface{}
|
| 92 |
-
err := json.NewDecoder(response.Body).Decode(&error_response)
|
| 93 |
-
if err != nil {
|
| 94 |
-
// Read response body
|
| 95 |
-
body, _ := io.ReadAll(response.Body)
|
| 96 |
-
c.JSON(response.StatusCode, gin.H{"error": gin.H{
|
| 97 |
-
"message": "Unknown error",
|
| 98 |
-
"type": "internal_server_error",
|
| 99 |
-
"param": nil,
|
| 100 |
-
"code": "500",
|
| 101 |
-
"details": string(body),
|
| 102 |
-
}})
|
| 103 |
-
return true
|
| 104 |
-
}
|
| 105 |
-
c.JSON(response.StatusCode, gin.H{"error": gin.H{
|
| 106 |
-
"message": error_response["detail"],
|
| 107 |
-
"type": response.Status,
|
| 108 |
-
"param": nil,
|
| 109 |
-
"code": "error",
|
| 110 |
-
}})
|
| 111 |
-
return true
|
| 112 |
-
}
|
| 113 |
-
return false
|
| 114 |
-
}
|
| 115 |
-
|
| 116 |
-
func createHeader() httpclient.AuroraHeaders {
|
| 117 |
-
header := make(httpclient.AuroraHeaders)
|
| 118 |
-
header.Set("accept-language", "zh-CN,zh;q=0.9")
|
| 119 |
-
header.Set("content-type", "application/json")
|
| 120 |
-
header.Set("origin", "https://duckduckgo.com")
|
| 121 |
-
header.Set("referer", "https://duckduckgo.com/")
|
| 122 |
-
header.Set("sec-ch-ua", `"Chromium";v="120", "Google Chrome";v="120", "Not-A.Brand";v="99"`)
|
| 123 |
-
header.Set("sec-ch-ua-mobile", "?0")
|
| 124 |
-
header.Set("sec-ch-ua-platform", `"Windows"`)
|
| 125 |
-
header.Set("user-agent", UA)
|
| 126 |
-
return header
|
| 127 |
-
}
|
| 128 |
-
|
| 129 |
-
func Handler(c *gin.Context, response *http.Response, oldRequest duckgotypes.ApiRequest, stream bool) string {
|
| 130 |
-
reader := bufio.NewReader(response.Body)
|
| 131 |
-
if stream {
|
| 132 |
-
// Response content type is text/event-stream
|
| 133 |
-
c.Header("Content-Type", "text/event-stream")
|
| 134 |
-
} else {
|
| 135 |
-
// Response content type is application/json
|
| 136 |
-
c.Header("Content-Type", "application/json")
|
| 137 |
-
}
|
| 138 |
-
|
| 139 |
-
var previousText strings.Builder
|
| 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 |
-
line = line[6:]
|
| 152 |
-
if !strings.HasPrefix(line, "[DONE]") {
|
| 153 |
-
var originalResponse duckgotypes.ApiResponse
|
| 154 |
-
err = json.Unmarshal([]byte(line), &originalResponse)
|
| 155 |
-
if err != nil {
|
| 156 |
-
continue
|
| 157 |
-
}
|
| 158 |
-
if originalResponse.Action != "success" {
|
| 159 |
-
c.JSON(500, gin.H{"error": "Error"})
|
| 160 |
-
return ""
|
| 161 |
-
}
|
| 162 |
-
responseString := ""
|
| 163 |
-
if originalResponse.Message != "" {
|
| 164 |
-
previousText.WriteString(originalResponse.Message)
|
| 165 |
-
translatedResponse := officialtypes.NewChatCompletionChunkWithModel(originalResponse.Message, originalResponse.Model)
|
| 166 |
-
responseString = "data: " + translatedResponse.String() + "\n\n"
|
| 167 |
-
}
|
| 168 |
-
|
| 169 |
-
if responseString == "" {
|
| 170 |
-
continue
|
| 171 |
-
}
|
| 172 |
-
|
| 173 |
-
if stream {
|
| 174 |
-
_, err = c.Writer.WriteString(responseString)
|
| 175 |
-
if err != nil {
|
| 176 |
-
return ""
|
| 177 |
-
}
|
| 178 |
-
c.Writer.Flush()
|
| 179 |
-
}
|
| 180 |
-
} else {
|
| 181 |
-
if stream {
|
| 182 |
-
final_line := officialtypes.StopChunkWithModel("stop", oldRequest.Model)
|
| 183 |
-
c.Writer.WriteString("data: " + final_line.String() + "\n\n")
|
| 184 |
-
}
|
| 185 |
-
}
|
| 186 |
-
}
|
| 187 |
-
return previousText.String()
|
| 188 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
internal/proxys/proxys.go
DELETED
|
@@ -1,35 +0,0 @@
|
|
| 1 |
-
package proxys
|
| 2 |
-
|
| 3 |
-
import "sync"
|
| 4 |
-
|
| 5 |
-
type IProxy struct {
|
| 6 |
-
ips []string
|
| 7 |
-
lock sync.Mutex
|
| 8 |
-
}
|
| 9 |
-
|
| 10 |
-
func NewIProxyIP(ips []string) IProxy {
|
| 11 |
-
return IProxy{
|
| 12 |
-
ips: ips,
|
| 13 |
-
}
|
| 14 |
-
}
|
| 15 |
-
|
| 16 |
-
func (p *IProxy) GetIPS() int {
|
| 17 |
-
return len(p.ips)
|
| 18 |
-
}
|
| 19 |
-
|
| 20 |
-
func (p *IProxy) GetProxyIP() string {
|
| 21 |
-
if p == nil {
|
| 22 |
-
return ""
|
| 23 |
-
}
|
| 24 |
-
|
| 25 |
-
p.lock.Lock()
|
| 26 |
-
defer p.lock.Unlock()
|
| 27 |
-
|
| 28 |
-
if len(p.ips) == 0 {
|
| 29 |
-
return ""
|
| 30 |
-
}
|
| 31 |
-
|
| 32 |
-
proxyIp := p.ips[0]
|
| 33 |
-
p.ips = append(p.ips[1:], proxyIp)
|
| 34 |
-
return proxyIp
|
| 35 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
main.go
CHANGED
|
@@ -1,50 +1,35 @@
|
|
| 1 |
package main
|
| 2 |
|
| 3 |
import (
|
| 4 |
-
"
|
| 5 |
-
"
|
| 6 |
-
"
|
| 7 |
-
"
|
| 8 |
-
"
|
| 9 |
-
"
|
| 10 |
-
|
| 11 |
"github.com/gin-gonic/gin"
|
| 12 |
-
|
| 13 |
-
"github.com/acheong08/endless"
|
| 14 |
-
"github.com/joho/godotenv"
|
| 15 |
)
|
| 16 |
|
| 17 |
-
|
| 18 |
-
|
|
|
|
|
|
|
| 19 |
|
| 20 |
func main() {
|
|
|
|
|
|
|
|
|
|
| 21 |
gin.SetMode(gin.ReleaseMode)
|
| 22 |
-
|
| 23 |
-
|
| 24 |
-
|
| 25 |
-
|
| 26 |
-
|
| 27 |
-
|
| 28 |
-
|
| 29 |
-
|
| 30 |
-
host := os.Getenv("SERVER_HOST")
|
| 31 |
-
port := os.Getenv("SERVER_PORT")
|
| 32 |
-
tlsCert := os.Getenv("TLS_CERT")
|
| 33 |
-
tlsKey := os.Getenv("TLS_KEY")
|
| 34 |
-
|
| 35 |
-
if host == "" {
|
| 36 |
-
host = "0.0.0.0"
|
| 37 |
-
}
|
| 38 |
-
if port == "" {
|
| 39 |
-
port = os.Getenv("PORT")
|
| 40 |
-
if port == "" {
|
| 41 |
-
port = "8080"
|
| 42 |
-
}
|
| 43 |
-
}
|
| 44 |
-
|
| 45 |
-
if tlsCert != "" && tlsKey != "" {
|
| 46 |
-
_ = endless.ListenAndServeTLS(host+":"+port, tlsCert, tlsKey, router)
|
| 47 |
-
} else {
|
| 48 |
-
_ = endless.ListenAndServe(host+":"+port, router)
|
| 49 |
}
|
|
|
|
|
|
|
|
|
|
| 50 |
}
|
|
|
|
| 1 |
package main
|
| 2 |
|
| 3 |
import (
|
| 4 |
+
"fmt"
|
| 5 |
+
"free-gpt3.5-2api/FreeGpt35Pool"
|
| 6 |
+
"free-gpt3.5-2api/ProxyPool"
|
| 7 |
+
"free-gpt3.5-2api/config"
|
| 8 |
+
"free-gpt3.5-2api/router"
|
| 9 |
+
"github.com/aurorax-neo/go-logger"
|
|
|
|
| 10 |
"github.com/gin-gonic/gin"
|
|
|
|
|
|
|
|
|
|
| 11 |
)
|
| 12 |
|
| 13 |
+
func Init() {
|
| 14 |
+
ProxyPool.GetProxyPoolInstance()
|
| 15 |
+
FreeGpt35Pool.GetFreeGpt35PoolInstance()
|
| 16 |
+
}
|
| 17 |
|
| 18 |
func main() {
|
| 19 |
+
// Init
|
| 20 |
+
Init()
|
| 21 |
+
// Initialize HTTP server
|
| 22 |
gin.SetMode(gin.ReleaseMode)
|
| 23 |
+
server := gin.New()
|
| 24 |
+
server.Use(gin.Recovery())
|
| 25 |
+
// 设置路由
|
| 26 |
+
router.SetRouter(server)
|
| 27 |
+
// 提示服务启动
|
| 28 |
+
host := config.Bind
|
| 29 |
+
if config.Bind == "0.0.0.0" {
|
| 30 |
+
host = "127.0.0.1"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 31 |
}
|
| 32 |
+
logger.Logger.Info(fmt.Sprint("Server started on http://", host, ":", config.Port))
|
| 33 |
+
// 启动 HTTP 服务器
|
| 34 |
+
_ = server.Run(fmt.Sprint(config.Bind, ":", config.Port))
|
| 35 |
}
|
middlewares/auth.go
DELETED
|
@@ -1,31 +0,0 @@
|
|
| 1 |
-
package middlewares
|
| 2 |
-
|
| 3 |
-
import (
|
| 4 |
-
"github.com/gin-gonic/gin"
|
| 5 |
-
"os"
|
| 6 |
-
"strings"
|
| 7 |
-
)
|
| 8 |
-
|
| 9 |
-
func Authorization(c *gin.Context) {
|
| 10 |
-
customer_key := os.Getenv("Authorization")
|
| 11 |
-
if customer_key != "" {
|
| 12 |
-
authHeader := c.GetHeader("Authorization")
|
| 13 |
-
if authHeader == "" {
|
| 14 |
-
c.JSON(401, gin.H{"error": "Unauthorized"})
|
| 15 |
-
c.Abort()
|
| 16 |
-
return
|
| 17 |
-
}
|
| 18 |
-
tokenParts := strings.Split(strings.Replace(authHeader, "Bearer ", "", 1)," ")
|
| 19 |
-
customAccessToken := tokenParts[0]
|
| 20 |
-
if customer_key != customAccessToken {
|
| 21 |
-
c.JSON(401, gin.H{"error": "Unauthorized"})
|
| 22 |
-
c.Abort()
|
| 23 |
-
return
|
| 24 |
-
}
|
| 25 |
-
if len(tokenParts) > 1 {
|
| 26 |
-
openaiAccessToken := tokenParts[1]
|
| 27 |
-
c.Request.Header.Set("Authorization", "Bearer " + openaiAccessToken)
|
| 28 |
-
}
|
| 29 |
-
}
|
| 30 |
-
c.Next()
|
| 31 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
middlewares/cors.go
DELETED
|
@@ -1,10 +0,0 @@
|
|
| 1 |
-
package middlewares
|
| 2 |
-
|
| 3 |
-
import "github.com/gin-gonic/gin"
|
| 4 |
-
|
| 5 |
-
func Cors(c *gin.Context) {
|
| 6 |
-
c.Header("Access-Control-Allow-Origin", "*")
|
| 7 |
-
c.Header("Access-Control-Allow-Methods", "*")
|
| 8 |
-
c.Header("Access-Control-Allow-Headers", "*")
|
| 9 |
-
c.Next()
|
| 10 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
queue/queue.go
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package queue
|
| 2 |
+
|
| 3 |
+
type (
|
| 4 |
+
Queue struct {
|
| 5 |
+
start, end *Node
|
| 6 |
+
length int
|
| 7 |
+
}
|
| 8 |
+
Node struct {
|
| 9 |
+
Value interface{}
|
| 10 |
+
next *Node
|
| 11 |
+
}
|
| 12 |
+
)
|
| 13 |
+
|
| 14 |
+
// New 新建一个队列
|
| 15 |
+
func New() *Queue {
|
| 16 |
+
return &Queue{nil, nil, 0}
|
| 17 |
+
}
|
| 18 |
+
|
| 19 |
+
// Dequeue 出队
|
| 20 |
+
func (Q *Queue) Dequeue() *Node {
|
| 21 |
+
if Q.length == 0 {
|
| 22 |
+
return nil
|
| 23 |
+
}
|
| 24 |
+
n := Q.start
|
| 25 |
+
if Q.length == 1 {
|
| 26 |
+
Q.start = nil
|
| 27 |
+
Q.end = nil
|
| 28 |
+
} else {
|
| 29 |
+
Q.start = Q.start.next
|
| 30 |
+
}
|
| 31 |
+
Q.length--
|
| 32 |
+
return n
|
| 33 |
+
}
|
| 34 |
+
|
| 35 |
+
// Enqueue 入队
|
| 36 |
+
func (Q *Queue) Enqueue(value interface{}) {
|
| 37 |
+
n := &Node{value, nil}
|
| 38 |
+
if Q.length == 0 {
|
| 39 |
+
Q.start = n
|
| 40 |
+
Q.end = n
|
| 41 |
+
} else {
|
| 42 |
+
Q.end.next = n
|
| 43 |
+
Q.end = n
|
| 44 |
+
}
|
| 45 |
+
Q.length++
|
| 46 |
+
}
|
| 47 |
+
|
| 48 |
+
// Len 获取队列长度
|
| 49 |
+
func (Q *Queue) Len() int {
|
| 50 |
+
return Q.length
|
| 51 |
+
}
|
| 52 |
+
|
| 53 |
+
// Peek 返回队列的第一个元素
|
| 54 |
+
func (Q *Queue) Peek() *Node {
|
| 55 |
+
if Q.length == 0 {
|
| 56 |
+
return nil
|
| 57 |
+
}
|
| 58 |
+
return Q.start
|
| 59 |
+
}
|
| 60 |
+
|
| 61 |
+
// Remove 移除指定节点
|
| 62 |
+
func (Q *Queue) Remove(n *Node) {
|
| 63 |
+
if Q.length == 0 || n == nil {
|
| 64 |
+
return
|
| 65 |
+
}
|
| 66 |
+
|
| 67 |
+
// 如果移除的是队列的第一个元素
|
| 68 |
+
if n == Q.start {
|
| 69 |
+
Q.start = Q.start.next
|
| 70 |
+
if Q.start == nil {
|
| 71 |
+
// 如果移除后队列为空,则end也应该设置为nil
|
| 72 |
+
Q.end = nil
|
| 73 |
+
}
|
| 74 |
+
Q.length--
|
| 75 |
+
return
|
| 76 |
+
}
|
| 77 |
+
|
| 78 |
+
// 找到n的前一个节点
|
| 79 |
+
prevNode := Q.start
|
| 80 |
+
for prevNode != nil && prevNode.next != n {
|
| 81 |
+
prevNode = prevNode.next
|
| 82 |
+
}
|
| 83 |
+
|
| 84 |
+
if prevNode == nil {
|
| 85 |
+
// 没有找到n的前一个节点(n不在队列中)
|
| 86 |
+
return
|
| 87 |
+
}
|
| 88 |
+
|
| 89 |
+
// 移除节点n
|
| 90 |
+
prevNode.next = n.next
|
| 91 |
+
// 如果移除的是最后一个元素,更新end指针
|
| 92 |
+
if n.next == nil {
|
| 93 |
+
Q.end = prevNode
|
| 94 |
+
}
|
| 95 |
+
Q.length--
|
| 96 |
+
}
|
| 97 |
+
|
| 98 |
+
// Traverse 遍历队列
|
| 99 |
+
func (Q *Queue) Traverse(cb func(n *Node)) {
|
| 100 |
+
if Q.length == 0 {
|
| 101 |
+
return
|
| 102 |
+
}
|
| 103 |
+
for n := Q.start; n != nil; n = n.next {
|
| 104 |
+
cb(n)
|
| 105 |
+
}
|
| 106 |
+
}
|
release.bat
CHANGED
|
@@ -5,10 +5,10 @@ REM 指定编码为 UTF-8
|
|
| 5 |
chcp 65001
|
| 6 |
|
| 7 |
REM 设置要生成的可执行文件的名称
|
| 8 |
-
set OUTPUT_NAME=
|
| 9 |
|
| 10 |
REM 设置 Go 源文件的名称
|
| 11 |
-
SET GOFILE=
|
| 12 |
|
| 13 |
REM 设置输出目录
|
| 14 |
SET OUTPUTDIR=target
|
|
|
|
| 5 |
chcp 65001
|
| 6 |
|
| 7 |
REM 设置要生成的可执行文件的名称
|
| 8 |
+
set OUTPUT_NAME=free-gpt3.5-2api
|
| 9 |
|
| 10 |
REM 设置 Go 源文件的名称
|
| 11 |
+
SET GOFILE=main.go
|
| 12 |
|
| 13 |
REM 设置输出目录
|
| 14 |
SET OUTPUTDIR=target
|
render.yaml
DELETED
|
@@ -1,7 +0,0 @@
|
|
| 1 |
-
services:
|
| 2 |
-
- type: web
|
| 3 |
-
name: duck2api
|
| 4 |
-
env: docker
|
| 5 |
-
dockerfilePath: ./Dockerfile
|
| 6 |
-
plan: free
|
| 7 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
router/middleware.go
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package router
|
| 2 |
+
|
| 3 |
+
import (
|
| 4 |
+
"fmt"
|
| 5 |
+
"free-gpt3.5-2api/common"
|
| 6 |
+
"free-gpt3.5-2api/config"
|
| 7 |
+
"github.com/aurorax-neo/go-logger"
|
| 8 |
+
"github.com/gin-gonic/gin"
|
| 9 |
+
)
|
| 10 |
+
|
| 11 |
+
// Ping 测试接口
|
| 12 |
+
func Ping(c *gin.Context) {
|
| 13 |
+
c.JSON(200, gin.H{
|
| 14 |
+
"message": "pong",
|
| 15 |
+
})
|
| 16 |
+
}
|
| 17 |
+
|
| 18 |
+
// V1Cors 跨域中间件
|
| 19 |
+
func V1Cors(c *gin.Context) {
|
| 20 |
+
// 允许跨域
|
| 21 |
+
c.Writer.Header().Set("Access-Control-Allow-Origin", "*")
|
| 22 |
+
c.Writer.Header().Set("Access-Control-Allow-Origin", "*")
|
| 23 |
+
c.Writer.Header().Set("Access-Control-Allow-Credentials", "true")
|
| 24 |
+
c.Writer.Header().Set("Access-Control-Allow-Headers", "Authorization, Content-Type, Accept")
|
| 25 |
+
c.Writer.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")
|
| 26 |
+
// 如果是OPTIONS请求,直接返回
|
| 27 |
+
if c.Request.Method == "OPTIONS" {
|
| 28 |
+
c.AbortWithStatus(204)
|
| 29 |
+
return
|
| 30 |
+
}
|
| 31 |
+
c.Next()
|
| 32 |
+
}
|
| 33 |
+
|
| 34 |
+
// V1Request 请求中间件
|
| 35 |
+
func V1Request(c *gin.Context) {
|
| 36 |
+
// 打印请求摘要 方法 url ip - user-agent 格式化输出
|
| 37 |
+
infoStr := fmt.Sprint(" -> ", c.Request.Method, " ", c.Request.URL.String(), " - ", c.ClientIP(), " - ", c.Request.Header.Get("User-Agent"))
|
| 38 |
+
logger.Logger.Info(infoStr)
|
| 39 |
+
c.Next()
|
| 40 |
+
}
|
| 41 |
+
|
| 42 |
+
// V1Auth 验证v1 api 的token
|
| 43 |
+
func V1Auth(c *gin.Context) {
|
| 44 |
+
authToken := c.Request.Header.Get("Authorization")
|
| 45 |
+
if authToken == "" && len(config.AUTHORIZATIONS) > 0 {
|
| 46 |
+
common.ErrorResponse(c, 401, "You didn't provide an API key. You need to provide your API key in an Authorization header using Bearer auth (i.e. Authorization: Bearer YOUR_KEY)", nil)
|
| 47 |
+
return
|
| 48 |
+
}
|
| 49 |
+
// 判断 authToken 是否在 config.CONFIG.AUTHORIZATIONS 列表
|
| 50 |
+
if !common.IsStrInArray(authToken, config.AUTHORIZATIONS) {
|
| 51 |
+
common.ErrorResponse(c, 401, "Incorrect API key provided: sk-4yNZz***************************************6mjw.", nil)
|
| 52 |
+
return
|
| 53 |
+
}
|
| 54 |
+
c.Next()
|
| 55 |
+
}
|
| 56 |
+
|
| 57 |
+
// V1Response 响应中间件
|
| 58 |
+
func V1Response(c *gin.Context) {
|
| 59 |
+
c.Next()
|
| 60 |
+
// 打印响应摘要 方法 url 状态码
|
| 61 |
+
infoStr := fmt.Sprint(" <- ", c.Request.Method, " ", c.Request.URL.String(), " - ", c.Writer.Status())
|
| 62 |
+
logger.Logger.Info(infoStr)
|
| 63 |
+
}
|
router/router.go
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package router
|
| 2 |
+
|
| 3 |
+
import (
|
| 4 |
+
v1 "free-gpt3.5-2api/service/v1"
|
| 5 |
+
"free-gpt3.5-2api/service/v1Chat"
|
| 6 |
+
"github.com/gin-gonic/gin"
|
| 7 |
+
"net/http"
|
| 8 |
+
)
|
| 9 |
+
|
| 10 |
+
func SetRouter(router *gin.Engine) {
|
| 11 |
+
router.GET("/", Index)
|
| 12 |
+
router.GET("/ping", Ping)
|
| 13 |
+
v1Router := router.Group("/v1")
|
| 14 |
+
v1Router.Use(V1Cors)
|
| 15 |
+
v1Router.Use(V1Request)
|
| 16 |
+
v1Router.Use(V1Response)
|
| 17 |
+
v1Router.Use(V1Auth)
|
| 18 |
+
v1Router.GET("/tokens", v1.Tokens)
|
| 19 |
+
v1Router.OPTIONS("/chat/completions", nil)
|
| 20 |
+
v1Router.POST("/chat/completions", v1Chat.Completions)
|
| 21 |
+
}
|
| 22 |
+
|
| 23 |
+
func Index(c *gin.Context) {
|
| 24 |
+
c.String(http.StatusOK, "Hello,This is free-gpt3.5-2api.")
|
| 25 |
+
}
|
service/v1/tokens.go
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package v1
|
| 2 |
+
|
| 3 |
+
import (
|
| 4 |
+
"fmt"
|
| 5 |
+
"free-gpt3.5-2api/FreeGpt35Pool"
|
| 6 |
+
"github.com/aurorax-neo/go-logger"
|
| 7 |
+
"github.com/gin-gonic/gin"
|
| 8 |
+
)
|
| 9 |
+
|
| 10 |
+
type TokensResp struct {
|
| 11 |
+
Count int `json:"count"`
|
| 12 |
+
}
|
| 13 |
+
|
| 14 |
+
func Tokens(c *gin.Context) {
|
| 15 |
+
resp := &TokensResp{
|
| 16 |
+
Count: FreeGpt35Pool.GetFreeGpt35PoolInstance().GetSize(),
|
| 17 |
+
}
|
| 18 |
+
logger.Logger.Info(fmt.Sprint("FreeGpt35Pool Tokens: ", resp.Count))
|
| 19 |
+
c.JSON(200, resp)
|
| 20 |
+
}
|
service/v1/util.go
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package v1
|
| 2 |
+
|
| 3 |
+
import (
|
| 4 |
+
"free-gpt3.5-2api/service/v1Chat/reqModel"
|
| 5 |
+
"github.com/google/uuid"
|
| 6 |
+
"math/rand"
|
| 7 |
+
)
|
| 8 |
+
|
| 9 |
+
func MappingModel(model string) string {
|
| 10 |
+
var modelMapping = map[string]string{
|
| 11 |
+
"gpt-3.5-turbo": "text-davinci-002-render-sha",
|
| 12 |
+
"gpt-3.5-turbo-16k": "text-davinci-002-render-sha",
|
| 13 |
+
"gpt-3.5-turbo-16k-0613": "text-davinci-002-render-sha",
|
| 14 |
+
"gpt-3.5-turbo-0301": "text-davinci-002-render-sha",
|
| 15 |
+
"gpt-3.5-turbo-0613": "text-davinci-002-render-sha",
|
| 16 |
+
"gpt-3.5-turbo-1106": "text-davinci-002-render-sha",
|
| 17 |
+
}
|
| 18 |
+
if model == "" {
|
| 19 |
+
return "text-davinci-002-render-sha"
|
| 20 |
+
}
|
| 21 |
+
if v, ok := modelMapping[model]; ok {
|
| 22 |
+
return v
|
| 23 |
+
}
|
| 24 |
+
return "text-davinci-002-render-sha"
|
| 25 |
+
}
|
| 26 |
+
|
| 27 |
+
func GenerateID(length int) string {
|
| 28 |
+
const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
|
| 29 |
+
id := "chatcmpl-"
|
| 30 |
+
for i := 0; i < length; i++ {
|
| 31 |
+
id += string(charset[rand.Intn(len(charset))])
|
| 32 |
+
}
|
| 33 |
+
return id
|
| 34 |
+
}
|
| 35 |
+
|
| 36 |
+
func ApiReq2ChatReq35(apiReq *reqModel.ApiReq) (chatReq *reqModel.ChatReq35) {
|
| 37 |
+
messages := make([]reqModel.ChatMessages, 0)
|
| 38 |
+
for _, apiMessage := range apiReq.Messages {
|
| 39 |
+
chatMessage := reqModel.ChatMessages{
|
| 40 |
+
Author: reqModel.ChatAuthor{
|
| 41 |
+
Role: apiMessage.Role,
|
| 42 |
+
},
|
| 43 |
+
Content: reqModel.ChatContent{
|
| 44 |
+
ContentType: "text",
|
| 45 |
+
Parts: []string{apiMessage.Content},
|
| 46 |
+
},
|
| 47 |
+
}
|
| 48 |
+
messages = append(messages, chatMessage)
|
| 49 |
+
}
|
| 50 |
+
|
| 51 |
+
chatReq = &reqModel.ChatReq35{
|
| 52 |
+
Action: "next",
|
| 53 |
+
Messages: messages,
|
| 54 |
+
ParentMessageId: uuid.New().String(),
|
| 55 |
+
Model: MappingModel(apiReq.Model),
|
| 56 |
+
TimeZoneOffsetMin: -180,
|
| 57 |
+
Suggestions: make([]string, 0),
|
| 58 |
+
HistoryAndTrainingDisabled: true,
|
| 59 |
+
ConversationMode: reqModel.ChatConversationMode{
|
| 60 |
+
Kind: "primary_assistant",
|
| 61 |
+
},
|
| 62 |
+
WebsocketRequestId: uuid.New().String(),
|
| 63 |
+
}
|
| 64 |
+
return chatReq
|
| 65 |
+
}
|
service/v1Chat/completions.go
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package v1Chat
|
| 2 |
+
|
| 3 |
+
import (
|
| 4 |
+
"free-gpt3.5-2api/common"
|
| 5 |
+
"free-gpt3.5-2api/service/v1Chat/reqModel"
|
| 6 |
+
"github.com/gin-gonic/gin"
|
| 7 |
+
"net/http"
|
| 8 |
+
)
|
| 9 |
+
|
| 10 |
+
func Completions(c *gin.Context) {
|
| 11 |
+
// 从请求中获取参数
|
| 12 |
+
apiReq := &reqModel.ApiReq{}
|
| 13 |
+
err := c.BindJSON(apiReq)
|
| 14 |
+
if err != nil {
|
| 15 |
+
common.ErrorResponse(c, http.StatusBadRequest, "Invalid parameter", nil)
|
| 16 |
+
return
|
| 17 |
+
}
|
| 18 |
+
Gpt35Completions(c, apiReq)
|
| 19 |
+
}
|
service/v1Chat/gpt35Completions.go
ADDED
|
@@ -0,0 +1,231 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package v1Chat
|
| 2 |
+
|
| 3 |
+
import (
|
| 4 |
+
"encoding/json"
|
| 5 |
+
"fmt"
|
| 6 |
+
"free-gpt3.5-2api/FreeGpt35"
|
| 7 |
+
"free-gpt3.5-2api/FreeGpt35Pool"
|
| 8 |
+
"free-gpt3.5-2api/common"
|
| 9 |
+
"free-gpt3.5-2api/service/v1"
|
| 10 |
+
"free-gpt3.5-2api/service/v1Chat/reqModel"
|
| 11 |
+
"free-gpt3.5-2api/service/v1Chat/respModel"
|
| 12 |
+
"github.com/aurorax-neo/go-logger"
|
| 13 |
+
fhttp "github.com/bogdanfinn/fhttp"
|
| 14 |
+
"github.com/gin-gonic/gin"
|
| 15 |
+
"github.com/launchdarkly/eventsource"
|
| 16 |
+
"io"
|
| 17 |
+
"net/http"
|
| 18 |
+
"strings"
|
| 19 |
+
)
|
| 20 |
+
|
| 21 |
+
func Gpt35Completions(c *gin.Context, apiReq *reqModel.ApiReq) {
|
| 22 |
+
// 获取 FreeGpt35 实例
|
| 23 |
+
ChatGpt35 := FreeGpt35Pool.GetFreeGpt35PoolInstance().GetFreeGpt35(3)
|
| 24 |
+
if ChatGpt35 == nil {
|
| 25 |
+
errStr := "please restart the program、change the IP address、use a proxy to try again."
|
| 26 |
+
logger.Logger.Error(errStr)
|
| 27 |
+
common.ErrorResponse(c, http.StatusUnauthorized, errStr, nil)
|
| 28 |
+
return
|
| 29 |
+
}
|
| 30 |
+
// 转换请求
|
| 31 |
+
ChatReq35 := v1.ApiReq2ChatReq35(apiReq)
|
| 32 |
+
// 请求参数
|
| 33 |
+
body, err := common.Struct2BytesBuffer(ChatReq35)
|
| 34 |
+
if err != nil {
|
| 35 |
+
logger.Logger.Error(err.Error())
|
| 36 |
+
common.ErrorResponse(c, http.StatusInternalServerError, "", err)
|
| 37 |
+
return
|
| 38 |
+
|
| 39 |
+
}
|
| 40 |
+
// 生成请求
|
| 41 |
+
request, err := ChatGpt35.NewRequest(fhttp.MethodPost, FreeGpt35.ChatUrl, body)
|
| 42 |
+
if err != nil || request == nil {
|
| 43 |
+
errStr := "Request is nil or error"
|
| 44 |
+
logger.Logger.Error("Request is nil or error")
|
| 45 |
+
common.ErrorResponse(c, http.StatusInternalServerError, errStr, err)
|
| 46 |
+
return
|
| 47 |
+
}
|
| 48 |
+
// 设置请求头
|
| 49 |
+
request.Header.Set("Content-Type", "application/json")
|
| 50 |
+
request.Header.Set("oai-device-id", ChatGpt35.FreeAuth.OaiDeviceId)
|
| 51 |
+
request.Header.Set("openai-sentinel-chat-requirements-token", ChatGpt35.FreeAuth.Token)
|
| 52 |
+
if ChatGpt35.FreeAuth.ProofWork.Required {
|
| 53 |
+
request.Header.Set("Openai-Sentinel-Proof-Token", ChatGpt35.FreeAuth.ProofWork.Ospt)
|
| 54 |
+
}
|
| 55 |
+
// 发送请求
|
| 56 |
+
response, err := ChatGpt35.RequestClient.Do(request)
|
| 57 |
+
if err != nil {
|
| 58 |
+
errStr := "RequestClient Do error"
|
| 59 |
+
logger.Logger.Error(fmt.Sprint(errStr, " ", err))
|
| 60 |
+
common.ErrorResponse(c, http.StatusInternalServerError, errStr, err)
|
| 61 |
+
return
|
| 62 |
+
}
|
| 63 |
+
defer func(Body io.ReadCloser) {
|
| 64 |
+
_ = Body.Close()
|
| 65 |
+
}(response.Body)
|
| 66 |
+
if response.StatusCode != http.StatusOK {
|
| 67 |
+
errStr := "Request error"
|
| 68 |
+
logger.Logger.Error(fmt.Sprint(errStr, " ", response.StatusCode))
|
| 69 |
+
common.ErrorResponse(c, response.StatusCode, errStr, nil)
|
| 70 |
+
return
|
| 71 |
+
}
|
| 72 |
+
// 流式返回
|
| 73 |
+
if apiReq.Stream {
|
| 74 |
+
__CompletionsStream(c, apiReq, response)
|
| 75 |
+
} else { // 非流式回应
|
| 76 |
+
__CompletionsNoStream(c, apiReq, response)
|
| 77 |
+
}
|
| 78 |
+
}
|
| 79 |
+
|
| 80 |
+
func __CompletionsStream(c *gin.Context, apiReq *reqModel.ApiReq, resp *fhttp.Response) {
|
| 81 |
+
defer func(Body io.ReadCloser) {
|
| 82 |
+
_ = Body.Close()
|
| 83 |
+
}(resp.Body)
|
| 84 |
+
messageTemp := ""
|
| 85 |
+
decoder := eventsource.NewDecoder(resp.Body)
|
| 86 |
+
// 响应id
|
| 87 |
+
id := v1.GenerateID(29)
|
| 88 |
+
handlingSigns := false
|
| 89 |
+
for {
|
| 90 |
+
event, err := decoder.Decode()
|
| 91 |
+
if err != nil {
|
| 92 |
+
logger.Logger.Error(err.Error())
|
| 93 |
+
common.ErrorResponse(c, http.StatusInternalServerError, "", err)
|
| 94 |
+
break
|
| 95 |
+
}
|
| 96 |
+
name := event.Event()
|
| 97 |
+
data := event.Data()
|
| 98 |
+
// 空白数据不处理
|
| 99 |
+
if data == "" {
|
| 100 |
+
continue
|
| 101 |
+
}
|
| 102 |
+
// 结束标志
|
| 103 |
+
if data == "[DONE]" {
|
| 104 |
+
// 生成响应 stream
|
| 105 |
+
apiRespStream := respModel.NewApiRespStream(id, apiReq.Model, "", "stop")
|
| 106 |
+
// 生成响应 bytes
|
| 107 |
+
bytes, err := common.Struct2Bytes(apiRespStream)
|
| 108 |
+
if err != nil {
|
| 109 |
+
logger.Logger.Error(err.Error())
|
| 110 |
+
continue
|
| 111 |
+
}
|
| 112 |
+
// 发送响应
|
| 113 |
+
c.SSEvent(name, fmt.Sprint(" ", string(bytes)))
|
| 114 |
+
// 结束
|
| 115 |
+
c.SSEvent(name, " [DONE]")
|
| 116 |
+
return
|
| 117 |
+
}
|
| 118 |
+
chatResp35 := &respModel.ChatResp35{}
|
| 119 |
+
err = json.Unmarshal([]byte(data), chatResp35)
|
| 120 |
+
if chatResp35.Error != nil && !handlingSigns {
|
| 121 |
+
logger.Logger.Error(fmt.Sprint(chatResp35.Error))
|
| 122 |
+
common.ErrorResponse(c, http.StatusInternalServerError, "", chatResp35.Error)
|
| 123 |
+
return
|
| 124 |
+
}
|
| 125 |
+
// 脏数据不处理
|
| 126 |
+
if err != nil {
|
| 127 |
+
continue
|
| 128 |
+
}
|
| 129 |
+
// 被block
|
| 130 |
+
if contentIsBlocked(chatResp35) {
|
| 131 |
+
// 返回响应
|
| 132 |
+
common.ErrorResponse(c, http.StatusBadRequest, "content is blocked.", "")
|
| 133 |
+
return
|
| 134 |
+
}
|
| 135 |
+
// 仅处理assistant的消息
|
| 136 |
+
if chatResp35.Message.Author.Role == "assistant" && (chatResp35.Message.Status == "in_progress" || handlingSigns) {
|
| 137 |
+
// handlingSigns 置为 true
|
| 138 |
+
handlingSigns = true
|
| 139 |
+
// 仅处理第一个part
|
| 140 |
+
parts := chatResp35.Message.Content.Parts[0]
|
| 141 |
+
// 去除重复数据
|
| 142 |
+
content := strings.Replace(parts, messageTemp, "", 1)
|
| 143 |
+
messageTemp = parts
|
| 144 |
+
// 空白数据不处理
|
| 145 |
+
if content == "" {
|
| 146 |
+
continue
|
| 147 |
+
}
|
| 148 |
+
// 生成响应 stream
|
| 149 |
+
apiRespStream := respModel.NewApiRespStream(id, apiReq.Model, content, "")
|
| 150 |
+
// 生成响应 bytes
|
| 151 |
+
bytes, err := common.Struct2Bytes(apiRespStream)
|
| 152 |
+
if err != nil {
|
| 153 |
+
logger.Logger.Error(err.Error())
|
| 154 |
+
continue
|
| 155 |
+
}
|
| 156 |
+
// 发送响应
|
| 157 |
+
c.SSEvent(name, fmt.Sprint(" ", string(bytes)))
|
| 158 |
+
// 继续
|
| 159 |
+
continue
|
| 160 |
+
}
|
| 161 |
+
}
|
| 162 |
+
}
|
| 163 |
+
|
| 164 |
+
func __CompletionsNoStream(c *gin.Context, apiReq *reqModel.ApiReq, resp *fhttp.Response) {
|
| 165 |
+
defer func(Body io.ReadCloser) {
|
| 166 |
+
_ = Body.Close()
|
| 167 |
+
}(resp.Body)
|
| 168 |
+
content := ""
|
| 169 |
+
decoder := eventsource.NewDecoder(resp.Body)
|
| 170 |
+
handlingSigns := false
|
| 171 |
+
for {
|
| 172 |
+
event, err := decoder.Decode()
|
| 173 |
+
if err != nil {
|
| 174 |
+
logger.Logger.Error(err.Error())
|
| 175 |
+
common.ErrorResponse(c, http.StatusInternalServerError, "", err)
|
| 176 |
+
return
|
| 177 |
+
}
|
| 178 |
+
data := event.Data()
|
| 179 |
+
// 空白数据不处理
|
| 180 |
+
if data == "" {
|
| 181 |
+
continue
|
| 182 |
+
}
|
| 183 |
+
// 结束标志
|
| 184 |
+
if data == "[DONE]" {
|
| 185 |
+
apiRespObj := respModel.NewApiRespJson(v1.GenerateID(29), apiReq.Model, content)
|
| 186 |
+
// 返回响应
|
| 187 |
+
c.JSON(http.StatusOK, apiRespObj)
|
| 188 |
+
return
|
| 189 |
+
}
|
| 190 |
+
chatResp35 := &respModel.ChatResp35{}
|
| 191 |
+
err = json.Unmarshal([]byte(data), chatResp35)
|
| 192 |
+
if chatResp35.Error != nil && !handlingSigns {
|
| 193 |
+
logger.Logger.Error(fmt.Sprint(chatResp35.Error))
|
| 194 |
+
common.ErrorResponse(c, http.StatusInternalServerError, "", chatResp35.Error)
|
| 195 |
+
return
|
| 196 |
+
}
|
| 197 |
+
// 被block
|
| 198 |
+
if contentIsBlocked(chatResp35) {
|
| 199 |
+
// 返回响应
|
| 200 |
+
common.ErrorResponse(c, http.StatusBadRequest, "content is blocked.", "")
|
| 201 |
+
return
|
| 202 |
+
}
|
| 203 |
+
// 脏数据不处理
|
| 204 |
+
if err != nil {
|
| 205 |
+
continue
|
| 206 |
+
}
|
| 207 |
+
// 仅处理assistant的消息
|
| 208 |
+
if chatResp35.Message.Author.Role == "assistant" && (chatResp35.Message.Status == "in_progress" || handlingSigns) {
|
| 209 |
+
// handlingSigns 置为 true
|
| 210 |
+
handlingSigns = true
|
| 211 |
+
// 如果不包含上一次的数据则不处理
|
| 212 |
+
if !strings.Contains(chatResp35.Message.Content.Parts[0], content) {
|
| 213 |
+
continue
|
| 214 |
+
}
|
| 215 |
+
// 仅处理第一个part
|
| 216 |
+
content = chatResp35.Message.Content.Parts[0]
|
| 217 |
+
// 空白数据不处理
|
| 218 |
+
if content == "" {
|
| 219 |
+
continue
|
| 220 |
+
}
|
| 221 |
+
continue
|
| 222 |
+
}
|
| 223 |
+
}
|
| 224 |
+
}
|
| 225 |
+
|
| 226 |
+
func contentIsBlocked(chatResp35 *respModel.ChatResp35) bool {
|
| 227 |
+
if !chatResp35.IsCompletion && chatResp35.ModerationResponse.Blocked {
|
| 228 |
+
return true
|
| 229 |
+
}
|
| 230 |
+
return false
|
| 231 |
+
}
|
service/v1Chat/reqModel/apiReq.go
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package reqModel
|
| 2 |
+
|
| 3 |
+
type ApiReq struct {
|
| 4 |
+
Messages []ApiMessage `json:"messages"`
|
| 5 |
+
Model string `json:"model"`
|
| 6 |
+
Stream bool `json:"stream"`
|
| 7 |
+
PluginIds []string `json:"plugin_ids"`
|
| 8 |
+
NewMessages string `json:"-"`
|
| 9 |
+
}
|
| 10 |
+
|
| 11 |
+
type ApiMessage struct {
|
| 12 |
+
Role string `json:"role"`
|
| 13 |
+
Content string `json:"content"`
|
| 14 |
+
}
|
service/v1Chat/reqModel/chatReq.go
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package reqModel
|
| 2 |
+
|
| 3 |
+
type ChatAuthor struct {
|
| 4 |
+
Role string `json:"role"`
|
| 5 |
+
}
|
| 6 |
+
|
| 7 |
+
type ChatContent struct {
|
| 8 |
+
ContentType string `json:"content_type"`
|
| 9 |
+
Parts []string `json:"parts"`
|
| 10 |
+
}
|
| 11 |
+
|
| 12 |
+
type ChatMessages struct {
|
| 13 |
+
Author ChatAuthor `json:"author"`
|
| 14 |
+
Content ChatContent `json:"content"`
|
| 15 |
+
}
|
| 16 |
+
|
| 17 |
+
type ChatConversationMode struct {
|
| 18 |
+
Kind string `json:"kind"`
|
| 19 |
+
}
|
| 20 |
+
|
| 21 |
+
type ChatReq35 struct {
|
| 22 |
+
Action string `json:"action"`
|
| 23 |
+
Messages []ChatMessages `json:"messages"`
|
| 24 |
+
ParentMessageId string `json:"parent_message_id"`
|
| 25 |
+
Model string `json:"model"`
|
| 26 |
+
TimeZoneOffsetMin int `json:"timezone_offset_min"`
|
| 27 |
+
Suggestions []string `json:"suggestions"`
|
| 28 |
+
HistoryAndTrainingDisabled bool `json:"history_and_training_disabled"`
|
| 29 |
+
ConversationMode ChatConversationMode `json:"conversation_mode"`
|
| 30 |
+
WebsocketRequestId string `json:"websocket_request_id"`
|
| 31 |
+
}
|