fix: update speech recognition services

BREAKING CHANGE: the options for speech recognition services have changed,
the configuration of certain services may be needed
main
dessant 1 year ago
parent 428a5ee6d4
commit cd84690f36

@ -1,10 +0,0 @@
{
"presets": [
["@babel/env", {"useBuiltIns": "usage", "corejs": {"version": 3}}]
],
"env": {
"production": {
"plugins": ["lodash"]
}
}
}

@ -25,15 +25,17 @@ please consider contributing with
## Description ## Description
> Obviously, this blue part here is the land.
>
> — <cite>Byron "Buster" Bluth, reading a map</cite>
Buster is a browser extension which helps you to solve difficult captchas Buster is a browser extension which helps you to solve difficult captchas
by completing reCAPTCHA audio challenges using speech recognition. by completing reCAPTCHA audio challenges using speech recognition.
Challenges are solved by clicking on the extension button at the bottom Challenges are solved by clicking on the extension button at the bottom
of the reCAPTCHA widget. of the reCAPTCHA widget.
> Obviously, this blue part here is the land.
>
> — <cite>Byron "Buster" Bluth, reading a map</cite>
## Motivation
reCAPTCHA challenges remain a considerable burden on the web, reCAPTCHA challenges remain a considerable burden on the web,
delaying and often blocking our access to services and information delaying and often blocking our access to services and information
depending on our physical and cognitive abilities, our social depending on our physical and cognitive abilities, our social
@ -42,8 +44,16 @@ and cultural background, and the devices or networks we connect from.
The difficulty of captchas can be so out of balance, The difficulty of captchas can be so out of balance,
that sometimes they seem friendlier to bots than they are to humans. that sometimes they seem friendlier to bots than they are to humans.
The goal of this project is to improve our experience with captchas, The goal of this project is to improve our experience on the web,
by giving us easy access to solutions already utilized by automated systems. by giving us easy access to solutions utilized by automated systems.
## Client App
The client app enables you to simulate user interactions and improves
the success rate of the extension. Follow the instructions
from the extension's options to download and install the client app
on Windows, Linux and macOS, or get the app
from [this](https://github.com/dessant/buster-client#readme) repository.
## Screenshots ## Screenshots

@ -2,7 +2,6 @@
"witApiKeys": { "witApiKeys": {
"arabic": "", "arabic": "",
"bengali": "", "bengali": "",
"catalan": "",
"chinese": "", "chinese": "",
"dutch": "", "dutch": "",
"english": "", "english": "",
@ -25,7 +24,6 @@
"spanish": "", "spanish": "",
"swedish": "", "swedish": "",
"tamil": "", "tamil": "",
"telugu": "",
"thai": "", "thai": "",
"turkish": "", "turkish": "",
"urdu": "", "urdu": "",

@ -44,158 +44,148 @@
"description": "Value of the option." "description": "Value of the option."
}, },
"optionTitle_ibmSpeechApiLoc": { "optionTitle_microsoftSpeechApiLoc": {
"message": "API location", "message": "API location",
"description": "Title of the option." "description": "Title of the option."
}, },
"optionValue_ibmSpeechApiLoc_seoul": { "optionValue_microsoftSpeechApiLoc_southafricanorth": {
"message": "Seoul", "message": "South Africa North",
"description": "Value of the option." "description": "Value of the option."
}, },
"optionValue_ibmSpeechApiLoc_london": { "optionValue_microsoftSpeechApiLoc_eastasia": {
"message": "London", "message": "East Asia",
"description": "Value of the option." "description": "Value of the option."
}, },
"optionValue_ibmSpeechApiLoc_frankfurt": { "optionValue_microsoftSpeechApiLoc_southeastasia": {
"message": "Frankfurt", "message": "Southeast Asia",
"description": "Value of the option." "description": "Value of the option."
}, },
"optionValue_ibmSpeechApiLoc_dallas": { "optionValue_microsoftSpeechApiLoc_australiaeast": {
"message": "Dallas", "message": "Australia East",
"description": "Value of the option." "description": "Value of the option."
}, },
"optionValue_ibmSpeechApiLoc_washington": { "optionValue_microsoftSpeechApiLoc_centralindia": {
"message": "Washington DC", "message": "Central India",
"description": "Value of the option." "description": "Value of the option."
}, },
"optionValue_ibmSpeechApiLoc_sydney": { "optionValue_microsoftSpeechApiLoc_japaneast": {
"message": "Sydney", "message": "Japan East",
"description": "Value of the option." "description": "Value of the option."
}, },
"optionValue_ibmSpeechApiLoc_tokyo": { "optionValue_microsoftSpeechApiLoc_japanwest": {
"message": "Tokyo", "message": "Japan West",
"description": "Value of the option." "description": "Value of the option."
}, },
"optionTitle_microsoftSpeechApiLoc": { "optionValue_microsoftSpeechApiLoc_koreacentral": {
"message": "API location", "message": "Korea Central",
"description": "Title of the option."
},
"optionValue_microsoftSpeechApiLoc_eastAu": {
"message": "Australia East",
"description": "Value of the option." "description": "Value of the option."
}, },
"optionValue_microsoftSpeechApiLoc_centralCa": { "optionValue_microsoftSpeechApiLoc_canadacentral": {
"message": "Canada Central", "message": "Canada Central",
"description": "Value of the option." "description": "Value of the option."
}, },
"optionValue_microsoftSpeechApiLoc_centralUs": { "optionValue_microsoftSpeechApiLoc_northeurope": {
"message": "Central US", "message": "North Europe",
"description": "Value of the option."
},
"optionValue_microsoftSpeechApiLoc_centralFr": {
"message": "France Central",
"description": "Value of the option." "description": "Value of the option."
}, },
"optionValue_microsoftSpeechApiLoc_centralIn": { "optionValue_microsoftSpeechApiLoc_westeurope": {
"message": "Central India", "message": "West Europe",
"description": "Value of the option." "description": "Value of the option."
}, },
"optionValue_microsoftSpeechApiLoc_eastJp": { "optionValue_microsoftSpeechApiLoc_francecentral": {
"message": "Japan East", "message": "France Central",
"description": "Value of the option." "description": "Value of the option."
}, },
"optionValue_microsoftSpeechApiLoc_westJp": { "optionValue_microsoftSpeechApiLoc_germanywestcentral": {
"message": "Japan West", "message": "Germany West Central",
"description": "Value of the option." "description": "Value of the option."
}, },
"optionValue_microsoftSpeechApiLoc_southBr": { "optionValue_microsoftSpeechApiLoc_norwayeast": {
"message": "Brazil South", "message": "Norway East",
"description": "Value of the option." "description": "Value of the option."
}, },
"optionValue_microsoftSpeechApiLoc_centralKr": { "optionValue_microsoftSpeechApiLoc_switzerlandnorth": {
"message": "Korea Central", "message": "Switzerland North",
"description": "Value of the option." "description": "Value of the option."
}, },
"optionValue_microsoftSpeechApiLoc_northCh": { "optionValue_microsoftSpeechApiLoc_switzerlandwest": {
"message": "Switzerland North", "message": "Switzerland West",
"description": "Value of the option." "description": "Value of the option."
}, },
"optionValue_microsoftSpeechApiLoc_northCentralUs": { "optionValue_microsoftSpeechApiLoc_uksouth": {
"message": "North Central US", "message": "UK South",
"description": "Value of the option." "description": "Value of the option."
}, },
"optionValue_microsoftSpeechApiLoc_southCentralUs": { "optionValue_microsoftSpeechApiLoc_uaenorth": {
"message": "South Central US", "message": "UAE North",
"description": "Value of the option." "description": "Value of the option."
}, },
"optionValue_microsoftSpeechApiLoc_westCentralUs": { "optionValue_microsoftSpeechApiLoc_brazilsouth": {
"message": "West Central US", "message": "Brazil South",
"description": "Value of the option." "description": "Value of the option."
}, },
"optionValue_microsoftSpeechApiLoc_southUk": { "optionValue_microsoftSpeechApiLoc_centralus": {
"message": "UK South", "message": "Central US",
"description": "Value of the option." "description": "Value of the option."
}, },
"optionValue_microsoftSpeechApiLoc_eastUs": { "optionValue_microsoftSpeechApiLoc_eastus": {
"message": "East US", "message": "East US",
"description": "Value of the option." "description": "Value of the option."
}, },
"optionValue_microsoftSpeechApiLoc_eastUs2": { "optionValue_microsoftSpeechApiLoc_eastus2": {
"message": "East US 2", "message": "East US 2",
"description": "Value of the option." "description": "Value of the option."
}, },
"optionValue_microsoftSpeechApiLoc_westUs": { "optionValue_microsoftSpeechApiLoc_northcentralus": {
"message": "West US", "message": "North Central US",
"description": "Value of the option." "description": "Value of the option."
}, },
"optionValue_microsoftSpeechApiLoc_westUs2": { "optionValue_microsoftSpeechApiLoc_southcentralus": {
"message": "West US 2", "message": "South Central US",
"description": "Value of the option." "description": "Value of the option."
}, },
"optionValue_microsoftSpeechApiLoc_eastAsia": { "optionValue_microsoftSpeechApiLoc_westcentralus": {
"message": "East Asia", "message": "West Central US",
"description": "Value of the option." "description": "Value of the option."
}, },
"optionValue_microsoftSpeechApiLoc_southeastAsia": { "optionValue_microsoftSpeechApiLoc_westus": {
"message": "Southeast Asia", "message": "West US",
"description": "Value of the option." "description": "Value of the option."
}, },
"optionValue_microsoftSpeechApiLoc_westEu": { "optionValue_microsoftSpeechApiLoc_westus2": {
"message": "West Europe", "message": "West US 2",
"description": "Value of the option." "description": "Value of the option."
}, },
"optionValue_microsoftSpeechApiLoc_northEu": { "optionValue_microsoftSpeechApiLoc_westus3": {
"message": "North Europe", "message": "West US 3",
"description": "Value of the option." "description": "Value of the option."
}, },
@ -279,11 +269,6 @@
"description": "Value of the option." "description": "Value of the option."
}, },
"optionValue_witSpeechApiLang_catalan": {
"message": "Catalan",
"description": "Value of the option."
},
"optionValue_witSpeechApiLang_chinese": { "optionValue_witSpeechApiLang_chinese": {
"message": "Chinese", "message": "Chinese",
"description": "Value of the option." "description": "Value of the option."
@ -394,11 +379,6 @@
"description": "Value of the option." "description": "Value of the option."
}, },
"optionValue_witSpeechApiLang_telugu": {
"message": "Telugu",
"description": "Value of the option."
},
"optionValue_witSpeechApiLang_thai": { "optionValue_witSpeechApiLang_thai": {
"message": "Thai", "message": "Thai",
"description": "Value of the option." "description": "Value of the option."
@ -419,6 +399,11 @@
"description": "Value of the option." "description": "Value of the option."
}, },
"inputLabel_apiUrl": {
"message": "API endpoint",
"description": "Label of the input."
},
"inputLabel_apiKey": { "inputLabel_apiKey": {
"message": "API key", "message": "API key",
"description": "Label of the input." "description": "Label of the input."
@ -576,6 +561,16 @@
"description": "Error message." "description": "Error message."
}, },
"error_captchaNotSolvedWitai": {
"message": "Wit.ai could not detect any speech. Try a new challenge, or switch to a more reliable service from the extension's options, such as IBM Watson.",
"description": "Error message."
},
"error_missingApiUrl": {
"message": "API endpoint missing. Visit the extension's options to configure the service.",
"description": "Error message."
},
"error_missingApiKey": { "error_missingApiKey": {
"message": "API key missing. Visit the extension's options to configure the service.", "message": "API key missing. Visit the extension's options to configure the service.",
"description": "Error message." "description": "Error message."

@ -27,9 +27,7 @@ import {
captchaGoogleSpeechApiLangCodes, captchaGoogleSpeechApiLangCodes,
captchaIbmSpeechApiLangCodes, captchaIbmSpeechApiLangCodes,
captchaMicrosoftSpeechApiLangCodes, captchaMicrosoftSpeechApiLangCodes,
captchaWitSpeechApiLangCodes, captchaWitSpeechApiLangCodes
ibmSpeechApiUrls,
microsoftSpeechApiUrls
} from 'utils/data'; } from 'utils/data';
import {targetEnv, clientAppVersion} from 'utils/config'; import {targetEnv, clientAppVersion} from 'utils/config';
@ -298,8 +296,7 @@ async function getWitSpeechApiKey(speechService, language) {
async function getWitSpeechApiResult(apiKey, audioContent) { async function getWitSpeechApiResult(apiKey, audioContent) {
const result = {}; const result = {};
const rsp = await fetch('https://api.wit.ai/speech?v=20200513', { const rsp = await fetch('https://api.wit.ai/speech?v=20221114', {
referrer: '',
mode: 'cors', mode: 'cors',
method: 'POST', method: 'POST',
headers: { headers: {
@ -316,7 +313,7 @@ async function getWitSpeechApiResult(apiKey, audioContent) {
throw new Error(`API response: ${rsp.status}, ${await rsp.text()}`); throw new Error(`API response: ${rsp.status}, ${await rsp.text()}`);
} }
} else { } else {
const data = (await rsp.json()).text; const data = JSON.parse((await rsp.text()).split('\r\n').at(-1)).text;
if (data) { if (data) {
result.text = data.trim(); result.text = data.trim();
} }
@ -325,15 +322,56 @@ async function getWitSpeechApiResult(apiKey, audioContent) {
return result; return result;
} }
async function getIbmSpeechApiResult(apiUrl, apiKey, audioContent, language) { async function getGoogleSpeechApiResult(
apiKey,
audioContent,
language,
detectAltLanguages
) {
const data = {
audio: {
content: arrayBufferToBase64(audioContent)
},
config: {
encoding: 'LINEAR16',
languageCode: language,
model: 'video',
sampleRateHertz: 16000
}
};
if (!['en-US', 'en-GB'].includes(language) && detectAltLanguages) {
data.config.model = 'default';
data.config.alternativeLanguageCodes = ['en-US'];
}
const rsp = await fetch(
`https://speech.googleapis.com/v1p1beta1/speech:recognize?key=${apiKey}`,
{
mode: 'cors',
method: 'POST',
body: JSON.stringify(data)
}
);
if (rsp.status !== 200) {
throw new Error(`API response: ${rsp.status}, ${await rsp.text()}`);
}
const results = (await rsp.json()).results;
if (results) {
return results[0].alternatives[0].transcript.trim();
}
}
async function getIbmSpeechApiResult(apiUrl, apiKey, audioContent, model) {
const rsp = await fetch( const rsp = await fetch(
`${apiUrl}?model=${language}&profanity_filter=false`, `${apiUrl}/v1/recognize?model=${model}&profanity_filter=false`,
{ {
referrer: '',
mode: 'cors', mode: 'cors',
method: 'POST', method: 'POST',
headers: { headers: {
Authorization: 'Basic ' + window.btoa('apiKey:' + apiKey), Authorization: 'Basic ' + window.btoa('apikey:' + apiKey),
'X-Watson-Learning-Opt-Out': 'true' 'X-Watson-Learning-Opt-Out': 'true'
}, },
body: new Blob([audioContent], {type: 'audio/wav'}) body: new Blob([audioContent], {type: 'audio/wav'})
@ -351,15 +389,14 @@ async function getIbmSpeechApiResult(apiUrl, apiKey, audioContent, language) {
} }
async function getMicrosoftSpeechApiResult( async function getMicrosoftSpeechApiResult(
apiUrl, apiLocation,
apiKey, apiKey,
audioContent, audioContent,
language language
) { ) {
const rsp = await fetch( const rsp = await fetch(
`${apiUrl}?language=${language}&format=detailed&profanity=raw`, `https://${apiLocation}.stt.speech.microsoft.com/speech/recognition/conversation/cognitiveservices/v1?language=${language}&format=detailed&profanity=raw`,
{ {
referrer: '',
mode: 'cors', mode: 'cors',
method: 'POST', method: 'POST',
headers: { headers: {
@ -383,7 +420,7 @@ async function getMicrosoftSpeechApiResult(
async function transcribeAudio(audioUrl, lang) { async function transcribeAudio(audioUrl, lang) {
let solution; let solution;
const audioRsp = await fetch(audioUrl, {referrer: ''}); const audioRsp = await fetch(audioUrl);
const audioContent = await prepareAudio(await audioRsp.arrayBuffer()); const audioContent = await prepareAudio(await audioRsp.arrayBuffer());
const {speechService, tryEnglishSpeechModel} = await storage.get([ const {speechService, tryEnglishSpeechModel} = await storage.get([
@ -395,6 +432,7 @@ async function transcribeAudio(audioUrl, lang) {
const language = captchaWitSpeechApiLangCodes[lang] || 'english'; const language = captchaWitSpeechApiLangCodes[lang] || 'english';
const apiKey = await getWitSpeechApiKey(speechService, language); const apiKey = await getWitSpeechApiKey(speechService, language);
if (!apiKey) { if (!apiKey) {
showNotification({messageId: 'error_missingApiKey'}); showNotification({messageId: 'error_missingApiKey'});
return; return;
@ -412,10 +450,12 @@ async function transcribeAudio(audioUrl, lang) {
if (!solution && language !== 'english' && tryEnglishSpeechModel) { if (!solution && language !== 'english' && tryEnglishSpeechModel) {
const apiKey = await getWitSpeechApiKey(speechService, 'english'); const apiKey = await getWitSpeechApiKey(speechService, 'english');
if (!apiKey) { if (!apiKey) {
showNotification({messageId: 'error_missingApiKey'}); showNotification({messageId: 'error_missingApiKey'});
return; return;
} }
const result = await getWitSpeechApiResult(apiKey, audioContent); const result = await getWitSpeechApiResult(apiKey, audioContent);
if (result.errorId) { if (result.errorId) {
showNotification({ showNotification({
@ -430,86 +470,62 @@ async function transcribeAudio(audioUrl, lang) {
const {googleSpeechApiKey: apiKey} = await storage.get( const {googleSpeechApiKey: apiKey} = await storage.get(
'googleSpeechApiKey' 'googleSpeechApiKey'
); );
if (!apiKey) { if (!apiKey) {
showNotification({messageId: 'error_missingApiKey'}); showNotification({messageId: 'error_missingApiKey'});
return; return;
} }
const apiUrl = `https://speech.googleapis.com/v1p1beta1/speech:recognize?key=${apiKey}`;
const language = captchaGoogleSpeechApiLangCodes[lang] || 'en-US'; const language = captchaGoogleSpeechApiLangCodes[lang] || 'en-US';
const data = { solution = await getGoogleSpeechApiResult(
audio: { apiKey,
content: arrayBufferToBase64(audioContent) audioContent,
}, language,
config: { tryEnglishSpeechModel
encoding: 'LINEAR16', );
languageCode: language, } else if (speechService === 'ibmSpeechApi') {
model: 'video', const {ibmSpeechApiUrl: apiUrl, ibmSpeechApiKey: apiKey} =
sampleRateHertz: 16000 await storage.get(['ibmSpeechApiUrl', 'ibmSpeechApiKey']);
}
};
if (!['en-US', 'en-GB'].includes(language) && tryEnglishSpeechModel) {
data.config.model = 'default';
data.config.alternativeLanguageCodes = ['en-US'];
}
const rsp = await fetch(apiUrl, {
referrer: '',
mode: 'cors',
method: 'POST',
body: JSON.stringify(data)
});
if (rsp.status !== 200) {
throw new Error(`API response: ${rsp.status}, ${await rsp.text()}`);
}
const results = (await rsp.json()).results; if (!apiUrl) {
if (results) { showNotification({messageId: 'error_missingApiUrl'});
solution = results[0].alternatives[0].transcript.trim(); return;
} }
} else if (speechService === 'ibmSpeechApi') {
const {ibmSpeechApiLoc: apiLoc, ibmSpeechApiKey: apiKey} =
await storage.get(['ibmSpeechApiLoc', 'ibmSpeechApiKey']);
if (!apiKey) { if (!apiKey) {
showNotification({messageId: 'error_missingApiKey'}); showNotification({messageId: 'error_missingApiKey'});
return; return;
} }
const apiUrl = ibmSpeechApiUrls[apiLoc];
const language =
captchaIbmSpeechApiLangCodes[lang] || 'en-US_BroadbandModel';
solution = await getIbmSpeechApiResult( const model = captchaIbmSpeechApiLangCodes[lang] || 'en-US_Multimedia';
apiUrl,
apiKey, solution = await getIbmSpeechApiResult(apiUrl, apiKey, audioContent, model);
audioContent,
language
);
if ( if (
!solution && !solution &&
!['en-US_BroadbandModel', 'en-GB_BroadbandModel'].includes(language) && !['en-US_Multimedia', 'en-GB_Multimedia'].includes(model) &&
tryEnglishSpeechModel tryEnglishSpeechModel
) { ) {
solution = await getIbmSpeechApiResult( solution = await getIbmSpeechApiResult(
apiUrl, apiUrl,
apiKey, apiKey,
audioContent, audioContent,
'en-US_BroadbandModel' 'en-US_Multimedia'
); );
} }
} else if (speechService === 'microsoftSpeechApi') { } else if (speechService === 'microsoftSpeechApi') {
const {microsoftSpeechApiLoc: apiLoc, microsoftSpeechApiKey: apiKey} = const {microsoftSpeechApiLoc: apiLocaction, microsoftSpeechApiKey: apiKey} =
await storage.get(['microsoftSpeechApiLoc', 'microsoftSpeechApiKey']); await storage.get(['microsoftSpeechApiLoc', 'microsoftSpeechApiKey']);
if (!apiKey) { if (!apiKey) {
showNotification({messageId: 'error_missingApiKey'}); showNotification({messageId: 'error_missingApiKey'});
return; return;
} }
const apiUrl = microsoftSpeechApiUrls[apiLoc];
const language = captchaMicrosoftSpeechApiLangCodes[lang] || 'en-US'; const language = captchaMicrosoftSpeechApiLangCodes[lang] || 'en-US';
solution = await getMicrosoftSpeechApiResult( solution = await getMicrosoftSpeechApiResult(
apiUrl, apiLocaction,
apiKey, apiKey,
audioContent, audioContent,
language language
@ -520,7 +536,7 @@ async function transcribeAudio(audioUrl, lang) {
tryEnglishSpeechModel tryEnglishSpeechModel
) { ) {
solution = await getMicrosoftSpeechApiResult( solution = await getMicrosoftSpeechApiResult(
apiUrl, apiLocaction,
apiKey, apiKey,
audioContent, audioContent,
'en-US' 'en-US'
@ -529,7 +545,14 @@ async function transcribeAudio(audioUrl, lang) {
} }
if (!solution) { if (!solution) {
showNotification({messageId: 'error_captchaNotSolved', timeout: 6000}); if (['witSpeechApiDemo', 'witSpeechApi'].includes(speechService)) {
showNotification({
messageId: 'error_captchaNotSolvedWitai',
timeout: 60000
});
} else {
showNotification({messageId: 'error_captchaNotSolved', timeout: 6000});
}
} else { } else {
return solution; return solution;
} }

@ -36,15 +36,14 @@
</a> </a>
<div <div
class="option select" class="option text-field"
v-if="options.speechService === 'ibmSpeechApi'" v-if="options.speechService === 'ibmSpeechApi'"
> >
<vn-select <vn-text-field
:label="getText('optionTitle_ibmSpeechApiLoc')" v-model.trim="options.ibmSpeechApiUrl"
:items="listItems.ibmSpeechApiLoc" :label="getText('inputLabel_apiUrl')"
v-model="options.ibmSpeechApiLoc"
> >
</vn-select> </vn-text-field>
</div> </div>
<div <div
class="option text-field" class="option text-field"
@ -271,7 +270,8 @@ import {enableContributions, clientAppVersion} from 'utils/config';
import { import {
optionKeys, optionKeys,
clientAppPlatforms, clientAppPlatforms,
captchaWitSpeechApiLangCodes captchaWitSpeechApiLangCodes,
microsoftSpeechApiRegions
} from 'utils/data'; } from 'utils/data';
export default { export default {
@ -301,46 +301,7 @@ export default {
{scope: 'optionValue_speechService'} {scope: 'optionValue_speechService'}
), ),
...getListItems( ...getListItems(
{ {microsoftSpeechApiLoc: microsoftSpeechApiRegions},
ibmSpeechApiLoc: [
'seoul',
'london',
'frankfurt',
'dallas',
'washington',
'sydney',
'tokyo'
]
},
{scope: 'optionValue_ibmSpeechApiLoc'}
),
...getListItems(
{
microsoftSpeechApiLoc: [
'eastAu',
'centralCa',
'centralUs',
'centralFr',
'centralIn',
'eastJp',
'westJp',
'southBr',
'centralKr',
'northCh',
'northCentralUs',
'southCentralUs',
'westCentralUs',
'southUk',
'eastUs',
'eastUs2',
'westUs',
'westUs2',
'eastAsia',
'southeastAsia',
'westEu',
'northEu'
]
},
{scope: 'optionValue_microsoftSpeechApiLoc'} {scope: 'optionValue_microsoftSpeechApiLoc'}
), ),
...getListItems( ...getListItems(
@ -372,7 +333,7 @@ export default {
options: { options: {
speechService: '', speechService: '',
googleSpeechApiKey: '', googleSpeechApiKey: '',
ibmSpeechApiLoc: '', ibmSpeechApiUrl: '',
ibmSpeechApiKey: '', ibmSpeechApiKey: '',
microsoftSpeechApiLoc: '', microsoftSpeechApiLoc: '',
microsoftSpeechApiKey: '', microsoftSpeechApiKey: '',

@ -135,7 +135,6 @@ export default {
data.append('session', this.session); data.append('session', this.session);
await fetch(`${this.apiUrl}/setup/close`, { await fetch(`${this.apiUrl}/setup/close`, {
referrer: '',
mode: 'cors', mode: 'cors',
method: 'POST', method: 'POST',
body: data body: data
@ -150,7 +149,6 @@ export default {
data.append('targetEnv', this.$env.targetEnv); data.append('targetEnv', this.$env.targetEnv);
const rsp = await fetch(`${this.apiUrl}/setup/location`, { const rsp = await fetch(`${this.apiUrl}/setup/location`, {
referrer: '',
mode: 'cors', mode: 'cors',
method: 'POST', method: 'POST',
body: data body: data
@ -176,7 +174,6 @@ export default {
data.append('extension', this.getExtensionId()); data.append('extension', this.getExtensionId());
const rsp = await fetch(`${this.apiUrl}/setup/install`, { const rsp = await fetch(`${this.apiUrl}/setup/install`, {
referrer: '',
mode: 'cors', mode: 'cors',
method: 'POST', method: 'POST',
body: data body: data

@ -10,7 +10,8 @@
"X3djS8vZC", "X3djS8vZC",
"DlgF14Chrh", "DlgF14Chrh",
"Lj3MYlSr4L", "Lj3MYlSr4L",
"20221211221603_add_theme_support" "20221211221603_add_theme_support",
"20221214080901_update_services"
], ],
"sync": [] "sync": []
} }

@ -0,0 +1,24 @@
const message = 'Update services';
const revision = '20221214080901_update_services';
async function upgrade() {
const changes = {};
const {witSpeechApiKeys} = await browser.storage.local.get(
'witSpeechApiKeys'
);
delete witSpeechApiKeys['catalan'];
delete witSpeechApiKeys['telugu'];
changes.witSpeechApiKeys = witSpeechApiKeys;
await browser.storage.local.remove('ibmSpeechApiLoc');
changes.ibmSpeechApiUrl = '';
changes.microsoftSpeechApiLoc = 'eastus';
changes.storageVersion = revision;
return browser.storage.local.set(changes);
}
export {message, revision, upgrade};

@ -1,7 +1,7 @@
const optionKeys = [ const optionKeys = [
'speechService', 'speechService',
'googleSpeechApiKey', 'googleSpeechApiKey',
'ibmSpeechApiLoc', 'ibmSpeechApiUrl',
'ibmSpeechApiKey', 'ibmSpeechApiKey',
'microsoftSpeechApiLoc', 'microsoftSpeechApiLoc',
'microsoftSpeechApiKey', 'microsoftSpeechApiKey',
@ -26,7 +26,7 @@ const recaptchaChallengeUrlRx =
/^https:\/\/(?:www\.)?(?:google\.com|recaptcha\.net)\/recaptcha\/(?:api2|enterprise)\/bframe.*/; /^https:\/\/(?:www\.)?(?:google\.com|recaptcha\.net)\/recaptcha\/(?:api2|enterprise)\/bframe.*/;
// https://developers.google.com/recaptcha/docs/language // https://developers.google.com/recaptcha/docs/language
// https://cloud.google.com/speech-to-text/docs/languages // https://cloud.google.com/speech-to-text/docs/speech-to-text-supported-languages
const captchaGoogleSpeechApiLangCodes = { const captchaGoogleSpeechApiLangCodes = {
ar: 'ar-SA', // Arabic ar: 'ar-SA', // Arabic
af: 'af-ZA', // Afrikaans af: 'af-ZA', // Afrikaans
@ -46,7 +46,7 @@ const captchaGoogleSpeechApiLangCodes = {
nl: 'nl-NL', // Dutch nl: 'nl-NL', // Dutch
'en-GB': 'en-GB', // English (UK) 'en-GB': 'en-GB', // English (UK)
en: 'en-US', // English (US) en: 'en-US', // English (US)
et: '', // Estonian et: 'et-EE', // Estonian
fil: 'fil-PH', // Filipino fil: 'fil-PH', // Filipino
fi: 'fi-FI', // Finnish fi: 'fi-FI', // Finnish
fr: 'fr-FR', // French fr: 'fr-FR', // French
@ -73,7 +73,7 @@ const captchaGoogleSpeechApiLangCodes = {
ms: 'ms-MY', // Malay ms: 'ms-MY', // Malay
ml: 'ml-IN', // Malayalam ml: 'ml-IN', // Malayalam
mr: 'mr-IN', // Marathi mr: 'mr-IN', // Marathi
mn: '', // Mongolian mn: 'mn-MN', // Mongolian
no: 'nb-NO', // Norwegian no: 'nb-NO', // Norwegian
fa: 'fa-IR', // Persian fa: 'fa-IR', // Persian
pl: 'pl-PL', // Polish pl: 'pl-PL', // Polish
@ -100,9 +100,9 @@ const captchaGoogleSpeechApiLangCodes = {
zu: 'zu-ZA' // Zulu zu: 'zu-ZA' // Zulu
}; };
// https://cloud.ibm.com/docs/services/speech-to-text?topic=speech-to-text-models#models // https://cloud.ibm.com/docs/speech-to-text?topic=speech-to-text-models-ng#models-ng-supported
const captchaIbmSpeechApiLangCodes = { const captchaIbmSpeechApiLangCodes = {
ar: 'ar-AR_BroadbandModel', // Arabic ar: 'ar-MS_Telephony', // Arabic
af: '', // Afrikaans af: '', // Afrikaans
am: '', // Amharic am: '', // Amharic
hy: '', // Armenian hy: '', // Armenian
@ -112,35 +112,35 @@ const captchaIbmSpeechApiLangCodes = {
bg: '', // Bulgarian bg: '', // Bulgarian
ca: '', // Catalan ca: '', // Catalan
'zh-HK': '', // Chinese (Hong Kong) 'zh-HK': '', // Chinese (Hong Kong)
'zh-CN': 'zh-CN_BroadbandModel', // Chinese (Simplified) 'zh-CN': 'zh-CN_Telephony', // Chinese (Simplified)
'zh-TW': 'zh-CN_BroadbandModel', // Chinese (Traditional) 'zh-TW': 'zh-CN_Telephony', // Chinese (Traditional)
hr: '', // Croatian hr: '', // Croatian
cs: '', // Czech cs: 'cs-CZ_Telephony', // Czech
da: '', // Danish da: '', // Danish
nl: 'nl-NL_BroadbandModel', // Dutch nl: 'nl-NL_Multimedia', // Dutch
'en-GB': 'en-GB_BroadbandModel', // English (UK) 'en-GB': 'en-GB_Multimedia', // English (UK)
en: 'en-US_BroadbandModel', // English (US) en: 'en-US_Multimedia', // English (US)
et: '', // Estonian et: '', // Estonian
fil: '', // Filipino fil: '', // Filipino
fi: '', // Finnish fi: '', // Finnish
fr: 'fr-FR_BroadbandModel', // French fr: 'fr-FR_Multimedia', // French
'fr-CA': 'fr-FR_BroadbandModel', // French (Canadian) 'fr-CA': 'fr-CA_Multimedia', // French (Canadian)
gl: '', // Galician gl: '', // Galician
ka: '', // Georgian ka: '', // Georgian
de: 'de-DE_BroadbandModel', // German de: 'de-DE_Multimedia', // German
'de-AT': 'de-DE_BroadbandModel', // German (Austria) 'de-AT': 'de-DE_Multimedia', // German (Austria)
'de-CH': 'de-DE_BroadbandModel', // German (Switzerland) 'de-CH': 'de-DE_Multimedia', // German (Switzerland)
el: '', // Greek el: '', // Greek
gu: '', // Gujarati gu: '', // Gujarati
iw: '', // Hebrew iw: '', // Hebrew
hi: '', // Hindi hi: 'hi-IN_Telephony', // Hindi
hu: '', // Hungarian hu: '', // Hungarian
is: '', // Icelandic is: '', // Icelandic
id: '', // Indonesian id: '', // Indonesian
it: 'it-IT_BroadbandModel', // Italian it: 'it-IT_Multimedia', // Italian
ja: 'ja-JP_BroadbandModel', // Japanese ja: 'ja-JP_Multimedia', // Japanese
kn: '', // Kannada kn: '', // Kannada
ko: 'ko-KR_BroadbandModel', // Korean ko: 'ko-KR_Multimedia', // Korean
lo: '', // Laothian lo: '', // Laothian
lv: '', // Latvian lv: '', // Latvian
lt: '', // Lithuanian lt: '', // Lithuanian
@ -151,19 +151,19 @@ const captchaIbmSpeechApiLangCodes = {
no: '', // Norwegian no: '', // Norwegian
fa: '', // Persian fa: '', // Persian
pl: '', // Polish pl: '', // Polish
pt: 'pt-BR_BroadbandModel', // Portuguese pt: 'pt-BR_Multimedia', // Portuguese
'pt-BR': 'pt-BR_BroadbandModel', // Portuguese (Brazil) 'pt-BR': 'pt-BR_Multimedia', // Portuguese (Brazil)
'pt-PT': 'pt-BR_BroadbandModel', // Portuguese (Portugal) 'pt-PT': 'pt-BR_Multimedia', // Portuguese (Portugal)
ro: '', // Romanian ro: '', // Romanian
ru: '', // Russian ru: '', // Russian
sr: '', // Serbian sr: '', // Serbian
si: '', // Sinhalese si: '', // Sinhalese
sk: '', // Slovak sk: '', // Slovak
sl: '', // Slovenian sl: '', // Slovenian
es: 'es-ES_BroadbandModel', // Spanish es: 'es-ES_Multimedia', // Spanish
'es-419': 'es-ES_BroadbandModel', // Spanish (Latin America) 'es-419': 'es-LA_Telephony', // Spanish (Latin America)
sw: '', // Swahili sw: '', // Swahili
sv: '', // Swedish sv: 'sv-SE_Telephony', // Swedish
ta: '', // Tamil ta: '', // Tamil
te: '', // Telugu te: '', // Telugu
th: '', // Thai th: '', // Thai
@ -174,78 +174,78 @@ const captchaIbmSpeechApiLangCodes = {
zu: '' // Zulu zu: '' // Zulu
}; };
// https://docs.microsoft.com/en-us/azure/cognitive-services/speech-service/language-support#speech-to-text // https://learn.microsoft.com/en-us/azure/cognitive-services/speech-service/language-support?tabs=stt-tts
const captchaMicrosoftSpeechApiLangCodes = { const captchaMicrosoftSpeechApiLangCodes = {
ar: 'ar-EG', // Arabic ar: 'ar-EG', // Arabic
af: '', // Afrikaans af: 'af-ZA', // Afrikaans
am: '', // Amharic am: 'am-ET', // Amharic
hy: '', // Armenian hy: 'hy-AM', // Armenian
az: '', // Azerbaijani az: 'az-AZ', // Azerbaijani
eu: '', // Basque eu: 'eu-ES', // Basque
bn: '', // Bengali bn: 'bn-IN', // Bengali
bg: '', // Bulgarian bg: 'bg-BG', // Bulgarian
ca: 'ca-ES', // Catalan ca: 'ca-ES', // Catalan
'zh-HK': 'zh-HK', // Chinese (Hong Kong) 'zh-HK': 'zh-HK', // Chinese (Hong Kong)
'zh-CN': 'zh-CN', // Chinese (Simplified) 'zh-CN': 'zh-CN', // Chinese (Simplified)
'zh-TW': 'zh-TW', // Chinese (Traditional) 'zh-TW': 'zh-TW', // Chinese (Traditional)
hr: '', // Croatian hr: 'hr-HR', // Croatian
cs: '', // Czech cs: 'cs-CZ', // Czech
da: 'da-DK', // Danish da: 'da-DK', // Danish
nl: 'nl-NL', // Dutch nl: 'nl-NL', // Dutch
'en-GB': 'en-GB', // English (UK) 'en-GB': 'en-GB', // English (UK)
en: 'en-US', // English (US) en: 'en-US', // English (US)
et: '', // Estonian et: 'et-EE', // Estonian
fil: '', // Filipino fil: 'fil-PH', // Filipino
fi: 'fi-FI', // Finnish fi: 'fi-FI', // Finnish
fr: 'fr-FR', // French fr: 'fr-FR', // French
'fr-CA': 'fr-CA', // French (Canadian) 'fr-CA': 'fr-CA', // French (Canadian)
gl: '', // Galician gl: 'gl-ES', // Galician
ka: '', // Georgian ka: 'ka-GE', // Georgian
de: 'de-DE', // German de: 'de-DE', // German
'de-AT': 'de-DE', // German (Austria) 'de-AT': 'de-AT', // German (Austria)
'de-CH': 'de-DE', // German (Switzerland) 'de-CH': 'de-CH', // German (Switzerland)
el: '', // Greek el: 'el-GR', // Greek
gu: 'gu-IN', // Gujarati gu: 'gu-IN', // Gujarati
iw: '', // Hebrew iw: 'he-IL', // Hebrew
hi: 'hi-IN', // Hindi hi: 'hi-IN', // Hindi
hu: '', // Hungarian hu: 'hu-HU', // Hungarian
is: '', // Icelandic is: 'is-IS', // Icelandic
id: '', // Indonesian id: 'id-ID', // Indonesian
it: 'it-IT', // Italian it: 'it-IT', // Italian
ja: 'ja-JP', // Japanese ja: 'ja-JP', // Japanese
kn: '', // Kannada kn: 'kn-IN', // Kannada
ko: 'ko-KR', // Korean ko: 'ko-KR', // Korean
lo: '', // Laothian lo: 'lo-LA', // Laothian
lv: '', // Latvian lv: 'lv-LV', // Latvian
lt: '', // Lithuanian lt: 'lt-LT', // Lithuanian
ms: '', // Malay ms: 'ms-MY', // Malay
ml: '', // Malayalam ml: 'ml-IN', // Malayalam
mr: 'mr-IN', // Marathi mr: 'mr-IN', // Marathi
mn: '', // Mongolian mn: 'mn-MN', // Mongolian
no: 'nb-NO', // Norwegian no: 'nb-NO', // Norwegian
fa: '', // Persian fa: 'fa-IR', // Persian
pl: 'pl-PL', // Polish pl: 'pl-PL', // Polish
pt: 'pt-PT', // Portuguese pt: 'pt-PT', // Portuguese
'pt-BR': 'pt-BR', // Portuguese (Brazil) 'pt-BR': 'pt-BR', // Portuguese (Brazil)
'pt-PT': 'pt-PT', // Portuguese (Portugal) 'pt-PT': 'pt-PT', // Portuguese (Portugal)
ro: '', // Romanian ro: 'ro-RO', // Romanian
ru: 'ru-RU', // Russian ru: 'ru-RU', // Russian
sr: '', // Serbian sr: 'sr-RS', // Serbian
si: '', // Sinhalese si: 'si-LK', // Sinhalese
sk: '', // Slovak sk: 'sk-SK', // Slovak
sl: '', // Slovenian sl: 'sl-SI', // Slovenian
es: 'es-ES', // Spanish es: 'es-ES', // Spanish
'es-419': 'es-MX', // Spanish (Latin America) 'es-419': 'es-MX', // Spanish (Latin America)
sw: '', // Swahili sw: 'sw-TZ', // Swahili
sv: 'sv-SE', // Swedish sv: 'sv-SE', // Swedish
ta: 'ta-IN', // Tamil ta: 'ta-IN', // Tamil
te: 'te-IN', // Telugu te: 'te-IN', // Telugu
th: 'th-TH', // Thai th: 'th-TH', // Thai
tr: 'tr-TR', // Turkish tr: 'tr-TR', // Turkish
uk: '', // Ukrainian uk: 'uk-UA', // Ukrainian
ur: '', // Urdu ur: '', // Urdu
vi: '', // Vietnamese vi: 'vi-VN', // Vietnamese
zu: '' // Zulu zu: 'zu-ZA' // Zulu
}; };
// https://wit.ai/faq // https://wit.ai/faq
@ -258,7 +258,7 @@ const captchaWitSpeechApiLangCodes = {
eu: '', // Basque eu: '', // Basque
bn: 'bengali', // Bengali bn: 'bengali', // Bengali
bg: '', // Bulgarian bg: '', // Bulgarian
ca: 'catalan', // Catalan ca: '', // Catalan
'zh-HK': '', // Chinese (Hong Kong) 'zh-HK': '', // Chinese (Hong Kong)
'zh-CN': 'chinese', // Chinese (Simplified) 'zh-CN': 'chinese', // Chinese (Simplified)
'zh-TW': 'chinese', // Chinese (Traditional) 'zh-TW': 'chinese', // Chinese (Traditional)
@ -313,7 +313,7 @@ const captchaWitSpeechApiLangCodes = {
sw: '', // Swahili sw: '', // Swahili
sv: 'swedish', // Swedish sv: 'swedish', // Swedish
ta: 'tamil', // Tamil ta: 'tamil', // Tamil
te: 'telugu', // Telugu te: '', // Telugu
th: 'thai', // Thai th: 'thai', // Thai
tr: 'turkish', // Turkish tr: 'turkish', // Turkish
uk: '', // Ukrainian uk: '', // Ukrainian
@ -322,67 +322,37 @@ const captchaWitSpeechApiLangCodes = {
zu: '' // Zulu zu: '' // Zulu
}; };
// https://cloud.ibm.com/apidocs/speech-to-text#service-endpoint // https://learn.microsoft.com/en-us/azure/cognitive-services/speech-service/regions#speech-service
const ibmSpeechApiUrls = { const microsoftSpeechApiRegions = [
seoul: 'https://api.kr-seo.speech-to-text.watson.cloud.ibm.com/v1/recognize', 'southafricanorth',
london: 'https://api.eu-gb.speech-to-text.watson.cloud.ibm.com/v1/recognize', 'eastasia',
frankfurt: 'southeastasia',
'https://api.eu-de.speech-to-text.watson.cloud.ibm.com/v1/recognize', 'australiaeast',
dallas: 'centralindia',
'https://api.us-south.speech-to-text.watson.cloud.ibm.com/v1/recognize', 'japaneast',
washington: 'japanwest',
'https://api.us-east.speech-to-text.watson.cloud.ibm.com/v1/recognize', 'koreacentral',
sydney: 'https://api.au-syd.speech-to-text.watson.cloud.ibm.com/v1/recognize', 'canadacentral',
tokyo: 'https://api.jp-tok.speech-to-text.watson.cloud.ibm.com/v1/recognize' 'northeurope',
}; 'westeurope',
'francecentral',
// https://docs.microsoft.com/en-us/azure/cognitive-services/speech-service/rest-speech-to-text#regions-and-endpoints 'germanywestcentral',
const microsoftSpeechApiUrls = { 'norwayeast',
eastAu: 'switzerlandnorth',
'https://australiaeast.stt.speech.microsoft.com/speech/recognition/conversation/cognitiveservices/v1', 'switzerlandwest',
centralCa: 'uksouth',
'https://canadacentral.stt.speech.microsoft.com/speech/recognition/conversation/cognitiveservices/v1', 'uaenorth',
centralUs: 'brazilsouth',
'https://centralus.stt.speech.microsoft.com/speech/recognition/conversation/cognitiveservices/v1', 'centralus',
centralFr: 'eastus',
'https://francecentral.stt.speech.microsoft.com/speech/recognition/conversation/cognitiveservices/v1', 'eastus2',
centralIn: 'northcentralus',
'https://centralindia.stt.speech.microsoft.com/speech/recognition/conversation/cognitiveservices/v1', 'southcentralus',
eastJp: 'westcentralus',
'https://japaneast.stt.speech.microsoft.com/speech/recognition/conversation/cognitiveservices/v1', 'westus',
westJp: 'westus2',
'https://japanwest.stt.speech.microsoft.com/speech/recognition/conversation/cognitiveservices/v1', 'westus3'
southBr: ];
'https://brazilsouth.stt.speech.microsoft.com/speech/recognition/conversation/cognitiveservices/v1',
centralKr:
'https://koreacentral.stt.speech.microsoft.com/speech/recognition/conversation/cognitiveservices/v1',
northCh:
'https://switzerlandnorth.stt.speech.microsoft.com/speech/recognition/conversation/cognitiveservices/v1',
northCentralUs:
'https://northcentralus.stt.speech.microsoft.com/speech/recognition/conversation/cognitiveservices/v1',
southCentralUs:
'https://southcentralus.stt.speech.microsoft.com/speech/recognition/conversation/cognitiveservices/v1',
westCentralUs:
'https://westcentralus.stt.speech.microsoft.com/speech/recognition/conversation/cognitiveservices/v1',
southUk:
'https://uksouth.stt.speech.microsoft.com/speech/recognition/conversation/cognitiveservices/v1',
eastUs:
'https://eastus.stt.speech.microsoft.com/speech/recognition/conversation/cognitiveservices/v1',
eastUs2:
'https://eastus.stt.speech.microsoft.com/speech/recognition/conversation/cognitiveservices/v1',
westUs:
'https://westus.stt.speech.microsoft.com/speech/recognition/conversation/cognitiveservices/v1',
westUs2:
'https://westus2.stt.speech.microsoft.com/speech/recognition/conversation/cognitiveservices/v1',
eastAsia:
'https://eastasia.stt.speech.microsoft.com/speech/recognition/conversation/cognitiveservices/v1',
southeastAsia:
'https://southeastasia.stt.speech.microsoft.com/speech/recognition/conversation/cognitiveservices/v1',
westEu:
'https://westeurope.stt.speech.microsoft.com/speech/recognition/conversation/cognitiveservices/v1',
northEu:
'https://northeurope.stt.speech.microsoft.com/speech/recognition/conversation/cognitiveservices/v1'
};
export { export {
optionKeys, optionKeys,
@ -392,6 +362,5 @@ export {
captchaIbmSpeechApiLangCodes, captchaIbmSpeechApiLangCodes,
captchaMicrosoftSpeechApiLangCodes, captchaMicrosoftSpeechApiLangCodes,
captchaWitSpeechApiLangCodes, captchaWitSpeechApiLangCodes,
ibmSpeechApiUrls, microsoftSpeechApiRegions
microsoftSpeechApiUrls
}; };

Loading…
Cancel
Save