{"version":3,"sources":["../src/index.ts","../src/classes/QBittorrentClient.ts","../src/utils/QBittorrentClientError.ts","../src/types/QBittorrentTorrentsMethods.ts"],"sourcesContent":["// Client exports\nexport { default } from './classes/QBittorrentClient'\nexport { default as QBittorrentClient } from './classes/QBittorrentClient'\nexport * from './classes/QBittorrentClient'\n\n// Client Error exports\nexport { default as QBittorrentClientError } from './utils/QBittorrentClientError'\nexport * from './utils/QBittorrentClientError'\n\n// Types exports\nexport * from './types/QBittorrentAppMethods'\nexport * from './types/QBittorrentSyncMethods'\nexport * from './types/QBittorrentTorrentsMethods'\nexport * from './types/QBittorrentTransferMethods'","import {\n  QBittorrentTorrentContentPriority,\n  QBittorrentTorrentContents,\n  QBittorrentTorrentProperties,\n  QBittorrentTorrentsAddOptions,\n  QBittorrentTorrentTrackers,\n  TorrentInfo,\n} from '../types/QBittorrentTorrentsMethods.js'\nimport axios, { AxiosResponse } from 'axios'\nimport QBittorrentClientError, { ErrorType } from '../utils/QBittorrentClientError'\nimport { QBittorrentAppPreferences } from '../types/QBittorrentAppMethods'\nimport { QBittorrentSyncTorrentPeers, QBittorrentTorrentPeers } from '../types/QBittorrentSyncMethods'\nimport { QBittorrentTransferInfo } from '../types/QBittorrentTransferMethods'\nimport FormData from 'form-data'\n\nexport interface QBittorrentClientOptions {\n  baseUrl: string\n}\n\nexport default class QBittorrentClient {\n  httpClient = axios.create()\n  sessionCookie?: string\n\n  constructor(readonly options: QBittorrentClientOptions) {\n    this.httpClient.defaults.baseURL = this.baseUrl\n    this.httpClient.interceptors.response.use(response => response, error => {\n      if (error.response.status === 403) {\n        throw new QBittorrentClientError('Authentication needed', {\n          type: ErrorType.FORBIDDEN,\n        })\n      }\n      throw error\n    })\n  }\n\n  protected get baseUrl(): string {\n    return this.options.baseUrl + '/api/v2'\n  }\n\n  async authenticate(username?: string, password?: string): Promise<void> {\n    return this.login(username, password)\n      .then(sessionCookie => {\n        if (!sessionCookie) {\n          throw new Error('No session cookie')\n        }\n        this.sessionCookie = sessionCookie\n        this.httpClient.defaults.headers.common['Cookie'] = sessionCookie\n      })\n  }\n\n  async login(username?: string, password?: string): Promise<string | undefined> {\n    const params = new URLSearchParams()\n    if (username) params.append('username', username)\n    if (password) params.append('password', password)\n\n    return this.httpClient('auth/login', {\n      method: 'POST',\n      data: params,\n\n      withCredentials: true,\n    })\n      .then(async response => {\n          if (response.status === 403) {\n            throw new QBittorrentClientError('Too many failed attempts, your IP is banned', {\n              type: ErrorType.IP_BANNED,\n            })\n          }\n          if (response.data === 'Fails.') {\n            throw new QBittorrentClientError('Invalid credentials', {\n              type: ErrorType.INVALID_CREDENTIALS,\n            })\n          }\n\n          const cookies = response.headers['set-cookie']\n          if (Array.isArray(cookies)) {\n            return cookies\n              .find((cookie) => cookie.startsWith('SID='))\n              ?.split(';')[0]\n          }\n\n          return undefined\n        },\n        error => {\n          if (error.response.status === 403) {\n            throw new QBittorrentClientError('Too many failed attempts, your IP is banned', {\n              type: ErrorType.IP_BANNED,\n            })\n          }\n          throw error\n        },\n      )\n  }\n\n  async logout(): Promise<void> {\n    await this.httpClient('/auth/logout', {\n      method: 'POST',\n      withCredentials: true,\n    })\n  }\n\n  async version(): Promise<string> {\n    return this.httpClient.get('app/version')\n      .then(response => response.data)\n  }\n\n  async getAppPreferences(): Promise<QBittorrentAppPreferences> {\n    return this.httpClient\n      .get<QBittorrentAppPreferences>(`app/preferences`)\n      .then((res) => res.data)\n  }\n\n  async setAppPreferences(preferences: Partial<QBittorrentAppPreferences>): Promise<void> {\n    await this.httpClient\n      .post(`app/setPreferences`, `json=${ JSON.stringify(preferences) }`)\n  }\n\n  async getTorrentInfos(): Promise<Array<TorrentInfo>> {\n    return this.httpClient.get<any, AxiosResponse<Array<TorrentInfo>>>('torrents/info')\n      .then((res) => res.data)\n  }\n\n\n  async getTorrentContents(hash: string): Promise<QBittorrentTorrentContents> {\n    return this.httpClient\n      .get<QBittorrentTorrentContents>(`torrents/files`, {\n        params: {\n          hash: hash.toLowerCase(),\n        },\n\n      })\n      .then((res) => res.data)\n  }\n\n  async getTorrentProperties(hash: string): Promise<QBittorrentTorrentProperties> {\n    return this.httpClient\n      .get<QBittorrentTorrentProperties>(`torrents/properties`, {\n        params: {\n          hash: hash.toLowerCase(),\n        },\n\n      })\n      .then((res) => res.data)\n  }\n\n  async getTorrentTrackers(hash: string): Promise<QBittorrentTorrentTrackers> {\n    return this.httpClient\n      .get<QBittorrentTorrentTrackers>(`torrents/trackers`, {\n        params: {\n          hash: hash.toLowerCase(),\n        },\n\n      })\n      .then((res) => res.data)\n  }\n\n  async getTransferInfo(): Promise<QBittorrentTransferInfo> {\n    return this.httpClient\n      .get<QBittorrentTransferInfo>(`transfer/info`, {})\n      .then((res) => res.data)\n  }\n\n  // async syncMainData(): Promise<QBittorrentMainData> {\n  //   const headers = await this.getRequestHeaders()\n  //\n  //   if (this.isMainDataPending == false) {\n  //     this.isMainDataPending = true\n  //     this.syncRids.mainData = this.syncRids.mainData.then((rid) =>\n  //       this.client\n  //         .get<QBittorrentSyncMainData>(`sync/maindata`, {\n  //           params: {\n  //             rid,\n  //           },\n  //           headers,\n  //         })\n  //         .then(({ data }) => {\n  //           const {\n  //             rid: newRid = 0,\n  //             full_update = false,\n  //             categories = {},\n  //             categories_removed = [],\n  //             server_state = EMPTY_SERVER_STATE,\n  //             tags = [],\n  //             tags_removed = [],\n  //             torrents = {},\n  //             torrents_removed = [],\n  //             trackers = {},\n  //             trackers_removed = [],\n  //           } = data\n  //\n  //           if (full_update) {\n  //             this.syncStates.mainData = {\n  //               categories,\n  //               server_state,\n  //               tags,\n  //               torrents,\n  //               trackers,\n  //             }\n  //           } else {\n  //             // categories\n  //             Object.keys(categories).forEach((category) => {\n  //               this.syncStates.mainData.categories[category] = {\n  //                 ...this.syncStates.mainData.categories[category],\n  //                 ...categories[category],\n  //               }\n  //             })\n  //\n  //             categories_removed.forEach((category) => {\n  //               delete this.syncStates.mainData.categories[category]\n  //             })\n  //\n  //             // tags\n  //             this.syncStates.mainData.tags.push(...tags)\n  //             this.syncStates.mainData.tags = this.syncStates.mainData.tags.filter(\n  //               (tag) => !tags_removed.includes(tag),\n  //             )\n  //\n  //             // torrents\n  //             Object.keys(torrents).forEach((torrent) => {\n  //               this.syncStates.mainData.torrents[torrent] = {\n  //                 ...this.syncStates.mainData.torrents[torrent],\n  //                 ...torrents[torrent],\n  //               }\n  //             })\n  //\n  //             torrents_removed.forEach((torrent) => {\n  //               delete this.syncStates.mainData.torrents[torrent]\n  //             })\n  //\n  //             // trackers\n  //             Object.keys(trackers).forEach((tracker) => {\n  //               this.syncStates.mainData.trackers[tracker] = {\n  //                 ...this.syncStates.mainData.trackers[tracker],\n  //                 ...trackers[tracker],\n  //               }\n  //             })\n  //\n  //             trackers_removed.forEach((tracker) => {\n  //               delete this.syncStates.mainData.trackers[tracker]\n  //             })\n  //           }\n  //\n  //           return newRid\n  //         })\n  //         .finally(() => {\n  //           this.isMainDataPending = false\n  //         }),\n  //     )\n  //   }\n  //\n  //   try {\n  //     await this.syncRids.mainData\n  //   } catch (e) {\n  //     this.syncRids.mainData = Promise.resolve(0)\n  //     throw e\n  //   }\n  //\n  //   return this.syncStates.mainData\n  // }\n\n  async syncTorrentPeers(hash: string): Promise<QBittorrentTorrentPeers> {\n    return this.httpClient\n      .get<QBittorrentSyncTorrentPeers>(`sync/torrentPeers`, {\n        params: {\n          hash: hash.toLowerCase(),\n          rid: 0,\n        },\n\n      })\n      .then(({ data }) => data.peers)\n  }\n\n  async torrentsPause(hashes: Array<string>): Promise<void> {\n    return this.httpClient\n      .get(`torrents/pause`, {\n        params: {\n          hashes: hashes.join('|').toLowerCase(),\n        },\n\n      })\n      .then(() => {\n        // returns nothing\n      })\n  }\n\n  async torrentsResume(hashes: Array<string>): Promise<void> {\n    return this.httpClient\n      .get(`torrents/resume`, {\n        params: {\n          hashes: hashes.join('|').toLowerCase(),\n        },\n\n      })\n      .then(() => {\n        // returns nothing\n      })\n  }\n\n  async torrentsDelete(hashes: Array<string>, deleteFiles: boolean): Promise<void> {\n    return this.httpClient\n      .get(`torrents/delete`, {\n        params: {\n          hashes: hashes.join('|').toLowerCase(),\n          deleteFiles: deleteFiles ? 'true' : 'false',\n        },\n\n      })\n      .then(() => {\n        // returns nothing\n      })\n  }\n\n  async torrentsRecheck(hashes: Array<string>): Promise<void> {\n    return this.httpClient\n      .get(`torrents/recheck`, {\n        params: {\n          hashes: hashes.join('|').toLowerCase(),\n        },\n\n      })\n      .then(() => {\n        // returns nothing\n      })\n  }\n\n  async torrentsSetLocation(hashes: Array<string>, location: string): Promise<void> {\n    return this.httpClient\n      .get(`torrents/setLocation`, {\n        params: {\n          hashes: hashes.join('|').toLowerCase(),\n          location,\n        },\n\n      })\n      .then(() => {\n        // returns nothing\n      })\n  }\n\n  async torrentsSetTopPrio(hashes: Array<string>): Promise<void> {\n    return this.httpClient\n      .get(`torrents/topPrio`, {\n        params: {\n          hashes: hashes.join('|').toLowerCase(),\n        },\n\n      })\n      .then(() => {\n        // returns nothing\n      })\n  }\n\n  async torrentsSetBottomPrio(hashes: Array<string>): Promise<void> {\n    return this.httpClient\n      .get(`torrents/bottomPrio`, {\n        params: {\n          hashes: hashes.join('|').toLowerCase(),\n        },\n\n      })\n      .then(() => {\n        // returns nothing\n      })\n  }\n\n  async torrentsAddFiles(files: Array<Buffer>, options: QBittorrentTorrentsAddOptions): Promise<void> {\n    const form = new FormData()\n\n    files.forEach((file, index) => {\n      form.append('torrents', file, {\n        filename: `${ index }.torrent`,\n        contentType: 'application/x-bittorrent',\n      })\n    })\n\n    Object.keys(options).forEach((key) => {\n      const property = key as keyof typeof options\n      form.append(property, `${ options[property] }`)\n    })\n\n    const headers = form.getHeaders({\n      Cookie: this.sessionCookie,\n      'Content-Length': form.getLengthSync(),\n    })\n\n    return this.httpClient\n      .post(`torrents/add`, form, {\n        headers,\n      })\n      .then(response => {\n        // Check if operation fail.\n        // No more detail can be given in response due to the non verbosity of qBittorrent api error.\n        if (response.data === 'Fails.') {\n          throw new QBittorrentClientError('Can not add torrent file', {\n            type: ErrorType.OPERATION_FAILED,\n          })\n        }\n      })\n  }\n\n  async torrentsAddURLs(urls: Array<string>, options: QBittorrentTorrentsAddOptions): Promise<void> {\n    const form = new FormData()\n\n    form.append('urls', urls.join('\\n'))\n\n    Object.keys(options).forEach((key) => {\n      const property = key as keyof typeof options\n      form.append(property, `${ options[property] }`)\n    })\n\n    const headers = form.getHeaders({\n      Cookie: this.sessionCookie,\n      'Content-Length': form.getLengthSync(),\n    })\n\n    return this.httpClient\n      .post(`torrents/add`, form, {\n        headers,\n      })\n      .then(() => {\n        // returns nothing\n      })\n  }\n\n  async torrentsAddTags(hashes: Array<string>, tags: Array<string>): Promise<void> {\n    return this.httpClient\n      .get(`torrents/addTags`, {\n        params: {\n          hashes: hashes.join('|').toLowerCase(),\n          tags: tags.join(','),\n        },\n\n      })\n      .then(() => {\n        // returns nothing\n      })\n  }\n\n  async torrentsRemoveTags(hashes: Array<string>, tags?: Array<string>): Promise<void> {\n    return this.httpClient\n      .get(`torrents/removeTags`, {\n        params: {\n          hashes: hashes.join('|').toLowerCase(),\n          tags: tags?.join(','),\n        },\n\n      })\n      .then(() => {\n        // returns nothing\n      })\n  }\n\n  async torrentsAddTrackers(hash: string, urls: Array<string>): Promise<void> {\n    if (urls.length > 0) {\n      return this.httpClient\n        .get(`torrents/addTrackers`, {\n          params: {\n            hash: hash.toLowerCase(),\n            urls: urls.join('\\n'),\n          },\n\n        })\n        .then(() => {\n          // returns nothing\n        })\n    }\n  }\n\n  async torrentsReannounce(hashes: Array<string>): Promise<void> {\n    if (hashes.length > 0) {\n      return this.httpClient\n        .get(`torrents/reannounce`, {\n          params: {\n            hashes: hashes.join('|').toLowerCase(),\n          },\n\n        })\n        .then(() => {\n          // returns nothing\n        })\n    }\n  }\n\n  async torrentsRemoveTrackers(hash: string, urls: Array<string>): Promise<void> {\n    if (urls.length > 0) {\n      return this.httpClient\n        .get(`torrents/removeTrackers`, {\n          params: {\n            hash: hash.toLowerCase(),\n            urls: urls.join('|'),\n          },\n\n        })\n        .then(() => {\n          // returns nothing\n        })\n    }\n  }\n\n  async torrentsSetSuperSeeding(hashes: Array<string>, value: boolean): Promise<void> {\n    if (hashes.length > 0) {\n      return this.httpClient\n        .get(`torrents/setSuperSeeding`, {\n          params: {\n            hashes: hashes.join('|').toLowerCase(),\n            value: value ? 'true' : 'false',\n          },\n\n        })\n        .then(() => {\n          // returns nothing\n        })\n    }\n  }\n\n  async torrentsToggleSequentialDownload(hashes: Array<string>): Promise<void> {\n    if (hashes.length > 0) {\n      return this.httpClient\n        .get(`torrents/toggleSequentialDownload`, {\n          params: {\n            hashes: hashes.join('|').toLowerCase(),\n          },\n        })\n        .then(() => {\n          // returns nothing\n        })\n    }\n  }\n\n  async torrentsFilePrio(hash: string, ids: Array<number>, priority: QBittorrentTorrentContentPriority) {\n    return this.httpClient\n      .get(`torrents/filePrio`, {\n        params: {\n          hash: hash.toLowerCase(),\n          id: ids.join('|'),\n          priority,\n        },\n      })\n      .then(() => {\n        // returns nothing\n      })\n  }\n}","export enum ErrorType {\n  FORBIDDEN = 'FORBIDDEN',\n  IP_BANNED = 'IP_BANNED',\n  INVALID_CREDENTIALS = 'INVALID_CREDENTIALS',\n  OPERATION_FAILED = 'OPERATION_FAILED',\n}\n\nexport interface ErrorContext {\n  type?: ErrorType\n}\n\nexport default class QBittorrentClientError extends Error {\n  readonly name = 'QBittorrentClientError'\n  readonly type?: ErrorType\n\n  constructor(message?: string, context?: ErrorContext) {\n    super(message ?? 'qBittorrent client error')\n    this.type = context?.type\n  }\n}","export type QBittorrentTorrentState =\n  | 'error'\n  | 'missingFiles'\n  | 'uploading'\n  | 'pausedUP'\n  | 'queuedUP'\n  | 'stalledUP'\n  | 'checkingUP'\n  | 'forcedUP'\n  | 'allocating'\n  | 'downloading'\n  | 'metaDL'\n  | 'pausedDL'\n  | 'queuedDL'\n  | 'stalledDL'\n  | 'checkingDL'\n  | 'forcedDL'\n  | 'checkingResumeData'\n  | 'moving'\n  | 'unknown';\n\nexport interface TorrentInfo {\n  // Time (Unix Epoch) when the torrent was added to the client\n  added_on: number;\n  // Amount of data left to download (bytes)\n  amount_left: number;\n  // Whether this torrent is managed by Automatic Torrent Management\n  auto_tmm: boolean;\n  // Percentage of file pieces currently available\n  availability: number;\n  // Category of the torrent\n  category: string;\n  // Amount of transfer data completed (bytes)\n  completed: number;\n  // Time (Unix Epoch) when the torrent completed\n  completion_on: number;\n  // Torrent download speed limit (bytes/s). -1 if unlimited.\n  dl_limit: number;\n  // Torrent download speed (bytes/s)\n  dlspeed: number;\n  // Amount of data downloaded\n  downloaded: number;\n  // Amount of data downloaded this session\n  downloaded_session: number;\n  // Torrent ETA (seconds)\n  eta: number;\n  // True if first last piece are prioritized\n  f_l_piece_prio: boolean;\n  // True if force start is enabled for this torrent\n  force_start: boolean;\n  // Torrent hash\n  hash: string;\n  // Last time (Unix Epoch) when a chunk was downloaded/uploaded\n  last_activity: number;\n  // Magnet URI corresponding to this torrent\n  magnet_uri: string;\n  // Maximum share ratio until torrent is stopped from seeding/uploading\n  max_ratio: number;\n  // Maximum seeding time (seconds) until torrent is stopped from seeding\n  max_seeding_time: number;\n  // Torrent name\n  name: string;\n  // Number of seeds in the swarm\n  num_complete: number;\n  // Number of leechers in the swarm\n  num_incomplete: number;\n  // Number of leechers connected to\n  num_leechs: number;\n  // Number of seeds connected to\n  num_seeds: number;\n  // Torrent priority. Returns -1 if queuing is disabled or torrent is in seed mode\n  priority: number;\n  // Torrent progress (percentage/100)\n  progress: number;\n  // Torrent share ratio. Max ratio value: 9999.\n  ratio: number;\n  // TODO (what is different from max_ratio?)\n  ratio_limit: number;\n  // Path where this torrent's data is stored\n  save_path: string;\n  // TODO (what is different from max_seeding_time?)\n  seeding_time_limit: number;\n  // Time (Unix Epoch) when this torrent was last seen complete\n  seen_complete: number;\n  // True if sequential download is enabled\n  seq_dl: boolean;\n  // Total size (bytes) of files selected for download\n  size: number;\n  // Torrent state\n  state: QBittorrentTorrentState;\n  // True if super seeding is enabled\n  super_seeding: boolean;\n  // Comma-concatenated tag list of the torrent\n  tags: string;\n  // Total active time (seconds)\n  time_active: number;\n  // Total size (bytes) of all file in this torrent (including unselected ones)\n  total_size: number;\n  // The first tracker with working status. Returns empty string if no tracker is working.\n  tracker: string;\n  // Torrent upload speed limit (bytes/s). -1 if unlimited.\n  up_limit: number;\n  // Amount of data uploaded\n  uploaded: number;\n  // Amount of data uploaded this session\n  uploaded_session: number;\n  // Torrent upload speed (bytes/s)\n  upspeed: number;\n}\n\nexport interface QBittorrentTorrentsAddOptions {\n  // Download folder\n  savepath?: string;\n  // Cookie sent to download the .torrent file\n  cookie?: string;\n  // Category for the torrent\n  category?: string;\n  // Tags for the torrent, split by ','\n  tags?: string;\n  // Skip hash checking. Possible values are true, false (default)\n  skip_checking?: boolean;\n  // Add torrents in the paused state. Possible values are true, false (default)\n  paused?: boolean;\n  // Create the root folder. Possible values are true, false, unset (default)\n  root_folder?: boolean;\n  // Content layout mode, replaces root_folder\n  contentLayout?: 'Original' | 'Subfolder' | 'NoSubfolder';\n  // Rename torrent\n  rename?: string;\n  // Set torrent upload speed limit. Unit in bytes/second\n  upLimit?: number;\n  // Set torrent download speed limit. Unit in bytes/second\n  dlLimit?: number;\n  // Whether Automatic Torrent Management should be used\n  autoTMM?: boolean;\n  // Enable sequential download. Possible values are true, false (default)\n  sequentialDownload?: boolean;\n  // Prioritize download first last piece. Possible values are true, false (default)\n  firstLastPiecePrio?: boolean;\n}\n\nexport enum QBittorrentTorrentContentPriority {\n  DO_NOT_DOWNLOAD = 0,\n  NORMAL = 1,\n  HIGH = 6,\n  MAXIMUM = 7,\n}\n\nexport interface QBittorrentTorrentContent {\n  // File name (including relative path)\n  name: string;\n  // File size (bytes)\n  size: number;\n  // File progress (percentage/100)\n  progress: number;\n  // File priority\n  priority: QBittorrentTorrentContentPriority;\n  // True if file is seeding/complete\n  is_seed: boolean;\n  // The first number is the starting piece index and the second number is the ending piece index (inclusive)\n  piece_range: Array<number>;\n  // Percentage of file pieces currently available\n  availability: number;\n}\n\nexport type QBittorrentTorrentContents = Array<QBittorrentTorrentContent>;\n\nexport interface QBittorrentTorrentProperties {\n  // Torrent save path\n  save_path: string;\n  // Torrent creation date (Unix timestamp)\n  creation_date: number;\n  // Torrent piece size (bytes)\n  piece_size: number;\n  // Torrent comment\n  comment: string;\n  // Total data wasted for torrent (bytes)\n  total_wasted: number;\n  // Total data uploaded for torrent (bytes)\n  total_uploaded: number;\n  // Total data uploaded this session (bytes)\n  total_uploaded_session: number;\n  // Total data downloaded for torrent (bytes)\n  total_downloaded: number;\n  // Total data downloaded this session (bytes)\n  total_downloaded_session: number;\n  // Torrent upload limit (bytes/s)\n  up_limit: number;\n  // Torrent download limit (bytes/s)\n  dl_limit: number;\n  // Torrent elapsed time (seconds)\n  time_elapsed: number;\n  // Torrent elapsed time while complete (seconds)\n  seeding_time: number;\n  // Torrent connection count\n  nb_connections: number;\n  // Torrent connection count limit\n  nb_connections_limit: number;\n  // Torrent share ratio\n  share_ratio: number;\n  // When this torrent was added (unix timestamp)\n  addition_date: number;\n  // Torrent completion date (unix timestamp)\n  completion_date: number;\n  // Torrent creator\n  created_by: string;\n  // Torrent average download speed (bytes/second)\n  dl_speed_avg: number;\n  // Torrent download speed (bytes/second)\n  dl_speed: number;\n  // Torrent ETA (seconds)\n  eta: number;\n  // Last seen complete date (unix timestamp)\n  last_seen: number;\n  // Number of peers connected to\n  peers: number;\n  // Number of peers in the swarm\n  peers_total: number;\n  // Number of pieces owned\n  pieces_have: number;\n  // Number of pieces of the torrent\n  pieces_num: number;\n  // Number of seconds until the next announce\n  reannounce: number;\n  // Number of seeds connected to\n  seeds: number;\n  // Number of seeds in the swarm\n  seeds_total: number;\n  // Torrent total size (bytes)\n  total_size: number;\n  // Torrent average upload speed (bytes/second)\n  up_speed_avg: number;\n  // Torrent upload speed (bytes/second)\n  up_speed: number;\n}\n\nexport enum QBittorrentTorrentTrackerStatus {\n  // Tracker is disabled (used for DHT, PeX, and LSD)\n  DISABLED = 0,\n  // Tracker has not been contacted yet\n  NOT_CONTACTED = 1,\n  // Tracker has been contacted and is working\n  CONTACTED = 2,\n  // Tracker is updating\n  UPDATING = 3,\n  // Tracker has been contacted, but it is not working (or doesn't send proper replies)\n  ERROR = 4,\n}\n\nexport interface QBittorrentTorrentTracker {\n  // Tracker url\n  url: string;\n  // Tracker status\n  status: QBittorrentTorrentTrackerStatus;\n  // Tracker priority tier. Lower tier trackers are tried before higher tiers\n  tier: number;\n  // Number of peers for current torrent, as reported by the tracker\n  num_peers: number;\n  // Number of seeds for current torrent, as reported by the tracker\n  num_seeds: number;\n  // Number of leeches for current torrent, as reported by the tracker\n  num_leeches: number;\n  // Number of completed downloads for current torrent, as reported by the tracker\n  num_downloaded: number;\n  // Tracker message (there is no way of knowing what this message is - it's up to tracker admins)\n  msg: string;\n}\n\nexport type QBittorrentTorrentTrackers = Array<QBittorrentTorrentTracker>;\n"],"mappings":"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","names":["ErrorType","axios","FormData","QBittorrentTorrentContentPriority","QBittorrentTorrentTrackerStatus"]}