// ==UserScript==
// @name Enhanced Catbox File Uploader with Auto-Close Drop Zone and Duration Option
// @namespace https://catbox.moe/
// @version 1.1
// @description Upload files to Catbox with URL history, customizable duration, minimize support, middle-click to open in new tab, auto-close drop zone if no file is dropped within 3 seconds.
// @match *://litterbox.catbox.moe/*
// @match *://catbox.moe/*
// @match *://*/*
// @grant GM_addStyle
// @grant GM_setValue
// @grant GM_getValue
// ==/UserScript==
(function() {
'use strict';
// Create necessary DOM elements
const uploadButton = document.createElement('div');
uploadButton.id = 'uploadButton';
uploadButton.innerHTML = '⬆';
document.body.appendChild(uploadButton);
const fileInput = document.createElement('input');
fileInput.type = 'file';
fileInput.style.display = 'none';
document.body.appendChild(fileInput);
const urlTextBox = document.createElement('input');
urlTextBox.type = 'text';
urlTextBox.id = 'fileUrl';
urlTextBox.placeholder = 'URL will appear here';
urlTextBox.readOnly = true;
urlTextBox.style.display = 'none';
document.body.appendChild(urlTextBox);
const copyButton = document.createElement('div');
copyButton.id = 'copyButton';
copyButton.innerHTML = '📋';
copyButton.style.display = 'none';
document.body.appendChild(copyButton);
const dropZone = document.createElement('div');
dropZone.id = 'dropZone';
dropZone.innerText = 'Drag & Drop File Here';
dropZone.style.display = 'none';
document.body.appendChild(dropZone);
const minimizeButton = document.createElement('div');
minimizeButton.id = 'minimizeButton';
minimizeButton.innerHTML = '—';
minimizeButton.style.display = 'none';
document.body.appendChild(minimizeButton);
const historyButton = document.createElement('div');
historyButton.id = 'historyButton';
historyButton.innerHTML = '📜';
historyButton.style.display = 'none';
document.body.appendChild(historyButton);
const clearHistoryButton = document.createElement('div');
clearHistoryButton.id = 'clearHistoryButton';
clearHistoryButton.innerHTML = '🗑️';
clearHistoryButton.style.display = 'none';
document.body.appendChild(clearHistoryButton);
const historyList = document.createElement('div');
historyList.id = 'historyList';
historyList.style.display = 'none';
document.body.appendChild(historyList);
const durationButton = document.createElement('div');
durationButton.id = 'durationButton';
durationButton.innerHTML = GM_getValue('uploadDuration', '1h'); // Display initial duration
durationButton.style.display = 'none';
document.body.appendChild(durationButton);
const durationMenu = document.createElement('div');
durationMenu.id = 'durationMenu';
durationMenu.style.display = 'none';
durationMenu.innerHTML = `
<div data-duration="1h">1 hour</div>
<div data-duration="12h">12 hours</div>
<div data-duration="24h">24 hours</div>
<div data-duration="72h">72 hours</div>
`;
document.body.appendChild(durationMenu);
GM_addStyle(`
#uploadButton, #historyButton, #clearHistoryButton, #minimizeButton, #durationButton {
position: fixed;
bottom: 20px;
width: 50px;
height: 50px;
background-color: #333;
color: white;
border: none;
border-radius: 50%;
cursor: pointer;
font-family: Arial, sans-serif;
font-size: 24px;
text-align: center;
line-height: 50px;
box-shadow: 0px 2px 5px rgba(0, 0, 0, 0.2);
z-index: 10000;
}
#uploadButton { left: 20px; }
#uploadButton.minimized {
bottom: 0;
width: 50px;
height: 10px;
border-radius: 50px 50px 0 0;
font-size: 10px;
line-height: 10px;
}
#minimizeButton, #historyButton, #clearHistoryButton, #durationButton {
width: 40px;
height: 40px;
font-size: 20px;
line-height: 40px;
}
#minimizeButton { left: 80px; }
#historyButton { left: 140px; }
#clearHistoryButton { left: 200px; }
#durationButton { left: 260px; }
#fileUrl, #historyList, #durationMenu {
position: fixed;
bottom: 80px;
left: 20px;
width: 270px;
background-color: #333;
color: white;
padding: 10px;
border: none;
border-radius: 5px;
font-size: 14px;
box-shadow: 0px 2px 5px rgba(0, 0, 0, 0.2);
z-index: 10000;
overflow-y: auto;
}
#fileUrl { display: block; }
#historyList {
height: 200px;
display: none;
}
#historyList div {
margin-bottom: 10px;
}
#historyList div span.timestamp {
display: block;
color: #aaa;
font-size: 12px;
margin-top: 4px;
border-top: 1px solid #555;
padding-top: 2px;
}
#historyList a {
color: #66ccff;
text-decoration: none;
}
#copyButton {
position: fixed;
bottom: 80px;
left: 300px;
width: 30px;
height: 30px;
background-color: #333;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
font-family: Arial, sans-serif;
font-size: 16px;
text-align: center;
line-height: 30px;
box-shadow: 0px 2px 5px rgba(0, 0, 0, 0.2);
z-index: 10000;
}
#dropZone {
position: fixed;
bottom: 150px;
left: 20px;
width: 300px;
height: 150px;
border: 2px dashed #aaa;
background-color: #444;
color: white;
text-align: center;
line-height: 150px;
font-family: Arial, sans-serif;
font-size: 14px;
border-radius: 5px;
z-index: 10000;
}
#dropZone.dragover {
border-color: #fff;
background-color: #555;
}
#durationMenu div:hover {
background-color: #555;
}
`);
let isMinimized = true;
let uploadDuration = GM_getValue('uploadDuration', '1h');
uploadButton.classList.add('minimized');
uploadButton.addEventListener('click', () => {
if (isMinimized) {
uploadButton.classList.remove('minimized');
isMinimized = false;
minimizeButton.style.display = 'block';
historyButton.style.display = 'block';
clearHistoryButton.style.display = 'block';
durationButton.style.display = 'block';
} else {
fileInput.click();
}
});
minimizeButton.addEventListener('click', () => {
uploadButton.classList.add('minimized');
isMinimized = true;
minimizeButton.style.display = 'none';
urlTextBox.style.display = 'none';
copyButton.style.display = 'none';
historyList.style.display = 'none';
historyButton.style.display = 'none';
clearHistoryButton.style.display = 'none';
durationButton.style.display = 'none';
dropZone.style.display = 'none';
durationMenu.style.display = 'none';
});
durationButton.addEventListener('click', () => {
durationMenu.style.display = durationMenu.style.display === 'none' ? 'block' : 'none';
});
durationMenu.addEventListener('click', (e) => {
if (e.target.dataset.duration) {
uploadDuration = e.target.dataset.duration;
GM_setValue('uploadDuration', uploadDuration);
durationButton.innerHTML = uploadDuration;
durationMenu.style.display = 'none';
}
});
fileInput.addEventListener('change', () => {
const file = fileInput.files[0];
if (file) uploadFile(file);
});
const uploadedUrlsKey = 'globalUploadedUrls';
const urlLimit = 10;
let savedUrls = GM_getValue(uploadedUrlsKey, []);
function updateHistoryList() {
historyList.innerHTML = savedUrls.map(item => `<div><a href="${item.url}" target="_blank">${item.url}</a><span class="timestamp">${item.timestamp}</span></div>`).join('');
}
historyButton.addEventListener('click', () => {
historyList.style.display = historyList.style.display === 'none' ? 'block' : 'none';
updateHistoryList();
});
clearHistoryButton.addEventListener('click', () => {
if (confirm("Are you sure you want to clear the URL history? This action cannot be undone.")) {
savedUrls = [];
GM_setValue(uploadedUrlsKey, savedUrls);
updateHistoryList();
}
});
function handleFileDrop(e) {
e.preventDefault();
dropZone.classList.remove('dragover');
const file = e.dataTransfer.files[0];
if (file) uploadFile(file);
}
document.addEventListener('dragover', e => {
e.preventDefault();
dropZone.style.display = 'block';
dropZone.classList.add('dragover');
});
document.addEventListener('dragleave', () => dropZone.style.display = 'none');
dropZone.addEventListener('drop', handleFileDrop);
async function uploadFile(file) {
const timestamp = new Date().toLocaleString('en-GB');
try {
const formData = new FormData();
formData.append('reqtype', 'fileupload');
formData.append('fileToUpload', file);
const response = await fetch('https://litterbox.catbox.moe/resources/internals/api.php', {
method: 'POST',
body: formData
});
const url = await response.text();
const newEntry = { url, timestamp };
savedUrls.push(newEntry);
if (savedUrls.length > urlLimit) savedUrls.shift();
GM_setValue(uploadedUrlsKey, savedUrls);
urlTextBox.value = url;
urlTextBox.style.display = 'block';
copyButton.style.display = 'block';
updateHistoryList();
} catch (error) {
console.error("Upload failed:", error);
}
}
copyButton.addEventListener('click', () => {
navigator.clipboard.writeText(urlTextBox.value).then(() => alert('Copied to clipboard!'));
});
})();