您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Copies audiobook metadata to JSON and opens MAM upload page. Updated from DrBlank's script to work on pages that have a banner at the top.
当前为
// ==UserScript== // @name Improved Audiobook Metadata // @namespace https://greasyfork.org/en/users/your-namespace // @version 1.0.2 // @license MIT // @description Copies audiobook metadata to JSON and opens MAM upload page. Updated from DrBlank's script to work on pages that have a banner at the top. // @author SnowmanNurse (Inspired by script by DrBlank) // @include https://www.audible.com/pd/* // @include https://www.audible.in/pd/* // @include https://www.audible.com/ac/* // @include https://www.audible.in/ac/* // @grant none // ==/UserScript== const RIPPER = "Libation"; // yours can be InAudible or Blank if Encoded const CHAPTERIZED = true; // yours will be false if not properly ripped const AVAILABLE_CATEGORIES = [ "Art", "Biographical", "Business", "Crafts", "Fantasy", "Food", "History", "Horror", "Humor", "Instructional", "Juvenile", "Language", "Medical", "Mystery", "Nature", "Philosophy", "Recreation", "Romance", "Self-Help", "Western", "Young Adult", "Historical Fiction", "Literary Classics", "Science Fiction", "True Crime", "Urban Fantasy", "Action/Adventure", "Computer/Internet", "Crime/Thriller", "Home/Garden", "Math/Science/Tech", "Travel/Adventure", "Pol/Soc/Relig", "General Fiction", "General Non-Fic", ]; function cleanName(name) { const titlesToRemove = [ "PhD", "MD", "JD", "MBA", "MA", "MS", "MSc", "MFA", "MEd", "MPH", "LLM", "DDS", "DVM", "EdD", "PsyD", "ThD", "DO", "PharmD", "DSc", "DBA", "RN", "CPA", "Esq.", "LCSW", "PE", "AIA", "FAIA", "CSP", "CFP", "Jr.", "Sr.", "I", "II", "III", "IV", "Dr.", "Mr.", "Mrs.", "Ms.", "Prof.", "Rev.", "Fr.", "Sr.", "Capt.", "Col.", "Gen.", "Lt.", "Cmdr.", "Adm.", "Sir", "Dame", "Hon.", "Amb.", "Gov.", "Sen.", "Rep." ]; let cleanedName = name.trim(); titlesToRemove.forEach(title => { const regexBefore = new RegExp(`^${title}\\s+`, 'i'); const regexAfter = new RegExp(`\\s*,?\\s*${title}$`, 'i'); cleanedName = cleanedName.replace(regexBefore, '').replace(regexAfter, ''); }); return cleanedName.trim(); } function cleanSeriesName(seriesName) { const wordsToRemove = ["series", "an", "the", "novel"]; let cleanedName = seriesName.toLowerCase(); wordsToRemove.forEach(word => { const regex = new RegExp(`\\b${word}\\b`, 'gi'); cleanedName = cleanedName.replace(regex, ''); }); // Remove extra spaces and trim cleanedName = cleanedName.replace(/\s+/g, ' ').trim(); // Capitalize the first letter of each word return cleanedName.replace(/\b\w/g, l => l.toUpperCase()); } function copyToClipboard(text) { navigator.clipboard.writeText(text).then(function () { console.log('Copied to clipboard successfully!'); window.open("https://www.myanonamouse.net/tor/upload.php", "_blank"); }, function (err) { console.error('Could not copy text: ', err); alert('Failed to copy metadata. Please check the console for errors.'); }); } function getLanguage() { let languageElement = document.querySelector(".languageLabel"); let patt = /\s*(\w+)$/g; let matches = patt.exec(languageElement.innerHTML.trim()); return matches[1]; } function getSeriesName() { let series = ""; let seriesElement = document.querySelector(".seriesLabel"); if (seriesElement) { series = seriesElement.querySelector("a").innerHTML; series = cleanSeriesName(series); } return series; } function getSeriesBookNumber() { let bookNumber = ""; if (!getSeriesName()) { return ""; } let seriesElement = document.querySelector(".seriesLabel"); let patt = /Book\s*?(\d+\.?\d*-?\d*\.?\d*)/g; bookNumber = patt.exec(seriesElement.innerHTML); if (!bookNumber) { return ""; } return bookNumber[1]; } function getSeries() { let seriesName = getSeriesName(); if (seriesName) { let bookNumber = getSeriesBookNumber(); return [{ name: seriesName, number: bookNumber }]; } return []; } function getAudibleCategory() { let categoryElement = document.querySelector(".categoriesLabel"); if (categoryElement) return categoryElement.innerText; categoryElement = document.querySelector("nav.bc-breadcrumb"); if (categoryElement) return categoryElement.innerText; return ""; } function getMAMCategory() { let audibleCategory = getAudibleCategory().toLowerCase(); let guesses = []; AVAILABLE_CATEGORIES.forEach((category) => { if (audibleCategory.includes(category.toLowerCase())) { guesses.push(`Audiobooks - ${category}`); return; } let separators = ["/", " "]; separators.forEach((separator) => { let splits = category.split(separator); splits.forEach((split) => { if (audibleCategory.includes(split.toLowerCase())) { guesses.push(`Audiobooks - ${category}`); return; } }); }); }); if (guesses.length) return guesses[0]; return ""; } function getTitle() { let title = document.getElementsByTagName("h1")[0].innerText; return title; } function getSubtitle() { let sLoggedIn = document.querySelector(".subtitle"); let sLoggedOut = document.querySelector("span.bc-size-medium"); let subtitle = ""; if (sLoggedIn) { subtitle = sLoggedIn.innerText; } else if (sLoggedOut) { subtitle = sLoggedOut.innerText; } if (!subtitle) return ""; if (subtitle.trim() === "+More") return ""; let series = getSeriesName().toLowerCase(); let isSubtitleSeries = Boolean( series && subtitle.toLocaleLowerCase().includes(series) ); if (isSubtitleSeries) return ""; return subtitle; } function getTitleAndSubtitle() { let subtitle = getSubtitle(); if (subtitle) { return `${getTitle()}: ${subtitle}`; } return getTitle(); } function getReleaseDate() { let element = document.querySelector(".releaseDateLabel"); let patt = /\d{2}-\d{2}-\d{2}/; let matches = patt.exec(element.innerText); return matches ? matches[0] : ""; } function getPublisher() { let publisherElement = document.querySelector(".publisherLabel>a"); return publisherElement ? publisherElement.innerText : "Unknown Publisher"; } function getRunTime() { let runtimeElement = document.querySelector(".runtimeLabel"); let runtime = runtimeElement ? runtimeElement.textContent : "Unknown"; let patt = new RegExp("Length:\\n\\s+(\\d[^\n]+)"); let matches = patt.exec(runtime); return matches ? matches[1] : "Unknown"; } function getAdditionalTags() { let tags = []; tags.push(`Duration: ${getRunTime()}`); if (CHAPTERIZED) tags.push("Chapterized"); if (RIPPER) tags.push(RIPPER); tags.push(`Audible Release: ${getReleaseDate()}`); tags.push(`Publisher: ${getPublisher()}`); tags.push(getAudibleCategory()); return tags.join(" | "); } function generateJson() { var authorElements = document.querySelectorAll(".authorLabel a"); var authors = []; for (let index = 0; index < authorElements.length; index++) { if (authorElements[index]) { let authorName = authorElements[index].innerHTML.replace(/ - (foreword|afterword|translator|editor)/gi, ""); authorName = cleanName(authorName); authors.push(authorName); } } var narratorElements = document.querySelectorAll(".narratorLabel a"); var narrators = []; for (let index = 0; index < narratorElements.length; index++) { if (narratorElements[index]) { let narratorName = narratorElements[index].innerHTML; narratorName = cleanName(narratorName); narrators.push(narratorName); } } var imgElement = document.querySelector(".bc-image-inset-border"); var imageSrc = imgElement ? imgElement.src : "No image available"; var descriptionElement = document.querySelector(".productPublisherSummary>div>div>span") || document.querySelector("div.bc-col-6 span.bc-text") || document.querySelector("div.bc-text.bc-color-secondary"); var description = descriptionElement ? descriptionElement.innerHTML : "No description available"; description = description.replace(/\s+/g, " ").replace(/"/g, '\\"').replace(/<p><\/p>/g, "").replace(/<\/p>/g, "</p><br>").replace(/<\/ul>/g, "</ul><br>"); var json = { "authors": authors, "description": description, "narrators": narrators, "tags": getAdditionalTags(), "thumbnail": imageSrc, "title": getTitleAndSubtitle(), "language": getLanguage(), "series": getSeries(), "category": getMAMCategory(), }; var strJson = JSON.stringify(json); copyToClipboard(strJson); } function addButton() { let buttonContainer = document.createElement("div"); buttonContainer.innerHTML = ` <div style="position:fixed;bottom:10px;right:10px;z-index:9999"> <button id="copyMetadataButton" style="padding:10px;background-color:#008CBA;color:white;border:none;border-radius:5px;font-size:14px;"> Copy Metadata & Open MAM </button> </div>`; document.body.appendChild(buttonContainer); document.getElementById("copyMetadataButton").addEventListener("click", function (event) { event.preventDefault(); generateJson(); }); } window.onload = function () { addButton(); };