// ==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!');
})();