diff --git a/LICENSE b/LICENSE index fd04129..0538296 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright 2020 Leo Herzog +Copyright © 2020 Leo Herzog Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: diff --git a/README.md b/README.md index 7f386aa..730c2e1 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ This project wouldn't be possible without the fantastic work of: The MIT License (MIT) -Copyright (c) 2020 Leo Herzog +Copyright © 2020 Leo Herzog Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: @@ -37,8 +37,6 @@ The above copyright notice and this permission notice shall be included in all c THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -- - - - - ## About Me diff --git a/bundle.js b/bundle.js index 2f5a532..61e435c 100644 --- a/bundle.js +++ b/bundle.js @@ -37884,6 +37884,10 @@ const mime = require('mime-types'); const WebTorrent = require('webtorrent'); const tippy = require('tippy.js').default; +var examples = document.getElementById('examples'); +var example1 = document.getElementById('example1'); +var example2 = document.getElementById('example2'); +var example3 = document.getElementById('example3'); var properties = document.getElementById('properties'); var originalSourceIcon = document.getElementById('originalSourceIcon'); var source; @@ -37973,6 +37977,26 @@ function start() { }); }); + example1.addEventListener('click', function(event) { + event.preventDefault(); + notyf.success("Parsing Ubuntu 20.04 Magnet URL"); + parse("magnet:?xt=urn:btih:9fc20b9e98ea98b4a35e6223041a5ef94ea27809&dn=ubuntu-20.04-desktop-amd64.iso&tr=https%3A%2F%2Ftorrent.ubuntu.com%2Fannounce&tr=https%3A%2F%2Fipv6.torrent.ubuntu.com%2Fannounce"); + }); + + example2.addEventListener('click', async function(event) { + event.preventDefault(); + notyf.success("Fetching and Parsing “The WIRED CD” Torrent File..."); + parseRemote("https://webtorrent.io/torrents/wired-cd.torrent"); + }); + + example3.addEventListener('click', async function(event) { + event.preventDefault(); + notyf.success("Parsing Jack Johnson Archive.org Torrent File"); + let response = await fetch("jj2008-06-14.mk4_archive.torrent"); + let arrayBuffer = await response.arrayBuffer(); + parse(Buffer.from(arrayBuffer)); + }); + let copyurl = new clipboard('#copyURL'); copyurl.on('success', function(e) { notyf.success('Copied site URL to clipboard!'); @@ -38054,7 +38078,7 @@ function parse(toLoad) { function parseRemote(toLoad) { parser.remote(toLoad, function(err, result) { if (err) { - notyf.error('Problem remotely fetching file or parsing result'); + notyf.error('Problem remotely fetching that file or parsing result'); console.warn(err); resetProperties(); return; @@ -38161,6 +38185,7 @@ function display() { copyURL.setAttribute('data-clipboard-text', window.location.origin + "#" + parser.toMagnetURI(parsed)); copyMagnet.setAttribute('data-clipboard-text', parser.toMagnetURI(parsed)); + examples.style.display = 'none'; properties.style.display = 'flex'; window.location.hash = parser.toMagnetURI(parsed); @@ -38250,6 +38275,7 @@ function propertyChange(e) { function resetProperties() { document.getElementById('magnet').value = ""; document.getElementById('torrent').value = ""; + examples.style.display = 'flex'; properties.style.display = 'none'; name.value = ""; created.value = ""; diff --git a/bundle.min.js b/bundle.min.js index 48dbfa6..ebec553 100644 --- a/bundle.min.js +++ b/bundle.min.js @@ -84,4 +84,4 @@ const i=e("debug")("torrent-discovery"),r=e("bittorrent-dht/client"),o=e("events /*! ut_metadata. MIT License. WebTorrent LLC */ const{EventEmitter:i}=e("events"),r=e("bencode"),o=e("bitfield").default,s=e("debug")("ut_metadata"),a=e("simple-sha1"),c=16384;t.exports=e=>{class t extends i{constructor(t){super(),this._wire=t,this._fetching=!1,this._metadataComplete=!1,this._metadataSize=null,this._remainingRejects=null,this._bitfield=new o(0,{grow:1e3}),n.isBuffer(e)&&this.setMetadata(e)}onHandshake(e,t,n){this._infoHash=e}onExtendedHandshake(e){return e.m&&e.m.ut_metadata?e.metadata_size?"number"!=typeof e.metadata_size||1e7this._metadataSize&&(n=this._metadataSize);const i=this.metadata.slice(t,n);this._data(e,i,this._metadataSize)}_onData(e,t,n){t.length>c||!this._fetching||(t.copy(this.metadata,e*c),this._bitfield.set(e),this._checkDone())}_onReject(e){this._remainingRejects>0&&this._fetching?(this._request(e),this._remainingRejects-=1):this.emit("warning",new Error('Peer sent "reject" too much'))}_requestPieces(){if(this._fetching){this.metadata=n.alloc(this._metadataSize);for(let e=0;e0?this._requestPieces():this.emit("warning",new Error("Peer sent invalid metadata"))}}return t.prototype.name="ut_metadata",t}}).call(this)}).call(this,e("buffer").Buffer)},{bencode:7,bitfield:302,buffer:60,debug:303,events:98,"simple-sha1":242}],302:[function(e,t,n){arguments[4][12][0].apply(n,arguments)},{dup:12}],303:[function(e,t,n){arguments[4][13][0].apply(n,arguments)},{"./common":304,_process:187,dup:13}],304:[function(e,t,n){arguments[4][14][0].apply(n,arguments)},{dup:14,ms:305}],305:[function(e,t,n){arguments[4][15][0].apply(n,arguments)},{dup:15}],306:[function(e,t,n){(function(e){(function(){function n(t){try{if(!e.localStorage)return!1}catch(e){return!1}var n=e.localStorage[t];return null!=n&&"true"===String(n).toLowerCase()}t.exports=function(e,t){if(n("noDeprecation"))return e;var i=!1;return function(){if(!i){if(n("throwDeprecation"))throw new Error(t);n("traceDeprecation")?console.trace(t):console.warn(t),i=!0}return e.apply(this,arguments)}}}).call(this)}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}],307:[function(e,t,n){(function(n){(function(){const i=e("binary-search"),r=e("events"),o=e("mp4-stream"),s=e("mp4-box-encoding"),a=e("range-slice-stream");class c{constructor(e,t){this._entries=e,this._countName=t||"count",this._index=0,this._offset=0,this.value=this._entries[0]}inc(){this._offset++,this._offset>=this._entries[this._index][this._countName]&&(this._index++,this._offset=0),this.value=this._entries[this._index]}}const l=1;t.exports=class extends r{constructor(e){super(),this._tracks=[],this._file=e,this._decoder=null,this._findMoov(0)}_findMoov(e){this._decoder&&this._decoder.destroy();let t=0;this._decoder=o.decode();const n=this._file.createReadStream({start:e});n.pipe(this._decoder);const i=r=>{"moov"===r.type?(this._decoder.removeListener("box",i),this._decoder.decode((e=>{n.destroy();try{this._processMoov(e)}catch(e){e.message="Cannot parse mp4 file: "+e.message,this.emit("error",e)}}))):r.length<4096?(t+=r.length,this._decoder.ignore()):(this._decoder.removeListener("box",i),t+=r.length,n.destroy(),this._decoder.destroy(),this._findMoov(e+t))};this._decoder.on("box",i)}_processMoov(e){const t=e.traks;this._tracks=[],this._hasVideo=!1,this._hasAudio=!1;for(let n=0;n=o.stsz.entries.length)break;if(f++,m+=e,f>=i.samplesPerChunk){f=0,m=0,h++;const e=o.stsc.entries[g+1];e&&h+1>=e.firstChunk&&g++}v+=t,b.inc(),x&&x.inc(),r&&y++}r.mdia.mdhd.duration=0,r.tkhd.duration=0;const _=i.sampleDescriptionId,w={type:"moov",mvhd:e.mvhd,traks:[{tkhd:r.tkhd,mdia:{mdhd:r.mdia.mdhd,hdlr:r.mdia.hdlr,elng:r.mdia.elng,minf:{vmhd:r.mdia.minf.vmhd,smhd:r.mdia.minf.smhd,dinf:r.mdia.minf.dinf,stbl:{stsd:o.stsd,stts:{version:0,flags:0,entries:[]},ctts:{version:0,flags:0,entries:[]},stsc:{version:0,flags:0,entries:[]},stsz:{version:0,flags:0,entries:[]},stco:{version:0,flags:0,entries:[]},stss:{version:0,flags:0,entries:[]}}}}}],mvex:{mehd:{fragmentDuration:e.mvhd.duration},trexs:[{trackId:r.tkhd.trackId,defaultSampleDescriptionIndex:_,defaultSampleDuration:0,defaultSampleSize:0,defaultSampleFlags:0}]}};this._tracks.push({fragmentSequence:1,trackId:r.tkhd.trackId,timeScale:r.mdia.mdhd.timeScale,samples:u,currSample:null,currTime:null,moov:w,mime:p})}if(0===this._tracks.length)return void this.emit("error",new Error("no playable tracks"));e.mvhd.duration=0,this._ftyp={type:"ftyp",brand:"iso5",brandVersion:0,compatibleBrands:["iso5"]};const r=s.encode(this._ftyp),o=this._tracks.map((e=>{const t=s.encode(e.moov);return{mime:e.mime,init:n.concat([r,t])}}));this.emit("ready",o)}seek(e){if(!this._tracks)throw new Error("Not ready yet; wait for 'ready' event");this._fileStream&&(this._fileStream.destroy(),this._fileStream=null);let t=-1;if(this._tracks.map(((n,i)=>{n.outStream&&n.outStream.destroy(),n.inStream&&(n.inStream.destroy(),n.inStream=null);const r=n.outStream=o.encode(),s=this._generateFragment(i,e);if(!s)return r.finalize();(-1===t||s.ranges[0].start{r.destroyed||r.box(e.moof,(t=>{if(t)return this.emit("error",t);if(r.destroyed)return;n.inStream.slice(e.ranges).pipe(r.mediaData(e.length,(e=>{if(e)return this.emit("error",e);if(r.destroyed)return;const t=this._generateFragment(i);if(!t)return r.finalize();a(t)})))}))};a(s)})),t>=0){const e=this._fileStream=this._file.createReadStream({start:t});this._tracks.forEach((n=>{n.inStream=new a(t,{highWaterMark:1e7}),e.pipe(n.inStream)}))}return this._tracks.map((e=>e.outStream))}_findSampleBefore(e,t){const n=this._tracks[e],r=Math.floor(n.timeScale*t);let o=i(n.samples,r,((e,t)=>e.dts+e.presentationOffset-t));for(-1===o?o=0:o<0&&(o=-o-2);!n.samples[o].sync;)o--;return o}_generateFragment(e,t){const n=this._tracks[e];let i;if(i=void 0!==t?this._findSampleBefore(e,t):n.currSample,i>=n.samples.length)return null;const r=n.samples[i].dts;let o=0;const s=[];for(var a=i;a=n.timeScale*l)break;o+=e.size;const t=s.length-1;t<0||s[t].end!==e.offset?s.push({start:e.offset,end:e.offset+e.size}):s[t].end+=e.size}return n.currSample=a,{moof:this._generateMoof(e,i,a),ranges:s,length:o}}_generateMoof(e,t,n){const i=this._tracks[e],r=[];let o=0;for(let e=t;e{this.detailedError=this._elemWrapper.detailedError,this.destroy()},this._onWaiting=()=>{this._waitingFired=!0,this._muxer?this._tracks&&this._pump():this._createMuxer()},t.autoplay&&(t.preload="auto"),t.addEventListener("waiting",this._onWaiting),t.addEventListener("error",this._onError)}s.prototype={_createMuxer(){this._muxer=new o(this._file),this._muxer.on("ready",(e=>{this._tracks=e.map((e=>{const t=this._elemWrapper.createWriteStream(e.mime);t.on("error",(e=>{this._elemWrapper.error(e)}));const n={muxed:null,mediaSource:t,initFlushed:!1,onInitFlushed:null};return t.write(e.init,(e=>{n.initFlushed=!0,n.onInitFlushed&&n.onInitFlushed(e)})),n})),(this._waitingFired||"auto"===this._elem.preload)&&this._pump()})),this._muxer.on("error",(e=>{this._elemWrapper.error(e)}))},_pump(){const e=this._muxer.seek(this._elem.currentTime,!this._tracks);this._tracks.forEach(((t,n)=>{const i=()=>{t.muxed&&(t.muxed.destroy(),t.mediaSource=this._elemWrapper.createWriteStream(t.mediaSource),t.mediaSource.on("error",(e=>{this._elemWrapper.error(e)}))),t.muxed=e[n],r(t.muxed,t.mediaSource)};t.initFlushed?i():t.onInitFlushed=e=>{e?this._elemWrapper.error(e):i()}}))},destroy(){this.destroyed||(this.destroyed=!0,this._elem.removeEventListener("waiting",this._onWaiting),this._elem.removeEventListener("error",this._onError),this._tracks&&this._tracks.forEach((e=>{e.muxed&&e.muxed.destroy()})),this._elem.src="")}},t.exports=s},{"./mp4-remuxer":307,mediasource:125,pump:188}],309:[function(e,t,n){(function(n,i,r){(function(){ /*! webtorrent. MIT License. WebTorrent LLC */ -const{EventEmitter:o}=e("events"),s=e("simple-concat"),a=e("create-torrent"),c=e("debug")("webtorrent"),l=e("bittorrent-dht/client"),p=e("load-ip-set"),u=e("run-parallel"),d=e("parse-torrent"),f=e("path"),h=e("simple-peer"),m=e("randombytes"),g=e("speedometer"),v=e("./lib/conn-pool"),b=e("./lib/torrent"),x=e("./package.json").version,y=x.replace(/\d*./g,(e=>("0"+e%100).slice(-2))).slice(0,4),_=`-WW${y}-`;class w extends o{constructor(e={}){super(),"string"==typeof e.peerId?this.peerId=e.peerId:r.isBuffer(e.peerId)?this.peerId=e.peerId.toString("hex"):this.peerId=r.from(_+m(9).toString("base64")).toString("hex"),this.peerIdBuffer=r.from(this.peerId,"hex"),"string"==typeof e.nodeId?this.nodeId=e.nodeId:r.isBuffer(e.nodeId)?this.nodeId=e.nodeId.toString("hex"):this.nodeId=m(20).toString("hex"),this.nodeIdBuffer=r.from(this.nodeId,"hex"),this._debugId=this.peerId.toString("hex").substring(0,7),this.destroyed=!1,this.listening=!1,this.torrentPort=e.torrentPort||0,this.dhtPort=e.dhtPort||0,this.tracker=void 0!==e.tracker?e.tracker:{},this.torrents=[],this.maxConns=Number(e.maxConns)||55,this.utp=!0===e.utp,this._debug("new webtorrent (peerId %s, nodeId %s, port %s)",this.peerId,this.nodeId,this.torrentPort),this.tracker&&("object"!=typeof this.tracker&&(this.tracker={}),e.rtcConfig&&(console.warn("WebTorrent: opts.rtcConfig is deprecated. Use opts.tracker.rtcConfig instead"),this.tracker.rtcConfig=e.rtcConfig),e.wrtc&&(console.warn("WebTorrent: opts.wrtc is deprecated. Use opts.tracker.wrtc instead"),this.tracker.wrtc=e.wrtc),i.WRTC&&!this.tracker.wrtc&&(this.tracker.wrtc=i.WRTC)),"function"==typeof v?this._connPool=new v(this):n.nextTick((()=>{this._onListening()})),this._downloadSpeed=g(),this._uploadSpeed=g(),!1!==e.dht&&"function"==typeof l?(this.dht=new l(Object.assign({},{nodeId:this.nodeId},e.dht)),this.dht.once("error",(e=>{this._destroy(e)})),this.dht.once("listening",(()=>{const e=this.dht.address();e&&(this.dhtPort=e.port)})),this.dht.setMaxListeners(0),this.dht.listen(this.dhtPort)):this.dht=!1,this.enableWebSeeds=!1!==e.webSeeds;const t=()=>{this.destroyed||(this.ready=!0,this.emit("ready"))};"function"==typeof p&&null!=e.blocklist?p(e.blocklist,{headers:{"user-agent":`WebTorrent/${x} (https://webtorrent.io)`}},((e,n)=>{if(e)return this.error("Failed to load blocklist: "+e.message);this.blocked=n,t()})):n.nextTick(t)}get downloadSpeed(){return this._downloadSpeed()}get uploadSpeed(){return this._uploadSpeed()}get progress(){const e=this.torrents.filter((e=>1!==e.progress));return e.reduce(((e,t)=>e+t.downloaded),0)/(e.reduce(((e,t)=>e+(t.length||0)),0)||1)}get ratio(){return this.torrents.reduce(((e,t)=>e+t.uploaded),0)/(this.torrents.reduce(((e,t)=>e+t.received),0)||1)}get(e){if(e instanceof b){if(this.torrents.includes(e))return e}else{let t;try{t=d(e)}catch(e){}if(!t)return null;if(!t.infoHash)throw new Error("Invalid torrent identifier");for(const e of this.torrents)if(e.infoHash===t.infoHash)return e}return null}download(e,t,n){return console.warn("WebTorrent: client.download() is deprecated. Use client.add() instead"),this.add(e,t,n)}add(e,t={},n=(()=>{})){if(this.destroyed)throw new Error("client is destroyed");"function"==typeof t&&([t,n]=[{},t]);const i=()=>{if(!this.destroyed)for(const e of this.torrents)if(e.infoHash===o.infoHash&&e!==o)return void o._destroy(new Error("Cannot add duplicate torrent "+o.infoHash))},r=()=>{this.destroyed||(n(o),this.emit("torrent",o))};this._debug("add"),t=t?Object.assign({},t):{};const o=new b(e,this,t);return this.torrents.push(o),o.once("_infoHash",i),o.once("ready",r),o.once("close",(function e(){o.removeListener("_infoHash",i),o.removeListener("ready",r),o.removeListener("close",e)})),o}seed(e,t,n){if(this.destroyed)throw new Error("client is destroyed");"function"==typeof t&&([t,n]=[{},t]),this._debug("seed"),(t=t?Object.assign({},t):{}).skipVerify=!0;const i="string"==typeof e;i&&(t.path=f.dirname(e)),t.createdBy||(t.createdBy="WebTorrent/"+y);const r=e=>{this._debug("on seed"),"function"==typeof n&&n(e),e.emit("seed"),this.emit("seed",e)},o=this.add(null,t,(e=>{const t=[t=>{if(i)return t();e.load(c,t)}];this.dht&&t.push((t=>{e.once("dhtAnnounce",t)})),u(t,(t=>{if(!this.destroyed)return t?e._destroy(t):void r(e)}))}));let c;var l;return l=e,"undefined"!=typeof FileList&&l instanceof FileList?e=Array.from(e):Array.isArray(e)||(e=[e]),u(e.map((e=>t=>{!function(e){return"object"==typeof e&&null!=e&&"function"==typeof e.pipe}(e)?t(null,e):s(e,t)})),((e,n)=>{if(!this.destroyed)return e?o._destroy(e):void a.parseInput(n,t,((e,i)=>{if(!this.destroyed){if(e)return o._destroy(e);c=i.map((e=>e.getStream)),a(n,t,((e,t)=>{if(this.destroyed)return;if(e)return o._destroy(e);const n=this.get(t);n?o._destroy(new Error("Cannot add duplicate torrent "+n.infoHash)):o._onTorrentId(t)}))}}))})),o}remove(e,t,n){if("function"==typeof t)return this.remove(e,null,t);this._debug("remove");if(!this.get(e))throw new Error("No torrent with id "+e);this._remove(e,t,n)}_remove(e,t,n){if("function"==typeof t)return this._remove(e,null,t);const i=this.get(e);i&&(this.torrents.splice(this.torrents.indexOf(i),1),i.destroy(t,n))}address(){return this.listening?this._connPool?this._connPool.tcpServer.address():{address:"0.0.0.0",family:"IPv4",port:0}:null}destroy(e){if(this.destroyed)throw new Error("client already destroyed");this._destroy(null,e)}_destroy(e,t){this._debug("client destroy"),this.destroyed=!0;const n=this.torrents.map((e=>t=>{e.destroy(t)}));this._connPool&&n.push((e=>{this._connPool.destroy(e)})),this.dht&&n.push((e=>{this.dht.destroy(e)})),u(n,t),e&&this.emit("error",e),this.torrents=[],this._connPool=null,this.dht=null}_onListening(){if(this._debug("listening"),this.listening=!0,this._connPool){const e=this._connPool.tcpServer.address();e&&(this.torrentPort=e.port)}this.emit("listening")}_debug(){const e=[].slice.call(arguments);e[0]=`[${this._debugId}] ${e[0]}`,c(...e)}}w.WEBRTC_SUPPORT=h.WEBRTC_SUPPORT,w.VERSION=x,t.exports=w}).call(this)}).call(this,e("_process"),"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{},e("buffer").Buffer)},{"./lib/conn-pool":55,"./lib/torrent":314,"./package.json":334,_process:187,"bittorrent-dht/client":55,buffer:60,"create-torrent":80,debug:316,events:98,"load-ip-set":55,"parse-torrent":184,path:185,randombytes:195,"run-parallel":218,"simple-concat":221,"simple-peer":223,speedometer:263}],310:[function(e,t,n){const i=e("debug")("webtorrent:file-stream"),r=e("readable-stream");class o extends r.Readable{constructor(e,t){super(t),this.destroyed=!1,this._torrent=e._torrent;const n=t&&t.start||0,i=t&&t.end&&t.end{if(this._notifying=!1,!this.destroyed){if(i("read %s (length %s) (err %s)",e,n.length,t&&t.message),t)return this._destroy(t);this._offset&&(n=n.slice(this._offset),this._offset=0),this._missing{e.end()})),e}const t=new u(this,e);return this._torrent.select(t._startPiece,t._endPiece,!0,(()=>{t._notify()})),o(t,(()=>{this._destroyed||this._torrent.destroyed||this._torrent.deselect(t._startPiece,t._endPiece,!0)})),t}getBuffer(e){p(this.createReadStream(),this.length,e)}getBlob(e){if("undefined"==typeof window)throw new Error("browser-only method");c(this.createReadStream(),this._getMimeType()).then((t=>e(null,t)),(t=>e(t)))}getBlobURL(e){if("undefined"==typeof window)throw new Error("browser-only method");l(this.createReadStream(),this._getMimeType()).then((t=>e(null,t)),(t=>e(t)))}appendTo(e,t,n){if("undefined"==typeof window)throw new Error("browser-only method");a.append(this,e,t,n)}renderTo(e,t,n){if("undefined"==typeof window)throw new Error("browser-only method");a.render(this,e,t,n)}_getMimeType(){return a.mime[s.extname(this.name).toLowerCase()]}_destroy(){this._destroyed=!0,this._torrent=null}}}).call(this)}).call(this,e("_process"))},{"./file-stream":310,_process:187,"end-of-stream":96,events:98,path:185,"readable-stream":333,"render-media":212,"stream-to-blob":284,"stream-to-blob-url":283,"stream-with-known-length-to-buffer":285}],312:[function(e,t,n){const i=e("unordered-array-remove"),r=e("debug")("webtorrent:peer"),o=e("bittorrent-protocol"),s=e("./webconn");n.createWebRTCPeer=(e,t)=>{const n=new l(e.id,"webrtc");return n.conn=e,n.swarm=t,n.conn.connected?n.onConnect():(n.conn.once("connect",(()=>{n.onConnect()})),n.conn.once("error",(e=>{n.destroy(e)})),n.startConnectTimeout()),n},n.createTCPIncomingPeer=e=>a(e,"tcpIncoming"),n.createUTPIncomingPeer=e=>a(e,"utpIncoming"),n.createTCPOutgoingPeer=(e,t)=>c(e,t,"tcpOutgoing"),n.createUTPOutgoingPeer=(e,t)=>c(e,t,"utpOutgoing");const a=(e,t)=>{const n=`${e.remoteAddress}:${e.remotePort}`,i=new l(n,t);return i.conn=e,i.addr=n,i.onConnect(),i},c=(e,t,n)=>{const i=new l(e,n);return i.addr=e,i.swarm=t,i};n.createWebSeedPeer=(e,t)=>{const n=new l(e,"webSeed");return n.swarm=t,n.conn=new s(e,t),n.onConnect(),n};class l{constructor(e,t){this.id=e,this.type=t,r("new %s Peer %s",t,e),this.addr=null,this.conn=null,this.swarm=null,this.wire=null,this.connected=!1,this.destroyed=!1,this.timeout=null,this.retries=0,this.sentHandshake=!1}onConnect(){if(this.destroyed)return;this.connected=!0,r("Peer %s connected",this.id),clearTimeout(this.connectTimeout);const e=this.conn;e.once("end",(()=>{this.destroy()})),e.once("close",(()=>{this.destroy()})),e.once("finish",(()=>{this.destroy()})),e.once("error",(e=>{this.destroy(e)}));const t=this.wire=new o;t.type=this.type,t.once("end",(()=>{this.destroy()})),t.once("close",(()=>{this.destroy()})),t.once("finish",(()=>{this.destroy()})),t.once("error",(e=>{this.destroy(e)})),t.once("handshake",((e,t)=>{this.onHandshake(e,t)})),this.startHandshakeTimeout(),e.pipe(t).pipe(e),this.swarm&&!this.sentHandshake&&this.handshake()}onHandshake(e,t){if(!this.swarm)return;if(this.destroyed)return;if(this.swarm.destroyed)return this.destroy(new Error("swarm already destroyed"));if(e!==this.swarm.infoHash)return this.destroy(new Error("unexpected handshake info hash for this swarm"));if(t===this.swarm.peerId)return this.destroy(new Error("refusing to connect to ourselves"));r("Peer %s got handshake %s",this.id,e),clearTimeout(this.handshakeTimeout),this.retries=0;let n=this.addr;!n&&this.conn.remoteAddress&&this.conn.remotePort&&(n=`${this.conn.remoteAddress}:${this.conn.remotePort}`),this.swarm._onWire(this.wire,n),this.swarm&&!this.swarm.destroyed&&(this.sentHandshake||this.handshake())}handshake(){const e={dht:!this.swarm.private&&!!this.swarm.client.dht};this.wire.handshake(this.swarm.infoHash,this.swarm.client.peerId,e),this.sentHandshake=!0}startConnectTimeout(){clearTimeout(this.connectTimeout);const e={webrtc:25e3,tcpOutgoing:5e3,utpOutgoing:5e3};this.connectTimeout=setTimeout((()=>{this.destroy(new Error("connect timeout"))}),e[this.type]),this.connectTimeout.unref&&this.connectTimeout.unref()}startHandshakeTimeout(){clearTimeout(this.handshakeTimeout),this.handshakeTimeout=setTimeout((()=>{this.destroy(new Error("handshake timeout"))}),25e3),this.handshakeTimeout.unref&&this.handshakeTimeout.unref()}destroy(e){if(this.destroyed)return;this.destroyed=!0,this.connected=!1,r("destroy %s %s (error: %s)",this.type,this.id,e&&(e.message||e)),clearTimeout(this.connectTimeout),clearTimeout(this.handshakeTimeout);const t=this.swarm,n=this.conn,o=this.wire;this.swarm=null,this.conn=null,this.wire=null,t&&o&&i(t.wires,t.wires.indexOf(o)),n&&(n.on("error",(()=>{})),n.destroy()),o&&o.destroy(),t&&t.removePeer(this.id)}}},{"./webconn":315,"bittorrent-protocol":11,debug:316,"unordered-array-remove":298}],313:[function(e,t,n){t.exports=class{constructor(e){this._torrent=e,this._numPieces=e.pieces.length,this._pieces=new Array(this._numPieces),this._onWire=e=>{this.recalculate(),this._initWire(e)},this._onWireHave=e=>{this._pieces[e]+=1},this._onWireBitfield=()=>{this.recalculate()},this._torrent.wires.forEach((e=>{this._initWire(e)})),this._torrent.on("wire",this._onWire),this.recalculate()}getRarestPiece(e){let t=[],n=1/0;for(let i=0;i{this._cleanupWireEvents(e)})),this._torrent=null,this._pieces=null,this._onWire=null,this._onWireHave=null,this._onWireBitfield=null}_initWire(e){e._onClose=()=>{this._cleanupWireEvents(e);for(let t=0;t{this.destroyed||this._onParsedTorrent(t)}))):x.remote(e,((e,t)=>{if(!this.destroyed)return e?this._destroy(e):void this._onParsedTorrent(t)}))}_onParsedTorrent(e){if(!this.destroyed){if(this._processParsedTorrent(e),!this.infoHash)return this._destroy(new Error("Malformed torrent data: No info hash"));this.path||(this.path=y.join(N,this.infoHash)),this._rechokeIntervalId=setInterval((()=>{this._rechoke()}),1e4),this._rechokeIntervalId.unref&&this._rechokeIntervalId.unref(),this.emit("_infoHash",this.infoHash),this.destroyed||(this.emit("infoHash",this.infoHash),this.destroyed||(this.client.listening?this._onListening():this.client.once("listening",(()=>{this._onListening()}))))}}_processParsedTorrent(e){this._debugId=e.infoHash.toString("hex").substring(0,7),void 0!==this.private&&(e.private=this.private),this.announce&&(e.announce=e.announce.concat(this.announce)),this.client.tracker&&i.WEBTORRENT_ANNOUNCE&&!e.private&&(e.announce=e.announce.concat(i.WEBTORRENT_ANNOUNCE)),this.urlList&&(e.urlList=e.urlList.concat(this.urlList)),e.announce=Array.from(new Set(e.announce)),e.urlList=Array.from(new Set(e.urlList)),Object.assign(this,e),this.magnetURI=x.toMagnetURI(e),this.torrentFile=x.toTorrentFile(e)}_onListening(){this.destroyed||(this.info?this._onMetadata(this):(this.xs&&this._getMetadataFromServer(),this._startDiscovery()))}_startDiscovery(){if(this.discovery||this.destroyed)return;let e=this.client.tracker;e&&(e=Object.assign({},this.client.tracker,{getAnnounceOpts:()=>{const e={uploaded:this.uploaded,downloaded:this.downloaded,left:Math.max(this.length-this.downloaded,0)};return this.client.tracker.getAnnounceOpts&&Object.assign(e,this.client.tracker.getAnnounceOpts()),this._getAnnounceOpts&&Object.assign(e,this._getAnnounceOpts()),e}})),this.peerAddresses&&this.peerAddresses.forEach((e=>this.addPeer(e))),this.discovery=new c({infoHash:this.infoHash,announce:this.announce,peerId:this.client.peerId,dht:!this.private&&this.client.dht,tracker:e,port:this.client.torrentPort,userAgent:P}),this.discovery.on("error",(e=>{this._destroy(e)})),this.discovery.on("peer",(e=>{"string"==typeof e&&this.done||this.addPeer(e)})),this.discovery.on("trackerAnnounce",(()=>{this.emit("trackerAnnounce"),0===this.numPeers&&this.emit("noPeers","tracker")})),this.discovery.on("dhtAnnounce",(()=>{this.emit("dhtAnnounce"),0===this.numPeers&&this.emit("noPeers","dht")})),this.discovery.on("warning",(e=>{this.emit("warning",e)}))}_getMetadataFromServer(){const e=this,t=(Array.isArray(this.xs)?this.xs:[this.xs]).map((t=>n=>{!function(t,n){if(0!==t.indexOf("http://")&&0!==t.indexOf("https://"))return e.emit("warning",new Error("skipping non-http xs param: "+t)),n(null);const i={url:t,method:"GET",headers:{"user-agent":P}};let r;try{r=d.concat(i,o)}catch(i){return e.emit("warning",new Error("skipping invalid url xs param: "+t)),n(null)}function o(i,r,o){if(e.destroyed)return n(null);if(e.metadata)return n(null);if(i)return e.emit("warning",new Error("http error from xs param: "+t)),n(null);if(200!==r.statusCode)return e.emit("warning",new Error(`non-200 status code ${r.statusCode} from xs param: ${t}`)),n(null);let s;try{s=x(o)}catch(i){}return s?s.infoHash!==e.infoHash?(e.emit("warning",new Error("got torrent file with incorrect info hash from xs param: "+t)),n(null)):(e._onMetadata(s),void n(null)):(e.emit("warning",new Error("got invalid torrent file from xs param: "+t)),n(null))}e._xsRequests.push(r)}(t,n)}));v(t)}_onMetadata(e){if(this.metadata||this.destroyed)return;let t;if(this._debug("got metadata"),this._xsRequests.forEach((e=>{e.abort()})),this._xsRequests=[],e&&e.infoHash)t=e;else try{t=x(e)}catch(e){return this._destroy(e)}if(this._processParsedTorrent(t),this.metadata=this.torrentFile,this.client.enableWebSeeds&&this.urlList.forEach((e=>{this.addWebSeed(e)})),this._rarityMap=new I(this),this.store=new f(new this._store(this.pieceLength,{torrent:{infoHash:this.infoHash},files:this.files.map((e=>({path:y.join(this.path,e.path),length:e.length,offset:e.offset}))),length:this.length,name:this.infoHash})),this.files=this.files.map((e=>new A(this,e))),this.so?this.files.forEach(((e,t)=>{this.so.includes(t)?this.files[t].select():this.files[t].deselect()})):0!==this.pieces.length&&this.select(0,this.pieces.length-1,!1),this._hashes=this.pieces,this.pieces=this.pieces.map(((e,t)=>{const n=t===this.pieces.length-1?this.lastPieceLength:this.pieceLength;return new _(n)})),this._reservations=this.pieces.map((()=>[])),this.bitfield=new o(this.pieces.length),this.wires.forEach((e=>{e.ut_metadata&&e.ut_metadata.setMetadata(this.metadata),this._onWireWithMetadata(e)})),this.emit("metadata"),!this.destroyed)if(this.skipVerify)this._markAllVerified(),this._onStore();else{const e=e=>{if(e)return this._destroy(e);this._debug("done verifying"),this._onStore()};this._debug("verifying existing torrent data"),this._fileModtimes&&this._store===u?this.getFileModtimes(((t,n)=>{if(t)return this._destroy(t);this.files.map(((e,t)=>n[t]===this._fileModtimes[t])).every((e=>e))?(this._markAllVerified(),this._onStore()):this._verifyPieces(e)})):this._verifyPieces(e)}}getFileModtimes(e){const t=[];b(this.files.map(((e,n)=>i=>{p.stat(y.join(this.path,e.path),((e,r)=>{if(e&&"ENOENT"!==e.code)return i(e);t[n]=r&&r.mtime.getTime(),i(null)}))})),U,(n=>{this._debug("done getting file modtimes"),e(n,t)}))}_verifyPieces(e){b(this.pieces.map(((e,t)=>e=>{if(this.destroyed)return e(new Error("torrent is destroyed"));this.store.get(t,((i,r)=>this.destroyed?e(new Error("torrent is destroyed")):i?n.nextTick(e,null):void E(r,(n=>{if(this.destroyed)return e(new Error("torrent is destroyed"));if(n===this._hashes[t]){if(!this.pieces[t])return e(null);this._debug("piece verified %s",t),this._markVerified(t)}else this._debug("piece invalid %s",t);e(null)}))))})),U,e)}rescanFiles(e){if(this.destroyed)throw new Error("torrent is destroyed");e||(e=q),this._verifyPieces((t=>{if(t)return this._destroy(t),e(t);this._checkDone(),e(null)}))}_markAllVerified(){for(let e=0;e{e.abort()})),this._rarityMap&&this._rarityMap.destroy();for(const e in this._peers)this.removePeer(e);this.files.forEach((e=>{e instanceof A&&e._destroy()}));const i=this._servers.map((e=>t=>{e.destroy(t)}));this.discovery&&i.push((e=>{this.discovery.destroy(e)})),this.store&&i.push((e=>{t&&t.destroyStore?this.store.destroy(e):this.store.close(e)})),v(i,n),e&&(0===this.listenerCount("error")?this.client.emit("error",e):this.emit("error",e)),this.emit("close"),this.client=null,this.files=[],this.discovery=null,this.store=null,this._rarityMap=null,this._peers=null,this._servers=null,this._xsRequests=null}addPeer(e){if(this.destroyed)throw new Error("torrent is destroyed");if(!this.infoHash)throw new Error("addPeer() must not be called before the `infoHash` event");if(this.client.blocked){let t;if("string"==typeof e){let n;try{n=r(e)}catch(t){return this._debug("ignoring peer: invalid %s",e),this.emit("invalidPeer",e),!1}t=n[0]}else"string"==typeof e.remoteAddress&&(t=e.remoteAddress);if(t&&this.client.blocked.contains(t))return this._debug("ignoring peer: blocked %s",e),"string"!=typeof e&&e.destroy(),this.emit("blockedPeer",e),!1}const t=!!this._addPeer(e,this.client.utp?"utp":"tcp");return t?this.emit("peer",e):this.emit("invalidPeer",e),t}_addPeer(e,t){if(this.destroyed)return"string"!=typeof e&&e.destroy(),null;if("string"==typeof e&&!this._validAddr(e))return this._debug("ignoring peer: invalid %s",e),null;const n=e&&e.id||e;if(this._peers[n])return this._debug("ignoring peer: duplicate (%s)",n),"string"!=typeof e&&e.destroy(),null;if(this.paused)return this._debug("ignoring peer: torrent is paused"),"string"!=typeof e&&e.destroy(),null;let i;return this._debug("add peer %s",n),i="string"==typeof e?"utp"===t?L.createUTPOutgoingPeer(e,this):L.createTCPOutgoingPeer(e,this):L.createWebRTCPeer(e,this),this._peers[i.id]=i,this._peersLength+=1,"string"==typeof e&&(this._queue.push(i),this._drain()),i}addWebSeed(e){if(this.destroyed)throw new Error("torrent is destroyed");if(!/^https?:\/\/.+/.test(e))return this.emit("warning",new Error("ignoring invalid web seed: "+e)),void this.emit("invalidPeer",e);if(this._peers[e])return this.emit("warning",new Error("ignoring duplicate web seed: "+e)),void this.emit("invalidPeer",e);this._debug("add web seed %s",e);const t=L.createWebSeedPeer(e,this);this._peers[t.id]=t,this._peersLength+=1,this.emit("peer",e)}_addIncomingPeer(e){return this.destroyed?e.destroy(new Error("torrent is destroyed")):this.paused?e.destroy(new Error("torrent is paused")):(this._debug("add incoming peer %s",e.id),this._peers[e.id]=e,void(this._peersLength+=1))}removePeer(e){const t=e&&e.id||e;(e=this._peers[t])&&(this._debug("removePeer %s",t),delete this._peers[t],this._peersLength-=1,e.destroy(),this._drain())}select(e,t,n,i){if(this.destroyed)throw new Error("torrent is destroyed");if(e<0||tt.priority-e.priority)),this._updateSelections()}deselect(e,t,n){if(this.destroyed)throw new Error("torrent is destroyed");n=Number(n)||0,this._debug("deselect %s-%s (priority %s)",e,t,n);for(let i=0;i{this.destroyed||(this.received+=e,this._downloadSpeed(e),this.client._downloadSpeed(e),this.emit("download",e),this.destroyed||this.client.emit("download",e))})),e.on("upload",(e=>{this.destroyed||(this.uploaded+=e,this._uploadSpeed(e),this.client._uploadSpeed(e),this.emit("upload",e),this.destroyed||this.client.emit("upload",e))})),this.wires.push(e),t){const n=r(t);e.remoteAddress=n[0],e.remotePort=n[1]}this.client.dht&&this.client.dht.listening&&e.on("port",(n=>{if(!this.destroyed&&!this.client.dht.destroyed){if(!e.remoteAddress)return this._debug("ignoring PORT from peer with no address");if(0===n||n>65536)return this._debug("ignoring invalid PORT from peer");this._debug("port: %s (from %s)",n,t),this.client.dht.addNode({host:e.remoteAddress,port:n})}})),e.on("timeout",(()=>{this._debug("wire timeout (%s)",t),e.destroy()})),e.setTimeout(3e4,!0),e.setKeepAlive(!0),e.use(C(this.metadata)),e.ut_metadata.on("warning",(e=>{this._debug("ut_metadata warning: %s",e.message)})),this.metadata||(e.ut_metadata.on("metadata",(e=>{this._debug("got metadata via ut_metadata"),this._onMetadata(e)})),e.ut_metadata.fetch()),"function"!=typeof T||this.private||(e.use(T()),e.ut_pex.on("peer",(e=>{this.done||(this._debug("ut_pex: got peer: %s (from %s)",e,t),this.addPeer(e))})),e.ut_pex.on("dropped",(e=>{const n=this._peers[e];n&&!n.connected&&(this._debug("ut_pex: dropped peer: %s (from %s)",e,t),this.removePeer(e))})),e.once("close",(()=>{e.ut_pex.reset()}))),this.emit("wire",e,t),this.metadata&&n.nextTick((()=>{this._onWireWithMetadata(e)}))}_onWireWithMetadata(e){let t=null;const n=()=>{this.destroyed||e.destroyed||(this._numQueued>2*(this._numConns-this.numPeers)&&e.amInterested?e.destroy():(t=setTimeout(n,R),t.unref&&t.unref()))};let i;const r=()=>{if(e.peerPieces.buffer.length===this.bitfield.buffer.length){for(i=0;i{r(),this._update(),this._updateWireInterest(e)})),e.on("have",(()=>{r(),this._update(),this._updateWireInterest(e)})),e.once("interested",(()=>{e.unchoke()})),e.once("close",(()=>{clearTimeout(t)})),e.on("choke",(()=>{clearTimeout(t),t=setTimeout(n,R),t.unref&&t.unref()})),e.on("unchoke",(()=>{clearTimeout(t),this._update()})),e.on("request",((t,n,i,r)=>{if(i>131072)return e.destroy();this.pieces[t]||this.store.get(t,{offset:n,length:i},r)})),e.bitfield(this.bitfield),this._updateWireInterest(e),e.peerExtensions.dht&&this.client.dht&&this.client.dht.listening&&e.port(this.client.dht.address().port),"webSeed"!==e.type&&(t=setTimeout(n,R),t.unref&&t.unref()),e.isSeeder=!1,r()}_updateSelections(){this.ready&&!this.destroyed&&(n.nextTick((()=>{this._gcSelections()})),this._updateInterest(),this._update())}_gcSelections(){for(let e=0;ethis._updateWireInterest(e))),e!==this._amInterested&&(this._amInterested?this.emit("interested"):this.emit("uninterested"))}_updateWireInterest(e){let t=!1;for(let n=0;n=i.from+i.offset;--o)if(e.peerPieces.get(o)&&t._request(e,o,!1))return}}();const n=D(e,.5);if(e.requests.length>=n)return;const i=D(e,1);function r(t,n,i,r){return o=>o>=t&&o<=n&&!(o in i)&&e.peerPieces.get(o)&&(!r||r(o))}function o(e){let n=e;for(let i=e;i=i)return!0;const s=function(){const n=e.downloadSpeed()||1;if(n>B)return()=>!0;const i=Math.max(1,e.requests.length)*_.BLOCK_LENGTH/n;let r=10,o=0;return e=>{if(!r||t.bitfield.get(e))return!0;let s=t.pieces[e].missing;for(;o0))return r--,!1}return!0}}();for(let a=0;a({wire:e,random:Math.random()}))).sort(((e,t)=>{const n=e.wire,i=t.wire;return n.downloadSpeed()!==i.downloadSpeed()?n.downloadSpeed()-i.downloadSpeed():n.uploadSpeed()!==i.uploadSpeed()?n.uploadSpeed()-i.uploadSpeed():n.amChoking!==i.amChoking?n.amChoking?-1:1:e.random-t.random})).map((e=>e.wire));this._rechokeOptimisticTime<=0?this._rechokeOptimisticWire=null:this._rechokeOptimisticTime-=1;let t=0;for(;e.length>0&&t0){const t=e.filter((e=>e.peerInterested));if(t.length>0){const e=t[(n=t.length,Math.random()*n|0)];e.unchoke(),this._rechokeOptimisticWire=e,this._rechokeOptimisticTime=2}}var n;e.filter((e=>e!==this._rechokeOptimisticWire)).forEach((e=>e.choke()))}_hotswap(e,t){const n=e.downloadSpeed();if(n<_.BLOCK_LENGTH)return!1;if(!this._reservations[t])return!1;const i=this._reservations[t];if(!i)return!1;let r,o,s=1/0;for(o=0;o=B||(2*a>n||a>s||(r=t,s=a))}if(!r)return!1;for(o=0;o=(s?Math.min(function(e,t,n){return 1+Math.ceil(t*e.downloadSpeed()/n)}(e,1,r.pieceLength),r.maxWebConns):D(e,1)))return!1;const a=r.pieces[t];let c=s?a.reserveRemaining():a.reserve();if(-1===c&&i&&r._hotswap(e,t)&&(c=s?a.reserveRemaining():a.reserve()),-1===c)return!1;let l=r._reservations[t];l||(l=r._reservations[t]=[]);let p=l.indexOf(null);-1===p&&(p=l.length),l[p]=e;const u=a.chunkOffset(c),d=s?a.chunkLengthRemaining(c):a.chunkLength(c);function f(){n.nextTick((()=>{r._update()}))}return e.request(t,u,d,(function n(i,o){if(r.destroyed)return;if(!r.ready)return r.once("ready",(()=>{n(i,o)}));if(l[p]===e&&(l[p]=null),a!==r.pieces[t])return f();if(i)return r._debug("error getting piece %s (offset: %s length: %s) from %s: %s",t,u,d,`${e.remoteAddress}:${e.remotePort}`,i.message),s?a.cancelRemaining(c):a.cancel(c),void f();if(r._debug("got piece %s (offset: %s length: %s) from %s",t,u,d,`${e.remoteAddress}:${e.remotePort}`),!a.set(c,o,e))return f();const h=a.flush();E(h,(e=>{if(!r.destroyed){if(e===r._hashes[t]){if(!r.pieces[t])return;r._debug("piece verified %s",t),r.pieces[t]=null,r._reservations[t]=null,r.bitfield.set(t,!0),r.store.put(t,h),r.wires.forEach((e=>{e.have(t)})),r._checkDone()&&!r.destroyed&&r.discovery.complete()}else r.pieces[t]=new _(a.length),r.emit("warning",new Error(`Piece ${t} failed verification`));f()}}))})),!0}_checkDone(){if(this.destroyed)return;this.files.forEach((e=>{if(!e.done){for(let t=e._startPiece;t<=e._endPiece;++t)if(!this.bitfield.get(t))return;e.done=!0,e.emit("done"),this._debug("file done: "+e.name)}}));let e=!0;for(let t=0;t{this.load(e,t)}));Array.isArray(e)||(e=[e]),t||(t=q);const n=new h(e),i=new s(this.store,this.pieceLength);w(n,i,(e=>{if(e)return t(e);this._markAllVerified(),this._checkDone(),t(null)}))}createServer(e){if("function"!=typeof O)throw new Error("node.js-only method");if(this.destroyed)throw new Error("torrent is destroyed");const t=new O(this,e);return this._servers.push(t),t}pause(){this.destroyed||(this._debug("pause"),this.paused=!0)}resume(){this.destroyed||(this._debug("resume"),this.paused=!1,this._drain())}_debug(){const e=[].slice.call(arguments);e[0]=`[${this.client?this.client._debugId:"No Client"}] [${this._debugId}] ${e[0]}`,a(...e)}_drain(){if(this._debug("_drain numConns %s maxConns %s",this._numConns,this.client.maxConns),"function"!=typeof m.connect||this.destroyed||this.paused||this._numConns>=this.client.maxConns)return;this._debug("drain (%s queued, %s/%s peers)",this._numQueued,this.numPeers,this.client.maxConns);const e=this._queue.shift();if(!e)return;this._debug("%s connect attempt to %s",e.type,e.addr);const t=r(e.addr),n={host:t[0],port:t[1]};"utpOutgoing"===e.type?e.conn=j.connect(n.port,n.host):e.conn=m.connect(n);const i=e.conn;i.once("connect",(()=>{e.onConnect()})),i.once("error",(t=>{e.destroy(t)})),e.startConnectTimeout(),i.on("close",(()=>{if(this.destroyed)return;if(e.retries>=M.length){if(this.client.utp){const t=this._addPeer(e.addr,"tcp");t&&(t.retries=0)}else this._debug("conn %s closed: will not re-add (max %s attempts)",e.addr,M.length);return}const t=M[e.retries];this._debug("conn %s closed: will re-add to queue in %sms (attempt %s)",e.addr,t,e.retries+1);const n=setTimeout((()=>{if(this.destroyed)return;const t=this._addPeer(e.addr,this.client.utp?"utp":"tcp");t&&(t.retries=e.retries+1)}),t);n.unref&&n.unref()}))}_validAddr(e){let t;try{t=r(e)}catch(e){return!1}const n=t[0],i=t[1];return i>0&&i<65535&&!("127.0.0.1"===n&&i===this.client.torrentPort)}}}).call(this)}).call(this,e("_process"),"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"../package.json":334,"./file":311,"./peer":312,"./rarity-map":313,"./server":55,_process:187,"addr-to-ip-port":3,bitfield:10,"chunk-store-stream/write":78,debug:316,events:98,fs:56,"fs-chunk-store":141,"immediate-chunk-store":118,multistream:166,net:55,os:55,"parse-torrent":184,path:185,pump:188,"random-iterate":194,"run-parallel":218,"run-parallel-limit":217,"simple-get":222,"simple-sha1":242,speedometer:263,"torrent-discovery":291,"torrent-piece":295,ut_metadata:301,ut_pex:55,"utp-native":55}],315:[function(e,t,n){(function(n){(function(){const i=e("bitfield"),r=e("debug")("webtorrent:webconn"),o=e("simple-get"),s=e("simple-sha1"),a=e("bittorrent-protocol"),c=e("../package.json").version;t.exports=class extends a{constructor(e,t){super(),this.url=e,this.webPeerId=s.sync(e),this._torrent=t,this._init()}_init(){this.setKeepAlive(!0),this.once("handshake",((e,t)=>{if(this.destroyed)return;this.handshake(e,this.webPeerId);const n=this._torrent.pieces.length,r=new i(n);for(let e=0;e<=n;e++)r.set(e,!0);this.bitfield(r)})),this.once("interested",(()=>{r("interested"),this.unchoke()})),this.on("uninterested",(()=>{r("uninterested")})),this.on("choke",(()=>{r("choke")})),this.on("unchoke",(()=>{r("unchoke")})),this.on("bitfield",(()=>{r("bitfield")})),this.on("request",((e,t,n,i)=>{r("request pieceIndex=%d offset=%d length=%d",e,t,n),this.httpRequest(e,t,n,i)}))}httpRequest(e,t,i,s){const a=e*this._torrent.pieceLength+t,l=a+i-1,p=this._torrent.files;let u;if(p.length<=1)u=[{url:this.url,start:a,end:l}];else{const e=p.filter((e=>e.offset<=l&&e.offset+e.length>a));if(e.length<1)return s(new Error("Could not find file corresponnding to web seed range request"));u=e.map((e=>{const t=e.offset+e.length-1;return{url:this.url+("/"===this.url[this.url.length-1]?"":"/")+e.path,fileOffsetInRange:Math.max(e.offset-a,0),start:Math.max(a-e.offset,0),end:Math.min(t,l-e.offset)}}))}let d,f=0,h=!1;u.length>1&&(d=n.alloc(i)),u.forEach((n=>{const a=n.url,l=n.start,p=n.end;r("Requesting url=%s pieceIndex=%d offset=%d length=%d start=%d end=%d",a,e,t,i,l,p);const m={url:a,method:"GET",headers:{"user-agent":`WebTorrent/${c} (https://webtorrent.io)`,range:`bytes=${l}-${p}`}};function g(e,t){if(e.statusCode<200||e.statusCode>=300)return h=!0,s(new Error("Unexpected HTTP status code "+e.statusCode));r("Got data of length %d",t.length),1===u.length?s(null,t):(t.copy(d,n.fileOffsetInRange),++f===u.length&&s(null,d))}o.concat(m,((e,t,n)=>{if(!h)return e?"undefined"==typeof window||a.startsWith(window.location.origin+"/")?(h=!0,s(e)):o.head(a,((t,n)=>{if(!h){if(t)return h=!0,s(t);if(n.statusCode<200||n.statusCode>=300)return h=!0,s(new Error("Unexpected HTTP status code "+n.statusCode));if(n.url===a)return h=!0,s(e);m.url=n.url,o.concat(m,((e,t,n)=>{if(!h)return e?(h=!0,s(e)):void g(t,n)}))}})):void g(t,n)}))}))}destroy(){super.destroy(),this._torrent=null}}}).call(this)}).call(this,e("buffer").Buffer)},{"../package.json":334,bitfield:10,"bittorrent-protocol":11,buffer:60,debug:316,"simple-get":222,"simple-sha1":242}],316:[function(e,t,n){arguments[4][13][0].apply(n,arguments)},{"./common":317,_process:187,dup:13}],317:[function(e,t,n){arguments[4][14][0].apply(n,arguments)},{dup:14,ms:318}],318:[function(e,t,n){arguments[4][15][0].apply(n,arguments)},{dup:15}],319:[function(e,t,n){arguments[4][16][0].apply(n,arguments)},{dup:16}],320:[function(e,t,n){arguments[4][17][0].apply(n,arguments)},{"./_stream_readable":322,"./_stream_writable":324,_process:187,dup:17,inherits:119}],321:[function(e,t,n){arguments[4][18][0].apply(n,arguments)},{"./_stream_transform":323,dup:18,inherits:119}],322:[function(e,t,n){arguments[4][19][0].apply(n,arguments)},{"../errors":319,"./_stream_duplex":320,"./internal/streams/async_iterator":325,"./internal/streams/buffer_list":326,"./internal/streams/destroy":327,"./internal/streams/from":329,"./internal/streams/state":331,"./internal/streams/stream":332,_process:187,buffer:60,dup:19,events:98,inherits:119,"string_decoder/":286,util:55}],323:[function(e,t,n){arguments[4][20][0].apply(n,arguments)},{"../errors":319,"./_stream_duplex":320,dup:20,inherits:119}],324:[function(e,t,n){arguments[4][21][0].apply(n,arguments)},{"../errors":319,"./_stream_duplex":320,"./internal/streams/destroy":327,"./internal/streams/state":331,"./internal/streams/stream":332,_process:187,buffer:60,dup:21,inherits:119,"util-deprecate":306}],325:[function(e,t,n){arguments[4][22][0].apply(n,arguments)},{"./end-of-stream":328,_process:187,dup:22}],326:[function(e,t,n){arguments[4][23][0].apply(n,arguments)},{buffer:60,dup:23,util:55}],327:[function(e,t,n){arguments[4][24][0].apply(n,arguments)},{_process:187,dup:24}],328:[function(e,t,n){arguments[4][25][0].apply(n,arguments)},{"../../../errors":319,dup:25}],329:[function(e,t,n){arguments[4][26][0].apply(n,arguments)},{dup:26}],330:[function(e,t,n){arguments[4][27][0].apply(n,arguments)},{"../../../errors":319,"./end-of-stream":328,dup:27}],331:[function(e,t,n){arguments[4][28][0].apply(n,arguments)},{"../../../errors":319,dup:28}],332:[function(e,t,n){arguments[4][29][0].apply(n,arguments)},{dup:29,events:98}],333:[function(e,t,n){arguments[4][30][0].apply(n,arguments)},{"./lib/_stream_duplex.js":320,"./lib/_stream_passthrough.js":321,"./lib/_stream_readable.js":322,"./lib/_stream_transform.js":323,"./lib/_stream_writable.js":324,"./lib/internal/streams/end-of-stream.js":328,"./lib/internal/streams/pipeline.js":330,dup:30}],334:[function(e,t,n){t.exports={version:"0.110.1"}},{}],335:[function(e,t,n){t.exports=function e(t,n){if(t&&n)return e(t)(n);if("function"!=typeof t)throw new TypeError("need wrapper function");return Object.keys(t).forEach((function(e){i[e]=t[e]})),i;function i(){for(var e=new Array(arguments.length),n=0;n1080?(B.setProps({placement:"right"}),U.setProps({placement:"right"}),M.setProps({placement:"right"})):(B.setProps({placement:"top"}),U.setProps({placement:"top"}),M.setProps({placement:"top"}))}function q(e){$();try{console.info("Attempting parse"),u=r(e),F(),u.xs&&(console.info("Magnet includes xs, attempting remote parse"),H(u.xs))}catch(t){console.warn(t),"magnet"==p?(console.info("Attempting remote parse"),H(e)):(N.error("Problem parsing input. Is this a .torrent file?"),console.error("Problem parsing input"))}}function H(e){r.remote(e,(function(e,t){if(e)return N.error("Problem remotely fetching file or parsing result"),console.warn(e),void $();p="remote-torrent-file",f.innerHTML='',h.setContent("Currently loaded information sourced from remotely fetched Torrent file"),u=t,F()}))}function F(){if(console.log(u),y.value=u.infoHash,m.value=u.name?u.name:"",u.created?(v.value=u.created.toISOString().slice(0,19),v.type="datetime-local"):v.type="text",b.value=u.createdBy?"by "+u.createdBy:"",x.value=u.comment?u.comment:"",E.innerHTML="",u.announce&&u.announce.length)for(let e=0;e',i.addEventListener("click",K),t.appendChild(i),E.appendChild(t)}if(S.innerHTML="",u.urlList&&u.urlList.length)for(let e=0;e',i.addEventListener("click",K),t.appendChild(i),S.appendChild(t)}if(j.innerHTML="",u.files&&u.files.length){A.style.display="none";for(let e of u.files){let t=W(a.lookup(e.name));j.appendChild(z(t,e.name,e.length))}j.appendChild(z("folder-tree","",u.length)),M.setContent("Download Torrent file"),R.addEventListener("click",Q),R.disabled=!1}else P.torrents.length>0?(A.style.display="none",j.innerHTML=''):(A.style.display="block",j.innerHTML=''),M.setContent("Files metadata is required to generate Torrent file. Try fetching files list from WebTorrent."),R.removeEventListener("click",Q),R.disabled=!0;L.setAttribute("data-clipboard-text",window.location.origin+"#"+r.toMagnetURI(u)),I.setAttribute("data-clipboard-text",r.toMagnetURI(u)),d.style.display="flex",window.location.hash=r.toMagnetURI(u),u.name?document.title="Torrent Parts | "+u.name:document.title="Torrent Parts | Inspect and edit what's in your Torrent file or Magnet link",h.enable(),gtag("event","view_item",{items:[{item_id:u.infoHash,item_name:u.name,item_category:p}]})}function z(e,t,n){let i=document.createElement("tr"),r=document.createElement("td");r.innerHTML='',i.appendChild(r);let o=document.createElement("td");o.innerHTML=t,i.appendChild(o);let a=document.createElement("td");return a.innerHTML=s.format(n,{decimalPlaces:1,unitSeparator:" "}),i.appendChild(a),i}function W(e){if(!e)return"file";switch(!0){case e.includes("msword"):case e.includes("wordprocessingml"):case e.includes("opendocument.text"):case e.includes("abiword"):return"file-word";case e.includes("ms-excel"):case e.includes("spreadsheet"):return"file-powerpoint";case e.includes("powerpoint"):case e.includes("presentation"):return"file-powerpoint";case e.includes("7z-"):case e.includes("iso9660"):case e.includes("zip"):case e.includes("octet-stream"):return"file-archive";case e.includes("csv"):return"file-csv";case e.includes("pdf"):return"file-pdf";case e.includes("font"):return"file-contract";case e.includes("text"):case e.includes("subrip"):case e.includes("vtt"):return"file-alt";case e.includes("audio"):return"file-audio";case e.includes("image"):return"file-image";case e.includes("video"):return"file-video";default:return"file"}}function V(e){this.dataset.group?u[this.dataset.group][this.dataset.index]=this.value?this.value:"":u[this.id]=this.value?this.value:"",window.location.hash=r.toMagnetURI(u),J()}function $(){document.getElementById("magnet").value="",document.getElementById("torrent").value="",d.style.display="none",m.value="",v.value="",b.value="",x.value="",y.value="",E.innerHTML="",S.innerHTML="",P.torrents.forEach((e=>e.destroy())),A.style.display="block",j.innerHTML="",window.location.hash="",L.setAttribute("data-clipboard-text",""),I.setAttribute("data-clipboard-text",""),document.title="Torrent Parts | Inspect and edit what's in your Torrent file or Magnet link",h.disable(),gtag("event","reset")}async function G(){_.className="disabled",_.innerHTML="Adding...";try{let e=await fetch("https://newtrackon.com/api/100"),t=await e.text();u.announce=u.announce.concat(t.split("\n\n")),u.announce.push("http://bt1.archive.org:6969/announce"),u.announce.push("http://bt2.archive.org:6969/announce"),u.announce=u.announce.filter(((e,t)=>e&&u.announce.indexOf(e)===t)),N.success("Added known working trackers from newTrackon"),J()}catch(e){N.error("Problem fetching trackers from newTrackon"),console.warn(e)}_.className="",_.innerHTML="Add Known Working Trackers",F(),gtag("event","add_trackers")}function Y(){u[this.dataset.type].unshift(""),F()}function K(){u[this.parentElement.className].splice(this.parentElement.dataset.index,1),F()}function X(e){u[e]=[],J(),F()}function J(){u.created=new Date,u.createdBy="Torrent Parts ",u.created?(v.value=u.created.toISOString().slice(0,19),v.type="datetime-local"):v.type="text",b.value=u.createdBy?"by "+u.createdBy:""}function Z(){console.info("Attempting fetching files from Webtorrent..."),A.style.display="none",u.announce.push("wss://tracker.webtorrent.io"),u.announce.push("wss://tracker.openwebtorrent.com"),u.announce.push("wss://tracker.btorrent.xyz"),u.announce.push("wss://tracker.fastcast.nz"),u.announce=u.announce.filter(((e,t)=>e&&u.announce.indexOf(e)===t)),P.add(r.toMagnetURI(u),(e=>{u.info=Object.assign({},e.info),u.files=e.files,u.infoBuffer=e.infoBuffer,u.length=e.length,u.lastPieceLength=e.lastPieceLength,J(),F(),N.success("Fetched file details from Webtorrent peers"),e.destroy()})),F(),gtag("event","attempt_webtorrent_fetch")}function Q(){let e=r.toTorrentFile(u);if(null!==e&&navigator.msSaveBlob)return navigator.msSaveBlob(new Blob([e],{type:"application/x-bittorrent"}),u.name+".torrent");let t=document.createElement("a");t.style.display="none";let n=window.URL.createObjectURL(new Blob([e],{type:"application/x-bittorrent"}));t.setAttribute("href",n),t.setAttribute("download",u.name+".torrent"),document.body.appendChild(t),t.click(),window.URL.revokeObjectURL(n),t.remove(),gtag("event","share",{method:"Torrent Download",content_id:u.name})}window.addEventListener("resize",D),D(),document.addEventListener("DOMContentLoaded",(function(){document.getElementById("magnet").addEventListener("keyup",(function(e){e.preventDefault(),"Enter"===e.key&&(p="magnet",f.innerHTML='',h.setContent("Currently loaded information sourced from Magnet URL"),q(magnet.value))})),document.getElementById("torrent").addEventListener("change",(function(e){e.preventDefault(),e.target.files[0].arrayBuffer().then((function(e){p="torrent-file",f.innerHTML='',h.setContent("Currently loaded information sourced from Torrent file"),q(o.from(e))}))}));let e=new i("#copyURL");e.on("success",(function(e){N.success("Copied site URL to clipboard!"),console.info(e),gtag("event","share",{method:"Copy URL",content_id:e.text})})),e.on("failure",(function(e){N.error("Problem copying to clipboard"),console.warn(e)}));let t=new i("#copyMagnet");t.on("success",(function(e){N.success("Copied Magnet URL to clipboard!"),gtag("event","share",{method:"Copy Magnet",content_id:e.text})})),t.on("failure",(function(e){N.error("Problem copying to clipboard"),console.warn(e)})),m.addEventListener("input",V),m.addEventListener("change",V),m.addEventListener("reset",V),m.addEventListener("paste",V),g.addEventListener("click",$),x.addEventListener("input",V),x.addEventListener("change",V),x.addEventListener("reset",V),x.addEventListener("paste",V),_.addEventListener("click",G),w.addEventListener("click",Y),k.addEventListener("click",(()=>X("announce"))),C.addEventListener("click",Y),T.addEventListener("click",(()=>X("urlList"))),A.addEventListener("click",Z),l("[data-tippy-content]",{theme:"torrent-parts",animation:"shift-away-subtle"}),h.disable(),window.location.hash&&(p="shared-url",f.innerHTML='',h.setContent("Currently loaded information sourced from shared torrent.parts link"),q(window.location.hash.split("#")[1]))}))},{Buffer:2,bytes:62,clipboard:79,"mime-types":144,"parse-torrent":184,"tippy.js":289,webtorrent:309}]},{},[337]); \ No newline at end of file +const{EventEmitter:o}=e("events"),s=e("simple-concat"),a=e("create-torrent"),c=e("debug")("webtorrent"),l=e("bittorrent-dht/client"),p=e("load-ip-set"),u=e("run-parallel"),d=e("parse-torrent"),f=e("path"),h=e("simple-peer"),m=e("randombytes"),g=e("speedometer"),v=e("./lib/conn-pool"),b=e("./lib/torrent"),x=e("./package.json").version,y=x.replace(/\d*./g,(e=>("0"+e%100).slice(-2))).slice(0,4),_=`-WW${y}-`;class w extends o{constructor(e={}){super(),"string"==typeof e.peerId?this.peerId=e.peerId:r.isBuffer(e.peerId)?this.peerId=e.peerId.toString("hex"):this.peerId=r.from(_+m(9).toString("base64")).toString("hex"),this.peerIdBuffer=r.from(this.peerId,"hex"),"string"==typeof e.nodeId?this.nodeId=e.nodeId:r.isBuffer(e.nodeId)?this.nodeId=e.nodeId.toString("hex"):this.nodeId=m(20).toString("hex"),this.nodeIdBuffer=r.from(this.nodeId,"hex"),this._debugId=this.peerId.toString("hex").substring(0,7),this.destroyed=!1,this.listening=!1,this.torrentPort=e.torrentPort||0,this.dhtPort=e.dhtPort||0,this.tracker=void 0!==e.tracker?e.tracker:{},this.torrents=[],this.maxConns=Number(e.maxConns)||55,this.utp=!0===e.utp,this._debug("new webtorrent (peerId %s, nodeId %s, port %s)",this.peerId,this.nodeId,this.torrentPort),this.tracker&&("object"!=typeof this.tracker&&(this.tracker={}),e.rtcConfig&&(console.warn("WebTorrent: opts.rtcConfig is deprecated. Use opts.tracker.rtcConfig instead"),this.tracker.rtcConfig=e.rtcConfig),e.wrtc&&(console.warn("WebTorrent: opts.wrtc is deprecated. Use opts.tracker.wrtc instead"),this.tracker.wrtc=e.wrtc),i.WRTC&&!this.tracker.wrtc&&(this.tracker.wrtc=i.WRTC)),"function"==typeof v?this._connPool=new v(this):n.nextTick((()=>{this._onListening()})),this._downloadSpeed=g(),this._uploadSpeed=g(),!1!==e.dht&&"function"==typeof l?(this.dht=new l(Object.assign({},{nodeId:this.nodeId},e.dht)),this.dht.once("error",(e=>{this._destroy(e)})),this.dht.once("listening",(()=>{const e=this.dht.address();e&&(this.dhtPort=e.port)})),this.dht.setMaxListeners(0),this.dht.listen(this.dhtPort)):this.dht=!1,this.enableWebSeeds=!1!==e.webSeeds;const t=()=>{this.destroyed||(this.ready=!0,this.emit("ready"))};"function"==typeof p&&null!=e.blocklist?p(e.blocklist,{headers:{"user-agent":`WebTorrent/${x} (https://webtorrent.io)`}},((e,n)=>{if(e)return this.error("Failed to load blocklist: "+e.message);this.blocked=n,t()})):n.nextTick(t)}get downloadSpeed(){return this._downloadSpeed()}get uploadSpeed(){return this._uploadSpeed()}get progress(){const e=this.torrents.filter((e=>1!==e.progress));return e.reduce(((e,t)=>e+t.downloaded),0)/(e.reduce(((e,t)=>e+(t.length||0)),0)||1)}get ratio(){return this.torrents.reduce(((e,t)=>e+t.uploaded),0)/(this.torrents.reduce(((e,t)=>e+t.received),0)||1)}get(e){if(e instanceof b){if(this.torrents.includes(e))return e}else{let t;try{t=d(e)}catch(e){}if(!t)return null;if(!t.infoHash)throw new Error("Invalid torrent identifier");for(const e of this.torrents)if(e.infoHash===t.infoHash)return e}return null}download(e,t,n){return console.warn("WebTorrent: client.download() is deprecated. Use client.add() instead"),this.add(e,t,n)}add(e,t={},n=(()=>{})){if(this.destroyed)throw new Error("client is destroyed");"function"==typeof t&&([t,n]=[{},t]);const i=()=>{if(!this.destroyed)for(const e of this.torrents)if(e.infoHash===o.infoHash&&e!==o)return void o._destroy(new Error("Cannot add duplicate torrent "+o.infoHash))},r=()=>{this.destroyed||(n(o),this.emit("torrent",o))};this._debug("add"),t=t?Object.assign({},t):{};const o=new b(e,this,t);return this.torrents.push(o),o.once("_infoHash",i),o.once("ready",r),o.once("close",(function e(){o.removeListener("_infoHash",i),o.removeListener("ready",r),o.removeListener("close",e)})),o}seed(e,t,n){if(this.destroyed)throw new Error("client is destroyed");"function"==typeof t&&([t,n]=[{},t]),this._debug("seed"),(t=t?Object.assign({},t):{}).skipVerify=!0;const i="string"==typeof e;i&&(t.path=f.dirname(e)),t.createdBy||(t.createdBy="WebTorrent/"+y);const r=e=>{this._debug("on seed"),"function"==typeof n&&n(e),e.emit("seed"),this.emit("seed",e)},o=this.add(null,t,(e=>{const t=[t=>{if(i)return t();e.load(c,t)}];this.dht&&t.push((t=>{e.once("dhtAnnounce",t)})),u(t,(t=>{if(!this.destroyed)return t?e._destroy(t):void r(e)}))}));let c;var l;return l=e,"undefined"!=typeof FileList&&l instanceof FileList?e=Array.from(e):Array.isArray(e)||(e=[e]),u(e.map((e=>t=>{!function(e){return"object"==typeof e&&null!=e&&"function"==typeof e.pipe}(e)?t(null,e):s(e,t)})),((e,n)=>{if(!this.destroyed)return e?o._destroy(e):void a.parseInput(n,t,((e,i)=>{if(!this.destroyed){if(e)return o._destroy(e);c=i.map((e=>e.getStream)),a(n,t,((e,t)=>{if(this.destroyed)return;if(e)return o._destroy(e);const n=this.get(t);n?o._destroy(new Error("Cannot add duplicate torrent "+n.infoHash)):o._onTorrentId(t)}))}}))})),o}remove(e,t,n){if("function"==typeof t)return this.remove(e,null,t);this._debug("remove");if(!this.get(e))throw new Error("No torrent with id "+e);this._remove(e,t,n)}_remove(e,t,n){if("function"==typeof t)return this._remove(e,null,t);const i=this.get(e);i&&(this.torrents.splice(this.torrents.indexOf(i),1),i.destroy(t,n))}address(){return this.listening?this._connPool?this._connPool.tcpServer.address():{address:"0.0.0.0",family:"IPv4",port:0}:null}destroy(e){if(this.destroyed)throw new Error("client already destroyed");this._destroy(null,e)}_destroy(e,t){this._debug("client destroy"),this.destroyed=!0;const n=this.torrents.map((e=>t=>{e.destroy(t)}));this._connPool&&n.push((e=>{this._connPool.destroy(e)})),this.dht&&n.push((e=>{this.dht.destroy(e)})),u(n,t),e&&this.emit("error",e),this.torrents=[],this._connPool=null,this.dht=null}_onListening(){if(this._debug("listening"),this.listening=!0,this._connPool){const e=this._connPool.tcpServer.address();e&&(this.torrentPort=e.port)}this.emit("listening")}_debug(){const e=[].slice.call(arguments);e[0]=`[${this._debugId}] ${e[0]}`,c(...e)}}w.WEBRTC_SUPPORT=h.WEBRTC_SUPPORT,w.VERSION=x,t.exports=w}).call(this)}).call(this,e("_process"),"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{},e("buffer").Buffer)},{"./lib/conn-pool":55,"./lib/torrent":314,"./package.json":334,_process:187,"bittorrent-dht/client":55,buffer:60,"create-torrent":80,debug:316,events:98,"load-ip-set":55,"parse-torrent":184,path:185,randombytes:195,"run-parallel":218,"simple-concat":221,"simple-peer":223,speedometer:263}],310:[function(e,t,n){const i=e("debug")("webtorrent:file-stream"),r=e("readable-stream");class o extends r.Readable{constructor(e,t){super(t),this.destroyed=!1,this._torrent=e._torrent;const n=t&&t.start||0,i=t&&t.end&&t.end{if(this._notifying=!1,!this.destroyed){if(i("read %s (length %s) (err %s)",e,n.length,t&&t.message),t)return this._destroy(t);this._offset&&(n=n.slice(this._offset),this._offset=0),this._missing{e.end()})),e}const t=new u(this,e);return this._torrent.select(t._startPiece,t._endPiece,!0,(()=>{t._notify()})),o(t,(()=>{this._destroyed||this._torrent.destroyed||this._torrent.deselect(t._startPiece,t._endPiece,!0)})),t}getBuffer(e){p(this.createReadStream(),this.length,e)}getBlob(e){if("undefined"==typeof window)throw new Error("browser-only method");c(this.createReadStream(),this._getMimeType()).then((t=>e(null,t)),(t=>e(t)))}getBlobURL(e){if("undefined"==typeof window)throw new Error("browser-only method");l(this.createReadStream(),this._getMimeType()).then((t=>e(null,t)),(t=>e(t)))}appendTo(e,t,n){if("undefined"==typeof window)throw new Error("browser-only method");a.append(this,e,t,n)}renderTo(e,t,n){if("undefined"==typeof window)throw new Error("browser-only method");a.render(this,e,t,n)}_getMimeType(){return a.mime[s.extname(this.name).toLowerCase()]}_destroy(){this._destroyed=!0,this._torrent=null}}}).call(this)}).call(this,e("_process"))},{"./file-stream":310,_process:187,"end-of-stream":96,events:98,path:185,"readable-stream":333,"render-media":212,"stream-to-blob":284,"stream-to-blob-url":283,"stream-with-known-length-to-buffer":285}],312:[function(e,t,n){const i=e("unordered-array-remove"),r=e("debug")("webtorrent:peer"),o=e("bittorrent-protocol"),s=e("./webconn");n.createWebRTCPeer=(e,t)=>{const n=new l(e.id,"webrtc");return n.conn=e,n.swarm=t,n.conn.connected?n.onConnect():(n.conn.once("connect",(()=>{n.onConnect()})),n.conn.once("error",(e=>{n.destroy(e)})),n.startConnectTimeout()),n},n.createTCPIncomingPeer=e=>a(e,"tcpIncoming"),n.createUTPIncomingPeer=e=>a(e,"utpIncoming"),n.createTCPOutgoingPeer=(e,t)=>c(e,t,"tcpOutgoing"),n.createUTPOutgoingPeer=(e,t)=>c(e,t,"utpOutgoing");const a=(e,t)=>{const n=`${e.remoteAddress}:${e.remotePort}`,i=new l(n,t);return i.conn=e,i.addr=n,i.onConnect(),i},c=(e,t,n)=>{const i=new l(e,n);return i.addr=e,i.swarm=t,i};n.createWebSeedPeer=(e,t)=>{const n=new l(e,"webSeed");return n.swarm=t,n.conn=new s(e,t),n.onConnect(),n};class l{constructor(e,t){this.id=e,this.type=t,r("new %s Peer %s",t,e),this.addr=null,this.conn=null,this.swarm=null,this.wire=null,this.connected=!1,this.destroyed=!1,this.timeout=null,this.retries=0,this.sentHandshake=!1}onConnect(){if(this.destroyed)return;this.connected=!0,r("Peer %s connected",this.id),clearTimeout(this.connectTimeout);const e=this.conn;e.once("end",(()=>{this.destroy()})),e.once("close",(()=>{this.destroy()})),e.once("finish",(()=>{this.destroy()})),e.once("error",(e=>{this.destroy(e)}));const t=this.wire=new o;t.type=this.type,t.once("end",(()=>{this.destroy()})),t.once("close",(()=>{this.destroy()})),t.once("finish",(()=>{this.destroy()})),t.once("error",(e=>{this.destroy(e)})),t.once("handshake",((e,t)=>{this.onHandshake(e,t)})),this.startHandshakeTimeout(),e.pipe(t).pipe(e),this.swarm&&!this.sentHandshake&&this.handshake()}onHandshake(e,t){if(!this.swarm)return;if(this.destroyed)return;if(this.swarm.destroyed)return this.destroy(new Error("swarm already destroyed"));if(e!==this.swarm.infoHash)return this.destroy(new Error("unexpected handshake info hash for this swarm"));if(t===this.swarm.peerId)return this.destroy(new Error("refusing to connect to ourselves"));r("Peer %s got handshake %s",this.id,e),clearTimeout(this.handshakeTimeout),this.retries=0;let n=this.addr;!n&&this.conn.remoteAddress&&this.conn.remotePort&&(n=`${this.conn.remoteAddress}:${this.conn.remotePort}`),this.swarm._onWire(this.wire,n),this.swarm&&!this.swarm.destroyed&&(this.sentHandshake||this.handshake())}handshake(){const e={dht:!this.swarm.private&&!!this.swarm.client.dht};this.wire.handshake(this.swarm.infoHash,this.swarm.client.peerId,e),this.sentHandshake=!0}startConnectTimeout(){clearTimeout(this.connectTimeout);const e={webrtc:25e3,tcpOutgoing:5e3,utpOutgoing:5e3};this.connectTimeout=setTimeout((()=>{this.destroy(new Error("connect timeout"))}),e[this.type]),this.connectTimeout.unref&&this.connectTimeout.unref()}startHandshakeTimeout(){clearTimeout(this.handshakeTimeout),this.handshakeTimeout=setTimeout((()=>{this.destroy(new Error("handshake timeout"))}),25e3),this.handshakeTimeout.unref&&this.handshakeTimeout.unref()}destroy(e){if(this.destroyed)return;this.destroyed=!0,this.connected=!1,r("destroy %s %s (error: %s)",this.type,this.id,e&&(e.message||e)),clearTimeout(this.connectTimeout),clearTimeout(this.handshakeTimeout);const t=this.swarm,n=this.conn,o=this.wire;this.swarm=null,this.conn=null,this.wire=null,t&&o&&i(t.wires,t.wires.indexOf(o)),n&&(n.on("error",(()=>{})),n.destroy()),o&&o.destroy(),t&&t.removePeer(this.id)}}},{"./webconn":315,"bittorrent-protocol":11,debug:316,"unordered-array-remove":298}],313:[function(e,t,n){t.exports=class{constructor(e){this._torrent=e,this._numPieces=e.pieces.length,this._pieces=new Array(this._numPieces),this._onWire=e=>{this.recalculate(),this._initWire(e)},this._onWireHave=e=>{this._pieces[e]+=1},this._onWireBitfield=()=>{this.recalculate()},this._torrent.wires.forEach((e=>{this._initWire(e)})),this._torrent.on("wire",this._onWire),this.recalculate()}getRarestPiece(e){let t=[],n=1/0;for(let i=0;i{this._cleanupWireEvents(e)})),this._torrent=null,this._pieces=null,this._onWire=null,this._onWireHave=null,this._onWireBitfield=null}_initWire(e){e._onClose=()=>{this._cleanupWireEvents(e);for(let t=0;t{this.destroyed||this._onParsedTorrent(t)}))):x.remote(e,((e,t)=>{if(!this.destroyed)return e?this._destroy(e):void this._onParsedTorrent(t)}))}_onParsedTorrent(e){if(!this.destroyed){if(this._processParsedTorrent(e),!this.infoHash)return this._destroy(new Error("Malformed torrent data: No info hash"));this.path||(this.path=y.join(N,this.infoHash)),this._rechokeIntervalId=setInterval((()=>{this._rechoke()}),1e4),this._rechokeIntervalId.unref&&this._rechokeIntervalId.unref(),this.emit("_infoHash",this.infoHash),this.destroyed||(this.emit("infoHash",this.infoHash),this.destroyed||(this.client.listening?this._onListening():this.client.once("listening",(()=>{this._onListening()}))))}}_processParsedTorrent(e){this._debugId=e.infoHash.toString("hex").substring(0,7),void 0!==this.private&&(e.private=this.private),this.announce&&(e.announce=e.announce.concat(this.announce)),this.client.tracker&&i.WEBTORRENT_ANNOUNCE&&!e.private&&(e.announce=e.announce.concat(i.WEBTORRENT_ANNOUNCE)),this.urlList&&(e.urlList=e.urlList.concat(this.urlList)),e.announce=Array.from(new Set(e.announce)),e.urlList=Array.from(new Set(e.urlList)),Object.assign(this,e),this.magnetURI=x.toMagnetURI(e),this.torrentFile=x.toTorrentFile(e)}_onListening(){this.destroyed||(this.info?this._onMetadata(this):(this.xs&&this._getMetadataFromServer(),this._startDiscovery()))}_startDiscovery(){if(this.discovery||this.destroyed)return;let e=this.client.tracker;e&&(e=Object.assign({},this.client.tracker,{getAnnounceOpts:()=>{const e={uploaded:this.uploaded,downloaded:this.downloaded,left:Math.max(this.length-this.downloaded,0)};return this.client.tracker.getAnnounceOpts&&Object.assign(e,this.client.tracker.getAnnounceOpts()),this._getAnnounceOpts&&Object.assign(e,this._getAnnounceOpts()),e}})),this.peerAddresses&&this.peerAddresses.forEach((e=>this.addPeer(e))),this.discovery=new c({infoHash:this.infoHash,announce:this.announce,peerId:this.client.peerId,dht:!this.private&&this.client.dht,tracker:e,port:this.client.torrentPort,userAgent:P}),this.discovery.on("error",(e=>{this._destroy(e)})),this.discovery.on("peer",(e=>{"string"==typeof e&&this.done||this.addPeer(e)})),this.discovery.on("trackerAnnounce",(()=>{this.emit("trackerAnnounce"),0===this.numPeers&&this.emit("noPeers","tracker")})),this.discovery.on("dhtAnnounce",(()=>{this.emit("dhtAnnounce"),0===this.numPeers&&this.emit("noPeers","dht")})),this.discovery.on("warning",(e=>{this.emit("warning",e)}))}_getMetadataFromServer(){const e=this,t=(Array.isArray(this.xs)?this.xs:[this.xs]).map((t=>n=>{!function(t,n){if(0!==t.indexOf("http://")&&0!==t.indexOf("https://"))return e.emit("warning",new Error("skipping non-http xs param: "+t)),n(null);const i={url:t,method:"GET",headers:{"user-agent":P}};let r;try{r=d.concat(i,o)}catch(i){return e.emit("warning",new Error("skipping invalid url xs param: "+t)),n(null)}function o(i,r,o){if(e.destroyed)return n(null);if(e.metadata)return n(null);if(i)return e.emit("warning",new Error("http error from xs param: "+t)),n(null);if(200!==r.statusCode)return e.emit("warning",new Error(`non-200 status code ${r.statusCode} from xs param: ${t}`)),n(null);let s;try{s=x(o)}catch(i){}return s?s.infoHash!==e.infoHash?(e.emit("warning",new Error("got torrent file with incorrect info hash from xs param: "+t)),n(null)):(e._onMetadata(s),void n(null)):(e.emit("warning",new Error("got invalid torrent file from xs param: "+t)),n(null))}e._xsRequests.push(r)}(t,n)}));v(t)}_onMetadata(e){if(this.metadata||this.destroyed)return;let t;if(this._debug("got metadata"),this._xsRequests.forEach((e=>{e.abort()})),this._xsRequests=[],e&&e.infoHash)t=e;else try{t=x(e)}catch(e){return this._destroy(e)}if(this._processParsedTorrent(t),this.metadata=this.torrentFile,this.client.enableWebSeeds&&this.urlList.forEach((e=>{this.addWebSeed(e)})),this._rarityMap=new I(this),this.store=new f(new this._store(this.pieceLength,{torrent:{infoHash:this.infoHash},files:this.files.map((e=>({path:y.join(this.path,e.path),length:e.length,offset:e.offset}))),length:this.length,name:this.infoHash})),this.files=this.files.map((e=>new A(this,e))),this.so?this.files.forEach(((e,t)=>{this.so.includes(t)?this.files[t].select():this.files[t].deselect()})):0!==this.pieces.length&&this.select(0,this.pieces.length-1,!1),this._hashes=this.pieces,this.pieces=this.pieces.map(((e,t)=>{const n=t===this.pieces.length-1?this.lastPieceLength:this.pieceLength;return new _(n)})),this._reservations=this.pieces.map((()=>[])),this.bitfield=new o(this.pieces.length),this.wires.forEach((e=>{e.ut_metadata&&e.ut_metadata.setMetadata(this.metadata),this._onWireWithMetadata(e)})),this.emit("metadata"),!this.destroyed)if(this.skipVerify)this._markAllVerified(),this._onStore();else{const e=e=>{if(e)return this._destroy(e);this._debug("done verifying"),this._onStore()};this._debug("verifying existing torrent data"),this._fileModtimes&&this._store===u?this.getFileModtimes(((t,n)=>{if(t)return this._destroy(t);this.files.map(((e,t)=>n[t]===this._fileModtimes[t])).every((e=>e))?(this._markAllVerified(),this._onStore()):this._verifyPieces(e)})):this._verifyPieces(e)}}getFileModtimes(e){const t=[];b(this.files.map(((e,n)=>i=>{p.stat(y.join(this.path,e.path),((e,r)=>{if(e&&"ENOENT"!==e.code)return i(e);t[n]=r&&r.mtime.getTime(),i(null)}))})),U,(n=>{this._debug("done getting file modtimes"),e(n,t)}))}_verifyPieces(e){b(this.pieces.map(((e,t)=>e=>{if(this.destroyed)return e(new Error("torrent is destroyed"));this.store.get(t,((i,r)=>this.destroyed?e(new Error("torrent is destroyed")):i?n.nextTick(e,null):void E(r,(n=>{if(this.destroyed)return e(new Error("torrent is destroyed"));if(n===this._hashes[t]){if(!this.pieces[t])return e(null);this._debug("piece verified %s",t),this._markVerified(t)}else this._debug("piece invalid %s",t);e(null)}))))})),U,e)}rescanFiles(e){if(this.destroyed)throw new Error("torrent is destroyed");e||(e=q),this._verifyPieces((t=>{if(t)return this._destroy(t),e(t);this._checkDone(),e(null)}))}_markAllVerified(){for(let e=0;e{e.abort()})),this._rarityMap&&this._rarityMap.destroy();for(const e in this._peers)this.removePeer(e);this.files.forEach((e=>{e instanceof A&&e._destroy()}));const i=this._servers.map((e=>t=>{e.destroy(t)}));this.discovery&&i.push((e=>{this.discovery.destroy(e)})),this.store&&i.push((e=>{t&&t.destroyStore?this.store.destroy(e):this.store.close(e)})),v(i,n),e&&(0===this.listenerCount("error")?this.client.emit("error",e):this.emit("error",e)),this.emit("close"),this.client=null,this.files=[],this.discovery=null,this.store=null,this._rarityMap=null,this._peers=null,this._servers=null,this._xsRequests=null}addPeer(e){if(this.destroyed)throw new Error("torrent is destroyed");if(!this.infoHash)throw new Error("addPeer() must not be called before the `infoHash` event");if(this.client.blocked){let t;if("string"==typeof e){let n;try{n=r(e)}catch(t){return this._debug("ignoring peer: invalid %s",e),this.emit("invalidPeer",e),!1}t=n[0]}else"string"==typeof e.remoteAddress&&(t=e.remoteAddress);if(t&&this.client.blocked.contains(t))return this._debug("ignoring peer: blocked %s",e),"string"!=typeof e&&e.destroy(),this.emit("blockedPeer",e),!1}const t=!!this._addPeer(e,this.client.utp?"utp":"tcp");return t?this.emit("peer",e):this.emit("invalidPeer",e),t}_addPeer(e,t){if(this.destroyed)return"string"!=typeof e&&e.destroy(),null;if("string"==typeof e&&!this._validAddr(e))return this._debug("ignoring peer: invalid %s",e),null;const n=e&&e.id||e;if(this._peers[n])return this._debug("ignoring peer: duplicate (%s)",n),"string"!=typeof e&&e.destroy(),null;if(this.paused)return this._debug("ignoring peer: torrent is paused"),"string"!=typeof e&&e.destroy(),null;let i;return this._debug("add peer %s",n),i="string"==typeof e?"utp"===t?L.createUTPOutgoingPeer(e,this):L.createTCPOutgoingPeer(e,this):L.createWebRTCPeer(e,this),this._peers[i.id]=i,this._peersLength+=1,"string"==typeof e&&(this._queue.push(i),this._drain()),i}addWebSeed(e){if(this.destroyed)throw new Error("torrent is destroyed");if(!/^https?:\/\/.+/.test(e))return this.emit("warning",new Error("ignoring invalid web seed: "+e)),void this.emit("invalidPeer",e);if(this._peers[e])return this.emit("warning",new Error("ignoring duplicate web seed: "+e)),void this.emit("invalidPeer",e);this._debug("add web seed %s",e);const t=L.createWebSeedPeer(e,this);this._peers[t.id]=t,this._peersLength+=1,this.emit("peer",e)}_addIncomingPeer(e){return this.destroyed?e.destroy(new Error("torrent is destroyed")):this.paused?e.destroy(new Error("torrent is paused")):(this._debug("add incoming peer %s",e.id),this._peers[e.id]=e,void(this._peersLength+=1))}removePeer(e){const t=e&&e.id||e;(e=this._peers[t])&&(this._debug("removePeer %s",t),delete this._peers[t],this._peersLength-=1,e.destroy(),this._drain())}select(e,t,n,i){if(this.destroyed)throw new Error("torrent is destroyed");if(e<0||tt.priority-e.priority)),this._updateSelections()}deselect(e,t,n){if(this.destroyed)throw new Error("torrent is destroyed");n=Number(n)||0,this._debug("deselect %s-%s (priority %s)",e,t,n);for(let i=0;i{this.destroyed||(this.received+=e,this._downloadSpeed(e),this.client._downloadSpeed(e),this.emit("download",e),this.destroyed||this.client.emit("download",e))})),e.on("upload",(e=>{this.destroyed||(this.uploaded+=e,this._uploadSpeed(e),this.client._uploadSpeed(e),this.emit("upload",e),this.destroyed||this.client.emit("upload",e))})),this.wires.push(e),t){const n=r(t);e.remoteAddress=n[0],e.remotePort=n[1]}this.client.dht&&this.client.dht.listening&&e.on("port",(n=>{if(!this.destroyed&&!this.client.dht.destroyed){if(!e.remoteAddress)return this._debug("ignoring PORT from peer with no address");if(0===n||n>65536)return this._debug("ignoring invalid PORT from peer");this._debug("port: %s (from %s)",n,t),this.client.dht.addNode({host:e.remoteAddress,port:n})}})),e.on("timeout",(()=>{this._debug("wire timeout (%s)",t),e.destroy()})),e.setTimeout(3e4,!0),e.setKeepAlive(!0),e.use(C(this.metadata)),e.ut_metadata.on("warning",(e=>{this._debug("ut_metadata warning: %s",e.message)})),this.metadata||(e.ut_metadata.on("metadata",(e=>{this._debug("got metadata via ut_metadata"),this._onMetadata(e)})),e.ut_metadata.fetch()),"function"!=typeof T||this.private||(e.use(T()),e.ut_pex.on("peer",(e=>{this.done||(this._debug("ut_pex: got peer: %s (from %s)",e,t),this.addPeer(e))})),e.ut_pex.on("dropped",(e=>{const n=this._peers[e];n&&!n.connected&&(this._debug("ut_pex: dropped peer: %s (from %s)",e,t),this.removePeer(e))})),e.once("close",(()=>{e.ut_pex.reset()}))),this.emit("wire",e,t),this.metadata&&n.nextTick((()=>{this._onWireWithMetadata(e)}))}_onWireWithMetadata(e){let t=null;const n=()=>{this.destroyed||e.destroyed||(this._numQueued>2*(this._numConns-this.numPeers)&&e.amInterested?e.destroy():(t=setTimeout(n,R),t.unref&&t.unref()))};let i;const r=()=>{if(e.peerPieces.buffer.length===this.bitfield.buffer.length){for(i=0;i{r(),this._update(),this._updateWireInterest(e)})),e.on("have",(()=>{r(),this._update(),this._updateWireInterest(e)})),e.once("interested",(()=>{e.unchoke()})),e.once("close",(()=>{clearTimeout(t)})),e.on("choke",(()=>{clearTimeout(t),t=setTimeout(n,R),t.unref&&t.unref()})),e.on("unchoke",(()=>{clearTimeout(t),this._update()})),e.on("request",((t,n,i,r)=>{if(i>131072)return e.destroy();this.pieces[t]||this.store.get(t,{offset:n,length:i},r)})),e.bitfield(this.bitfield),this._updateWireInterest(e),e.peerExtensions.dht&&this.client.dht&&this.client.dht.listening&&e.port(this.client.dht.address().port),"webSeed"!==e.type&&(t=setTimeout(n,R),t.unref&&t.unref()),e.isSeeder=!1,r()}_updateSelections(){this.ready&&!this.destroyed&&(n.nextTick((()=>{this._gcSelections()})),this._updateInterest(),this._update())}_gcSelections(){for(let e=0;ethis._updateWireInterest(e))),e!==this._amInterested&&(this._amInterested?this.emit("interested"):this.emit("uninterested"))}_updateWireInterest(e){let t=!1;for(let n=0;n=i.from+i.offset;--o)if(e.peerPieces.get(o)&&t._request(e,o,!1))return}}();const n=D(e,.5);if(e.requests.length>=n)return;const i=D(e,1);function r(t,n,i,r){return o=>o>=t&&o<=n&&!(o in i)&&e.peerPieces.get(o)&&(!r||r(o))}function o(e){let n=e;for(let i=e;i=i)return!0;const s=function(){const n=e.downloadSpeed()||1;if(n>B)return()=>!0;const i=Math.max(1,e.requests.length)*_.BLOCK_LENGTH/n;let r=10,o=0;return e=>{if(!r||t.bitfield.get(e))return!0;let s=t.pieces[e].missing;for(;o0))return r--,!1}return!0}}();for(let a=0;a({wire:e,random:Math.random()}))).sort(((e,t)=>{const n=e.wire,i=t.wire;return n.downloadSpeed()!==i.downloadSpeed()?n.downloadSpeed()-i.downloadSpeed():n.uploadSpeed()!==i.uploadSpeed()?n.uploadSpeed()-i.uploadSpeed():n.amChoking!==i.amChoking?n.amChoking?-1:1:e.random-t.random})).map((e=>e.wire));this._rechokeOptimisticTime<=0?this._rechokeOptimisticWire=null:this._rechokeOptimisticTime-=1;let t=0;for(;e.length>0&&t0){const t=e.filter((e=>e.peerInterested));if(t.length>0){const e=t[(n=t.length,Math.random()*n|0)];e.unchoke(),this._rechokeOptimisticWire=e,this._rechokeOptimisticTime=2}}var n;e.filter((e=>e!==this._rechokeOptimisticWire)).forEach((e=>e.choke()))}_hotswap(e,t){const n=e.downloadSpeed();if(n<_.BLOCK_LENGTH)return!1;if(!this._reservations[t])return!1;const i=this._reservations[t];if(!i)return!1;let r,o,s=1/0;for(o=0;o=B||(2*a>n||a>s||(r=t,s=a))}if(!r)return!1;for(o=0;o=(s?Math.min(function(e,t,n){return 1+Math.ceil(t*e.downloadSpeed()/n)}(e,1,r.pieceLength),r.maxWebConns):D(e,1)))return!1;const a=r.pieces[t];let c=s?a.reserveRemaining():a.reserve();if(-1===c&&i&&r._hotswap(e,t)&&(c=s?a.reserveRemaining():a.reserve()),-1===c)return!1;let l=r._reservations[t];l||(l=r._reservations[t]=[]);let p=l.indexOf(null);-1===p&&(p=l.length),l[p]=e;const u=a.chunkOffset(c),d=s?a.chunkLengthRemaining(c):a.chunkLength(c);function f(){n.nextTick((()=>{r._update()}))}return e.request(t,u,d,(function n(i,o){if(r.destroyed)return;if(!r.ready)return r.once("ready",(()=>{n(i,o)}));if(l[p]===e&&(l[p]=null),a!==r.pieces[t])return f();if(i)return r._debug("error getting piece %s (offset: %s length: %s) from %s: %s",t,u,d,`${e.remoteAddress}:${e.remotePort}`,i.message),s?a.cancelRemaining(c):a.cancel(c),void f();if(r._debug("got piece %s (offset: %s length: %s) from %s",t,u,d,`${e.remoteAddress}:${e.remotePort}`),!a.set(c,o,e))return f();const h=a.flush();E(h,(e=>{if(!r.destroyed){if(e===r._hashes[t]){if(!r.pieces[t])return;r._debug("piece verified %s",t),r.pieces[t]=null,r._reservations[t]=null,r.bitfield.set(t,!0),r.store.put(t,h),r.wires.forEach((e=>{e.have(t)})),r._checkDone()&&!r.destroyed&&r.discovery.complete()}else r.pieces[t]=new _(a.length),r.emit("warning",new Error(`Piece ${t} failed verification`));f()}}))})),!0}_checkDone(){if(this.destroyed)return;this.files.forEach((e=>{if(!e.done){for(let t=e._startPiece;t<=e._endPiece;++t)if(!this.bitfield.get(t))return;e.done=!0,e.emit("done"),this._debug("file done: "+e.name)}}));let e=!0;for(let t=0;t{this.load(e,t)}));Array.isArray(e)||(e=[e]),t||(t=q);const n=new h(e),i=new s(this.store,this.pieceLength);w(n,i,(e=>{if(e)return t(e);this._markAllVerified(),this._checkDone(),t(null)}))}createServer(e){if("function"!=typeof O)throw new Error("node.js-only method");if(this.destroyed)throw new Error("torrent is destroyed");const t=new O(this,e);return this._servers.push(t),t}pause(){this.destroyed||(this._debug("pause"),this.paused=!0)}resume(){this.destroyed||(this._debug("resume"),this.paused=!1,this._drain())}_debug(){const e=[].slice.call(arguments);e[0]=`[${this.client?this.client._debugId:"No Client"}] [${this._debugId}] ${e[0]}`,a(...e)}_drain(){if(this._debug("_drain numConns %s maxConns %s",this._numConns,this.client.maxConns),"function"!=typeof m.connect||this.destroyed||this.paused||this._numConns>=this.client.maxConns)return;this._debug("drain (%s queued, %s/%s peers)",this._numQueued,this.numPeers,this.client.maxConns);const e=this._queue.shift();if(!e)return;this._debug("%s connect attempt to %s",e.type,e.addr);const t=r(e.addr),n={host:t[0],port:t[1]};"utpOutgoing"===e.type?e.conn=j.connect(n.port,n.host):e.conn=m.connect(n);const i=e.conn;i.once("connect",(()=>{e.onConnect()})),i.once("error",(t=>{e.destroy(t)})),e.startConnectTimeout(),i.on("close",(()=>{if(this.destroyed)return;if(e.retries>=M.length){if(this.client.utp){const t=this._addPeer(e.addr,"tcp");t&&(t.retries=0)}else this._debug("conn %s closed: will not re-add (max %s attempts)",e.addr,M.length);return}const t=M[e.retries];this._debug("conn %s closed: will re-add to queue in %sms (attempt %s)",e.addr,t,e.retries+1);const n=setTimeout((()=>{if(this.destroyed)return;const t=this._addPeer(e.addr,this.client.utp?"utp":"tcp");t&&(t.retries=e.retries+1)}),t);n.unref&&n.unref()}))}_validAddr(e){let t;try{t=r(e)}catch(e){return!1}const n=t[0],i=t[1];return i>0&&i<65535&&!("127.0.0.1"===n&&i===this.client.torrentPort)}}}).call(this)}).call(this,e("_process"),"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"../package.json":334,"./file":311,"./peer":312,"./rarity-map":313,"./server":55,_process:187,"addr-to-ip-port":3,bitfield:10,"chunk-store-stream/write":78,debug:316,events:98,fs:56,"fs-chunk-store":141,"immediate-chunk-store":118,multistream:166,net:55,os:55,"parse-torrent":184,path:185,pump:188,"random-iterate":194,"run-parallel":218,"run-parallel-limit":217,"simple-get":222,"simple-sha1":242,speedometer:263,"torrent-discovery":291,"torrent-piece":295,ut_metadata:301,ut_pex:55,"utp-native":55}],315:[function(e,t,n){(function(n){(function(){const i=e("bitfield"),r=e("debug")("webtorrent:webconn"),o=e("simple-get"),s=e("simple-sha1"),a=e("bittorrent-protocol"),c=e("../package.json").version;t.exports=class extends a{constructor(e,t){super(),this.url=e,this.webPeerId=s.sync(e),this._torrent=t,this._init()}_init(){this.setKeepAlive(!0),this.once("handshake",((e,t)=>{if(this.destroyed)return;this.handshake(e,this.webPeerId);const n=this._torrent.pieces.length,r=new i(n);for(let e=0;e<=n;e++)r.set(e,!0);this.bitfield(r)})),this.once("interested",(()=>{r("interested"),this.unchoke()})),this.on("uninterested",(()=>{r("uninterested")})),this.on("choke",(()=>{r("choke")})),this.on("unchoke",(()=>{r("unchoke")})),this.on("bitfield",(()=>{r("bitfield")})),this.on("request",((e,t,n,i)=>{r("request pieceIndex=%d offset=%d length=%d",e,t,n),this.httpRequest(e,t,n,i)}))}httpRequest(e,t,i,s){const a=e*this._torrent.pieceLength+t,l=a+i-1,p=this._torrent.files;let u;if(p.length<=1)u=[{url:this.url,start:a,end:l}];else{const e=p.filter((e=>e.offset<=l&&e.offset+e.length>a));if(e.length<1)return s(new Error("Could not find file corresponnding to web seed range request"));u=e.map((e=>{const t=e.offset+e.length-1;return{url:this.url+("/"===this.url[this.url.length-1]?"":"/")+e.path,fileOffsetInRange:Math.max(e.offset-a,0),start:Math.max(a-e.offset,0),end:Math.min(t,l-e.offset)}}))}let d,f=0,h=!1;u.length>1&&(d=n.alloc(i)),u.forEach((n=>{const a=n.url,l=n.start,p=n.end;r("Requesting url=%s pieceIndex=%d offset=%d length=%d start=%d end=%d",a,e,t,i,l,p);const m={url:a,method:"GET",headers:{"user-agent":`WebTorrent/${c} (https://webtorrent.io)`,range:`bytes=${l}-${p}`}};function g(e,t){if(e.statusCode<200||e.statusCode>=300)return h=!0,s(new Error("Unexpected HTTP status code "+e.statusCode));r("Got data of length %d",t.length),1===u.length?s(null,t):(t.copy(d,n.fileOffsetInRange),++f===u.length&&s(null,d))}o.concat(m,((e,t,n)=>{if(!h)return e?"undefined"==typeof window||a.startsWith(window.location.origin+"/")?(h=!0,s(e)):o.head(a,((t,n)=>{if(!h){if(t)return h=!0,s(t);if(n.statusCode<200||n.statusCode>=300)return h=!0,s(new Error("Unexpected HTTP status code "+n.statusCode));if(n.url===a)return h=!0,s(e);m.url=n.url,o.concat(m,((e,t,n)=>{if(!h)return e?(h=!0,s(e)):void g(t,n)}))}})):void g(t,n)}))}))}destroy(){super.destroy(),this._torrent=null}}}).call(this)}).call(this,e("buffer").Buffer)},{"../package.json":334,bitfield:10,"bittorrent-protocol":11,buffer:60,debug:316,"simple-get":222,"simple-sha1":242}],316:[function(e,t,n){arguments[4][13][0].apply(n,arguments)},{"./common":317,_process:187,dup:13}],317:[function(e,t,n){arguments[4][14][0].apply(n,arguments)},{dup:14,ms:318}],318:[function(e,t,n){arguments[4][15][0].apply(n,arguments)},{dup:15}],319:[function(e,t,n){arguments[4][16][0].apply(n,arguments)},{dup:16}],320:[function(e,t,n){arguments[4][17][0].apply(n,arguments)},{"./_stream_readable":322,"./_stream_writable":324,_process:187,dup:17,inherits:119}],321:[function(e,t,n){arguments[4][18][0].apply(n,arguments)},{"./_stream_transform":323,dup:18,inherits:119}],322:[function(e,t,n){arguments[4][19][0].apply(n,arguments)},{"../errors":319,"./_stream_duplex":320,"./internal/streams/async_iterator":325,"./internal/streams/buffer_list":326,"./internal/streams/destroy":327,"./internal/streams/from":329,"./internal/streams/state":331,"./internal/streams/stream":332,_process:187,buffer:60,dup:19,events:98,inherits:119,"string_decoder/":286,util:55}],323:[function(e,t,n){arguments[4][20][0].apply(n,arguments)},{"../errors":319,"./_stream_duplex":320,dup:20,inherits:119}],324:[function(e,t,n){arguments[4][21][0].apply(n,arguments)},{"../errors":319,"./_stream_duplex":320,"./internal/streams/destroy":327,"./internal/streams/state":331,"./internal/streams/stream":332,_process:187,buffer:60,dup:21,inherits:119,"util-deprecate":306}],325:[function(e,t,n){arguments[4][22][0].apply(n,arguments)},{"./end-of-stream":328,_process:187,dup:22}],326:[function(e,t,n){arguments[4][23][0].apply(n,arguments)},{buffer:60,dup:23,util:55}],327:[function(e,t,n){arguments[4][24][0].apply(n,arguments)},{_process:187,dup:24}],328:[function(e,t,n){arguments[4][25][0].apply(n,arguments)},{"../../../errors":319,dup:25}],329:[function(e,t,n){arguments[4][26][0].apply(n,arguments)},{dup:26}],330:[function(e,t,n){arguments[4][27][0].apply(n,arguments)},{"../../../errors":319,"./end-of-stream":328,dup:27}],331:[function(e,t,n){arguments[4][28][0].apply(n,arguments)},{"../../../errors":319,dup:28}],332:[function(e,t,n){arguments[4][29][0].apply(n,arguments)},{dup:29,events:98}],333:[function(e,t,n){arguments[4][30][0].apply(n,arguments)},{"./lib/_stream_duplex.js":320,"./lib/_stream_passthrough.js":321,"./lib/_stream_readable.js":322,"./lib/_stream_transform.js":323,"./lib/_stream_writable.js":324,"./lib/internal/streams/end-of-stream.js":328,"./lib/internal/streams/pipeline.js":330,dup:30}],334:[function(e,t,n){t.exports={version:"0.110.1"}},{}],335:[function(e,t,n){t.exports=function e(t,n){if(t&&n)return e(t)(n);if("function"!=typeof t)throw new TypeError("need wrapper function");return Object.keys(t).forEach((function(e){i[e]=t[e]})),i;function i(){for(var e=new Array(arguments.length),n=0;n1080?(N.setProps({placement:"right"}),D.setProps({placement:"right"}),q.setProps({placement:"right"})):(N.setProps({placement:"top"}),D.setProps({placement:"top"}),q.setProps({placement:"top"}))}function W(e){X();try{console.info("Attempting parse"),u=r(e),$(),u.xs&&(console.info("Magnet includes xs, attempting remote parse"),V(u.xs))}catch(t){console.warn(t),"magnet"==p?(console.info("Attempting remote parse"),V(e)):(F.error("Problem parsing input. Is this a .torrent file?"),console.error("Problem parsing input"))}}function V(e){r.remote(e,(function(e,t){if(e)return F.error("Problem remotely fetching that file or parsing result"),console.warn(e),void X();p="remote-torrent-file",v.innerHTML='',b.setContent("Currently loaded information sourced from remotely fetched Torrent file"),u=t,$()}))}function $(){if(console.log(u),E.value=u.infoHash,x.value=u.name?u.name:"",u.created?(_.value=u.created.toISOString().slice(0,19),_.type="datetime-local"):_.type="text",w.value=u.createdBy?"by "+u.createdBy:"",k.value=u.comment?u.comment:"",j.innerHTML="",u.announce&&u.announce.length)for(let e=0;e',i.addEventListener("click",Q),t.appendChild(i),j.appendChild(t)}if(A.innerHTML="",u.urlList&&u.urlList.length)for(let e=0;e',i.addEventListener("click",Q),t.appendChild(i),A.appendChild(t)}if(O.innerHTML="",u.files&&u.files.length){R.style.display="none";for(let e of u.files){let t=Y(a.lookup(e.name));O.appendChild(G(t,e.name,e.length))}O.appendChild(G("folder-tree","",u.length)),q.setContent("Download Torrent file"),P.addEventListener("click",ie),P.disabled=!1}else H.torrents.length>0?(R.style.display="none",O.innerHTML=''):(R.style.display="block",O.innerHTML=''),q.setContent("Files metadata is required to generate Torrent file. Try fetching files list from WebTorrent."),P.removeEventListener("click",ie),P.disabled=!0;B.setAttribute("data-clipboard-text",window.location.origin+"#"+r.toMagnetURI(u)),U.setAttribute("data-clipboard-text",r.toMagnetURI(u)),d.style.display="none",g.style.display="flex",window.location.hash=r.toMagnetURI(u),u.name?document.title="Torrent Parts | "+u.name:document.title="Torrent Parts | Inspect and edit what's in your Torrent file or Magnet link",b.enable(),gtag("event","view_item",{items:[{item_id:u.infoHash,item_name:u.name,item_category:p}]})}function G(e,t,n){let i=document.createElement("tr"),r=document.createElement("td");r.innerHTML='',i.appendChild(r);let o=document.createElement("td");o.innerHTML=t,i.appendChild(o);let a=document.createElement("td");return a.innerHTML=s.format(n,{decimalPlaces:1,unitSeparator:" "}),i.appendChild(a),i}function Y(e){if(!e)return"file";switch(!0){case e.includes("msword"):case e.includes("wordprocessingml"):case e.includes("opendocument.text"):case e.includes("abiword"):return"file-word";case e.includes("ms-excel"):case e.includes("spreadsheet"):return"file-powerpoint";case e.includes("powerpoint"):case e.includes("presentation"):return"file-powerpoint";case e.includes("7z-"):case e.includes("iso9660"):case e.includes("zip"):case e.includes("octet-stream"):return"file-archive";case e.includes("csv"):return"file-csv";case e.includes("pdf"):return"file-pdf";case e.includes("font"):return"file-contract";case e.includes("text"):case e.includes("subrip"):case e.includes("vtt"):return"file-alt";case e.includes("audio"):return"file-audio";case e.includes("image"):return"file-image";case e.includes("video"):return"file-video";default:return"file"}}function K(e){this.dataset.group?u[this.dataset.group][this.dataset.index]=this.value?this.value:"":u[this.id]=this.value?this.value:"",window.location.hash=r.toMagnetURI(u),te()}function X(){document.getElementById("magnet").value="",document.getElementById("torrent").value="",d.style.display="flex",g.style.display="none",x.value="",_.value="",w.value="",k.value="",E.value="",j.innerHTML="",A.innerHTML="",H.torrents.forEach((e=>e.destroy())),R.style.display="block",O.innerHTML="",window.location.hash="",B.setAttribute("data-clipboard-text",""),U.setAttribute("data-clipboard-text",""),document.title="Torrent Parts | Inspect and edit what's in your Torrent file or Magnet link",b.disable(),gtag("event","reset")}async function J(){S.className="disabled",S.innerHTML="Adding...";try{let e=await fetch("https://newtrackon.com/api/100"),t=await e.text();u.announce=u.announce.concat(t.split("\n\n")),u.announce.push("http://bt1.archive.org:6969/announce"),u.announce.push("http://bt2.archive.org:6969/announce"),u.announce=u.announce.filter(((e,t)=>e&&u.announce.indexOf(e)===t)),F.success("Added known working trackers from newTrackon"),te()}catch(e){F.error("Problem fetching trackers from newTrackon"),console.warn(e)}S.className="",S.innerHTML="Add Known Working Trackers",$(),gtag("event","add_trackers")}function Z(){u[this.dataset.type].unshift(""),$()}function Q(){u[this.parentElement.className].splice(this.parentElement.dataset.index,1),$()}function ee(e){u[e]=[],te(),$()}function te(){u.created=new Date,u.createdBy="Torrent Parts ",u.created?(_.value=u.created.toISOString().slice(0,19),_.type="datetime-local"):_.type="text",w.value=u.createdBy?"by "+u.createdBy:""}function ne(){console.info("Attempting fetching files from Webtorrent..."),R.style.display="none",u.announce.push("wss://tracker.webtorrent.io"),u.announce.push("wss://tracker.openwebtorrent.com"),u.announce.push("wss://tracker.btorrent.xyz"),u.announce.push("wss://tracker.fastcast.nz"),u.announce=u.announce.filter(((e,t)=>e&&u.announce.indexOf(e)===t)),H.add(r.toMagnetURI(u),(e=>{u.info=Object.assign({},e.info),u.files=e.files,u.infoBuffer=e.infoBuffer,u.length=e.length,u.lastPieceLength=e.lastPieceLength,te(),$(),F.success("Fetched file details from Webtorrent peers"),e.destroy()})),$(),gtag("event","attempt_webtorrent_fetch")}function ie(){let e=r.toTorrentFile(u);if(null!==e&&navigator.msSaveBlob)return navigator.msSaveBlob(new Blob([e],{type:"application/x-bittorrent"}),u.name+".torrent");let t=document.createElement("a");t.style.display="none";let n=window.URL.createObjectURL(new Blob([e],{type:"application/x-bittorrent"}));t.setAttribute("href",n),t.setAttribute("download",u.name+".torrent"),document.body.appendChild(t),t.click(),window.URL.revokeObjectURL(n),t.remove(),gtag("event","share",{method:"Torrent Download",content_id:u.name})}window.addEventListener("resize",z),z(),document.addEventListener("DOMContentLoaded",(function(){document.getElementById("magnet").addEventListener("keyup",(function(e){e.preventDefault(),"Enter"===e.key&&(p="magnet",v.innerHTML='',b.setContent("Currently loaded information sourced from Magnet URL"),W(magnet.value))})),document.getElementById("torrent").addEventListener("change",(function(e){e.preventDefault(),e.target.files[0].arrayBuffer().then((function(e){p="torrent-file",v.innerHTML='',b.setContent("Currently loaded information sourced from Torrent file"),W(o.from(e))}))})),f.addEventListener("click",(function(e){e.preventDefault(),F.success("Parsing Ubuntu 20.04 Magnet URL"),W("magnet:?xt=urn:btih:9fc20b9e98ea98b4a35e6223041a5ef94ea27809&dn=ubuntu-20.04-desktop-amd64.iso&tr=https%3A%2F%2Ftorrent.ubuntu.com%2Fannounce&tr=https%3A%2F%2Fipv6.torrent.ubuntu.com%2Fannounce")})),h.addEventListener("click",(async function(e){e.preventDefault(),F.success("Fetching and Parsing “The WIRED CD” Torrent File..."),V("https://webtorrent.io/torrents/wired-cd.torrent")})),m.addEventListener("click",(async function(e){e.preventDefault(),F.success("Parsing Jack Johnson Archive.org Torrent File");let t=await fetch("jj2008-06-14.mk4_archive.torrent"),n=await t.arrayBuffer();W(o.from(n))}));let e=new i("#copyURL");e.on("success",(function(e){F.success("Copied site URL to clipboard!"),console.info(e),gtag("event","share",{method:"Copy URL",content_id:e.text})})),e.on("failure",(function(e){F.error("Problem copying to clipboard"),console.warn(e)}));let t=new i("#copyMagnet");t.on("success",(function(e){F.success("Copied Magnet URL to clipboard!"),gtag("event","share",{method:"Copy Magnet",content_id:e.text})})),t.on("failure",(function(e){F.error("Problem copying to clipboard"),console.warn(e)})),x.addEventListener("input",K),x.addEventListener("change",K),x.addEventListener("reset",K),x.addEventListener("paste",K),y.addEventListener("click",X),k.addEventListener("input",K),k.addEventListener("change",K),k.addEventListener("reset",K),k.addEventListener("paste",K),S.addEventListener("click",J),C.addEventListener("click",Z),T.addEventListener("click",(()=>ee("announce"))),L.addEventListener("click",Z),I.addEventListener("click",(()=>ee("urlList"))),R.addEventListener("click",ne),l("[data-tippy-content]",{theme:"torrent-parts",animation:"shift-away-subtle"}),b.disable(),window.location.hash&&(p="shared-url",v.innerHTML='',b.setContent("Currently loaded information sourced from shared torrent.parts link"),W(window.location.hash.split("#")[1]))}))},{Buffer:2,bytes:62,clipboard:79,"mime-types":144,"parse-torrent":184,"tippy.js":289,webtorrent:309}]},{},[337]); \ No newline at end of file diff --git a/index.html b/index.html index f16c2f0..95715dd 100644 --- a/index.html +++ b/index.html @@ -59,15 +59,24 @@
- + + + - + +
+ +
+
...or, try some examples!
+ + +