Files
MIXBOX-ARCHIVE/apps/transmission/web/tr-web-control/script/transmission.torrents.js
2020-03-05 00:08:40 +08:00

488 lines
12 KiB
JavaScript

// Torrent related information
transmission.torrents = {
all: null,
puased: null,
downloading: null,
actively: null,
searchResult: null,
error: null,
warning: null,
folders: {},
status: {},
count: 0,
totalSize: 0,
loadSimpleInfo: false,
activeTorrentCount: 0,
pausedTorrentCount: 0,
fields: {
base: "id,name,status,hashString,totalSize,percentDone,addedDate,trackerStats,leftUntilDone,rateDownload,rateUpload,recheckProgress" + ",rateDownload,rateUpload,peersGettingFromUs,peersSendingToUs,uploadRatio,uploadedEver,downloadedEver,downloadDir,error,errorString,doneDate,queuePosition,activityDate",
status: "id,status,percentDone,trackerStats,leftUntilDone,rateDownload,rateUpload" + ",rateDownload,rateUpload,peersGettingFromUs,peersSendingToUs,uploadRatio,uploadedEver,downloadedEver,error,errorString,doneDate,queuePosition,activityDate",
config: "downloadLimit,downloadLimited,peer-limit,seedIdleLimit,seedIdleMode,seedRatioLimit,seedRatioMode,uploadLimit,uploadLimited"
},
// List of all the torrents that have been acquired
datas: {},
// The list of recently acquired torrents
recently: null,
// The recently removed seed
removed: null,
// Whether the torrents are being changed
isRecentlyActive: false,
// New torrents
newIds: new Array(),
btItems: [],
getallids: function(callback, ids, moreFields) {
var tmp = this.fields.base;
if (this.loadSimpleInfo && this.all)
tmp = this.fields.status;
var fields = tmp.split(",");
if ($.isArray(moreFields)) {
$.unique($.merge(fields, moreFields));
}
var args = {
fields: fields
};
this.isRecentlyActive = false;
// If it has been acquired
if (this.all && ids == undefined) {
args["ids"] = "recently-active";
this.isRecentlyActive = true;
} else if (ids) {
args["ids"] = ids;
}
if (!this.all) {
this.all = {};
}
transmission.exec({
method: "torrent-get",
arguments: args
}, function(data) {
if (data.result == "success") {
transmission.torrents.newIds.length = 0;
transmission.torrents.loadSimpleInfo = true;
transmission.torrents.recently = data.arguments.torrents;
transmission.torrents.removed = data.arguments.removed;
transmission.torrents.splitid();
if (callback) {
callback(data.arguments.torrents);
}
} else {
transmission.torrents.datas = null;
if (callback) {
callback(null);
}
}
});
},
// The IDs are sorted according to the torrent status
splitid: function() {
// Downloading
this.downloading = new Array();
// Paused
this.puased = new Array();
// Active lately
this.actively = new Array();
// With Errors
this.error = new Array();
// With Warnings
this.warning = new Array();
this.btItems = new Array();
// All download directories used by current torrents
transmission.downloadDirs = new Array();
var _Status = transmission._status;
this.status = {};
transmission.trackers = {};
this.totalSize = 0;
this.folders = {};
this.count = 0;
var B64 = new Base64();
// Merge two numbers
for (var index in this.recently) {
var item = this.recently[index];
this.datas[item.id] = item;
}
var removed = new Array();
// Remove the torrents that have been removed
for (var index in this.removed) {
var item = this.removed[index];
removed.push(item);
}
// Torrents are classified
for (var index in this.datas) {
var item = this.datas[index];
if (!item) {
return;
}
if ($.inArray(item.id, removed) != -1 && removed.length > 0) {
if (this.all[item.id]) {
this.all[item.id] = null;
delete this.all[item.id];
}
this.datas[index] = null;
delete this.datas[index];
continue;
}
// If the current torrent is being acquired and there is no such torrent in the previous torrent list, that is, the new torrent needs to be reloaded with the basic information
if (this.isRecentlyActive && !this.all[item.id]) {
this.newIds.push(item.id);
}
item = $.extend(this.all[item.id], item);
if (item.uploadedEver == 0 && item.downloadedEver == 0) {
item.uploadRatio = "∞";
}
item.infoIsLoading = false;
var type = this.status[item.status];
this.addTracker(item);
if (!type) {
this.status[item.status] = new Array();
type = this.status[item.status];
}
// Total size
this.totalSize += item.totalSize;
// Time left
if (item.rateDownload > 0 && item.leftUntilDone > 0) {
item["remainingTime"] = Math.floor(item.leftUntilDone / item.rateDownload * 1000);
} else if (item.rateDownload == 0 && item.leftUntilDone == 0 && item.totalSize != 0) {
item["remainingTime"] = 0;
} else {
// ~100 years
item["remainingTime"] = 3153600000000;
}
type.push(item);
// The seed for which the error occurred
if (item.error != 0) {
this.error.push(item);
}
// There is currently a number of seeds
if (item.rateUpload > 0 || item.rateDownload > 0) {
this.actively.push(item);
}
switch (item.status) {
case _Status.stopped:
this.puased.push(item);
break;
case _Status.download:
this.downloading.push(item);
break;
}
this.all[item.id] = item;
// Set the directory
if ($.inArray(item.downloadDir, transmission.downloadDirs) == -1) {
transmission.downloadDirs.push(item.downloadDir);
}
if (transmission.options.getFolders) {
if (item.downloadDir) {
// 统一使用 / 来分隔目录
var folder = item.downloadDir.replace(/\\/g,"/").split("/");
var folderkey = "folders-";
for (var i in folder) {
var text = folder[i];
if (text == "") {
continue;
}
var key = B64.encode(text);
// 去除特殊字符
folderkey += key.replace(/[+|\/|=]/g,"0");
var node = this.folders[folderkey];
if (!node) {
node = {
count: 0,
torrents: new Array(),
size: 0,
nodeid: folderkey
};
}
node.torrents.push(item);
node.count++;
node.size += item.totalSize;
this.folders[folderkey] = node;
}
}
}
this.count++;
}
transmission.downloadDirs = transmission.downloadDirs.sort();
// If there a need to acquire new seeds
if (this.newIds.length > 0) {
this.getallids(null, this.newIds);
}
},
addTracker: function(item) {
var trackerStats = item.trackerStats;
var trackers = [];
item.leecherCount = 0;
item.seederCount = 0;
if (trackerStats.length > 0) {
var warnings = [];
for (var index in trackerStats) {
var trackerInfo = trackerStats[index];
var lastResult = trackerInfo.lastAnnounceResult.toLowerCase();
var hostName = trackerInfo.host.getHostName();
var trackerUrl = hostName.split(".");
if ($.inArray(trackerUrl[0], "www,tracker".split(",")) != -1) {
trackerUrl.shift();
}
var name = trackerUrl.join(".");
var id = "tracker-" + name.replace(/\./g, "-");
var tracker = transmission.trackers[id];
if (!tracker) {
transmission.trackers[id] = {
count: 0,
torrents: new Array(),
size: 0,
connected: true,
isBT: (trackerStats.length>5)
};
tracker = transmission.trackers[id];
}
tracker["name"] = name;
tracker["nodeid"] = id;
tracker["host"] = trackerInfo.host;
// 判断当前tracker状态
if (!trackerInfo.lastAnnounceSucceeded && trackerInfo.announceState != transmission._trackerStatus.inactive) {
warnings.push(trackerInfo.lastAnnounceResult);
if (lastResult == "could not connect to tracker") {
tracker.connected = false;
}
}
if (tracker.torrents.indexOf(item)==-1) {
tracker.torrents.push(item);
tracker.count++;
tracker.size += item.totalSize;
}
item.leecherCount += trackerInfo.leecherCount;
item.seederCount += trackerInfo.seederCount;
if (trackers.indexOf(name)==-1) {
trackers.push(name);
}
}
if (trackerStats.length>5) {
this.btItems.push(item);
}
if (warnings.length == trackerStats.length) {
item["warning"] = warnings.join(";");
// 设置下次更新时间
if (!item["nextAnnounceTime"])
item["nextAnnounceTime"] = trackerInfo.nextAnnounceTime;
else if (item["nextAnnounceTime"] > trackerInfo.nextAnnounceTime)
item["nextAnnounceTime"] = trackerInfo.nextAnnounceTime;
this.warning.push(item);
}
if (item.leecherCount < 0) item.leecherCount = 0;
if (item.seederCount < 0) item.seederCount = 0;
item.leecher = item.leecherCount + " (" + item.peersGettingFromUs + ")";
item.seeder = item.seederCount + " (" + item.peersSendingToUs + ")";
item.trackers = trackers.join(";");
}
},
// 获取下载者和做种者数量测试
getPeers: function(ids) {
transmission.exec({
method: "torrent-get",
arguments: {
fields: ("peers,peersFrom").split(","),
ids: ids
}
}, function(data) {
console.log("data:", data);
});
},
// 获取更多信息
getMoreInfos: function(fields, ids, callback) {
transmission.exec({
method: "torrent-get",
arguments: {
fields: fields.split(","),
ids: ids
}
}, function(data) {
if (data.result == "success") {
if (callback)
callback(data.arguments.torrents);
} else if (callback)
callback(null);
});
},
// 从当前已获取的种子列表中搜索指定关键的种子
search: function(key, source) {
if (!key) {
return null;
}
if (!source) {
source = this.all;
}
var arrReturn = new Array();
$.each(source, function(item, i) {
if (source[item].name.toLowerCase().indexOf(key.toLowerCase()) != -1) {
arrReturn.push(source[item]);
}
});
this.searchResult = arrReturn;
return arrReturn;
},
// 获取指定种子的文件列表
getFiles: function(id, callback) {
transmission.exec({
method: "torrent-get",
arguments: {
fields: ("files,fileStats").split(","),
ids: id
}
}, function(data) {
if (data.result == "success") {
if (callback)
callback(data.arguments.torrents);
} else if (callback)
callback(null);
});
},
// 获取指定种子的设置信息
getConfig: function(id, callback) {
this.getMoreInfos(this.fields.config, id, callback);
},
// 获取错误/警告的ID列表
getErrorIds: function(ignore, needUpdateOnly) {
var result = new Array();
var now = new Date();
if (needUpdateOnly == true) {
now = now.getTime() / 1000;
}
for (var index in this.error) {
var item = this.error[index];
if ($.inArray(item.id, ignore) != -1 && ignore.length > 0) {
continue;
}
if (needUpdateOnly == true) {
// 当前时间没有超过“下次更新时间”时,不需要更新
if (now < item.nextAnnounceTime) {
continue;
}
}
// 已停止的種子不計算在內
if (item.status == transmission._status.stopped) {
continue;
}
result.push(item.id);
}
for (var index in this.warning) {
var item = this.warning[index];
if ($.inArray(item.id, ignore) != -1 && ignore.length > 0) {
continue;
}
if (needUpdateOnly == true) {
// 当前时间没有超过“下次更新时间”时,不需要更新
if (now < item.nextAnnounceTime) {
continue;
}
}
result.push(item.id);
}
return result;
},
// 查找并替換 Tracker
searchAndReplaceTrackers: function(oldTracker, newTracker, callback) {
if (!oldTracker || !newTracker) {
return;
}
var result = {};
var count = 0;
for (var index in this.all) {
var item = this.all[index];
if (!item) {
return;
}
var trackerStats = item.trackerStats;
for (var n in trackerStats) {
var tracker = trackerStats[n];
if (tracker.announce == oldTracker) {
if (!result[n]) {
result[n] = {
ids: new Array(),
tracker: newTracker
};
}
result[n].ids.push(item.id);
count++;
}
}
}
if (count == 0) {
if (callback) {
callback(null, 0);
}
}
for (var index in result) {
transmission.exec({
method: "torrent-set",
arguments: {
ids: result[index].ids,
trackerReplace: [parseInt(index), result[index].tracker]
}
}, function(data, tags) {
if (data.result == "success") {
if (callback) {
callback(tags, count);
}
} else {
if (callback) {
callback(null);
}
}
}, result[index].ids);
}
}
};