Last active
May 28, 2025 21:03
-
-
Save navinor/d295b298f026134ae979f94517e98f8b to your computer and use it in GitHub Desktop.
mclo.gs Log Uploader
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ==UserScript== | |
// @name mclo.gs Log Uploader | |
// @namespace http://tampermonkey.net/ | |
// @version 1.1 | |
// @description Upload log files to mclo.gs. | |
// @author Navinor | |
// @match *://*/* | |
// @grant GM_setClipboard | |
// @grant GM.xmlHttpRequest | |
// @grant GM_addStyle | |
// @grant GM_registerMenuCommand | |
// @connect api.mclo.gs | |
// @connect * | |
// @run-at document-start | |
// ==/UserScript== | |
(function() { | |
'use strict'; | |
let lastLogLink = null; | |
// Add custom CSS for our upload button and notifications | |
GM_addStyle(` | |
.mclogs-notification { | |
position: fixed; | |
top: 20px; | |
right: 20px; | |
background: #2d3142; | |
color: #ffffff; | |
padding: 16px 20px; | |
border-radius: 8px; | |
border-left: 4px solid #4CAF50; | |
box-shadow: 0 4px 12px rgba(0,0,0,0.3); | |
z-index: 10001; | |
max-width: 350px; | |
font-family: Arial, sans-serif; | |
font-size: 14px; | |
opacity: 0; | |
transform: translateX(100%); | |
transition: all 0.3s ease; | |
} | |
.mclogs-notification.show { | |
opacity: 1; | |
transform: translateX(0); | |
} | |
.mclogs-notification.error { | |
border-left-color: #f44336; | |
} | |
.mclogs-notification-title { | |
font-weight: bold; | |
margin-bottom: 4px; | |
} | |
.mclogs-notification-message { | |
font-size: 12px; | |
line-height: 1.4; | |
color: #d1d5db; | |
} | |
.mclogs-link-indicator { | |
position: relative; | |
} | |
.mclogs-link-indicator::after { | |
content: "📤"; | |
position: absolute; | |
top: -5px; | |
right: -15px; | |
font-size: 10px; | |
opacity: 0.6; | |
pointer-events: none; | |
} | |
`); | |
// Check if URL appears to be a log file | |
function isLogFile(url) { | |
if (!url) return false; | |
const logExtensions = ['.log', '.txt', '.out', '.crash']; | |
const urlLower = url.toLowerCase(); | |
return logExtensions.some(ext => urlLower.includes(ext)) || | |
urlLower.includes('log') || | |
urlLower.includes('crash') || | |
urlLower.includes('latest'); | |
} | |
// Create and show custom notification | |
function showNotification(title, message, isError = false) { | |
// Remove existing notifications | |
const existing = document.querySelectorAll('.mclogs-notification'); | |
existing.forEach(n => n.remove()); | |
const notification = document.createElement('div'); | |
notification.className = `mclogs-notification ${isError ? 'error' : ''}`; | |
notification.innerHTML = ` | |
<div class="mclogs-notification-title">${title}</div> | |
<div class="mclogs-notification-message">${message}</div> | |
`; | |
document.body.appendChild(notification); | |
// Trigger animation | |
setTimeout(() => notification.classList.add('show'), 10); | |
// Auto remove after 5 seconds | |
setTimeout(() => { | |
notification.classList.remove('show'); | |
setTimeout(() => notification.remove(), 300); | |
}, 5000); | |
} | |
// Send content to mclo.gs API | |
function sendToMclogs(content) { | |
return new Promise((resolve, reject) => { | |
GM.xmlHttpRequest({ | |
method: 'POST', | |
url: 'https://api.mclo.gs/1/log', | |
headers: { | |
'Content-Type': 'application/x-www-form-urlencoded' | |
}, | |
data: `content=${encodeURIComponent(content)}`, | |
onload: function(response) { | |
try { | |
const status = response.status; | |
const result = JSON.parse(response.responseText); | |
if (status === 200 && result.success) { | |
resolve({ | |
success: true, | |
url: result.url, | |
id: result.id | |
}); | |
} else if (status === 429) { | |
reject(new Error('Rate limit exceeded. Try again in a few minutes.')); | |
} else { | |
reject(new Error(result?.error || `Upload failed (HTTP ${status})`)); | |
} | |
} catch (e) { | |
reject(new Error('Invalid response from server')); | |
} | |
}, | |
onerror: function() { | |
reject(new Error('Network error occurred')); | |
} | |
}); | |
}); | |
} | |
// Fetch file content | |
function fetchFileContent(url) { | |
return new Promise((resolve, reject) => { | |
GM.xmlHttpRequest({ | |
method: 'GET', | |
url: url, | |
onload: function(response) { | |
if (response.status === 200) { | |
resolve(response.responseText); | |
} else { | |
reject(new Error(`HTTP error! status: ${response.status}`)); | |
} | |
}, | |
onerror: function(response) { | |
reject(new Error('Failed to fetch file')); | |
} | |
}); | |
}); | |
} | |
// Handle the upload process | |
async function handleUpload(linkUrl) { | |
try { | |
showNotification( | |
'⏳ Uploading to mclo.gs', | |
'Downloading and uploading log file...' | |
); | |
// Fetch the file content | |
const content = await fetchFileContent(linkUrl); | |
// Send to mclo.gs | |
const result = await sendToMclogs(content); | |
if (result.success) { | |
// Copy URL to clipboard | |
GM_setClipboard(result.url); | |
// Build the <a> element with DOM methods | |
const linkEl = document.createElement('a'); | |
linkEl.href = result.url; // href is already a safe, encoded string | |
linkEl.textContent = result.url; // avoid innerHTML injection | |
linkEl.target = '_blank'; // optional: open in new tab | |
showNotification( | |
'✅ Upload Successful!', | |
'Log uploaded to mclo.gs! URL copied to clipboard:<br>', | |
); | |
} else { | |
throw new Error('Upload failed'); | |
} | |
} catch (error) { | |
console.error('Error uploading to mclo.gs:', error); | |
showNotification( | |
'❌ Upload Failed', | |
`Failed to upload log: ${error.message}`, | |
true | |
); | |
} | |
} | |
// Track last right-clicked link | |
document.addEventListener('contextmenu', function(e) { | |
const link = e.target.closest('a'); | |
if (link && link.href && isLogFile(link.href)) { | |
lastLogLink = link.href; | |
} | |
}); | |
// Register menu command for uploading right-clicked log link | |
GM_registerMenuCommand("📤 Upload to mclo.gs", function() { | |
if (lastLogLink) { | |
handleUpload(lastLogLink); | |
} else { | |
showNotification( | |
'ℹ️ No Log Link Found', | |
'Right-click on a log file link first, then use this menu option.' | |
); | |
} | |
}); | |
console.log('mclo.gs Log Uploader registered.'); | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment