mirror of
https://github.com/qbittorrent/qBittorrent.git
synced 2026-01-02 21:52:32 -06:00
@@ -62,8 +62,7 @@ window.qBittorrent.Cache ??= (() => {
|
||||
if (!response.ok)
|
||||
return;
|
||||
|
||||
const responseText = await response.text();
|
||||
const responseJSON = JSON.parse(responseText);
|
||||
const responseJSON = await response.json();
|
||||
deepFreeze(responseJSON);
|
||||
this.#m_store = responseJSON;
|
||||
});
|
||||
|
||||
@@ -748,199 +748,199 @@ window.addEventListener("DOMContentLoaded", () => {
|
||||
let syncMainDataTimeoutID = -1;
|
||||
let syncRequestInProgress = false;
|
||||
const syncMainData = () => {
|
||||
const url = new URI("api/v2/sync/maindata");
|
||||
url.setData("rid", syncMainDataLastResponseId);
|
||||
const request = new Request.JSON({
|
||||
url: url,
|
||||
noCache: true,
|
||||
method: "get",
|
||||
onFailure: () => {
|
||||
const errorDiv = $("error_div");
|
||||
if (errorDiv)
|
||||
errorDiv.textContent = "QBT_TR(qBittorrent client is not reachable)QBT_TR[CONTEXT=HttpServer]";
|
||||
syncRequestInProgress = false;
|
||||
syncData(2000);
|
||||
},
|
||||
onSuccess: (response) => {
|
||||
$("error_div").textContent = "";
|
||||
if (response) {
|
||||
clearTimeout(torrentsFilterInputTimer);
|
||||
torrentsFilterInputTimer = -1;
|
||||
syncRequestInProgress = true;
|
||||
fetch(new URI("api/v2/sync/maindata").setData("rid", syncMainDataLastResponseId), {
|
||||
method: "GET",
|
||||
cache: "no-store"
|
||||
})
|
||||
.then(async (response) => {
|
||||
if (response.ok) {
|
||||
$("error_div").textContent = "";
|
||||
|
||||
let torrentsTableSelectedRows;
|
||||
let updateStatuses = false;
|
||||
let update_categories = false;
|
||||
let updateTags = false;
|
||||
let updateTrackers = false;
|
||||
let updateTorrents = false;
|
||||
const full_update = (response["full_update"] === true);
|
||||
if (full_update) {
|
||||
torrentsTableSelectedRows = torrentsTable.selectedRowsIds();
|
||||
updateStatuses = true;
|
||||
update_categories = true;
|
||||
updateTags = true;
|
||||
updateTrackers = true;
|
||||
updateTorrents = true;
|
||||
torrentsTable.clear();
|
||||
category_list.clear();
|
||||
tagList.clear();
|
||||
trackerList.clear();
|
||||
}
|
||||
if (response["rid"])
|
||||
syncMainDataLastResponseId = response["rid"];
|
||||
if (response["categories"]) {
|
||||
for (const key in response["categories"]) {
|
||||
if (!Object.hasOwn(response["categories"], key))
|
||||
continue;
|
||||
const responseJSON = await response.json();
|
||||
|
||||
const responseCategory = response["categories"][key];
|
||||
const categoryHash = window.qBittorrent.Misc.genHash(key);
|
||||
const category = category_list.get(categoryHash);
|
||||
if (category !== undefined) {
|
||||
// only the save path can change for existing categories
|
||||
category.savePath = responseCategory.savePath;
|
||||
}
|
||||
else {
|
||||
category_list.set(categoryHash, {
|
||||
name: responseCategory.name,
|
||||
savePath: responseCategory.savePath,
|
||||
torrents: new Set()
|
||||
});
|
||||
}
|
||||
}
|
||||
update_categories = true;
|
||||
}
|
||||
if (response["categories_removed"]) {
|
||||
response["categories_removed"].each((category) => {
|
||||
const categoryHash = window.qBittorrent.Misc.genHash(category);
|
||||
category_list.delete(categoryHash);
|
||||
});
|
||||
update_categories = true;
|
||||
}
|
||||
if (response["tags"]) {
|
||||
for (const tag of response["tags"]) {
|
||||
const tagHash = window.qBittorrent.Misc.genHash(tag);
|
||||
if (!tagList.has(tagHash)) {
|
||||
tagList.set(tagHash, {
|
||||
name: tag,
|
||||
torrents: new Set()
|
||||
});
|
||||
}
|
||||
}
|
||||
updateTags = true;
|
||||
}
|
||||
if (response["tags_removed"]) {
|
||||
for (let i = 0; i < response["tags_removed"].length; ++i) {
|
||||
const tagHash = window.qBittorrent.Misc.genHash(response["tags_removed"][i]);
|
||||
tagList.delete(tagHash);
|
||||
}
|
||||
updateTags = true;
|
||||
}
|
||||
if (response["trackers"]) {
|
||||
for (const [tracker, torrents] of Object.entries(response["trackers"])) {
|
||||
const host = window.qBittorrent.Misc.getHost(tracker);
|
||||
const hash = window.qBittorrent.Misc.genHash(host);
|
||||
clearTimeout(torrentsFilterInputTimer);
|
||||
torrentsFilterInputTimer = -1;
|
||||
|
||||
let trackerListItem = trackerList.get(hash);
|
||||
if (trackerListItem === undefined) {
|
||||
trackerListItem = { host: host, trackerTorrentMap: new Map() };
|
||||
trackerList.set(hash, trackerListItem);
|
||||
}
|
||||
trackerListItem.trackerTorrentMap.set(tracker, new Set(torrents));
|
||||
let torrentsTableSelectedRows;
|
||||
let updateStatuses = false;
|
||||
let update_categories = false;
|
||||
let updateTags = false;
|
||||
let updateTrackers = false;
|
||||
let updateTorrents = false;
|
||||
const fullUpdate = (responseJSON["fullUpdate"] === true);
|
||||
if (fullUpdate) {
|
||||
torrentsTableSelectedRows = torrentsTable.selectedRowsIds();
|
||||
updateStatuses = true;
|
||||
update_categories = true;
|
||||
updateTags = true;
|
||||
updateTrackers = true;
|
||||
updateTorrents = true;
|
||||
torrentsTable.clear();
|
||||
category_list.clear();
|
||||
tagList.clear();
|
||||
trackerList.clear();
|
||||
}
|
||||
updateTrackers = true;
|
||||
}
|
||||
if (response["trackers_removed"]) {
|
||||
for (let i = 0; i < response["trackers_removed"].length; ++i) {
|
||||
const tracker = response["trackers_removed"][i];
|
||||
const host = window.qBittorrent.Misc.getHost(tracker);
|
||||
const hash = window.qBittorrent.Misc.genHash(host);
|
||||
const trackerListEntry = trackerList.get(hash);
|
||||
if (trackerListEntry) {
|
||||
trackerListEntry.trackerTorrentMap.delete(tracker);
|
||||
// Remove unused trackers
|
||||
if (trackerListEntry.trackerTorrentMap.size === 0) {
|
||||
trackerList.delete(hash);
|
||||
if (selectedTracker === hash) {
|
||||
selectedTracker = TRACKERS_ALL;
|
||||
LocalPreferences.set("selected_tracker", selectedTracker.toString());
|
||||
if (responseJSON["rid"])
|
||||
syncMainDataLastResponseId = responseJSON["rid"];
|
||||
if (responseJSON["categories"]) {
|
||||
for (const key in responseJSON["categories"]) {
|
||||
if (!Object.hasOwn(responseJSON["categories"], key))
|
||||
continue;
|
||||
|
||||
const responseCategory = responseJSON["categories"][key];
|
||||
const categoryHash = window.qBittorrent.Misc.genHash(key);
|
||||
const category = category_list.get(categoryHash);
|
||||
if (category !== undefined) {
|
||||
// only the save path can change for existing categories
|
||||
category.savePath = responseCategory.savePath;
|
||||
}
|
||||
else {
|
||||
category_list.set(categoryHash, {
|
||||
name: responseCategory.name,
|
||||
savePath: responseCategory.savePath,
|
||||
torrents: new Set()
|
||||
});
|
||||
}
|
||||
}
|
||||
update_categories = true;
|
||||
}
|
||||
if (responseJSON["categories_removed"]) {
|
||||
responseJSON["categories_removed"].each((category) => {
|
||||
const categoryHash = window.qBittorrent.Misc.genHash(category);
|
||||
category_list.delete(categoryHash);
|
||||
});
|
||||
update_categories = true;
|
||||
}
|
||||
if (responseJSON["tags"]) {
|
||||
for (const tag of responseJSON["tags"]) {
|
||||
const tagHash = window.qBittorrent.Misc.genHash(tag);
|
||||
if (!tagList.has(tagHash)) {
|
||||
tagList.set(tagHash, {
|
||||
name: tag,
|
||||
torrents: new Set()
|
||||
});
|
||||
}
|
||||
}
|
||||
updateTags = true;
|
||||
}
|
||||
if (responseJSON["tags_removed"]) {
|
||||
for (let i = 0; i < responseJSON["tags_removed"].length; ++i) {
|
||||
const tagHash = window.qBittorrent.Misc.genHash(responseJSON["tags_removed"][i]);
|
||||
tagList.delete(tagHash);
|
||||
}
|
||||
updateTags = true;
|
||||
}
|
||||
if (responseJSON["trackers"]) {
|
||||
for (const [tracker, torrents] of Object.entries(responseJSON["trackers"])) {
|
||||
const host = window.qBittorrent.Misc.getHost(tracker);
|
||||
const hash = window.qBittorrent.Misc.genHash(host);
|
||||
|
||||
let trackerListItem = trackerList.get(hash);
|
||||
if (trackerListItem === undefined) {
|
||||
trackerListItem = { host: host, trackerTorrentMap: new Map() };
|
||||
trackerList.set(hash, trackerListItem);
|
||||
}
|
||||
trackerListItem.trackerTorrentMap.set(tracker, new Set(torrents));
|
||||
}
|
||||
updateTrackers = true;
|
||||
}
|
||||
if (responseJSON["trackers_removed"]) {
|
||||
for (let i = 0; i < responseJSON["trackers_removed"].length; ++i) {
|
||||
const tracker = responseJSON["trackers_removed"][i];
|
||||
const host = window.qBittorrent.Misc.getHost(tracker);
|
||||
const hash = window.qBittorrent.Misc.genHash(host);
|
||||
const trackerListEntry = trackerList.get(hash);
|
||||
if (trackerListEntry) {
|
||||
trackerListEntry.trackerTorrentMap.delete(tracker);
|
||||
// Remove unused trackers
|
||||
if (trackerListEntry.trackerTorrentMap.size === 0) {
|
||||
trackerList.delete(hash);
|
||||
if (selectedTracker === hash) {
|
||||
selectedTracker = TRACKERS_ALL;
|
||||
LocalPreferences.set("selected_tracker", selectedTracker.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
updateTrackers = true;
|
||||
}
|
||||
updateTrackers = true;
|
||||
}
|
||||
if (response["torrents"]) {
|
||||
for (const key in response["torrents"]) {
|
||||
if (!Object.hasOwn(response["torrents"], key))
|
||||
continue;
|
||||
if (responseJSON["torrents"]) {
|
||||
for (const key in responseJSON["torrents"]) {
|
||||
if (!Object.hasOwn(responseJSON["torrents"], key))
|
||||
continue;
|
||||
|
||||
response["torrents"][key]["hash"] = key;
|
||||
response["torrents"][key]["rowId"] = key;
|
||||
if (response["torrents"][key]["state"]) {
|
||||
const state = response["torrents"][key]["state"];
|
||||
response["torrents"][key]["status"] = state;
|
||||
response["torrents"][key]["_statusOrder"] = statusSortOrder[state];
|
||||
updateStatuses = true;
|
||||
responseJSON["torrents"][key]["hash"] = key;
|
||||
responseJSON["torrents"][key]["rowId"] = key;
|
||||
if (responseJSON["torrents"][key]["state"]) {
|
||||
const state = responseJSON["torrents"][key]["state"];
|
||||
responseJSON["torrents"][key]["status"] = state;
|
||||
responseJSON["torrents"][key]["_statusOrder"] = statusSortOrder[state];
|
||||
updateStatuses = true;
|
||||
}
|
||||
torrentsTable.updateRowData(responseJSON["torrents"][key]);
|
||||
if (addTorrentToCategoryList(responseJSON["torrents"][key]))
|
||||
update_categories = true;
|
||||
if (addTorrentToTagList(responseJSON["torrents"][key]))
|
||||
updateTags = true;
|
||||
updateTorrents = true;
|
||||
}
|
||||
torrentsTable.updateRowData(response["torrents"][key]);
|
||||
if (addTorrentToCategoryList(response["torrents"][key]))
|
||||
update_categories = true;
|
||||
if (addTorrentToTagList(response["torrents"][key]))
|
||||
updateTags = true;
|
||||
}
|
||||
if (responseJSON["torrents_removed"]) {
|
||||
responseJSON["torrents_removed"].each((hash) => {
|
||||
torrentsTable.removeRow(hash);
|
||||
removeTorrentFromCategoryList(hash);
|
||||
update_categories = true; // Always to update All category
|
||||
removeTorrentFromTagList(hash);
|
||||
updateTags = true; // Always to update All tag
|
||||
});
|
||||
updateTorrents = true;
|
||||
updateStatuses = true;
|
||||
}
|
||||
}
|
||||
if (response["torrents_removed"]) {
|
||||
response["torrents_removed"].each((hash) => {
|
||||
torrentsTable.removeRow(hash);
|
||||
removeTorrentFromCategoryList(hash);
|
||||
update_categories = true; // Always to update All category
|
||||
removeTorrentFromTagList(hash);
|
||||
updateTags = true; // Always to update All tag
|
||||
});
|
||||
updateTorrents = true;
|
||||
updateStatuses = true;
|
||||
}
|
||||
|
||||
// don't update the table unnecessarily
|
||||
if (updateTorrents)
|
||||
torrentsTable.updateTable(full_update);
|
||||
// don't update the table unnecessarily
|
||||
if (updateTorrents)
|
||||
torrentsTable.updateTable(fullUpdate);
|
||||
|
||||
if (response["server_state"]) {
|
||||
const tmp = response["server_state"];
|
||||
for (const k in tmp) {
|
||||
if (!Object.hasOwn(tmp, k))
|
||||
continue;
|
||||
serverState[k] = tmp[k];
|
||||
if (responseJSON["server_state"]) {
|
||||
const tmp = responseJSON["server_state"];
|
||||
for (const k in tmp) {
|
||||
if (!Object.hasOwn(tmp, k))
|
||||
continue;
|
||||
serverState[k] = tmp[k];
|
||||
}
|
||||
processServerState();
|
||||
}
|
||||
processServerState();
|
||||
|
||||
if (updateStatuses)
|
||||
updateFiltersList();
|
||||
|
||||
if (update_categories) {
|
||||
updateCategoryList();
|
||||
window.qBittorrent.TransferList.contextMenu.updateCategoriesSubMenu(category_list);
|
||||
}
|
||||
if (updateTags) {
|
||||
updateTagList();
|
||||
window.qBittorrent.TransferList.contextMenu.updateTagsSubMenu(tagList);
|
||||
}
|
||||
if (updateTrackers)
|
||||
updateTrackerList();
|
||||
|
||||
if (fullUpdate)
|
||||
// re-select previously selected rows
|
||||
torrentsTable.reselectRows(torrentsTableSelectedRows);
|
||||
}
|
||||
|
||||
if (updateStatuses)
|
||||
updateFiltersList();
|
||||
|
||||
if (update_categories) {
|
||||
updateCategoryList();
|
||||
window.qBittorrent.TransferList.contextMenu.updateCategoriesSubMenu(category_list);
|
||||
}
|
||||
if (updateTags) {
|
||||
updateTagList();
|
||||
window.qBittorrent.TransferList.contextMenu.updateTagsSubMenu(tagList);
|
||||
}
|
||||
if (updateTrackers)
|
||||
updateTrackerList();
|
||||
|
||||
if (full_update)
|
||||
// re-select previously selected rows
|
||||
torrentsTable.reselectRows(torrentsTableSelectedRows);
|
||||
}
|
||||
syncRequestInProgress = false;
|
||||
syncData(window.qBittorrent.Client.getSyncMainDataInterval());
|
||||
}
|
||||
});
|
||||
syncRequestInProgress = true;
|
||||
request.send();
|
||||
syncRequestInProgress = false;
|
||||
syncData(window.qBittorrent.Client.getSyncMainDataInterval());
|
||||
},
|
||||
(error) => {
|
||||
const errorDiv = $("error_div");
|
||||
if (errorDiv)
|
||||
errorDiv.textContent = "QBT_TR(qBittorrent client is not reachable)QBT_TR[CONTEXT=HttpServer]";
|
||||
syncRequestInProgress = false;
|
||||
syncData(2000);
|
||||
});
|
||||
};
|
||||
|
||||
updateMainData = () => {
|
||||
@@ -1101,18 +1101,19 @@ window.addEventListener("DOMContentLoaded", () => {
|
||||
// Change icon immediately to give some feedback
|
||||
updateAltSpeedIcon(!alternativeSpeedLimits);
|
||||
|
||||
new Request({
|
||||
url: "api/v2/transfer/toggleSpeedLimitsMode",
|
||||
method: "post",
|
||||
onComplete: () => {
|
||||
fetch("api/v2/transfer/toggleSpeedLimitsMode", {
|
||||
method: "POST"
|
||||
})
|
||||
.then((response) => {
|
||||
if (!response.ok) {
|
||||
// Restore icon in case of failure
|
||||
updateAltSpeedIcon(alternativeSpeedLimits);
|
||||
return;
|
||||
}
|
||||
|
||||
alternativeSpeedLimits = !alternativeSpeedLimits;
|
||||
updateMainData();
|
||||
},
|
||||
onFailure: () => {
|
||||
// Restore icon in case of failure
|
||||
updateAltSpeedIcon(alternativeSpeedLimits);
|
||||
}
|
||||
}).send();
|
||||
});
|
||||
});
|
||||
|
||||
$("DlInfos").addEventListener("click", () => { globalDownloadLimitFN(); });
|
||||
|
||||
@@ -36,26 +36,28 @@ window.qBittorrent.Download ??= (() => {
|
||||
let defaultSavePath = "";
|
||||
|
||||
const getCategories = () => {
|
||||
new Request.JSON({
|
||||
url: "api/v2/torrents/categories",
|
||||
method: "get",
|
||||
noCache: true,
|
||||
onSuccess: (data) => {
|
||||
if (data) {
|
||||
categories = data;
|
||||
for (const i in data) {
|
||||
if (!Object.hasOwn(data, i))
|
||||
continue;
|
||||
fetch("api/v2/torrents/categories", {
|
||||
method: "GET",
|
||||
cache: "no-store"
|
||||
})
|
||||
.then(async (response) => {
|
||||
if (!response.ok)
|
||||
return;
|
||||
|
||||
const category = data[i];
|
||||
const option = document.createElement("option");
|
||||
option.value = category.name;
|
||||
option.textContent = category.name;
|
||||
$("categorySelect").appendChild(option);
|
||||
}
|
||||
const data = await response.json();
|
||||
|
||||
categories = data;
|
||||
for (const i in data) {
|
||||
if (!Object.hasOwn(data, i))
|
||||
continue;
|
||||
|
||||
const category = data[i];
|
||||
const option = document.createElement("option");
|
||||
option.value = category.name;
|
||||
option.textContent = category.name;
|
||||
$("categorySelect").appendChild(option);
|
||||
}
|
||||
}
|
||||
}).send();
|
||||
});
|
||||
};
|
||||
|
||||
const getPreferences = () => {
|
||||
|
||||
@@ -308,18 +308,20 @@ window.qBittorrent.PropFiles ??= (() => {
|
||||
clearTimeout(loadTorrentFilesDataTimer);
|
||||
loadTorrentFilesDataTimer = -1;
|
||||
|
||||
new Request({
|
||||
url: "api/v2/torrents/filePrio",
|
||||
method: "post",
|
||||
data: {
|
||||
"hash": current_hash,
|
||||
"id": fileIds.join("|"),
|
||||
"priority": priority
|
||||
},
|
||||
onComplete: () => {
|
||||
fetch("api/v2/torrents/filePrio", {
|
||||
method: "POST",
|
||||
body: new URLSearchParams({
|
||||
"hash": current_hash,
|
||||
"id": fileIds.join("|"),
|
||||
"priority": priority
|
||||
})
|
||||
})
|
||||
.then((response) => {
|
||||
if (!response.ok)
|
||||
return;
|
||||
|
||||
loadTorrentFilesDataTimer = loadTorrentFilesData.delay(1000);
|
||||
}
|
||||
}).send();
|
||||
});
|
||||
|
||||
const ignore = (priority === FilePriority.Ignored);
|
||||
ids.forEach((_id) => {
|
||||
@@ -352,16 +354,16 @@ window.qBittorrent.PropFiles ??= (() => {
|
||||
current_hash = new_hash;
|
||||
loadedNewTorrent = true;
|
||||
}
|
||||
const url = new URI("api/v2/torrents/files?hash=" + current_hash);
|
||||
new Request.JSON({
|
||||
url: url,
|
||||
method: "get",
|
||||
noCache: true,
|
||||
onComplete: () => {
|
||||
clearTimeout(loadTorrentFilesDataTimer);
|
||||
loadTorrentFilesDataTimer = loadTorrentFilesData.delay(5000);
|
||||
},
|
||||
onSuccess: (files) => {
|
||||
fetch(new URI("api/v2/torrents/files").setData("hash", current_hash), {
|
||||
method: "GET",
|
||||
cache: "no-store"
|
||||
})
|
||||
.then(async (response) => {
|
||||
if (!response.ok)
|
||||
return;
|
||||
|
||||
const files = await response.json();
|
||||
|
||||
clearTimeout(torrentFilesFilterInputTimer);
|
||||
torrentFilesFilterInputTimer = -1;
|
||||
|
||||
@@ -373,8 +375,11 @@ window.qBittorrent.PropFiles ??= (() => {
|
||||
if (loadedNewTorrent)
|
||||
collapseAllNodes();
|
||||
}
|
||||
}
|
||||
}).send();
|
||||
})
|
||||
.finally(() => {
|
||||
clearTimeout(loadTorrentFilesDataTimer);
|
||||
loadTorrentFilesDataTimer = loadTorrentFilesData.delay(5000);
|
||||
});
|
||||
};
|
||||
|
||||
const updateData = () => {
|
||||
|
||||
@@ -87,18 +87,22 @@ window.qBittorrent.PropGeneral ??= (() => {
|
||||
clearTimeout(loadTorrentDataTimer);
|
||||
return;
|
||||
}
|
||||
const url = new URI("api/v2/torrents/properties?hash=" + current_id);
|
||||
new Request.JSON({
|
||||
url: url,
|
||||
method: "get",
|
||||
noCache: true,
|
||||
onFailure: () => {
|
||||
$("error_div").textContent = "QBT_TR(qBittorrent client is not reachable)QBT_TR[CONTEXT=HttpServer]";
|
||||
clearTimeout(loadTorrentDataTimer);
|
||||
loadTorrentDataTimer = loadTorrentData.delay(10000);
|
||||
},
|
||||
onSuccess: (data) => {
|
||||
|
||||
fetch(new URI("api/v2/torrents/properties").setData("hash", current_id), {
|
||||
method: "GET",
|
||||
cache: "no-store"
|
||||
})
|
||||
.then(async (response) => {
|
||||
if (!response.ok) {
|
||||
$("error_div").textContent = "QBT_TR(qBittorrent client is not reachable)QBT_TR[CONTEXT=HttpServer]";
|
||||
clearTimeout(loadTorrentDataTimer);
|
||||
loadTorrentDataTimer = loadTorrentData.delay(10000);
|
||||
return;
|
||||
}
|
||||
|
||||
$("error_div").textContent = "";
|
||||
|
||||
const data = await response.json();
|
||||
if (data) {
|
||||
// Update Torrent data
|
||||
|
||||
@@ -224,22 +228,23 @@ window.qBittorrent.PropGeneral ??= (() => {
|
||||
}
|
||||
clearTimeout(loadTorrentDataTimer);
|
||||
loadTorrentDataTimer = loadTorrentData.delay(5000);
|
||||
}
|
||||
}).send();
|
||||
});
|
||||
|
||||
fetch(new URI("api/v2/torrents/pieceStates").setData("hash", current_id), {
|
||||
method: "GET",
|
||||
cache: "no-store"
|
||||
})
|
||||
.then(async (response) => {
|
||||
if (!response.ok) {
|
||||
$("error_div").textContent = "QBT_TR(qBittorrent client is not reachable)QBT_TR[CONTEXT=HttpServer]";
|
||||
clearTimeout(loadTorrentDataTimer);
|
||||
loadTorrentDataTimer = loadTorrentData.delay(10000);
|
||||
return;
|
||||
}
|
||||
|
||||
const piecesUrl = new URI("api/v2/torrents/pieceStates?hash=" + current_id);
|
||||
new Request.JSON({
|
||||
url: piecesUrl,
|
||||
method: "get",
|
||||
noCache: true,
|
||||
onFailure: () => {
|
||||
$("error_div").textContent = "QBT_TR(qBittorrent client is not reachable)QBT_TR[CONTEXT=HttpServer]";
|
||||
clearTimeout(loadTorrentDataTimer);
|
||||
loadTorrentDataTimer = loadTorrentData.delay(10000);
|
||||
},
|
||||
onSuccess: (data) => {
|
||||
$("error_div").textContent = "";
|
||||
|
||||
const data = await response.json();
|
||||
if (data)
|
||||
piecesBar.setPieces(data);
|
||||
else
|
||||
@@ -247,8 +252,7 @@ window.qBittorrent.PropGeneral ??= (() => {
|
||||
|
||||
clearTimeout(loadTorrentDataTimer);
|
||||
loadTorrentDataTimer = loadTorrentData.delay(5000);
|
||||
}
|
||||
}).send();
|
||||
});
|
||||
};
|
||||
|
||||
const updateData = () => {
|
||||
|
||||
@@ -56,44 +56,45 @@ window.qBittorrent.PropPeers ??= (() => {
|
||||
clearTimeout(loadTorrentPeersTimer);
|
||||
return;
|
||||
}
|
||||
const url = new URI("api/v2/sync/torrentPeers");
|
||||
url.setData("rid", syncTorrentPeersLastResponseId);
|
||||
url.setData("hash", current_hash);
|
||||
new Request.JSON({
|
||||
url: url,
|
||||
method: "get",
|
||||
noCache: true,
|
||||
onComplete: () => {
|
||||
clearTimeout(loadTorrentPeersTimer);
|
||||
loadTorrentPeersTimer = loadTorrentPeersData.delay(window.qBittorrent.Client.getSyncMainDataInterval());
|
||||
},
|
||||
onSuccess: (response) => {
|
||||
const url = new URI("api/v2/sync/torrentPeers")
|
||||
.setData("rid", syncTorrentPeersLastResponseId)
|
||||
.setData("hash", current_hash);
|
||||
fetch(url, {
|
||||
method: "GET",
|
||||
cache: "no-store"
|
||||
})
|
||||
.then(async (response) => {
|
||||
if (!response.ok)
|
||||
return;
|
||||
|
||||
const responseJSON = await response.json();
|
||||
|
||||
$("error_div").textContent = "";
|
||||
if (response) {
|
||||
const full_update = (response["full_update"] === true);
|
||||
if (responseJSON) {
|
||||
const full_update = (responseJSON["full_update"] === true);
|
||||
if (full_update)
|
||||
torrentPeersTable.clear();
|
||||
if (response["rid"])
|
||||
syncTorrentPeersLastResponseId = response["rid"];
|
||||
if (response["peers"]) {
|
||||
for (const key in response["peers"]) {
|
||||
if (!Object.hasOwn(response["peers"], key))
|
||||
if (responseJSON["rid"])
|
||||
syncTorrentPeersLastResponseId = responseJSON["rid"];
|
||||
if (responseJSON["peers"]) {
|
||||
for (const key in responseJSON["peers"]) {
|
||||
if (!Object.hasOwn(responseJSON["peers"], key))
|
||||
continue;
|
||||
|
||||
response["peers"][key]["rowId"] = key;
|
||||
torrentPeersTable.updateRowData(response["peers"][key]);
|
||||
responseJSON["peers"][key]["rowId"] = key;
|
||||
torrentPeersTable.updateRowData(responseJSON["peers"][key]);
|
||||
}
|
||||
}
|
||||
if (response["peers_removed"]) {
|
||||
response["peers_removed"].each((hash) => {
|
||||
if (responseJSON["peers_removed"]) {
|
||||
responseJSON["peers_removed"].each((hash) => {
|
||||
torrentPeersTable.removeRow(hash);
|
||||
});
|
||||
}
|
||||
torrentPeersTable.updateTable(full_update);
|
||||
|
||||
if (response["show_flags"]) {
|
||||
if (show_flags !== response["show_flags"]) {
|
||||
show_flags = response["show_flags"];
|
||||
if (responseJSON["show_flags"]) {
|
||||
if (show_flags !== responseJSON["show_flags"]) {
|
||||
show_flags = responseJSON["show_flags"];
|
||||
torrentPeersTable.columns["country"].force_hide = !show_flags;
|
||||
torrentPeersTable.updateColumn("country");
|
||||
}
|
||||
@@ -102,8 +103,12 @@ window.qBittorrent.PropPeers ??= (() => {
|
||||
else {
|
||||
torrentPeersTable.clear();
|
||||
}
|
||||
}
|
||||
}).send();
|
||||
|
||||
})
|
||||
.finally(() => {
|
||||
clearTimeout(loadTorrentPeersTimer);
|
||||
loadTorrentPeersTimer = loadTorrentPeersData.delay(window.qBittorrent.Client.getSyncMainDataInterval());
|
||||
});
|
||||
};
|
||||
|
||||
const updateData = () => {
|
||||
@@ -146,14 +151,13 @@ window.qBittorrent.PropPeers ??= (() => {
|
||||
return;
|
||||
|
||||
if (confirm("QBT_TR(Are you sure you want to permanently ban the selected peers?)QBT_TR[CONTEXT=PeerListWidget]")) {
|
||||
new Request({
|
||||
url: "api/v2/transfer/banPeers",
|
||||
method: "post",
|
||||
data: {
|
||||
hash: torrentsTable.getCurrentTorrentID(),
|
||||
peers: selectedPeers.join("|")
|
||||
}
|
||||
}).send();
|
||||
fetch("api/v2/transfer/banPeers", {
|
||||
method: "POST",
|
||||
body: new URLSearchParams({
|
||||
"hash": torrentsTable.getCurrentTorrentID(),
|
||||
"peers": selectedPeers.join("|")
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -32,24 +32,28 @@ MochaUI.extend({
|
||||
addUpLimitSlider: (hashes) => {
|
||||
if ($("uplimitSliderarea")) {
|
||||
// Get global upload limit
|
||||
let maximum = 500;
|
||||
new Request({
|
||||
url: "api/v2/transfer/uploadLimit",
|
||||
method: "get",
|
||||
data: {},
|
||||
onSuccess: (data) => {
|
||||
if (data) {
|
||||
const tmp = Number(data);
|
||||
if (tmp > 0) {
|
||||
maximum = tmp / 1024.0;
|
||||
}
|
||||
else {
|
||||
if (hashes[0] === "global")
|
||||
maximum = 10000;
|
||||
else
|
||||
maximum = 1000;
|
||||
}
|
||||
fetch("api/v2/transfer/uploadLimit", {
|
||||
method: "GET",
|
||||
cache: "no-store"
|
||||
})
|
||||
.then(async (response) => {
|
||||
if (!response.ok)
|
||||
return;
|
||||
|
||||
const data = await response.text();
|
||||
|
||||
let maximum = 500;
|
||||
const tmp = Number(data);
|
||||
if (tmp > 0) {
|
||||
maximum = tmp / 1024.0;
|
||||
}
|
||||
else {
|
||||
if (hashes[0] === "global")
|
||||
maximum = 10000;
|
||||
else
|
||||
maximum = 1000;
|
||||
}
|
||||
|
||||
// Get torrents upload limit
|
||||
// And create slider
|
||||
if (hashes[0] === "global") {
|
||||
@@ -83,77 +87,82 @@ MochaUI.extend({
|
||||
}
|
||||
}
|
||||
else {
|
||||
new Request.JSON({
|
||||
url: "api/v2/torrents/uploadLimit",
|
||||
method: "post",
|
||||
data: {
|
||||
hashes: hashes.join("|")
|
||||
},
|
||||
onSuccess: (data) => {
|
||||
if (data) {
|
||||
let up_limit = data[hashes[0]];
|
||||
for (const key in data) {
|
||||
if (up_limit !== data[key]) {
|
||||
up_limit = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (up_limit < 0)
|
||||
fetch("api/v2/torrents/uploadLimit", {
|
||||
method: "POST",
|
||||
body: new URLSearchParams({
|
||||
"hashes": hashes.join("|")
|
||||
})
|
||||
})
|
||||
.then(async (response) => {
|
||||
if (!response.ok)
|
||||
return;
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
let up_limit = data[hashes[0]];
|
||||
for (const key in data) {
|
||||
if (up_limit !== data[key]) {
|
||||
up_limit = 0;
|
||||
new Slider($("uplimitSliderarea"), $("uplimitSliderknob"), {
|
||||
steps: maximum,
|
||||
offset: 0,
|
||||
initialStep: (up_limit / 1024.0).round(),
|
||||
onChange: (pos) => {
|
||||
if (pos > 0) {
|
||||
$("uplimitUpdatevalue").value = pos;
|
||||
$("upLimitUnit").style.visibility = "visible";
|
||||
}
|
||||
else {
|
||||
$("uplimitUpdatevalue").value = "∞";
|
||||
$("upLimitUnit").style.visibility = "hidden";
|
||||
}
|
||||
}
|
||||
});
|
||||
// Set default value
|
||||
if (up_limit === 0) {
|
||||
$("uplimitUpdatevalue").value = "∞";
|
||||
$("upLimitUnit").style.visibility = "hidden";
|
||||
}
|
||||
else {
|
||||
$("uplimitUpdatevalue").value = (up_limit / 1024.0).round();
|
||||
$("upLimitUnit").style.visibility = "visible";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}).send();
|
||||
if (up_limit < 0)
|
||||
up_limit = 0;
|
||||
new Slider($("uplimitSliderarea"), $("uplimitSliderknob"), {
|
||||
steps: maximum,
|
||||
offset: 0,
|
||||
initialStep: (up_limit / 1024.0).round(),
|
||||
onChange: (pos) => {
|
||||
if (pos > 0) {
|
||||
$("uplimitUpdatevalue").value = pos;
|
||||
$("upLimitUnit").style.visibility = "visible";
|
||||
}
|
||||
else {
|
||||
$("uplimitUpdatevalue").value = "∞";
|
||||
$("upLimitUnit").style.visibility = "hidden";
|
||||
}
|
||||
}
|
||||
});
|
||||
// Set default value
|
||||
if (up_limit === 0) {
|
||||
$("uplimitUpdatevalue").value = "∞";
|
||||
$("upLimitUnit").style.visibility = "hidden";
|
||||
}
|
||||
else {
|
||||
$("uplimitUpdatevalue").value = (up_limit / 1024.0).round();
|
||||
$("upLimitUnit").style.visibility = "visible";
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}).send();
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
addDlLimitSlider: (hashes) => {
|
||||
if ($("dllimitSliderarea")) {
|
||||
// Get global upload limit
|
||||
let maximum = 500;
|
||||
new Request({
|
||||
url: "api/v2/transfer/downloadLimit",
|
||||
method: "get",
|
||||
data: {},
|
||||
onSuccess: (data) => {
|
||||
if (data) {
|
||||
const tmp = Number(data);
|
||||
if (tmp > 0) {
|
||||
maximum = tmp / 1024.0;
|
||||
}
|
||||
else {
|
||||
if (hashes[0] === "global")
|
||||
maximum = 10000;
|
||||
else
|
||||
maximum = 1000;
|
||||
}
|
||||
fetch("api/v2/transfer/downloadLimit", {
|
||||
method: "GET",
|
||||
cache: "no-store"
|
||||
})
|
||||
.then(async (response) => {
|
||||
if (!response.ok)
|
||||
return;
|
||||
|
||||
const data = await response.text();
|
||||
|
||||
let maximum = 500;
|
||||
const tmp = Number(data);
|
||||
if (tmp > 0) {
|
||||
maximum = tmp / 1024.0;
|
||||
}
|
||||
else {
|
||||
if (hashes[0] === "global")
|
||||
maximum = 10000;
|
||||
else
|
||||
maximum = 1000;
|
||||
}
|
||||
|
||||
// Get torrents download limit
|
||||
// And create slider
|
||||
if (hashes[0] === "global") {
|
||||
@@ -187,53 +196,54 @@ MochaUI.extend({
|
||||
}
|
||||
}
|
||||
else {
|
||||
new Request.JSON({
|
||||
url: "api/v2/torrents/downloadLimit",
|
||||
method: "post",
|
||||
data: {
|
||||
hashes: hashes.join("|")
|
||||
},
|
||||
onSuccess: (data) => {
|
||||
if (data) {
|
||||
let dl_limit = data[hashes[0]];
|
||||
for (const key in data) {
|
||||
if (dl_limit !== data[key]) {
|
||||
dl_limit = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (dl_limit < 0)
|
||||
fetch("api/v2/torrents/downloadLimit", {
|
||||
method: "POST",
|
||||
body: new URLSearchParams({
|
||||
"hashes": hashes.join("|")
|
||||
})
|
||||
})
|
||||
.then(async (response) => {
|
||||
if (!response.ok)
|
||||
return;
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
let dl_limit = data[hashes[0]];
|
||||
for (const key in data) {
|
||||
if (dl_limit !== data[key]) {
|
||||
dl_limit = 0;
|
||||
new Slider($("dllimitSliderarea"), $("dllimitSliderknob"), {
|
||||
steps: maximum,
|
||||
offset: 0,
|
||||
initialStep: (dl_limit / 1024.0).round(),
|
||||
onChange: (pos) => {
|
||||
if (pos > 0) {
|
||||
$("dllimitUpdatevalue").value = pos;
|
||||
$("dlLimitUnit").style.visibility = "visible";
|
||||
}
|
||||
else {
|
||||
$("dllimitUpdatevalue").value = "∞";
|
||||
$("dlLimitUnit").style.visibility = "hidden";
|
||||
}
|
||||
}
|
||||
});
|
||||
// Set default value
|
||||
if (dl_limit === 0) {
|
||||
$("dllimitUpdatevalue").value = "∞";
|
||||
$("dlLimitUnit").style.visibility = "hidden";
|
||||
}
|
||||
else {
|
||||
$("dllimitUpdatevalue").value = (dl_limit / 1024.0).round();
|
||||
$("dlLimitUnit").style.visibility = "visible";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}).send();
|
||||
if (dl_limit < 0)
|
||||
dl_limit = 0;
|
||||
new Slider($("dllimitSliderarea"), $("dllimitSliderknob"), {
|
||||
steps: maximum,
|
||||
offset: 0,
|
||||
initialStep: (dl_limit / 1024.0).round(),
|
||||
onChange: (pos) => {
|
||||
if (pos > 0) {
|
||||
$("dllimitUpdatevalue").value = pos;
|
||||
$("dlLimitUnit").style.visibility = "visible";
|
||||
}
|
||||
else {
|
||||
$("dllimitUpdatevalue").value = "∞";
|
||||
$("dlLimitUnit").style.visibility = "hidden";
|
||||
}
|
||||
}
|
||||
});
|
||||
// Set default value
|
||||
if (dl_limit === 0) {
|
||||
$("dllimitUpdatevalue").value = "∞";
|
||||
$("dlLimitUnit").style.visibility = "hidden";
|
||||
}
|
||||
else {
|
||||
$("dllimitUpdatevalue").value = (dl_limit / 1024.0).round();
|
||||
$("dlLimitUnit").style.visibility = "visible";
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}).send();
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user