Refactor json audio source (#1711)

* Move sources to the end of audio options object

* Add custom-json audio source type

* Add support for downloading custom-json

* Remove customSourceType
This commit is contained in:
toasted-nutbread 2021-05-26 20:38:15 -04:00 committed by GitHub
parent 900bceda47
commit 0232325f96
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 61 additions and 58 deletions

View File

@ -341,36 +341,17 @@
"type": "object", "type": "object",
"required": [ "required": [
"enabled", "enabled",
"sources",
"volume", "volume",
"autoPlay", "autoPlay",
"customSourceUrl", "customSourceUrl",
"customSourceType", "textToSpeechVoice",
"textToSpeechVoice" "sources"
], ],
"properties": { "properties": {
"enabled": { "enabled": {
"type": "boolean", "type": "boolean",
"default": true "default": true
}, },
"sources": {
"type": "array",
"items": {
"type": "string",
"enum": [
"jpod101",
"jpod101-alternate",
"jisho",
"text-to-speech",
"text-to-speech-reading",
"custom"
],
"default": "jpod101"
},
"default": [
"jpod101"
]
},
"volume": { "volume": {
"type": "number", "type": "number",
"minimum": 0, "minimum": 0,
@ -385,14 +366,28 @@
"type": "string", "type": "string",
"default": "" "default": ""
}, },
"customSourceType": {
"type": "string",
"enum": ["audio", "json"],
"default": "audio"
},
"textToSpeechVoice": { "textToSpeechVoice": {
"type": "string", "type": "string",
"default": "" "default": ""
},
"sources": {
"type": "array",
"items": {
"type": "string",
"enum": [
"jpod101",
"jpod101-alternate",
"jisho",
"text-to-speech",
"text-to-speech-reading",
"custom",
"custom-json"
],
"default": "jpod101"
},
"default": [
"jpod101"
]
} }
} }
}, },

View File

@ -1742,7 +1742,7 @@ class Backend {
return null; return null;
} }
const {sources, preferredAudioIndex, customSourceUrl, customSourceType} = details; const {sources, preferredAudioIndex, customSourceUrl} = details;
let data; let data;
let contentType; let contentType;
try { try {
@ -1754,7 +1754,6 @@ class Backend {
{ {
textToSpeechVoice: null, textToSpeechVoice: null,
customSourceUrl, customSourceUrl,
customSourceType,
binary: true, binary: true,
disableCache: true disableCache: true
} }

View File

@ -817,11 +817,25 @@ class OptionsUtil {
// Version 12 changes: // Version 12 changes:
// Changed sentenceParsing.enableTerminationCharacters to sentenceParsing.terminationCharacterMode. // Changed sentenceParsing.enableTerminationCharacters to sentenceParsing.terminationCharacterMode.
// Added {search-query} field marker. // Added {search-query} field marker.
// Updated audio.sources[] to change 'custom' into 'custom-json'.
// Removed audio.customSourceType.
await this._applyAnkiFieldTemplatesPatch(options, '/data/templates/anki-field-templates-upgrade-v12.handlebars'); await this._applyAnkiFieldTemplatesPatch(options, '/data/templates/anki-field-templates-upgrade-v12.handlebars');
for (const profile of options.profiles) { for (const profile of options.profiles) {
const {sentenceParsing} = profile.options; const {sentenceParsing, audio} = profile.options;
sentenceParsing.terminationCharacterMode = sentenceParsing.enableTerminationCharacters ? 'custom' : 'newlines'; sentenceParsing.terminationCharacterMode = sentenceParsing.enableTerminationCharacters ? 'custom' : 'newlines';
delete sentenceParsing.enableTerminationCharacters; delete sentenceParsing.enableTerminationCharacters;
const {sources, customSourceType} = audio;
audio.sources = sources.map((type) => {
switch (type) {
case 'custom':
return (customSourceType === 'json' ? 'custom-json' : 'custom');
default:
return type;
}
});
delete audio.customSourceType;
} }
return options; return options;
} }

View File

@ -116,7 +116,7 @@ class DisplayAudio {
const {term, reading} = headword; const {term, reading} = headword;
const audioOptions = this._getAudioOptions(); const audioOptions = this._getAudioOptions();
const {textToSpeechVoice, customSourceUrl, customSourceType, volume} = audioOptions; const {textToSpeechVoice, customSourceUrl, volume} = audioOptions;
if (!Array.isArray(sources)) { if (!Array.isArray(sources)) {
({sources} = audioOptions); ({sources} = audioOptions);
} }
@ -131,7 +131,7 @@ class DisplayAudio {
let audio; let audio;
let title; let title;
let source = null; let source = null;
const info = await this._createTermAudio(sources, sourceDetailsMap, term, reading, {textToSpeechVoice, customSourceUrl, customSourceType}); const info = await this._createTermAudio(sources, sourceDetailsMap, term, reading, {textToSpeechVoice, customSourceUrl});
const valid = (info !== null); const valid = (info !== null);
if (valid) { if (valid) {
({audio, source} = info); ({audio, source} = info);
@ -518,7 +518,8 @@ class DisplayAudio {
['jisho', 'Jisho.org', true], ['jisho', 'Jisho.org', true],
['text-to-speech', 'Text-to-speech', ttsSupported], ['text-to-speech', 'Text-to-speech', ttsSupported],
['text-to-speech-reading', 'Text-to-speech (Kana reading)', ttsSupported], ['text-to-speech-reading', 'Text-to-speech (Kana reading)', ttsSupported],
['custom', 'Custom', customSupported] ['custom', 'Custom URL', customSupported],
['custom-json', 'Custom URL (JSON)', customSupported]
]; ];
const results = []; const results = [];

View File

@ -1554,7 +1554,7 @@ class Display extends EventDispatcher {
async _injectAnkiNoteMedia(dictionaryEntry, options, fields) { async _injectAnkiNoteMedia(dictionaryEntry, options, fields) {
const { const {
anki: {screenshot: {format, quality}}, anki: {screenshot: {format, quality}},
audio: {sources, customSourceUrl, customSourceType} audio: {sources, customSourceUrl}
} = options; } = options;
const timestamp = Date.now(); const timestamp = Date.now();
@ -1570,7 +1570,7 @@ class Display extends EventDispatcher {
sources2 = [primaryCardAudio.source]; sources2 = [primaryCardAudio.source];
preferredAudioIndex = primaryCardAudio.index; preferredAudioIndex = primaryCardAudio.index;
} }
audioDetails = {sources: sources2, preferredAudioIndex, customSourceUrl, customSourceType}; audioDetails = {sources: sources2, preferredAudioIndex, customSourceUrl};
} }
const screenshotDetails = ( const screenshotDetails = (

View File

@ -33,7 +33,8 @@ class AudioDownloader {
['jisho', this._getInfoJisho.bind(this)], ['jisho', this._getInfoJisho.bind(this)],
['text-to-speech', this._getInfoTextToSpeech.bind(this)], ['text-to-speech', this._getInfoTextToSpeech.bind(this)],
['text-to-speech-reading', this._getInfoTextToSpeechReading.bind(this)], ['text-to-speech-reading', this._getInfoTextToSpeechReading.bind(this)],
['custom', this._getInfoCustom.bind(this)] ['custom', this._getInfoCustom.bind(this)],
['custom-json', this._getInfoCustomJson.bind(this)]
]); ]);
} }
@ -191,22 +192,14 @@ class AudioDownloader {
return [{type: 'tts', text: reading, voice: textToSpeechVoice}]; return [{type: 'tts', text: reading, voice: textToSpeechVoice}];
} }
async _getInfoCustom(term, reading, {customSourceUrl, customSourceType}) { async _getInfoCustom(term, reading, {customSourceUrl}) {
if (typeof customSourceUrl !== 'string') { const url = this._getCustomUrl(term, reading, customSourceUrl);
throw new Error('No custom URL defined'); return [{type: 'url', url}];
}
const data = {term, reading};
const url = customSourceUrl.replace(/\{([^}]*)\}/g, (m0, m1) => (Object.prototype.hasOwnProperty.call(data, m1) ? `${data[m1]}` : m0));
switch (customSourceType) {
case 'json':
return await this._getInfoCustomJson(url);
default:
return [{type: 'url', url}];
}
} }
async _getInfoCustomJson(url) { async _getInfoCustomJson(term, reading, {customSourceUrl}) {
const url = this._getCustomUrl(term, reading, customSourceUrl);
const response = await this._requestBuilder.fetchAnonymous(url, { const response = await this._requestBuilder.fetchAnonymous(url, {
method: 'GET', method: 'GET',
mode: 'cors', mode: 'cors',
@ -237,6 +230,14 @@ class AudioDownloader {
return results; return results;
} }
_getCustomUrl(term, reading, customSourceUrl) {
if (typeof customSourceUrl !== 'string') {
throw new Error('No custom URL defined');
}
const data = {term, reading};
return customSourceUrl.replace(/\{([^}]*)\}/g, (m0, m1) => (Object.prototype.hasOwnProperty.call(data, m1) ? `${data[m1]}` : m0));
}
async _downloadAudioFromUrl(url, source) { async _downloadAudioFromUrl(url, source) {
const response = await this._requestBuilder.fetchAnonymous(url, { const response = await this._requestBuilder.fetchAnonymous(url, {
method: 'GET', method: 'GET',

View File

@ -2398,13 +2398,6 @@
</div> </div>
<div class="settings-item-right"> <div class="settings-item-right">
<div class="settings-item-group"> <div class="settings-item-group">
<div class="settings-item-group-item">
<div class="settings-item-group-item-label">Type</div>
<select class="short-width short-height" data-setting="audio.customSourceType">
<option value="audio">Audio</option>
<option value="json">JSON</option>
</select>
</div>
<div class="settings-item-group-item"> <div class="settings-item-group-item">
<div class="settings-item-group-item-label">URL</div> <div class="settings-item-group-item-label">URL</div>
<input class="short-height" type="text" spellcheck="false" autocomplete="off" data-setting="audio.customSourceUrl" placeholder="None"> <input class="short-height" type="text" spellcheck="false" autocomplete="off" data-setting="audio.customSourceUrl" placeholder="None">
@ -2483,7 +2476,8 @@
<option value="jisho">Jisho.org</option> <option value="jisho">Jisho.org</option>
<option value="text-to-speech">Text-to-speech</option> <option value="text-to-speech">Text-to-speech</option>
<option value="text-to-speech-reading">Text-to-speech (Kana reading)</option> <option value="text-to-speech-reading">Text-to-speech (Kana reading)</option>
<option value="custom">Custom</option> <option value="custom">Custom URL</option>
<option value="custom-json">Custom URL (JSON)</option>
</select> </select>
<button class="icon-button audio-source-menu-button" data-menu="audio-source-menu" data-menu-position="below left"><span class="icon-button-inner"><span class="icon" data-icon="kebab-menu"></span></span></button> <button class="icon-button audio-source-menu-button" data-menu="audio-source-menu" data-menu-position="below left"><span class="icon-button-inner"><span class="icon" data-icon="kebab-menu"></span></span></button>
</div></template> </div></template>

View File

@ -310,7 +310,6 @@ function createProfileOptionsUpdatedTestData1() {
volume: 100, volume: 100,
autoPlay: false, autoPlay: false,
customSourceUrl: 'http://localhost/audio.mp3?term={term}&reading={reading}', customSourceUrl: 'http://localhost/audio.mp3?term={term}&reading={reading}',
customSourceType: 'audio',
textToSpeechVoice: '' textToSpeechVoice: ''
}, },
scanning: { scanning: {