From 21d194d14510abb149d22c8cbd56570cd6b62266 Mon Sep 17 00:00:00 2001
From: toasted-nutbread <toasted-nutbread@users.noreply.github.com>
Date: Sat, 7 Mar 2020 14:25:25 -0500
Subject: Make _audioInject internal to Backend

---
 ext/bg/js/audio.js   | 44 --------------------------------------------
 ext/bg/js/backend.js | 47 +++++++++++++++++++++++++++++++++++++++++++----
 2 files changed, 43 insertions(+), 48 deletions(-)

(limited to 'ext/bg/js')

diff --git a/ext/bg/js/audio.js b/ext/bg/js/audio.js
index c94121ae..361a19cc 100644
--- a/ext/bg/js/audio.js
+++ b/ext/bg/js/audio.js
@@ -138,47 +138,3 @@ function audioUrlNormalize(url, baseUrl, basePath) {
     }
     return url;
 }
-
-function audioBuildFilename(definition) {
-    if (definition.reading || definition.expression) {
-        let filename = 'yomichan';
-        if (definition.reading) {
-            filename += `_${definition.reading}`;
-        }
-        if (definition.expression) {
-            filename += `_${definition.expression}`;
-        }
-
-        return filename += '.mp3';
-    }
-    return null;
-}
-
-async function audioInject(definition, fields, sources, optionsContext, audioSystem) {
-    let usesAudio = false;
-    for (const fieldValue of Object.values(fields)) {
-        if (fieldValue.includes('{audio}')) {
-            usesAudio = true;
-            break;
-        }
-    }
-
-    if (!usesAudio) {
-        return true;
-    }
-
-    try {
-        const expressions = definition.expressions;
-        const audioSourceDefinition = Array.isArray(expressions) ? expressions[0] : definition;
-
-        const {uri} = await audioSystem.getDefinitionAudio(audioSourceDefinition, sources, {tts: false, optionsContext});
-        const filename = audioBuildFilename(audioSourceDefinition);
-        if (filename !== null) {
-            definition.audio = {url: uri, filename};
-        }
-
-        return true;
-    } catch (e) {
-        return false;
-    }
-}
diff --git a/ext/bg/js/backend.js b/ext/bg/js/backend.js
index 6e5235ed..1fdc4c70 100644
--- a/ext/bg/js/backend.js
+++ b/ext/bg/js/backend.js
@@ -21,7 +21,7 @@ conditionsTestValue, profileConditionsDescriptor
 handlebarsRenderDynamic
 requestText, requestJson, optionsLoad
 dictConfigured, dictTermsSort, dictEnabledSet
-audioGetUrl, audioInject
+audioGetUrl
 jpConvertReading, jpDistributeFuriganaInflected, jpKatakanaToHiragana
 AnkiNoteBuilder, AudioSystem, Translator, AnkiConnect, AnkiNull, Mecab, BackendApiForwarder, JsonSchema, ClipboardMonitor*/
 
@@ -434,12 +434,11 @@ class Backend {
         const templates = this.defaultAnkiFieldTemplates;
 
         if (mode !== 'kanji') {
-            await audioInject(
+            await this._audioInject(
                 definition,
                 options.anki.terms.fields,
                 options.audio.sources,
-                optionsContext,
-                this.audioSystem
+                optionsContext
             );
         }
 
@@ -775,6 +774,35 @@ class Backend {
         return await audioGetUrl(definition, source, options);
     }
 
+    async _audioInject(definition, fields, sources, optionsContext) {
+        let usesAudio = false;
+        for (const fieldValue of Object.values(fields)) {
+            if (fieldValue.includes('{audio}')) {
+                usesAudio = true;
+                break;
+            }
+        }
+
+        if (!usesAudio) {
+            return true;
+        }
+
+        try {
+            const expressions = definition.expressions;
+            const audioSourceDefinition = Array.isArray(expressions) ? expressions[0] : definition;
+
+            const {uri} = await this.audioSystem.getDefinitionAudio(audioSourceDefinition, sources, {tts: false, optionsContext});
+            const filename = this._createInjectedAudioFileName(audioSourceDefinition);
+            if (filename !== null) {
+                definition.audio = {url: uri, filename};
+            }
+
+            return true;
+        } catch (e) {
+            return false;
+        }
+    }
+
     async _injectScreenshot(definition, fields, screenshot) {
         let usesScreenshot = false;
         for (const fieldValue of Object.values(fields)) {
@@ -815,6 +843,17 @@ class Backend {
         return handlebarsRenderDynamic(template, data);
     }
 
+    _createInjectedAudioFileName(definition) {
+        const {reading, expression} = definition;
+        if (!reading && !expression) { return null; }
+
+        let filename = 'yomichan';
+        if (reading) { filename += `_${reading}`; }
+        if (expression) { filename += `_${expression}`; }
+        filename += '.mp3';
+        return filename;
+    }
+
     static _getTabUrl(tab) {
         return new Promise((resolve) => {
             chrome.tabs.sendMessage(tab.id, {action: 'getUrl'}, {frameId: 0}, (response) => {
-- 
cgit v1.2.3


From 391f3dd29af2017b540b38e67a06242af85268ba Mon Sep 17 00:00:00 2001
From: toasted-nutbread <toasted-nutbread@users.noreply.github.com>
Date: Sat, 7 Mar 2020 14:36:16 -0500
Subject: Update how audio URIs are built

---
 ext/bg/js/audio.js   | 104 +++++++++++++++++++++++++++++----------------------
 ext/bg/js/backend.js |   8 ++--
 2 files changed, 64 insertions(+), 48 deletions(-)

(limited to 'ext/bg/js')

diff --git a/ext/bg/js/audio.js b/ext/bg/js/audio.js
index 361a19cc..80e9cb9a 100644
--- a/ext/bg/js/audio.js
+++ b/ext/bg/js/audio.js
@@ -18,8 +18,49 @@
 
 /*global jpIsStringEntirelyKana*/
 
-const audioUrlBuilders = new Map([
-    ['jpod101', async (definition) => {
+class AudioUriBuilder {
+    constructor() {
+        this._getUrlHandlers = new Map([
+            ['jpod101', this._getUriJpod101.bind(this)],
+            ['jpod101-alternate', this._getUriJpod101Alternate.bind(this)],
+            ['jisho', this._getUriJisho.bind(this)],
+            ['text-to-speech', this._getUriTextToSpeech.bind(this)],
+            ['text-to-speech-reading', this._getUriTextToSpeechReading.bind(this)],
+            ['custom', this._getUriCustom.bind(this)]
+        ]);
+    }
+
+    normalizeUrl(url, baseUrl, basePath) {
+        if (url) {
+            if (url[0] === '/') {
+                if (url.length >= 2 && url[1] === '/') {
+                    // Begins with "//"
+                    url = baseUrl.substring(0, baseUrl.indexOf(':') + 1) + url;
+                } else {
+                    // Begins with "/"
+                    url = baseUrl + url;
+                }
+            } else if (!/^[a-z][a-z0-9\-+.]*:/i.test(url)) {
+                // No URI scheme => relative path
+                url = baseUrl + basePath + url;
+            }
+        }
+        return url;
+    }
+
+    async getUri(mode, definition, options) {
+        const handler = this._getUrlHandlers.get(mode);
+        if (typeof handler === 'function') {
+            try {
+                return await handler(definition, options);
+            } catch (e) {
+                // NOP
+            }
+        }
+        return null;
+    }
+
+    async _getUriJpod101(definition) {
         let kana = definition.reading;
         let kanji = definition.expression;
 
@@ -37,8 +78,9 @@ const audioUrlBuilders = new Map([
         }
 
         return `https://assets.languagepod101.com/dictionary/japanese/audiomp3.php?${params.join('&')}`;
-    }],
-    ['jpod101-alternate', async (definition) => {
+    }
+
+    async _getUriJpod101Alternate(definition) {
         const response = await new Promise((resolve, reject) => {
             const xhr = new XMLHttpRequest();
             xhr.open('POST', 'https://www.japanesepod101.com/learningcenter/reference/dictionary_post');
@@ -54,7 +96,7 @@ const audioUrlBuilders = new Map([
                 const url = row.querySelector('audio>source[src]').getAttribute('src');
                 const reading = row.getElementsByClassName('dc-vocab_kana').item(0).textContent;
                 if (url && reading && (!definition.reading || definition.reading === reading)) {
-                    return audioUrlNormalize(url, 'https://www.japanesepod101.com', '/learningcenter/reference/');
+                    return this.normalizeUrl(url, 'https://www.japanesepod101.com', '/learningcenter/reference/');
                 }
             } catch (e) {
                 // NOP
@@ -62,8 +104,9 @@ const audioUrlBuilders = new Map([
         }
 
         throw new Error('Failed to find audio URL');
-    }],
-    ['jisho', async (definition) => {
+    }
+
+    async _getUriJisho(definition) {
         const response = await new Promise((resolve, reject) => {
             const xhr = new XMLHttpRequest();
             xhr.open('GET', `https://jisho.org/search/${definition.expression}`);
@@ -78,7 +121,7 @@ const audioUrlBuilders = new Map([
             if (audio !== null) {
                 const url = audio.getElementsByTagName('source').item(0).getAttribute('src');
                 if (url) {
-                    return audioUrlNormalize(url, 'https://jisho.org', '/search/');
+                    return this.normalizeUrl(url, 'https://jisho.org', '/search/');
                 }
             }
         } catch (e) {
@@ -86,55 +129,28 @@ const audioUrlBuilders = new Map([
         }
 
         throw new Error('Failed to find audio URL');
-    }],
-    ['text-to-speech', async (definition, options) => {
+    }
+
+    async _getUriTextToSpeech(definition, options) {
         const voiceURI = options.audio.textToSpeechVoice;
         if (!voiceURI) {
             throw new Error('No voice');
         }
 
         return `tts:?text=${encodeURIComponent(definition.expression)}&voice=${encodeURIComponent(voiceURI)}`;
-    }],
-    ['text-to-speech-reading', async (definition, options) => {
+    }
+
+    async _getUriTextToSpeechReading(definition, options) {
         const voiceURI = options.audio.textToSpeechVoice;
         if (!voiceURI) {
             throw new Error('No voice');
         }
 
         return `tts:?text=${encodeURIComponent(definition.reading || definition.expression)}&voice=${encodeURIComponent(voiceURI)}`;
-    }],
-    ['custom', async (definition, options) => {
-        const customSourceUrl = options.audio.customSourceUrl;
-        return customSourceUrl.replace(/\{([^}]*)\}/g, (m0, m1) => (hasOwn(definition, m1) ? `${definition[m1]}` : m0));
-    }]
-]);
-
-async function audioGetUrl(definition, mode, options, download) {
-    const handler = audioUrlBuilders.get(mode);
-    if (typeof handler === 'function') {
-        try {
-            return await handler(definition, options, download);
-        } catch (e) {
-            // NOP
-        }
     }
-    return null;
-}
 
-function audioUrlNormalize(url, baseUrl, basePath) {
-    if (url) {
-        if (url[0] === '/') {
-            if (url.length >= 2 && url[1] === '/') {
-                // Begins with "//"
-                url = baseUrl.substring(0, baseUrl.indexOf(':') + 1) + url;
-            } else {
-                // Begins with "/"
-                url = baseUrl + url;
-            }
-        } else if (!/^[a-z][a-z0-9\-+.]*:/i.test(url)) {
-            // No URI scheme => relative path
-            url = baseUrl + basePath + url;
-        }
+    async _getUriCustom(definition, options) {
+        const customSourceUrl = options.audio.customSourceUrl;
+        return customSourceUrl.replace(/\{([^}]*)\}/g, (m0, m1) => (hasOwn(definition, m1) ? `${definition[m1]}` : m0));
     }
-    return url;
 }
diff --git a/ext/bg/js/backend.js b/ext/bg/js/backend.js
index 1fdc4c70..66378b0c 100644
--- a/ext/bg/js/backend.js
+++ b/ext/bg/js/backend.js
@@ -21,9 +21,8 @@ conditionsTestValue, profileConditionsDescriptor
 handlebarsRenderDynamic
 requestText, requestJson, optionsLoad
 dictConfigured, dictTermsSort, dictEnabledSet
-audioGetUrl
 jpConvertReading, jpDistributeFuriganaInflected, jpKatakanaToHiragana
-AnkiNoteBuilder, AudioSystem, Translator, AnkiConnect, AnkiNull, Mecab, BackendApiForwarder, JsonSchema, ClipboardMonitor*/
+AnkiNoteBuilder, AudioSystem, AudioUriBuilder, Translator, AnkiConnect, AnkiNull, Mecab, BackendApiForwarder, JsonSchema, ClipboardMonitor*/
 
 class Backend {
     constructor() {
@@ -36,6 +35,7 @@ class Backend {
         this.optionsSchema = null;
         this.defaultAnkiFieldTemplates = null;
         this.audioSystem = new AudioSystem({getAudioUri: this._getAudioUri.bind(this)});
+        this.audioUriBuilder = new AudioUriBuilder();
         this.optionsContext = {
             depth: 0,
             url: window.location.href
@@ -515,7 +515,7 @@ class Backend {
 
     async _onApiAudioGetUrl({definition, source, optionsContext}) {
         const options = this.getOptions(optionsContext);
-        return await audioGetUrl(definition, source, options);
+        return await this.audioUriBuilder.getUri(source, definition, options);
     }
 
     _onApiScreenshotGet({options}, sender) {
@@ -771,7 +771,7 @@ class Backend {
         }
 
         const options = this.getOptions(optionsContext);
-        return await audioGetUrl(definition, source, options);
+        return await this.audioUriBuilder.getUri(source, definition, options);
     }
 
     async _audioInject(definition, fields, sources, optionsContext) {
-- 
cgit v1.2.3


From aad4ab5eccaeed14514d676c0de4f3e2db718072 Mon Sep 17 00:00:00 2001
From: toasted-nutbread <toasted-nutbread@users.noreply.github.com>
Date: Sat, 7 Mar 2020 14:37:44 -0500
Subject: Rename audio functions using "url" to use "uri"

---
 ext/bg/js/backend.js        | 4 ++--
 ext/bg/js/settings/audio.js | 4 ++--
 ext/mixed/js/api.js         | 4 ++--
 ext/mixed/js/display.js     | 4 ++--
 4 files changed, 8 insertions(+), 8 deletions(-)

(limited to 'ext/bg/js')

diff --git a/ext/bg/js/backend.js b/ext/bg/js/backend.js
index 66378b0c..eb88a6c1 100644
--- a/ext/bg/js/backend.js
+++ b/ext/bg/js/backend.js
@@ -67,7 +67,7 @@ class Backend {
             ['noteView', this._onApiNoteView.bind(this)],
             ['templateRender', this._onApiTemplateRender.bind(this)],
             ['commandExec', this._onApiCommandExec.bind(this)],
-            ['audioGetUrl', this._onApiAudioGetUrl.bind(this)],
+            ['audioGetUri', this._onApiAudioGetUri.bind(this)],
             ['screenshotGet', this._onApiScreenshotGet.bind(this)],
             ['forward', this._onApiForward.bind(this)],
             ['frameInformationGet', this._onApiFrameInformationGet.bind(this)],
@@ -513,7 +513,7 @@ class Backend {
         return this._runCommand(command, params);
     }
 
-    async _onApiAudioGetUrl({definition, source, optionsContext}) {
+    async _onApiAudioGetUri({definition, source, optionsContext}) {
         const options = this.getOptions(optionsContext);
         return await this.audioUriBuilder.getUri(source, definition, options);
     }
diff --git a/ext/bg/js/settings/audio.js b/ext/bg/js/settings/audio.js
index 6f581d9b..c825be6b 100644
--- a/ext/bg/js/settings/audio.js
+++ b/ext/bg/js/settings/audio.js
@@ -16,7 +16,7 @@
  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
  */
 
-/*global getOptionsContext, getOptionsMutable, settingsSaveOptions, apiAudioGetUrl
+/*global getOptionsContext, getOptionsMutable, settingsSaveOptions, apiAudioGetUri
 AudioSystem, AudioSourceUI*/
 
 let audioSourceUI = null;
@@ -26,7 +26,7 @@ async function audioSettingsInitialize() {
     audioSystem = new AudioSystem({
         getAudioUri: async (definition, source) => {
             const optionsContext = getOptionsContext();
-            return await apiAudioGetUrl(definition, source, optionsContext);
+            return await apiAudioGetUri(definition, source, optionsContext);
         }
     });
 
diff --git a/ext/mixed/js/api.js b/ext/mixed/js/api.js
index 26f4389d..0ab07039 100644
--- a/ext/mixed/js/api.js
+++ b/ext/mixed/js/api.js
@@ -69,8 +69,8 @@ function apiTemplateRender(template, data) {
     return _apiInvoke('templateRender', {data, template});
 }
 
-function apiAudioGetUrl(definition, source, optionsContext) {
-    return _apiInvoke('audioGetUrl', {definition, source, optionsContext});
+function apiAudioGetUri(definition, source, optionsContext) {
+    return _apiInvoke('audioGetUri', {definition, source, optionsContext});
 }
 
 function apiCommandExec(command, params) {
diff --git a/ext/mixed/js/display.js b/ext/mixed/js/display.js
index 3fe8e684..a220c1f7 100644
--- a/ext/mixed/js/display.js
+++ b/ext/mixed/js/display.js
@@ -18,7 +18,7 @@
 
 /*global docRangeFromPoint, docSentenceExtract
 apiKanjiFind, apiTermsFind, apiNoteView, apiOptionsGet, apiDefinitionsAddable, apiDefinitionAdd
-apiScreenshotGet, apiForward, apiAudioGetUrl
+apiScreenshotGet, apiForward, apiAudioGetUri
 AudioSystem, DisplayGenerator, WindowScroll, DisplayContext, DOM*/
 
 class Display {
@@ -919,6 +919,6 @@ class Display {
 
     async _getAudioUri(definition, source) {
         const optionsContext = this.getOptionsContext();
-        return await apiAudioGetUrl(definition, source, optionsContext);
+        return await apiAudioGetUri(definition, source, optionsContext);
     }
 }
-- 
cgit v1.2.3


From 9cd4a52b9e701f47c7ca7b44c52cbcd66b7bcb05 Mon Sep 17 00:00:00 2001
From: toasted-nutbread <toasted-nutbread@users.noreply.github.com>
Date: Sat, 7 Mar 2020 14:39:25 -0500
Subject: Rename audio.js to audio-uri-builder.js

---
 ext/bg/background.html         |   2 +-
 ext/bg/js/audio-uri-builder.js | 156 +++++++++++++++++++++++++++++++++++++++++
 ext/bg/js/audio.js             | 156 -----------------------------------------
 3 files changed, 157 insertions(+), 157 deletions(-)
 create mode 100644 ext/bg/js/audio-uri-builder.js
 delete mode 100644 ext/bg/js/audio.js

(limited to 'ext/bg/js')

diff --git a/ext/bg/background.html b/ext/bg/background.html
index f6e00bf5..44abe8fd 100644
--- a/ext/bg/background.html
+++ b/ext/bg/background.html
@@ -24,7 +24,7 @@
         <script src="/bg/js/anki.js"></script>
         <script src="/bg/js/anki-note-builder.js"></script>
         <script src="/bg/js/mecab.js"></script>
-        <script src="/bg/js/audio.js"></script>
+        <script src="/bg/js/audio-uri-builder.js"></script>
         <script src="/bg/js/backend-api-forwarder.js"></script>
         <script src="/bg/js/clipboard-monitor.js"></script>
         <script src="/bg/js/conditions.js"></script>
diff --git a/ext/bg/js/audio-uri-builder.js b/ext/bg/js/audio-uri-builder.js
new file mode 100644
index 00000000..80e9cb9a
--- /dev/null
+++ b/ext/bg/js/audio-uri-builder.js
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2017-2020  Alex Yatskov <alex@foosoft.net>
+ * Author: Alex Yatskov <alex@foosoft.net>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+/*global jpIsStringEntirelyKana*/
+
+class AudioUriBuilder {
+    constructor() {
+        this._getUrlHandlers = new Map([
+            ['jpod101', this._getUriJpod101.bind(this)],
+            ['jpod101-alternate', this._getUriJpod101Alternate.bind(this)],
+            ['jisho', this._getUriJisho.bind(this)],
+            ['text-to-speech', this._getUriTextToSpeech.bind(this)],
+            ['text-to-speech-reading', this._getUriTextToSpeechReading.bind(this)],
+            ['custom', this._getUriCustom.bind(this)]
+        ]);
+    }
+
+    normalizeUrl(url, baseUrl, basePath) {
+        if (url) {
+            if (url[0] === '/') {
+                if (url.length >= 2 && url[1] === '/') {
+                    // Begins with "//"
+                    url = baseUrl.substring(0, baseUrl.indexOf(':') + 1) + url;
+                } else {
+                    // Begins with "/"
+                    url = baseUrl + url;
+                }
+            } else if (!/^[a-z][a-z0-9\-+.]*:/i.test(url)) {
+                // No URI scheme => relative path
+                url = baseUrl + basePath + url;
+            }
+        }
+        return url;
+    }
+
+    async getUri(mode, definition, options) {
+        const handler = this._getUrlHandlers.get(mode);
+        if (typeof handler === 'function') {
+            try {
+                return await handler(definition, options);
+            } catch (e) {
+                // NOP
+            }
+        }
+        return null;
+    }
+
+    async _getUriJpod101(definition) {
+        let kana = definition.reading;
+        let kanji = definition.expression;
+
+        if (!kana && jpIsStringEntirelyKana(kanji)) {
+            kana = kanji;
+            kanji = null;
+        }
+
+        const params = [];
+        if (kanji) {
+            params.push(`kanji=${encodeURIComponent(kanji)}`);
+        }
+        if (kana) {
+            params.push(`kana=${encodeURIComponent(kana)}`);
+        }
+
+        return `https://assets.languagepod101.com/dictionary/japanese/audiomp3.php?${params.join('&')}`;
+    }
+
+    async _getUriJpod101Alternate(definition) {
+        const response = await new Promise((resolve, reject) => {
+            const xhr = new XMLHttpRequest();
+            xhr.open('POST', 'https://www.japanesepod101.com/learningcenter/reference/dictionary_post');
+            xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
+            xhr.addEventListener('error', () => reject(new Error('Failed to scrape audio data')));
+            xhr.addEventListener('load', () => resolve(xhr.responseText));
+            xhr.send(`post=dictionary_reference&match_type=exact&search_query=${encodeURIComponent(definition.expression)}`);
+        });
+
+        const dom = new DOMParser().parseFromString(response, 'text/html');
+        for (const row of dom.getElementsByClassName('dc-result-row')) {
+            try {
+                const url = row.querySelector('audio>source[src]').getAttribute('src');
+                const reading = row.getElementsByClassName('dc-vocab_kana').item(0).textContent;
+                if (url && reading && (!definition.reading || definition.reading === reading)) {
+                    return this.normalizeUrl(url, 'https://www.japanesepod101.com', '/learningcenter/reference/');
+                }
+            } catch (e) {
+                // NOP
+            }
+        }
+
+        throw new Error('Failed to find audio URL');
+    }
+
+    async _getUriJisho(definition) {
+        const response = await new Promise((resolve, reject) => {
+            const xhr = new XMLHttpRequest();
+            xhr.open('GET', `https://jisho.org/search/${definition.expression}`);
+            xhr.addEventListener('error', () => reject(new Error('Failed to scrape audio data')));
+            xhr.addEventListener('load', () => resolve(xhr.responseText));
+            xhr.send();
+        });
+
+        const dom = new DOMParser().parseFromString(response, 'text/html');
+        try {
+            const audio = dom.getElementById(`audio_${definition.expression}:${definition.reading}`);
+            if (audio !== null) {
+                const url = audio.getElementsByTagName('source').item(0).getAttribute('src');
+                if (url) {
+                    return this.normalizeUrl(url, 'https://jisho.org', '/search/');
+                }
+            }
+        } catch (e) {
+            // NOP
+        }
+
+        throw new Error('Failed to find audio URL');
+    }
+
+    async _getUriTextToSpeech(definition, options) {
+        const voiceURI = options.audio.textToSpeechVoice;
+        if (!voiceURI) {
+            throw new Error('No voice');
+        }
+
+        return `tts:?text=${encodeURIComponent(definition.expression)}&voice=${encodeURIComponent(voiceURI)}`;
+    }
+
+    async _getUriTextToSpeechReading(definition, options) {
+        const voiceURI = options.audio.textToSpeechVoice;
+        if (!voiceURI) {
+            throw new Error('No voice');
+        }
+
+        return `tts:?text=${encodeURIComponent(definition.reading || definition.expression)}&voice=${encodeURIComponent(voiceURI)}`;
+    }
+
+    async _getUriCustom(definition, options) {
+        const customSourceUrl = options.audio.customSourceUrl;
+        return customSourceUrl.replace(/\{([^}]*)\}/g, (m0, m1) => (hasOwn(definition, m1) ? `${definition[m1]}` : m0));
+    }
+}
diff --git a/ext/bg/js/audio.js b/ext/bg/js/audio.js
deleted file mode 100644
index 80e9cb9a..00000000
--- a/ext/bg/js/audio.js
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * Copyright (C) 2017-2020  Alex Yatskov <alex@foosoft.net>
- * Author: Alex Yatskov <alex@foosoft.net>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- */
-
-/*global jpIsStringEntirelyKana*/
-
-class AudioUriBuilder {
-    constructor() {
-        this._getUrlHandlers = new Map([
-            ['jpod101', this._getUriJpod101.bind(this)],
-            ['jpod101-alternate', this._getUriJpod101Alternate.bind(this)],
-            ['jisho', this._getUriJisho.bind(this)],
-            ['text-to-speech', this._getUriTextToSpeech.bind(this)],
-            ['text-to-speech-reading', this._getUriTextToSpeechReading.bind(this)],
-            ['custom', this._getUriCustom.bind(this)]
-        ]);
-    }
-
-    normalizeUrl(url, baseUrl, basePath) {
-        if (url) {
-            if (url[0] === '/') {
-                if (url.length >= 2 && url[1] === '/') {
-                    // Begins with "//"
-                    url = baseUrl.substring(0, baseUrl.indexOf(':') + 1) + url;
-                } else {
-                    // Begins with "/"
-                    url = baseUrl + url;
-                }
-            } else if (!/^[a-z][a-z0-9\-+.]*:/i.test(url)) {
-                // No URI scheme => relative path
-                url = baseUrl + basePath + url;
-            }
-        }
-        return url;
-    }
-
-    async getUri(mode, definition, options) {
-        const handler = this._getUrlHandlers.get(mode);
-        if (typeof handler === 'function') {
-            try {
-                return await handler(definition, options);
-            } catch (e) {
-                // NOP
-            }
-        }
-        return null;
-    }
-
-    async _getUriJpod101(definition) {
-        let kana = definition.reading;
-        let kanji = definition.expression;
-
-        if (!kana && jpIsStringEntirelyKana(kanji)) {
-            kana = kanji;
-            kanji = null;
-        }
-
-        const params = [];
-        if (kanji) {
-            params.push(`kanji=${encodeURIComponent(kanji)}`);
-        }
-        if (kana) {
-            params.push(`kana=${encodeURIComponent(kana)}`);
-        }
-
-        return `https://assets.languagepod101.com/dictionary/japanese/audiomp3.php?${params.join('&')}`;
-    }
-
-    async _getUriJpod101Alternate(definition) {
-        const response = await new Promise((resolve, reject) => {
-            const xhr = new XMLHttpRequest();
-            xhr.open('POST', 'https://www.japanesepod101.com/learningcenter/reference/dictionary_post');
-            xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
-            xhr.addEventListener('error', () => reject(new Error('Failed to scrape audio data')));
-            xhr.addEventListener('load', () => resolve(xhr.responseText));
-            xhr.send(`post=dictionary_reference&match_type=exact&search_query=${encodeURIComponent(definition.expression)}`);
-        });
-
-        const dom = new DOMParser().parseFromString(response, 'text/html');
-        for (const row of dom.getElementsByClassName('dc-result-row')) {
-            try {
-                const url = row.querySelector('audio>source[src]').getAttribute('src');
-                const reading = row.getElementsByClassName('dc-vocab_kana').item(0).textContent;
-                if (url && reading && (!definition.reading || definition.reading === reading)) {
-                    return this.normalizeUrl(url, 'https://www.japanesepod101.com', '/learningcenter/reference/');
-                }
-            } catch (e) {
-                // NOP
-            }
-        }
-
-        throw new Error('Failed to find audio URL');
-    }
-
-    async _getUriJisho(definition) {
-        const response = await new Promise((resolve, reject) => {
-            const xhr = new XMLHttpRequest();
-            xhr.open('GET', `https://jisho.org/search/${definition.expression}`);
-            xhr.addEventListener('error', () => reject(new Error('Failed to scrape audio data')));
-            xhr.addEventListener('load', () => resolve(xhr.responseText));
-            xhr.send();
-        });
-
-        const dom = new DOMParser().parseFromString(response, 'text/html');
-        try {
-            const audio = dom.getElementById(`audio_${definition.expression}:${definition.reading}`);
-            if (audio !== null) {
-                const url = audio.getElementsByTagName('source').item(0).getAttribute('src');
-                if (url) {
-                    return this.normalizeUrl(url, 'https://jisho.org', '/search/');
-                }
-            }
-        } catch (e) {
-            // NOP
-        }
-
-        throw new Error('Failed to find audio URL');
-    }
-
-    async _getUriTextToSpeech(definition, options) {
-        const voiceURI = options.audio.textToSpeechVoice;
-        if (!voiceURI) {
-            throw new Error('No voice');
-        }
-
-        return `tts:?text=${encodeURIComponent(definition.expression)}&voice=${encodeURIComponent(voiceURI)}`;
-    }
-
-    async _getUriTextToSpeechReading(definition, options) {
-        const voiceURI = options.audio.textToSpeechVoice;
-        if (!voiceURI) {
-            throw new Error('No voice');
-        }
-
-        return `tts:?text=${encodeURIComponent(definition.reading || definition.expression)}&voice=${encodeURIComponent(voiceURI)}`;
-    }
-
-    async _getUriCustom(definition, options) {
-        const customSourceUrl = options.audio.customSourceUrl;
-        return customSourceUrl.replace(/\{([^}]*)\}/g, (m0, m1) => (hasOwn(definition, m1) ? `${definition[m1]}` : m0));
-    }
-}
-- 
cgit v1.2.3


From 0cbf427ab50061b48c9027e63e9ee8a209946d37 Mon Sep 17 00:00:00 2001
From: toasted-nutbread <toasted-nutbread@users.noreply.github.com>
Date: Mon, 9 Mar 2020 21:00:57 -0400
Subject: Update argument order

---
 ext/bg/js/audio-uri-builder.js | 4 ++--
 ext/bg/js/backend.js           | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

(limited to 'ext/bg/js')

diff --git a/ext/bg/js/audio-uri-builder.js b/ext/bg/js/audio-uri-builder.js
index 80e9cb9a..15cea995 100644
--- a/ext/bg/js/audio-uri-builder.js
+++ b/ext/bg/js/audio-uri-builder.js
@@ -48,8 +48,8 @@ class AudioUriBuilder {
         return url;
     }
 
-    async getUri(mode, definition, options) {
-        const handler = this._getUrlHandlers.get(mode);
+    async getUri(definition, source, options) {
+        const handler = this._getUrlHandlers.get(source);
         if (typeof handler === 'function') {
             try {
                 return await handler(definition, options);
diff --git a/ext/bg/js/backend.js b/ext/bg/js/backend.js
index eb88a6c1..adc6f13d 100644
--- a/ext/bg/js/backend.js
+++ b/ext/bg/js/backend.js
@@ -515,7 +515,7 @@ class Backend {
 
     async _onApiAudioGetUri({definition, source, optionsContext}) {
         const options = this.getOptions(optionsContext);
-        return await this.audioUriBuilder.getUri(source, definition, options);
+        return await this.audioUriBuilder.getUri(definition, source, options);
     }
 
     _onApiScreenshotGet({options}, sender) {
@@ -771,7 +771,7 @@ class Backend {
         }
 
         const options = this.getOptions(optionsContext);
-        return await this.audioUriBuilder.getUri(source, definition, options);
+        return await this.audioUriBuilder.getUri(definition, source, options);
     }
 
     async _audioInject(definition, fields, sources, optionsContext) {
-- 
cgit v1.2.3