|
// ==UserScript== |
|
// @name π Amazon Kindle Downloader |
|
// @namespace http://tampermonkey.net |
|
// @version 1.0.0 |
|
// @description π₯ Save hours by automating Kindle book downloads with a click of a button! |
|
// @author Nicholas Adamou (nicholasadamou.com) |
|
// @match https://www.amazon.com/hz/mycd/digital-console/contentlist/booksAll/dateDsc/* |
|
// @icon https://www.google.com/s2/favicons?sz=64&domain=amazon.com |
|
// @grant GM_xmlhttpRequest |
|
// @grant GM_addStyle |
|
// @run-at document-idle |
|
// @license MIT |
|
// ==/UserScript== |
|
|
|
(function () { |
|
'use strict'; |
|
|
|
console.log("π Kindle Downloader Script Loaded"); |
|
|
|
/** |
|
* Pauses execution for a specified duration. |
|
* @param {number} [duration=1000] - Duration to pause in milliseconds. |
|
* @returns {Promise<void>} A promise that resolves after the specified duration. |
|
*/ |
|
function pause(duration = 1000) { |
|
return new Promise(resolve => setTimeout(resolve, duration)); |
|
} |
|
|
|
/** |
|
* Closes any active notification popups on the page. |
|
*/ |
|
function closeNotification() { |
|
const closeNote = document.querySelector("span#notification-close"); |
|
if (closeNote) { |
|
closeNote.click(); |
|
console.log("π Closed notification."); |
|
} |
|
} |
|
|
|
/** |
|
* Initiates the download process for all books on the current page. |
|
*/ |
|
async function downloadBooksOnPage() { |
|
const menus = Array.from( |
|
document.querySelectorAll('div[class*="Dropdown-module_dropdown_container"]') |
|
).map(container => |
|
Array.from(container.children).find(child => child.innerHTML.includes("DOWNLOAD_AND_TRANSFER_DIALOG")) |
|
).filter(Boolean); |
|
|
|
for (const menu of menus) { |
|
try { |
|
const dialog = menu.querySelector("div[id^='DOWNLOAD_AND_TRANSFER_DIALOG_']"); |
|
if (!dialog) { |
|
console.warn("β οΈ No dialog found for menu."); |
|
continue; |
|
} |
|
|
|
const parts = dialog.id.split("_"); |
|
const asin = parts[parts.length - 1]; |
|
console.log(`π Processing book: ASIN ${asin}`); |
|
|
|
menu.click(); |
|
await pause(500); |
|
|
|
const inputSelector = `ul#download_and_transfer_list_${asin} li[class^='ActionList-module_action_list_item__'] > div > label`; |
|
const input = document.querySelector(inputSelector); |
|
if (!input) { |
|
console.warn(`β οΈ No download option found for ASIN ${asin}`); |
|
continue; |
|
} |
|
input.click(); |
|
await pause(500); |
|
|
|
const buttonSelector = `div[id^='DOWNLOAD_AND_TRANSFER_DIALOG_${asin}'] div[class^='DeviceDialogBox-module_button_container__'] > div[id$='_CONFIRM']`; |
|
const button = document.querySelector(buttonSelector); |
|
if (!button) { |
|
console.warn(`β οΈ No confirm button found for ASIN ${asin}`); |
|
continue; |
|
} |
|
button.click(); |
|
await pause(1000); |
|
|
|
closeNotification(); |
|
await pause(500); |
|
console.log(`β
Successfully triggered download for ASIN ${asin}`); |
|
} catch (error) { |
|
console.error(`β Error processing book ASIN ${asin}: ${error.message}`); |
|
} |
|
} |
|
} |
|
|
|
/** |
|
* Navigates to the next page of books if available. |
|
* @returns {Promise<boolean>} True if there is another page, false otherwise. |
|
*/ |
|
async function goToNextPage() { |
|
const currentPage = document.querySelector("a.page-item.active"); |
|
if (!currentPage) { |
|
console.warn("β οΈ Could not find the active page."); |
|
return false; |
|
} |
|
|
|
const nextPage = currentPage.nextElementSibling; |
|
if (nextPage && nextPage.classList.contains("page-item")) { |
|
console.log("β‘οΈ Navigating to the next page..."); |
|
nextPage.click(); |
|
await pause(5000); |
|
return true; |
|
} else { |
|
console.log("π No more pages to process."); |
|
return false; |
|
} |
|
} |
|
|
|
/** |
|
* Starts the book download process across all pages. |
|
*/ |
|
async function startDownloadProcess() { |
|
console.log("π₯ Downloading books from the current page..."); |
|
while (true) { |
|
await downloadBooksOnPage(); |
|
const hasNext = await goToNextPage(); |
|
if (!hasNext) break; |
|
} |
|
console.log("π Script completed. All books processed."); |
|
} |
|
|
|
/** |
|
* Adds a button to the webpage to trigger the download process. |
|
*/ |
|
function addDownloadButton() { |
|
const button = document.createElement('button'); |
|
button.innerText = 'Download Kindle Books'; |
|
button.style.position = 'fixed'; |
|
button.style.top = '20px'; |
|
button.style.right = '20px'; |
|
button.style.padding = '10px'; |
|
button.style.fontSize = '16px'; |
|
button.style.backgroundColor = '#4CAF50'; |
|
button.style.color = 'white'; |
|
button.style.border = 'none'; |
|
button.style.borderRadius = '5px'; |
|
button.style.cursor = 'pointer'; |
|
button.style.zIndex = 9999; |
|
button.addEventListener('click', startDownloadProcess); |
|
|
|
document.body.appendChild(button); |
|
} |
|
|
|
window.addEventListener('load', addDownloadButton); |
|
|
|
GM_addStyle(` |
|
button { |
|
font-family: Arial, sans-serif; |
|
box-shadow: 0px 4px 6px rgba(0, 0, 0, 0.1); |
|
} |
|
`); |
|
})(); |