mirror of
https://github.com/OwO-Network/DeepLX.git
synced 2025-04-19 14:13:24 +00:00
Compare commits
106 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
4cee0f3031 | ||
|
cbc3c1be51 | ||
|
84792ead81 | ||
|
0a9ff6b582 | ||
|
d1dbfcc1e5 | ||
|
2400139a8d | ||
|
26a9003b13 | ||
|
85fd738f3e | ||
|
de9888ca5f | ||
|
bbfb808793 | ||
|
4a77cbf30e | ||
|
2d8b84e2c8 | ||
|
1c8beb8a87 | ||
|
f2fa90208d | ||
|
b04139e89d | ||
|
44b6c2915f | ||
|
b89751f78f | ||
|
1f62d85b60 | ||
|
547c735b1f | ||
|
ede6229b0e | ||
|
d98f71d1c5 | ||
|
9edb997f06 | ||
|
62a993bb13 | ||
|
c678e87631 | ||
|
ac8ec23790 | ||
|
9e8c68fc94 | ||
|
1bef182a15 | ||
|
74cf2b9845 | ||
|
f172f59fb6 | ||
|
29ac0e1589 | ||
|
dce5ccd029 | ||
|
56755a1b92 | ||
|
a9a5a914b6 | ||
|
e9b5dedc43 | ||
|
0d73552773 | ||
|
7090eadfd5 | ||
|
f78de58337 | ||
|
8bf6d05603 | ||
|
93a3204eab | ||
|
eeeeeee684 | ||
|
3a4b1507d9 | ||
|
0b93569182 | ||
|
1dfc27518b | ||
|
b44e9b614d | ||
|
56c066a316 | ||
|
9ce414d6a2 | ||
|
a0b110681d | ||
|
7b50838f68 | ||
|
c954c65d0f | ||
|
401b5cb117 | ||
|
90d4d44fc0 | ||
|
e15e63b797 | ||
|
15cca97b81 | ||
|
7b97e65ec7 | ||
|
f75bfc20f7 | ||
|
a191d9d27f | ||
|
e580d64fbf | ||
|
7c4b521050 | ||
|
dedd87c3a8 | ||
|
9fff35f4fe | ||
|
aec7a29b12 | ||
|
41bba5e89f | ||
|
e286a732cb | ||
|
6db098eb8b | ||
|
fab55bfefa | ||
|
2055f022dc | ||
|
b85bb324e2 | ||
|
23693936cf | ||
|
7622b40986 | ||
|
9a3d8f8d75 | ||
|
55b1fccc48 | ||
|
e359bc7eec | ||
|
c965f54072 | ||
|
683b256760 | ||
|
fd1de8250a | ||
|
46087d017a | ||
|
9ca3249919 | ||
|
9b2d712469 | ||
|
5e080f3871 | ||
|
d93ac81ea2 | ||
|
fdcac338fe | ||
|
5489e11113 | ||
|
365cf185a4 | ||
|
6710536837 | ||
|
128225979a | ||
|
cba84471ba | ||
|
7617110dbd | ||
|
7705e7ae1c | ||
|
0bcb4bbfcc | ||
|
8209c080e3 | ||
|
8853c4b44e | ||
|
ea27af8c80 | ||
|
60d1f387e4 | ||
|
ddd4de353d | ||
|
cd4848e739 | ||
|
11b9dbff58 | ||
|
f2d416b189 | ||
|
ecf3ab9aeb | ||
|
d32f667869 | ||
|
558eeaa51c | ||
|
c3787f9dff | ||
|
f3797aa3c3 | ||
|
874fec1446 | ||
|
37a8a25111 | ||
|
ca08fa9804 | ||
|
6688c9d35c |
@ -2,8 +2,8 @@
|
||||
###
|
||||
# @Author: Vincent Young
|
||||
# @Date: 2022-10-20 02:19:06
|
||||
# @LastEditors: Vincent Young
|
||||
# @LastEditTime: 2023-02-18 20:45:52
|
||||
# @LastEditors: Vincent Yang
|
||||
# @LastEditTime: 2024-03-20 16:52:40
|
||||
# @FilePath: /DeepLX/.cross_compile.sh
|
||||
# @Telegram: https://t.me/missuo
|
||||
#
|
||||
@ -30,9 +30,9 @@ for pl in ${PLATFORMS}; do
|
||||
echo "build => ${TARGET}"
|
||||
if [ "${DEBUG_MODE}" == "debug" ]; then
|
||||
CGO_ENABLED=0 go build -trimpath -gcflags "all=-N -l" -o ${TARGET} \
|
||||
-ldflags "-w -s" main.go
|
||||
-ldflags "-w -s" .
|
||||
else
|
||||
CGO_ENABLED=0 go build -trimpath -o ${TARGET} \
|
||||
-ldflags "-w -s" main.go
|
||||
-ldflags "-w -s" .
|
||||
fi
|
||||
done
|
||||
|
27
.github/workflows/ci.yaml
vendored
Normal file
27
.github/workflows/ci.yaml
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
|
||||
name: CI
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Build
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout Code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: '1.24.2'
|
||||
|
||||
- name: Install golint
|
||||
run: go install golang.org/x/lint/golint@latest
|
||||
|
||||
- name: Build
|
||||
run: go build ./...
|
||||
|
||||
- name: Test
|
||||
run: go test ./...
|
1
.github/workflows/docker.yaml
vendored
1
.github/workflows/docker.yaml
vendored
@ -8,7 +8,6 @@ on:
|
||||
- 'v*'
|
||||
|
||||
env:
|
||||
# github.repository as <account>/<repo>
|
||||
DOCKER_IMAGE_NAME: missuo/deeplx
|
||||
GHCR_IMAGE_NAME: ${{ github.repository }}
|
||||
DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
|
||||
|
@ -4,18 +4,18 @@ on:
|
||||
- 'v*'
|
||||
pull_request:
|
||||
|
||||
name: Build Release
|
||||
name: Release
|
||||
jobs:
|
||||
|
||||
Build:
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
runs-on: self-hosted
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/setup-go@v2
|
||||
- uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: "1.19"
|
||||
go-version: "1.24.2"
|
||||
|
||||
- run: bash .cross_compile.sh
|
||||
|
||||
@ -23,5 +23,6 @@ jobs:
|
||||
uses: softprops/action-gh-release@v1
|
||||
with:
|
||||
draft: false
|
||||
generate_release_notes: true
|
||||
files: |
|
||||
dist/*
|
@ -1,10 +1,6 @@
|
||||
# syntax=docker/dockerfile:1
|
||||
|
||||
FROM golang:1.19 AS builder
|
||||
FROM golang:1.24.2 AS builder
|
||||
WORKDIR /go/src/github.com/OwO-Network/DeepLX
|
||||
COPY main.go ./
|
||||
COPY go.mod ./
|
||||
COPY go.sum ./
|
||||
COPY . .
|
||||
RUN go get -d -v ./
|
||||
RUN CGO_ENABLED=0 go build -a -installsuffix cgo -o deeplx .
|
||||
|
||||
|
208
README.md
208
README.md
@ -1,197 +1,47 @@
|
||||
<!--
|
||||
* @Author: Vincent Young
|
||||
* @Date: 2022-10-18 07:32:29
|
||||
* @LastEditors: Vincent Young
|
||||
* @LastEditTime: 2023-10-28 22:45:58
|
||||
* @LastEditors: Vincent Yang
|
||||
* @LastEditTime: 2024-11-30 19:48:00
|
||||
* @FilePath: /DeepLX/README.md
|
||||
* @Telegram: https://t.me/missuo
|
||||
*
|
||||
* Copyright © 2022 by Vincent, All Rights Reserved.
|
||||
-->
|
||||
<h1 align="center">
|
||||
<br>DeepL X<br>
|
||||
</h1>
|
||||
<h4 align="center">Permanently free DeepL API written in Golang.</h4>
|
||||
<p align="center">
|
||||
<a href="https://goreportcard.com/report/github.com/OwO-Network/DeepLX">
|
||||
<img src="https://goreportcard.com/badge/github.com/OwO-Network/DeepLX?style=flat-square">
|
||||
</a>
|
||||
<a href="https://github.com/OwO-Network/DeepLX/releases">
|
||||
<img src="https://img.shields.io/github/release/OwO-Network/DeepLX/all.svg?style=flat-square">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
## **Related Projects**
|
||||
[OwO-Network/PyDeepLX](https://github.com/OwO-Network/PyDeepLX): Python Package for DeepLX.
|
||||
[![GitHub Workflow][1]](https://github.com/OwO-Network/DeepLX/actions)
|
||||
[![Go Version][2]](https://github.com/OwO-Network/DeepLX/blob/main/go.mod)
|
||||
[![Go Report][3]](https://goreportcard.com/badge/github.com/OwO-Network/DeepLX)
|
||||
[![GitHub License][4]](https://github.com/OwO-Network/DeepLX/blob/main/LICENSE)
|
||||
[![Docker Pulls][5]](https://hub.docker.com/r/missuo/deeplx)
|
||||
[![Releases][6]](https://github.com/OwO-Network/DeepLX/releases)
|
||||
|
||||
[OwO-Network/gdeeplx](https://github.com/OwO-Network/gdeeplx): Golang Package for DeepLX.
|
||||
[1]: https://img.shields.io/github/actions/workflow/status/OwO-Network/DeepLX/release.yaml?logo=github
|
||||
[2]: https://img.shields.io/github/go-mod/go-version/OwO-Network/DeepLX?logo=go
|
||||
[3]: https://goreportcard.com/badge/github.com/OwO-Network/DeepLX
|
||||
[4]: https://img.shields.io/github/license/OwO-Network/DeepLX
|
||||
[5]: https://img.shields.io/docker/pulls/missuo/deeplx?logo=docker
|
||||
[6]: https://img.shields.io/github/v/release/OwO-Network/DeepLX?logo=smartthings
|
||||
|
||||
## How to use
|
||||
|
||||
> \[!TIP]
|
||||
>
|
||||
> Learn more about [📘 Using DeepLX](https://deeplx.owo.network) by checking it out.
|
||||
|
||||
## Discussion Group
|
||||
[Telegram Group](https://t.me/+8KDGHKJCxEVkNzll)
|
||||
|
||||
## Description
|
||||
- `DeepLX` is listening to `0.0.0.0:1188` by default. You can modify the listening port by yourself.
|
||||
- `DeepLX` is using `DeepL` Free API.
|
||||
- `DeepLX` is unlimited to the number of requests.
|
||||
## Acknowledgements
|
||||
|
||||
## Usage
|
||||
### Request Parameters
|
||||
- text: string
|
||||
- source_lang: string
|
||||
- target_lang: string
|
||||
### Contributors
|
||||
|
||||
### Response
|
||||
```json
|
||||
{
|
||||
"alternatives": [
|
||||
"no one else",
|
||||
"there is no other person (idiom); there is no one else",
|
||||
"there is no other person"
|
||||
],
|
||||
"code": 200,
|
||||
"data": "there is no one else",
|
||||
"id": 8352115005,
|
||||
"source_lang": "ZH",
|
||||
"target_lang": "EN"
|
||||
}
|
||||
```
|
||||
### Specify the port (Optional)
|
||||
**Thanks to [cijiugechu](https://github.com/cijiugechu) for [his contribution](https://github.com/OwO-Network/DeepLX/commit/4a0920579ea868b0f05ccdff6bceae316bfd5dc8) to make this feature possible for this project!**
|
||||
```bash
|
||||
./deeplx -p 3333
|
||||
# or
|
||||
./deeplx -port 3333
|
||||
```
|
||||
### Set access password (Optional)
|
||||
**To prevent abuse of your public API, you can use a token to restrict translation requests.**
|
||||
```bash
|
||||
./deeplx -token hellodeeplx
|
||||
```
|
||||
<a href="https://github.com/OwO-Network/DeepLX/graphs/contributors">
|
||||
<img src="https://contrib.rocks/image?repo=OwO-Network/DeepLX&anon=0" />
|
||||
</a>
|
||||
|
||||
```
|
||||
curl -X POST http://localhost:1188/translate \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Authorization: Bearer your_access_token" \
|
||||
-d '{
|
||||
"text": "Hello, world!",
|
||||
"source_lang": "EN",
|
||||
"target_lang": "DE"
|
||||
}'
|
||||
## Activity
|
||||

|
||||
|
||||
```
|
||||
|
||||
### Run with Docker
|
||||
```bash
|
||||
# ghcr.io
|
||||
docker run -itd -p 1188:1188 ghcr.io/owo-network/deeplx:latest
|
||||
|
||||
# dockerhub
|
||||
docker run -itd -p 1188:1188 missuo/deeplx:latest
|
||||
```
|
||||
|
||||
### Run with Docker Compose
|
||||
```bash
|
||||
mkdir deeplx
|
||||
cd deeplx
|
||||
wget https://raw.githubusercontent.com/OwO-Network/DeepLX/main/docker-compose.yaml
|
||||
# docker compose v1
|
||||
docker-compose up -d
|
||||
# or docker compose v2
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
### Run on Linux Server
|
||||
```bash
|
||||
bash <(curl -Ls https://raw.githubusercontent.com/OwO-Network/DeepLX/main/install.sh)
|
||||
# or
|
||||
bash <(curl -Ls https://qwq.mx/deeplx)
|
||||
```
|
||||
|
||||
### Run on Mac
|
||||
#### Homebrew (Recommended)
|
||||
**Homebrew has been fixed in the latest version and works perfectly.**
|
||||
```bash
|
||||
brew tap owo-network/brew
|
||||
brew install deeplx
|
||||
brew services start owo-network/brew/deeplx
|
||||
|
||||
# Update to the latest version
|
||||
brew update
|
||||
brew upgrade deeplx
|
||||
brew services restart owo-network/brew/deeplx
|
||||
|
||||
# View the currently installed version
|
||||
brew list --versions deeplx
|
||||
```
|
||||
|
||||
#### Manual
|
||||
1. Download the latest release of DeepL X.
|
||||
```bash
|
||||
sudo mv deeplx_darwin_amd64 /usr/local/bin/deeplx
|
||||
sudo chmod +x /usr/local/bin/deeplx
|
||||
```
|
||||
|
||||
2. Download the `me.missuo.deeplx.plist` to `~/Library/LaunchAgents`.
|
||||
```bash
|
||||
wget https://raw.githubusercontent.com/OwO-Network/DeepLX/main/me.missuo.deeplx.plist -O ~/Library/LaunchAgents/me.missuo.deeplx.plist
|
||||
```
|
||||
3. Run following command.
|
||||
```bash
|
||||
launchctl load ~/Library/LaunchAgents/me.missuo.deeplx.plist
|
||||
launchctl start ~/Library/LaunchAgents/me.missuo.deeplx.plist
|
||||
```
|
||||
|
||||
### Install from AUR
|
||||
```bash
|
||||
paru -S deeplx-bin
|
||||
```
|
||||
|
||||
After installation, start the daemon with the following command.
|
||||
|
||||
```bash
|
||||
systemctl daemon-reload
|
||||
systemctl enable deeplx
|
||||
|
||||
```
|
||||
## Setup on [Bob App](https://bobtranslate.com/)
|
||||
1. Install [bob-plugin-deeplx](https://github.com/missuo/bob-plugin-deeplx) on Bob.
|
||||
|
||||
2. Setup the API. (If you use Brew to install locally you can skip this step)
|
||||

|
||||
|
||||
## Setup on [immersive-translate](https://github.com/immersive-translate/immersive-translate)
|
||||
**It is not recommended, because the `immersive-translate` will send many requests in a short time, which will cause the `DeepL API` to block your IP.**
|
||||
|
||||
1. Install Latest [immersive-translate ](https://github.com/immersive-translate/immersive-translate/releases) on your browser.
|
||||
|
||||
2. Click on **Developer Settings** in the bottom left corner. **Enable Beta experimental features**.
|
||||
|
||||
3. Set the URL. (If you are not deploying locally, you need to change 127.0.0.1 to the IP of your server)
|
||||
|
||||

|
||||
|
||||
## Use in Python
|
||||
```python
|
||||
import httpx, json
|
||||
|
||||
deeplx_api = "http://127.0.0.1:1188/translate"
|
||||
|
||||
data = {
|
||||
"text": "Hello World",
|
||||
"source_lang": "EN",
|
||||
"target_lang": "ZH"
|
||||
}
|
||||
|
||||
post_data = json.dumps(data)
|
||||
r = httpx.post(url = deeplx_api, data = post_data).text
|
||||
print(r)
|
||||
```
|
||||
|
||||
## Backup the Docker Image of zu1k
|
||||
```shell
|
||||
docker run -itd -p 1188:80 missuo/deeplx-bk
|
||||
```
|
||||
**This docker image is not related to this project, as the original author deleted the image, it is only for backup.**
|
||||
|
||||
## Author
|
||||
**DeepL X** © [DeepL X Contributors](https://github.com/OwO-Network/DeepLX/graphs/contributors), Released under the [MIT](./LICENSE) License.<br>
|
||||
## License
|
||||
[](https://app.fossa.com/projects/git%2Bgithub.com%2FOwO-Network%2FDeepLX?ref=badge_large)
|
||||
|
@ -1,8 +1,9 @@
|
||||
version: '3'
|
||||
|
||||
services:
|
||||
deeplx:
|
||||
image: ghcr.io/owo-network/deeplx:latest
|
||||
restart: always
|
||||
ports:
|
||||
- "1188:1188"
|
||||
- "1188:1188"
|
||||
# environment:
|
||||
# - TOKEN=helloworld
|
||||
# - DL_SESSION=xxxxxx
|
54
go.mod
54
go.mod
@ -1,40 +1,58 @@
|
||||
module github.com/OwO-Network/DeepLX
|
||||
|
||||
go 1.19
|
||||
go 1.23.0
|
||||
|
||||
require (
|
||||
github.com/abadojack/whatlanggo v1.0.1
|
||||
github.com/andybalholm/brotli v1.0.5
|
||||
github.com/gin-contrib/cors v1.4.0
|
||||
github.com/andybalholm/brotli v1.1.0
|
||||
github.com/gin-contrib/cors v1.6.0
|
||||
github.com/gin-gonic/gin v1.9.1
|
||||
github.com/imroc/req/v3 v3.48.0
|
||||
github.com/tidwall/gjson v1.14.3
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/bytedance/sonic v1.9.1 // indirect
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.2 // indirect
|
||||
github.com/bytedance/sonic v1.11.2 // indirect
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect
|
||||
github.com/chenzhuoyu/iasm v0.9.1 // indirect
|
||||
github.com/cloudflare/circl v1.4.0 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
|
||||
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||
github.com/go-playground/locales v0.14.1 // indirect
|
||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||
github.com/go-playground/validator/v10 v10.14.0 // indirect
|
||||
github.com/go-playground/validator/v10 v10.19.0 // indirect
|
||||
github.com/go-task/slim-sprig/v3 v3.0.0 // indirect
|
||||
github.com/goccy/go-json v0.10.2 // indirect
|
||||
github.com/google/pprof v0.0.0-20240910150728-a0b0bb1d4134 // indirect
|
||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.4 // indirect
|
||||
github.com/leodido/go-urn v1.2.4 // indirect
|
||||
github.com/mattn/go-isatty v0.0.19 // indirect
|
||||
github.com/klauspost/compress v1.17.9 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.7 // indirect
|
||||
github.com/kr/text v0.2.0 // indirect
|
||||
github.com/leodido/go-urn v1.4.0 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.0.8 // indirect
|
||||
github.com/onsi/ginkgo/v2 v2.20.2 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.1.1 // indirect
|
||||
github.com/quic-go/qpack v0.5.1 // indirect
|
||||
github.com/quic-go/quic-go v0.48.2 // indirect
|
||||
github.com/refraction-networking/utls v1.6.7 // indirect
|
||||
github.com/tidwall/match v1.1.1 // indirect
|
||||
github.com/tidwall/pretty v1.2.0 // indirect
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||
github.com/ugorji/go/codec v1.2.11 // indirect
|
||||
golang.org/x/arch v0.3.0 // indirect
|
||||
golang.org/x/crypto v0.14.0 // indirect
|
||||
golang.org/x/net v0.17.0 // indirect
|
||||
golang.org/x/sys v0.13.0 // indirect
|
||||
golang.org/x/text v0.13.0 // indirect
|
||||
google.golang.org/protobuf v1.30.0 // indirect
|
||||
github.com/ugorji/go/codec v1.2.12 // indirect
|
||||
go.uber.org/mock v0.4.0 // indirect
|
||||
golang.org/x/arch v0.7.0 // indirect
|
||||
golang.org/x/crypto v0.35.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 // indirect
|
||||
golang.org/x/mod v0.21.0 // indirect
|
||||
golang.org/x/net v0.36.0 // indirect
|
||||
golang.org/x/sync v0.11.0 // indirect
|
||||
golang.org/x/sys v0.30.0 // indirect
|
||||
golang.org/x/text v0.22.0 // indirect
|
||||
golang.org/x/tools v0.25.0 // indirect
|
||||
google.golang.org/protobuf v1.34.1 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
162
go.sum
162
go.sum
@ -1,89 +1,106 @@
|
||||
github.com/abadojack/whatlanggo v1.0.1 h1:19N6YogDnf71CTHm3Mp2qhYfkRdyvbgwWdd2EPxJRG4=
|
||||
github.com/abadojack/whatlanggo v1.0.1/go.mod h1:66WiQbSbJBIlOZMsvbKe5m6pzQovxCH9B/K8tQB2uoc=
|
||||
github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs=
|
||||
github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
|
||||
github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M=
|
||||
github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY=
|
||||
github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM=
|
||||
github.com/bytedance/sonic v1.9.1 h1:6iJ6NqdoxCDr6mbY8h18oSO+cShGSMRGCEo7F2h0x8s=
|
||||
github.com/bytedance/sonic v1.9.1/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U=
|
||||
github.com/bytedance/sonic v1.10.0-rc/go.mod h1:ElCzW+ufi8qKqNW0FY314xriJhyJhuoJ3gFZdAHF7NM=
|
||||
github.com/bytedance/sonic v1.11.2 h1:ywfwo0a/3j9HR8wsYGWsIWl2mvRsI950HyoxiBERw5A=
|
||||
github.com/bytedance/sonic v1.11.2/go.mod h1:iZcSUejdk5aukTND/Eu/ivjQuEL0Cu9/rf50Hi0u/g4=
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY=
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 h1:qSGYFH7+jGhDF8vLC+iwCD4WpbV1EBDSzWkJODFLams=
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk=
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d h1:77cEq6EriyTZ0g/qfRdp61a3Uu/AWrgIq2s0ClJV1g0=
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d/go.mod h1:8EPpVsBuRksnlj1mLy4AWzRNQYxauNi62uWcE3to6eA=
|
||||
github.com/chenzhuoyu/iasm v0.9.0/go.mod h1:Xjy2NpN3h7aUqeqM+woSuuvxmIe6+DDsiNLIrkAmYog=
|
||||
github.com/chenzhuoyu/iasm v0.9.1 h1:tUHQJXo3NhBqw6s33wkGn9SP3bvrWLdlVIJ3hQBL7P0=
|
||||
github.com/chenzhuoyu/iasm v0.9.1/go.mod h1:Xjy2NpN3h7aUqeqM+woSuuvxmIe6+DDsiNLIrkAmYog=
|
||||
github.com/cloudflare/circl v1.4.0 h1:BV7h5MgrktNzytKmWjpOtdYrf0lkkbF8YMlBGPhJQrY=
|
||||
github.com/cloudflare/circl v1.4.0/go.mod h1:PDRU+oXvdD7KCtgKxW95M5Z8BpSCJXQORiZFnBQS5QU=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU=
|
||||
github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA=
|
||||
github.com/gin-contrib/cors v1.4.0 h1:oJ6gwtUl3lqV0WEIwM/LxPF1QZ5qe2lGWdY2+bz7y0g=
|
||||
github.com/gin-contrib/cors v1.4.0/go.mod h1:bs9pNM0x/UsmHPBWT2xZz9ROh8xYjYkiURUfmBoMlcs=
|
||||
github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
|
||||
github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk=
|
||||
github.com/gin-contrib/cors v1.6.0 h1:0Z7D/bVhE6ja07lI8CTjTonp6SB07o8bNuFyRbsBUQg=
|
||||
github.com/gin-contrib/cors v1.6.0/go.mod h1:cI+h6iOAyxKRtUtC6iF/Si1KSFvGm/gK+kshxlCi8ro=
|
||||
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
|
||||
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
|
||||
github.com/gin-gonic/gin v1.8.1/go.mod h1:ji8BvRH1azfM+SYow9zQ6SZMvR8qOMZHmsCuWR9tTTk=
|
||||
github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg=
|
||||
github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU=
|
||||
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
|
||||
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
|
||||
github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs=
|
||||
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
|
||||
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
|
||||
github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA=
|
||||
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
|
||||
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
|
||||
github.com/go-playground/validator/v10 v10.10.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos=
|
||||
github.com/go-playground/validator/v10 v10.14.0 h1:vgvQWe3XCz3gIeFDm/HnTIbj6UGmg/+t63MyGU2n5js=
|
||||
github.com/go-playground/validator/v10 v10.14.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU=
|
||||
github.com/goccy/go-json v0.9.7/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
||||
github.com/go-playground/validator/v10 v10.19.0 h1:ol+5Fu+cSq9JD7SoSqe04GMI92cbn0+wvQ3bZ8b/AU4=
|
||||
github.com/go-playground/validator/v10 v10.19.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
|
||||
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
|
||||
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
|
||||
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
|
||||
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/pprof v0.0.0-20240910150728-a0b0bb1d4134 h1:c5FlPPgxOn7kJz3VoPLkQYQXGBS3EklQ4Zfi57uOuqQ=
|
||||
github.com/google/pprof v0.0.0-20240910150728-a0b0bb1d4134/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
|
||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
|
||||
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
|
||||
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
|
||||
github.com/imroc/req/v3 v3.48.0 h1:IYuMGetuwLzOOTzDCquDqs912WNwpsPK0TBXWPIvoqg=
|
||||
github.com/imroc/req/v3 v3.48.0/go.mod h1:weam9gmyb00QnOtu6HXSnk44dNFkIUQb5QdMx13FeUU=
|
||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||
github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA=
|
||||
github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
|
||||
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||
github.com/klauspost/cpuid/v2 v2.2.4 h1:acbojRNwl3o09bUq+yDCtZFc1aiwaAAxtcn8YkZXnvk=
|
||||
github.com/klauspost/cpuid/v2 v2.2.4/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM=
|
||||
github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
|
||||
github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
|
||||
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
|
||||
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
|
||||
github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q=
|
||||
github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4=
|
||||
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
|
||||
github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
|
||||
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
|
||||
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
github.com/pelletier/go-toml/v2 v2.0.1/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo=
|
||||
github.com/pelletier/go-toml/v2 v2.0.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZR9tGQ=
|
||||
github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4=
|
||||
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
||||
github.com/onsi/ginkgo/v2 v2.20.2 h1:7NVCeyIWROIAheY21RLS+3j2bb52W0W82tkberYytp4=
|
||||
github.com/onsi/ginkgo/v2 v2.20.2/go.mod h1:K9gyxPIlb+aIvnZ8bd9Ak+YP18w3APlR+5coaZoE2ag=
|
||||
github.com/onsi/gomega v1.34.1 h1:EUMJIKUjM8sKjYbtxQI9A4z2o+rruxnzNvpknOXie6k=
|
||||
github.com/onsi/gomega v1.34.1/go.mod h1:kU1QgUvBDLXBJq618Xvm2LUX6rSAfRaFRTcdOeDLwwY=
|
||||
github.com/pelletier/go-toml/v2 v2.1.1 h1:LWAJwfNvjQZCFIDKWYQaM62NcYeYViCmWIwmOStowAI=
|
||||
github.com/pelletier/go-toml/v2 v2.1.1/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
|
||||
github.com/quic-go/qpack v0.5.1 h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI=
|
||||
github.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg=
|
||||
github.com/quic-go/quic-go v0.48.2 h1:wsKXZPeGWpMpCGSWqOcqpW2wZYic/8T3aqiOID0/KWE=
|
||||
github.com/quic-go/quic-go v0.48.2/go.mod h1:yBgs3rWBOADpga7F+jJsb6Ybg1LSYiQvwWlLX+/6HMs=
|
||||
github.com/refraction-networking/utls v1.6.7 h1:zVJ7sP1dJx/WtVuITug3qYUq034cDq9B2MR1K67ULZM=
|
||||
github.com/refraction-networking/utls v1.6.7/go.mod h1:BC3O4vQzye5hqpmDTWUqi4P5DDhzJfkV1tdqtawQIH0=
|
||||
github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8=
|
||||
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY=
|
||||
github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/tidwall/gjson v1.14.3 h1:9jvXn7olKEHU1S9vwoMGliaT8jq1vJ7IH/n9zD9Dnlw=
|
||||
github.com/tidwall/gjson v1.14.3/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
|
||||
@ -92,47 +109,40 @@ github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
|
||||
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
|
||||
github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M=
|
||||
github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY=
|
||||
github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU=
|
||||
github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
|
||||
github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE=
|
||||
github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
|
||||
go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU=
|
||||
go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc=
|
||||
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
|
||||
golang.org/x/arch v0.3.0 h1:02VY4/ZcO/gBOH6PUaoiptASxtXU10jazRCP865E97k=
|
||||
golang.org/x/arch v0.3.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
|
||||
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
|
||||
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
|
||||
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/arch v0.7.0 h1:pskyeJh/3AmoQ8CPE95vxHLqp1G1GfGNXTmcl9NEKTc=
|
||||
golang.org/x/arch v0.7.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
|
||||
golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs=
|
||||
golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ=
|
||||
golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 h1:e66Fs6Z+fZTbFBAxKfP3PALWBtpfqks2bwGcexMxgtk=
|
||||
golang.org/x/exp v0.0.0-20240909161429-701f63a606c0/go.mod h1:2TbTHSBQa924w8M6Xs1QcRcFwyucIwBGpK1p2f1YFFY=
|
||||
golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0=
|
||||
golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
|
||||
golang.org/x/net v0.36.0 h1:vWF2fRbw4qslQsQzgFqZff+BItCvGFQqKzKIzx1rmoA=
|
||||
golang.org/x/net v0.36.0/go.mod h1:bFmbeoIPfrw4sMHNhb4J9f6+tPziuGjq7Jk/38fxi1I=
|
||||
golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w=
|
||||
golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
|
||||
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
|
||||
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
|
||||
google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
|
||||
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
|
||||
golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
|
||||
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
|
||||
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||
golang.org/x/tools v0.25.0 h1:oFU9pkj/iJgs+0DT+VMHrx+oBKs/LJMV+Uvg78sl+fE=
|
||||
golang.org/x/tools v0.25.0/go.mod h1:/vtpO8WL1N9cQC3FN5zPqb//fRXskFHbLKk4OW1Q7rg=
|
||||
google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg=
|
||||
google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
|
||||
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
|
||||
|
BIN
img/6a48ba28621f2465028f0.png
Normal file
BIN
img/6a48ba28621f2465028f0.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 287 KiB |
BIN
img/c5c19dd89df6fae1a256d.png
Normal file
BIN
img/c5c19dd89df6fae1a256d.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 592 KiB |
307
main.go
307
main.go
@ -1,319 +1,34 @@
|
||||
/*
|
||||
* @Author: Vincent Young
|
||||
* @Author: Vincent Yang
|
||||
* @Date: 2023-07-01 21:45:34
|
||||
* @LastEditors: Vincent Young
|
||||
* @LastEditTime: 2023-10-28 22:42:08
|
||||
* @LastEditors: Jason Lyu
|
||||
* @LastEditTime: 2025-04-08 13:45:00
|
||||
* @FilePath: /DeepLX/main.go
|
||||
* @Telegram: https://t.me/missuo
|
||||
* @GitHub: https://github.com/missuo
|
||||
*
|
||||
* Copyright © 2023 by Vincent, All Rights Reserved.
|
||||
* Copyright © 2024 by Vincent, All Rights Reserved.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"math/rand"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/abadojack/whatlanggo"
|
||||
"github.com/andybalholm/brotli"
|
||||
"github.com/gin-contrib/cors"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/tidwall/gjson"
|
||||
|
||||
"github.com/OwO-Network/DeepLX/service"
|
||||
)
|
||||
|
||||
var port int
|
||||
var token string
|
||||
|
||||
func init() {
|
||||
const (
|
||||
defaultPort = 1188
|
||||
usage = "set up the port to listen on"
|
||||
)
|
||||
|
||||
flag.IntVar(&port, "port", defaultPort, usage)
|
||||
flag.IntVar(&port, "p", defaultPort, usage)
|
||||
flag.StringVar(&token, "token", "", "set the access token for /translate endpoint")
|
||||
|
||||
log.SetFlags(log.LstdFlags | log.Lshortfile)
|
||||
}
|
||||
|
||||
type Lang struct {
|
||||
SourceLangUserSelected string `json:"source_lang_user_selected"`
|
||||
TargetLang string `json:"target_lang"`
|
||||
}
|
||||
|
||||
type CommonJobParams struct {
|
||||
WasSpoken bool `json:"wasSpoken"`
|
||||
TranscribeAS string `json:"transcribe_as"`
|
||||
// RegionalVariant string `json:"regionalVariant"`
|
||||
}
|
||||
|
||||
type Params struct {
|
||||
Texts []Text `json:"texts"`
|
||||
Splitting string `json:"splitting"`
|
||||
Lang Lang `json:"lang"`
|
||||
Timestamp int64 `json:"timestamp"`
|
||||
CommonJobParams CommonJobParams `json:"commonJobParams"`
|
||||
}
|
||||
|
||||
type Text struct {
|
||||
Text string `json:"text"`
|
||||
RequestAlternatives int `json:"requestAlternatives"`
|
||||
}
|
||||
|
||||
type PostData struct {
|
||||
Jsonrpc string `json:"jsonrpc"`
|
||||
Method string `json:"method"`
|
||||
ID int64 `json:"id"`
|
||||
Params Params `json:"params"`
|
||||
}
|
||||
|
||||
func initData(sourceLang string, targetLang string) *PostData {
|
||||
return &PostData{
|
||||
Jsonrpc: "2.0",
|
||||
Method: "LMT_handle_texts",
|
||||
Params: Params{
|
||||
Splitting: "newlines",
|
||||
Lang: Lang{
|
||||
SourceLangUserSelected: sourceLang,
|
||||
TargetLang: targetLang,
|
||||
},
|
||||
CommonJobParams: CommonJobParams{
|
||||
WasSpoken: false,
|
||||
TranscribeAS: "",
|
||||
// RegionalVariant: "en-US",
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func getICount(translateText string) int64 {
|
||||
return int64(strings.Count(translateText, "i"))
|
||||
}
|
||||
|
||||
func getRandomNumber() int64 {
|
||||
rand.Seed(time.Now().Unix())
|
||||
num := rand.Int63n(99999) + 8300000
|
||||
return num * 1000
|
||||
}
|
||||
|
||||
func getTimeStamp(iCount int64) int64 {
|
||||
ts := time.Now().UnixMilli()
|
||||
if iCount != 0 {
|
||||
iCount = iCount + 1
|
||||
return ts - ts%iCount + iCount
|
||||
} else {
|
||||
return ts
|
||||
}
|
||||
}
|
||||
|
||||
type ResData struct {
|
||||
TransText string `json:"text"`
|
||||
SourceLang string `json:"source_lang"`
|
||||
TargetLang string `json:"target_lang"`
|
||||
}
|
||||
|
||||
func main() {
|
||||
// Parsing the command-line flags
|
||||
flag.Parse()
|
||||
cfg := service.InitConfig()
|
||||
|
||||
// Displaying initialization information
|
||||
fmt.Printf("DeepL X has been successfully launched! Listening on 0.0.0.0:%v\n", port)
|
||||
fmt.Printf("DeepL X has been successfully launched! Listening on %v:%v\n", cfg.IP, cfg.Port)
|
||||
fmt.Println("Developed by sjlleo <i@leo.moe> and missuo <me@missuo.me>.")
|
||||
|
||||
// Check if the token is set in the environment variable
|
||||
if token == "" {
|
||||
envToken, ok := os.LookupEnv("TOKEN")
|
||||
if ok {
|
||||
token = envToken
|
||||
fmt.Println("Access token is set from the environment variable.")
|
||||
}
|
||||
}
|
||||
|
||||
if token == "" {
|
||||
fmt.Println("Access token is not set. You can set it using the -token flag or the TOKEN environment variable.")
|
||||
} else {
|
||||
fmt.Println("Access token is set. Use the Authorization: Bearer <token> header to access /translate.")
|
||||
}
|
||||
|
||||
// Generating a random ID
|
||||
id := getRandomNumber()
|
||||
|
||||
// Setting the application to release mode
|
||||
gin.SetMode(gin.ReleaseMode)
|
||||
r := gin.Default()
|
||||
r.Use(cors.Default())
|
||||
|
||||
// Defining the root endpoint which returns the project details
|
||||
r.GET("/", func(c *gin.Context) {
|
||||
c.JSON(200, gin.H{
|
||||
"code": 200,
|
||||
"message": "DeepL Free API, Developed by sjlleo <i@leo.moe> and missuo <me@missuo.me>. Go to /translate with POST. http://github.com/OwO-Network/DeepLX",
|
||||
})
|
||||
})
|
||||
|
||||
// Defining the translation endpoint which receives translation requests and returns translations
|
||||
r.POST("/translate", func(c *gin.Context) {
|
||||
reqj := ResData{}
|
||||
c.BindJSON(&reqj)
|
||||
|
||||
if token != "" {
|
||||
providedToken := c.GetHeader("Authorization")
|
||||
if providedToken != "Bearer "+token {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{
|
||||
"code": http.StatusUnauthorized,
|
||||
"message": "Invalid access token",
|
||||
})
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Extracting details from the request JSON
|
||||
sourceLang := reqj.SourceLang
|
||||
targetLang := reqj.TargetLang
|
||||
translateText := reqj.TransText
|
||||
|
||||
// If source language is not specified, auto-detect it
|
||||
if sourceLang == "" {
|
||||
lang := whatlanggo.DetectLang(translateText)
|
||||
deepLLang := strings.ToUpper(lang.Iso6391())
|
||||
sourceLang = deepLLang
|
||||
}
|
||||
// If target language is not specified, set it to English
|
||||
if targetLang == "" {
|
||||
targetLang = "EN"
|
||||
}
|
||||
// Handling empty translation text
|
||||
if translateText == "" {
|
||||
c.JSON(http.StatusNotFound, gin.H{
|
||||
"code": http.StatusNotFound,
|
||||
"message": "No Translate Text Found",
|
||||
})
|
||||
return
|
||||
}
|
||||
// Preparing the request data for the DeepL API
|
||||
url := "https://www2.deepl.com/jsonrpc"
|
||||
id = id + 1
|
||||
postData := initData(sourceLang, targetLang)
|
||||
text := Text{
|
||||
Text: translateText,
|
||||
RequestAlternatives: 3,
|
||||
}
|
||||
postData.ID = id
|
||||
postData.Params.Texts = append(postData.Params.Texts, text)
|
||||
postData.Params.Timestamp = getTimeStamp(getICount(translateText))
|
||||
|
||||
// Marshalling the request data to JSON and making necessary string replacements
|
||||
post_byte, _ := json.Marshal(postData)
|
||||
postStr := string(post_byte)
|
||||
|
||||
// Adding spaces to the JSON string based on the ID to adhere to DeepL's request formatting rules
|
||||
if (id+5)%29 == 0 || (id+3)%13 == 0 {
|
||||
postStr = strings.Replace(postStr, "\"method\":\"", "\"method\" : \"", -1)
|
||||
} else {
|
||||
postStr = strings.Replace(postStr, "\"method\":\"", "\"method\": \"", -1)
|
||||
}
|
||||
|
||||
// Creating a new HTTP POST request with the JSON data as the body
|
||||
post_byte = []byte(postStr)
|
||||
reader := bytes.NewReader(post_byte)
|
||||
request, err := http.NewRequest("POST", url, reader)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return
|
||||
}
|
||||
|
||||
// Setting HTTP headers to mimic a request from the DeepL iOS App
|
||||
request.Header.Set("Content-Type", "application/json")
|
||||
request.Header.Set("Accept", "*/*")
|
||||
request.Header.Set("x-app-os-name", "iOS")
|
||||
request.Header.Set("x-app-os-version", "16.3.0")
|
||||
request.Header.Set("Accept-Language", "en-US,en;q=0.9")
|
||||
request.Header.Set("Accept-Encoding", "gzip, deflate, br")
|
||||
request.Header.Set("x-app-device", "iPhone13,2")
|
||||
request.Header.Set("User-Agent", "DeepL-iOS/2.9.1 iOS 16.3.0 (iPhone13,2)")
|
||||
request.Header.Set("x-app-build", "510265")
|
||||
request.Header.Set("x-app-version", "2.9.1")
|
||||
request.Header.Set("Connection", "keep-alive")
|
||||
|
||||
// Making the HTTP request to the DeepL API
|
||||
client := &http.Client{}
|
||||
resp, err := client.Do(request)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
// Handling potential Brotli compressed response body
|
||||
var bodyReader io.Reader
|
||||
switch resp.Header.Get("Content-Encoding") {
|
||||
case "br":
|
||||
bodyReader = brotli.NewReader(resp.Body)
|
||||
default:
|
||||
bodyReader = resp.Body
|
||||
}
|
||||
|
||||
// Reading the response body and parsing it with gjson
|
||||
body, err := io.ReadAll(bodyReader)
|
||||
// body, _ := io.ReadAll(resp.Body)
|
||||
res := gjson.ParseBytes(body)
|
||||
|
||||
// Handling various response statuses and potential errors
|
||||
if res.Get("error.code").String() == "-32600" {
|
||||
log.Println(res.Get("error").String())
|
||||
c.JSON(http.StatusNotAcceptable, gin.H{
|
||||
"code": http.StatusNotAcceptable,
|
||||
"message": "Invalid targetLang",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
if resp.StatusCode == http.StatusTooManyRequests {
|
||||
c.JSON(http.StatusTooManyRequests, gin.H{
|
||||
"code": http.StatusTooManyRequests,
|
||||
"message": "Too Many Requests",
|
||||
})
|
||||
} else {
|
||||
var alternatives []string
|
||||
res.Get("result.texts.0.alternatives").ForEach(func(key, value gjson.Result) bool {
|
||||
alternatives = append(alternatives, value.Get("text").String())
|
||||
return true
|
||||
})
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"code": http.StatusOK,
|
||||
"id": id,
|
||||
"data": res.Get("result.texts.0.text").String(),
|
||||
"alternatives": alternatives,
|
||||
"source_lang": sourceLang,
|
||||
"target_lang": targetLang,
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
// Catch-all route to handle undefined paths
|
||||
r.NoRoute(func(c *gin.Context) {
|
||||
c.JSON(http.StatusNotFound, gin.H{
|
||||
"code": http.StatusNotFound,
|
||||
"message": "Path not found",
|
||||
})
|
||||
})
|
||||
|
||||
// Determining which port to run the server on, with a fallback to a default port
|
||||
envPort, ok := os.LookupEnv("PORT")
|
||||
if ok {
|
||||
r.Run(":" + envPort)
|
||||
} else {
|
||||
r.Run(fmt.Sprintf(":%v", port))
|
||||
}
|
||||
app := service.Router(cfg)
|
||||
app.Run(fmt.Sprintf("%v:%v", cfg.IP, cfg.Port))
|
||||
}
|
||||
|
75
service/config.go
Normal file
75
service/config.go
Normal file
@ -0,0 +1,75 @@
|
||||
/*
|
||||
* @Author: Vincent Yang
|
||||
* @Date: 2024-04-23 00:39:03
|
||||
* @LastEditors: Jason Lyu
|
||||
* @LastEditTime: 2025-04-08 13:45:00
|
||||
* @FilePath: /DeepLX/config.go
|
||||
* @Telegram: https://t.me/missuo
|
||||
* @GitHub: https://github.com/missuo
|
||||
*
|
||||
* Copyright © 2024 by Vincent, All Rights Reserved.
|
||||
*/
|
||||
|
||||
package service
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
IP string
|
||||
Port int
|
||||
Token string
|
||||
DlSession string
|
||||
Proxy string
|
||||
}
|
||||
|
||||
func InitConfig() *Config {
|
||||
cfg := &Config{
|
||||
IP: "0.0.0.0",
|
||||
Port: 1188,
|
||||
}
|
||||
|
||||
// IP flag
|
||||
if ip, ok := os.LookupEnv("IP"); ok && ip != "" {
|
||||
cfg.IP = ip
|
||||
}
|
||||
flag.StringVar(&cfg.IP, "ip", cfg.IP, "set up the IP address to bind to")
|
||||
flag.StringVar(&cfg.IP, "i", cfg.IP, "set up the IP address to bind to")
|
||||
|
||||
// Port flag
|
||||
if port, ok := os.LookupEnv("PORT"); ok && port != "" {
|
||||
fmt.Sscanf(port, "%d", &cfg.Port)
|
||||
}
|
||||
flag.IntVar(&cfg.Port, "port", cfg.Port, "set up the port to listen on")
|
||||
flag.IntVar(&cfg.Port, "p", cfg.Port, "set up the port to listen on")
|
||||
|
||||
// DL Session flag
|
||||
flag.StringVar(&cfg.DlSession, "s", "", "set the dl-session for /v1/translate endpoint")
|
||||
if cfg.DlSession == "" {
|
||||
if dlSession, ok := os.LookupEnv("DL_SESSION"); ok {
|
||||
cfg.DlSession = dlSession
|
||||
}
|
||||
}
|
||||
|
||||
// Access token flag
|
||||
flag.StringVar(&cfg.Token, "token", "", "set the access token for /translate endpoint")
|
||||
if cfg.Token == "" {
|
||||
if token, ok := os.LookupEnv("TOKEN"); ok {
|
||||
cfg.Token = token
|
||||
}
|
||||
}
|
||||
|
||||
// HTTP Proxy flag
|
||||
flag.StringVar(&cfg.Proxy, "proxy", "", "set the proxy URL for HTTP requests")
|
||||
if cfg.Proxy == "" {
|
||||
if proxy, ok := os.LookupEnv("PROXY"); ok {
|
||||
cfg.Proxy = proxy
|
||||
}
|
||||
}
|
||||
|
||||
flag.Parse()
|
||||
return cfg
|
||||
}
|
275
service/service.go
Normal file
275
service/service.go
Normal file
@ -0,0 +1,275 @@
|
||||
/*
|
||||
* @Author: Vincent Yang
|
||||
* @Date: 2023-07-01 21:45:34
|
||||
* @LastEditors: Jason Lyu
|
||||
* @LastEditTime: 2025-04-08 13:45:00
|
||||
* @FilePath: /DeepLX/main.go
|
||||
* @Telegram: https://t.me/missuo
|
||||
* @GitHub: https://github.com/missuo
|
||||
*
|
||||
* Copyright © 2024 by Vincent, All Rights Reserved.
|
||||
*/
|
||||
|
||||
package service
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/gin-contrib/cors"
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"github.com/OwO-Network/DeepLX/translate"
|
||||
)
|
||||
|
||||
func authMiddleware(cfg *Config) gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
if cfg.Token != "" {
|
||||
providedTokenInQuery := c.Query("token")
|
||||
providedTokenInHeader := c.GetHeader("Authorization")
|
||||
|
||||
// Compatability with the Bearer token format
|
||||
if providedTokenInHeader != "" {
|
||||
parts := strings.Split(providedTokenInHeader, " ")
|
||||
if len(parts) == 2 {
|
||||
if parts[0] == "Bearer" || parts[0] == "DeepL-Auth-Key" {
|
||||
providedTokenInHeader = parts[1]
|
||||
} else {
|
||||
providedTokenInHeader = ""
|
||||
}
|
||||
} else {
|
||||
providedTokenInHeader = ""
|
||||
}
|
||||
}
|
||||
|
||||
if providedTokenInHeader != cfg.Token && providedTokenInQuery != cfg.Token {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{
|
||||
"code": http.StatusUnauthorized,
|
||||
"message": "Invalid access token",
|
||||
})
|
||||
c.Abort()
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
c.Next()
|
||||
}
|
||||
}
|
||||
|
||||
type PayloadFree struct {
|
||||
TransText string `json:"text"`
|
||||
SourceLang string `json:"source_lang"`
|
||||
TargetLang string `json:"target_lang"`
|
||||
TagHandling string `json:"tag_handling"`
|
||||
}
|
||||
|
||||
type PayloadAPI struct {
|
||||
Text []string `json:"text"`
|
||||
TargetLang string `json:"target_lang"`
|
||||
SourceLang string `json:"source_lang"`
|
||||
TagHandling string `json:"tag_handling"`
|
||||
}
|
||||
|
||||
func Router(cfg *Config) *gin.Engine {
|
||||
// Set Proxy
|
||||
proxyURL := os.Getenv("PROXY")
|
||||
if proxyURL == "" {
|
||||
proxyURL = cfg.Proxy
|
||||
}
|
||||
if proxyURL != "" {
|
||||
proxy, err := url.Parse(proxyURL)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to parse proxy URL: %v", err)
|
||||
}
|
||||
http.DefaultTransport = &http.Transport{
|
||||
Proxy: http.ProxyURL(proxy),
|
||||
}
|
||||
}
|
||||
|
||||
if cfg.Token != "" {
|
||||
fmt.Println("Access token is set.")
|
||||
}
|
||||
|
||||
r := gin.Default()
|
||||
r.Use(cors.Default())
|
||||
|
||||
// Defining the root endpoint which returns the project details
|
||||
r.GET("/", func(c *gin.Context) {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"code": http.StatusOK,
|
||||
"message": "DeepL Free API, Developed by sjlleo and missuo. Go to /translate with POST. http://github.com/OwO-Network/DeepLX",
|
||||
})
|
||||
})
|
||||
|
||||
// Free API endpoint, No Pro Account required
|
||||
r.POST("/translate", authMiddleware(cfg), func(c *gin.Context) {
|
||||
req := PayloadFree{}
|
||||
c.BindJSON(&req)
|
||||
|
||||
sourceLang := req.SourceLang
|
||||
targetLang := req.TargetLang
|
||||
translateText := req.TransText
|
||||
tagHandling := req.TagHandling
|
||||
|
||||
proxyURL := cfg.Proxy
|
||||
|
||||
if tagHandling != "" && tagHandling != "html" && tagHandling != "xml" {
|
||||
c.JSON(http.StatusBadRequest, gin.H{
|
||||
"code": http.StatusBadRequest,
|
||||
"message": "Invalid tag_handling value. Allowed values are 'html' and 'xml'.",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
result, err := translate.TranslateByDeepLX(sourceLang, targetLang, translateText, tagHandling, proxyURL, "")
|
||||
if err != nil {
|
||||
log.Fatalf("Translation failed: %s", err)
|
||||
}
|
||||
|
||||
if result.Code == http.StatusOK {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"code": http.StatusOK,
|
||||
"id": result.ID,
|
||||
"data": result.Data,
|
||||
"alternatives": result.Alternatives,
|
||||
"source_lang": result.SourceLang,
|
||||
"target_lang": result.TargetLang,
|
||||
"method": result.Method,
|
||||
})
|
||||
} else {
|
||||
c.JSON(result.Code, gin.H{
|
||||
"code": result.Code,
|
||||
"message": result.Message,
|
||||
})
|
||||
|
||||
}
|
||||
})
|
||||
|
||||
// Pro API endpoint, Pro Account required
|
||||
r.POST("/v1/translate", authMiddleware(cfg), func(c *gin.Context) {
|
||||
req := PayloadFree{}
|
||||
c.BindJSON(&req)
|
||||
|
||||
sourceLang := req.SourceLang
|
||||
targetLang := req.TargetLang
|
||||
translateText := req.TransText
|
||||
tagHandling := req.TagHandling
|
||||
proxyURL := cfg.Proxy
|
||||
|
||||
dlSession := cfg.DlSession
|
||||
|
||||
if tagHandling != "" && tagHandling != "html" && tagHandling != "xml" {
|
||||
c.JSON(http.StatusBadRequest, gin.H{
|
||||
"code": http.StatusBadRequest,
|
||||
"message": "Invalid tag_handling value. Allowed values are 'html' and 'xml'.",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
cookie := c.GetHeader("Cookie")
|
||||
if cookie != "" {
|
||||
dlSession = strings.Replace(cookie, "dl_session=", "", -1)
|
||||
}
|
||||
|
||||
if dlSession == "" {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{
|
||||
"code": http.StatusUnauthorized,
|
||||
"message": "No dl_session Found",
|
||||
})
|
||||
return
|
||||
} else if strings.Contains(dlSession, ".") {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{
|
||||
"code": http.StatusUnauthorized,
|
||||
"message": "Your account is not a Pro account. Please upgrade your account or switch to a different account.",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
result, err := translate.TranslateByDeepLX(sourceLang, targetLang, translateText, tagHandling, proxyURL, dlSession)
|
||||
if err != nil {
|
||||
log.Fatalf("Translation failed: %s", err)
|
||||
}
|
||||
|
||||
if result.Code == http.StatusOK {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"code": http.StatusOK,
|
||||
"id": result.ID,
|
||||
"data": result.Data,
|
||||
"alternatives": result.Alternatives,
|
||||
"source_lang": result.SourceLang,
|
||||
"target_lang": result.TargetLang,
|
||||
"method": result.Method,
|
||||
})
|
||||
} else {
|
||||
c.JSON(result.Code, gin.H{
|
||||
"code": result.Code,
|
||||
"message": result.Message,
|
||||
})
|
||||
|
||||
}
|
||||
})
|
||||
|
||||
// Free API endpoint, Consistent with the official API format
|
||||
r.POST("/v2/translate", authMiddleware(cfg), func(c *gin.Context) {
|
||||
proxyURL := cfg.Proxy
|
||||
|
||||
var translateText string
|
||||
var targetLang string
|
||||
|
||||
translateText = c.PostForm("text")
|
||||
targetLang = c.PostForm("target_lang")
|
||||
|
||||
if translateText == "" || targetLang == "" {
|
||||
var jsonData struct {
|
||||
Text []string `json:"text"`
|
||||
TargetLang string `json:"target_lang"`
|
||||
}
|
||||
|
||||
if err := c.BindJSON(&jsonData); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{
|
||||
"code": http.StatusBadRequest,
|
||||
"message": "Invalid request payload",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
translateText = strings.Join(jsonData.Text, "\n")
|
||||
targetLang = jsonData.TargetLang
|
||||
}
|
||||
|
||||
result, err := translate.TranslateByDeepLX("", targetLang, translateText, "", proxyURL, "")
|
||||
if err != nil {
|
||||
log.Fatalf("Translation failed: %s", err)
|
||||
}
|
||||
|
||||
if result.Code == http.StatusOK {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"translations": []map[string]interface{}{
|
||||
{
|
||||
"detected_source_language": result.SourceLang,
|
||||
"text": result.Data,
|
||||
},
|
||||
},
|
||||
})
|
||||
} else {
|
||||
c.JSON(result.Code, gin.H{
|
||||
"code": result.Code,
|
||||
"message": result.Message,
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
// Catch-all route to handle undefined paths
|
||||
r.NoRoute(func(c *gin.Context) {
|
||||
c.JSON(http.StatusNotFound, gin.H{
|
||||
"code": http.StatusNotFound,
|
||||
"message": "Path not found",
|
||||
})
|
||||
})
|
||||
|
||||
return r
|
||||
}
|
292
translate/translate.go
Normal file
292
translate/translate.go
Normal file
@ -0,0 +1,292 @@
|
||||
/*
|
||||
* @Author: Vincent Young
|
||||
* @Date: 2024-09-16 11:59:24
|
||||
* @LastEditors: Vincent Yang
|
||||
* @LastEditTime: 2025-04-08 14:26:33
|
||||
* @FilePath: /DeepLX/translate/translate.go
|
||||
* @Telegram: https://t.me/missuo
|
||||
* @GitHub: https://github.com/missuo
|
||||
*
|
||||
* Copyright © 2024 by Vincent, All Rights Reserved.
|
||||
*/
|
||||
|
||||
package translate
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"compress/flate"
|
||||
"compress/gzip"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/abadojack/whatlanggo"
|
||||
"github.com/imroc/req/v3"
|
||||
|
||||
"github.com/andybalholm/brotli"
|
||||
"github.com/tidwall/gjson"
|
||||
)
|
||||
|
||||
// makeRequest makes an HTTP request to DeepL API
|
||||
func makeRequest(postData *PostData, proxyURL string, dlSession string) (gjson.Result, error) {
|
||||
urlFull := "https://www2.deepl.com/jsonrpc"
|
||||
postStr := formatPostString(postData)
|
||||
|
||||
// Create a new req client
|
||||
client := req.C().SetTLSFingerprintRandomized()
|
||||
|
||||
// Set headers
|
||||
headers := http.Header{
|
||||
"Content-Type": []string{"application/json"},
|
||||
"User-Agent": []string{"DeepL/1627620 CFNetwork/3826.500.62.2.1 Darwin/24.4.0"},
|
||||
"Accept": []string{"*/*"},
|
||||
"X-App-Os-Name": []string{"iOS"},
|
||||
"X-App-Os-Version": []string{"18.4.0"},
|
||||
"Accept-Language": []string{"en-US,en;q=0.9"},
|
||||
"Accept-Encoding": []string{"gzip, deflate, br"}, // Keep this!
|
||||
"X-App-Device": []string{"iPhone16,2"},
|
||||
"Referer": []string{"https://www.deepl.com/"},
|
||||
"X-Product": []string{"translator"},
|
||||
"X-App-Build": []string{"1627620"},
|
||||
"X-App-Version": []string{"25.1"},
|
||||
}
|
||||
|
||||
if dlSession != "" {
|
||||
headers.Set("Cookie", "dl_session="+dlSession)
|
||||
}
|
||||
|
||||
// Set proxy if provided
|
||||
if proxyURL != "" {
|
||||
proxy, err := url.Parse(proxyURL)
|
||||
if err != nil {
|
||||
return gjson.Result{}, err
|
||||
}
|
||||
client.SetProxyURL(proxy.String())
|
||||
}
|
||||
|
||||
// Make the request
|
||||
r := client.R()
|
||||
r.Headers = headers
|
||||
resp, err := r.
|
||||
SetBody(bytes.NewReader([]byte(postStr))).
|
||||
Post(urlFull)
|
||||
|
||||
if err != nil {
|
||||
return gjson.Result{}, err
|
||||
}
|
||||
|
||||
var bodyReader io.Reader
|
||||
contentEncoding := resp.Header.Get("Content-Encoding")
|
||||
switch contentEncoding {
|
||||
case "br":
|
||||
bodyReader = brotli.NewReader(resp.Body)
|
||||
case "gzip":
|
||||
bodyReader, err = gzip.NewReader(resp.Body) // Use gzip.NewReader
|
||||
if err != nil {
|
||||
return gjson.Result{}, fmt.Errorf("failed to create gzip reader: %w", err)
|
||||
}
|
||||
case "deflate": // Less common, but good to handle
|
||||
bodyReader = flate.NewReader(resp.Body)
|
||||
default:
|
||||
bodyReader = resp.Body
|
||||
}
|
||||
|
||||
body, err := io.ReadAll(bodyReader)
|
||||
if err != nil {
|
||||
return gjson.Result{}, fmt.Errorf("failed to read response body: %w", err)
|
||||
}
|
||||
return gjson.ParseBytes(body), nil
|
||||
}
|
||||
|
||||
// TranslateByDeepLX performs translation using DeepL API
|
||||
func TranslateByDeepLX(sourceLang, targetLang, text string, tagHandling string, proxyURL string, dlSession string) (DeepLXTranslationResult, error) {
|
||||
if text == "" {
|
||||
return DeepLXTranslationResult{
|
||||
Code: http.StatusNotFound,
|
||||
Message: "No text to translate",
|
||||
}, nil
|
||||
}
|
||||
|
||||
if tagHandling == "" {
|
||||
tagHandling = "plaintext"
|
||||
}
|
||||
|
||||
// Split text by newlines and store them for later reconstruction
|
||||
textParts := strings.Split(text, "\n")
|
||||
var translatedParts []string
|
||||
var allAlternatives [][]string // Store alternatives for each part
|
||||
|
||||
for _, part := range textParts {
|
||||
if strings.TrimSpace(part) == "" {
|
||||
translatedParts = append(translatedParts, "")
|
||||
allAlternatives = append(allAlternatives, []string{""})
|
||||
continue
|
||||
}
|
||||
|
||||
// Get detected language if source language is auto
|
||||
if sourceLang == "auto" || sourceLang == "" {
|
||||
sourceLang = strings.ToUpper(whatlanggo.DetectLang(part).Iso6391())
|
||||
}
|
||||
|
||||
// Prepare jobs from split result
|
||||
var jobs []Job
|
||||
|
||||
jobs = append(jobs, Job{
|
||||
Kind: "default",
|
||||
PreferredNumBeams: 4,
|
||||
RawEnContextBefore: []string{},
|
||||
RawEnContextAfter: []string{},
|
||||
Sentences: []Sentence{{
|
||||
Prefix: "",
|
||||
Text: text,
|
||||
ID: 0,
|
||||
}},
|
||||
})
|
||||
|
||||
hasRegionalVariant := false
|
||||
targetLangCode := targetLang
|
||||
targetLangParts := strings.Split(targetLang, "-")
|
||||
if len(targetLangParts) > 1 {
|
||||
targetLangCode = targetLangParts[0]
|
||||
hasRegionalVariant = true
|
||||
}
|
||||
|
||||
// Prepare translation request
|
||||
id := getRandomNumber()
|
||||
|
||||
postData := &PostData{
|
||||
Jsonrpc: "2.0",
|
||||
Method: "LMT_handle_jobs",
|
||||
ID: id,
|
||||
Params: Params{
|
||||
CommonJobParams: CommonJobParams{
|
||||
Mode: "translate",
|
||||
Formality: "undefined",
|
||||
TranscribeAs: "romanize",
|
||||
AdvancedMode: false,
|
||||
TextType: tagHandling,
|
||||
WasSpoken: false,
|
||||
},
|
||||
Lang: Lang{
|
||||
SourceLangUserSelected: "auto",
|
||||
TargetLang: strings.ToUpper(targetLangCode),
|
||||
SourceLangComputed: strings.ToUpper(sourceLang),
|
||||
},
|
||||
Jobs: jobs,
|
||||
Timestamp: getTimeStamp(getICount(part)),
|
||||
},
|
||||
}
|
||||
|
||||
if hasRegionalVariant {
|
||||
postData = &PostData{
|
||||
Jsonrpc: "2.0",
|
||||
Method: "LMT_handle_jobs",
|
||||
ID: id,
|
||||
Params: Params{
|
||||
CommonJobParams: CommonJobParams{
|
||||
Mode: "translate",
|
||||
Formality: "undefined",
|
||||
TranscribeAs: "romanize",
|
||||
AdvancedMode: false,
|
||||
TextType: tagHandling,
|
||||
WasSpoken: false,
|
||||
RegionalVariant: targetLang,
|
||||
},
|
||||
Lang: Lang{
|
||||
SourceLangUserSelected: "auto",
|
||||
TargetLang: strings.ToUpper(targetLangCode),
|
||||
SourceLangComputed: strings.ToUpper(sourceLang),
|
||||
},
|
||||
Jobs: jobs,
|
||||
Timestamp: getTimeStamp(getICount(part)),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// Make translation request
|
||||
result, err := makeRequest(postData, proxyURL, dlSession)
|
||||
if err != nil {
|
||||
return DeepLXTranslationResult{
|
||||
Code: http.StatusServiceUnavailable,
|
||||
Message: err.Error(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Process translation results
|
||||
var partTranslation string
|
||||
var partAlternatives []string
|
||||
|
||||
translations := result.Get("result.translations").Array()
|
||||
if len(translations) > 0 {
|
||||
// Process main translation
|
||||
for _, translation := range translations {
|
||||
partTranslation += translation.Get("beams.0.sentences.0.text").String() + " "
|
||||
}
|
||||
partTranslation = strings.TrimSpace(partTranslation)
|
||||
|
||||
// Process alternatives
|
||||
numBeams := len(translations[0].Get("beams").Array())
|
||||
for i := 1; i < numBeams; i++ { // Start from 1 since 0 is the main translation
|
||||
var altText string
|
||||
for _, translation := range translations {
|
||||
beams := translation.Get("beams").Array()
|
||||
if i < len(beams) {
|
||||
altText += beams[i].Get("sentences.0.text").String() + " "
|
||||
}
|
||||
}
|
||||
if altText != "" {
|
||||
partAlternatives = append(partAlternatives, strings.TrimSpace(altText))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if partTranslation == "" {
|
||||
return DeepLXTranslationResult{
|
||||
Code: http.StatusServiceUnavailable,
|
||||
Message: "Translation failed",
|
||||
}, nil
|
||||
}
|
||||
|
||||
translatedParts = append(translatedParts, partTranslation)
|
||||
allAlternatives = append(allAlternatives, partAlternatives)
|
||||
}
|
||||
|
||||
// Join all translated parts with newlines
|
||||
translatedText := strings.Join(translatedParts, "\n")
|
||||
|
||||
// Combine alternatives with proper newline handling
|
||||
var combinedAlternatives []string
|
||||
maxAlts := 0
|
||||
for _, alts := range allAlternatives {
|
||||
if len(alts) > maxAlts {
|
||||
maxAlts = len(alts)
|
||||
}
|
||||
}
|
||||
|
||||
// Create combined alternatives preserving line structure
|
||||
for i := 0; i < maxAlts; i++ {
|
||||
var altParts []string
|
||||
for j, alts := range allAlternatives {
|
||||
if i < len(alts) {
|
||||
altParts = append(altParts, alts[i])
|
||||
} else if len(translatedParts[j]) == 0 {
|
||||
altParts = append(altParts, "") // Keep empty lines
|
||||
} else {
|
||||
altParts = append(altParts, translatedParts[j]) // Use main translation if no alternative
|
||||
}
|
||||
}
|
||||
combinedAlternatives = append(combinedAlternatives, strings.Join(altParts, "\n"))
|
||||
}
|
||||
|
||||
return DeepLXTranslationResult{
|
||||
Code: http.StatusOK,
|
||||
ID: getRandomNumber(), // Using new ID for the complete translation
|
||||
Data: translatedText,
|
||||
Alternatives: combinedAlternatives,
|
||||
SourceLang: sourceLang,
|
||||
TargetLang: targetLang,
|
||||
Method: map[bool]string{true: "Pro", false: "Free"}[dlSession != ""],
|
||||
}, nil
|
||||
}
|
103
translate/types.go
Normal file
103
translate/types.go
Normal file
@ -0,0 +1,103 @@
|
||||
/*
|
||||
* @Author: Vincent Young
|
||||
* @Date: 2024-09-16 11:59:24
|
||||
* @LastEditors: Vincent Yang
|
||||
* @LastEditTime: 2025-03-01 04:16:07
|
||||
* @FilePath: /DeepLX/translate/types.go
|
||||
* @Telegram: https://t.me/missuo
|
||||
* @GitHub: https://github.com/missuo
|
||||
*
|
||||
* Copyright © 2024 by Vincent, All Rights Reserved.
|
||||
*/
|
||||
|
||||
package translate
|
||||
|
||||
// Lang represents the language settings for translation
|
||||
type Lang struct {
|
||||
SourceLangUserSelected string `json:"source_lang_user_selected"` // Can be "auto"
|
||||
TargetLang string `json:"target_lang"`
|
||||
SourceLangComputed string `json:"source_lang_computed,omitempty"`
|
||||
}
|
||||
|
||||
// CommonJobParams represents common parameters for translation jobs
|
||||
type CommonJobParams struct {
|
||||
Formality string `json:"formality"` // Can be "undefined"
|
||||
TranscribeAs string `json:"transcribe_as"`
|
||||
Mode string `json:"mode"`
|
||||
WasSpoken bool `json:"wasSpoken"`
|
||||
AdvancedMode bool `json:"advancedMode"`
|
||||
TextType string `json:"textType"`
|
||||
RegionalVariant string `json:"regionalVariant,omitempty"`
|
||||
}
|
||||
|
||||
// Sentence represents a sentence in the translation request
|
||||
type Sentence struct {
|
||||
Prefix string `json:"prefix"`
|
||||
Text string `json:"text"`
|
||||
ID int `json:"id"`
|
||||
}
|
||||
|
||||
// Job represents a translation job
|
||||
type Job struct {
|
||||
Kind string `json:"kind"`
|
||||
PreferredNumBeams int `json:"preferred_num_beams"`
|
||||
RawEnContextBefore []string `json:"raw_en_context_before"`
|
||||
RawEnContextAfter []string `json:"raw_en_context_after"`
|
||||
Sentences []Sentence `json:"sentences"`
|
||||
}
|
||||
|
||||
// Params represents parameters for translation requests
|
||||
type Params struct {
|
||||
CommonJobParams CommonJobParams `json:"commonJobParams"`
|
||||
Lang Lang `json:"lang"`
|
||||
Jobs []Job `json:"jobs"`
|
||||
Timestamp int64 `json:"timestamp"`
|
||||
}
|
||||
|
||||
// PostData represents the complete translation request
|
||||
type PostData struct {
|
||||
Jsonrpc string `json:"jsonrpc"`
|
||||
Method string `json:"method"`
|
||||
ID int64 `json:"id"`
|
||||
Params Params `json:"params"`
|
||||
}
|
||||
|
||||
// TranslationResponse represents the response from translation
|
||||
type TranslationResponse struct {
|
||||
Jsonrpc string `json:"jsonrpc"`
|
||||
ID int64 `json:"id"`
|
||||
Result struct {
|
||||
Translations []struct {
|
||||
Beams []struct {
|
||||
Sentences []SentenceResponse `json:"sentences"`
|
||||
NumSymbols int `json:"num_symbols"`
|
||||
RephraseVariant struct { // Added rephrase_variant
|
||||
Name string `json:"name"`
|
||||
} `json:"rephrase_variant"`
|
||||
} `json:"beams"`
|
||||
Quality string `json:"quality"` // Added quality
|
||||
} `json:"translations"`
|
||||
TargetLang string `json:"target_lang"`
|
||||
SourceLang string `json:"source_lang"`
|
||||
SourceLangIsConfident bool `json:"source_lang_is_confident"`
|
||||
DetectedLanguages map[string]interface{} `json:"detectedLanguages"` // Use interface{} for now
|
||||
} `json:"result"`
|
||||
}
|
||||
|
||||
// SentenceResponse is a helper struct for the response sentences
|
||||
type SentenceResponse struct {
|
||||
Text string `json:"text"`
|
||||
IDS []int `json:"ids"` // Added IDS
|
||||
}
|
||||
|
||||
// DeepLXTranslationResult represents the final translation result
|
||||
type DeepLXTranslationResult struct {
|
||||
Code int `json:"code"`
|
||||
ID int64 `json:"id"`
|
||||
Message string `json:"message,omitempty"`
|
||||
Data string `json:"data"` // The primary translated text
|
||||
Alternatives []string `json:"alternatives"` // Other possible translations
|
||||
SourceLang string `json:"source_lang"`
|
||||
TargetLang string `json:"target_lang"`
|
||||
Method string `json:"method"`
|
||||
}
|
57
translate/utils.go
Normal file
57
translate/utils.go
Normal file
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* @Author: Vincent Young
|
||||
* @Date: 2024-09-16 11:59:24
|
||||
* @LastEditors: Vincent Yang
|
||||
* @LastEditTime: 2025-04-08 14:27:21
|
||||
* @FilePath: /DeepLX/translate/utils.go
|
||||
* @Telegram: https://t.me/missuo
|
||||
* @GitHub: https://github.com/missuo
|
||||
*
|
||||
* Copyright © 2024 by Vincent, All Rights Reserved.
|
||||
*/
|
||||
|
||||
package translate
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"math/rand"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// getICount returns the number of 'i' characters in the text
|
||||
func getICount(translateText string) int64 {
|
||||
return int64(strings.Count(translateText, "i"))
|
||||
}
|
||||
|
||||
// getRandomNumber generates a random number for request ID
|
||||
func getRandomNumber() int64 {
|
||||
src := rand.NewSource(time.Now().UnixNano())
|
||||
rng := rand.New(src)
|
||||
num := rng.Int63n(99999) + 8300000
|
||||
return num * 1000
|
||||
}
|
||||
|
||||
// getTimeStamp generates timestamp for request based on i count
|
||||
func getTimeStamp(iCount int64) int64 {
|
||||
ts := time.Now().UnixMilli()
|
||||
if iCount != 0 {
|
||||
iCount = iCount + 1
|
||||
return ts - ts%iCount + iCount
|
||||
}
|
||||
return ts
|
||||
}
|
||||
|
||||
// formatPostString formats the request JSON string with specific spacing rules
|
||||
func formatPostString(postData *PostData) string {
|
||||
postBytes, _ := json.Marshal(postData)
|
||||
postStr := string(postBytes)
|
||||
|
||||
if (postData.ID+5)%29 == 0 || (postData.ID+3)%13 == 0 {
|
||||
postStr = strings.Replace(postStr, `"method":"`, `"method" : "`, 1)
|
||||
} else {
|
||||
postStr = strings.Replace(postStr, `"method":"`, `"method": "`, 1)
|
||||
}
|
||||
|
||||
return postStr
|
||||
}
|
Loading…
Reference in New Issue
Block a user