您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Right-click image upload to Mobilism image hosting with different size options
// ==UserScript== // @name Imgilism - Image Uploader // @namespace http://tampermonkey.net/ // @version 1.0.9 // @description Right-click image upload to Mobilism image hosting with different size options // @author EyezOnly (converted to userscript) // @match http://*/* // @match https://*/* // @grant GM_xmlhttpRequest // @grant GM_registerMenuCommand // @grant GM_notification // @grant GM_setClipboard // @run-at document-start // ==/UserScript== (function() { 'use strict'; let contextMenuShown = false; let contextMenuDiv = null; let currentImageUrl = null; // Create context menu styles const style = document.createElement('style'); style.textContent = ` .imgilism-context-menu { position: fixed; background: #fff; border: 1px solid #ccc; border-radius: 4px; box-shadow: 0 2px 10px rgba(0,0,0,0.2); z-index: 10000; min-width: 150px; font-family: Arial, sans-serif; font-size: 14px; } .imgilism-menu-item { padding: 8px 12px; cursor: pointer; border-bottom: 1px solid #eee; transition: background-color 0.2s; } .imgilism-menu-item:hover { background-color: #f0f0f0; } .imgilism-menu-item:last-child { border-bottom: none; } .imgilism-menu-header { padding: 8px 12px; background: #f5f5f5; font-weight: bold; border-bottom: 1px solid #ddd; color: #333; } .imgilism-progress { padding: 8px 12px; background: #e8f4f8; color: #0066cc; font-style: italic; } `; document.head.appendChild(style); // Create context menu function createContextMenu() { contextMenuDiv = document.createElement('div'); contextMenuDiv.className = 'imgilism-context-menu'; contextMenuDiv.innerHTML = ` <div class="imgilism-menu-header">📸 Imgilism Upload</div> <div class="imgilism-menu-item" data-action="single">Single [320x240]</div> <div class="imgilism-menu-item" data-action="multiple">Multiple [240x160]</div> <div class="imgilism-menu-item" data-action="large">Large [500xAuto]</div> `; document.body.appendChild(contextMenuDiv); // Add click handlers contextMenuDiv.addEventListener('click', function(e) { const action = e.target.dataset.action; if (action && currentImageUrl) { hideContextMenu(); uploadImage(currentImageUrl, action); } }); } // Show context menu function showContextMenu(x, y, imageUrl) { currentImageUrl = imageUrl; if (!contextMenuDiv) { createContextMenu(); } contextMenuDiv.style.left = x + 'px'; contextMenuDiv.style.top = y + 'px'; contextMenuDiv.style.display = 'block'; contextMenuShown = true; } // Hide context menu function hideContextMenu() { if (contextMenuDiv) { contextMenuDiv.style.display = 'none'; } contextMenuShown = false; currentImageUrl = null; } // Upload image function function uploadImage(imageUrl, sizeOption) { console.log('Starting image upload for:', imageUrl, 'with size option:', sizeOption); // Show progress if (contextMenuDiv) { contextMenuDiv.innerHTML = '<div class="imgilism-progress">Uploading image...</div>'; contextMenuDiv.style.display = 'block'; } // Configure size options let height, width, responseId; switch(sizeOption) { case 'single': height = '320'; width = ''; responseId = 'codehtml'; break; case 'multiple': height = '240'; width = '160'; responseId = 'codelbb'; break; case 'large': height = '500'; width = ''; responseId = 'codehtml'; break; } console.log('Upload config:', { height, width, responseId }); // Fetch the image GM_xmlhttpRequest({ method: 'GET', url: imageUrl, responseType: 'blob', timeout: 30000, // 30 second timeout onload: function(response) { console.log('Image fetch response:', response.status, response.statusText); if (response.status === 200) { const blob = response.response; const fileName = imageUrl.split(/[?#]/)[0].split('/').pop() || 'image.jpg'; console.log('Processing blob:', blob.size, 'bytes, filename:', fileName); // Create a proper File object like the Chrome extension does const file = new File([blob], fileName, { type: blob.type }); // Create FormData exactly like the Chrome extension const formData = new FormData(); formData.append('links', ''); formData.append('imgUrl', ''); formData.append('fileName[]', fileName); formData.append('Search files', 'Browse'); formData.append('file[]', file); // Use File object instead of blob formData.append('alt[]', fileName.replace(/[-_]/g, ' ').replace(/\.[^.]*$/, '')); formData.append('private[0]', '1'); formData.append('new_height[]', height); formData.append('new_width[]', width); formData.append('submit', 'Upload'); console.log('Uploading to Mobilism...'); // Upload to Mobilism GM_xmlhttpRequest({ method: 'POST', url: 'https://images.mobilism.org/upload.php', data: formData, timeout: 60000, // 60 second timeout for upload onload: function(uploadResponse) { console.log('Upload response:', uploadResponse.status, uploadResponse.statusText); console.log('Response text length:', uploadResponse.responseText.length); hideContextMenu(); if (uploadResponse.status === 200) { try { // Parse response const parser = new DOMParser(); const responseDoc = parser.parseFromString(uploadResponse.responseText, 'text/html'); const urlElement = responseDoc.getElementById(responseId); console.log('Looking for element with ID:', responseId); console.log('Found element:', urlElement); if (urlElement && urlElement.value && urlElement.value.trim()) { const uploadedUrl = urlElement.value.trim(); console.log('Extracted URL:', uploadedUrl); // Copy to clipboard GM_setClipboard(uploadedUrl); // Show notification GM_notification({ title: 'Imgilism Upload Success', text: 'Image uploaded! URL copied to clipboard.', timeout: 3000 }); // Also show prompt for backup setTimeout(() => { prompt('Image uploaded successfully! URL (also copied to clipboard):', uploadedUrl); }, 100); } else { console.error('Failed to find URL element or empty value'); console.log('Available elements with IDs:', Array.from(responseDoc.querySelectorAll('[id]')).map(el => el.id)); // Try to find any textarea or input that might contain the URL const allInputs = responseDoc.querySelectorAll('input, textarea'); console.log('All inputs found:', allInputs.length); GM_notification({ title: 'Imgilism Upload Failed', text: 'Failed to extract image URL from response. Check console for details.', timeout: 5000 }); } } catch (parseError) { console.error('Error parsing response:', parseError); GM_notification({ title: 'Imgilism Upload Failed', text: 'Error parsing upload response: ' + parseError.message, timeout: 3000 }); } } else { console.error('Upload failed with status:', uploadResponse.status); GM_notification({ title: 'Imgilism Upload Failed', text: 'Upload request failed with status: ' + uploadResponse.status, timeout: 3000 }); } }, onerror: function(error) { console.error('Upload error:', error); hideContextMenu(); GM_notification({ title: 'Imgilism Upload Error', text: 'Upload failed: ' + (error.message || 'Network error'), timeout: 3000 }); }, ontimeout: function() { console.error('Upload timeout'); hideContextMenu(); GM_notification({ title: 'Imgilism Upload Timeout', text: 'Upload request timed out. Please try again.', timeout: 3000 }); } }); } else { console.error('Failed to fetch image:', response.status, response.statusText); hideContextMenu(); GM_notification({ title: 'Imgilism Error', text: 'Failed to fetch image: ' + response.status + ' ' + response.statusText, timeout: 3000 }); } }, onerror: function(error) { console.error('Image fetch error:', error); hideContextMenu(); GM_notification({ title: 'Imgilism Error', text: 'Failed to fetch image: ' + (error.message || 'Network error'), timeout: 3000 }); }, ontimeout: function() { console.error('Image fetch timeout'); hideContextMenu(); GM_notification({ title: 'Imgilism Error', text: 'Image fetch timed out. Please try again.', timeout: 3000 }); } }); } // Event listeners document.addEventListener('contextmenu', function(e) { if (e.target.tagName === 'IMG' && e.target.src) { e.preventDefault(); // Skip menu, go straight to Large upload uploadImage(e.target.src, 'large'); } else if (contextMenuShown) { hideContextMenu(); } }); document.addEventListener('click', function(e) { if (contextMenuShown && !contextMenuDiv.contains(e.target)) { hideContextMenu(); } }); document.addEventListener('keydown', function(e) { if (e.key === 'Escape' && contextMenuShown) { hideContextMenu(); } }); // Register menu commands for manual access GM_registerMenuCommand('Upload Image (Single 320x240)', function() { const imageUrl = prompt('Enter image URL:'); if (imageUrl) { uploadImage(imageUrl, 'single'); } }); GM_registerMenuCommand('Upload Image (Multiple 240x160)', function() { const imageUrl = prompt('Enter image URL:'); if (imageUrl) { uploadImage(imageUrl, 'multiple'); } }); GM_registerMenuCommand('Upload Image (Large 500xAuto)', function() { const imageUrl = prompt('Enter image URL:'); if (imageUrl) { uploadImage(imageUrl, 'large'); } }); console.log('Imgilism userscript loaded successfully!'); })();