你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式
你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式
你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式
你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式
你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式
你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式
(我已經安裝了使用者樣式管理器,讓我安裝!)
// ==UserScript==
// @name Universal Video Downloader
// @namespace http://tampermonkey.net/
// @version 0.3
// @description Enhanced video downloader with console and broader platform support
// @author usercromix & Grok
// @match *://*/*
// @grant GM_xmlhttpRequest
// @connect *
// ==/UserScript==
(function() {
'use strict';
// Platform detection patterns
const platformPatterns = {
youtube: /youtube\.com|youtu\.be/,
twitter: /twitter\.com|x\.com/,
facebook: /facebook\.com/,
instagram: /instagram\.com/,
tiktok: /tiktok\.com/,
vimeo: /vimeo\.com/
};
// Create UI container
const uiContainer = document.createElement('div');
uiContainer.id = 'video-downloader-ui';
uiContainer.style.cssText = `
position: fixed;
z-index: 9999;
background: linear-gradient(135deg, #2b2d42, #8d99ae);
padding: 15px;
border-radius: 10px;
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.3);
cursor: move;
user-select: none;
top: 20px;
right: 20px;
font-family: Arial, sans-serif;
transition: all 0.3s ease;
width: 250px;
`;
// Create console
const consoleDiv = document.createElement('div');
consoleDiv.style.cssText = `
background: #1e1e1e;
color: #00ff00;
padding: 10px;
border-radius: 5px;
max-height: 150px;
overflow-y: auto;
font-family: monospace;
font-size: 12px;
margin-top: 10px;
`;
function logToConsole(message) {
const entry = document.createElement('div');
entry.textContent = `[${new Date().toLocaleTimeString()}] ${message}`;
consoleDiv.appendChild(entry);
consoleDiv.scrollTop = consoleDiv.scrollHeight;
}
// Create UI elements
const header = document.createElement('div');
header.textContent = 'Video Downloader';
header.style.cssText = `
color: #edf2f4;
font-size: 14px;
font-weight: bold;
margin-bottom: 10px;
text-align: center;
`;
const buttonContainer = document.createElement('div');
buttonContainer.style.cssText = `
display: flex;
flex-direction: column;
gap: 10px;
`;
const downloadButton = document.createElement('button');
downloadButton.textContent = 'Download Video';
const selectButton = document.createElement('button');
selectButton.textContent = 'Select Video';
// Button styling
[downloadButton, selectButton].forEach(button => {
button.style.cssText = `
background: linear-gradient(45deg, #ef233c, #d90429);
color: white;
border: none;
padding: 8px 16px;
border-radius: 5px;
cursor: pointer;
transition: transform 0.2s ease;
`;
button.addEventListener('mouseover', () => button.style.transform = 'scale(1.05)');
button.addEventListener('mouseout', () => button.style.transform = 'scale(1)');
});
// Append elements
buttonContainer.appendChild(downloadButton);
buttonContainer.appendChild(selectButton);
uiContainer.appendChild(header);
uiContainer.appendChild(buttonContainer);
uiContainer.appendChild(consoleDiv);
document.body.appendChild(uiContainer);
// Draggable UI
let isDragging = false;
let initialX, initialY;
header.addEventListener('mousedown', (e) => {
isDragging = true;
const rect = uiContainer.getBoundingClientRect();
initialX = e.clientX - rect.left;
initialY = e.clientY - rect.top;
});
document.addEventListener('mousemove', (e) => {
if (isDragging) {
e.preventDefault();
uiContainer.style.left = (e.clientX - initialX) + 'px';
uiContainer.style.top = (e.clientY - initialY) + 'px';
uiContainer.style.right = 'auto';
}
});
document.addEventListener('mouseup', () => isDragging = false);
// Platform-specific video detection
function detectPlatform() {
const url = window.location.href;
for (const [platform, pattern] of Object.entries(platformPatterns)) {
if (pattern.test(url)) return platform;
}
return 'generic';
}
// Enhanced video URL getters
const videoGetters = {
youtube: () => {
const videoId = new URLSearchParams(window.location.search).get('v');
return videoId ? `https://www.youtube.com/watch?v=${videoId}` :
document.querySelector('meta[property="og:video:url"]')?.content;
},
twitter: () => document.querySelector('video[src*="video.twimg.com"]')?.src,
facebook: () => document.querySelector('video[src*="fbcdn.net"]')?.src ||
document.querySelector('meta[property="og:video"]')?.content,
instagram: () => document.querySelector('video[src*="instagram.com"]')?.src,
tiktok: () => document.querySelector('video[src*="tiktokcdn.com"]')?.src,
vimeo: () => document.querySelector('video[src*="vimeocdn.com"]')?.src
};
function detectVideo() {
const platform = detectPlatform();
const getter = videoGetters[platform] || (() => {
const videos = document.getElementsByTagName('video');
return videos.length > 0 ? (videos[0].src || videos[0].currentSrc) : null;
});
const url = getter();
logToConsole(`Detected ${platform} video: ${url || 'none'}`);
return url;
}
// Enhanced download with corruption prevention
function downloadVideo(videoUrl) {
if (!videoUrl) {
logToConsole('Error: No video URL provided');
alert('No video selected or detected!');
return;
}
logToConsole(`Initiating download: ${videoUrl}`);
GM_xmlhttpRequest({
method: 'GET',
url: videoUrl,
responseType: 'blob',
headers: {
'Accept': 'video/*',
'Referer': window.location.href
},
onload: (response) => {
try {
const blob = response.response;
if (blob.size === 0) {
throw new Error('Empty response');
}
const platform = detectPlatform();
const filename = `${platform}_${Date.now()}.mp4`;
const url = window.URL.createObjectURL(blob);
const downloadLink = document.createElement('a');
downloadLink.href = url;
downloadLink.download = filename;
document.body.appendChild(downloadLink);
downloadLink.click();
document.body.removeChild(downloadLink);
window.URL.revokeObjectURL(url);
logToConsole(`Download completed: ${filename}`);
} catch (error) {
logToConsole(`Download failed: ${error.message}`);
alert('Download failed: ' + error.message);
}
},
onerror: (error) => {
logToConsole(`Network error: ${error.statusText}`);
alert('Network error occurred');
}
});
}
// Button handlers
downloadButton.addEventListener('click', () => {
const videoUrl = detectVideo();
downloadVideo(videoUrl);
});
let isSelecting = false;
selectButton.addEventListener('click', () => {
if (!isSelecting) {
isSelecting = true;
selectButton.textContent = 'Click a Video';
document.body.style.cursor = 'crosshair';
logToConsole('Selection mode activated');
const videoClickHandler = (e) => {
const video = e.target.closest('video') ||
e.target.closest('a[href*=".mp4"]') ||
e.target.closest('a[href*=".webm"]');
const videoUrl = video?.src || video?.currentSrc || video?.href || detectVideo();
if (videoUrl) {
e.preventDefault();
downloadVideo(videoUrl);
}
cleanupSelection();
};
const cleanupSelection = () => {
isSelecting = false;
selectButton.textContent = 'Select Video';
document.body.style.cursor = 'default';
document.removeEventListener('click', videoClickHandler);
logToConsole('Selection mode deactivated');
};
document.addEventListener('click', videoClickHandler, { once: true });
setTimeout(cleanupSelection, 10000);
}
});
// Initial console message
logToConsole('Video Downloader initialized');
// Anti-detection
Object.defineProperty(window, 'videoDownloader', {
value: undefined,
writable: false,
configurable: false
});
})();