// ==UserScript== // @name gelbooru.com Button DW ADD // @namespace nyakonya_gelbooruocdw_dev // @match https://gelbooru.com/index.php* // @grant GM_xmlhttpRequest // @grant GM_registerMenuCommand // @grant GM_getValue // @grant GM_setValue // @version 1.1r // @author https://t.me/Nyako_TW // @downloadURL https://git.nekono.su/Nyako/Local-Booru/raw/branch/main/button_script.user.js // @updateURL https://git.nekono.su/Nyako/Local-Booru/raw/branch/main/button_script.user.js // @description Adds a one-click button to download the original image on Gelbooru post pages. // ==/UserScript== 'use strict'; // Рекомендуется оставить для более строгого и безопасного выполнения кода. // Функция безопасного запуска функций function safeRun(fn, name) { try { fn(); } catch (e) { console.error(`Ошибка в ${name}:`, e); } } // Функция генерации текстовой конфигурации function registerTextInput(key, defaultValue, title, promptMessage) { const currentValue = GM_getValue(key, defaultValue); const menuText = `⚙️ ${title}: ${currentValue}`; GM_registerMenuCommand(menuText, () => { const newValue = prompt(promptMessage, currentValue); if (newValue !== null) { GM_setValue(key, newValue.trim()); alert( `Настройка изменена!\n${title}: ${newValue.trim()}\nОбновите страницу для применения настроек.` ); location.reload(); } }); } // Генерация конфигураций function config_runner() { registerTextInput( 'nyakonya_gb_api_root', 'http://127.0.2.1', 'Адрес API', 'Введите базовый URL локального API (например, http://127.0.2.1 или https://booru.loc):' ); } // Запуск конфигуратора safeRun(config_runner, "config_runner"); // 1. Находим ссылку на оригинальное изображение по тексту const params = new URLSearchParams(window.location.search); const imageID = params.get("id"); const xpathResult = document.evaluate( '//a[text()="Original image"]', document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null ); const originalImageLinkElement = xpathResult.singleNodeValue; if (originalImageLinkElement) { const imageUrl = originalImageLinkElement.href; const existingAnchor = document.querySelector('a[onclick*="saveTagSearch"]'); if (existingAnchor) { const downloadSvgIcon = ` `; const newDownloadButton = document.createElement('a'); newDownloadButton.id = "nyakonya-gelbooruocdw-geter"; newDownloadButton.title = "Download original image"; newDownloadButton.innerHTML = downloadSvgIcon; newDownloadButton.className = existingAnchor.className; newDownloadButton.style.cssText = existingAnchor.style.cssText; existingAnchor.parentNode.insertBefore(newDownloadButton, existingAnchor.nextSibling); const searchBox = document.getElementById("tags-search"); if (searchBox) { searchBox.style.width = "calc(100% - 380px)"; } console.log('Кнопка для скачивания добавлена:', newDownloadButton); newDownloadButton.addEventListener('click', (event) => { event.preventDefault(); // Отменяем стандартное действие ссылки // Получаем настроенный пользователем корневой путь const apiRoot = GM_getValue('nyakonya_gb_api_root', 'http://127.0.2.1'); // Формируем корректный URL для запроса к dw_api const apiUrl = apiRoot.endsWith('/') ? `${apiRoot}dw_api` : `${apiRoot}/dw_api`; console.log(`Отправка URL на локальный API: ${imageUrl} (Endpoint: ${apiUrl})`); const originalOutline = newDownloadButton.style.outline; newDownloadButton.style.outline = "2px solid yellow"; // Статус "в процессе" GM_xmlhttpRequest({ method: "POST", url: apiUrl, headers: { "Content-Type": "application/json" }, data: JSON.stringify({ id: imageID , type: "download"}), onload: function(response) { console.log('Ответ от API:', response.responseText); newDownloadButton.style.outline = "2px solid green"; // Успех setTimeout(() => { newDownloadButton.style.outline = originalOutline; }, 2000); }, onerror: function(response) { console.error('Ошибка при отправке на API:', response); newDownloadButton.style.outline = "2px solid red"; // Ошибка alert('Не удалось отправить на локальный загрузчик. Убедитесь, что Python-скрипт запущен и вы приняли самоподписанный сертификат в браузере. Подробности в консоли (F12).'); setTimeout(() => { newDownloadButton.style.outline = originalOutline; }, 5000); } }); }); } else { console.warn('Исходный элемент для вставки кнопки (saveTagSearch) не найден.'); } }