1+ const peerid = require ( 'bittorrent-peerid' )
2+
3+ const get8Chars =
4+ peerId => Buffer . from ( peerId , "hex" )
5+ . toString ( )
6+ . substring ( 0 , 8 )
7+
8+ function addPeerClient ( _clients , peer ) {
9+ const clientId = peer . client . client ;
10+ const client = _clients [ clientId ] || { } ;
11+ // If the client is not known show 8 chars from peerId as version
12+ const version = peer . client . version
13+ || get8Chars ( peer . peerId )
14+
15+ if ( ! client [ version ] ) client [ version ] = 1
16+ else client [ version ] ++
17+
18+ _clients [ clientId ] = client
19+
20+ return _clients
21+ }
22+
23+ function groupByClient ( allPeers ) {
24+ const clients =
25+ Object . values ( allPeers )
26+ . reduce ( addPeerClient , { } )
27+
28+ return clients ;
29+ }
30+
31+ const countPeers =
32+ allPeers =>
33+ filterFunction => {
34+ const filteredPeers =
35+ Object . values ( allPeers ) . filter ( filterFunction )
36+
37+ return filteredPeers . length
38+ }
39+
40+ const addPeer =
41+ peers =>
42+ ( allPeers , peerId ) => {
43+ // Don't mark the peer as most recently used for stats
44+ const peer = peers . peek ( peerId )
45+
46+ if ( peer == null ) return // peers.peek() can evict the peer
47+
48+ const peerData = {
49+ peerId : peer . peerId ,
50+ client : peerid ( peer . peerId ) ,
51+ ipv4 : ! peer . ip . includes ( ':' ) ,
52+ ipv6 : peer . ip . includes ( ':' ) ,
53+ seeder : peer . complete ,
54+ leecher : ! peer . complete
55+ }
56+
57+ allPeers [ peerId ] = peerData
58+
59+ return allPeers
60+ }
61+
62+ const hasKeys = ( torrent ) => ( torrent . peers . keys . length > 0 )
63+ const countActiveTorrents = torrents => torrents . filter ( hasKeys ) . length
64+
65+ const addTorrentKeys = ( allPeers , torrent ) => {
66+ const peers = torrent . peers
67+ const keys = peers . keys
68+
69+ const result = keys . reduce ( addPeer ( peers ) , allPeers )
70+
71+ return result
72+ }
73+
74+ const isSeederOnly = peer => ( peer . seeder && peer . leecher === false )
75+ const isLeecherOnly = peer => ( peer . leecher && peer . seeder === false )
76+ const isSeederAndLeecher = peer => ( peer . seeder && peer . leecher )
77+ const isIPv4 = peer => peer . ipv4
78+ const isIPv6 = peer => peer . ipv6
79+
80+ const getStats = server => {
81+ const torrents = Object . values ( server . torrents )
82+ const activeTorrents = countActiveTorrents ( torrents )
83+ const allPeers = torrents . reduce ( addTorrentKeys , { } )
84+ const countAllPeers = countPeers ( allPeers )
85+
86+ const stats = {
87+ torrents : torrents . length ,
88+ activeTorrents,
89+ peersAll : Object . keys ( allPeers ) . length ,
90+ peersSeederOnly : countAllPeers ( isSeederOnly ) ,
91+ peersLeecherOnly : countAllPeers ( isLeecherOnly ) ,
92+ peersSeederAndLeecher : countAllPeers ( isSeederAndLeecher ) ,
93+ peersIPv4 : countAllPeers ( isIPv4 ) ,
94+ peersIPv6 : countAllPeers ( isIPv6 ) ,
95+ clients : groupByClient ( allPeers )
96+ }
97+
98+ return stats
99+ }
100+
101+ module . exports = getStats
0 commit comments