Skip to content

Instantly share code, notes, and snippets.

@MikeRawding
Last active November 8, 2021 01:05
Show Gist options
  • Save MikeRawding/9826e5f736316e35b50b1b007209b7a5 to your computer and use it in GitHub Desktop.
Save MikeRawding/9826e5f736316e35b50b1b007209b7a5 to your computer and use it in GitHub Desktop.
Adds button to download all parts of an audio book from Overdrive.com
// ==UserScript==
// @name Overdrive Audio Book Downloader
// @namespace https://gist.github.com/MikeRawding
// @version 0.4
// @description Adds a button to download all parts of an audio book from listen.overdrive.com
// @author Mike Rawding
// @include *listen.overdrive.com*
// @icon https://www.overdrive.com/Content/img/icons/svg/overdrive-app-icon.svg
// @grant none
// ==/UserScript==
(() => {
'use strict';
const GM_addStyle = (css) => {
const style = document.getElementById("GM_addStyleBy8626") || (function() {
const style = document.createElement('style');
style.type = 'text/css';
style.id = "GM_addStyleBy8626";
document.head.appendChild(style);
return style;
})();
const sheet = style.sheet;
sheet.insertRule(css, (sheet.rules || sheet.cssRules || []).length);
}
GM_addStyle(".download-icon { width: 40px; padding-top: 20px; margin-left: 6px; height: 32px; cursor: pointer;}");
let downloadButton = null
const zeroPad = num => {
if (num < 10) {
return `0${num}`
} else {
return `${num}`
}
}
const download = async ({ filename, url }) => {
const response = await fetch(url)
if (response.status !== 200) {
throw new Error()
}
const blob = await response.blob()
const downloadUrl = await URL.createObjectURL(blob)
const link = document.createElement("a");
link.href = downloadUrl;
link.download = filename;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
const downloadAll = () => {
downloadButton.onclick = () => { }
window.bData.spine.forEach((part, index) => {
const url = `${window.location.origin}/${part.path}`
const filename = `${window.bData.title.main}-Part${zeroPad(index + 1)}`
download({ filename, url })
})
// Disable button for a moment so the user doesn't click twice
setTimeout(() => {
downloadButton.onclick = downloadAll
}, 2_000)
}
const createButton = () => {
const builderDiv = document.createElement('div')
builderDiv.innerHTML =
`
<div title="Download All Parts" class="menu-bar-shortcut menu-bar-shortcut-speedo" touch-action="none" style="touch-action: none;">
<svg viewBox="0 0 384 512" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="download-icon">
<g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<path d="M348.5 264l-148 148.5c-4.7 4.7-12.3 4.7-17 0L35.5 264c-4.7-4.7-4.7-12.3 0-17l7.1-7.1c4.7-4.7 12.3-4.7 17 0l115.4 116V44c0-6.6 5.4-12 12-12h10c6.6 0 12 5.4 12 12v311.9L324.4 240c4.7-4.7 12.3-4.7 17 0l7.1 7.1c4.7 4.6 4.7 12.2 0 16.9zM384 468v-8c0-6.6-5.4-12-12-12H12c-6.6 0-12 5.4-12 12v8c0 6.6 5.4 12 12 12h360c6.6 0 12-5.4 12-12z" stroke="#000000" stroke-width="3" stroke-linecap="round" class="icon-solid"></path>
</g>
</svg>
</div>
`.trim()
downloadButton = builderDiv.firstChild
downloadButton.onclick = downloadAll
return downloadButton
}
/**
* Adds download button
* Might outrun the rest of the dom,
* so keep retrying until the container is ready
*/
const addButton = () => {
const container = document.getElementsByClassName('nav-action-bar-right')
if (container && container[0]) {
container[0].appendChild(createButton())
} else {
setTimeout(addButton, 10)
}
}
addButton()
})();
@MikeRawding
Copy link
Author

MikeRawding commented Apr 22, 2021

v0.2

  1. Disable button while download in progress
  2. Change button to use down arrow icon in same group as other sit icons

@MikeRawding
Copy link
Author

v0.3

  1. Update favicon to correct URL

@MikeRawding
Copy link
Author

v0.4

  1. Update selector to use new css class name on since overdrive.com has changed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment