Refactor Amazon Invoice Downloader for improved functionality and clarity

This commit is contained in:
2026-02-10 23:56:18 +01:00
parent 021981befe
commit 0e4ca8d8eb

View File

@@ -1,36 +1,110 @@
var sleepInterval = 2200;
var sleep = 0;
/**
* Amazon Invoice Downloader
*
* Instructions:
* 1. Go to your Amazon orders page.
* 2. Open browser console (F12).
* 3. Paste this script and press Enter.
*/
function finda(txt) {
let finds = Array.from(document.querySelectorAll("a")).filter((el) =>
el.textContent.includes(txt)
);
console.log(txt + ": " + finds.length);
return finds;
}
async function downloadAmazonInvoices() {
const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms));
// Helper to find all "Invoice" dropdown buttons
function getInvoiceButtons() {
const triggers = Array.from(document.querySelectorAll("a, span, button")).filter(el => {
const text = el.textContent || "";
// Look for exact "Rechnung" text
const isMatch = text.trim() === "Rechnung";
const isClickable = el.tagName === "A" || el.tagName === "BUTTON" || el.closest("a") || el.classList.contains("a-declarative");
return isMatch && isClickable;
});
function downloada(txt) {
finda(txt).forEach((el, i, arr) => {
console.log(`Downloading ${txt}...`, el.href);
const link = document.createElement("a");
link.href = el.href;
link.target = "_blank";
link.download = "";
link.click();
});
}
finda("Rechnung").forEach((e, i, arr) => {
setTimeout(() => {
e.click();
console.log(i, e);
if (i === arr.length - 1) {
setTimeout(() => downloada("Rechnung 1"), 1000);
setTimeout(() => downloada("Rechnung 2"), 2000);
setTimeout(() => downloada("Rechnung 3"), 3000);
setTimeout(() => downloada("Rechnung 4"), 4000);
setTimeout(() => downloada("Rechnung 5"), 5000);
// Remove duplicates: if we found both a link and the span inside it,
// only keep the outer-most one to avoid clicking the same thing twice.
return triggers.filter(el => {
let parent = el.parentElement;
while (parent) {
if (triggers.includes(parent)) return false;
parent = parent.parentElement;
}
return true;
});
}
}, sleep);
sleep += sleepInterval;
});
const buttons = getInvoiceButtons();
console.log(`Found ${buttons.length} orders with invoices.`);
for (let i = 0; i < buttons.length; i++) {
console.log(`Processing order ${i + 1}/${buttons.length}...`);
const btn = buttons[i];
// Scroll into view to ensure clickability
btn.scrollIntoView({ block: "center" });
await sleep(200);
btn.click();
// Wait for the AJAX popover to load
await sleep(2000);
// Find links in the currently visible popover
const visiblePopover = Array.from(document.querySelectorAll(".a-popover")).find(p => p.style.visibility !== "hidden" && p.style.display !== "none");
const container = visiblePopover || document;
const popoverLinks = Array.from(container.querySelectorAll("a")).filter(el => {
const text = el.textContent.trim().toLowerCase();
const href = el.href.toLowerCase();
// Only include actual invoice downloads
// Matches "rechnung" (including "Rechnung 1") or URLs with "invoice.pdf"
// Excludes "Rechnung anfordern" (Request) and "Bestellübersicht" (Summary)
const isInvoiceText = text.startsWith("rechnung") || text.startsWith("invoice");
const isInvoiceUrl = href.includes("invoice.pdf");
const isBlacklisted = text.includes("anfordern") || text.includes("request") || text.includes("summary") || text.includes("übersicht");
return (isInvoiceText || isInvoiceUrl) && !isBlacklisted;
});
// Deduplicate links by URL to avoid downloading the same file twice
const uniqueLinks = [];
const seenUrls = new Set();
for (const link of popoverLinks) {
if (!seenUrls.has(link.href)) {
seenUrls.add(link.href);
uniqueLinks.push(link);
}
}
console.log(`Found ${uniqueLinks.length} actual invoices in popover.`);
for (const link of uniqueLinks) {
console.log(`Downloading: ${link.textContent.trim()}`, link.href);
// Create a temporary link to force proper browser behavior
// and ensure we don't navigate the main window away.
const a = document.createElement("a");
a.href = link.href;
a.target = "_blank"; // Open in new tab/background
a.download = ""; // Hint to download instead of opening
document.body.appendChild(a);
a.click();
// Clean up
setTimeout(() => document.body.removeChild(a), 100);
await sleep(500);
}
// Close the popover by clicking the close button if it exists, or clicking the button again
const closeButton = document.querySelector(".a-popover-header .a-button-close, .a-button-close");
if (closeButton) {
closeButton.click();
await sleep(200);
}
}
console.log("Finished processing all invoices.");
}
downloadAmazonInvoices();