From 908af9d53d1150c3e16ddf08da979af36bd4f69d Mon Sep 17 00:00:00 2001 From: vlad_rus Date: Thu, 22 Oct 2026 16:16:59 +0400 Subject: [PATCH] Add qbit-simple.js: minimal qBittorrent v5.x compatible downloader (no select, no conflict) --- qbit-simple.js | 156 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 156 insertions(+) create mode 100644 qbit-simple.js diff --git a/qbit-simple.js b/qbit-simple.js new file mode 100644 index 0000000..dfd272a --- /dev/null +++ b/qbit-simple.js @@ -0,0 +1,156 @@ +(function () { + 'use strict'; + + var PLUGIN_ID = 'lampa_qbit_simple'; + + function ready(fn) { + if (window.Lampa && Lampa.Storage) fn(); + else setInterval(function () { if (window.Lampa && Lampa.Storage) { clearInterval(arguments.callee); fn(); } }, 500); + } + + function storage(name, fallback) { + var v = Lampa.Storage.field(name); + return (v === undefined || v === null) ? fallback : v; + } + + function notify(text) { + if (Lampa.Noty && Lampa.Noty.show) Lampa.Noty.show(text); + } + + function requestForm(url, formData, onSuccess, onError) { + var xhr = new XMLHttpRequest(); + xhr.open('POST', url, true); + xhr.onreadystatechange = function () { + if (xhr.readyState !== 4) return; + if (xhr.status >= 200 && xhr.status < 300) onSuccess(xhr.responseText); + else onError(new Error('HTTP ' + xhr.status + ': ' + xhr.responseText)); + }; + xhr.send(formData); + } + + function loginDirect(baseUrl, done, fail) { + var username = storage('qbit_simple_username', 'admin'); + var password = storage('qbit_simple_password', ''); + + if (!username && !password) return done(); + + var form = new URLSearchParams(); + form.set('username', username); + form.set('password', password); + + requestForm(baseUrl + '/api/v2/auth/login', form, function (text) { + // qBittorrent v5.x: "Ok." или пустой ответ с 204 + var t = String(text).trim(); + if (t === '' || t === 'Ok.' || t === 'True.') done(); + else fail(new Error('qBittorrent auth: ' + t)); + }, fail); + } + + function download(element) { + var baseUrl = (storage('qbit_simple_url', 'http://127.0.0.1:8080')).replace(/\/+$/, ''); + var magnet = element.MagnetUri || element.magnet || element.downloadUrl || ''; + + if (!magnet) { + notify('Нет magnet-ссылки'); + return; + } + + var category = storage('qbit_simple_category', 'lampa'); + var sequential = storage('qbit_simple_sequential', true); + var firstLast = storage('qbit_simple_first_last', true); + + loginDirect(baseUrl, function () { + var form = new URLSearchParams(); + form.set('urls', magnet); + if (category) form.set('category', category); + if (sequential) form.set('sequentialDownload', 'true'); + if (firstLast) form.set('firstLastPiecePrio', 'true'); + + requestForm(baseUrl + '/api/v2/torrents/add', form, function () { + notify('✓ Отправлено в qBittorrent: ' + (element.Title || element.title || 'torrent')); + }, function (err) { + notify('Ошибка: ' + err.message); + }); + }, function (err) { + notify('Auth ошибка: ' + err.message); + }); + } + + function patchSelect() { + var original = Lampa.Select.show; + Lampa.Select.show = function (params) { + if (params && params.items) { + var modified = false; + params.items.forEach(function (item) { + if (item && (item.element && (item.element.MagnetUri || item.element.magnet))) { + if (!item.__qbit_added) { + item.__qbit_added = true; + modified = true; + } + } + }); + + // Добавляем пункт "Скачать в qBittorrent" в конец + var hasMagnet = params.items.some(function (item) { + return item && item.element && (item.element.MagnetUri || item.element.magnet); + }); + + if (hasMagnet) { + var origOnSelect = params.onSelect; + params.onSelect = function (item) { + if (item && item.__qbit_download) { + var el = params.items.find(function (i) { return i.element && (i.element.MagnetUri || i.element.magnet); }); + if (el) download(el.element); + return; + } + if (origOnSelect) origOnSelect.apply(this, arguments); + }; + params.items.push({ + __qbit_download: true, + name: '⬇ Скачать в qBittorrent', + icon: 'download' + }); + } + } + return original.call(this, params); + }; + } + + function setupSettings() { + Lampa.SettingsApi.addComponent({ + component: 'qbit_simple', + name: 'qBittorrent', + icon: '' + }); + + var fields = [ + ['qbit_simple_url', 'input', 'Адрес qBittorrent', 'http://127.0.0.1:8080'], + ['qbit_simple_username', 'input', 'Логин', 'admin'], + ['qbit_simple_password', 'input', 'Пароль', ''], + ['qbit_simple_category', 'input', 'Категория', 'lampa'], + ['qbit_simple_sequential', 'trigger', 'Sequential download', true], + ['qbit_simple_first_last', 'trigger', 'Первый/последний блок', true] + ]; + + fields.forEach(function (row) { + Lampa.SettingsApi.addParam({ + component: 'qbit_simple', + param: { + name: row[0], + type: row[1], + default: row[3] + }, + field: { + name: row[2] + } + }); + }); + } + + ready(function () { + setupSettings(); + patchSelect(); + console.log('[qbit-simple] Plugin loaded'); + }); + +})();