Skip to content

Instantly share code, notes, and snippets.

@robjweiss
Forked from miere43/jisho-audio-downloader.js
Last active April 25, 2019 16:49
Show Gist options
  • Save robjweiss/aea91100964cbabe35cfb2e25d2db07d to your computer and use it in GitHub Desktop.
Save robjweiss/aea91100964cbabe35cfb2e25d2db07d to your computer and use it in GitHub Desktop.

About

Scripts to download audio from Jisho dictionary entries

Bookmarklet

The JavaScript can be stored in a browser bookmark, clicking the bookmark will initiate the download

Closure Compiled Bookmarklet

Functionally the same at the original bookmarklet, but optimized using Google's Closure Compiler

Userscript

Creates a "Download Audio" link below the "Play Audio" link on Jisho dictionary entries

Usage

Bookmarklet

Add a bookmark and set the URL as javascript: and then paste the closure compiled bookmarklet

Userscript

Add the userscript to your userscript manager

(function(){function l(g,h){var m=window.URL||window.webkitURL,b=new XMLHttpRequest,c=document.createElement("a");b.open("GET","https://cors-anywhere.herokuapp.com/"+g,!0);b.responseType="blob";b.onerror=function(){c.href=g;c.download=h;c.click()};b.onload=function(){c.href=m.createObjectURL(new Blob([b.response],{type:"application/octet-stream"}));c.download=h;c.click()};b.send()}for(var k=document.getElementsByTagName("audio"),e=0;e<k.length;++e){var a=k[e],d=a.id,f=a.nextElementSibling;f&&f.dataset&&f.dataset.id==d&&(a=a.children[0].src,d=(!d||7>d.length?"unknown":d.match("(?<=_)(.*?)(?=:)")[0])+(a&&0!==a.length?"."+a.split(".").pop(-1):""),l(a,d))}})();
(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 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?
}
const url = audioElement.children[0].src;
const fileName = getWordNameFromAudioID(audioID) + getFileExtension(url);
downloadFileWithFileName(url, fileName);
}
})();
// ==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);
}
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment