|
// ==UserScript== |
|
// @name Jisho Audio Downloader |
|
// @namespace http://miere.ru/ |
|
// @version 0.3 |
|
// @description Adds download audio button to Jisho.org pages which downloads word audio clips. |
|
// @author Vladislav <miere> Vorobiev, Rob Weiss |
|
// @match http://jisho.org/search/* |
|
// @match http://jisho.org/word/* |
|
// @grant none |
|
// ==/UserScript== |
|
|
|
(function() { |
|
'use strict'; |
|
function getWordNameFromAudioID(audioID) { |
|
if (!audioID || audioID.length < 7) return "unknown"; |
|
|
|
// audioID is of the format: audio_元気:げんき |
|
// The regex below grabs the kanji between the underscore and the semicolon |
|
const regex = '(?<=_)(.*?)(?=:)'; |
|
const match = audioID.match(regex); |
|
return match[0]; |
|
} |
|
|
|
function getFileExtension(file) { |
|
if (!file || file.length === 0) return ""; |
|
|
|
// Splits the file url and gets the extension |
|
const fileExtension = '.' + file.split('.').pop(-1); |
|
return fileExtension; |
|
} |
|
|
|
function insertNodeAfter(insertNode, afterNode) { |
|
afterNode.parentNode.insertBefore(insertNode, afterNode.nextSibling); |
|
} |
|
|
|
function downloadFileWithFileName(url, fileName) { |
|
const URL = window.URL || window.webkitURL; |
|
|
|
const xhr = new XMLHttpRequest() |
|
const a = document.createElement('a') |
|
|
|
// The server the audio files are hosted on does not have different origin policy |
|
// This proxy server will append an appropriate header to the response, allowing the browser to load it |
|
const proxy = 'https://cors-anywhere.herokuapp.com/'; |
|
|
|
xhr.open('GET', proxy + url, true); |
|
xhr.responseType = 'blob'; |
|
xhr.onerror = function() { |
|
a.href = url; |
|
a.download = fileName; |
|
a.click(); |
|
}; |
|
xhr.onload = function() { |
|
const file = new Blob([xhr.response], { type : 'application/octet-stream' }); |
|
a.href = URL.createObjectURL(file); |
|
a.download = fileName; |
|
a.click(); |
|
}; |
|
xhr.send(); |
|
} |
|
|
|
const audioElements = document.getElementsByTagName('audio'); |
|
for (let i = 0; i < audioElements.length; ++i) { |
|
const audioElement = audioElements[i]; |
|
const audioID = audioElement.id; |
|
const audioLinkElement = audioElement.nextElementSibling; |
|
if (!audioLinkElement || !audioLinkElement.dataset || audioLinkElement.dataset.id != audioID) { |
|
continue; // @TODO: Site layout has changed, skip this or show alert? |
|
} |
|
let downloadAudioElement = document.createElement('a'); |
|
downloadAudioElement.className = 'concept_light-status_link'; |
|
downloadAudioElement.dataset.href = audioElement.children[0].src; |
|
downloadAudioElement.dataset.download = getWordNameFromAudioID(audioID) + getFileExtension(downloadAudioElement.dataset.href); |
|
downloadAudioElement.innerText = 'Download audio'; |
|
downloadAudioElement.addEventListener('click', function(ev) { |
|
downloadFileWithFileName(ev.target.dataset.href, ev.target.dataset.download); |
|
}); |
|
insertNodeAfter(downloadAudioElement, audioLinkElement); |
|
} |
|
})(); |