Skip to content

Commit

Permalink
更新:v2.0.0 新增参数控制和优化日志 (#15)
Browse files Browse the repository at this point in the history
  • Loading branch information
guobao2333 authored Sep 15, 2024
2 parents 551537b + f7fd45a commit 3d14a0c
Show file tree
Hide file tree
Showing 4 changed files with 92 additions and 38 deletions.
10 changes: 2 additions & 8 deletions .github/workflows/docker-image.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -64,16 +64,10 @@ jobs:
type=ref,event=branch
type=ref,event=pr
type=sha
type=raw,value=${{ github.ref }},enable=${{ github.event.ref_type == 'tag' && startsWith(github.ref, 'refs/tags/v') }}
type=raw,value=${{ github.event_time }},enable=${{ github.event.ref_type != 'tag' }}
type=raw,value=latest,enable=${{ github.event.ref_type == 'tag' }}
- name: Add tag based on condition
run: |
if [[ ${{ github.ref }} =~ refs/tags/v ]]; then
echo "::set-output name=tag::${{ github.event.ref }}"
else
echo "::set-output name=tag::${{ github.event_time }}"
fi
# Build and push Docker image with Buildx (don't push on PR)
# https://github.com/docker/build-push-action
- name: Build and push Docker image
Expand Down
28 changes: 17 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# DeepLX Serverless
[本项目](https://github.com/guobao2333/DeepLX-Serverless)是一个基于 DeepL翻译API 的无服务器函数部署项目,旨在提供一个可直接对接的免费翻译解决方案,很适合需要在无服务器环境中集成DeepL翻译服务的开发者使用。

与原项目[DeepLX](https://github.com/OwO-Network/DeepLX)的区别在于**利用了无服务器函数(边缘函数)请求IP不固定的特性**,有效避免了`Error 429`请求太频繁的报错(不过嘛凡事总有例外¯\\_(ツ)_/¯)
与原项目[DeepLX](https://github.com/OwO-Network/DeepLX)的区别在于**利用了无服务器函数(边缘函数)请求IP不固定的特性**,有效避免了`Error 429`请求太频繁的报错(不过嘛凡事总有例外¯\\\_(ツ)_/¯)

虽然因此不会立马被*暂时封禁*,但也请不要滥用!目前我部署在vercel上会有流量限制,如果您有大量内容需要翻译,请购买DeepL的付费版,当前项目使用的free接口会受到DeepL政策限制
由于目前项目未对pro接口进行适配,所以现在还只能使用free接口,不过在将来会完善,敬请期待~ („• ֊ •„)੭
Expand All @@ -16,7 +16,7 @@
你需要:
- 一双灵活的小手🙌🏻
- 一个聪明的小脑袋瓜🧠
- 支持 `Nodejs ≥16.13``Docker``Serverless Function` 的服务器💻
- 支持 `Nodejs ≥18``Docker``Serverless Function` 的服务器💻
- (可选) 拥有[Vercel](https://vercel.com)[Netlify](https://netlify.com)的账号

## Deploy | 部署
Expand All @@ -34,11 +34,6 @@
因维护者我有多个仓库需要维护,短时间内将无法对多平台部署方案进行兼容,您可以打开一个`issues📌`或打开一个`Pull Request📎`贡献您的代码。
✨项目当前没有任何需要填写的变量值,但在后续可能会添加。

> [!IMPORTANT]
> 如果您需要跨域访问,请在`server.js`中配置`CORS`
> Vercel这类平台支持更便捷的方式配置,详请查阅其平台文档。

### Docker | 容器部署

🐳直接运行预构建容器:
Expand All @@ -48,8 +43,8 @@ docker run -d -p 9000:9000 ghcr.io/guobao2333/deeplx-serverless

🚧你还可以自己构建后运行:
```bash
docker build -t DeepLXS .
docker run -d -p 9000:9000 DeepLXS
docker build -t deeplxs .
docker run -d -p 9000:9000 deeplxs
```


Expand All @@ -73,6 +68,17 @@ git clone https://github.com/guobao2333/DeepLX-Serverless && cd DeepLX-Serverles

如果部署完成了,就可以开始使用啦!🎉

#### startup parameters | 启动参数
> [!IMPORTANT]
> 此功能在 v2.0.0 及以上版本中可用
如果你想的话,可以在启动时添加参数。
添加一个`--no`前缀来禁止备选翻译:
```bash
npm run start -- --no-a
```

💡使用`-h`来获取所有参数。

## How To Use | 如何使用
> [!IMPORTANT]
Expand Down Expand Up @@ -121,7 +127,7 @@ curl --location --request POST 'http://localhost:9000/translate' --header 'Conte
如果你是第一次贡献,并且真的想贡献点什么,那么请查看[《如何为开源做贡献》](https://opensource.guide/how-to-contribute/),不过我喜欢叫它「开源贡献指南」,那里有你需要知道的一切。

## License | 开源许可
本项目遵循[GNU/AGPLv3 许可证](./LICENSE)的条款发布
本项目遵循[GNU/AGPLv3](./LICENSE)许可证的条款发布

DeepL free translate API for Serverless
Copyright (C) 2024 shiguobaona
Expand All @@ -142,5 +148,5 @@ curl --location --request POST 'http://localhost:9000/translate' --header 'Conte
## Acknowledgments | 鸣谢

1. [OwO-Network/DeepLX](https://github.com/OwO-Network/DeepLX) - 感谢OwO-Network的优秀项目(•̀ᴗ•́)و̑̑
2. [LegendLeo/deeplx-serverless](https://github.com/LegendLeo/deeplx-serverless) - 本项目的重构前项目,接过维护的大旗(ง •̀_•́)ง
2. [LegendLeo/deeplx-serverless](https://github.com/LegendLeo/deeplx-serverless) - 原项目
3. [bropines/Deeplx-vercel](https://github.com/bropines/Deeplx-vercel) - 参考部分实现
8 changes: 5 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
{
"name": "deeplx-serverless",
"version": "1.1.2",
"version": "2.0.0",
"description": "DeepL free API for Serverless",
"type": "module",
"main": "server.js",
"engines": {
"node": ">=16.13"
"node": ">=18"
},
"scripts": {
"start": "node server.js",
"test": "node test.js"
},
"keywords": [
"deeplxs",
"deeplx",
"deepl",
"translate",
Expand All @@ -25,6 +26,7 @@
"express": "^4.18.2",
"lodash": "^4.17.21",
"node-fetch": "^3.3.2",
"random-int": "^3.0.0"
"random-int": "^3.0.0",
"yargs": "^17.7.2"
}
}
84 changes: 68 additions & 16 deletions server.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,41 @@
import express from 'express';
import cors from 'cors';
import bodyParser from 'body-parser';
import yargs from 'yargs/yargs';
import { hideBin } from 'yargs/helpers';
import { translate } from './translate.js';

// 解析参数
const argv = yargs(hideBin(process.argv))
.option('port', {
alias: 'p',
describe: '端口号',
coerce: coerce_port,
default: 9000
})
.option('alt', {
alias: 'a',
describe: '请求备选翻译',
type: 'boolean',
default: true
})
.option('cors', {
alias: 'c',
describe: '允许跨域访问的源(origin)',
coerce: coerce_cors,
default: false
})
.help().alias('help', 'h')
.argv;

// 定义配置
const app = express(),
PORT = 9000,
allowAlternative = true,
PORT = argv.port,
allowAlternative = argv.alt,
CORS = {
origin: false, // 默认关闭跨域访问,还支持指定多个域名或正则表达式
origin: argv.cors,
methods: 'GET,POST',
allowedHeaders: 'Content-Type',
allowedHeaders: ['Content-Type', 'Authorization'],
preflightContinue: false
};

Expand All @@ -24,24 +50,33 @@ app.get('/', async (req, res) => await get(req, res));
async function post(req, res) {
const startTime = Date.now(); // 记录开始时间

// 检查请求方法和请求体
if (req.method !== 'POST' || !req.body || !req.body.text) {
// 检查请求体
if (!req.body || Object.keys(req.body).length === 0) {
const duration = Date.now() - startTime;
console.log(`[LOG] ${new Date().toISOString()} | 404 | ${duration}ms | POST "translate"`);
return res.status(404).json({
"code": 404,
"message": "Path not found"
console.log(`[LOG] ${new Date().toISOString()} | POST "translate" | 400 | Request body does not exist | ${duration}ms`);
return res.status(400).json({
"code": 400,
"message": "Bad Request"
});
}

// 是否允许备选翻译
if (!allowAlternative) alt_count = 0;
const { text, source_lang, target_lang, alt_count } = req.body;

// 是否允许备选翻译
if (!allowAlternative && alt_count !== undefined) {
const duration = Date.now() - startTime;
console.log(`[LOG] ${new Date().toISOString()} | POST "translate" | 405 | Alt Not Allowed | ${duration}ms`);
return res.status(405).json({
"code": 405,
"message": "Alternative Translate Not Allowed"
});
alt_count = 0;
}

try {
const result = await translate(text, source_lang, target_lang, alt_count);
const duration = Date.now() - startTime; // 计算处理时间
console.log(`[LOG] ${new Date().toISOString()} | 200 | ${duration}ms | POST "translate"`);
console.log(`[LOG] ${new Date().toISOString()} | POST "translate" | 200 | ${duration}ms`);

const responseData = {
code: 200,
Expand All @@ -54,9 +89,10 @@ async function post(req, res) {
};

res.json(responseData);

} catch (error) {
const duration = Date.now() - startTime;
console.error(`[ERROR] ${new Date().toISOString()} | 500 | ${duration}ms | POST "translate" | ${error.message}`);
console.error(`[ERR] ${new Date().toISOString()} | POST "translate" | 500 | ${error.message} | ${duration}ms`);
res.status(500).json({
code: 500,
message: 'Translation failed',
Expand All @@ -72,9 +108,25 @@ async function get(req, res) {
});
};

function coerce_cors(arg) {
if (typeof arg === 'string' || typeof arg === 'boolean') {
return arg;
}
console.error("ParamTypeError: \x1b[33m'"+arg+"'\x1b[31m, origin should be Boolean or String.\n\x1b[0meg: \x1b[32m'*' or true or RegExp");
process.exit(1);
}

function coerce_port(arg) {
if (typeof arg === 'number' && !isNaN(arg) && Number.isInteger(arg) && arg >= 0 && arg <= 65535) {
return arg;
}
console.warn("WARNING:\x1b[0m port should be >= 0 and < 65536.\nUsed default value instead: 9000\n");
return 9000;
}

// 启动本地服务器
app.listen(PORT, () => {
console.log(`Server is running on http://localhost:${PORT}`);
console.log(`Server is running and listening on http://localhost:${PORT}`);
});

export { post, get };
export { post, get };

0 comments on commit 3d14a0c

Please sign in to comment.