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:
parent
900bceda47
commit
0232325f96
@ -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"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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 = [];
|
||||||
|
@ -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 = (
|
||||||
|
@ -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');
|
|
||||||
}
|
|
||||||
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}];
|
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',
|
||||||
|
@ -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>
|
||||||
|
@ -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: {
|
||||||
|
Loading…
Reference in New Issue
Block a user