nicovideo downloader

script for downloading videos from the nicovideo website

// ==UserScript==
// @name         nicovideo downloader
// @description  script for downloading videos from the nicovideo website
// @namespace    kwlNjR37xBCMkr76P5eKA88apmOClCfZ
// @author       kwlNjR37xBCMkr76P5eKA88apmOClCfZ
// @version      0001
// @match        *://www.nicovideo.jp/watch/sm*
// @match        *://ext.nicovideo.jp/?sm*
// @website      https://gf.qytechs.cn/en/scripts/548403
// @icon         https://www.google.com/s2/favicons?domain=ext.nicovideo.jp
// @grant        GM.setValue
// @grant        GM.getValue
// @license      CC0 1.0
// ==/UserScript==

(function() {
	'use strict';

	let targetContainer;
	let observer;
	const SCRIPT_SRC_720p = "https://www.nicozon.net/js/bookmarklet_old_720p.js";
	const SCRIPT_SRC_480p = "https://www.nicozon.net/js/bookmarklet_old_480p.js";
	const SCRIPT_SRC_360p = "https://www.nicozon.net/js/bookmarklet_old_360p.js";
	const SCRIPT_SRC_audio = "https://www.nicozon.net/js/bookmarklet_old_audio.js";

	// Log script initialization
	console.log('NicoVideo Downloader script initialized');

	// Function to extract video ID from URL
	function getVideoId() {
		try {
			const url = window.location.href;
			const match = url.match(/sm(\d+)/);
			const videoId = match ? match[0] : null;

			if (!videoId) {
				console.error('Could not extract video ID from URL:', url);
			} else {
				console.log('Extracted video ID:', videoId);
			}

			return videoId;
		} catch (error) {
			console.error('Error extracting video ID:', error);
			return null;
		}
	}

	// Function to create download links
	function createDownloadLinks() {
		try {
			const videoId = getVideoId();
			if (!videoId) {
				console.error('Cannot create download links without video ID');
				return null;
			}

			// Create container for links
			const linksContainer = document.createElement('div');
			linksContainer.className = 'download-links';
			linksContainer.style.cssText = `
                display: inline-block;
                margin-left: 10px;
                font-size: 14px;
            `;

			// Add label
			const label = document.createElement('span');
			label.textContent = 'Download: ';
			label.style.marginRight = '8px';
			linksContainer.appendChild(label);

			// Create download options
			const options = [
				{ text: '720p', quality: '720p', script: SCRIPT_SRC_720p },
				{ text: '480p', quality: '480p', script: SCRIPT_SRC_480p },
				{ text: '360p', quality: '360p', script: SCRIPT_SRC_360p },
				{ text: 'Audio', quality: 'audio', script: SCRIPT_SRC_audio }
			];

			options.forEach((option, index) => {
				const link = document.createElement('a');
				link.href = `https://ext.nicovideo.jp/?${videoId}`;
				link.textContent = option.text;
				link.dataset.quality = option.quality;
				link.dataset.script = option.script;
				link.style.cssText = `
                    color: #ff9900;
                    text-decoration: none;
                    margin: 0 4px;
                    font-weight: bold;
                    cursor: pointer;
                `;
				link.addEventListener('mouseover', function() {
					this.style.textDecoration = 'underline';
				});
				link.addEventListener('mouseout', function() {
					this.style.textDecoration = 'none';
				});
				link.addEventListener('click', async function(e) {
					e.preventDefault();
					try {
						// Store the selected quality using GM.setValue
						await GM.setValue('nicovideoDownloadQuality', this.dataset.quality);
						await GM.setValue('nicovideoDownloadScript', this.dataset.script);
						console.log('Stored download preference:', this.dataset.quality);
						window.open(this.href, '_blank');
					} catch (error) {
						console.error('Error storing download preference:', error);
						alert('Error saving download preference. Please check console for details.');
					}
				});

				linksContainer.appendChild(link);

				// Add separator except for the last item
				if (index < options.length - 1) {
					const separator = document.createElement('span');
					separator.textContent = '|';
					separator.style.cssText = 'color: #ccc; margin: 0 4px;';
					linksContainer.appendChild(separator);
				}
			});

			console.log('Download links created successfully');
			return linksContainer;
		} catch (error) {
			console.error('Error creating download links:', error);
			return null;
		}
	}

	function addDownloadLinks() {
		try {
			targetContainer = document.querySelector('.d_flex.gap_x2.text-layer_lowEm.fs_s.fw_bold.white-space_nowrap.ai_center');
			if (targetContainer) {
				// Check if links already exist to avoid duplicates
				if (!targetContainer.querySelector('.download-links')) {
					const linksContainer = createDownloadLinks();
					if (linksContainer) {
						targetContainer.appendChild(linksContainer);
						console.log('Download links added to page');

						// Stop observing once we've successfully added the links
						if (observer) {
							observer.disconnect();
							console.log('MutationObserver disconnected');
						}
					}
				} else {
					console.log('Download links already exist, skipping');
				}
			} else {
				console.log('Target container not found yet');
				return false;
			}
			return true;
		} catch (error) {
			console.error('Error adding download links:', error);
			return false;
		}
	}

	// Function to handle different page types
	async function handlePage() {
		try {
			console.log('Handling page:', window.location.hostname);
			const videoId = getVideoId();
			if (!videoId) {
				console.error('No video ID found, stopping execution');
				return;
			}

			if (window.location.hostname === 'www.nicovideo.jp') {
				console.log('On main nicovideo page');
				// Try immediately first
				const success = addDownloadLinks();

				// If not found, set up MutationObserver to watch for DOM changes
				if (!success) {
					console.log('Setting up MutationObserver to watch for target container');
					observer = new MutationObserver(function(mutations) {
						console.log('DOM mutation observed', mutations.length, 'changes');
						mutations.forEach(function(mutation) {
							if (mutation.addedNodes && mutation.addedNodes.length > 0) {
								addDownloadLinks();
							}
						});
					});

					// Start observing the document body for added nodes
					observer.observe(document.body, {
						childList: true,
						subtree: true
					});

					// Set a timeout as fallback
					/*setTimeout(() => {
						if (observer) {
							observer.disconnect();
							console.log('MutationObserver disconnected after timeout');
						}
						const finalAttempt = addDownloadLinks();
						if (!finalAttempt) {
							console.error('Failed to add download links after timeout');
						}
					}, 30000); // 30 seconds as fallback*/
				}
			}
			else if (window.location.hostname === 'ext.nicovideo.jp') {
				console.log('On ext.nicovideo page');
				// On ext.nicovideo page, check if we have a stored quality preference
				const quality = await GM.getValue('nicovideoDownloadQuality');
				const scriptSrc = await GM.getValue('nicovideoDownloadScript');

				console.log('Retrieved stored values - Quality:', quality, '; Script:', scriptSrc);

				const p = document.createElement("p");
				p.textContent = "Download: " + (quality || 'No quality selected');
				document.body.appendChild(p);

				// Clean up stored values
				await GM.setValue('nicovideoDownloadQuality', '');
				await GM.setValue('nicovideoDownloadScript', '');
				console.log('Cleared stored values');

				if (scriptSrc) {
					console.log('Loading download script:', scriptSrc);
					try {
						const script = document.createElement('script');
						script.setAttribute('charset', 'utf-8');
						script.src = scriptSrc;
						script.onload = function() {
							console.log('Download script loaded successfully');
						};
						script.onerror = function() {
							console.error('Failed to load download script:', scriptSrc);
							alert('Failed to load download script. Please try again.');
						};
						document.body.appendChild(script);
					} catch (error) {
						console.error('Error loading download script:', error);
					}
				} else {
					console.log('No script source found, creating download links instead');
					const linksContainer = createDownloadLinks();
					if (linksContainer) {
						document.body.appendChild(linksContainer);
					}
				}
			} else {
				console.warn('Unsupported hostname:', window.location.hostname);
			}
		} catch (error) {
			console.error('Error in handlePage function:', error);
		}
	}

	// Run when DOM is ready
	if (document.readyState === 'loading') {
		console.log('DOM not ready, adding DOMContentLoaded listener');
		document.addEventListener('DOMContentLoaded', function() {
			console.log('DOMContentLoaded fired');
			handlePage();
		});
	} else {
		console.log('DOM already ready, executing immediately');
		handlePage();
	}
})();

// https://www.youtube.com/watch?v=sztJ8cO4mak
// https://www.nicozon.net/

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址