Skip to content

Commit b56aade

Browse files
committed
google-translate availability check max 2.5s to prevent blocking voice enumeration
1 parent 284f006 commit b56aade

File tree

1 file changed

+53
-79
lines changed

1 file changed

+53
-79
lines changed

js/google-translate.js

Lines changed: 53 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -1,97 +1,67 @@
11

22
(function() {
3-
var got = {
4-
get: function(url) {
5-
return ajaxGet(url).then(function(x) {return {body: x}});
6-
},
7-
post: function(url, opts) {
8-
return ajaxPost(url + "?" + urlEncode(opts.searchParams), opts.form).then(function(x) {return {body: x}});
9-
}
10-
};
3+
const url = "https://translate.google.com"
114

12-
var config = {
13-
get: function(key) {
14-
return getSettings([key]).then(function(settings) {return settings[key]});
15-
},
16-
set: function(key, value) {
17-
var settings = {};
18-
settings[key] = value;
19-
return updateSettings(settings);
5+
const wiz$ = rxjs.defer(async () => {
6+
let wiz = await getSetting("gtWiz")
7+
if (wiz && wiz.expire > Date.now()) {
8+
console.debug("Wiz still valid")
9+
} else {
10+
console.debug("Fetching new wiz")
11+
wiz = await fetchWizGlobalData(url)
12+
wiz.expire = Date.now() + 3600*1000
13+
await updateSetting("gtWiz", wiz)
2014
}
21-
};
15+
return wiz
16+
}).pipe(
17+
rxjs.timeout({
18+
first: 7500,
19+
with: () => rxjs.throwError(() => new Error("Timeout fetching " + url))
20+
}),
21+
rxjs.tap({
22+
error: err => console.error("Failed fetch wiz", err)
23+
}),
24+
rxjs.share({
25+
connector: () => new rxjs.ReplaySubject(1),
26+
resetOnComplete: false,
27+
resetOnError: false,
28+
resetOnRefCountZero: false
29+
})
30+
)
2231

2332
var batchNumber = 0;
2433

2534

26-
/**
27-
* @param {string} rpcId ID of service to call
28-
* @param {Array} payload Arguments for the service call
29-
* @param {string} [opts.tld="com"] translate.google.[tld]
30-
* @param {number} [opts.tokensTTL=3600] How long to cache tokens
31-
*/
32-
function batchExecute(rpcId, payload, opts) {
33-
if (!opts) opts = {};
34-
if (!opts.tld) opts.tld = "com";
35-
if (!opts.tokensTTL) opts.tokensTTL = 3600;
36-
37-
var url = "https://translate.google." + opts.tld;
38-
39-
return Promise.resolve(config.get("wiz"))
40-
.then(function(wiz) {
41-
if (wiz && (wiz.timestamp + opts.tokensTTL * 1000) > Date.now()) return wiz;
42-
return fetchWizGlobalData(url)
43-
.then(function(wiz) {
44-
wiz.timestamp = Date.now();
45-
config.set("wiz", wiz);
46-
return wiz;
47-
})
48-
})
49-
.then(function(wiz) {
50-
return getBatchExecuteParams(wiz, rpcId, payload);
51-
})
52-
.then(function(params) {
53-
if (opts.validateOnly) return;
54-
if (!params.body.at) delete params.body.at;
55-
return got.post(url + "/_/TranslateWebserverUi/data/batchexecute", {
56-
searchParams: params.query,
57-
form: params.body,
58-
responseType: "text"
59-
})
60-
.then(function(res) {
61-
var match = res.body.match(/\d+/);
62-
return res.body.substr(match.index + match[0].length, Number(match[0]));
63-
})
64-
.then(JSON.parse)
65-
.then(function(envelopes) {
66-
var payload = envelopes[0][2];
67-
return JSON.parse(payload);
68-
})
69-
})
35+
async function batchExecute(rpcId, payload) {
36+
const wiz = await rxjs.firstValueFrom(wiz$)
37+
const {query, body} = getBatchExecuteParams(wiz, rpcId, payload)
38+
if (!body.at) delete body.at
39+
const res = {body: await ajaxPost(url + "/_/TranslateWebserverUi/data/batchexecute?" + urlEncode(query), body)}
40+
var match = res.body.match(/\d+/);
41+
const envelopes = JSON.parse(res.body.substr(match.index + match[0].length, Number(match[0])))
42+
var payload = envelopes[0][2];
43+
return JSON.parse(payload);
7044
}
7145

7246

73-
function fetchWizGlobalData(url) {
47+
async function fetchWizGlobalData(url) {
7448
var propFinder = {
7549
"f.sid": /"FdrFJe":"(.*?)"/,
7650
"bl": /"cfb2h":"(.*?)"/,
7751
"at": /"SNlM0e":"(.*?)"/,
7852
}
79-
return got.get(url)
80-
.then(function(res) {
81-
var start = res.body.indexOf("WIZ_global_data = {");
82-
if (start == -1) throw new Error("Wiz not found");
83-
var end = res.body.indexOf("</script>", start);
84-
return res.body.substring(start, end);
85-
})
86-
.then(function(text) {
87-
var wiz = {};
88-
for (var prop in propFinder) {
89-
var match = propFinder[prop].exec(text);
90-
if (match) wiz[prop] = match[1];
91-
else console.warn("Wiz property not found '" + prop + "'");
92-
}
93-
return wiz;
94-
})
53+
const res = {body: await ajaxGet(url)}
54+
var start = res.body.indexOf("WIZ_global_data = {");
55+
if (start == -1) throw new Error("Wiz not found");
56+
var end = res.body.indexOf("</script>", start);
57+
const text = res.body.substring(start, end)
58+
var wiz = {};
59+
for (var prop in propFinder) {
60+
var match = propFinder[prop].exec(text);
61+
if (match) wiz[prop] = match[1];
62+
else console.warn("Wiz property not found '" + prop + "'");
63+
}
64+
return wiz;
9565
}
9666

9767

@@ -118,7 +88,11 @@
11888

11989

12090
window.googleTranslateReady = function() {
121-
return batchExecute("jQ1olc", [], {validateOnly: true});
91+
return rxjs.firstValueFrom(
92+
wiz$.pipe(
93+
rxjs.timeout(2500)
94+
)
95+
)
12296
}
12397

12498
window.googleTranslateSynthesizeSpeech = function(text, lang) {

0 commit comments

Comments
 (0)