Created
February 28, 2024 03:20
-
-
Save starxg/596de36b55bd1a508ae184e39940b718 to your computer and use it in GitHub Desktop.
Google Translate API
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import cn.hutool.http.HttpRequest; | |
import cn.hutool.http.HttpUtil; | |
import org.apache.commons.lang3.StringUtils; | |
import java.util.Arrays; | |
public class Test { | |
public static class Hasher { | |
public long shiftLeftOrRightThenSumOrXor(long num, String[] opArray) { | |
long result = num; | |
int current = 0; | |
while (current < opArray.length) { | |
char op1 = opArray[current].charAt(1); // '+' | '-' ~ SUM | XOR | |
char op2 = opArray[current].charAt(0); // '+' | '^' ~ SLL | SRL | |
char xd = opArray[current].charAt(2); // [0-9a-f] | |
assertError(op1 == '+' | |
|| op1 == '-', "Invalid OP: " + op1); | |
assertError(op2 == '+' | |
|| op2 == '^', "Invalid OP: " + op2); | |
assertError(('0' <= xd && xd <= '9') | |
|| ('a' <= xd && xd <= 'f'), "Not an 0x? value: " + xd); | |
int shiftAmount = hexCharAsNumber(xd); | |
int mask = (op1 == '+') ? ((int) result) >>> shiftAmount : ((int) result) << shiftAmount; | |
long subresult = (op2 == '+') ? (((int) result) + ((int) mask) & 0xffffffff) | |
: (((int) result) ^ mask); | |
result = subresult; | |
current++; | |
} | |
return result; | |
} | |
public void assertError(boolean cond, String e) { | |
if (!cond) { | |
System.err.println(); | |
} | |
} | |
public int hexCharAsNumber(char xd) { | |
return (xd >= 'a') ? xd - 87 : Character.getNumericValue(xd); | |
} | |
public int[] transformQuery(String query) { | |
int[] e = new int[query.length() << 2]; | |
int resultSize = 1000; | |
for (int f = 0, g = 0; g < query.length(); g++) { | |
int l = query.charAt(g); | |
if (l < 128) { | |
e[f++] = l; // 0{l[6-0]} | |
} else if (l < 2048) { | |
e[f++] = l >> 6 | 0xC0; // 110{l[10-6]} | |
e[f++] = l & 0x3F | 0x80; // 10{l[5-0]} | |
} else if (0xD800 == (l & 0xFC00) && | |
g + 1 < query.length() && 0xDC00 == (query.charAt(g + 1) & 0xFC00)) { | |
// that's pretty rare... (avoid ovf?) | |
l = (1 << 16) + ((l & 0x03FF) << 10) + (query.charAt(++g) & 0x03FF); | |
e[f++] = l >> 18 | 0xF0; // 111100{l[9-8*]} | |
e[f++] = l >> 12 & 0x3F | 0x80; // 10{l[7*-2]} | |
e[f++] = l & 0x3F | 0x80; // 10{(l+1)[5-0]} | |
} else { | |
e[f++] = l >> 12 | 0xE0; // 1110{l[15-12]} | |
e[f++] = l >> 6 & 0x3F | 0x80; // 10{l[11-6]} | |
e[f++] = l & 0x3F | 0x80; // 10{l[5-0]} | |
} | |
resultSize = f; | |
} | |
return Arrays.copyOf(e, resultSize); | |
} | |
public long normalizeHash(long encondindRound2) { | |
if (encondindRound2 < 0) { | |
encondindRound2 = (encondindRound2 & 0x7fffffff) + 0x80000000L; | |
} | |
return (encondindRound2) % 1_000_000; | |
} | |
/* | |
/ EXAMPLE: | |
/ | |
/ INPUT: query: 'hola', windowTkk: '409837.2120040981' | |
/ OUTPUT: '70528.480109' | |
/ | |
*/ | |
public String calcHash(String query, String windowTkk) { | |
// STEP 1: spread the the query char codes on a byte-array, 1-3 bytes per char | |
int[] bytesArray = transformQuery(query); | |
// STEP 2: starting with TKK index, | |
// add the array from last step one-by-one, and do 2 rounds of shift+add/xor | |
String[] d = windowTkk.split("\\."); | |
int tkkIndex = 0; | |
try { | |
tkkIndex = Integer.valueOf(d[0]); | |
} catch (Exception e) { | |
e.printStackTrace(); | |
} | |
long tkkKey = 0; | |
try { | |
tkkKey = Long.valueOf(d[1]); | |
} catch (Exception e) { | |
e.printStackTrace(); | |
} | |
int current = 0; | |
long result = tkkIndex; | |
while (current < bytesArray.length) { | |
result += bytesArray[current]; | |
long subresult = shiftLeftOrRightThenSumOrXor(result, | |
new String[]{"+-a", "^+6"}); | |
result = subresult; | |
current++; | |
} | |
long encondingRound1 = result; | |
//System.out.println("encodingRound1: " + encondingRound1); | |
// STEP 3: apply 3 rounds of shift+add/xor and XOR with they TKK key | |
long encondingRound2 = ((int) shiftLeftOrRightThenSumOrXor(encondingRound1, | |
new String[]{"+-3", "^+b", "+-f"})) ^ ((int) tkkKey); | |
//System.out.println("encodingRound2: " + encondingRound2); | |
// STEP 4: Normalize to 2s complement & format | |
long normalizedResult = normalizeHash(encondingRound2); | |
//System.out.println("normalizedResult: " + normalizedResult); | |
return String.valueOf(normalizedResult) + "." | |
+ (((int) normalizedResult) ^ (tkkIndex)); | |
} | |
} | |
public static void main(String[] args) { | |
final String q1 = "<a i=0>Our mission is to</a><a i=1>organize</a><a i=2> the world’s </a><a i=3>information</a><a i=4> and make it </a><a i=5>universally accessible</a><a i=6> and </a><a i=7>useful</a><a i=8>.</a>"; | |
final String q2 = "Hello world!"; | |
final Hasher hasher = new Hasher(); | |
final String tk = hasher.calcHash(String.join(StringUtils.EMPTY, q1, q2), "XXX"); | |
final HttpRequest request = HttpUtil.createPost("https://translate.googleapis.com/translate_a/t?anno=3&client=te_lib&format=html&v=1.0&sl=auto&tl=zh-CN&sp=pbmt&tk=" + tk); | |
request.header("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36"); | |
request.contentType("application/x-www-form-urlencoded"); | |
request.form("q", q1); | |
request.form("q", q2); | |
System.out.println(request.execute().body()); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment