@@ -47,6 +47,7 @@ WebSocketTracker.prototype.announce = function (opts) {
4747
4848 self . _generateOffers ( numwant , function ( offers ) {
4949 var params = extend ( opts , {
50+ action : 'announce' ,
5051 numwant : numwant ,
5152 info_hash : self . client . _infoHashBinary ,
5253 peer_id : self . client . _peerIdBinary ,
@@ -61,7 +62,21 @@ WebSocketTracker.prototype.announce = function (opts) {
6162WebSocketTracker . prototype . scrape = function ( opts ) {
6263 var self = this
6364 if ( self . destroyed || self . reconnecting ) return
64- self . _onSocketError ( new Error ( 'scrape not supported ' + self . announceUrl ) )
65+ if ( ! self . socket . connected ) {
66+ return self . socket . once ( 'connect' , self . scrape . bind ( self , opts ) )
67+ }
68+
69+ var infoHashes = ( Array . isArray ( opts . infoHash ) && opts . infoHash . length > 0 )
70+ ? opts . infoHash . map ( function ( infoHash ) {
71+ return infoHash . toString ( 'binary' )
72+ } )
73+ : ( opts . infoHash && opts . infoHash . toString ( 'binary' ) ) || self . client . _infoHashBinary
74+ var params = {
75+ action : 'scrape' ,
76+ info_hash : infoHashes
77+ }
78+
79+ self . _send ( params )
6580}
6681
6782WebSocketTracker . prototype . destroy = function ( onclose ) {
@@ -133,6 +148,18 @@ WebSocketTracker.prototype._onSocketData = function (data) {
133148 return
134149 }
135150
151+ if ( data . action === common . ACTIONS . ANNOUNCE || data . offer || data . answer ) {
152+ self . _onAnnounceResponse ( data )
153+ } else if ( data . action === common . ACTIONS . SCRAPE ) {
154+ self . _onScrapeResponse ( data )
155+ } else {
156+ throw new Error ( 'invalid action in WS response: ' + data . action )
157+ }
158+ }
159+
160+ WebSocketTracker . prototype . _onAnnounceResponse = function ( data ) {
161+ var self = this
162+
136163 if ( data . info_hash !== self . client . _infoHashBinary ) {
137164 debug (
138165 'ignoring websocket data from %s for %s (looking for %s: reused socket)' ,
@@ -215,6 +242,32 @@ WebSocketTracker.prototype._onSocketData = function (data) {
215242 }
216243}
217244
245+ WebSocketTracker . prototype . _onScrapeResponse = function ( data ) {
246+ var self = this
247+ // NOTE: the unofficial spec says to use the 'files' key, 'host' has been
248+ // seen in practice
249+ data = data . files || data . host || { }
250+
251+ var keys = Object . keys ( data )
252+ if ( keys . length === 0 ) {
253+ self . client . emit ( 'warning' , new Error ( 'invalid scrape response' ) )
254+ return
255+ }
256+
257+ keys . forEach ( function ( infoHash ) {
258+ var response = data [ infoHash ]
259+ // TODO: optionally handle data.flags.min_request_interval
260+ // (separate from announce interval)
261+ self . client . emit ( 'scrape' , {
262+ announce : self . announceUrl ,
263+ infoHash : common . binaryToHex ( infoHash ) ,
264+ complete : response . complete ,
265+ incomplete : response . incomplete ,
266+ downloaded : response . downloaded
267+ } )
268+ } )
269+ }
270+
218271WebSocketTracker . prototype . _onSocketClose = function ( ) {
219272 var self = this
220273 if ( self . destroyed ) return
0 commit comments