Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

恢复彩云 API 的可用性 #135

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 98 additions & 0 deletions config/caiyunApi.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
var JWT_GENERATE_URL =
"https://api.interpreter.caiyunai.com/v1/user/jwt/generate";
var TRANSLATE_URL = "https://api.interpreter.caiyunai.com/v1/translator";
var ORIGIN_URL = "https://fanyi.caiyunapp.com";
var USER_AGENT =
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.109 Safari/537.36";
var AUTH_TOKEN = "token:qgemv4jr1y38jyq6vhvi";

////////////////////////////////////////////////////////

var jwt;
var browserId;

if (!browserId) {
browserId = randomBrowserId();
}

jwtCheck()
.then(() => translate())
.catch((e) => callback(`error: ${e}`));

////////////////////////////////////////////////////////

function jwtCheck() {
if (
!jwt ||
JSON.parse(Buffer.from(jwt.split(".")[1], "base64")).exp < Date.now / 1000
) {
return renewJWT().then((t) => (jwt = t));
} else {
return Promise.resolve();
}
}

function renewJWT() {
return Request.post(JWT_GENERATE_URL, {
headers: {
Origin: ORIGIN_URL,
Referer: ORIGIN_URL,
"User-Agent": USER_AGENT,
"X-Authorization": AUTH_TOKEN,
},
body: {
browser_id: browserId,
},
json: true,
}).then((j) => j.jwt);
}

function translate() {
return Request.post(TRANSLATE_URL, {
gzip: true,
headers: {
Origin: ORIGIN_URL,
Referer: ORIGIN_URL,
"T-Authorization": jwt,
"X-Authorization": AUTH_TOKEN,
"User-Agent": USER_AGENT,
},
body: {
source: text,
trans_type: "ja2zh",
request_id: "web_fanyi",
media: "text",
os_type: "web",
dict: false,
cached: false,
replaced: true,
browser_id: browserId,
},
json: true,
}).then((json) => {
callback(decrypt(json.target));
});
}

////////////////////////////////////////////////////////

function randomBrowserId() {
var characters = "abcdefghijklmnopqrstuvwxyz0123456789";
var result = "";
for (var i = 0; i < 32; i++) {
result += characters.charAt(Math.floor(Math.random() * characters.length));
}
return result;
}

function rocn(str, n = 13) {
return str.replace(/[a-zA-Z]/g, function (c) {
return String.fromCharCode(
(c <= "Z" ? 90 : 122) >= (c = c.charCodeAt(0) + n) ? c : c - 26
);
});
}

function decrypt(str) {
return Buffer.from(rocn(str), "base64").toString("utf-8");
}
9 changes: 3 additions & 6 deletions config/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,9 @@
},
{
"enable": false,
"method": "POST",
"name": "彩云",
"requestBodyFormat": "J{\"source\": %TEXT%, \"trans_type\": \"ja2zh\", \"request_id\": \"demo\", \"detect\": \"true\"}",
"requestHeaders": "{\"X-Authorization\": \"token 3975l6lr5pcbvidl6jl2\"}",
"responseBodyPattern": "J%RESPONSE%.target",
"url": "https://api.interpreter.caiyunai.com/v1/translator"
"external": true,
"jsFile": "config\\caiyunApi.js",
"name": "彩云"
},
{
"enable": false,
Expand Down
1 change: 1 addition & 0 deletions src/main/translate/ExternalApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ export default class ExternalApi implements yuki.Translator {

private createVmContext () {
this.responseVmContext = vm.createContext({
Buffer,
Request: request,
text: '',
md5: (data: string, encoding: crypto.HexBase64Latin1Encoding) => {
Expand Down
36 changes: 15 additions & 21 deletions test/unit/specs/main/Api.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ import Api from '../../../../src/main/translate/Api'
import TranslationManager from '../../../../src/main/translate/TranslationManager'

describe('Api', () => {
before(() => {
(global as any).__baseDir = __dirname
})

it('gets translation from form and parses with regex', (done) => {
const googleCN = new Api({
name: 'googleCN',
Expand All @@ -16,7 +20,7 @@ describe('Api', () => {
'悠真くんを攻略すれば210円か。なるほどなぁ…',
(translation) => {
try {
expect(translation).to.equal('如果捕获了尤马坤,则为210日元。我知道了 ...')
expect(translation).to.equal('如果您捕获尤马坤,它是210日元。我懂了...')
} catch (e) {
return done(e)
}
Expand All @@ -36,14 +40,10 @@ describe('Api', () => {
enable: true
},
{
enable: true,
method: 'POST',
name: 'caiyun',
requestBodyFormat:
'J{"source": %TEXT%, "trans_type": "ja2zh", "request_id": "demo", "detect": "true"}',
requestHeaders: '{"X-Authorization": "token 3975l6lr5pcbvidl6jl2"}',
responseBodyPattern: 'J%RESPONSE%.target',
url: 'https://api.interpreter.caiyunai.com/v1/translator'
external: true,
jsFile: '../../../../config/caiyunApi.js',
enable: true
}
]

Expand All @@ -56,11 +56,8 @@ describe('Api', () => {
console.log(translations)
try {
expect(translations.original).to.equal('悠真くんを攻略すれば210円か。なるほどなぁ…')
expect(translations.translations.googleCN).to.equal('如果捕获了尤马坤,则为210日元。我知道了 ...')
expect(translations.translations.caiyun).to.be.oneOf([
'攻下悠真的话是210日元吗。 原来如此',
"ERR: TypeError: Cannot read property 'target' of undefined"
])
expect(translations.translations.googleCN).to.equal('如果您捕获尤马坤,它是210日元。我懂了...')
expect(translations.translations.caiyun).to.equal('攻下悠真的话是210日元吗。原来如此')
} catch (e) {
return done(e)
}
Expand Down Expand Up @@ -120,14 +117,10 @@ describe('Api', () => {
enable: true
},
{
enable: false,
method: 'POST',
name: 'caiyun',
requestBodyFormat: 'J{"source": %TEXT%, "trans_type": "ja2zh", ' +
'"request_id": "web_fanyi", "os_type": "web", ' +
'"dict": "false", "cached": "false", "replaced": "false"}',
responseBodyPattern: 'J%RESPONSE%.target',
url: 'https://api.interpreter.caiyunai.com/v1/translator'
external: true,
jsFile: '../../../../config/caiyunApi.js',
enable: true
}
]

Expand All @@ -140,7 +133,8 @@ describe('Api', () => {
expect(translations).to.deep.equal({
original: '悠真くんを攻略すれば210円か。なるほどなぁ…',
translations: {
googleCN: '如果捕获了尤马坤,则为210日元。我知道了 ...'
googleCN: '如果您捕获尤马坤,它是210日元。我懂了...',
caiyun: '攻下悠真的话是210日元吗。原来如此'
}
})
} catch (e) {
Expand Down
4 changes: 2 additions & 2 deletions test/unit/specs/main/ExternalApi.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ describe('ExternalApi', () => {
const qq = new ExternalApi({
enable: true,
external: true,
jsFile: '..\\..\\temp\\qqApi.js',
jsFile: '../../temp/qqApi.js',
name: 'qq'
})

Expand All @@ -31,7 +31,7 @@ describe('ExternalApi', () => {
const qq = new ExternalApi({
enable: true,
external: true,
jsFile: '..\\..\\temp\\qqApi.js',
jsFile: '../../temp/qqApi.js',
name: 'qq'
})

Expand Down