您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Download video and bulk images from myreadingmanga manga/doujin page.
当前为
- // ==UserScript==
- // @name MRM Downloader
- // @namespace https://nyt92.eu.org
- // @version 2025-1-27
- // @description Download video and bulk images from myreadingmanga manga/doujin page.
- // @author nyt92
- // @match https://myreadingmanga.info/*
- // @exclude https://myreadingmanga.info/about/
- // @exclude https://myreadingmanga.info/cats/*
- // @exclude https://myreadingmanga.info/pairing/*
- // @exclude https://myreadingmanga.info/group/*
- // @exclude https://myreadingmanga.info/privacy-policy/
- // @exclude https://myreadingmanga.info/dmca-notice/
- // @exclude https://myreadingmanga.info/contact/
- // @exclude https://myreadingmanga.info/terms-service/
- // @exclude https://myreadingmanga.info/sitemap/
- // @exclude https://myreadingmanga.info/my-bookmark/
- // @exclude https://myreadingmanga.info/tag/*
- // @exclude https://myreadingmanga.info/genre/*
- // @exclude https://myreadingmanga.info/status/*
- // @exclude https://myreadingmanga.info/lang/*
- // @exclude https://myreadingmanga.info/yaoi-manga/*
- // @exclude https://myreadingmanga.info/manhwa/*
- // @connect myreadingmanga.info
- // @connect i1.myreadingmanga.info
- // @connect i2.myreadingmanga.info
- // @connect i3.myreadingmanga.info
- // @connect i4.myreadingmanga.info
- // @connect i5.myreadingmanga.info
- // @connect i6.myreadingmanga.info
- // @supportURL https://github.com/NYT92/mrm-downloader
- // @icon https://www.google.com/s2/favicons?sz=64&domain=myreadingmanga.info
- // @require https://cdnjs.cloudflare.com/ajax/libs/jszip/3.7.1/jszip.min.js
- // @require https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/2.0.5/FileSaver.min.js
- // @grant GM_xmlhttpRequest
- // @license GPLv3
- // ==/UserScript==
- // THIS USERSCRIPT IS LICENSE UNDER THE GPLv3 License
- (function () {
- ("use strict");
- function saveCookies() {
- const cookies = prompt("Please paste your cookies here:");
- if (cookies) {
- localStorage.setItem("mrm_cookies", cookies);
- alert("Cookies saved!");
- window.location.reload();
- }
- }
- const cookiesBtn = document.createElement("button");
- cookiesBtn.id = "saveCookiesBtn";
- cookiesBtn.textContent = "Load 🍪";
- cookiesBtn.style.cssText =
- "position: fixed; bottom: 10px; right: 10px; z-index: 9999;";
- document.body.appendChild(cookiesBtn);
- cookiesBtn.addEventListener("click", saveCookies);
- const title =
- document
- .querySelector(".entry-header h1.entry-title")
- ?.textContent.trim() || "Untitled";
- const imageDlBtn = document.createElement("button");
- imageDlBtn.id = "downloadImagesBtn";
- imageDlBtn.textContent = "Download Images (.zip)";
- imageDlBtn.style.cssText =
- "position: fixed; top: 10px; right: 10px; z-index: 9999;";
- const videoDlBtn = document.createElement("button");
- videoDlBtn.id = "downloadVideoBtn";
- videoDlBtn.textContent = "Download Video";
- videoDlBtn.style.cssText =
- "position: fixed; top: 10px; right: 10px; z-index: 9999;";
- const progressBar = document.createElement("div");
- progressBar.id = "downloadProgress";
- progressBar.style.cssText =
- "position: fixed; top:120px; right: 10px; width: 235px; right: 10px; height: 20px; background-color: #f0f0f0; display: none; z-index: 9999;";
- const progressInner = document.createElement("div");
- progressInner.style.cssText =
- "width: 0%; height: 100%; background-color: #4CAF50; transition: width 0.5s;";
- progressBar.appendChild(progressInner);
- const progressText = document.createElement("div");
- progressText.style.cssText =
- "position: fixed; top: 145px; right: 10px; z-index: 9999; display: none;";
- progressText.textContent = "Preparing download...";
- const checkIfVid = document.querySelectorAll(".entry-categories a");
- if (!checkIfVid) {
- console.log("no media found!");
- } else if (document.querySelector("#MRM_video") !== null) {
- document.body.appendChild(videoDlBtn);
- } else if (document.querySelector(".img-myreadingmanga") !== null) {
- document.body.appendChild(imageDlBtn);
- }
- document.body.appendChild(progressBar);
- document.body.appendChild(progressText);
- console.log(
- "Info: Cookies are required for this script to work due to browser limitations and Cloudflare protection. See https://github.com/NYT92/mrm-downloader/tree/main?tab=readme-ov-file#using-the-script for more information."
- );
- const savedCookies = localStorage.getItem("mrm_cookies");
- const lastAlertTime = localStorage.getItem("mrm_last_alert");
- const ONE_WEEK = 7 * 24 * 60 * 60 * 1000;
- if (!savedCookies) {
- const currentTime = Date.now();
- if (!lastAlertTime || currentTime - parseInt(lastAlertTime) > ONE_WEEK) {
- alert(
- "Please set the cookies first before downloading images. See https://github.com/NYT92/mrm-downloader/tree/main?tab=readme-ov-file#using-the-script for more information. This alert will only shown once per week"
- );
- localStorage.setItem("mrm_last_alert", currentTime.toString());
- }
- imageDlBtn.style.display = "none";
- videoDlBtn.style.display = "none";
- return;
- }
- const cookiesValue = savedCookies || "";
- imageDlBtn.addEventListener("click", function () {
- imageDlBtn.disabled = true;
- imageDlBtn.textContent = "Downloading...";
- const images = document.querySelectorAll(".img-myreadingmanga");
- let imageSources = [];
- imageSources = Array.from(images)
- .map((img) => img.dataset.src)
- .filter(Boolean);
- if (imageSources.length === 0) {
- imageSources = Array.from(images)
- .map((img) => img.src)
- .filter(Boolean);
- }
- if (imageSources.length === 0) {
- const nestedImages = document.querySelectorAll(".img-myreadingmanga img");
- imageSources = Array.from(nestedImages)
- .map((img) => img.src || img.dataset.src)
- .filter(Boolean);
- }
- if (imageSources.length === 0) {
- alert(
- "No images found on this page. Check the console for debugging information."
- );
- imageDlBtn.disabled = false;
- imageDlBtn.textContent = "Download Images (.zip)";
- return;
- }
- const pageElement = document.querySelector(".post-page-numbers.current");
- const page = pageElement ? pageElement.textContent.trim() : "1";
- const zip = new JSZip();
- progressBar.style.display = "block";
- progressText.style.display = "block";
- progressInner.style.width = "0%";
- function getExtensionFromMimeType(mimeType) {
- const mimeToExt = {
- "image/jpeg": "jpg",
- "image/png": "png",
- "image/gif": "gif",
- "image/webp": "webp",
- "image/jpg": "jpg",
- "text/html": "html",
- };
- return mimeToExt[mimeType.toLowerCase()];
- }
- function addImageToZip(src, index) {
- return new Promise((resolve, reject) => {
- progressText.textContent = `Downloading image ${index + 1} of ${
- imageSources.length
- }...`;
- GM_xmlhttpRequest({
- method: "GET",
- url: src,
- headers: {
- Cookie: cookiesValue,
- },
- responseType: "arraybuffer",
- onload: function (response) {
- try {
- const arrayBuffer = response.response;
- const byteArray = new Uint8Array(arrayBuffer);
- let mimeType = "image/jpeg";
- try {
- const contentTypeMatch = response.responseHeaders.match(
- /Content-Type:\s*(\S+)/i
- );
- if (contentTypeMatch && contentTypeMatch[1]) {
- mimeType = contentTypeMatch[1];
- }
- } catch (headerError) {
- console.warn(
- `Could not parse Content-Type header for ${src}:`,
- headerError
- );
- }
- const blob = new Blob([byteArray], { type: mimeType });
- if (blob.type.includes("text/html")) {
- alert(
- "The script have detected the Cloudflare is blocking the page. You need to re-enter the cookies info due to Cloudflare resetting the cookies or the cookies is expired. See https://github.com/NYT92/mrm-downloader/tree/main?tab=readme-ov-file#using-the-script for more information."
- );
- reject(new Error("Invalid cookies"));
- window.location.reload();
- } else {
- const ext = getExtensionFromMimeType(blob.type);
- const fileName = `image_${index + 1}.${ext}`;
- zip.file(fileName, blob, { binary: true });
- console.log(
- `Added ${fileName} to ZIP (${blob.size} bytes, type: ${blob.type})`
- );
- const progress = ((index + 1) / imageSources.length) * 100;
- progressInner.style.width = `${progress}%`;
- resolve();
- }
- } catch (error) {
- console.error(`Error processing ${src}:`, error);
- reject(error);
- }
- },
- onerror: function (error) {
- console.error(`Error fetching ${src}:`, error);
- reject(error);
- },
- });
- });
- }
- Promise.all(imageSources.map(addImageToZip))
- .then(() => {
- progressText.textContent = "Creating ZIP file...";
- return zip.generateAsync({ type: "blob" });
- })
- .then(function (content) {
- const safeTitle = title.replace(/[^a-z0-9]/gi, "_").toLowerCase();
- const fileName = `${safeTitle}_ch${page}.zip`;
- saveAs(content, fileName);
- console.log("ZIP file saved successfully");
- progressBar.style.display = "none";
- progressText.style.display = "none";
- imageDlBtn.disabled = false;
- imageDlBtn.textContent = "Download Images (.zip)";
- })
- .catch((error) => {
- console.error("Error creating ZIP file:", error);
- alert(
- "An error occurred while creating the ZIP file. Please check the console for details."
- );
- progressBar.style.display = "none";
- progressText.style.display = "none";
- imageDlBtn.disabled = false;
- imageDlBtn.textContent = "Download Images (.zip)";
- });
- });
- videoDlBtn.addEventListener("click", function () {
- videoDlBtn.disabled = true;
- videoDlBtn.textContent = "Downloading...";
- const videoElement = document.querySelector("#MRM_video > video > source");
- if (!videoElement) {
- alert("No video found on this page.");
- videoDlBtn.disabled = false;
- videoDlBtn.textContent = "Download Video";
- return;
- }
- const videoSrc = videoElement.src;
- if (!videoSrc) {
- alert("Unable to find video source.");
- videoDlBtn.disabled = false;
- videoDlBtn.textContent = "Download Video";
- return;
- }
- progressBar.style.display = "block";
- progressText.style.display = "block";
- progressText.textContent = "Starting video download...";
- progressInner.style.width = "0%";
- GM_xmlhttpRequest({
- method: "GET",
- url: videoSrc,
- headers: {
- Cookie: cookiesValue,
- },
- responseType: "arraybuffer",
- onprogress: function (progress) {
- if (progress.lengthComputable) {
- const percentComplete = (progress.loaded / progress.total) * 100;
- progressInner.style.width = percentComplete + "%";
- const downloadedMB = (progress.loaded / (1024 * 1024)).toFixed(2);
- const totalMB = (progress.total / (1024 * 1024)).toFixed(2);
- console.log(`Downloaded: ${downloadedMB}MB / ${totalMB}MB`);
- progressText.textContent = `Downloaded: ${downloadedMB}MB / ${totalMB}MB`;
- }
- },
- onload: function (response) {
- const blob = new Blob([response.response], { type: "video/mp4" });
- if (new Blob([response.response]).type.includes("text/html")) {
- alert(
- "The script have detected the Cloudflare is blocking the page. You need to re-enter the cookies info due to Cloudflare resetting the cookies or the cookies is expired. See https://github.com/NYT92/mrm-downloader/tree/main?tab=readme-ov-file#using-the-script for more information."
- );
- window.location.reload();
- } else {
- const safeTitle = title.replace(/[^a-z0-9]/gi, "_").toLowerCase();
- const fileName = `${safeTitle}.mp4`;
- saveAs(blob, fileName);
- console.log("Video downloaded successfully");
- progressBar.style.display = "none";
- progressText.style.display = "none";
- videoDlBtn.disabled = false;
- videoDlBtn.textContent = "Download Video";
- }
- },
- onerror: function (error) {
- console.error("Error downloading video:", error);
- alert(
- "An error occurred while downloading the video. Please check the console for details."
- );
- progressBar.style.display = "none";
- progressText.style.display = "none";
- videoDlBtn.disabled = false;
- videoDlBtn.textContent = "Download Video";
- },
- });
- });
- })();