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;
|