@@ -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 ( cb ) {
@@ -134,6 +149,18 @@ WebSocketTracker.prototype._onSocketData = function (data) {
134149 return
135150 }
136151
152+ if ( data . action === common . ACTIONS . ANNOUNCE || data . offer || data . answer ) {
153+ self . _onAnnounceResponse ( data )
154+ } else if ( data . action === common . ACTIONS . SCRAPE ) {
155+ self . _onScrapeResponse ( data )
156+ } else {
157+ throw new Error ( 'invalid action in WS response: ' + data . action )
158+ }
159+ }
160+
161+ WebSocketTracker . prototype . _onAnnounceResponse = function ( data ) {
162+ var self = this
163+
137164 if ( data . info_hash !== self . client . _infoHashBinary ) {
138165 debug (
139166 'ignoring websocket data from %s for %s (looking for %s: reused socket)' ,
@@ -216,6 +243,32 @@ WebSocketTracker.prototype._onSocketData = function (data) {
216243 }
217244}
218245
246+ WebSocketTracker . prototype . _onScrapeResponse = function ( data ) {
247+ var self = this
248+ // NOTE: the unofficial spec says to use the 'files' key, 'host' has been
249+ // seen in practice
250+ data = data . files || data . host || { }
251+
252+ var keys = Object . keys ( data )
253+ if ( keys . length === 0 ) {
254+ self . client . emit ( 'warning' , new Error ( 'invalid scrape response' ) )
255+ return
256+ }
257+
258+ keys . forEach ( function ( infoHash ) {
259+ var response = data [ infoHash ]
260+ // TODO: optionally handle data.flags.min_request_interval
261+ // (separate from announce interval)
262+ self . client . emit ( 'scrape' , {
263+ announce : self . announceUrl ,
264+ infoHash : common . binaryToHex ( infoHash ) ,
265+ complete : response . complete ,
266+ incomplete : response . incomplete ,
267+ downloaded : response . downloaded
268+ } )
269+ } )
270+ }
271+
219272WebSocketTracker . prototype . _onSocketClose = function ( ) {
220273 var self = this
221274 if ( self . destroyed ) return
0 commit comments