Загрузка изображений на FastPic при перетаскивании в текстовое поле
当前为
// ==UserScript==
// @name FastPic Upload for RuTracker
// @name:en FastPic Upload for RuTracker
// @namespace http://tampermonkey.net/
// @version 1.0
// @description Загрузка изображений на FastPic при перетаскивании в текстовое поле
// @description:en Image upload to FastPic via drag&drop in the text field
// @author С
// @license MIT
// @match https://rutracker.org/forum/viewtopic.php?*
// @match https://rutracker.org/forum/posting.php?*
// @grant GM_xmlhttpRequest
// ==/UserScript==
(function() {
'use strict';
const textarea = document.querySelector('#post-textarea');
if (!textarea) return;
const style = document.createElement('style');
style.textContent = `
.fastpic-upload-progress {
position: fixed;
top: 20px;
right: 20px;
background: #fff;
padding: 10px;
border: 1px solid #ccc;
border-radius: 5px;
box-shadow: 0 2px 5px rgba(0,0,0,0.2);
z-index: 9999;
}
`;
document.head.appendChild(style);
function parseFastPicResponse(responseText) {
const uploadSettingsRegex = /<UploadSettings[^>]*>([\s\S]*?)<\/UploadSettings>/g;
const results = [];
let match;
while ((match = uploadSettingsRegex.exec(responseText)) !== null) {
const settingsXml = match[0];
const status = settingsXml.match(/<status>([^<]+)<\/status>/)?.[1];
if (status === 'ok') {
const imagePath = settingsXml.match(/<imagepath>([^<]+)<\/imagepath>/)?.[1];
const thumbPath = settingsXml.match(/<thumbpath>([^<]+)<\/thumbpath>/)?.[1];
const viewUrl = settingsXml.match(/<viewurl>([^<]+)<\/viewurl>/)?.[1];
const sessionUrl = settingsXml.match(/<sessionurl>([^<]+)<\/sessionurl>/)?.[1];
if (imagePath && thumbPath && viewUrl) {
results.push({
imagePath,
thumbPath,
viewUrl,
sessionUrl
});
}
} else {
const error = settingsXml.match(/<error>([^<]+)<\/error>/)?.[1] || 'Неизвестная ошибка';
throw new Error(error);
}
}
if (results.length === 0) {
throw new Error('Не получено информации о загруженных изображениях');
}
return results;
}
async function uploadImages(files) {
const formData = new FormData();
for (let i = 0; i < files.length; i++) {
formData.append(`file${i + 1}`, files[i]);
}
formData.append('uploading', files.length.toString());
formData.append('submit', 'Загрузить');
const response = await new Promise((resolve, reject) => {
GM_xmlhttpRequest({
method: 'POST',
url: 'https://fastpic.org/upload?api=1',
data: formData,
onload: (response) => {
console.log('FastPic response:', response.responseText);
resolve(response);
},
onerror: (error) => reject(error)
});
});
return parseFastPicResponse(response.responseText);
}
textarea.addEventListener('dragover', (e) => {
e.preventDefault();
e.stopPropagation();
textarea.style.border = '2px dashed #4a90e2';
});
textarea.addEventListener('dragleave', (e) => {
textarea.style.border = '';
});
textarea.addEventListener('drop', async (e) => {
e.preventDefault();
e.stopPropagation();
textarea.style.border = '';
const files = Array.from(e.dataTransfer.files).filter(file => file.type.startsWith('image/'));
if (files.length === 0) return;
const progressDiv = document.createElement('div');
progressDiv.className = 'fastpic-upload-progress';
document.body.appendChild(progressDiv);
const cursorPos = textarea.selectionStart;
let bbCode = '';
try {
progressDiv.textContent = `Загрузка ${files.length} изображений...`;
const images = await uploadImages(files);
bbCode = images.map(({ thumbPath, viewUrl }) =>
`[url=${viewUrl}][img]${thumbPath}[/img][/url]`
).join(' ');
const textBefore = textarea.value.substring(0, cursorPos);
const textAfter = textarea.value.substring(cursorPos);
textarea.value = textBefore + bbCode + textAfter;
textarea.selectionStart = textarea.selectionEnd = cursorPos + bbCode.length;
progressDiv.textContent = `Успешно загружено ${images.length} изображений`;
} catch (error) {
console.error('Ошибка при загрузке изображений:', error);
alert(`Ошибка при загрузке изображений на FastPic: ${error.message}`);
progressDiv.textContent = 'Ошибка при загрузке изображений';
} finally {
setTimeout(() => progressDiv.remove(), 3000);
}
});
})();