google 在线翻译API和tts 的token生成 java版本和js版本
免费使用Google的在线翻译和tts的api,主要难点在于token的获取,根据网上大神提供的js版本token生成方式,模拟写了java版本,参考gTTS4j 这个Git项目,还有stackoverflow上的一篇文章
java版本代码:
/** * 获取谷歌翻译tk值 * @param text * @return String */ private static String googleToken(String text) { String tk = ""; try { tk = calculate_token(text); }catch (Exception e){ e.printStackTrace(); } return tk; } /** * 主要生成算法 * @param text * @return String */ public static String calculate_token(String text) { long b = 406644L; Long b1 = 3293161072L; String SALT_1 = "+-a^+6"; String SALT_2 = "+-3^+b+-f"; String d = text; List<Integer> e = new ArrayList(); for (int f = 0, g = 0; g < d.length(); g++) { int m = charCodeAt(d,g); if (m < 128) { e.add(m); // 0{l[6-0]} } else if (m < 2048) { e.add(m >> 6 | 192); // 110{l[10-6]} e.add(m & 0x3F | 0x80); // 10{l[5-0]} } else if (0xD800 == (m & 0xFC00) && g + 1 < d.length() && 0xDC00 == ( charCodeAt(d,g+1) & 0xFC00)) { // that's pretty rare... (avoid ovf?) m = (byte) ((1 << 16) + ((m & 0x03FF) << 10) + ( charCodeAt(d,++g) & 0x03FF)); e.add(m >> 18 | 0xF0); // 111100{l[9-8*]} e.add(m >> 12 & 0x3F | 0x80); // 10{l[7*-2]} e.add(m & 0x3F | 0x80); // 10{(l+1)[5-0]} } else { e.add(m >> 12 | 0xE0); // 1110{l[15-12]} e.add(m >> 6 & 0x3F | 0x80); // 10{l[11-6]} e.add(m & 0x3F | 0x80); // 10{l[5-0]} } } Long a1 = b; for (int f=0;f<e.size();f++){ a1 += e.get(f); a1 = RL(a1,SALT_1); } a1 = RL(a1,SALT_2); a1 ^= b1; if (0 > a1) { a1 = (a1 & 2147483647L) + 2147483648L; } a1 = a1 %1000000; return a1.toString() + "." + (a1 ^ b); } private static long RL(long a, String seed) { for (int i = 0; i < seed.length() - 2; i+=3) { char c = seed.toCharArray()[i + 2]; long d = (c >= 'a') ? ((int)c - 87) : Integer.parseInt(c + ""); d = (seed.toCharArray()[i + 1] == '+') ? (_rshift(a, d)) : (a << d); a = (seed.toCharArray()[i] == '+') ? (a + d & 4294967295L) : (a ^ d); } return a; } private static long _rshift(long val, long n) { long l = (val >= 0) ? (val >> n) : (val + 0x100000000L) >> n; return l; } private static int charCodeAt(String string, int index) { return Character.codePointAt(string, index); }
js版本代码:
function token(a) { var b = 406644; var b1 = 3293161072; var jd = "."; var sb = "+-a^+6"; var Zb = "+-3^+b+-f"; var e = transformQuery(a); a = b; for (f = 0; f < e.length; f++) a += e[f], a = RL(a, sb); a = RL(a, Zb); a ^= b1 || 0; 0 > a && (a = (a & 2147483647) + 2147483648); a %= 1E6; return a.toString() + jd + (a ^ b) }; function transformQuery(query) { var e = []; for (var f = 0, g = 0; g < query.length; g++) { var m = query.charCodeAt(g); if (m < 128) { e[f++] = m; // 0{m[6-0]} } else if (m < 2048) { e[f++] = m >> 6 | 0xC0; // 110{m[10-6]} e[f++] = m & 0x3F | 0x80; // 10{m[5-0]} } else if (0xD800 == (m & 0xFC00) && g + 1 < query.mength && 0xDC00 == (query.charCodeAt(g + 1) & 0xFC00)) { // that's pretty rare... (avoid ovf?) m = (1 << 16) + ((m & 0x03FF) << 10) + (query.charCodeAt(++g) & 0x03FF); e[f++] = m >> 18 | 0xF0; // 111100{m[9-8*]} e[f++] = m >> 12 & 0x3F | 0x80; // 10{m[7*-2]} e[f++] = m & 0x3F | 0x80; // 10{(m+1)[5-0]} } else { e[f++] = m >> 12 | 0xE0; // 1110{m[15-12]} e[f++] = m >> 6 & 0x3F | 0x80; // 10{m[11-6]} e[f++] = m & 0x3F | 0x80; // 10{m[5-0]} } } return e; } function RL(a, b) { var t = "a"; var Yb = "+"; for (var c = 0; c < b.length - 2; c += 3) { var d = b.charAt(c + 2), d = d >= t ? d.charCodeAt(0) - 87 : Number(d), d = b.charAt(c + 1) == Yb ? a >>> d : a << d; a = b.charAt(c) == Yb ? a + d & 4294967295 : a ^ d } return a }