Repository: OwO-Network/DeepLX
Branch: main
Commit: 8d145722eba5
Files: 22
Total size: 43.5 KB
Directory structure:
gitextract_wsz2ewjq/
├── .cross_compile.sh
├── .github/
│ ├── FUNDING.yaml
│ └── workflows/
│ ├── ci.yaml
│ ├── docker.yaml
│ └── release.yaml
├── .gitignore
├── Dockerfile
├── LICENSE
├── README.md
├── compose.yaml
├── deeplx.service
├── go.mod
├── go.sum
├── install.sh
├── main.go
├── me.missuo.deeplx.plist
├── service/
│ ├── config.go
│ └── service.go
├── translate/
│ ├── translate.go
│ ├── types.go
│ └── utils.go
└── uninstall.sh
================================================
FILE CONTENTS
================================================
================================================
FILE: .cross_compile.sh
================================================
###
# @Author: Vincent Young
# @Date: 2022-10-20 02:19:06
# @LastEditors: Vincent Yang
# @LastEditTime: 2024-03-20 16:52:40
# @FilePath: /DeepLX/.cross_compile.sh
# @Telegram: https://t.me/missuo
#
# Copyright © 2022 by Vincent, All Rights Reserved.
###
set -e
DIST_PREFIX="deeplx"
DEBUG_MODE=${2}
TARGET_DIR="dist"
PLATFORMS="darwin/amd64 darwin/arm64 linux/386 linux/amd64 linux/arm64 linux/mips openbsd/amd64 openbsd/arm64 freebsd/amd64 freebsd/arm64 windows/386 windows/amd64"
rm -rf ${TARGET_DIR}
mkdir ${TARGET_DIR}
for pl in ${PLATFORMS}; do
export GOOS=$(echo ${pl} | cut -d'/' -f1)
export GOARCH=$(echo ${pl} | cut -d'/' -f2)
export TARGET=${TARGET_DIR}/${DIST_PREFIX}_${GOOS}_${GOARCH}
if [ "${GOOS}" == "windows" ]; then
export TARGET=${TARGET_DIR}/${DIST_PREFIX}_${GOOS}_${GOARCH}.exe
fi
echo "build => ${TARGET}"
if [ "${DEBUG_MODE}" == "debug" ]; then
CGO_ENABLED=0 go build -trimpath -gcflags "all=-N -l" -o ${TARGET} \
-ldflags "-w -s" .
else
CGO_ENABLED=0 go build -trimpath -o ${TARGET} \
-ldflags "-w -s" .
fi
done
================================================
FILE: .github/FUNDING.yaml
================================================
github: [missuo]
================================================
FILE: .github/workflows/ci.yaml
================================================
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 ./...
================================================
FILE: .github/workflows/docker.yaml
================================================
name: Docker Image CI
on:
push:
branches:
- dev
tags:
- 'v*'
env:
DOCKER_IMAGE_NAME: missuo/deeplx
GHCR_IMAGE_NAME: ${{ github.repository }}
DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
GHCR_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GHCR_USERNAME: ${{ github.repository_owner }}
jobs:
docker_build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
with:
platforms: all
- name: Set up docker buildx
id: buildx
uses: docker/setup-buildx-action@v2
with:
version: latest
- name: Login to DockerHub
uses: docker/login-action@v2
with:
registry: docker.io
username: ${{ env.DOCKER_USERNAME }}
password: ${{ env.DOCKER_PASSWORD }}
- name: Login to GHCR
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ env.GHCR_USERNAME }}
password: ${{ env.GHCR_TOKEN }}
- name: Docker meta
id: meta
uses: docker/metadata-action@v4
with:
# list of Docker images to use as base name for tags
images: |
docker.io/${{ env.DOCKER_IMAGE_NAME }}
ghcr.io/${{ env.GHCR_IMAGE_NAME }}
# generate Docker tags based on the following events/attributes
tags: |
type=raw,value=latest,enable=${{ startsWith(github.ref, 'refs/tags/') }}
type=pep440,pattern={{raw}},enable=${{ startsWith(github.ref, 'refs/tags/') }}
type=raw,value=dev,enable=${{ github.ref == 'refs/heads/dev' }}
- name: Build and push
uses: docker/build-push-action@v3
with:
context: .
platforms: linux/amd64,linux/arm64
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
================================================
FILE: .github/workflows/release.yaml
================================================
on:
push:
tags:
- 'v*'
pull_request:
name: Release
jobs:
Build:
if: startsWith(github.ref, 'refs/tags/v')
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v4
with:
go-version: "1.24.2"
- run: bash .cross_compile.sh
- name: Release
uses: softprops/action-gh-release@v1
with:
draft: false
generate_release_notes: true
files: |
dist/*
================================================
FILE: .gitignore
================================================
DeepLX
================================================
FILE: Dockerfile
================================================
FROM golang:1.25 AS builder
WORKDIR /go/src/github.com/OwO-Network/DeepLX
COPY . .
RUN go get -d -v ./
RUN CGO_ENABLED=0 go build -a -installsuffix cgo -o deeplx .
FROM alpine:latest
WORKDIR /app
COPY --from=builder /go/src/github.com/OwO-Network/DeepLX/deeplx /app/deeplx
CMD ["/app/deeplx"]
================================================
FILE: LICENSE
================================================
MIT License
Copyright (c) 2022 OwO Network Limited
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: README.md
================================================
[![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)
[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)
## Acknowledgements
### Contributors
## Activity

## License
[](https://app.fossa.com/projects/git%2Bgithub.com%2FOwO-Network%2FDeepLX?ref=badge_large)
================================================
FILE: compose.yaml
================================================
services:
deeplx:
image: ghcr.io/owo-network/deeplx:latest
restart: always
ports:
- "1188:1188"
# environment:
# - TOKEN=helloworld
# - DL_SESSION=xxxxxx
================================================
FILE: deeplx.service
================================================
[Unit]
Description=DeepLX Service
After=network.target
[Service]
Type=simple
Restart=always
WorkingDirectory=/usr/bin/
ExecStart=/usr/bin/deeplx
[Install]
WantedBy=multi-user.target
================================================
FILE: go.mod
================================================
module github.com/OwO-Network/DeepLX
go 1.25.0
require (
github.com/abadojack/whatlanggo v1.0.1
github.com/andybalholm/brotli v1.2.0
github.com/gin-contrib/cors v1.7.6
github.com/gin-gonic/gin v1.11.0
github.com/imroc/req/v3 v3.57.0
github.com/tidwall/gjson v1.18.0
)
require (
github.com/bytedance/gopkg v0.1.3 // indirect
github.com/bytedance/sonic v1.15.0 // indirect
github.com/bytedance/sonic/loader v0.5.0 // indirect
github.com/cloudwego/base64x v0.1.6 // indirect
github.com/gabriel-vasile/mimetype v1.4.13 // indirect
github.com/gin-contrib/sse v1.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.30.1 // indirect
github.com/goccy/go-json v0.10.5 // indirect
github.com/goccy/go-yaml v1.19.2 // indirect
github.com/google/go-querystring v1.2.0 // indirect
github.com/icholy/digest v1.1.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/compress v1.18.4 // indirect
github.com/klauspost/cpuid/v2 v2.3.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.2.4 // indirect
github.com/quic-go/qpack v0.6.0 // indirect
github.com/quic-go/quic-go v0.57.1 // indirect
github.com/refraction-networking/utls v1.8.2 // indirect
github.com/tidwall/match v1.2.0 // indirect
github.com/tidwall/pretty v1.2.1 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.3.1 // indirect
golang.org/x/arch v0.24.0 // indirect
golang.org/x/crypto v0.48.0 // indirect
golang.org/x/net v0.51.0 // indirect
golang.org/x/sys v0.41.0 // indirect
golang.org/x/text v0.34.0 // indirect
google.golang.org/protobuf v1.36.11 // indirect
)
================================================
FILE: go.sum
================================================
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.2.0 h1:ukwgCxwYrmACq68yiUqwIWnGY0cTPox/M94sVwToPjQ=
github.com/andybalholm/brotli v1.2.0/go.mod h1:rzTDkvFWvIrjDXZHkuS16NPggd91W3kUSvPlQ1pLaKY=
github.com/bytedance/gopkg v0.1.3 h1:TPBSwH8RsouGCBcMBktLt1AymVo2TVsBVCY4b6TnZ/M=
github.com/bytedance/gopkg v0.1.3/go.mod h1:576VvJ+eJgyCzdjS+c4+77QF3p7ubbtiKARP3TxducM=
github.com/bytedance/sonic v1.15.0 h1:/PXeWFaR5ElNcVE84U0dOHjiMHQOwNIx3K4ymzh/uSE=
github.com/bytedance/sonic v1.15.0/go.mod h1:tFkWrPz0/CUCLEF4ri4UkHekCIcdnkqXw9VduqpJh0k=
github.com/bytedance/sonic/loader v0.5.0 h1:gXH3KVnatgY7loH5/TkeVyXPfESoqSBSBEiDd5VjlgE=
github.com/bytedance/sonic/loader v0.5.0/go.mod h1:AR4NYCk5DdzZizZ5djGqQ92eEhCCcdf5x77udYiSJRo=
github.com/cloudwego/base64x v0.1.6 h1:t11wG9AECkCDk5fMSoxmufanudBtJ+/HemLstXDLI2M=
github.com/cloudwego/base64x v0.1.6/go.mod h1:OFcloc187FXDaYHvrNIjxSe8ncn0OOM8gEHfghB2IPU=
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.13 h1:46nXokslUBsAJE/wMsp5gtO500a4F3Nkz9Ufpk2AcUM=
github.com/gabriel-vasile/mimetype v1.4.13/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s=
github.com/gin-contrib/cors v1.7.6 h1:3gQ8GMzs1Ylpf70y8bMw4fVpycXIeX1ZemuSQIsnQQY=
github.com/gin-contrib/cors v1.7.6/go.mod h1:Ulcl+xN4jel9t1Ry8vqph23a60FwH9xVLd+3ykmTjOk=
github.com/gin-contrib/sse v1.1.0 h1:n0w2GMuUpWDVp7qSpvze6fAu9iRxJY4Hmj6AmBOU05w=
github.com/gin-contrib/sse v1.1.0/go.mod h1:hxRZ5gVpWMT7Z0B0gSNYqqsSCNIJMjzvm6fqCz9vjwM=
github.com/gin-gonic/gin v1.11.0 h1:OW/6PLjyusp2PPXtyxKHU0RbX6I/l28FTdDlae5ueWk=
github.com/gin-gonic/gin v1.11.0/go.mod h1:+iq/FyxlGzII0KHiBGjuNn4UNENUlKbGlNmc+W50Dls=
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
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.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.30.1 h1:f3zDSN/zOma+w6+1Wswgd9fLkdwy06ntQJp0BBvFG0w=
github.com/go-playground/validator/v10 v10.30.1/go.mod h1:oSuBIQzuJxL//3MelwSLD5hc2Tu889bF0Idm9Dg26cM=
github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4=
github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
github.com/goccy/go-yaml v1.19.2 h1:PmFC1S6h8ljIz6gMRBopkjP1TVT7xuwrButHID66PoM=
github.com/goccy/go-yaml v1.19.2/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/go-querystring v1.2.0 h1:yhqkPbu2/OH+V9BfpCVPZkNmUXhb2gBxJArfhIxNtP0=
github.com/google/go-querystring v1.2.0/go.mod h1:8IFJqpSRITyJ8QhQ13bmbeMBDfmeEJZD5A0egEOmkqU=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/icholy/digest v1.1.0 h1:HfGg9Irj7i+IX1o1QAmPfIBNu/Q5A5Tu3n/MED9k9H4=
github.com/icholy/digest v1.1.0/go.mod h1:QNrsSGQ5v7v9cReDI0+eyjsXGUoRSUZQHeQ5C4XLa0Y=
github.com/imroc/req/v3 v3.57.0 h1:LMTUjNRUybUkTPn8oJDq8Kg3JRBOBTcnDhKu7mzupKI=
github.com/imroc/req/v3 v3.57.0/go.mod h1:JL62ey1nvSLq81HORNcosvlf7SxZStONNqOprg0Pz00=
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.18.4 h1:RPhnKRAQ4Fh8zU2FY/6ZFDwTVTxgJ/EMydqSTzE9a2c=
github.com/klauspost/compress v1.18.4/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4=
github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y=
github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0=
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.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4=
github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
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/quic-go/qpack v0.6.0 h1:g7W+BMYynC1LbYLSqRt8PBg5Tgwxn214ZZR34VIOjz8=
github.com/quic-go/qpack v0.6.0/go.mod h1:lUpLKChi8njB4ty2bFLX2x4gzDqXwUpaO1DP9qMDZII=
github.com/quic-go/quic-go v0.57.1 h1:25KAAR9QR8KZrCZRThWMKVAwGoiHIrNbT72ULHTuI10=
github.com/quic-go/quic-go v0.57.1/go.mod h1:ly4QBAjHA2VhdnxhojRsCUOeJwKYg+taDlos92xb1+s=
github.com/refraction-networking/utls v1.8.2 h1:j4Q1gJj0xngdeH+Ox/qND11aEfhpgoEvV+S9iJ2IdQo=
github.com/refraction-networking/utls v1.8.2/go.mod h1:jkSOEkLqn+S/jtpEHPOsVv/4V4EVnelwbMQl4vCWXAM=
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/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
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.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY=
github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
github.com/tidwall/match v1.2.0 h1:0pt8FlkOwjN2fPt4bIl4BoNxb98gGHN2ObFEDkrfZnM=
github.com/tidwall/match v1.2.0/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4=
github.com/tidwall/pretty v1.2.1/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/codec v1.3.1 h1:waO7eEiFDwidsBN6agj1vJQ4AG7lh2yqXyOXqhgQuyY=
github.com/ugorji/go/codec v1.3.1/go.mod h1:pRBVtBSKl77K30Bv8R2P+cLSGaTtex6fsA2Wjqmfxj4=
github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZqKjWU=
github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E=
go.uber.org/mock v0.6.0 h1:hyF9dfmbgIX5EfOdasqLsWD6xqpNZlXblLB/Dbnwv3Y=
go.uber.org/mock v0.6.0/go.mod h1:KiVJ4BqZJaMj4svdfmHM0AUx4NJYO8ZNpPnZn1Z+BBU=
golang.org/x/arch v0.24.0 h1:qlJ3M9upxvFfwRM51tTg3Yl+8CP9vCC1E7vlFpgv99Y=
golang.org/x/arch v0.24.0/go.mod h1:dNHoOeKiyja7GTvF9NJS1l3Z2yntpQNzgrjh1cU103A=
golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts=
golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos=
golang.org/x/net v0.51.0 h1:94R/GTO7mt3/4wIKpcR5gkGmRLOuE/2hNGeWq/GBIFo=
golang.org/x/net v0.51.0/go.mod h1:aamm+2QF5ogm02fjy5Bb7CQ0WMt1/WVM7FtyaTLlA9Y=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k=
golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk=
golang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA=
golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE=
golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/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=
gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU=
gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU=
================================================
FILE: install.sh
================================================
###
# @Author: Vincent Young
# @Date: 2023-02-12 09:53:21
# @LastEditors: Vincent Young
# @LastEditTime: 2023-02-12 10:01:57
# @FilePath: /DeepLX/install.sh
# @Telegram: https://t.me/missuo
#
# Copyright © 2023 by Vincent, All Rights Reserved.
###
install_deeplx(){
last_version=$(curl -Ls "https://api.github.com/repos/OwO-Network/DeepLX/releases/latest" | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/')
if [[ ! -n "$last_version" ]]; then
echo -e "${red}Failed to detect DeepLX version, probably due to exceeding Github API limitations.${plain}"
exit 1
fi
echo -e "DeepLX latest version: ${last_version}, Start install..."
wget -q -N --no-check-certificate -O /usr/bin/deeplx https://github.com/OwO-Network/DeepLX/releases/download/${last_version}/deeplx_linux_amd64
chmod +x /usr/bin/deeplx
wget -q -N --no-check-certificate -O /etc/systemd/system/deeplx.service https://raw.githubusercontent.com/OwO-Network/DeepLX/main/deeplx.service
systemctl daemon-reload
systemctl enable deeplx
systemctl start deeplx
echo -e "Installed successfully, listening at 0.0.0.0:1188"
}
install_deeplx
================================================
FILE: main.go
================================================
/*
* @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 main
import (
"fmt"
"github.com/gin-gonic/gin"
"github.com/OwO-Network/DeepLX/service"
)
func main() {
cfg := service.InitConfig()
fmt.Printf("DeepL X has been successfully launched! Listening on %v:%v\n", cfg.IP, cfg.Port)
fmt.Println("Developed by sjlleo and missuo .")
// Setting the application to release mode
gin.SetMode(gin.ReleaseMode)
app := service.Router(cfg)
app.Run(fmt.Sprintf("%v:%v", cfg.IP, cfg.Port))
}
================================================
FILE: me.missuo.deeplx.plist
================================================
Label
me.missuo.deeplx
KeepAlive
ProgramArguments
/usr/local/bin/deeplx
RunAtLoad
OnDemand
LaunchOnlyOnce
================================================
FILE: service/config.go
================================================
/*
* @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
}
================================================
FILE: service/service.go
================================================
/*
* @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
}
================================================
FILE: translate/translate.go
================================================
/*
* @Author: Vincent Young
* @Date: 2024-09-16 11:59:24
* @LastEditors: Vincent Yang
* @LastEditTime: 2025-07-13 23:09:49
* @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"
)
// makeRequestWithBody makes an HTTP request with pre-formatted body using minimal headers
func makeRequestWithBody(postStr string, proxyURL string, dlSession string) (gjson.Result, error) {
urlFull := "https://www2.deepl.com/jsonrpc"
// Create a new req client
client := req.C().SetTLSFingerprintRandomized()
// Set headers to simulate browser request
headers := http.Header{
"Content-Type": []string{"application/json"},
"Accept": []string{"*/*"},
"Accept-Language": []string{"en-US,en;q=0.9"},
"Accept-Encoding": []string{"gzip, deflate, br, zstd"},
"Origin": []string{"https://www.deepl.com"},
"Referer": []string{"https://www.deepl.com/"},
"Sec-Fetch-Dest": []string{"empty"},
"Sec-Fetch-Mode": []string{"cors"},
"Sec-Fetch-Site": []string{"same-site"},
"User-Agent": []string{"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36 Edg/141.0.0.0"},
}
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
}
// Check for blocked status like TypeScript version
if resp.StatusCode == 429 {
return gjson.Result{}, fmt.Errorf("too many requests, your IP has been blocked by DeepL temporarily, please don't request it frequently in a short time")
}
// Check for other error status codes
if resp.StatusCode != 200 {
return gjson.Result{}, fmt.Errorf("request failed with status code: %d", resp.StatusCode)
}
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)
if err != nil {
return gjson.Result{}, fmt.Errorf("failed to create gzip reader: %w", err)
}
case "deflate":
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
}
// Get detected language if source language is auto
if sourceLang == "auto" || sourceLang == "" {
sourceLang = strings.ToUpper(whatlanggo.DetectLang(text).Iso6391())
}
// Prepare translation request using new LMT_handle_texts method
id := getRandomNumber()
iCount := getICount(text)
timestamp := getTimeStamp(iCount)
postData := &PostData{
Jsonrpc: "2.0",
Method: "LMT_handle_texts",
ID: id,
Params: Params{
Splitting: "newlines",
Lang: Lang{
SourceLangUserSelected: sourceLang,
TargetLang: targetLang,
},
Texts: []TextItem{{
Text: text,
RequestAlternatives: 3,
}},
Timestamp: timestamp,
},
}
// Format and apply body manipulation method like TypeScript
postStr := formatPostString(postData)
postStr = handlerBodyMethod(id, postStr)
// Make translation request
result, err := makeRequestWithBody(postStr, proxyURL, dlSession)
if err != nil {
return DeepLXTranslationResult{
Code: http.StatusServiceUnavailable,
Message: err.Error(),
}, nil
}
// Process translation results using new format
textsArray := result.Get("result.texts").Array()
if len(textsArray) == 0 {
return DeepLXTranslationResult{
Code: http.StatusServiceUnavailable,
Message: "Translation failed",
}, nil
}
// Get main translation
mainText := textsArray[0].Get("text").String()
if mainText == "" {
return DeepLXTranslationResult{
Code: http.StatusServiceUnavailable,
Message: "Translation failed",
}, nil
}
// Get alternatives
var alternatives []string
alternativesArray := textsArray[0].Get("alternatives").Array()
for _, alt := range alternativesArray {
altText := alt.Get("text").String()
if altText != "" {
alternatives = append(alternatives, altText)
}
}
// Get detected source language from response
detectedLang := result.Get("result.lang").String()
if detectedLang != "" {
sourceLang = detectedLang
}
return DeepLXTranslationResult{
Code: http.StatusOK,
ID: id,
Data: mainText,
Alternatives: alternatives,
SourceLang: sourceLang,
TargetLang: targetLang,
Method: map[bool]string{true: "Pro", false: "Free"}[dlSession != ""],
}, nil
}
================================================
FILE: translate/types.go
================================================
/*
* @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"`
}
// TextItem represents a text item for translation
type TextItem struct {
Text string `json:"text"`
RequestAlternatives int `json:"requestAlternatives"`
}
// Params represents parameters for translation requests
type Params struct {
Splitting string `json:"splitting"`
Lang Lang `json:"lang"`
Texts []TextItem `json:"texts"`
Timestamp int64 `json:"timestamp"`
}
// LegacyParams represents the old parameters structure for jobs (kept for compatibility)
type LegacyParams 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"`
}
// TextResponse represents a single text response
type TextResponse struct {
Text string `json:"text"`
Alternatives []struct {
Text string `json:"text"`
} `json:"alternatives"`
}
// TranslationResponse represents the response from LMT_handle_texts
type TranslationResponse struct {
Jsonrpc string `json:"jsonrpc"`
ID int64 `json:"id"`
Result struct {
Lang string `json:"lang"`
Texts []TextResponse `json:"texts"`
} `json:"result"`
}
// LegacyTranslationResponse represents the old response format (kept for compatibility)
type LegacyTranslationResponse 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"`
}
================================================
FILE: translate/utils.go
================================================
/*
* @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) + 100000
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)
return postStr
}
// handlerBodyMethod manipulates the request body based on random number calculation
func handlerBodyMethod(random int64, body string) string {
calc := (random+5)%29 == 0 || (random+3)%13 == 0
if calc {
return strings.Replace(body, `"method":"`, `"method" : "`, 1)
}
return strings.Replace(body, `"method":"`, `"method": "`, 1)
}
================================================
FILE: uninstall.sh
================================================
#!/bin/bash
# Colors
red='\033[0;31m'
green='\033[0;32m'
yellow='\033[0;33m'
plain='\033[0m'
# Check for root privileges
if [[ $EUID -ne 0 ]]; then
echo -e "${red}This script must be run as root.${plain}"
exit 1
fi
uninstall_deeplx() {
echo -e "${green}Starting DeepLX uninstallation...${plain}"
# 1. Stop and disable the DeepLX service
if systemctl is-active --quiet deeplx; then
echo -e "${yellow}Stopping DeepLX service...${plain}"
systemctl stop deeplx
else
echo -e "${yellow}DeepLX service is not running or not found.${plain}"
fi
if systemctl is-enabled --quiet deeplx; then
echo -e "${yellow}Disabling DeepLX service from starting on boot...${plain}"
systemctl disable deeplx
else
echo -e "${yellow}DeepLX service is not enabled.${plain}"
fi
# 2. Remove the systemd service file
if [ -f /etc/systemd/system/deeplx.service ]; then
echo -e "${yellow}Removing DeepLX systemd service file (/etc/systemd/system/deeplx.service)...${plain}"
rm -f /etc/systemd/system/deeplx.service
systemctl daemon-reload
echo -e "${green}Systemd daemon reloaded.${plain}"
else
echo -e "${yellow}DeepLX systemd service file not found, skipping removal.${plain}"
fi
# 3. Remove the DeepLX executable
if [ -f /usr/bin/deeplx ]; then
echo -e "${yellow}Removing DeepLX executable (/usr/bin/deeplx)...${plain}"
rm -f /usr/bin/deeplx
else
echo -e "${yellow}DeepLX executable not found, skipping removal.${plain}"
fi
echo -e "${green}DeepLX uninstallation complete.${plain}"
echo -e "${green}If you wish to reinstall, please run the install script again.${plain}"
}
uninstall_deeplx