Compare commits
No commits in common. "main" and "v1.0" have entirely different histories.
34
README.md
34
README.md
@ -1,24 +1,20 @@
|
|||||||
# Lampa Plugins
|
# Lampa Plugins (patched)
|
||||||
|
|
||||||
## qbit-simple.js — Минимальный qBittorrent downloader (v5.x compatible)
|
Исправленные плагины для Lampa/Lampyris.
|
||||||
|
|
||||||
Рабочий плагин для отправки торрентов в qBittorrent v5.x из Lampa/Lampyris.
|
## td-fixed.js — Torrent Downloader (фикс для qBittorrent v5.x)
|
||||||
|
|
||||||
**Установка:**
|
Оригинал: https://github.com/lampame/td
|
||||||
|
|
||||||
|
**Проблема:** qBittorrent v5.x не принимает логин/пароль в URL query-параметрах
|
||||||
|
и возвращает HTTP 204 (а не 200) на успешный login. Оригинал падает с "Ошибка авторизации".
|
||||||
|
|
||||||
|
**Фикс:**
|
||||||
|
- Login через POST body вместо query params
|
||||||
|
- Принятие HTTP 204 как успеха
|
||||||
|
- encodeURIComponent() для пароля
|
||||||
|
|
||||||
|
**Установка в Lampa:**
|
||||||
```
|
```
|
||||||
http://192.168.27.107:3001/vlad_rus/lampa-plugins/raw/branch/main/qbit-simple.js
|
http://192.168.27.107:3001/vlad_rus/lampa-plugins/raw/branch/main/td-fixed.js
|
||||||
```
|
```
|
||||||
|
|
||||||
**Настройка (Настройки → qBittorrent):**
|
|
||||||
- Адрес: `http://192.168.27.107:8091`
|
|
||||||
- Логин: `admin`
|
|
||||||
- Пароль: `(ваш пароль)`
|
|
||||||
- Категория: `lampa`
|
|
||||||
|
|
||||||
**Использование:** долгий тап / правая кнопка на торренте → "⬇ Скачать в qBittorrent"
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## td-fixed.js — Патченный lampame/td (legacy)
|
|
||||||
|
|
||||||
Исправленный оригинальный плагин. Может конфликтовать с другими плагинами.
|
|
||||||
|
|||||||
156
qbit-simple.js
156
qbit-simple.js
@ -1,156 +0,0 @@
|
|||||||
(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: '<svg width="24" height="24" viewBox="0 0 24 24" fill="currentColor"><path d="M12 3a9 9 0 1 0 9 9h-2a7 7 0 1 1-7-7V3Zm1 0v8.59l3.3-3.3 1.4 1.42-5.7 5.7-5.7-5.7 1.4-1.42 3.3 3.3V3h2Z"/></svg>'
|
|
||||||
});
|
|
||||||
|
|
||||||
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');
|
|
||||||
});
|
|
||||||
|
|
||||||
})();
|
|
||||||
Loading…
Reference in New Issue
Block a user