AudioUriBuilder simplification (#799)

* Rename variables to disambiguate

* Update handler argument convention

* Update getUri argument convention

* Change _getAudioUri argument convention

* Change getDefinitionAudio argument convention

* Add api.getDefinitionAudio definition
This commit is contained in:
toasted-nutbread 2020-09-10 11:57:38 -04:00 committed by GitHub
parent 17ebe6a754
commit 35abd517b9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 47 additions and 42 deletions

View File

@ -124,15 +124,16 @@ class AnkiNoteBuilder {
try { try {
const {sources, customSourceUrl} = details; const {sources, customSourceUrl} = details;
const expressions = definition.expressions; const expressions = definition.expressions;
const audioSourceDefinition = Array.isArray(expressions) ? expressions[0] : definition; const {expression, reading} = Array.isArray(expressions) ? expressions[0] : definition;
let fileName = this._createInjectedAudioFileName(audioSourceDefinition); let fileName = this._createInjectedAudioFileName(expression, reading);
if (fileName === null) { return; } if (fileName === null) { return; }
fileName = this._replaceInvalidFileNameCharacters(fileName); fileName = this._replaceInvalidFileNameCharacters(fileName);
const {audio: data} = await this._getDefinitionAudio( const {audio: data} = await this._getDefinitionAudio(
audioSourceDefinition,
sources, sources,
expression,
reading,
{ {
textToSpeechVoice: null, textToSpeechVoice: null,
customSourceUrl, customSourceUrl,
@ -199,8 +200,7 @@ class AnkiNoteBuilder {
} }
} }
_createInjectedAudioFileName(definition) { _createInjectedAudioFileName(expression, reading) {
const {reading, expression} = definition;
if (!reading && !expression) { return null; } if (!reading && !expression) { return null; }
let fileName = 'yomichan'; let fileName = 'yomichan';

View File

@ -51,11 +51,11 @@ class AudioUriBuilder {
return url; return url;
} }
async getUri(definition, source, details) { async getUri(source, expression, reading, details) {
const handler = this._getUrlHandlers.get(source); const handler = this._getUrlHandlers.get(source);
if (typeof handler === 'function') { if (typeof handler === 'function') {
try { try {
return await handler(definition, details); return await handler(expression, reading, details);
} catch (e) { } catch (e) {
// NOP // NOP
} }
@ -63,9 +63,9 @@ class AudioUriBuilder {
return null; return null;
} }
async _getUriJpod101(definition) { async _getUriJpod101(expression, reading) {
let kana = definition.reading; let kana = reading;
let kanji = definition.expression; let kanji = expression;
if (!kana && jp.isStringEntirelyKana(kanji)) { if (!kana && jp.isStringEntirelyKana(kanji)) {
kana = kanji; kana = kanji;
@ -83,9 +83,9 @@ class AudioUriBuilder {
return `https://assets.languagepod101.com/dictionary/japanese/audiomp3.php?${params.join('&')}`; return `https://assets.languagepod101.com/dictionary/japanese/audiomp3.php?${params.join('&')}`;
} }
async _getUriJpod101Alternate(definition) { async _getUriJpod101Alternate(expression, reading) {
const fetchUrl = 'https://www.japanesepod101.com/learningcenter/reference/dictionary_post'; const fetchUrl = 'https://www.japanesepod101.com/learningcenter/reference/dictionary_post';
const data = `post=dictionary_reference&match_type=exact&search_query=${encodeURIComponent(definition.expression)}&vulgar=true`; const data = `post=dictionary_reference&match_type=exact&search_query=${encodeURIComponent(expression)}&vulgar=true`;
const response = await this._requestBuilder.fetchAnonymous(fetchUrl, { const response = await this._requestBuilder.fetchAnonymous(fetchUrl, {
method: 'POST', method: 'POST',
mode: 'cors', mode: 'cors',
@ -112,11 +112,11 @@ class AudioUriBuilder {
const url = dom.getAttribute(source, 'src'); const url = dom.getAttribute(source, 'src');
if (url === null) { continue; } if (url === null) { continue; }
const readings = dom.getElementsByClassName('dc-vocab_kana'); const htmlReadings = dom.getElementsByClassName('dc-vocab_kana');
if (readings.length === 0) { continue; } if (htmlReadings.length === 0) { continue; }
const reading = dom.getTextContent(readings[0]); const htmlReading = dom.getTextContent(htmlReadings[0]);
if (reading && (!definition.reading || definition.reading === reading)) { if (htmlReading && (!reading || reading === htmlReading)) {
return this.normalizeUrl(url, 'https://www.japanesepod101.com', '/learningcenter/reference/'); return this.normalizeUrl(url, 'https://www.japanesepod101.com', '/learningcenter/reference/');
} }
} catch (e) { } catch (e) {
@ -127,8 +127,8 @@ class AudioUriBuilder {
throw new Error('Failed to find audio URL'); throw new Error('Failed to find audio URL');
} }
async _getUriJisho(definition) { async _getUriJisho(expression, reading) {
const fetchUrl = `https://jisho.org/search/${definition.expression}`; const fetchUrl = `https://jisho.org/search/${expression}`;
const response = await this._requestBuilder.fetchAnonymous(fetchUrl, { const response = await this._requestBuilder.fetchAnonymous(fetchUrl, {
method: 'GET', method: 'GET',
mode: 'cors', mode: 'cors',
@ -141,7 +141,7 @@ class AudioUriBuilder {
const dom = new SimpleDOMParser(responseText); const dom = new SimpleDOMParser(responseText);
try { try {
const audio = dom.getElementById(`audio_${definition.expression}:${definition.reading}`); const audio = dom.getElementById(`audio_${expression}:${reading}`);
if (audio !== null) { if (audio !== null) {
const source = dom.getElementByTagName('source', audio); const source = dom.getElementByTagName('source', audio);
if (source !== null) { if (source !== null) {
@ -158,24 +158,25 @@ class AudioUriBuilder {
throw new Error('Failed to find audio URL'); throw new Error('Failed to find audio URL');
} }
async _getUriTextToSpeech(definition, {textToSpeechVoice}) { async _getUriTextToSpeech(expression, reading, {textToSpeechVoice}) {
if (!textToSpeechVoice) { if (!textToSpeechVoice) {
throw new Error('No voice'); throw new Error('No voice');
} }
return `tts:?text=${encodeURIComponent(definition.expression)}&voice=${encodeURIComponent(textToSpeechVoice)}`; return `tts:?text=${encodeURIComponent(expression)}&voice=${encodeURIComponent(textToSpeechVoice)}`;
} }
async _getUriTextToSpeechReading(definition, {textToSpeechVoice}) { async _getUriTextToSpeechReading(expression, reading, {textToSpeechVoice}) {
if (!textToSpeechVoice) { if (!textToSpeechVoice) {
throw new Error('No voice'); throw new Error('No voice');
} }
return `tts:?text=${encodeURIComponent(definition.reading || definition.expression)}&voice=${encodeURIComponent(textToSpeechVoice)}`; return `tts:?text=${encodeURIComponent(reading || expression)}&voice=${encodeURIComponent(textToSpeechVoice)}`;
} }
async _getUriCustom(definition, {customSourceUrl}) { async _getUriCustom(expression, reading, {customSourceUrl}) {
if (typeof customSourceUrl !== 'string') { if (typeof customSourceUrl !== 'string') {
throw new Error('No custom URL defined'); throw new Error('No custom URL defined');
} }
return customSourceUrl.replace(/\{([^}]*)\}/g, (m0, m1) => (hasOwn(definition, m1) ? `${definition[m1]}` : m0)); const data = {expression, reading};
return customSourceUrl.replace(/\{([^}]*)\}/g, (m0, m1) => (hasOwn(data, m1) ? `${data[m1]}` : m0));
} }
} }

View File

@ -508,8 +508,8 @@ class Backend {
return this._runCommand(command, params); return this._runCommand(command, params);
} }
async _onApiAudioGetUri({definition, source, details}) { async _onApiAudioGetUri({source, expression, reading, details}) {
return await this._audioUriBuilder.getUri(definition, source, details); return await this._audioUriBuilder.getUri(source, expression, reading, details);
} }
_onApiScreenshotGet({options}, sender) { _onApiScreenshotGet({options}, sender) {
@ -828,8 +828,8 @@ class Backend {
return (tab !== null); return (tab !== null);
} }
async _onApiGetDefinitionAudio({definition, sources, details}) { async _onApiGetDefinitionAudio({sources, expression, reading, details}) {
return this._getDefinitionAudio(definition, sources, details); return this._getDefinitionAudio(sources, expression, reading, details);
} }
// Command handlers // Command handlers
@ -1637,7 +1637,7 @@ class Backend {
} }
} }
async _getDefinitionAudio(definition, sources, details) { async _getDefinitionAudio(sources, expression, reading, details) {
return await this._audioSystem.getDefinitionAudio(definition, sources, details); return await this._audioSystem.getDefinitionAudio(sources, expression, reading, details);
} }
} }

View File

@ -93,8 +93,8 @@ const api = (() => {
return this._invoke('templateRender', {data, template, marker}); return this._invoke('templateRender', {data, template, marker});
} }
audioGetUri(definition, source, details) { audioGetUri(source, expression, reading, details) {
return this._invoke('audioGetUri', {definition, source, details}); return this._invoke('audioGetUri', {source, expression, reading, details});
} }
commandExec(command, params) { commandExec(command, params) {
@ -197,6 +197,10 @@ const api = (() => {
return this._invoke('isTabSearchPopup', {tabId}); return this._invoke('isTabSearchPopup', {tabId});
} }
getDefinitionAudio(sources, expression, reading, details) {
return this._invoke('getDefinitionAudio', {sources, expression, reading, details});
}
// Invoke functions with progress // Invoke functions with progress
deleteDictionary(dictionaryName, onProgress) { deleteDictionary(dictionaryName, onProgress) {

View File

@ -78,8 +78,8 @@ class AudioSystem {
} }
} }
async getDefinitionAudio(definition, sources, details) { async getDefinitionAudio(sources, expression, reading, details) {
const key = `${definition.expression}:${definition.reading}`; const key = `${expression}:${reading}`;
const hasCache = (this._cache !== null && !details.disableCache); const hasCache = (this._cache !== null && !details.disableCache);
if (hasCache) { if (hasCache) {
@ -95,7 +95,7 @@ class AudioSystem {
for (let i = 0, ii = sources.length; i < ii; ++i) { for (let i = 0, ii = sources.length; i < ii; ++i) {
const source = sources[i]; const source = sources[i];
const uri = await this._getAudioUri(definition, source, details); const uri = await this._getAudioUri(source, expression, reading, details);
if (uri === null) { continue; } if (uri === null) { continue; }
try { try {
@ -129,10 +129,10 @@ class AudioSystem {
// NOP // NOP
} }
_getAudioUri(definition, source, details) { _getAudioUri(source, expression, reading, details) {
return ( return (
this._audioUriBuilder !== null ? this._audioUriBuilder !== null ?
this._audioUriBuilder.getUri(definition, source, details) : this._audioUriBuilder.getUri(source, expression, reading, details) :
null null
); );
} }

View File

@ -42,8 +42,8 @@ class Display extends EventDispatcher {
this._audioFallback = null; this._audioFallback = null;
this._audioSystem = new AudioSystem({ this._audioSystem = new AudioSystem({
audioUriBuilder: { audioUriBuilder: {
getUri: async (definition, source, details) => { getUri: async (source, expression, reading, details) => {
return await api.audioGetUri(definition, source, details); return await api.audioGetUri(source, expression, reading, details);
} }
}, },
useCache: true useCache: true
@ -1071,7 +1071,7 @@ class Display extends EventDispatcher {
try { try {
this.setSpinnerVisible(true); this.setSpinnerVisible(true);
const expression = expressionIndex === -1 ? definition : definition.expressions[expressionIndex]; const {expression, reading} = expressionIndex === -1 ? definition : definition.expressions[expressionIndex];
this._stopPlayingAudio(); this._stopPlayingAudio();
@ -1079,7 +1079,7 @@ class Display extends EventDispatcher {
try { try {
const {sources, textToSpeechVoice, customSourceUrl} = this._options.audio; const {sources, textToSpeechVoice, customSourceUrl} = this._options.audio;
let index; let index;
({audio, index} = await this._audioSystem.getDefinitionAudio(expression, sources, {textToSpeechVoice, customSourceUrl})); ({audio, index} = await this._audioSystem.getDefinitionAudio(sources, expression, reading, {textToSpeechVoice, customSourceUrl}));
info = `From source ${1 + index}: ${sources[index]}`; info = `From source ${1 + index}: ${sources[index]}`;
} catch (e) { } catch (e) {
if (this._audioFallback === null) { if (this._audioFallback === null) {