2016-05-31 16:51:12 +02:00
|
|
|
(function () {
|
|
|
|
'use strict';
|
|
|
|
|
2016-12-10 17:25:19 +01:00
|
|
|
angular.module('ariaNg').factory('aria2TaskService', ['$q', '$translate', 'bittorrentPeeridService', 'aria2Errors', 'aria2RpcService', 'ariaNgCommonService', 'ariaNgLogService', function ($q, $translate, bittorrentPeeridService, aria2Errors, aria2RpcService, ariaNgCommonService, ariaNgLogService) {
|
2016-06-23 16:45:55 +02:00
|
|
|
var getFileName = function (file) {
|
|
|
|
if (!file) {
|
2016-12-10 18:50:25 +01:00
|
|
|
ariaNgLogService.warn('[aria2TaskService.getFileName] file is null');
|
2016-06-23 16:45:55 +02:00
|
|
|
return '';
|
|
|
|
}
|
|
|
|
|
|
|
|
var path = file.path;
|
|
|
|
|
|
|
|
if (!path && file.uris && file.uris.length > 0) {
|
|
|
|
path = file.uris[0].uri;
|
2016-05-31 16:51:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
var index = path.lastIndexOf('/');
|
|
|
|
|
2016-08-01 19:26:10 +02:00
|
|
|
if (index <= 0 || index === path.length) {
|
2016-05-31 16:51:12 +02:00
|
|
|
return path;
|
|
|
|
}
|
|
|
|
|
|
|
|
return path.substring(index + 1);
|
|
|
|
};
|
|
|
|
|
|
|
|
var calculateDownloadRemainTime = function (remainBytes, downloadSpeed) {
|
2016-08-01 19:26:10 +02:00
|
|
|
if (downloadSpeed === 0) {
|
2016-05-31 16:51:12 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return remainBytes / downloadSpeed;
|
|
|
|
};
|
|
|
|
|
|
|
|
var getTaskName = function (task) {
|
2016-10-30 13:24:54 +01:00
|
|
|
var taskName = '';
|
2016-06-22 18:39:44 +02:00
|
|
|
var success = true;
|
2016-05-31 16:51:12 +02:00
|
|
|
|
|
|
|
if (task.bittorrent && task.bittorrent.info) {
|
|
|
|
taskName = task.bittorrent.info.name;
|
|
|
|
}
|
|
|
|
|
2016-06-23 16:45:55 +02:00
|
|
|
if (!taskName && task.files && task.files.length > 0) {
|
|
|
|
taskName = getFileName(task.files[0]);
|
2016-05-31 16:51:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!taskName) {
|
|
|
|
taskName = $translate.instant('Unknown');
|
2016-06-22 18:39:44 +02:00
|
|
|
success = false;
|
2016-05-31 16:51:12 +02:00
|
|
|
}
|
|
|
|
|
2016-06-22 18:39:44 +02:00
|
|
|
return {
|
|
|
|
name: taskName,
|
|
|
|
success: success
|
|
|
|
};
|
2016-05-31 16:51:12 +02:00
|
|
|
};
|
|
|
|
|
2016-10-30 13:24:54 +01:00
|
|
|
var getTaskErrorDescription = function (task) {
|
|
|
|
if (!task.errorCode) {
|
|
|
|
return '';
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!aria2Errors[task.errorCode] || !aria2Errors[task.errorCode].descriptionKey) {
|
|
|
|
return '';
|
|
|
|
}
|
|
|
|
|
|
|
|
if (aria2Errors[task.errorCode].hide) {
|
|
|
|
return '';
|
|
|
|
}
|
|
|
|
|
|
|
|
return aria2Errors[task.errorCode].descriptionKey;
|
|
|
|
};
|
|
|
|
|
2016-07-16 16:15:37 +02:00
|
|
|
var getPieceStatus = function (bitField, pieceCount) {
|
|
|
|
var pieces = [];
|
|
|
|
|
|
|
|
for (var i = 0; i < pieceCount; i++) {
|
|
|
|
pieces.push(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!bitField) {
|
|
|
|
return pieces;
|
|
|
|
}
|
|
|
|
|
|
|
|
var pieceIndex = 0;
|
|
|
|
|
|
|
|
for (var i = 0; i < bitField.length; i++) {
|
|
|
|
var bitSet = parseInt(bitField[i], 16);
|
|
|
|
|
|
|
|
for (var j = 1; j <= 4; j++) {
|
|
|
|
var bit = (1 << (4 - j));
|
2016-08-01 19:26:10 +02:00
|
|
|
var isCompleted = (bitSet & bit) === bit;
|
2016-07-16 16:15:37 +02:00
|
|
|
|
|
|
|
pieces[pieceIndex++] = isCompleted;
|
|
|
|
|
|
|
|
if (pieceIndex >= pieceCount) {
|
|
|
|
return pieces;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return pieces;
|
|
|
|
};
|
|
|
|
|
|
|
|
var getCombinedPieces = function (bitField, pieceCount) {
|
|
|
|
var pieces = getPieceStatus(bitField, pieceCount);
|
|
|
|
var combinedPieces = [];
|
|
|
|
|
|
|
|
for (var i = 0; i < pieces.length; i++) {
|
|
|
|
var isCompleted = pieces[i];
|
|
|
|
|
2016-08-01 19:26:10 +02:00
|
|
|
if (combinedPieces.length > 0 && combinedPieces[combinedPieces.length - 1].isCompleted === isCompleted) {
|
2016-07-16 16:15:37 +02:00
|
|
|
combinedPieces[combinedPieces.length - 1].count++;
|
|
|
|
} else {
|
|
|
|
combinedPieces.push({
|
|
|
|
isCompleted: isCompleted,
|
|
|
|
count: 1
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return combinedPieces;
|
|
|
|
};
|
|
|
|
|
2016-05-31 16:51:12 +02:00
|
|
|
var processDownloadTask = function (task) {
|
|
|
|
if (!task) {
|
2016-12-10 18:50:25 +01:00
|
|
|
ariaNgLogService.warn('[aria2TaskService.processDownloadTask] task is null');
|
2016-05-31 16:51:12 +02:00
|
|
|
return task;
|
|
|
|
}
|
|
|
|
|
2016-07-16 16:15:37 +02:00
|
|
|
var pieceStatus = getPieceStatus(task.bitfield, task.numPieces);
|
|
|
|
|
2016-05-31 16:51:12 +02:00
|
|
|
task.totalLength = parseInt(task.totalLength);
|
|
|
|
task.completedLength = parseInt(task.completedLength);
|
|
|
|
task.completePercent = (task.totalLength > 0 ? task.completedLength / task.totalLength * 100 : 0);
|
2016-05-31 16:55:25 +02:00
|
|
|
task.remainLength = task.totalLength - task.completedLength;
|
2016-05-31 16:51:12 +02:00
|
|
|
task.remainPercent = 100 - task.completePercent;
|
2016-06-09 11:31:36 +02:00
|
|
|
task.uploadLength = (task.uploadLength ? parseInt(task.uploadLength) : 0);
|
2016-06-26 13:52:14 +02:00
|
|
|
task.shareRatio = (task.completedLength > 0 ? task.uploadLength / task.completedLength : 0);
|
2016-05-31 16:55:25 +02:00
|
|
|
|
|
|
|
task.uploadSpeed = parseInt(task.uploadSpeed);
|
|
|
|
task.downloadSpeed = parseInt(task.downloadSpeed);
|
|
|
|
|
2016-07-16 16:15:37 +02:00
|
|
|
task.numPieces = parseInt(task.numPieces);
|
|
|
|
task.completedPieces = ariaNgCommonService.countArray(pieceStatus, true);
|
|
|
|
task.pieceLength = parseInt(task.pieceLength);
|
|
|
|
|
2016-08-01 19:26:10 +02:00
|
|
|
task.idle = task.downloadSpeed === 0;
|
2016-05-31 16:55:25 +02:00
|
|
|
task.remainTime = calculateDownloadRemainTime(task.remainLength, task.downloadSpeed);
|
2016-07-10 11:37:34 +02:00
|
|
|
task.seeder = (task.seeder === true || task.seeder === 'true');
|
2016-05-31 16:51:12 +02:00
|
|
|
|
2016-06-22 18:39:44 +02:00
|
|
|
var taskNameResult = getTaskName(task);
|
|
|
|
task.taskName = taskNameResult.name;
|
|
|
|
task.hasTaskName = taskNameResult.success;
|
|
|
|
|
2016-10-30 13:24:54 +01:00
|
|
|
task.errorDescription = getTaskErrorDescription(task);
|
|
|
|
|
2016-05-31 16:51:12 +02:00
|
|
|
if (task.files) {
|
2016-06-27 18:32:17 +02:00
|
|
|
var selectedFileCount = 0;
|
|
|
|
|
2016-05-31 16:51:12 +02:00
|
|
|
for (var i = 0; i < task.files.length; i++) {
|
|
|
|
var file = task.files[i];
|
2016-06-23 16:45:55 +02:00
|
|
|
file.fileName = getFileName(file);
|
2016-05-31 16:51:12 +02:00
|
|
|
file.length = parseInt(file.length);
|
2016-06-27 18:32:17 +02:00
|
|
|
file.selected = (file.selected === true || file.selected === 'true');
|
2016-05-31 16:51:12 +02:00
|
|
|
file.completedLength = parseInt(file.completedLength);
|
|
|
|
file.completePercent = (file.length > 0 ? file.completedLength / file.length * 100 : 0);
|
2016-06-27 18:32:17 +02:00
|
|
|
|
|
|
|
selectedFileCount += file.selected ? 1 : 0;
|
2016-05-31 16:51:12 +02:00
|
|
|
}
|
2016-06-27 18:32:17 +02:00
|
|
|
|
|
|
|
task.selectedFileCount = selectedFileCount;
|
2016-05-31 16:51:12 +02:00
|
|
|
}
|
2016-07-16 16:33:49 +02:00
|
|
|
|
2016-05-31 16:51:12 +02:00
|
|
|
return task;
|
|
|
|
};
|
|
|
|
|
2016-07-03 12:07:07 +02:00
|
|
|
var processBtPeers = function (peers, task, includeLocalPeer) {
|
|
|
|
if (!peers) {
|
2016-12-10 18:50:25 +01:00
|
|
|
ariaNgLogService.warn('[aria2TaskService.processBtPeers] peers is null');
|
2016-07-03 12:07:07 +02:00
|
|
|
return peers;
|
|
|
|
}
|
|
|
|
|
|
|
|
var localTaskCompletedPieces = getPieceStatus(task.bitfield, task.numPieces);
|
|
|
|
var localTaskCompletedPieceCount = ariaNgCommonService.countArray(localTaskCompletedPieces, true);
|
|
|
|
var localTaskCompletedPercent = task.completePercent;
|
|
|
|
|
|
|
|
for (var i = 0; i < peers.length; i++) {
|
|
|
|
var peer = peers[i];
|
|
|
|
var upstreamToSpeed = peer.uploadSpeed;
|
|
|
|
var downstreamFromSpeed = peer.downloadSpeed;
|
|
|
|
var completedPieces = getPieceStatus(peer.bitfield, task.numPieces);
|
|
|
|
var completedPieceCount = ariaNgCommonService.countArray(completedPieces, true);
|
|
|
|
|
|
|
|
peer.name = peer.ip + ':' + peer.port;
|
|
|
|
peer.completePercent = completedPieceCount / task.numPieces * 100;
|
|
|
|
peer.downloadSpeed = upstreamToSpeed;
|
|
|
|
peer.uploadSpeed = downstreamFromSpeed;
|
2016-07-10 11:37:34 +02:00
|
|
|
peer.seeder = (peer.seeder === true || peer.seeder === 'true');
|
2016-07-03 12:07:07 +02:00
|
|
|
|
2016-08-01 19:26:10 +02:00
|
|
|
if (completedPieceCount === localTaskCompletedPieceCount && peer.completePercent !== localTaskCompletedPercent) {
|
2016-07-03 12:07:07 +02:00
|
|
|
peer.completePercent = localTaskCompletedPercent;
|
|
|
|
}
|
2016-07-16 15:47:02 +02:00
|
|
|
|
|
|
|
if (peer.peerId) {
|
|
|
|
var peerId = ariaNgCommonService.decodePercentEncodedString(peer.peerId);
|
2016-07-16 16:33:49 +02:00
|
|
|
var clientInfo = (peerId ? bittorrentPeeridService.parseClient(peerId) : null);
|
2016-07-16 15:47:02 +02:00
|
|
|
|
2016-08-01 19:26:10 +02:00
|
|
|
if (clientInfo && clientInfo.client !== 'unknown') {
|
2016-07-16 16:33:49 +02:00
|
|
|
var client = {
|
|
|
|
name: (clientInfo.client ? clientInfo.client.trim() : ''),
|
|
|
|
version: (clientInfo.version ? clientInfo.version.trim() : '')
|
2016-07-16 15:47:02 +02:00
|
|
|
};
|
2016-07-16 16:33:49 +02:00
|
|
|
|
|
|
|
client.info = client.name + (client.version ? ' ' + client.version : '');
|
|
|
|
|
|
|
|
peer.client = client;
|
2016-07-16 15:47:02 +02:00
|
|
|
}
|
|
|
|
}
|
2016-07-03 12:07:07 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (includeLocalPeer) {
|
|
|
|
peers.push(createLocalPeerFromTask(task));
|
|
|
|
}
|
|
|
|
|
|
|
|
return peers;
|
|
|
|
};
|
|
|
|
|
2016-07-16 17:16:07 +02:00
|
|
|
var createTaskEventCallback = function (getTaskStatusFunc, callback, type) {
|
2016-06-28 18:18:17 +02:00
|
|
|
return function (event) {
|
|
|
|
var context = {
|
|
|
|
type: type,
|
|
|
|
task: null
|
|
|
|
};
|
|
|
|
|
|
|
|
if (event && event.gid) {
|
|
|
|
getTaskStatusFunc(event.gid, function (response) {
|
|
|
|
context.task = (response.success ? response.data : null);
|
|
|
|
callback(context);
|
|
|
|
}, true);
|
|
|
|
} else {
|
|
|
|
callback(context);
|
|
|
|
}
|
2016-12-10 18:50:25 +01:00
|
|
|
};
|
2016-06-28 18:18:17 +02:00
|
|
|
};
|
|
|
|
|
2016-06-12 16:50:49 +02:00
|
|
|
var createLocalPeerFromTask = function (task) {
|
|
|
|
return {
|
|
|
|
local: true,
|
|
|
|
bitfield: task.bitfield,
|
|
|
|
completePercent: task.completePercent,
|
|
|
|
downloadSpeed: task.downloadSpeed,
|
|
|
|
name: '(local)',
|
|
|
|
seeder: task.seeder,
|
|
|
|
uploadSpeed: task.uploadSpeed
|
|
|
|
};
|
2016-05-31 16:51:12 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
return {
|
2016-06-04 09:33:40 +02:00
|
|
|
getTaskList: function (type, full, callback, silent) {
|
2016-05-31 16:51:12 +02:00
|
|
|
var invokeMethod = null;
|
|
|
|
|
2016-08-01 19:26:10 +02:00
|
|
|
if (type === 'downloading') {
|
2016-05-31 16:51:12 +02:00
|
|
|
invokeMethod = aria2RpcService.tellActive;
|
2016-08-01 19:26:10 +02:00
|
|
|
} else if (type === 'waiting') {
|
2016-05-31 16:51:12 +02:00
|
|
|
invokeMethod = aria2RpcService.tellWaiting;
|
2016-08-01 19:26:10 +02:00
|
|
|
} else if (type === 'stopped') {
|
2016-05-31 16:51:12 +02:00
|
|
|
invokeMethod = aria2RpcService.tellStopped;
|
|
|
|
} else {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
return invokeMethod({
|
2016-06-22 18:39:44 +02:00
|
|
|
requestWholeInfo: full,
|
2016-05-31 16:51:12 +02:00
|
|
|
requestParams: full ? aria2RpcService.getFullTaskParams() : aria2RpcService.getBasicTaskParams(),
|
2016-06-04 09:33:40 +02:00
|
|
|
silent: !!silent,
|
2016-06-10 13:23:16 +02:00
|
|
|
callback: function (response) {
|
2016-05-31 16:51:12 +02:00
|
|
|
if (!callback) {
|
2016-12-10 18:50:25 +01:00
|
|
|
ariaNgLogService.warn('[aria2TaskService.getTaskList] callback is null');
|
2016-05-31 16:51:12 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-06-10 13:23:16 +02:00
|
|
|
callback(response);
|
2016-05-31 16:51:12 +02:00
|
|
|
}
|
|
|
|
});
|
|
|
|
},
|
2016-06-04 09:33:40 +02:00
|
|
|
getTaskStatus: function (gid, callback, silent) {
|
2016-05-31 16:51:12 +02:00
|
|
|
return aria2RpcService.tellStatus({
|
|
|
|
gid: gid,
|
2016-06-04 09:33:40 +02:00
|
|
|
silent: !!silent,
|
2016-06-10 13:23:16 +02:00
|
|
|
callback: function (response) {
|
2016-05-31 16:51:12 +02:00
|
|
|
if (!callback) {
|
2016-12-10 18:50:25 +01:00
|
|
|
ariaNgLogService.warn('[aria2TaskService.getTaskStatus] callback is null');
|
2016-05-31 16:51:12 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-06-10 13:23:16 +02:00
|
|
|
if (response.success) {
|
|
|
|
processDownloadTask(response.data);
|
|
|
|
}
|
|
|
|
|
|
|
|
callback(response);
|
2016-05-31 16:51:12 +02:00
|
|
|
}
|
|
|
|
});
|
|
|
|
},
|
2016-06-10 13:23:16 +02:00
|
|
|
getTaskOptions: function (gid, callback, silent) {
|
2016-05-31 16:51:12 +02:00
|
|
|
return aria2RpcService.getOption({
|
|
|
|
gid: gid,
|
2016-06-10 13:23:16 +02:00
|
|
|
silent: !!silent,
|
2016-05-31 16:51:12 +02:00
|
|
|
callback: callback
|
|
|
|
});
|
|
|
|
},
|
2016-06-10 13:23:16 +02:00
|
|
|
setTaskOption: function (gid, key, value, callback, silent) {
|
2016-06-01 18:02:10 +02:00
|
|
|
var data = {};
|
|
|
|
data[key] = value;
|
2016-06-04 09:33:40 +02:00
|
|
|
|
2016-06-01 18:02:10 +02:00
|
|
|
return aria2RpcService.changeOption({
|
|
|
|
gid: gid,
|
|
|
|
options: data,
|
2016-06-10 13:23:16 +02:00
|
|
|
silent: !!silent,
|
2016-06-01 18:02:10 +02:00
|
|
|
callback: callback
|
|
|
|
});
|
|
|
|
},
|
2016-06-10 13:23:16 +02:00
|
|
|
selectTaskFile: function (gid, selectedFileIndexArr, callback, silent) {
|
2016-06-06 17:15:46 +02:00
|
|
|
var selectedFileIndex = '';
|
2016-06-09 11:31:36 +02:00
|
|
|
|
2016-06-06 17:15:46 +02:00
|
|
|
for (var i = 0; i < selectedFileIndexArr.length; i++) {
|
|
|
|
if (selectedFileIndex.length > 0) {
|
|
|
|
selectedFileIndex += ',';
|
|
|
|
}
|
|
|
|
|
|
|
|
selectedFileIndex += selectedFileIndexArr[i];
|
|
|
|
}
|
2016-06-09 11:31:36 +02:00
|
|
|
|
2016-06-10 13:23:16 +02:00
|
|
|
return this.setTaskOption(gid, 'select-file', selectedFileIndex, callback, silent);
|
2016-06-06 17:15:46 +02:00
|
|
|
},
|
2016-07-03 12:07:07 +02:00
|
|
|
getBtTaskPeers: function (task, callback, silent, includeLocalPeer) {
|
2016-05-31 16:51:12 +02:00
|
|
|
return aria2RpcService.getPeers({
|
2016-06-12 16:50:49 +02:00
|
|
|
gid: task.gid,
|
2016-06-04 09:33:40 +02:00
|
|
|
silent: !!silent,
|
2016-06-10 13:23:16 +02:00
|
|
|
callback: function (response) {
|
2016-05-31 16:51:12 +02:00
|
|
|
if (!callback) {
|
2016-12-10 18:50:25 +01:00
|
|
|
ariaNgLogService.warn('[aria2TaskService.getBtTaskPeers] callback is null');
|
2016-05-31 16:51:12 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-06-10 13:23:16 +02:00
|
|
|
if (response.success) {
|
2016-07-03 12:07:07 +02:00
|
|
|
processBtPeers(response.data, task, includeLocalPeer);
|
|
|
|
}
|
|
|
|
|
|
|
|
callback(response);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
},
|
2016-07-04 18:59:04 +02:00
|
|
|
getTaskStatusAndBtPeers: function (gid, callback, silent, requirePeers, includeLocalPeer) {
|
|
|
|
var methods = [
|
|
|
|
aria2RpcService.tellStatus({ gid: gid }, true)
|
|
|
|
];
|
|
|
|
|
|
|
|
if (requirePeers) {
|
|
|
|
methods.push(aria2RpcService.getPeers({ gid: gid }, true));
|
|
|
|
}
|
|
|
|
|
2016-07-03 12:07:07 +02:00
|
|
|
return aria2RpcService.multicall({
|
2016-07-04 18:59:04 +02:00
|
|
|
methods: methods,
|
2016-07-03 12:07:07 +02:00
|
|
|
silent: !!silent,
|
|
|
|
callback: function (response) {
|
|
|
|
if (!callback) {
|
2016-12-10 18:50:25 +01:00
|
|
|
ariaNgLogService.warn('[aria2TaskService.getTaskStatusAndBtPeers] callback is null');
|
2016-07-03 12:07:07 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
response.task = {};
|
|
|
|
|
2016-07-04 18:59:04 +02:00
|
|
|
if (response.success && response.data.length > 0) {
|
2016-07-03 12:07:07 +02:00
|
|
|
response.task = response.data[0][0];
|
|
|
|
processDownloadTask(response.task);
|
|
|
|
}
|
|
|
|
|
2016-07-04 18:59:04 +02:00
|
|
|
if (response.success && response.task.bittorrent && response.data.length > 1) {
|
2016-07-03 12:07:07 +02:00
|
|
|
response.peers = response.data[1][0];
|
|
|
|
processBtPeers(response.peers, response.task, includeLocalPeer);
|
2016-05-31 16:51:12 +02:00
|
|
|
}
|
|
|
|
|
2016-06-10 13:23:16 +02:00
|
|
|
callback(response);
|
2016-05-31 16:51:12 +02:00
|
|
|
}
|
|
|
|
});
|
|
|
|
},
|
2016-06-25 13:47:02 +02:00
|
|
|
newUriTask: function (task, pauseOnAdded, callback, silent) {
|
|
|
|
return aria2RpcService.addUri({
|
|
|
|
task: task,
|
|
|
|
pauseOnAdded: !!pauseOnAdded,
|
|
|
|
silent: !!silent,
|
|
|
|
callback: callback
|
|
|
|
});
|
|
|
|
},
|
2016-06-20 17:37:25 +02:00
|
|
|
newUriTasks: function (tasks, pauseOnAdded, callback, silent) {
|
2016-06-18 18:11:19 +02:00
|
|
|
return aria2RpcService.addUriMulti({
|
|
|
|
tasks: tasks,
|
2016-06-20 17:37:25 +02:00
|
|
|
pauseOnAdded: !!pauseOnAdded,
|
2016-06-18 18:11:19 +02:00
|
|
|
silent: !!silent,
|
|
|
|
callback: callback
|
|
|
|
});
|
|
|
|
},
|
2016-06-23 18:39:18 +02:00
|
|
|
newTorrentTask: function (task, pauseOnAdded, callback, silent) {
|
|
|
|
return aria2RpcService.addTorrent({
|
|
|
|
task: task,
|
|
|
|
pauseOnAdded: !!pauseOnAdded,
|
|
|
|
silent: !!silent,
|
|
|
|
callback: callback
|
|
|
|
});
|
|
|
|
},
|
|
|
|
newMetalinkTask: function (task, pauseOnAdded, callback, silent) {
|
|
|
|
return aria2RpcService.addMetalink({
|
|
|
|
task: task,
|
|
|
|
pauseOnAdded: !!pauseOnAdded,
|
|
|
|
silent: !!silent,
|
|
|
|
callback: callback
|
|
|
|
});
|
|
|
|
},
|
2016-06-10 13:23:16 +02:00
|
|
|
startTasks: function (gids, callback, silent) {
|
2016-05-31 16:51:12 +02:00
|
|
|
return aria2RpcService.unpauseMulti({
|
|
|
|
gids: gids,
|
2016-06-10 13:23:16 +02:00
|
|
|
silent: !!silent,
|
2016-05-31 16:51:12 +02:00
|
|
|
callback: callback
|
|
|
|
});
|
|
|
|
},
|
2016-06-10 13:23:16 +02:00
|
|
|
pauseTasks: function (gids, callback, silent) {
|
2016-05-31 16:51:12 +02:00
|
|
|
return aria2RpcService.forcePauseMulti({
|
|
|
|
gids: gids,
|
2016-06-10 13:23:16 +02:00
|
|
|
silent: !!silent,
|
2016-05-31 16:51:12 +02:00
|
|
|
callback: callback
|
|
|
|
});
|
|
|
|
},
|
2016-12-10 17:25:19 +01:00
|
|
|
restartTask: function (gid, callback, silent) {
|
|
|
|
var deferred = $q.defer();
|
|
|
|
|
|
|
|
var methods = [
|
|
|
|
aria2RpcService.tellStatus({gid: gid}, true),
|
|
|
|
aria2RpcService.getOption({gid: gid}, true)
|
|
|
|
];
|
|
|
|
|
|
|
|
var task = null, options = null;
|
|
|
|
|
|
|
|
aria2RpcService.multicall({
|
|
|
|
methods: methods,
|
|
|
|
silent: !!silent,
|
|
|
|
callback: function (response) {
|
|
|
|
if (!callback) {
|
2016-12-10 18:50:25 +01:00
|
|
|
ariaNgLogService.warn('[aria2TaskService.restartTask] callback is null');
|
2016-12-10 17:25:19 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!response.success) {
|
2016-12-10 18:50:25 +01:00
|
|
|
ariaNgLogService.warn('[aria2TaskService.restartTask] response is not success');
|
2016-12-10 17:25:19 +01:00
|
|
|
deferred.reject(response);
|
|
|
|
callback(response);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (response.data.length > 0) {
|
|
|
|
task = response.data[0][0];
|
|
|
|
}
|
|
|
|
|
|
|
|
if (response.data.length > 1) {
|
|
|
|
options = response.data[1][0];
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!task || !options || !task.files || task.files.length != 1 || task.bittorrent) {
|
|
|
|
if (!task) {
|
2016-12-10 18:50:25 +01:00
|
|
|
ariaNgLogService.warn('[aria2TaskService.restartTask] task is null');
|
2016-12-10 17:25:19 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!options) {
|
2016-12-10 18:50:25 +01:00
|
|
|
ariaNgLogService.warn('[aria2TaskService.restartTask] options is null');
|
2016-12-10 17:25:19 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!task.files) {
|
2016-12-10 18:50:25 +01:00
|
|
|
ariaNgLogService.warn('[aria2TaskService.restartTask] task file is null');
|
2016-12-10 17:25:19 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (task.files.length != 1) {
|
2016-12-10 18:50:25 +01:00
|
|
|
ariaNgLogService.warn('[aria2TaskService.restartTask] task file length is not equal 1');
|
2016-12-10 17:25:19 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (task.bittorrent) {
|
2016-12-10 18:50:25 +01:00
|
|
|
ariaNgLogService.warn('[aria2TaskService.restartTask] task is bittorrent');
|
2016-12-10 17:25:19 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
deferred.reject(gid);
|
|
|
|
callback({
|
|
|
|
success: false
|
|
|
|
});
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
var file = task.files[0];
|
|
|
|
var urls = [];
|
|
|
|
|
|
|
|
for (var i = 0; i < file.uris.length; i++) {
|
|
|
|
var uriObj = file.uris[i];
|
|
|
|
urls.push(uriObj.uri);
|
|
|
|
}
|
|
|
|
|
|
|
|
aria2RpcService.addUri({
|
|
|
|
task: {
|
|
|
|
urls: urls,
|
|
|
|
options: options
|
|
|
|
},
|
|
|
|
pauseOnAdded: false,
|
|
|
|
silent: !!silent,
|
|
|
|
callback: function (response) {
|
|
|
|
if (!response.success) {
|
2016-12-10 18:50:25 +01:00
|
|
|
ariaNgLogService.warn('[aria2TaskService.restartTask] addUri response is not success');
|
2016-12-10 17:25:19 +01:00
|
|
|
deferred.reject(response);
|
|
|
|
callback(response);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
deferred.resolve(response);
|
|
|
|
callback(response);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
return deferred.promise;
|
|
|
|
},
|
2016-06-10 13:23:16 +02:00
|
|
|
removeTasks: function (tasks, callback, silent) {
|
2016-06-04 10:52:24 +02:00
|
|
|
var runningTaskGids = [];
|
|
|
|
var stoppedTaskGids = [];
|
2016-06-06 17:15:46 +02:00
|
|
|
|
2016-06-04 10:52:24 +02:00
|
|
|
for (var i = 0; i < tasks.length; i++) {
|
2016-08-01 19:26:10 +02:00
|
|
|
if (tasks[i].status === 'complete' || tasks[i].status === 'error' || tasks[i].status === 'removed') {
|
2016-06-04 10:52:24 +02:00
|
|
|
stoppedTaskGids.push(tasks[i].gid);
|
|
|
|
} else {
|
|
|
|
runningTaskGids.push(tasks[i].gid);
|
|
|
|
}
|
|
|
|
}
|
2016-06-06 17:15:46 +02:00
|
|
|
|
2016-06-04 10:52:24 +02:00
|
|
|
var promises = [];
|
2016-06-10 13:23:16 +02:00
|
|
|
|
|
|
|
var hasSuccess = false;
|
|
|
|
var hasError = false;
|
|
|
|
var results = [];
|
2016-06-06 17:15:46 +02:00
|
|
|
|
2016-06-04 10:52:24 +02:00
|
|
|
if (runningTaskGids.length > 0) {
|
|
|
|
promises.push(aria2RpcService.forceRemoveMulti({
|
|
|
|
gids: runningTaskGids,
|
2016-06-10 13:23:16 +02:00
|
|
|
silent: !!silent,
|
|
|
|
callback: function (response) {
|
|
|
|
ariaNgCommonService.pushArrayTo(results, response.results);
|
|
|
|
hasSuccess = hasSuccess | response.hasSuccess;
|
|
|
|
hasError = hasError | response.hasError;
|
2016-06-04 10:52:24 +02:00
|
|
|
}
|
|
|
|
}));
|
|
|
|
}
|
2016-06-06 17:15:46 +02:00
|
|
|
|
2016-06-04 10:52:24 +02:00
|
|
|
if (stoppedTaskGids.length > 0) {
|
|
|
|
promises.push(aria2RpcService.removeDownloadResultMulti({
|
|
|
|
gids: stoppedTaskGids,
|
2016-06-10 13:23:16 +02:00
|
|
|
silent: !!silent,
|
|
|
|
callback: function (response) {
|
|
|
|
ariaNgCommonService.pushArrayTo(results, response.results);
|
|
|
|
hasSuccess = hasSuccess | response.hasSuccess;
|
|
|
|
hasError = hasError | response.hasError;
|
2016-06-04 10:52:24 +02:00
|
|
|
}
|
|
|
|
}));
|
|
|
|
}
|
|
|
|
|
|
|
|
return $q.all(promises).then(function () {
|
|
|
|
if (callback) {
|
2016-06-10 13:23:16 +02:00
|
|
|
callback({
|
|
|
|
hasSuccess: !!hasSuccess,
|
|
|
|
hasError: !!hasError,
|
|
|
|
results: results
|
|
|
|
});
|
2016-06-04 10:52:24 +02:00
|
|
|
}
|
|
|
|
});
|
|
|
|
},
|
2016-06-10 13:23:16 +02:00
|
|
|
changeTaskPosition: function (gid, position, callback, silent) {
|
2016-05-31 18:09:11 +02:00
|
|
|
return aria2RpcService.changePosition({
|
|
|
|
gid: gid,
|
|
|
|
pos: position,
|
|
|
|
how: 'POS_SET',
|
2016-06-10 13:23:16 +02:00
|
|
|
silent: !!silent,
|
2016-05-31 18:09:11 +02:00
|
|
|
callback: callback
|
2016-12-10 18:50:25 +01:00
|
|
|
});
|
2016-05-31 18:09:11 +02:00
|
|
|
},
|
2016-06-10 13:23:16 +02:00
|
|
|
clearStoppedTasks: function (callback, silent) {
|
2016-06-04 10:52:24 +02:00
|
|
|
return aria2RpcService.purgeDownloadResult({
|
2016-06-10 13:23:16 +02:00
|
|
|
silent: !!silent,
|
2016-06-04 10:52:24 +02:00
|
|
|
callback: callback
|
|
|
|
});
|
|
|
|
},
|
2016-07-16 17:16:07 +02:00
|
|
|
onFirstSuccess: function (callback) {
|
|
|
|
if (!callback) {
|
2016-12-10 18:50:25 +01:00
|
|
|
ariaNgLogService.warn('[aria2TaskService.onFirstSuccess] callback is null');
|
2016-07-16 17:16:07 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
aria2RpcService.onFirstSuccess({
|
|
|
|
callback: callback
|
|
|
|
});
|
|
|
|
},
|
2016-06-28 18:18:17 +02:00
|
|
|
onTaskCompleted: function (callback) {
|
|
|
|
if (!callback) {
|
2016-12-10 18:50:25 +01:00
|
|
|
ariaNgLogService.warn('[aria2TaskService.onTaskCompleted] callback is null');
|
2016-06-28 18:18:17 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
aria2RpcService.onDownloadComplete({
|
2016-07-16 17:16:07 +02:00
|
|
|
callback: createTaskEventCallback(this.getTaskStatus, callback, 'completed')
|
2016-06-28 18:18:17 +02:00
|
|
|
});
|
|
|
|
},
|
|
|
|
onBtTaskCompleted: function (callback) {
|
|
|
|
if (!callback) {
|
2016-12-10 18:50:25 +01:00
|
|
|
ariaNgLogService.warn('[aria2TaskService.onBtTaskCompleted] callback is null');
|
2016-06-28 18:18:17 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
aria2RpcService.onBtDownloadComplete({
|
2016-07-16 17:16:07 +02:00
|
|
|
callback: createTaskEventCallback(this.getTaskStatus, callback, 'btcompleted')
|
2016-06-28 18:18:17 +02:00
|
|
|
});
|
|
|
|
},
|
|
|
|
onTaskErrorOccur: function (callback) {
|
|
|
|
if (!callback) {
|
2016-12-10 18:50:25 +01:00
|
|
|
ariaNgLogService.warn('[aria2TaskService.onTaskErrorOccur] callback is null');
|
2016-06-28 18:18:17 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
aria2RpcService.onDownloadError({
|
2016-07-16 17:16:07 +02:00
|
|
|
callback: createTaskEventCallback(this.getTaskStatus, callback, 'error')
|
2016-06-28 18:18:17 +02:00
|
|
|
});
|
|
|
|
},
|
2016-05-31 16:51:12 +02:00
|
|
|
processDownloadTasks: function (tasks) {
|
|
|
|
if (!angular.isArray(tasks)) {
|
2016-12-10 18:50:25 +01:00
|
|
|
ariaNgLogService.warn('[aria2TaskService.processDownloadTasks] tasks is not array');
|
2016-05-31 16:51:12 +02:00
|
|
|
return;
|
|
|
|
}
|
2016-05-31 16:55:25 +02:00
|
|
|
|
2016-05-31 16:51:12 +02:00
|
|
|
for (var i = 0; i < tasks.length; i++) {
|
|
|
|
processDownloadTask(tasks[i]);
|
|
|
|
}
|
|
|
|
},
|
2016-06-11 14:53:04 +02:00
|
|
|
getPieceStatus: function (bitField, pieceCount) {
|
2016-06-12 16:50:49 +02:00
|
|
|
return getPieceStatus(bitField, pieceCount);
|
2016-06-11 14:53:04 +02:00
|
|
|
},
|
|
|
|
getCombinedPieces: function (bitField, pieceCount) {
|
2016-06-12 16:50:49 +02:00
|
|
|
return getCombinedPieces(bitField, pieceCount);
|
2016-06-11 14:53:04 +02:00
|
|
|
},
|
|
|
|
estimateHealthPercentFromPeers: function (task, peers) {
|
2016-07-04 16:57:05 +02:00
|
|
|
if (!task || task.numPieces < 1 || peers.length < 1) {
|
2016-12-10 18:50:25 +01:00
|
|
|
ariaNgLogService.warn('[aria2TaskService.estimateHealthPercentFromPeers] tasks is null or numPieces < 1 or peers < 1');
|
2016-06-11 14:53:04 +02:00
|
|
|
return task.completePercent;
|
|
|
|
}
|
|
|
|
|
2016-06-12 16:20:38 +02:00
|
|
|
var totalPieces = [];
|
|
|
|
var maxCompletedPieceCount = 0;
|
|
|
|
var maxCompletedPercent = task.completePercent;
|
|
|
|
|
2016-07-10 13:39:08 +02:00
|
|
|
for (var i = 0; i < task.numPieces; i++) {
|
|
|
|
totalPieces.push(0);
|
2016-06-12 16:20:38 +02:00
|
|
|
}
|
2016-06-11 14:53:04 +02:00
|
|
|
|
2016-05-31 16:51:12 +02:00
|
|
|
for (var i = 0; i < peers.length; i++) {
|
|
|
|
var peer = peers[i];
|
2016-06-12 16:50:49 +02:00
|
|
|
var peerPieces = getPieceStatus(peer.bitfield, task.numPieces);
|
2016-06-12 16:20:38 +02:00
|
|
|
var completedPieceCount = 0;
|
2016-05-31 16:51:12 +02:00
|
|
|
|
2016-06-11 14:53:04 +02:00
|
|
|
for (var j = 0; j < peerPieces.length; j++) {
|
2016-06-12 16:20:38 +02:00
|
|
|
var count = (peerPieces[j] ? 1 : 0);
|
|
|
|
totalPieces[j] += count;
|
|
|
|
completedPieceCount += count;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (completedPieceCount > maxCompletedPieceCount) {
|
|
|
|
maxCompletedPieceCount = completedPieceCount;
|
|
|
|
maxCompletedPercent = peer.completePercent;
|
2016-08-01 19:26:10 +02:00
|
|
|
} else if (completedPieceCount === maxCompletedPieceCount && peer.completePercent > maxCompletedPercent) {
|
2016-06-12 16:20:38 +02:00
|
|
|
maxCompletedPercent = peer.completePercent;
|
2016-05-31 16:51:12 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-06-12 16:20:38 +02:00
|
|
|
var totalCompletedPieceCount = 0;
|
2016-05-31 16:51:12 +02:00
|
|
|
|
2016-07-04 16:57:05 +02:00
|
|
|
if (totalPieces.length > 0) {
|
|
|
|
while (true) {
|
|
|
|
var completed = true;
|
|
|
|
|
|
|
|
for (var i = 0; i < totalPieces.length; i++) {
|
|
|
|
if (totalPieces[i] > 0) {
|
|
|
|
totalCompletedPieceCount++;
|
|
|
|
totalPieces[i]--;
|
|
|
|
} else {
|
|
|
|
completed = false;
|
|
|
|
}
|
2016-05-31 16:51:12 +02:00
|
|
|
}
|
|
|
|
|
2016-07-04 16:57:05 +02:00
|
|
|
if (!completed) {
|
|
|
|
break;
|
|
|
|
}
|
2016-05-31 16:51:12 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-06-12 16:20:38 +02:00
|
|
|
if (totalCompletedPieceCount <= maxCompletedPieceCount) {
|
|
|
|
return maxCompletedPercent;
|
|
|
|
}
|
|
|
|
|
|
|
|
var healthPercent = totalCompletedPieceCount / task.numPieces * 100;
|
2016-05-31 16:51:12 +02:00
|
|
|
|
2016-06-12 16:20:38 +02:00
|
|
|
if (healthPercent <= maxCompletedPercent) {
|
|
|
|
return maxCompletedPercent;
|
2016-05-31 16:51:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return healthPercent;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}]);
|
2016-08-01 16:49:16 +02:00
|
|
|
}());
|