Merge pull request #162 from jfurrow/refactor/separate-clientUtil-responsibilities

[3] Consolidate clientUtil into clientResponseUtil and related props
This commit is contained in:
John Furrow
2016-10-28 20:36:36 -07:00
committed by GitHub
13 changed files with 333 additions and 304 deletions
-1
View File
@@ -6,7 +6,6 @@ let path = require('path');
let util = require('util');
let clientSettingsMap = require('../../shared/constants/clientSettingsMap');
let clientUtil = require('../util/clientUtil');
let rTorrentPropMap = require('../util/rTorrentPropMap');
let scgi = require('../util/scgi');
let stringUtil = require('../../shared/util/stringUtil');
+2 -2
View File
@@ -104,7 +104,7 @@ class Torrent {
}
getPeerCount(string) {
// This lovely delimiter is defined in clientUtil.
// This lovely delimiter is defined in clientResponseUtil.
let markerPosition = string.indexOf('@!@');
return string.substr(0, markerPosition);
}
@@ -220,7 +220,7 @@ class Torrent {
}
getTrackers(clientData) {
// This lovely delimiter is defined in clientUtil.
// This lovely delimiter is defined in clientResponseUtil.
let trackers = clientData.trackers.split('@!@');
let trackerDomains = [];
+5 -4
View File
@@ -2,9 +2,10 @@
let _ = require('lodash');
let clientUtil = require('../util/clientUtil');
let torrentStatusMap = require('../../shared/constants/torrentStatusMap');
let clientResponseUtil = require('../util/clientResponseUtil');
let stringUtil = require('../../shared/util/stringUtil');
let torrentGeneralPropsMap = require('../../shared/constants/torrentGeneralPropsMap');
let torrentStatusMap = require('../../shared/constants/torrentStatusMap');
let Torrent = require('./Torrent');
const DEFAULT_TAG = 'untagged';
@@ -95,8 +96,8 @@ class TorrentCollection {
updateTorrents(clientData) {
let currentTime = Date.now();
let knownHashes = [];
let torrentData = clientUtil.mapClientResponse(
clientUtil.defaults.torrentProperties, clientData
let torrentData = clientResponseUtil.mapPropsToResponse(
torrentGeneralPropsMap.props, clientData
);
this.resetStatusCount();
+8 -5
View File
@@ -6,11 +6,14 @@ let util = require('util');
let clientResponseUtil = require('../util/clientResponseUtil');
let clientSettingsMap = require('../../shared/constants/clientSettingsMap');
let ClientRequest = require('./ClientRequest');
let clientUtil = require('../util/clientUtil');
let formatUtil = require('../../shared/util/formatUtil');
let scgi = require('../util/scgi');
let Torrent = require('./Torrent');
let TorrentCollection = require('./TorrentCollection');
let torrentFilePropsMap = require('../../shared/constants/torrentFilePropsMap');
let torrentGeneralPropsMap = require('../../shared/constants/torrentGeneralPropsMap');
let torrentPeerPropsMap = require('../../shared/constants/torrentPeerPropsMap');
let torrentTrackerPropsMap = require('../../shared/constants/torrentTrackerPropsMap');
let statusCount = {};
let tagCount = {};
@@ -168,9 +171,9 @@ var client = {
request.add('getTorrentDetails', {
hash,
fileProps: clientUtil.defaults.filePropertyMethods,
peerProps: clientUtil.defaults.peerPropertyMethods,
trackerProps: clientUtil.defaults.trackerPropertyMethods
fileProps: torrentFilePropsMap.methods,
peerProps: torrentPeerPropsMap.methods,
trackerProps: torrentTrackerPropsMap.methods
});
request.postProcess(clientResponseUtil.processTorrentDetails);
request.onComplete(callback);
@@ -181,7 +184,7 @@ var client = {
let request = new ClientRequest();
request.add('getTorrentList',
{props: clientUtil.defaults.torrentPropertyMethods});
{props: torrentGeneralPropsMap.methods});
request.postProcess((data) => {
let torrentList = [];
-1
View File
@@ -5,7 +5,6 @@ let multer = require('multer');
let ajaxUtil = require('../util/ajaxUtil');
let client = require('../models/client');
let clientUtil = require('../util/clientUtil');
let history = require('../models/history');
let router = express.Router();
let settings = require('../models/settings');
+70 -33
View File
@@ -1,6 +1,9 @@
'use strict';
let clientUtil = require('./clientUtil');
let clientGeneralPropsMap = require('../../shared/constants/clientGeneralPropsMap');
let torrentFilePropsMap = require('../../shared/constants/torrentFilePropsMap');
let torrentPeerPropsMap = require('../../shared/constants/torrentPeerPropsMap');
let torrentTrackerPropsMap = require('../../shared/constants/torrentTrackerPropsMap');
let util = require('util');
let getFileTreeFromPathsArr = (tree, directory, file, depth) => {
@@ -31,42 +34,36 @@ let getFileTreeFromPathsArr = (tree, directory, file, depth) => {
};
let clientResponseUtil = {
processTorrentDetails(data) {
// TODO: This is ugly.
let peersData = data[0][0] || null;
let filesData = data[1][0] || null;
let trackerData = data[2][0] || null;
let peers = null;
let files = null;
let trackers = null;
let fileTree = {};
if (peersData && peersData.length) {
peers = clientUtil.mapClientResponse(
clientUtil.defaults.peerProperties,
peersData
);
mapPropsToResponse: (requestedKeys, clientResponse) => {
if (clientResponse.length === 0) {
return [];
}
if (filesData && filesData.length) {
files = clientUtil.mapClientResponse(
clientUtil.defaults.fileProperties,
filesData
);
// clientResponse is always an array of arrays.
if (clientResponse[0].length === 1) {
// When the length of the nested arrays is 1, the nested arrays represent a
// singular requested value (e.g. total data transferred or current upload
// speed). Therefore we construct an object where the requested keys map to
// their values.
return clientResponse.reduce((memo, value, index) => {
memo[requestedKeys[index]] = value[0];
fileTree = files.reduce((memo, file) => {
return getFileTreeFromPathsArr(memo, file.pathComponents[0], file);
return memo;
}, {});
}
} else {
// When the length of the nested arrays is more than 1, the nested arrays
// represent one of many items of the same type (e.g. a list of torrents,
// peers, files, etc). Therefore we construct an array of objects, where each
// object contains all of the requested keys and its value. We add an index
// for each item, a requirement for file lists.
return clientResponse.map((listItem, index) => {
return listItem.reduce((nestedMemo, value, nestedIndex) => {
nestedMemo[requestedKeys[nestedIndex]] = value;
if (trackerData && trackerData.length) {
trackers = clientUtil.mapClientResponse(
clientUtil.defaults.trackerProperties,
trackerData
);
return nestedMemo;
}, {index});
}, []);
}
return {peers, trackers, fileTree};
},
processFile(file) {
@@ -80,9 +77,49 @@ let clientResponseUtil = {
return file;
},
processTorrentDetails(data) {
// TODO: This is ugly.
let peersData = data[0][0] || null;
let filesData = data[1][0] || null;
let trackerData = data[2][0] || null;
let peers = null;
let files = null;
let trackers = null;
let fileTree = {};
if (peersData && peersData.length) {
peers = clientResponseUtil.mapPropsToResponse(
torrentPeerPropsMap.props,
peersData
);
}
if (filesData && filesData.length) {
files = clientResponseUtil.mapPropsToResponse(
torrentFilePropsMap.props,
filesData
);
fileTree = files.reduce((memo, file) => {
return getFileTreeFromPathsArr(memo, file.pathComponents[0], file);
}, {});
}
if (trackerData && trackerData.length) {
trackers = clientResponseUtil.mapPropsToResponse(
torrentTrackerPropsMap.props,
trackerData
);
}
return {peers, trackers, fileTree};
},
processTransferStats(data) {
return clientUtil.mapClientResponse(clientUtil.defaults.clientProperties,
data);
return clientResponseUtil.mapPropsToResponse(
clientGeneralPropsMap.props,
data
);
}
}
-257
View File
@@ -1,257 +0,0 @@
var util = require('util');
var clientUtil = {
defaults: {
torrentProperties: [
'hash',
'name',
'message',
'state',
'stateChanged',
'isActive',
'isComplete',
'isHashChecking',
'isOpen',
'priority',
'uploadRate',
'uploadTotal',
'downloadRate',
'downloadTotal',
'ratio',
'bytesDone',
'sizeBytes',
// 'chunkSize',
// 'chunksCompleted',
'connectedPeers',
'connectedSeeds',
// 'peerExchange',
'peersConnected',
// 'peersNotConnected',
// 'trackerFocus',
'directory',
'filename',
'basePath',
'baseFilename',
'directoryBase',
'seeding',
'added',
// 'leeches',
// 'seeds',
'creationDate',
'freeDiskSpace',
// 'localId',
// 'localIdHtml',
// 'maxFileSize',
// 'maxSizePex',
'throttleName',
// 'tiedToFile',
// 'trackerNumWant',
// 'trackerSize',
'isMultiFile',
// 'isPexActive',
'isPrivate',
'tags',
'comment',
'ignoreScheduler',
'trackers',
'totalSeeds',
'totalPeers',
// 'cat_dViews',
// 'mode'
],
torrentPropertyMethods: [
'', // yep, rTorrent requires an empty string as the first item.
'main',
'd.hash=',
'd.name=',
'd.message=',
'd.state=',
'd.state_changed=',
'd.is_active=',
'd.complete=',
'd.is_hash_checking=',
'd.is_open=',
'd.priority=',
'd.up.rate=',
'd.up.total=',
'd.down.rate=',
'd.down.total=',
'd.ratio=',
'd.bytes_done=',
'd.size_bytes=',
// 'd.chunk_size=',
// 'd.completed_chunks=',
'd.peers_accounted=', // connnected peers
'd.peers_complete=', // connected seeds
// 'd.peer_exchange=',
'd.peers_connected=', // connected peers + seeds
// 'd.peers_not_connected=',
// 'd.tracker_focus=',
'd.directory=',
'd.base_filename=',
'd.base_path=',
'd.base_filename=',
'd.directory_base=',
'd.custom=seedingtime',
'd.custom=addtime',
// 'd.connection_leech=',
// 'd.connection_seed=',
'd.creation_date=',
'd.free_diskspace=',
// 'd.local_id=',
// 'd.local_id_html=',
// 'd.max_file_size=',
// 'd.max_size_pex=',
'd.throttle_name=',
// 'd.tied_to_file=',
// 'd.tracker_numwant=',
// 'd.tracker_size=',
'd.is_multi_file=',
// 'd.is_pex_active=',
'd.is_private=',
'd.custom1=',
'd.custom2=',
'd.custom=sch_ignore', // ignore scheduler
'cat="$t.multicall=d.hash=,t.url=,cat={@!@}"', // trackers
'cat="$t.multicall=d.hash=,t.scrape_complete=,cat={@!@}"', // seeds
'cat="$t.multicall=d.hash=,t.scrape_incomplete=,cat={@!@}"', // peers
// 'cat=$d.views=',
// 'd.mode='
],
fileProperties: [
'path',
'pathComponents',
'priority',
'sizeBytes',
'sizeChunks',
'completedChunks'
],
filePropertyMethods: [
'f.path=',
'f.path_components=',
'f.priority=',
'f.size_bytes=',
'f.size_chunks=',
'f.completed_chunks='
],
trackerProperties: [
'group',
'url',
'id',
'minInterval',
'normalInterval',
'type'
],
trackerPropertyMethods: [
't.group=',
't.url=',
't.id=',
't.min_interval=',
't.normal_interval=',
't.type='
],
clientProperties: [
'uploadRate',
'uploadTotal',
'uploadThrottle',
'downloadRate',
'downloadTotal',
'downloadThrottle'
],
clientPropertyMethods: [
'throttle.global_up.rate',
'throttle.global_up.total',
'throttle.global_up.max_rate',
'throttle.global_down.rate',
'throttle.global_down.total',
'throttle.global_down.max_rate'
],
peerProperties: [
'address',
'completedPercent',
'clientVersion',
'downloadRate',
'downloadTotal',
'uploadRate',
'uploadTotal',
'id',
'peerRate',
'peerTotal',,
'isEncrypted',
'isIncoming'
],
peerPropertyMethods: [
'p.address=',
'p.completed_percent=',
'p.client_version=',
'p.down_rate=',
'p.down_total=',
'p.up_rate=',
'p.up_total=',
'p.id=',
'p.peer_rate=',
'p.peer_total=',
'p.is_encrypted=',
'p.is_incoming='
]
},
mapClientResponse: (requestedKeys, clientResponse) => {
if (clientResponse.length === 0) {
return [];
}
// clientResponse is always an array of arrays.
if (clientResponse[0].length === 1) {
// When the length of the nested arrays is 1, the nested arrays represent a
// singular requested value (e.g. total data transferred or current upload
// speed). Therefore we construct an object where the requested keys map to
// their values.
return clientResponse.reduce((memo, value, index) => {
memo[requestedKeys[index]] = value[0];
return memo;
}, {});
} else {
// When the length of the nested arrays is more than 1, the nested arrays
// represent one of many items of the same type (e.g. a list of torrents,
// peers, files, etc). Therefore we construct an array of objects, where each
// object contains all of the requested keys and its value. We add an index
// for each item, a requirement for file lists.
return clientResponse.map((listItem, index) => {
return listItem.reduce((nestedMemo, value, nestedIndex) => {
nestedMemo[requestedKeys[nestedIndex]] = value;
return nestedMemo;
}, {index});
}, []);
}
}
}
module.exports = clientUtil;
+24
View File
@@ -0,0 +1,24 @@
'use strict';
const clientGeneralPropsMap = {
props: [
'uploadRate',
'uploadTotal',
'uploadThrottle',
'downloadRate',
'downloadTotal',
'downloadThrottle'
],
methods: [
'throttle.global_up.rate',
'throttle.global_up.total',
'throttle.global_up.max_rate',
'throttle.global_down.rate',
'throttle.global_down.total',
'throttle.global_down.max_rate'
]
};
module.exports = clientGeneralPropsMap;
+22
View File
@@ -0,0 +1,22 @@
'use strict';
const torrentFilePropsMap = {
props: [
'path',
'pathComponents',
'priority',
'sizeBytes',
'sizeChunks',
'completedChunks'
],
methods: [
'f.path=',
'f.path_components=',
'f.priority=',
'f.size_bytes=',
'f.size_chunks=',
'f.completed_chunks='
]
};
module.exports = torrentFilePropsMap;
+145
View File
@@ -0,0 +1,145 @@
'use strict';
const torrentGeneralPropsMap = {
props: [
'hash',
'name',
'message',
'state',
'stateChanged',
'isActive',
'isComplete',
'isHashChecking',
'isOpen',
'priority',
'uploadRate',
'uploadTotal',
'downloadRate',
'downloadTotal',
'ratio',
'bytesDone',
'sizeBytes',
// 'chunkSize',
// 'chunksCompleted',
'connectedPeers',
'connectedSeeds',
// 'peerExchange',
'peersConnected',
// 'peersNotConnected',
// 'trackerFocus',
'directory',
'filename',
'basePath',
'baseFilename',
'directoryBase',
'seeding',
'added',
// 'leeches',
// 'seeds',
'creationDate',
'freeDiskSpace',
// 'localId',
// 'localIdHtml',
// 'maxFileSize',
// 'maxSizePex',
'throttleName',
// 'tiedToFile',
// 'trackerNumWant',
// 'trackerSize',
'isMultiFile',
// 'isPexActive',
'isPrivate',
'tags',
'comment',
'ignoreScheduler',
'trackers',
'totalSeeds',
'totalPeers',
// 'cat_dViews',
// 'mode'
],
methods: [
'', // yep, rTorrent requires an empty string as the first item.
'main',
'd.hash=',
'd.name=',
'd.message=',
'd.state=',
'd.state_changed=',
'd.is_active=',
'd.complete=',
'd.is_hash_checking=',
'd.is_open=',
'd.priority=',
'd.up.rate=',
'd.up.total=',
'd.down.rate=',
'd.down.total=',
'd.ratio=',
'd.bytes_done=',
'd.size_bytes=',
// 'd.chunk_size=',
// 'd.completed_chunks=',
'd.peers_accounted=', // connnected peers
'd.peers_complete=', // connected seeds
// 'd.peer_exchange=',
'd.peers_connected=', // connected peers + seeds
// 'd.peers_not_connected=',
// 'd.tracker_focus=',
'd.directory=',
'd.base_filename=',
'd.base_path=',
'd.base_filename=',
'd.directory_base=',
'd.custom=seedingtime',
'd.custom=addtime',
// 'd.connection_leech=',
// 'd.connection_seed=',
'd.creation_date=',
'd.free_diskspace=',
// 'd.local_id=',
// 'd.local_id_html=',
// 'd.max_file_size=',
// 'd.max_size_pex=',
'd.throttle_name=',
// 'd.tied_to_file=',
// 'd.tracker_numwant=',
// 'd.tracker_size=',
'd.is_multi_file=',
// 'd.is_pex_active=',
'd.is_private=',
'd.custom1=',
'd.custom2=',
'd.custom=sch_ignore', // ignore scheduler
'cat="$t.multicall=d.hash=,t.url=,cat={@!@}"', // trackers
'cat="$t.multicall=d.hash=,t.scrape_complete=,cat={@!@}"', // seeds
'cat="$t.multicall=d.hash=,t.scrape_incomplete=,cat={@!@}"', // peers
// 'cat=$d.views=',
// 'd.mode='
]
};
module.exports = torrentGeneralPropsMap;
+34
View File
@@ -0,0 +1,34 @@
'use strict';
const torrentPeerPropsMap = {
props: [
'address',
'completedPercent',
'clientVersion',
'downloadRate',
'downloadTotal',
'uploadRate',
'uploadTotal',
'id',
'peerRate',
'peerTotal',,
'isEncrypted',
'isIncoming'
],
methods: [
'p.address=',
'p.completed_percent=',
'p.client_version=',
'p.down_rate=',
'p.down_total=',
'p.up_rate=',
'p.up_total=',
'p.id=',
'p.peer_rate=',
'p.peer_total=',
'p.is_encrypted=',
'p.is_incoming='
]
};
module.exports = torrentPeerPropsMap;
@@ -0,0 +1,22 @@
'use strict';
const torrentTrackerPropsMap = {
props: [
'group',
'url',
'id',
'minInterval',
'normalInterval',
'type'
],
methods: [
't.group=',
't.url=',
't.id=',
't.min_interval=',
't.normal_interval=',
't.type='
]
};
module.exports = torrentTrackerPropsMap;
+1 -1
View File
@@ -7,7 +7,7 @@ const FORMAT_UTIL = {
},
parsePeers: (string) => {
// This lovely delimiter is defined in clientUtil.
// This lovely delimiter is defined in clientResponseUtil.
let markerPosition = string.indexOf('@!@');
return string.substr(0, markerPosition);
},