mirror of https://github.com/jkjoy/sunpeiwen.git
339 lines
16 KiB
JavaScript
339 lines
16 KiB
JavaScript
'use strict';
|
||
|
||
const front = require('hexo-front-matter');
|
||
const fs = require('hexo-fs');
|
||
// const request = require('request');
|
||
const rp = require('request-promise');
|
||
const qs = require('querystring');
|
||
const url = require('url');
|
||
const cheerio = require('cheerio');
|
||
const http = require('http');
|
||
|
||
//辅助函数:首次获取google翻译页面的TTK -- 此方法有问题,待完善,暂时选用固定值方法
|
||
// let initial_google_get_ttk =((function(){
|
||
// let final_tkk = null;
|
||
// let initial_google_trans_url = "http://translate.google.cn";
|
||
// request.get({
|
||
// 'url':initial_google_trans_url
|
||
// ,'proxy':'http://localhost:8123'
|
||
// ,'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.75 Safari/537.36 QQBrowser/4.1.4132.400'
|
||
// },function(error,response,body){
|
||
// if(error){
|
||
// console.log(error);
|
||
// }
|
||
// if(response && response.statusCode==200){
|
||
// var myRegexp = /TKK=eval.*var a\\x3d(.*);var b\\x3d(.*);return ([0-9]+)\+/g;
|
||
// var match = body.match(myRegexp);
|
||
// let tkk_param1 = RegExp.$3;
|
||
// let tkk_param2 = RegExp.$1+RegExp.$2;
|
||
// final_tkk = tkk_param1+"."+tkk_param2;
|
||
// console.log(final_tkk);
|
||
// return final_tkk;
|
||
// }
|
||
// });
|
||
// })());
|
||
|
||
//辅助函数:固定值获取TKK ---1
|
||
let TKK = ((function () {
|
||
var a = 561666268;
|
||
var b = 1526272306;
|
||
return 406398 + '.' + (a + b);
|
||
})());
|
||
//辅助函数:根据获取的TKK获取tk ---2
|
||
let b = function (a, b) {
|
||
for (var d = 0; d < b.length - 2; d += 3) {
|
||
var c = b.charAt(d + 2),
|
||
c = "a" <= c ? c.charCodeAt(0) - 87 : Number(c),
|
||
c = "+" == b.charAt(d + 1) ? a >>> c : a << c;
|
||
a = "+" == b.charAt(d) ? a + c & 4294967295 : a ^ c
|
||
}
|
||
return a;
|
||
}
|
||
//辅助函数:根据获取的TKK获取tk ---3
|
||
let get_tk = function (a) {
|
||
for (var e = TKK.split("."), h = Number(e[0]) || 0, g = [], d = 0, f = 0; f < a.length; f++) {
|
||
var c = a.charCodeAt(f);
|
||
128 > c ? g[d++] = c : (2048 > c ? g[d++] = c >> 6 | 192 : (55296 == (c & 64512) && f + 1 < a.length && 56320 == (a.charCodeAt(f + 1) & 64512) ? (c = 65536 + ((c & 1023) << 10) + (a.charCodeAt(++f) & 1023), g[d++] = c >> 18 | 240, g[d++] = c >> 12 & 63 | 128) : g[d++] = c >> 12 | 224, g[d++] = c >> 6 & 63 | 128), g[d++] = c & 63 | 128)
|
||
}
|
||
a = h;
|
||
for (d = 0; d < g.length; d++) a += g[d], a = b(a, "+-a^+6");
|
||
a = b(a, "+-3^+b+-f");
|
||
a ^= Number(e[1]) || 0;
|
||
0 > a && (a = (a & 2147483647) + 2147483648);
|
||
a %= 1E6;
|
||
return a.toString() + "." + (a ^ h);
|
||
}
|
||
//样例 http://translate.google.cn/translate_a/t?client=t&sl=zh-CN&tl=en&hl=zh-CN&v=1.0&source=is&tk=244803.389825&q=%E5%A4%A9%E6%B0%94%E5%BE%88%E5%A5%BD
|
||
//Google翻译
|
||
let google_translation = async function (data, fromLanguage, toLanguage, is_need_proxy, proxy_url) {
|
||
let tmpPost = front.parse(data.raw);
|
||
let ori_translate_title = data.translate_title;//先保存原来的翻译标题
|
||
data.translate_title = '';//初始化
|
||
// console.log("原始data:"+postStr);
|
||
let title = data.title;
|
||
let encodedStr = encodeURI(title);
|
||
let googleTransUrl = "https://translate.google.cn/translate_a/t?";
|
||
googleTransUrl += "client=" + "t";
|
||
googleTransUrl += "&sl=" + fromLanguage;// source language
|
||
googleTransUrl += "&tl=" + toLanguage; // to language
|
||
googleTransUrl += "&hl=" + fromLanguage;
|
||
googleTransUrl += "$dt=at&dt=bd&dt=ex&dt=ld&dt=md&dt=qca&dt=rw&dt=rm&dt=ss&dt=t&ie=UTF-8&oe=UTF-8&clearbtn=1&otf=1&pc=1&ssel=0&tsel=0&kc=2&v=1.0&source=is";
|
||
googleTransUrl += "&tk=" + get_tk(title);
|
||
googleTransUrl += "&q=" + encodedStr;
|
||
let google_request_option_str = {
|
||
method: 'GET',
|
||
uri: googleTransUrl
|
||
};
|
||
if (is_need_proxy) {
|
||
google_request_option_str = {
|
||
method: 'GET',
|
||
uri: googleTransUrl,
|
||
proxy: proxy_url
|
||
};
|
||
}
|
||
await rp(google_request_option_str).then(function (body) {
|
||
if (body != null) {
|
||
//去除标点符号,空格转换为横线连接
|
||
let title_array = body.replace(/[\~|\`|\!|\@|\#|\$|\%|\^|\&|\*|\(|\)|\-|\_|\+|\=|\||\\|\[|\]|\{|\}|\;|\:|\"|\'|\,|\<|\.|\>|\/|\?]/g, "").replace(/\s/g, "-").split("-");
|
||
let tmp_title_array = [];
|
||
let final_title_str = '';
|
||
//去除重复单词和空值,只保留一个
|
||
for (var i = 0; i < title_array.length; i++) {
|
||
let lowercase_title = title_array[i].toLowerCase();
|
||
if (tmp_title_array.indexOf(lowercase_title) == -1 && lowercase_title!='') {
|
||
tmp_title_array.push(lowercase_title);
|
||
}
|
||
}
|
||
final_title_str = tmp_title_array.join("-");
|
||
// console.log(final_title_str);
|
||
let temp_tanslate_title = final_title_str.replace(/\"/g, "").replace(/\"/g,"");
|
||
data.translate_title = temp_tanslate_title;
|
||
tmpPost.translate_title = temp_tanslate_title;
|
||
if(ori_translate_title!=temp_tanslate_title){
|
||
let postStr = front.stringify(tmpPost);
|
||
postStr = '---\n' + postStr;
|
||
fs.writeFileSync(data.full_source, postStr, 'utf-8');
|
||
console.log("Google->Generate link %s for post [%s]", temp_tanslate_title, data.title);
|
||
}else{
|
||
data.translate_title = ori_translate_title;
|
||
}
|
||
return data;
|
||
}
|
||
}).catch(function (err) {
|
||
console.error(err);
|
||
});
|
||
};
|
||
//有道翻译
|
||
//样例:http://fanyi.youdao.com/openapi.do?keyfrom=evansliu-blog&key=230388660&type=data&doctype=<doctype>&version=1.1&q=要翻译的文本(需要urlencode)
|
||
let youdao_translation = async function (data, youdao_api_key, youdao_keyfrom) {
|
||
let tmpPost = front.parse(data.raw);
|
||
let ori_translate_title = data.translate_title;//先保存原来的翻译标题
|
||
data.translate_title = '';//初始化
|
||
let title = data.title;
|
||
let encodedStr = encodeURI(title);
|
||
let youdaoTransUrl = "http://fanyi.youdao.com/openapi.do?keyfrom=" + youdao_keyfrom;
|
||
youdaoTransUrl += "&key=" + youdao_api_key;
|
||
youdaoTransUrl += "&type=data&doctype=json&version=1.1&q=" + encodedStr;
|
||
await rp(youdaoTransUrl).then(function (body) {
|
||
if (body != null) {
|
||
let json_str = JSON.parse(body);
|
||
let temp_str = json_str.translation[0];
|
||
// let title_array = temp_str.replace(/\s/g, "-").replace(/(.)\1+/gi, '$1').split("-");
|
||
//去除标点符号,空格转换为横线连接
|
||
let title_array = temp_str.replace(/[\~|\`|\!|\@|\#|\$|\%|\^|\&|\*|\(|\)|\-|\_|\+|\=|\||\\|\[|\]|\{|\}|\;|\:|\"|\'|\,|\<|\.|\>|\/|\?]/g, "").replace(/\s/g, "-").split("-");
|
||
let tmp_title_array = [];
|
||
let final_title_str = '';
|
||
//去除重复单词和空值,只保留一个
|
||
for (var i = 0; i < title_array.length; i++) {
|
||
let lowercase_title = title_array[i].toLowerCase();
|
||
if (tmp_title_array.indexOf(lowercase_title) == -1 && lowercase_title!='') {
|
||
tmp_title_array.push(lowercase_title);
|
||
}
|
||
}
|
||
final_title_str = tmp_title_array.join("-");
|
||
let temp_tanslate_title = final_title_str.replace(/\"/g, "").replace(/\"/g,"");
|
||
data.translate_title = temp_tanslate_title;
|
||
tmpPost.translate_title = temp_tanslate_title;
|
||
if(ori_translate_title!=temp_tanslate_title){
|
||
let postStr = front.stringify(tmpPost);
|
||
postStr = '---\n' + postStr;
|
||
fs.writeFileSync(data.full_source, postStr, 'utf-8');
|
||
console.log("Youdao->Generate link %s for post [%s]", temp_tanslate_title, data.title);
|
||
}else{
|
||
data.translate_title = ori_translate_title;
|
||
}
|
||
return data;
|
||
}
|
||
}).catch(function (err) {
|
||
console.error(err);
|
||
});
|
||
};
|
||
|
||
//百度翻译-需要appid+appkey版,每月前200w字翻译免费,足够大家写博客使用
|
||
let baidu_translation_with_appid = async function (data,fromLanguage,toLanguage,appid,appkey){
|
||
const lib_baidu_trans = require('./baidu_trans_md5.js');
|
||
let salt = (new Date).getTime();
|
||
let tmpPost = front.parse(data.raw);
|
||
let ori_translate_title = data.translate_title;//先保存原来的翻译标题
|
||
data.translate_title = '';//初始化
|
||
let query_title = data.title;
|
||
let encodedStr = encodeURI(query_title);
|
||
// 多个query可以用\n连接 如 query='apple\norange\nbanana\npear'
|
||
let str1 = appid + query_title + salt +appkey;
|
||
let sign = lib_baidu_trans.baidu_trans_md5(str1);
|
||
let baiduTransUrl = 'http://api.fanyi.baidu.com/api/trans/vip/translate';
|
||
let json_data = {
|
||
q: query_title,
|
||
appid: appid,
|
||
salt: salt,
|
||
from: fromLanguage,
|
||
to: toLanguage,
|
||
sign: sign
|
||
};
|
||
let baiduTransOption = {
|
||
method: 'GET',
|
||
uri: baiduTransUrl,
|
||
qs: json_data,
|
||
json: true
|
||
};
|
||
await rp(baiduTransOption).then(function (body) {
|
||
if (body != null) {
|
||
let trans_title = body['trans_result'][0]['dst'];
|
||
let trans_title_array = trans_title.toString().toLowerCase().split(" ");
|
||
let final_title_str = trans_title_array.join("-");
|
||
let temp_tanslate_title = final_title_str.replace(/\"/g, "").replace(/\"/g,"");
|
||
data.translate_title = temp_tanslate_title;
|
||
tmpPost.translate_title = temp_tanslate_title;
|
||
if(ori_translate_title!=temp_tanslate_title){
|
||
let postStr = front.stringify(tmpPost);
|
||
postStr = '---\n' + postStr;
|
||
fs.writeFileSync(data.full_source, postStr, 'utf-8');
|
||
console.log("Baidu->Generate link %s for post [%s]", temp_tanslate_title, data.title);
|
||
}else{
|
||
data.translate_title = ori_translate_title;
|
||
}
|
||
return data;
|
||
}
|
||
}).catch(function (err) {
|
||
console.error(err);
|
||
});
|
||
}
|
||
|
||
//百度翻译-无需appid版本,已完成Cookie+token为固定值版本,Cookie动态获取尚不知如何获取
|
||
//接口地址:http://fanyi.baidu.com/v2transapi
|
||
/**
|
||
'auto' => '自动检测',
|
||
'ara' => '阿拉伯语',
|
||
'de' => '德语',
|
||
'ru' => '俄语',
|
||
'fra' => '法语',
|
||
'kor' => '韩语',
|
||
'nl' => '荷兰语',
|
||
'pt' => '葡萄牙语',
|
||
'jp' => '日语',
|
||
'th' => '泰语',
|
||
'wyw' => '文言文',
|
||
'spa' => '西班牙语',
|
||
'el' => '希腊语',
|
||
'it' => '意大利语',
|
||
'en' => '英语',
|
||
'yue' => '粤语',
|
||
'zh' => '中文'
|
||
**/
|
||
let baidu_translation_no_appid = async function (data, fromLanguage, toLanguage) {
|
||
var baidu_decode = require('./sign.js');
|
||
let tmpPost = front.parse(data.raw);
|
||
let ori_translate_title = data.translate_title;//先保存原来的翻译标题
|
||
data.translate_title = '';//初始化,否则在生成html文件时,会调用之前的翻译内容,原因未知
|
||
let title = data.title;
|
||
let baiduTransUrl = "https://fanyi.baidu.com/v2transapi";
|
||
let baiduFanyiUrl = "http://fanyi.baidu.com";
|
||
let final_token = '';//初始化token
|
||
let final_gtk = '';//初始化GTK值
|
||
let final_baiduid = '';
|
||
// let gtk_val = '320305.131321201';
|
||
let final_sign = '';
|
||
let cookie_max_age = 0;
|
||
//首先get方式加载一次百度翻译页面,正则获取token值、gtk值和cookie中的BAIDUID
|
||
var token_options = {
|
||
uri: baiduFanyiUrl,
|
||
resolveWithFullResponse: true,//header和body全部返回值
|
||
};
|
||
await rp(token_options).then(function (response) {
|
||
if (response && response.statusCode == 200) {
|
||
let $ = cheerio.load(response.body);
|
||
let script_html = $('body>script').text();
|
||
let token_array = script_html.match(/token: '([^\"]*)\',/);
|
||
let token_str = token_array[0].split(",")[0];
|
||
final_token = token_str.replace("token: '", "").replace("'", "");
|
||
// console.log('final_token===>', final_token);
|
||
let gtk_array = script_html.match(/window.gtk = '([^\"]*)\';/);
|
||
let gtk_str = gtk_array[0].split(",")[0];
|
||
final_gtk = gtk_str.replace("window.gtk = '","").replace("';","");
|
||
// console.log('final_gtk==>',final_gtk);
|
||
let temp_baiduid_str = response.headers['set-cookie'][1];
|
||
let temp_baiduid_str2 = temp_baiduid_str.match(/BAIDUID=[^\s]*/);
|
||
final_baiduid = temp_baiduid_str2[0].replace("BAIDUID=","");
|
||
// console.log('final_baiduid===>',final_baiduid);
|
||
let cookie_max_age_str = temp_baiduid_str.match(/max-age=[^\s]*/);
|
||
cookie_max_age = cookie_max_age_str[0].replace("max-age=","").replace(";","");
|
||
// console.log('cookie_max_age===>',cookie_max_age);
|
||
final_sign = baidu_decode.get_baidu_hash(title, final_gtk);
|
||
// console.log('final_sign===>',final_sign);
|
||
}
|
||
}).catch(function (err) {
|
||
console.log('get token error==>', err);
|
||
});
|
||
//封装post数据
|
||
let postData = {
|
||
from: fromLanguage,
|
||
to: toLanguage,
|
||
query: title,
|
||
transtype: 'realtime',
|
||
simple_means_flag: 3,
|
||
sign: final_sign,
|
||
// token: final_token
|
||
token:'6902b9e28a39a2f4ea72c65f0724a170'
|
||
};
|
||
let postHeaders = {
|
||
'Cookie':'locale=zh; BAIDUID=092A5CA5950212EA685F7754D334A3F4:FG=1; REALTIME_TRANS_SWITCH=1; FANYI_WORD_SWITCH=1; HISTORY_SWITCH=1; SOUND_SPD_SWITCH=1; SOUND_PREFER_SWITCH=1; Hm_lvt_64ecd82404c51e03dc91cb9e8c025574=1526543144; Hm_lpvt_64ecd82404c51e03dc91cb9e8c025574=1526543145; from_lang_often=%5B%7B%22value%22%3A%22en%22%2C%22text%22%3A%22%u82F1%u8BED%22%7D%2C%7B%22value%22%3A%22zh%22%2C%22text%22%3A%22%u4E2D%u6587%22%7D%5D; to_lang_often=%5B%7B%22value%22%3A%22zh%22%2C%22text%22%3A%22%u4E2D%u6587%22%7D%2C%7B%22value%22%3A%22en%22%2C%22text%22%3A%22%u82F1%u8BED%22%7D%5D',
|
||
'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.101 Safari/537.36 QQBrowser/4.3.4986.400',
|
||
};
|
||
let options = {
|
||
method: 'POST',
|
||
uri: baiduTransUrl,
|
||
headers: postHeaders,
|
||
form: postData,
|
||
json:true
|
||
};
|
||
// console.log('options==>', options);
|
||
// return false;
|
||
await rp(options).then(function (response) {
|
||
if (response&&response.trans_result.status==0) {
|
||
let trans_title = response.trans_result.data[0].dst;
|
||
let trans_title_array = trans_title.toString().toLowerCase().split(" ");
|
||
let final_title_str = trans_title_array.join("-");
|
||
let temp_tanslate_title = final_title_str.replace(/\"/g, "").replace(/\"/g,"");
|
||
if(ori_translate_title!=temp_tanslate_title){
|
||
data.translate_title = temp_tanslate_title;
|
||
tmpPost.translate_title = temp_tanslate_title;
|
||
let postStr = front.stringify(tmpPost);
|
||
postStr = '---\n' + postStr;
|
||
fs.writeFileSync(data.full_source, postStr, 'utf-8');
|
||
console.log("Baidu->Generate link %s for post [%s]", temp_tanslate_title, data.title);
|
||
}else{
|
||
data.translate_title = ori_translate_title;
|
||
}
|
||
return data;
|
||
}
|
||
}).catch(function (err) {
|
||
console.log('post error===>',err);
|
||
// POST failed...
|
||
});
|
||
//错误代码:997,没有cookie; 998,cookie 过期;999,内部错误。
|
||
};
|
||
|
||
exports.google_translation = google_translation;
|
||
exports.youdao_translation = youdao_translation;
|
||
exports.baidu_translation_no_appid = baidu_translation_no_appid;
|
||
exports.baidu_translation_with_appid = baidu_translation_with_appid; |