From 046b1b45a5c3f6624e383cab6fe4358f7e1edf8a Mon Sep 17 00:00:00 2001 From: Alex Yatskov Date: Wed, 22 Mar 2017 21:57:16 -0700 Subject: [PATCH 1/5] work on getting audio working again --- ext/mixed/js/display.js | 92 +++++++++++++++++++++++++++++++---------- 1 file changed, 70 insertions(+), 22 deletions(-) diff --git a/ext/mixed/js/display.js b/ext/mixed/js/display.js index d90cf897..0ccf7528 100644 --- a/ext/mixed/js/display.js +++ b/ext/mixed/js/display.js @@ -80,7 +80,7 @@ class Display { $('.action-play-audio').click(e => { e.preventDefault(); const index = Display.entryIndexFind($(e.currentTarget)); - Display.audioPlay(this.definitions[index], this.audioCache); + this.audioPlay(this.definitions[index], this.audioCache); }); $('.kanji-link').click(e => { e.preventDefault(); @@ -168,7 +168,7 @@ class Display { const definition = this.definitions[index]; if (mode !== 'kanji') { - const url = Display.audioBuildUrl(definition); + const url = Display.audioBuildUrlOld(definition); const filename = Display.audioBuildFilename(definition); if (url && filename) { definition.audio = {url, filename}; @@ -184,7 +184,9 @@ class Display { }).catch(this.handleError.bind(this)).then(() => this.spinner.hide()); } - static audioPlay(definition, cache) { + audioPlay(definition, cache) { + this.spinner.show(); + for (const key in cache) { const audio = cache[key]; if (audio !== null) { @@ -192,26 +194,23 @@ class Display { } } - const url = Display.audioBuildUrl(definition); - if (!url) { - return; - } - - let audio = cache[url]; - if (audio) { - audio.currentTime = 0; - audio.play(); - } else { - audio = new Audio(url); - audio.onloadeddata = () => { - if (audio.duration === 5.694694 || audio.duration === 5.720718) { - audio = new Audio('/mixed/mp3/button.mp3'); - } - - cache[url] = audio; + Display.audioBuildUrl(definition).then(url => { + let audio = cache[url]; + if (audio) { + audio.currentTime = 0; audio.play(); - }; - } + } else { + audio = new Audio(url); + audio.onloadeddata = () => { + if (audio.duration === 5.694694 || audio.duration === 5.720718) { + audio = new Audio('/mixed/mp3/button.mp3'); + } + + cache[url] = audio; + audio.play(); + }; + } + }).catch(this.handleError.bind(this)).then(() => this.spinner.hide()); } static entryIndexFind(element) { @@ -223,6 +222,55 @@ class Display { } static audioBuildUrl(definition) { + return new Promise((resolve, reject) => { + const data = { + post: 'dictionary_reference', + match_type: 'exact', + search_query: definition.expression + }; + + const params = []; + for (const key in data) { + params.push(`${encodeURIComponent(key)}=${encodeURIComponent(data[key])}`); + } + + const xhr = new XMLHttpRequest(); + xhr.addEventListener('error', () => reject('failed to execute network request')); + xhr.addEventListener('load', () => resolve(xhr.responseText)); + xhr.open('POST', 'https://www.japanesepod101.com/learningcenter/reference/dictionary_post'); + xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); + xhr.send(params.join('&')); + }).then(response => { + const dom = new DOMParser().parseFromString(response, 'text/html'); + const entries = []; + + for (const row of dom.getElementsByClassName('dc-result-row')) { + try { + const url = row.getElementsByClassName('ill-onebuttonplayer').item(0).getAttribute('data-url'); + const expression = dom.getElementsByClassName('dc-vocab').item(0).innerText; + const reading = dom.getElementsByClassName('dc-vocab_kana').item(0).innerText; + + if (url && expression && reading) { + entries.push({url, expression, reading}); + } + } catch (e) { + // NOP + } + } + + return entries; + }).then(entries => { + for (const entry of entries) { + if (!definition.reading || definition.reading === entry.reading) { + return entry.url; + } + } + + return '/mixed/mp3/button.mp3'; + }); + } + + static audioBuildUrlOld(definition) { let kana = definition.reading; let kanji = definition.expression; From 80d864d6b1b1e94045d11281f803fd1bace657f8 Mon Sep 17 00:00:00 2001 From: Alex Yatskov Date: Wed, 22 Mar 2017 22:28:22 -0700 Subject: [PATCH 2/5] wip --- ext/mixed/js/display.js | 71 +++++++++++++++++------------------------ 1 file changed, 29 insertions(+), 42 deletions(-) diff --git a/ext/mixed/js/display.js b/ext/mixed/js/display.js index 0ccf7528..aa2b5be9 100644 --- a/ext/mixed/js/display.js +++ b/ext/mixed/js/display.js @@ -23,6 +23,7 @@ class Display { this.container = container; this.definitions = []; this.audioCache = {}; + this.resultCache = {}; this.sequence = 0; } @@ -80,7 +81,7 @@ class Display { $('.action-play-audio').click(e => { e.preventDefault(); const index = Display.entryIndexFind($(e.currentTarget)); - this.audioPlay(this.definitions[index], this.audioCache); + this.audioPlay(this.definitions[index]); }); $('.kanji-link').click(e => { e.preventDefault(); @@ -184,18 +185,18 @@ class Display { }).catch(this.handleError.bind(this)).then(() => this.spinner.hide()); } - audioPlay(definition, cache) { + audioPlay(definition) { this.spinner.show(); - for (const key in cache) { - const audio = cache[key]; + for (const key in this.audioCache) { + const audio = this.audioCache[key]; if (audio !== null) { audio.pause(); } } - Display.audioBuildUrl(definition).then(url => { - let audio = cache[url]; + this.audioBuildUrl(definition).then(url => { + let audio = this.audioCache[url]; if (audio) { audio.currentTime = 0; audio.play(); @@ -206,23 +207,21 @@ class Display { audio = new Audio('/mixed/mp3/button.mp3'); } - cache[url] = audio; + this.audioCache[url] = audio; audio.play(); }; } }).catch(this.handleError.bind(this)).then(() => this.spinner.hide()); } - static entryIndexFind(element) { - return $('.entry').index(element.closest('.entry')); - } - - static adderButtonFind(index, mode) { - return $('.entry').eq(index).find(`.action-add-note[data-mode="${mode}"]`); - } - - static audioBuildUrl(definition) { + audioBuildUrl(definition) { return new Promise((resolve, reject) => { + const response = this.resultCache[definition.expression]; + if (response) { + resolve(response); + return; + } + const data = { post: 'dictionary_reference', match_type: 'exact', @@ -235,10 +234,14 @@ class Display { } const xhr = new XMLHttpRequest(); - xhr.addEventListener('error', () => reject('failed to execute network request')); - xhr.addEventListener('load', () => resolve(xhr.responseText)); xhr.open('POST', 'https://www.japanesepod101.com/learningcenter/reference/dictionary_post'); xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); + xhr.addEventListener('error', () => reject('failed to execute network request')); + xhr.addEventListener('load', () => { + this.resultCache[definition.expression] = xhr.responseText; + resolve(xhr.responseText); + }); + xhr.send(params.join('&')); }).then(response => { const dom = new DOMParser().parseFromString(response, 'text/html'); @@ -270,30 +273,6 @@ class Display { }); } - static audioBuildUrlOld(definition) { - let kana = definition.reading; - let kanji = definition.expression; - - if (!kana && !kanji) { - return null; - } - - if (!kana && wanakana.isHiragana(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('&')}`; - } - static audioBuildFilename(definition) { if (!definition.reading && !definition.expression) { return null; @@ -309,4 +288,12 @@ class Display { return filename += '.mp3'; } + + static entryIndexFind(element) { + return $('.entry').index(element.closest('.entry')); + } + + static adderButtonFind(index, mode) { + return $('.entry').eq(index).find(`.action-add-note[data-mode="${mode}"]`); + } } From 633c5a64f77f6fc4ccd7d79683cbd90e374ae71e Mon Sep 17 00:00:00 2001 From: Alex Yatskov Date: Thu, 23 Mar 2017 19:54:36 -0700 Subject: [PATCH 3/5] wip --- ext/mixed/js/display.js | 41 +++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/ext/mixed/js/display.js b/ext/mixed/js/display.js index aa2b5be9..f8c419b4 100644 --- a/ext/mixed/js/display.js +++ b/ext/mixed/js/display.js @@ -23,7 +23,7 @@ class Display { this.container = container; this.definitions = []; this.audioCache = {}; - this.resultCache = {}; + this.responseCache = {}; this.sequence = 0; } @@ -168,20 +168,22 @@ class Display { const index = Display.entryIndexFind(link); const definition = this.definitions[index]; + let promise = Promise.resolve(); if (mode !== 'kanji') { - const url = Display.audioBuildUrlOld(definition); const filename = Display.audioBuildFilename(definition); - if (url && filename) { - definition.audio = {url, filename}; + if (filename) { + promise = this.audioBuildUrl(definition).then(url => definition.audio = {url, filename}); } } - this.definitionAdd(definition, mode).then(success => { - if (success) { - Display.adderButtonFind(index, mode).addClass('disabled'); - } else { - this.handleError('note could not be added'); - } + promise.then(() => { + return this.definitionAdd(definition, mode).then(success => { + if (success) { + Display.adderButtonFind(index, mode).addClass('disabled'); + } else { + this.handleError('note could not be added'); + } + }); }).catch(this.handleError.bind(this)).then(() => this.spinner.hide()); } @@ -189,13 +191,14 @@ class Display { this.spinner.show(); for (const key in this.audioCache) { - const audio = this.audioCache[key]; - if (audio !== null) { - audio.pause(); - } + this.audioCache[key].pause(); } this.audioBuildUrl(definition).then(url => { + if (!url) { + url = '/mixed/mp3/button.mp3'; + } + let audio = this.audioCache[url]; if (audio) { audio.currentTime = 0; @@ -216,7 +219,7 @@ class Display { audioBuildUrl(definition) { return new Promise((resolve, reject) => { - const response = this.resultCache[definition.expression]; + const response = this.responseCache[definition.expression]; if (response) { resolve(response); return; @@ -236,9 +239,9 @@ class Display { 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('failed to execute network request')); + xhr.addEventListener('error', () => reject('failed to scrape audio data')); xhr.addEventListener('load', () => { - this.resultCache[definition.expression] = xhr.responseText; + this.responseCache[definition.expression] = xhr.responseText; resolve(xhr.responseText); }); @@ -268,14 +271,12 @@ class Display { return entry.url; } } - - return '/mixed/mp3/button.mp3'; }); } static audioBuildFilename(definition) { if (!definition.reading && !definition.expression) { - return null; + return; } let filename = 'yomichan'; From 77b0487912de46e5fd027b5b7c4c9ee1f7d02f7f Mon Sep 17 00:00:00 2001 From: Alex Yatskov Date: Thu, 23 Mar 2017 20:03:50 -0700 Subject: [PATCH 4/5] wip --- ext/manifest.json | 2 +- ext/mixed/js/display.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ext/manifest.json b/ext/manifest.json index 30f33975..9c311b2f 100644 --- a/ext/manifest.json +++ b/ext/manifest.json @@ -1,7 +1,7 @@ { "manifest_version": 2, "name": "Yomichan", - "version": "1.1.6", + "version": "1.1.7", "description": "Japanese dictionary with Anki integration", "icons": {"16": "mixed/img/icon16.png", "48": "mixed/img/icon48.png", "128": "mixed/img/icon128.png"}, diff --git a/ext/mixed/js/display.js b/ext/mixed/js/display.js index f8c419b4..63620dc6 100644 --- a/ext/mixed/js/display.js +++ b/ext/mixed/js/display.js @@ -172,7 +172,7 @@ class Display { if (mode !== 'kanji') { const filename = Display.audioBuildFilename(definition); if (filename) { - promise = this.audioBuildUrl(definition).then(url => definition.audio = {url, filename}); + promise = this.audioBuildUrl(definition).then(url => definition.audio = {url, filename}).catch(() => {}); } } From 3a1959bfffcf869e65a55cdeb902fd3cbed21aa7 Mon Sep 17 00:00:00 2001 From: Alex Yatskov Date: Thu, 23 Mar 2017 20:07:22 -0700 Subject: [PATCH 5/5] updating license, distro script --- build_zip.sh | 2 +- ext/bg/legal.html | 33 --------------------------------- 2 files changed, 1 insertion(+), 34 deletions(-) diff --git a/build_zip.sh b/build_zip.sh index be34255d..fd4e494a 100755 --- a/build_zip.sh +++ b/build_zip.sh @@ -1,4 +1,4 @@ #!/bin/sh ZIP=yomichan.zip rm -f $ZIP -7z a $ZIP ./ext/* +7za a $ZIP ./ext/* diff --git a/ext/bg/legal.html b/ext/bg/legal.html index f3ca4e01..4b0a3649 100644 --- a/ext/bg/legal.html +++ b/ext/bg/legal.html @@ -24,39 +24,6 @@ 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 <http://www.gnu.org/licenses/>. - -

VLGothic License

-
-Copyright (c) 1990-2003 Wada Laboratory, the University of Tokyo.
-Copyright (c) 2003-2004 Electronic Font Open Laboratory (/efont/).
-Copyright (C) 2002-2013 M+ FONTS PROJECT
-Copyright (C) 2006-2013 Daisuke SUZUKI .
-Copyright (C) 2006-2013 Project Vine .
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright notice,
-this list of conditions and the following disclaimer.
-2. Redistributions in binary form must reproduce the above copyright notice,
-this list of conditions and the following disclaimer in the documentation
-and/or other materials provided with the distribution.
-3. Neither the name of the Wada Laboratory, the University of Tokyo nor
-the names of its contributors may be used to endorse or promote products
-derived from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY WADA LABORATORY, THE UNIVERSITY OF TOKYO AND
-CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
-NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE LABORATORY OR
-CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
-OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 

EDRDG License