qBittorrent API Helper

Funciones para interactuar con qBittorrent Web UI

Tento skript by neměl být instalován přímo. Jedná se o knihovnu, kterou by měly jiné skripty využívat pomocí meta příkazu // @require https://update.greatest.deepsurf.us/scripts/531519/1563838/qBittorrent%20API%20Helper.js

  1. // ==UserScript==
  2. // @name qBittorrent API Helper
  3. // @version 1.0
  4. // @description Funciones para interactuar con qBittorrent Web UI
  5. // @grant GM_xmlhttpRequest
  6. // @grant GM_notification
  7. // ==/UserScript==
  8.  
  9. class QBittorrentAPI {
  10. constructor(host, username, password) {
  11. this.host = host;
  12. this.username = username;
  13. this.password = password;
  14. this.cookie = null;
  15. }
  16.  
  17. async login() {
  18. return new Promise((resolve, reject) => {
  19. GM_xmlhttpRequest({
  20. method: "POST",
  21. url: `${this.host}/api/v2/auth/login`,
  22. headers: {
  23. "Content-Type": "application/x-www-form-urlencoded",
  24. "Referer": this.host
  25. },
  26. data: `username=${encodeURIComponent(this.username)}&password=${encodeURIComponent(this.password)}`,
  27. onload: (response) => {
  28. if (response.responseText.trim() === "Ok.") {
  29. // Obtener la cookie de la respuesta
  30. const setCookie = response.responseHeaders.match(/SID=([^;]+)/);
  31. if (setCookie) {
  32. this.cookie = setCookie[0];
  33. }
  34. resolve();
  35. } else {
  36. reject(new Error("Login fallido. Verifica usuario y contraseña."));
  37. }
  38. },
  39. onerror: (error) => {
  40. reject(new Error(`No se pudo conectar a qBittorrent: ${error.statusText}`));
  41. }
  42. });
  43. });
  44. }
  45.  
  46. async addMagnet(magnetLink) {
  47. if (!this.cookie) {
  48. await this.login();
  49. }
  50.  
  51. return new Promise((resolve, reject) => {
  52. GM_xmlhttpRequest({
  53. method: "POST",
  54. url: `${this.host}/api/v2/torrents/add`,
  55. headers: {
  56. "Content-Type": "application/x-www-form-urlencoded",
  57. "Cookie": this.cookie,
  58. "Referer": this.host
  59. },
  60. data: `urls=${encodeURIComponent(magnetLink)}`,
  61. onload: (response) => {
  62. if (response.status === 200) {
  63. resolve();
  64. } else if (response.status === 403) {
  65. // Sesión expirada, intentar reloguear
  66. this.cookie = null;
  67. this.addMagnet(magnetLink).then(resolve).catch(reject);
  68. } else {
  69. reject(new Error(`Error al agregar torrent: ${response.statusText}`));
  70. }
  71. },
  72. onerror: (error) => {
  73. reject(new Error(`Error de conexión: ${error.statusText}`));
  74. }
  75. });
  76. });
  77. }
  78.  
  79. static isValidMagnet(magnetLink) {
  80. const magnetRegex = /^magnet:\?xt=urn:[a-zA-Z0-9]+:[a-zA-Z0-9]{32,}/i;
  81. return magnetRegex.test(magnetLink);
  82. }
  83.  
  84. static showNotification(title, message, isError = false) {
  85. GM_notification({
  86. title: isError ? `⚠️ ${title}` : title,
  87. text: message,
  88. timeout: isError ? 6000 : 4000,
  89. silent: true
  90. });
  91. }
  92. }