✨ Refactor Amazon Invoice Downloader for improved functionality and clarity ✨
This commit is contained in:
@@ -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();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user