diff --git a/README.md b/README.md index 7014932..d8a8790 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,9 @@ # DeepLX Serverless +
+ ***本项目3.0版本开始完全基于[OwO-Network/DeepLX](https://github.com/OwO-Network/DeepLX)和DeepL网页端API进行重写。*** **2.0及之前版本在[LegendLeo/deeplx-serverless](https://github.com/LegendLeo/deeplx-serverless)的基础上进行重构。** @@ -69,7 +73,7 @@ curl -X POST 'http://localhost:6119/translate' -H 'Content-Type: application/jso 简单的示例: ```javascript -import { translate } from './translate.js'; +import { translate } from './src/translate.js'; translate('how are you?', 'en', 'zh', '', false, false) .then(result => { console.log(result) diff --git a/package.json b/package.json index 6e15f7c..0ebcebc 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "version": "3.0.1", "description": "DeepL free API for Serverless", "type": "module", - "main": "server.js", + "main": "src/server.js", "keywords": [ "deeplxs", "deeplx", @@ -19,7 +19,7 @@ "scripts": { "start": "node src/server.js", "test": "node test.js", - "start:sl": "node src/index.js", + "start:sl": "node api/index.js", "test:post": "node test_post.js" }, "dependencies": { diff --git a/src/server.js b/src/server.js index 836047a..3d17a54 100644 --- a/src/server.js +++ b/src/server.js @@ -72,7 +72,6 @@ async function post(req, res) { code: 405, message: "Alternative Translate Not Allowed" }); - // alt_count = 0; } try { @@ -83,10 +82,19 @@ async function post(req, res) { return decompressedData; });*/ - const duration = Date.now() - startTime; // 计算处理时间 + let duration = Date.now() - startTime; + if(result.code === 429) { + console.error(`[WARN] ${new Date().toISOString()} | POST "translate" | 429 | ${result.message} | ${duration}ms`); + res.status(429).json({ + code: 429, + message: result.message + }); + } + + duration = Date.now() - startTime; // console.log(result); - if(result == "") { - console.error(`[ERROR] ${new Date().toISOString()} | POST "translate" | 500 | ${error.message} | ${duration}ms`); + if(result == "" || result.data == "") { + console.error(`[ERROR] ${new Date().toISOString()} | POST "translate" | 500 | ${result.message} | ${duration}ms`); res.status(500).json({ code: 500, message: "Translation failed", @@ -96,7 +104,7 @@ async function post(req, res) { console.log(`[LOG] ${new Date().toISOString()} | POST "translate" | 200 | ${duration}ms`); const responseData = { - code: 200, + code: result.code, id: result.id, data: result.data, // 取第一个翻译结果 method: "Free", @@ -116,16 +124,15 @@ async function post(req, res) { } catch (err) { console.error(err, err.stack); - return res.status(500).json({ + res.status(500).json({ code: 500, - message: "Translation failed", - error: err.message + message: err.message }); } }; async function get(req, res) { - res.json({ + res.status(200).json({ code: 200, message: "Welcome to the DeepL Free API. Please POST to '/translate'. Visit 'https://github.com/guobao2333/DeepLX-Serverless' for more information." }); diff --git a/src/translate.js b/src/translate.js index 0efd34b..b8c5dce 100644 --- a/src/translate.js +++ b/src/translate.js @@ -35,24 +35,33 @@ async function sendRequest(postData, urlMethod, dlSession, printResult) { ...(dlSession && {'Cookie': `dl_session=${dlSession}`}) }; postData = formatPostString(postData); - // console.log(postData); + // console.warn(postData); try { const response = await axios.post(urlFull, postData, { headers: headers }); - // console.log(response.data); - + if (response.headers['content-encoding'] === 'br') { - const decompressed = brotliDecompress(response.data, (err, data) => { - if (err) console.error(err); - return data; + const decompressed = await new Promise((resolve, reject) => { + brotliDecompress(response.data, (err, data) => { + if (err) reject(err); + else resolve(data); + }); }); return JSON.parse(decompressed.toString()); } return response.data; } catch (err) { - console.error(err); + if (err.response.status === 429) { + return { + code: err.response.status, + message: 'Too Many Requests' + }; + } else { + console.error(`[ERROR] sendRequest: ${err.message}`); + throw err; + } } } @@ -69,7 +78,12 @@ async function splitText(text, tagHandling, dlSession, printResult) { } }; - return await sendRequest(postData, 'LMT_split_text', dlSession, printResult); + try { + return await sendRequest(postData, 'LMT_split_text', dlSession, printResult); + } catch (err) { + console.error("[ERROR] splitText:", err); + throw new Error(`splitText failed: ${err.message || err}`); + } } // 执行翻译任务 @@ -81,12 +95,12 @@ async function translate(text, sourceLang, targetLang, dlSession, tagHandling, p // 分割文本 const splitResult = await splitText(text, tagHandling === 'html' || tagHandling === 'xml', dlSession, printResult); - // console.log(splitResult); + // console.warn(splitResult); - if (splitResult.code == 429) { - throw { + if (splitResult.code === 429) { + return { code: splitResult.code, - message: splitResult.data.error + message: splitResult.message } } @@ -157,7 +171,7 @@ async function translate(text, sourceLang, targetLang, dlSession, tagHandling, p } const ret = { - code: 200, + code: postData.status, id: postData.id, method: "Free", data: translatedText, @@ -167,8 +181,9 @@ async function translate(text, sourceLang, targetLang, dlSession, tagHandling, p } if(printResult) console.log(ret); return ret; - } catch(err) { - return err; + } catch (err) { + console.error("[ERROR] translate:", err); + throw new Error(err.message || err); } } diff --git a/src/translate_old.js b/src/translate_old.js deleted file mode 100644 index 40951f8..0000000 --- a/src/translate_old.js +++ /dev/null @@ -1,130 +0,0 @@ -// 由于代码已重构,此实现暂时停用,部分旧实现将会陆续合并到新的实现,以确保向前兼容 - -import axios from 'axios'; -import { brotliDecompress } from 'zlib'; - -const DEEPL_BASE_URL = 'https://www2.deepl.com/jsonrpc'/*, - DEEPL_PRO_URL = 'https://api.deepl.com', - DEEPL_FREE_URL = 'https://api-free.deepl.com'*/; -const headers = { - "Accept": "*/*", - "Accept-Language": "en-US,en;q=0.9,zh-CN;q=0.8,zh-TW;q=0.7,zh-HK;q=0.6,zh;q=0.5", - "Authorization": "None", - "Cache-Control": "no-cache", - "Content-Type": "application/json", - "DNT": "1", - "Origin": "chrome-extension://cofdbpoegempjloogbagkncekinflcnj", - "Pragma": "no-cache", - "Priority": "u=1, i", - "Referer": "https://www.deepl.com/", - "Sec-Fetch-Dest": "empty", - "Sec-Fetch-Mode": "cors", - "Sec-Fetch-Site": "none", - "Sec-GPC": "1", - "User-Agent": "DeepLBrowserExtension/1.28.0 Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36" -}; - -function getICount(translateText) { - return (translateText || '').split('i').length - 1; -} - -function getRandomInt(min=8300000, max=8399998) { - min = Math.ceil(min); - max = Math.floor(max); - return (Math.floor(Math.random() * (max - min + 1)) + min) * 1000; -} - -function getTimestamp(iCount) { - const ts = Date.now(); - if (iCount === 0) { - return ts; - } - iCount++; - return ts - (ts % iCount) + iCount; -} - -/** - * 你可以在其他js中调用,无需运行 'npm start' - * 如果无需在控制台打印,最后一个布尔值参数可以去掉 - * - * @async - * @param {string} text - 待翻译的文本 - * @param {string} [sourceLang='AUTO'] - 源语言国家/地区代号 默认自动识别 - * @param {string} targetLang - 目标语言国家/地区代号 - * @param {number} [alternativeCount] - 请求的备选翻译数量 - * @param {boolean} [printResult] - 控制台打印返回结果 - * @returns {Promise