diff --git a/bin/bundle.js b/bin/bundle.js index a500950..635a39d 100644 --- a/bin/bundle.js +++ b/bin/bundle.js @@ -62726,12 +62726,18 @@ function start() { example1.addEventListener('click', function(event) { event.preventDefault(); notyf.success("Parsing Ubuntu 20.04 Magnet URL"); + source = "magnet"; + originalSourceIcon.innerHTML = ''; + sourceTooltip.setContent("Currently loaded information sourced from 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..."); + source = "remote-torrent-file"; + originalSourceIcon.innerHTML = ''; + sourceTooltip.setContent("Currently loaded information sourced from remotely fetched Torrent file"); parseRemote("https://webtorrent.io/torrents/wired-cd.torrent"); }); @@ -62740,6 +62746,9 @@ function start() { notyf.success("Parsing Jack Johnson Archive.org Torrent File"); let response = await fetch("/ext/jj2008-06-14.mk4_archive.torrent"); let arrayBuffer = await response.arrayBuffer(); + source = "torrent-file"; + originalSourceIcon.innerHTML = ''; + sourceTooltip.setContent("Currently loaded information sourced from Torrent file"); parse(Buffer.from(arrayBuffer)); }); diff --git a/bin/bundle.min.js b/bin/bundle.min.js index 8b15ce4..f567545 100644 --- a/bin/bundle.min.js +++ b/bin/bundle.min.js @@ -106,4 +106,4 @@ const i=16384;class n{constructor(e){this.length=e,this.missing=e,this.sources=n /*! ut_metadata. MIT License. WebTorrent LLC */ const{EventEmitter:n}=e("events"),r=e("bencode"),s=e("bitfield").default,a=e("debug")("ut_metadata"),o=e("simple-sha1"),c=16384;t.exports=e=>{class t extends n{constructor(t){super(),this._wire=t,this._fetching=!1,this._metadataComplete=!1,this._metadataSize=null,this._remainingRejects=null,this._bitfield=new s(0,{grow:1e3}),i.isBuffer(e)&&this.setMetadata(e)}onHandshake(e,t,i){this._infoHash=e}onExtendedHandshake(e){return e.m&&e.m.ut_metadata?e.metadata_size?"number"!=typeof e.metadata_size||1e7this._metadataSize&&(i=this._metadataSize);const n=this.metadata.slice(t,i);this._data(e,n,this._metadataSize)}_onData(e,t,i){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=i.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:23,bitfield:27,buffer:110,debug:161,events:193,"simple-sha1":411}],485:[function(e,t,i){(function(e){(function(){function i(t){try{if(!e.localStorage)return!1}catch(e){return!1}var i=e.localStorage[t];return null!=i&&"true"===String(i).toLowerCase()}t.exports=function(e,t){if(i("noDeprecation"))return e;var n=!1;return function(){if(!n){if(i("throwDeprecation"))throw new Error(t);i("traceDeprecation")?console.trace(t):console.warn(t),n=!0}return e.apply(this,arguments)}}}).call(this)}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}],486:[function(e,t,i){(function(i){(function(){const n=e("binary-search"),r=e("events"),s=e("mp4-stream"),a=e("mp4-box-encoding"),o=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=s.decode();const i=this._file.createReadStream({start:e});i.pipe(this._decoder);const n=r=>{"moov"===r.type?(this._decoder.removeListener("box",n),this._decoder.decode((e=>{i.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",n),t+=r.length,i.destroy(),this._decoder.destroy(),this._findMoov(e+t))};this._decoder.on("box",n)}_processMoov(e){const t=e.traks;this._tracks=[],this._hasVideo=!1,this._hasAudio=!1;for(let i=0;i=s.stsz.entries.length)break;if(f++,m+=e,f>=n.samplesPerChunk){f=0,m=0,h++;const e=s.stsc.entries[b+1];e&&h+1>=e.firstChunk&&b++}v+=t,g.inc(),y&&y.inc(),r&&_++}r.mdia.mdhd.duration=0,r.tkhd.duration=0;const x=n.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:s.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:x,defaultSampleDuration:0,defaultSampleSize:0,defaultSampleFlags:0}]}};this._tracks.push({fragmentSequence:1,trackId:r.tkhd.trackId,timeScale:r.mdia.mdhd.timeScale,samples:p,currSample:null,currTime:null,moov:w,mime:u})}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=a.encode(this._ftyp),s=this._tracks.map((e=>{const t=a.encode(e.moov);return{mime:e.mime,init:i.concat([r,t])}}));this.emit("ready",s)}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(((i,n)=>{i.outStream&&i.outStream.destroy(),i.inStream&&(i.inStream.destroy(),i.inStream=null);const r=i.outStream=s.encode(),a=this._generateFragment(n,e);if(!a)return r.finalize();(-1===t||a.ranges[0].start{r.destroyed||r.box(e.moof,(t=>{if(t)return this.emit("error",t);if(r.destroyed)return;i.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(n);if(!t)return r.finalize();o(t)})))}))};o(a)})),t>=0){const e=this._fileStream=this._file.createReadStream({start:t});this._tracks.forEach((i=>{i.inStream=new o(t,{highWaterMark:1e7}),e.pipe(i.inStream)}))}return this._tracks.map((e=>e.outStream))}_findSampleBefore(e,t){const i=this._tracks[e],r=Math.floor(i.timeScale*t);let s=n(i.samples,r,((e,t)=>e.dts+e.presentationOffset-t));for(-1===s?s=0:s<0&&(s=-s-2);!i.samples[s].sync;)s--;return s}_generateFragment(e,t){const i=this._tracks[e];let n;if(n=void 0!==t?this._findSampleBefore(e,t):i.currSample,n>=i.samples.length)return null;const r=i.samples[n].dts;let s=0;const a=[];for(var o=n;o=i.timeScale*l)break;s+=e.size;const t=a.length-1;t<0||a[t].end!==e.offset?a.push({start:e.offset,end:e.offset+e.size}):a[t].end+=e.size}return i.currSample=o,{moof:this._generateMoof(e,n,o),ranges:a,length:s}}_generateMoof(e,t,i){const n=this._tracks[e],r=[];let s=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)}a.prototype={_createMuxer(){this._muxer=new s(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 i={muxed:null,mediaSource:t,initFlushed:!1,onInitFlushed:null};return t.write(e.init,(e=>{i.initFlushed=!0,i.onInitFlushed&&i.onInitFlushed(e)})),i})),(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,i)=>{const n=()=>{t.muxed&&(t.muxed.destroy(),t.mediaSource=this._elemWrapper.createWriteStream(t.mediaSource),t.mediaSource.on("error",(e=>{this._elemWrapper.error(e)}))),t.muxed=e[i],r(t.muxed,t.mediaSource)};t.initFlushed?n():t.onInitFlushed=e=>{e?this._elemWrapper.error(e):n()}}))},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=a},{"./mp4-remuxer":486,mediasource:259,pump:349}],488:[function(e,t,i){(function(i){(function(){ /*! webtorrent. MIT License. WebTorrent LLC */ -const n=e("events"),r=e("path"),s=e("simple-concat"),a=e("create-torrent"),o=e("debug"),c=e("bittorrent-dht/client"),l=e("load-ip-set"),u=e("run-parallel"),p=e("parse-torrent"),d=e("simple-peer"),f=e("queue-microtask"),h=e("randombytes"),m=e("simple-sha1"),b=e("speedometer"),{ThrottleGroup:v}=e("speed-limiter"),g=e("./lib/conn-pool.js"),y=e("./lib/torrent.js"),{version:_}=e("./package.json"),x=o("webtorrent"),w=_.replace(/\d*./g,(e=>("0"+e%100).slice(-2))).slice(0,4),k=`-WW${w}-`;class E extends n{constructor(t={}){super(),"string"==typeof t.peerId?this.peerId=t.peerId:i.isBuffer(t.peerId)?this.peerId=t.peerId.toString("hex"):this.peerId=i.from(k+h(9).toString("base64")).toString("hex"),this.peerIdBuffer=i.from(this.peerId,"hex"),"string"==typeof t.nodeId?this.nodeId=t.nodeId:i.isBuffer(t.nodeId)?this.nodeId=t.nodeId.toString("hex"):this.nodeId=h(20).toString("hex"),this.nodeIdBuffer=i.from(this.nodeId,"hex"),this._debugId=this.peerId.toString("hex").substring(0,7),this.destroyed=!1,this.listening=!1,this.torrentPort=t.torrentPort||0,this.dhtPort=t.dhtPort||0,this.tracker=void 0!==t.tracker?t.tracker:{},this.lsd=!1!==t.lsd,this.torrents=[],this.maxConns=Number(t.maxConns)||55,this.utp=E.UTP_SUPPORT&&!1!==t.utp,this._downloadLimit=Math.max("number"==typeof t.downloadLimit?t.downloadLimit:-1,-1),this._uploadLimit=Math.max("number"==typeof t.uploadLimit?t.uploadLimit:-1,-1),this.serviceWorker=null,this.workerKeepAliveInterval=null,this.workerPortCount=0,!0===t.secure&&e("./lib/peer").enableSecure(),this._debug("new webtorrent (peerId %s, nodeId %s, port %s)",this.peerId,this.nodeId,this.torrentPort),this.throttleGroups={down:new v({rate:Math.max(this._downloadLimit,0),enabled:this._downloadLimit>=0}),up:new v({rate:Math.max(this._uploadLimit,0),enabled:this._uploadLimit>=0})},this.tracker&&("object"!=typeof this.tracker&&(this.tracker={}),globalThis.WRTC&&!this.tracker.wrtc&&(this.tracker.wrtc=globalThis.WRTC)),"function"==typeof g?this._connPool=new g(this):f((()=>{this._onListening()})),this._downloadSpeed=b(),this._uploadSpeed=b(),!1!==t.dht&&"function"==typeof c?(this.dht=new c(Object.assign({},{nodeId:this.nodeId},t.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!==t.webSeeds;const n=()=>{this.destroyed||(this.ready=!0,this.emit("ready"))};"function"==typeof l&&null!=t.blocklist?l(t.blocklist,{headers:{"user-agent":`WebTorrent/${_} (https://webtorrent.io)`}},((e,t)=>{if(e)return console.error(`Failed to load blocklist: ${e.message}`);this.blocked=t,n()})):f(n)}loadWorker(e,t=(()=>{})){if(!(e instanceof ServiceWorker))throw new Error("Invalid worker registration");if("activated"!==e.state)throw new Error("Worker isn't activated");this.serviceWorker=e,navigator.serviceWorker.addEventListener("message",(e=>{const{data:t}=e;if(!t.type||"webtorrent"===!t.type||!t.url)return null;let[i,...n]=t.url.slice(t.url.indexOf(t.scope+"webtorrent/")+11+t.scope.length).split("/");if(n=decodeURI(n.join("/")),!i||!n)return null;const[r]=e.ports,s=this.get(i)&&this.get(i).files.find((e=>e.path===n));if(!s)return null;const[a,o,c]=s._serve(t),l=o&&o[Symbol.asyncIterator](),u=()=>{r.onmessage=null,o&&o.destroy(),c&&c.destroy(),this.workerPortCount--,this.workerPortCount||(clearInterval(this.workerKeepAliveInterval),this.workerKeepAliveInterval=null)};r.onmessage=async e=>{if(e.data){let e;try{e=(await l.next()).value}catch(e){}r.postMessage(e),e||u(),this.workerKeepAliveInterval||(this.workerKeepAliveInterval=setInterval((()=>fetch(`${this.serviceWorker.scriptURL.substr(0,this.serviceWorker.scriptURL.lastIndexOf("/")+1).slice(window.location.origin.length)}webtorrent/keepalive/`)),2e4))}else u()},this.workerPortCount++,r.postMessage(a)})),t(this.serviceWorker)}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 y){if(this.torrents.includes(e))return e}else{let t;try{t=p(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}add(e,t={},i=(()=>{})){if(this.destroyed)throw new Error("client is destroyed");"function"==typeof t&&([t,i]=[{},t]);const n=()=>{if(!this.destroyed)for(const e of this.torrents)if(e.infoHash===s.infoHash&&e!==s)return void s._destroy(new Error(`Cannot add duplicate torrent ${s.infoHash}`))},r=()=>{this.destroyed||(i(s),this.emit("torrent",s))};this._debug("add"),t=t?Object.assign({},t):{};const s=new y(e,this,t);return this.torrents.push(s),s.once("_infoHash",n),s.once("ready",r),s.once("close",(function e(){s.removeListener("_infoHash",n),s.removeListener("ready",r),s.removeListener("close",e)})),s}seed(e,t,i){if(this.destroyed)throw new Error("client is destroyed");"function"==typeof t&&([t,i]=[{},t]),this._debug("seed"),(t=t?Object.assign({},t):{}).skipVerify=!0;const n="string"==typeof e;n&&(t.path=r.dirname(e)),t.createdBy||(t.createdBy=`WebTorrent/${w}`);const o=e=>{this._debug("on seed"),"function"==typeof i&&i(e),e.emit("seed"),this.emit("seed",e)},c=this.add(null,t,(e=>{const i=[i=>{if(n||t.preloadedStore)return i();e.load(l,i)}];this.dht&&i.push((t=>{e.once("dhtAnnounce",t)})),u(i,(t=>{if(!this.destroyed)return t?e._destroy(t):void o(e)}))}));let l;var p;return p=e,"undefined"!=typeof FileList&&p instanceof FileList?e=Array.from(e):Array.isArray(e)||(e=[e]),u(e.map((e=>i=>{!t.preloadedStore&&function(e){return"object"==typeof e&&null!=e&&"function"==typeof e.pipe}(e)?s(e,((t,n)=>{if(t)return i(t);n.name=e.name,i(null,n)})):i(null,e)})),((e,i)=>{if(!this.destroyed)return e?c._destroy(e):void a.parseInput(i,t,((e,n)=>{if(!this.destroyed){if(e)return c._destroy(e);l=n.map((e=>e.getStream)),a(i,t,((e,t)=>{if(this.destroyed)return;if(e)return c._destroy(e);const i=this.get(t);i?c._destroy(new Error(`Cannot add duplicate torrent ${i.infoHash}`)):c._onTorrentId(t)}))}}))})),c}remove(e,t,i){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,i)}_remove(e,t,i){if("function"==typeof t)return this._remove(e,null,t);const n=this.get(e);n&&(this.torrents.splice(this.torrents.indexOf(n),1),n.destroy(t,i),this.dht&&this.dht._tables.remove(n.infoHash))}address(){return this.listening?this._connPool?this._connPool.tcpServer.address():{address:"0.0.0.0",family:"IPv4",port:0}:null}throttleDownload(e){return e=Number(e),!(isNaN(e)||!isFinite(e)||e<-1)&&(this._downloadLimit=e,this._downloadLimit<0?this.throttleGroups.down.setEnabled(!1):(this.throttleGroups.down.setEnabled(!0),void this.throttleGroups.down.setRate(this._downloadLimit)))}throttleUpload(e){return e=Number(e),!(isNaN(e)||!isFinite(e)||e<-1)&&(this._uploadLimit=e,this._uploadLimit<0?this.throttleGroups.up.setEnabled(!1):(this.throttleGroups.up.setEnabled(!0),void this.throttleGroups.up.setRate(this._uploadLimit)))}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 i=this.torrents.map((e=>t=>{e.destroy(t)}));this._connPool&&i.push((e=>{this._connPool.destroy(e)})),this.dht&&i.push((e=>{this.dht.destroy(e)})),u(i,t),e&&this.emit("error",e),this.torrents=[],this._connPool=null,this.dht=null,this.throttleGroups.down.destroy(),this.throttleGroups.up.destroy()}_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]}`,x(...e)}_getByHash(e){for(const t of this.torrents)if(t.infoHashHash||(t.infoHashHash=m.sync(i.from("72657132"+t.infoHash,"hex"))),e===t.infoHashHash)return t;return null}}E.WEBRTC_SUPPORT=d.WEBRTC_SUPPORT,E.UTP_SUPPORT=g.UTP_SUPPORT,E.VERSION=_,t.exports=E}).call(this)}).call(this,e("buffer").Buffer)},{"./lib/conn-pool.js":67,"./lib/peer":491,"./lib/torrent.js":493,"./package.json":495,"bittorrent-dht/client":67,buffer:110,"create-torrent":144,debug:161,events:193,"load-ip-set":67,"parse-torrent":332,path:333,"queue-microtask":354,randombytes:357,"run-parallel":381,"simple-concat":393,"simple-peer":395,"simple-sha1":411,"speed-limiter":429,speedometer:433}],489:[function(e,t,i){const n=e("stream"),r=e("debug"),s=e("end-of-stream"),a=r("webtorrent:file-stream");class o extends n.Readable{constructor(e,t){super(t),this._torrent=e._torrent;const i=t&&t.start||0,n=t&&t.end&&t.end{this._notify()})),s(this,(e=>{this.destroy(e)}))}_read(){this._reading||(this._reading=!0,this._notify())}_notify(){if(!this._reading||0===this._missing)return;if(!this._torrent.bitfield.get(this._piece))return this._torrent.critical(this._piece,this._piece+this._criticalLength);if(this._notifying)return;if(this._notifying=!0,this._torrent.destroyed)return this.destroy(new Error("Torrent removed"));const e=this._piece,t={};e===this._torrent.pieces.length-1&&(t.length=this._torrent.lastPieceLength),this._torrent.store.get(e,t,((t,i)=>{if(this._notifying=!1,!this.destroyed){if(a("read %s (length %s) (err %s)",e,i&&i.length,t&&t.message),t)return this.destroy(t);this._offset&&(i=i.slice(this._offset),this._offset=0),this._missing{const s=r===e.length-1?n:i;return t.get(r)?s:s-e[r].missing};let o=0;for(let t=r;t<=s;t+=1){const c=a(t);if(o+=c,t===r){const e=this.offset%i;o-=Math.min(e,c)}if(t===s){const t=(s===e.length-1?n:i)-(this.offset+this.length)%i;o-=Math.min(t,c)}}return o}get progress(){return this.length?this.downloaded/this.length:0}select(e){0!==this.length&&this._torrent.select(this._startPiece,this._endPiece,e)}deselect(){0!==this.length&&this._torrent.deselect(this._startPiece,this._endPiece,!1)}createReadStream(e){if(0===this.length){const e=new r;return u((()=>{e.end()})),e}const t=new h(this,e);return this._fileStreams.add(t),t.once("close",(()=>{this._fileStreams.delete(t)})),t}getBuffer(e){l(this.createReadStream(),this.length,e)}getBlob(e){if("undefined"==typeof window)throw new Error("browser-only method");o(this.createReadStream(),this._getMimeType()).then((t=>e(null,t)),(t=>e(t)))}getBlobURL(e){if("undefined"==typeof window)throw new Error("browser-only method");c(this.createReadStream(),this._getMimeType()).then((t=>e(null,t)),(t=>e(t)))}appendTo(e,t,i){if("undefined"==typeof window)throw new Error("browser-only method");a.append(this,e,t,i)}renderTo(e,t,i){if("undefined"==typeof window)throw new Error("browser-only method");a.render(this,e,t,i)}_serve(e){const t={status:200,headers:{"Accept-Ranges":"bytes","Content-Type":d.getType(this.name),"Cache-Control":"no-cache, no-store, must-revalidate, max-age=0",Expires:"0"},body:"HEAD"===e.method?"":"STREAM"};"document"===e.destination&&(t.headers["Content-Type"]="application/octet-stream",t.headers["Content-Disposition"]="attachment",t.body="DOWNLOAD");let i=p(this.length,e.headers.range||"");i.constructor===Array?(t.status=206,i=i[0],t.headers["Content-Range"]=`bytes ${i.start}-${i.end}/${this.length}`,t.headers["Content-Length"]=""+(i.end-i.start+1)):t.headers["Content-Length"]=this.length;const n="GET"===e.method&&this.createReadStream(i);let r=null;return n&&this.emit("stream",{stream:n,req:e,file:this},(e=>{r=e,f(e,(()=>{e&&e.destroy(),n.destroy()}))})),[t,r||n,r&&n]}getStreamURL(e=(()=>{})){if("undefined"==typeof window)throw new Error("browser-only method");if(!this._serviceWorker)throw new Error("No worker registered");if("activated"!==this._serviceWorker.state)throw new Error("Worker isn't activated");e(null,`${this._serviceWorker.scriptURL.substr(0,this._serviceWorker.scriptURL.lastIndexOf("/")+1).slice(window.location.origin.length)}webtorrent/${this._torrent.infoHash}/${encodeURI(this.path)}`)}streamTo(e,t=(()=>{})){if("undefined"==typeof window)throw new Error("browser-only method");if(!this._serviceWorker)throw new Error("No worker registered");if("activated"!==this._serviceWorker.state)throw new Error("Worker isn't activated");const i=this._serviceWorker.scriptURL.substr(0,this._serviceWorker.scriptURL.lastIndexOf("/")+1).slice(window.location.origin.length);e.src=`${i}webtorrent/${this._torrent.infoHash}/${encodeURI(this.path)}`,t(null,e)}_getMimeType(){return a.mime[s.extname(this.name).toLowerCase()]}_destroy(){this._destroyed=!0,this._torrent=null;for(const e of this._fileStreams)e.destroy();this._fileStreams.clear()}}},{"./file-stream.js":489,"end-of-stream":191,events:193,mime:282,path:333,"queue-microtask":354,"range-parser":359,"render-media":377,stream:434,"stream-to-blob":469,"stream-to-blob-url":468,"stream-with-known-length-to-buffer":470}],491:[function(e,t,i){const n=e("events"),{Transform:r}=e("stream"),s=e("unordered-array-remove"),a=e("debug"),o=e("bittorrent-protocol"),c=a("webtorrent:peer");let l=!1;i.enableSecure=()=>{l=!0},i.createWebRTCPeer=(e,t,i)=>{const n=new d(e.id,"webrtc");if(n.conn=e,n.swarm=t,n.throttleGroups=i,n.conn.connected)n.onConnect();else{const e=()=>{n.conn.removeListener("connect",t),n.conn.removeListener("error",i)},t=()=>{e(),n.onConnect()},i=t=>{e(),n.destroy(t)};n.conn.once("connect",t),n.conn.once("error",i),n.startConnectTimeout()}return n},i.createTCPIncomingPeer=(e,t)=>u(e,"tcpIncoming",t),i.createUTPIncomingPeer=(e,t)=>u(e,"utpIncoming",t),i.createTCPOutgoingPeer=(e,t,i)=>p(e,t,"tcpOutgoing",i),i.createUTPOutgoingPeer=(e,t,i)=>p(e,t,"utpOutgoing",i);const u=(e,t,i)=>{const n=`${e.remoteAddress}:${e.remotePort}`,r=new d(n,t);return r.conn=e,r.addr=n,r.throttleGroups=i,r.onConnect(),r},p=(e,t,i,n)=>{const r=new d(e,i);return r.addr=e,r.swarm=t,r.throttleGroups=n,r};i.createWebSeedPeer=(e,t,i,n)=>{const r=new d(t,"webSeed");return r.swarm=i,r.conn=e,r.throttleGroups=n,r.onConnect(),r};class d extends n{constructor(e,t){super(),this.id=e,this.type=t,c("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.sentPe1=!1,this.sentPe2=!1,this.sentPe3=!1,this.sentPe4=!1,this.sentHandshake=!1}onConnect(){if(this.destroyed)return;this.connected=!0,c("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(this.type,this.retries,l);t.once("end",(()=>{this.destroy()})),t.once("close",(()=>{this.destroy()})),t.once("finish",(()=>{this.destroy()})),t.once("error",(e=>{this.destroy(e)})),t.once("pe1",(()=>{this.onPe1()})),t.once("pe2",(()=>{this.onPe2()})),t.once("pe3",(()=>{this.onPe3()})),t.once("pe4",(()=>{this.onPe4()})),t.once("handshake",((e,t)=>{this.onHandshake(e,t)})),this.startHandshakeTimeout(),this.setThrottlePipes(),this.swarm&&("tcpOutgoing"===this.type?l&&0===this.retries&&!this.sentPe1?this.sendPe1():this.sentHandshake||this.handshake():"tcpIncoming"===this.type||this.sentHandshake||this.handshake())}sendPe1(){this.wire.sendPe1(),this.sentPe1=!0}onPe1(){this.sendPe2()}sendPe2(){this.wire.sendPe2(),this.sentPe2=!0}onPe2(){this.sendPe3()}sendPe3(){this.wire.sendPe3(this.swarm.infoHash),this.sentPe3=!0}onPe3(e){this.swarm&&(this.swarm.infoHashHash!==e&&this.destroy(new Error("unexpected crypto handshake info hash for this swarm")),this.sendPe4())}sendPe4(){this.wire.sendPe4(this.swarm.infoHash),this.sentPe4=!0}onPe4(){this.sentHandshake||this.handshake()}clearPipes(){this.conn.unpipe(),this.wire.unpipe()}setThrottlePipes(){const e=this;this.conn.pipe(this.throttleGroups.down.throttle()).pipe(new r({transform(t,i,n){e.emit("download",t.length),e.destroyed||n(null,t)}})).pipe(this.wire).pipe(this.throttleGroups.up.throttle()).pipe(new r({transform(t,i,n){e.emit("upload",t.length),e.destroyed||n(null,t)}})).pipe(this.conn)}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"));c("Peer %s got handshake %s",this.id,e),clearTimeout(this.handshakeTimeout),this.retries=0;let i=this.addr;!i&&this.conn.remoteAddress&&this.conn.remotePort&&(i=`${this.conn.remoteAddress}:${this.conn.remotePort}`),this.swarm._onWire(this.wire,i),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,c("destroy %s %s (error: %s)",this.type,this.id,e&&(e.message||e)),clearTimeout(this.connectTimeout),clearTimeout(this.handshakeTimeout);const t=this.swarm,i=this.conn,n=this.wire;this.swarm=null,this.conn=null,this.wire=null,t&&n&&s(t.wires,t.wires.indexOf(n)),i&&(i.on("error",(()=>{})),i.destroy()),n&&n.destroy(),t&&t.removePeer(this.id)}}},{"bittorrent-protocol":28,debug:161,events:193,stream:434,"unordered-array-remove":481}],492:[function(e,t,i){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=[],i=1/0;for(let n=0;n{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)}))):E.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._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&&n.WEBTORRENT_ANNOUNCE&&!e.private&&(e.announce=e.announce.concat(n.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=E.toMagnetURI(e),this.torrentFile=E.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:()=>{if(this.destroyed)return;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 m({infoHash:this.infoHash,announce:this.announce,peerId:this.client.peerId,dht:!this.private&&this.client.dht,tracker:e,port:this.client.torrentPort,userAgent:W,lsd:this.client.lsd}),this.discovery.on("error",(e=>{this._destroy(e)})),this.discovery.on("peer",((e,t)=>{this._debug("peer %s discovered via %s",e,t),"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=>i=>{!function(t,i){if(0!==t.indexOf("http://")&&0!==t.indexOf("https://"))return e.emit("warning",new Error(`skipping non-http xs param: ${t}`)),i(null);const n={url:t,method:"GET",headers:{"user-agent":W}};let r;try{r=v.concat(n,s)}catch(n){return e.emit("warning",new Error(`skipping invalid url xs param: ${t}`)),i(null)}function s(n,r,s){if(e.destroyed)return i(null);if(e.metadata)return i(null);if(n)return e.emit("warning",new Error(`http error from xs param: ${t}`)),i(null);if(200!==r.statusCode)return e.emit("warning",new Error(`non-200 status code ${r.statusCode} from xs param: ${t}`)),i(null);let a;try{a=E(s)}catch(n){}return a?a.infoHash!==e.infoHash?(e.emit("warning",new Error(`got torrent file with incorrect info hash from xs param: ${t}`)),i(null)):(e._onMetadata(a),void i(null)):(e.emit("warning",new Error(`got invalid torrent file from xs param: ${t}`)),i(null))}e._xsRequests.push(r)}(t,i)}));w(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=E(e)}catch(e){return this._destroy(e)}this._processParsedTorrent(t),this.metadata=this.torrentFile,this.client.enableWebSeeds&&this.urlList.forEach((e=>{this.addWebSeed(e)})),this._rarityMap=new O(this),this.files=this.files.map((e=>new R(this,e)));let i=this._preloadedStore;if(i||(i=new this._store(this.pieceLength,{...this.storeOpts,torrent:this,path:this.path,files:this.files,length:this.length,name:this.name+" - "+this.infoHash.slice(0,8),addUID:this.addUID})),this._storeCacheSlots>0&&!(i instanceof _)&&(i=new p(i,{max:this._storeCacheSlots})),this.store=new g(i),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 i=t===this.pieces.length-1?this.lastPieceLength:this.pieceLength;return new S(i)})),this._reservations=this.pieces.map((()=>[])),this.bitfield=new u(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===b?this.getFileModtimes(((t,i)=>{if(t)return this._destroy(t);this.files.map(((e,t)=>i[t]===this._fileModtimes[t])).every((e=>e))?(this._markAllVerified(),this._onStore()):this._verifyPieces(e)})):this._verifyPieces(e)}}getFileModtimes(e){const t=[];k(this.files.map(((e,i)=>n=>{const r=this.addUID?c.join(this.name+" - "+this.infoHash.slice(0,8)):c.join(this.path,e.path);s.stat(r,((e,r)=>{if(e&&"ENOENT"!==e.code)return n(e);t[i]=r&&r.mtime.getTime(),n(null)}))})),H,(i=>{this._debug("done getting file modtimes"),e(i,t)}))}_verifyPieces(e){k(this.pieces.map(((e,t)=>e=>{if(this.destroyed)return e(new Error("torrent is destroyed"));const i={};t===this.pieces.length-1&&(i.length=this.lastPieceLength),this.store.get(t,i,((i,n)=>this.destroyed?e(new Error("torrent is destroyed")):i?A((()=>e(null))):void I(n,(i=>{if(this.destroyed)return e(new Error("torrent is destroyed"));i===this._hashes[t]?(this._debug("piece verified %s",t),this._markVerified(t)):this._debug("piece invalid %s",t),e(null)}))))})),H,e)}rescanFiles(e){if(this.destroyed)throw new Error("torrent is destroyed");e||(e=$),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 R&&e._destroy()}));const n=this._servers.map((e=>t=>{e.destroy(t)}));if(this.discovery&&n.push((e=>{this.discovery.destroy(e)})),this.store){let e=this._destroyStoreOnDestroy;t&&void 0!==t.destroyStore&&(e=t.destroyStore),n.push((t=>{e?this.store.destroy(t):this.store.close(t)}))}w(n,i),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");let t;if(this.client.blocked){if("string"==typeof e){let i;try{i=l(e)}catch(t){return this._debug("ignoring peer: invalid %s",e),this.emit("invalidPeer",e),!1}t=i[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 i=this.client.utp&&this._isIPv4(t)?"utp":"tcp",n=!!this._addPeer(e,i);return n?this.emit("peer",e):this.emit("invalidPeer",e),n}_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 i=e&&e.id||e;if(this._peers[i])return this._debug("ignoring peer: duplicate (%s)",i),"string"!=typeof e&&e.destroy(),null;if(this.paused)return this._debug("ignoring peer: torrent is paused"),"string"!=typeof e&&e.destroy(),null;let n;return this._debug("add peer %s",i),n="string"==typeof e?"utp"===t?L.createUTPOutgoingPeer(e,this,this.client.throttleGroups):L.createTCPOutgoingPeer(e,this,this.client.throttleGroups):L.createWebRTCPeer(e,this,this.client.throttleGroups),this._registerPeer(n),"string"==typeof e&&(this._queue.push(n),this._drain()),n}addWebSeed(e){if(this.destroyed)throw new Error("torrent is destroyed");let t,i;if("string"==typeof e){if(t=e,!/^https?:\/\/.+/.test(t))return this.emit("warning",new Error(`ignoring invalid web seed: ${t}`)),void this.emit("invalidPeer",t);if(this._peers[t])return this.emit("warning",new Error(`ignoring duplicate web seed: ${t}`)),void this.emit("invalidPeer",t);i=new q(t,this)}else{if(!e||"string"!=typeof e.connId)return void this.emit("warning",new Error("addWebSeed must be passed a string or connection object with id property"));if(i=e,t=i.connId,this._peers[t])return this.emit("warning",new Error(`ignoring duplicate web seed: ${t}`)),void this.emit("invalidPeer",t)}this._debug("add web seed %s",t);const n=L.createWebSeedPeer(i,t,this,this.client.throttleGroups);this._registerPeer(n),this.emit("peer",t)}_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),void this._registerPeer(e))}_registerPeer(e){e.on("download",(e=>{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._peers[e.id]=e,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,i,n){if(this.destroyed)throw new Error("torrent is destroyed");if(e<0||tt.priority-e.priority)),this._updateSelections()}deselect(e,t,i){if(this.destroyed)throw new Error("torrent is destroyed");i=Number(i)||0,this._debug("deselect %s-%s (priority %s)",e,t,i);for(let n=0;n{if(!this.destroyed&&!this.client.dht.destroyed){if(!e.remoteAddress)return this._debug("ignoring PORT from peer with no address");if(0===i||i>65536)return this._debug("ignoring invalid PORT from peer");this._debug("port: %s (from %s)",i,t),this.client.dht.addNode({host:e.remoteAddress,port:i})}})),e.on("timeout",(()=>{this._debug("wire timeout (%s)",t),e.destroy()})),"webSeed"!==e.type&&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 B||this.private||(e.use(B()),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 i=this._peers[e];i&&!i.connected&&(this._debug("ut_pex: dropped peer: %s (from %s)",e,t),this.removePeer(e))})),e.once("close",(()=>{e.ut_pex.reset()}))),e.use(y()),this.emit("wire",e,t),this.metadata&&A((()=>{this._onWireWithMetadata(e)}))}_onWireWithMetadata(e){let t=null;const i=()=>{this.destroyed||e.destroyed||(this._numQueued>2*(this._numConns-this.numPeers)&&e.amInterested?e.destroy():(t=setTimeout(i,D),t.unref&&t.unref()))};let n;const r=()=>{if(e.peerPieces.buffer.length===this.bitfield.buffer.length){for(n=0;n{r(),this._update(),this._updateWireInterest(e)})),e.on("have",(()=>{r(),this._update(),this._updateWireInterest(e)})),e.lt_donthave.on("donthave",(()=>{r(),this._update(),this._updateWireInterest(e)})),e.once("interested",(()=>{e.unchoke()})),e.once("close",(()=>{clearTimeout(t)})),e.on("choke",(()=>{clearTimeout(t),t=setTimeout(i,D),t.unref&&t.unref()})),e.on("unchoke",(()=>{clearTimeout(t),this._update()})),e.on("request",((t,i,n,r)=>{if(n>131072)return e.destroy();this.pieces[t]||this.store.get(t,{offset:i,length:n},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(i,D),t.unref&&t.unref()),e.isSeeder=!1,r()}_updateSelections(){this.ready&&!this.destroyed&&(A((()=>{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 i=0;i{t._updateWire(e)}),{timeout:250}):t._updateWire(e)}_updateWire(e){const t=this;if(e.peerChoking)return;if(!e.downloaded)return function(){if(e.requests.length)return;let i=t._selections.length;for(;i--;){const n=t._selections[i];let s;if("rarest"===t.strategy){const i=n.from+n.offset,a=n.to,o=a-i+1,c={};let l=0;const u=r(i,a,c);for(;l=n.from+n.offset;--s)if(e.peerPieces.get(s)&&t._request(e,s,!1))return}}();const i=V(e,.5);if(e.requests.length>=i)return;const n=V(e,1);function r(t,i,n,r){return s=>s>=t&&s<=i&&!(s in n)&&e.peerPieces.get(s)&&(!r||r(s))}function s(e){let i=e;for(let n=e;n=n)return!0;const a=function(){const i=e.downloadSpeed()||1;if(i>z)return()=>!0;const n=Math.max(1,e.requests.length)*S.BLOCK_LENGTH/i;let r=10,s=0;return e=>{if(!r||t.bitfield.get(e))return!0;let a=t.pieces[e].missing;for(;s0))return r--,!1}return!0}}();for(let o=0;o({wire:e,random:Math.random()}))).sort(((e,t)=>{const i=e.wire,n=t.wire;return i.downloadSpeed()!==n.downloadSpeed()?i.downloadSpeed()-n.downloadSpeed():i.uploadSpeed()!==n.uploadSpeed()?i.uploadSpeed()-n.uploadSpeed():i.amChoking!==n.amChoking?i.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[(i=t.length,Math.random()*i|0)];e.unchoke(),this._rechokeOptimisticWire=e,this._rechokeOptimisticTime=2}}var i;e.filter((e=>e!==this._rechokeOptimisticWire)).forEach((e=>e.choke()))}_hotswap(e,t){const i=e.downloadSpeed();if(i=z||(2*o>i||o>a||(r=t,a=o))}if(!r)return!1;for(s=0;s=a)return!1;const o=n.pieces[t];let c=s?o.reserveRemaining():o.reserve();if(-1===c&&i&&n._hotswap(e,t)&&(c=s?o.reserveRemaining():o.reserve()),-1===c)return!1;let l=n._reservations[t];l||(l=n._reservations[t]=[]);let u=l.indexOf(null);-1===u&&(u=l.length),l[u]=e;const p=o.chunkOffset(c),d=s?o.chunkLengthRemaining(c):o.chunkLength(c);function f(){A((()=>{n._update()}))}return e.request(t,p,d,(function i(r,a){if(n.destroyed)return;if(!n.ready)return n.once("ready",(()=>{i(r,a)}));if(l[u]===e&&(l[u]=null),o!==n.pieces[t])return f();if(r)return n._debug("error getting piece %s (offset: %s length: %s) from %s: %s",t,p,d,`${e.remoteAddress}:${e.remotePort}`,r.message),s?o.cancelRemaining(c):o.cancel(c),void f();if(n._debug("got piece %s (offset: %s length: %s) from %s",t,p,d,`${e.remoteAddress}:${e.remotePort}`),!o.set(c,a,e))return f();const h=o.flush();I(h,(e=>{n.destroyed||(e===n._hashes[t]?(n._debug("piece verified %s",t),n.store.put(t,h,(e=>{e?n._destroy(e):(n.pieces[t]=null,n._markVerified(t),n.wires.forEach((e=>{e.have(t)})),n._checkDone()&&!n.destroyed&&n.discovery.complete(),f())}))):(n.pieces[t]=new S(o.length),n.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(const t of this._selections){for(let i=t.from;i<=t.to;i++)if(!this.bitfield.get(i)){e=!1;break}if(!e)break}return!this.done&&e?(this.done=!0,this._debug(`torrent done: ${this.infoHash}`),this.emit("done")):this.done=!1,this._gcSelections(),e}load(e,t){if(this.destroyed)throw new Error("torrent is destroyed");if(!this.ready)return this.once("ready",(()=>{this.load(e,t)}));Array.isArray(e)||(e=[e]),t||(t=$);const i=new x(e),n=new d(this.store,this.pieceLength);M(i,n,(e=>{if(e)return t(e);this._markAllVerified(),this._checkDone(),t(null)}))}createServer(e){if("function"!=typeof P)throw new Error("node.js-only method");if(this.destroyed)throw new Error("torrent is destroyed");const t=new P(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]}`,N(...e)}_drain(){if(this._debug("_drain numConns %s maxConns %s",this._numConns,this.client.maxConns),"function"!=typeof a.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=l(e.addr),i={host:t[0],port:t[1]};this.client.utp&&"utpOutgoing"===e.type?e.conn=U.connect(i.port,i.host):e.conn=a.connect(i);const n=e.conn;n.once("connect",(()=>{e.onConnect()})),n.once("error",(t=>{e.destroy(t)})),e.startConnectTimeout(),n.on("close",(()=>{if(this.destroyed)return;if(e.retries>=F.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,F.length);return}const t=F[e.retries];this._debug("conn %s closed: will re-add to queue in %sms (attempt %s)",e.addr,t,e.retries+1);const i=setTimeout((()=>{if(this.destroyed)return;const t=l(e.addr)[0],i=this.client.utp&&this._isIPv4(t)?"utp":"tcp",n=this._addPeer(e.addr,i);n&&(n.retries=e.retries+1)}),t);i.unref&&i.unref()}))}_validAddr(e){let t;try{t=l(e)}catch(e){return!1}const i=t[0],n=t[1];return n>0&&n<65535&&!("127.0.0.1"===i&&n===this.client.torrentPort)}_isIPv4(e){return/^((?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])[.]){3}(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])$/.test(e)}}}).call(this)}).call(this,e("_process"),"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"../package.json":495,"./file.js":490,"./peer.js":491,"./rarity-map.js":492,"./server.js":67,"./utp.js":67,"./webconn.js":494,_process:341,"addr-to-ip-port":3,bitfield:27,"cache-chunk-store":117,"chunk-store-stream/write":133,cpus:137,debug:161,events:193,fs:67,"fs-chunk-store":275,"immediate-chunk-store":245,lt_donthave:256,"memory-chunk-store":275,multistream:309,net:67,os:67,"parse-torrent":332,path:333,pump:349,"queue-microtask":354,"random-iterate":356,"run-parallel":381,"run-parallel-limit":380,"simple-get":394,"simple-sha1":411,speedometer:433,"torrent-discovery":477,"torrent-piece":478,ut_metadata:484,ut_pex:67}],494:[function(e,t,i){(function(i){(function(){const{default:n}=e("bitfield"),r=e("debug"),s=e("simple-get"),a=e("lt_donthave"),o=e("simple-sha1"),c=e("bittorrent-protocol"),l=r("webtorrent:webconn"),u=e("../package.json").version;t.exports=class extends c{constructor(e,t){super(),this.url=e,this.connId=e,this.webPeerId=o.sync(e),this._torrent=t,this._init()}_init(){this.setKeepAlive(!0),this.use(a()),this.once("handshake",((e,t)=>{if(this.destroyed)return;this.handshake(e,this.webPeerId);const i=this._torrent.pieces.length,r=new n(i);for(let e=0;e<=i;e++)r.set(e,!0);this.bitfield(r)})),this.once("interested",(()=>{l("interested"),this.unchoke()})),this.on("uninterested",(()=>{l("uninterested")})),this.on("choke",(()=>{l("choke")})),this.on("unchoke",(()=>{l("unchoke")})),this.on("bitfield",(()=>{l("bitfield")})),this.lt_donthave.on("donthave",(()=>{l("donthave")})),this.on("request",((e,t,i,n)=>{l("request pieceIndex=%d offset=%d length=%d",e,t,i),this.httpRequest(e,t,i,((t,i)=>{if(t){this.lt_donthave.donthave(e);const t=setTimeout((()=>{this.destroyed||this.have(e)}),1e4);t.unref&&t.unref()}n(t,i)}))}))}httpRequest(e,t,n,r){const a=e*this._torrent.pieceLength+t,o=a+n-1,c=this._torrent.files;let p;if(c.length<=1)p=[{url:this.url,start:a,end:o}];else{const e=c.filter((e=>e.offset<=o&&e.offset+e.length>a));if(e.length<1)return r(new Error("Could not find file corresponding to web seed range request"));p=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,o-e.offset)}}))}let d,f=0,h=!1;p.length>1&&(d=i.alloc(n)),p.forEach((i=>{const a=i.url,o=i.start,c=i.end;l("Requesting url=%s pieceIndex=%d offset=%d length=%d start=%d end=%d",a,e,t,n,o,c);const m={url:a,method:"GET",headers:{"user-agent":`WebTorrent/${u} (https://webtorrent.io)`,range:`bytes=${o}-${c}`},timeout:6e4};function b(e,t){if(e.statusCode<200||e.statusCode>=300){if(h)return;return h=!0,r(new Error(`Unexpected HTTP status code ${e.statusCode}`))}l("Got data of length %d",t.length),1===p.length?r(null,t):(t.copy(d,i.fileOffsetInRange),++f===p.length&&r(null,d))}s.concat(m,((e,t,i)=>{if(!h)return e?"undefined"==typeof window||a.startsWith(`${window.location.origin}/`)?(h=!0,r(e)):s.head(a,((t,i)=>{if(!h){if(t)return h=!0,r(t);if(i.statusCode<200||i.statusCode>=300)return h=!0,r(new Error(`Unexpected HTTP status code ${i.statusCode}`));if(i.url===a)return h=!0,r(e);m.url=i.url,s.concat(m,((e,t,i)=>{if(!h)return e?(h=!0,r(e)):void b(t,i)}))}})):void b(t,i)}))}))}destroy(){super.destroy(),this._torrent=null}}}).call(this)}).call(this,e("buffer").Buffer)},{"../package.json":495,bitfield:27,"bittorrent-protocol":28,buffer:110,debug:161,lt_donthave:256,"simple-get":394,"simple-sha1":411}],495:[function(e,t,i){t.exports={version:"1.5.8"}},{}],496:[function(e,t,i){t.exports=function e(t,i){if(t&&i)return e(t)(i);if("function"!=typeof t)throw new TypeError("need wrapper function");return Object.keys(t).forEach((function(e){n[e]=t[e]})),n;function n(){for(var e=new Array(arguments.length),i=0;i1080?(q.setProps({placement:"right"}),N.setProps({placement:"right"}),D.setProps({placement:"right"})):(q.setProps({placement:"top"}),N.setProps({placement:"top"}),D.setProps({placement:"top"}))}function W(e){Y();try{console.info("Attempting parse"),p=r(e),V(),p.xs&&(console.info("Magnet includes xs, attempting remote parse"),K(p.xs))}catch(t){console.warn(t),"magnet"==u?(console.info("Attempting remote parse"),K(e)):(H.error("Problem parsing input. Is this a .torrent file?"),console.error("Problem parsing input"))}}function K(e){r.remote(e,(function(e,t){if(e)return H.error("Problem remotely fetching that file or parsing result"),console.warn(e),void Y();u="remote-torrent-file",v.innerHTML='',g.setContent("Currently loaded information sourced from remotely fetched Torrent file"),p=t,V()}))}function V(){if(console.log(p),E.value=p.infoHash,y.value=p.name?p.name:"",p.created?(x.value=p.created.toISOString().slice(0,19),x.type="datetime-local"):x.type="text",w.value=p.createdBy?"by "+p.createdBy:"",k.value=p.comment?p.comment:"",j.innerHTML="",p.announce&&p.announce.length)for(let e=0;e',n.addEventListener("click",Q),t.appendChild(n),j.appendChild(t)}if(I.innerHTML="",p.urlList&&p.urlList.length)for(let e=0;e',n.addEventListener("click",Q),t.appendChild(n),I.appendChild(t)}if(B.innerHTML="",p.files&&p.files.length){if(R.style.display="none",p.files.length<100)for(let e of p.files){let t=G(o.lookup(e.name));B.appendChild($(t,e.name,e.length))}else{for(let e=0;e<100;e++){let t=G(o.lookup(p.files[e].name));B.appendChild($(t,p.files[e].name,p.files[e].length))}B.appendChild($("","...and another "+(p.files.length-100)+" more files",""))}B.appendChild($("folder-tree","",p.length)),D.setContent("Download Torrent file"),U.addEventListener("click",ne),U.disabled=!1}else z.torrents.length>0?(R.style.display="none",B.innerHTML=''):(R.style.display="block",B.innerHTML=''),D.setContent("Files metadata is required to generate a Torrent file. Try fetching files list from WebTorrent."),U.removeEventListener("click",ne),U.disabled=!0;L.setAttribute("data-clipboard-text",window.location.origin+"#"+r.toMagnetURI(p)),O.setAttribute("data-clipboard-text",r.toMagnetURI(p)),d.style.display="none",b.style.display="flex",window.location.hash=r.toMagnetURI(p),p.name?document.title="Torrent Parts | "+p.name:document.title="Torrent Parts | Inspect and edit what's in your Torrent file or Magnet link",g.enable(),gtag("event","view_item",{items:[{item_id:p.infoHash,item_name:p.name,item_category:u}]})}function $(e,t,i){let n=document.createElement("tr"),r=document.createElement("td");e&&(r.innerHTML=''),n.appendChild(r);let s=document.createElement("td");s.innerHTML=t,n.appendChild(s);let o=document.createElement("td");return o.innerHTML=a.format(i,{decimalPlaces:1,unitSeparator:" "}),n.appendChild(o),n}function G(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"):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 X(e){this.dataset.group?p[this.dataset.group][this.dataset.index]=this.value?this.value:"":p[this.id]=this.value?this.value:"",window.location.hash=r.toMagnetURI(p),te()}function Y(){document.getElementById("magnet").value="",document.getElementById("torrent").value="",d.style.display="flex",b.style.display="none",y.value="",x.value="",w.value="",k.value="",E.value="",j.innerHTML="",I.innerHTML="",z.torrents.forEach((e=>e.destroy())),R.style.display="block",B.innerHTML="",window.location.hash="",L.setAttribute("data-clipboard-text",""),O.setAttribute("data-clipboard-text",""),document.title="Torrent Parts | Inspect and edit what's in your Torrent file or Magnet link",g.disable(),gtag("event","reset")}async function Z(){S.className="disabled",S.innerHTML="Adding...";try{let e=await fetch("https://newtrackon.com/api/stable"),t=await e.text();p.announce=p.announce.concat(t.split("\n\n")),p.announce.push("http://bt1.archive.org:6969/announce"),p.announce.push("http://bt2.archive.org:6969/announce"),p.announce=p.announce.filter(((e,t)=>e&&p.announce.indexOf(e)===t)),H.success("Added known working trackers from newTrackon"),te()}catch(e){H.error("Problem fetching trackers from newTrackon"),console.warn(e)}S.className="",S.innerHTML="Add Known Working Trackers",V(),gtag("event","add_trackers")}function J(){p[this.dataset.type].unshift(""),V()}function Q(){p[this.parentElement.className].splice(this.parentElement.dataset.index,1),V()}function ee(e){p[e]=[],te(),V()}function te(){p.created=new Date,p.createdBy="Torrent Parts ",p.created?(x.value=p.created.toISOString().slice(0,19),x.type="datetime-local"):x.type="text",w.value=p.createdBy?"by "+p.createdBy:""}function ie(){console.info("Attempting fetching files from Webtorrent..."),R.style.display="none",p.announce.push("wss://tracker.webtorrent.io"),p.announce.push("wss://tracker.openwebtorrent.com"),p.announce.push("wss://tracker.btorrent.xyz"),p.announce.push("wss://tracker.fastcast.nz"),p.announce=p.announce.filter(((e,t)=>e&&p.announce.indexOf(e)===t)),z.add(r.toMagnetURI(p),(e=>{p.info=Object.assign({},e.info),p.files=e.files,p.infoBuffer=e.infoBuffer,p.length=e.length,p.lastPieceLength=e.lastPieceLength,te(),V(),H.success("Fetched file details from Webtorrent peers"),e.destroy()})),V(),gtag("event","attempt_webtorrent_fetch")}function ne(){let e=r.toTorrentFile(p);if(null!==e&&navigator.msSaveBlob)return navigator.msSaveBlob(new Blob([e],{type:"application/x-bittorrent"}),p.name+".torrent");let t=document.createElement("a");t.style.display="none";let i=window.URL.createObjectURL(new Blob([e],{type:"application/x-bittorrent"}));t.setAttribute("href",i),t.setAttribute("download",p.name+".torrent"),document.body.appendChild(t),t.click(),window.URL.revokeObjectURL(i),t.remove(),gtag("event","share",{method:"Torrent Download",content_id:p.name})}window.addEventListener("resize",F),F(),document.addEventListener("DOMContentLoaded",(function(){document.getElementById("magnet").addEventListener("keyup",(function(e){e.preventDefault(),"Enter"===e.key&&(u="magnet",v.innerHTML='',g.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){u="torrent-file",v.innerHTML='',g.setContent("Currently loaded information sourced from Torrent file"),W(s.from(e))}))})),document.addEventListener("dragover",(function(e){e.preventDefault()})),document.addEventListener("drop",(function(e){e.preventDefault(),e.dataTransfer.items[0].getAsFile().arrayBuffer().then((function(e){u="torrent-file",v.innerHTML='',g.setContent("Currently loaded information sourced from Torrent file"),W(s.from(e))}))})),f.addEventListener("click",(function(e){e.preventDefault(),H.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(),H.success("Fetching and Parsing “The WIRED CD” Torrent File..."),K("https://webtorrent.io/torrents/wired-cd.torrent")})),m.addEventListener("click",(async function(e){e.preventDefault(),H.success("Parsing Jack Johnson Archive.org Torrent File");let t=await fetch("/ext/jj2008-06-14.mk4_archive.torrent"),i=await t.arrayBuffer();W(s.from(i))}));let e=new n("#copyURL");e.on("success",(function(e){H.success("Copied site URL to clipboard!"),console.info(e),gtag("event","share",{method:"Copy URL",content_id:e.text})})),e.on("failure",(function(e){H.error("Problem copying to clipboard"),console.warn(e)}));let t=new n("#copyMagnet");t.on("success",(function(e){H.success("Copied Magnet URL to clipboard!"),gtag("event","share",{method:"Copy Magnet",content_id:e.text})})),t.on("failure",(function(e){H.error("Problem copying to clipboard"),console.warn(e)})),y.addEventListener("input",X),y.addEventListener("change",X),y.addEventListener("reset",X),y.addEventListener("paste",X),_.addEventListener("click",Y),k.addEventListener("input",X),k.addEventListener("change",X),k.addEventListener("reset",X),k.addEventListener("paste",X),S.addEventListener("click",Z),M.addEventListener("click",J),A.addEventListener("click",(()=>ee("announce"))),T.addEventListener("click",J),C.addEventListener("click",(()=>ee("urlList"))),R.addEventListener("click",ie),l("[data-tippy-content]",{theme:"torrent-parts",animation:"shift-away-subtle"}),g.disable(),window.location.hash&&(u="shared-url",v.innerHTML='',g.setContent("Currently loaded information sourced from shared torrent.parts link"),W(window.location.hash.split("#")[1]))}))},{Buffer:2,bytes:116,clipboard:135,"mime-types":280,"parse-torrent":332,"tippy.js":475,webtorrent:488}]},{},[498]); \ No newline at end of file +const n=e("events"),r=e("path"),s=e("simple-concat"),a=e("create-torrent"),o=e("debug"),c=e("bittorrent-dht/client"),l=e("load-ip-set"),u=e("run-parallel"),p=e("parse-torrent"),d=e("simple-peer"),f=e("queue-microtask"),h=e("randombytes"),m=e("simple-sha1"),b=e("speedometer"),{ThrottleGroup:v}=e("speed-limiter"),g=e("./lib/conn-pool.js"),y=e("./lib/torrent.js"),{version:_}=e("./package.json"),x=o("webtorrent"),w=_.replace(/\d*./g,(e=>("0"+e%100).slice(-2))).slice(0,4),k=`-WW${w}-`;class E extends n{constructor(t={}){super(),"string"==typeof t.peerId?this.peerId=t.peerId:i.isBuffer(t.peerId)?this.peerId=t.peerId.toString("hex"):this.peerId=i.from(k+h(9).toString("base64")).toString("hex"),this.peerIdBuffer=i.from(this.peerId,"hex"),"string"==typeof t.nodeId?this.nodeId=t.nodeId:i.isBuffer(t.nodeId)?this.nodeId=t.nodeId.toString("hex"):this.nodeId=h(20).toString("hex"),this.nodeIdBuffer=i.from(this.nodeId,"hex"),this._debugId=this.peerId.toString("hex").substring(0,7),this.destroyed=!1,this.listening=!1,this.torrentPort=t.torrentPort||0,this.dhtPort=t.dhtPort||0,this.tracker=void 0!==t.tracker?t.tracker:{},this.lsd=!1!==t.lsd,this.torrents=[],this.maxConns=Number(t.maxConns)||55,this.utp=E.UTP_SUPPORT&&!1!==t.utp,this._downloadLimit=Math.max("number"==typeof t.downloadLimit?t.downloadLimit:-1,-1),this._uploadLimit=Math.max("number"==typeof t.uploadLimit?t.uploadLimit:-1,-1),this.serviceWorker=null,this.workerKeepAliveInterval=null,this.workerPortCount=0,!0===t.secure&&e("./lib/peer").enableSecure(),this._debug("new webtorrent (peerId %s, nodeId %s, port %s)",this.peerId,this.nodeId,this.torrentPort),this.throttleGroups={down:new v({rate:Math.max(this._downloadLimit,0),enabled:this._downloadLimit>=0}),up:new v({rate:Math.max(this._uploadLimit,0),enabled:this._uploadLimit>=0})},this.tracker&&("object"!=typeof this.tracker&&(this.tracker={}),globalThis.WRTC&&!this.tracker.wrtc&&(this.tracker.wrtc=globalThis.WRTC)),"function"==typeof g?this._connPool=new g(this):f((()=>{this._onListening()})),this._downloadSpeed=b(),this._uploadSpeed=b(),!1!==t.dht&&"function"==typeof c?(this.dht=new c(Object.assign({},{nodeId:this.nodeId},t.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!==t.webSeeds;const n=()=>{this.destroyed||(this.ready=!0,this.emit("ready"))};"function"==typeof l&&null!=t.blocklist?l(t.blocklist,{headers:{"user-agent":`WebTorrent/${_} (https://webtorrent.io)`}},((e,t)=>{if(e)return console.error(`Failed to load blocklist: ${e.message}`);this.blocked=t,n()})):f(n)}loadWorker(e,t=(()=>{})){if(!(e instanceof ServiceWorker))throw new Error("Invalid worker registration");if("activated"!==e.state)throw new Error("Worker isn't activated");this.serviceWorker=e,navigator.serviceWorker.addEventListener("message",(e=>{const{data:t}=e;if(!t.type||"webtorrent"===!t.type||!t.url)return null;let[i,...n]=t.url.slice(t.url.indexOf(t.scope+"webtorrent/")+11+t.scope.length).split("/");if(n=decodeURI(n.join("/")),!i||!n)return null;const[r]=e.ports,s=this.get(i)&&this.get(i).files.find((e=>e.path===n));if(!s)return null;const[a,o,c]=s._serve(t),l=o&&o[Symbol.asyncIterator](),u=()=>{r.onmessage=null,o&&o.destroy(),c&&c.destroy(),this.workerPortCount--,this.workerPortCount||(clearInterval(this.workerKeepAliveInterval),this.workerKeepAliveInterval=null)};r.onmessage=async e=>{if(e.data){let e;try{e=(await l.next()).value}catch(e){}r.postMessage(e),e||u(),this.workerKeepAliveInterval||(this.workerKeepAliveInterval=setInterval((()=>fetch(`${this.serviceWorker.scriptURL.substr(0,this.serviceWorker.scriptURL.lastIndexOf("/")+1).slice(window.location.origin.length)}webtorrent/keepalive/`)),2e4))}else u()},this.workerPortCount++,r.postMessage(a)})),t(this.serviceWorker)}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 y){if(this.torrents.includes(e))return e}else{let t;try{t=p(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}add(e,t={},i=(()=>{})){if(this.destroyed)throw new Error("client is destroyed");"function"==typeof t&&([t,i]=[{},t]);const n=()=>{if(!this.destroyed)for(const e of this.torrents)if(e.infoHash===s.infoHash&&e!==s)return void s._destroy(new Error(`Cannot add duplicate torrent ${s.infoHash}`))},r=()=>{this.destroyed||(i(s),this.emit("torrent",s))};this._debug("add"),t=t?Object.assign({},t):{};const s=new y(e,this,t);return this.torrents.push(s),s.once("_infoHash",n),s.once("ready",r),s.once("close",(function e(){s.removeListener("_infoHash",n),s.removeListener("ready",r),s.removeListener("close",e)})),s}seed(e,t,i){if(this.destroyed)throw new Error("client is destroyed");"function"==typeof t&&([t,i]=[{},t]),this._debug("seed"),(t=t?Object.assign({},t):{}).skipVerify=!0;const n="string"==typeof e;n&&(t.path=r.dirname(e)),t.createdBy||(t.createdBy=`WebTorrent/${w}`);const o=e=>{this._debug("on seed"),"function"==typeof i&&i(e),e.emit("seed"),this.emit("seed",e)},c=this.add(null,t,(e=>{const i=[i=>{if(n||t.preloadedStore)return i();e.load(l,i)}];this.dht&&i.push((t=>{e.once("dhtAnnounce",t)})),u(i,(t=>{if(!this.destroyed)return t?e._destroy(t):void o(e)}))}));let l;var p;return p=e,"undefined"!=typeof FileList&&p instanceof FileList?e=Array.from(e):Array.isArray(e)||(e=[e]),u(e.map((e=>i=>{!t.preloadedStore&&function(e){return"object"==typeof e&&null!=e&&"function"==typeof e.pipe}(e)?s(e,((t,n)=>{if(t)return i(t);n.name=e.name,i(null,n)})):i(null,e)})),((e,i)=>{if(!this.destroyed)return e?c._destroy(e):void a.parseInput(i,t,((e,n)=>{if(!this.destroyed){if(e)return c._destroy(e);l=n.map((e=>e.getStream)),a(i,t,((e,t)=>{if(this.destroyed)return;if(e)return c._destroy(e);const i=this.get(t);i?c._destroy(new Error(`Cannot add duplicate torrent ${i.infoHash}`)):c._onTorrentId(t)}))}}))})),c}remove(e,t,i){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,i)}_remove(e,t,i){if("function"==typeof t)return this._remove(e,null,t);const n=this.get(e);n&&(this.torrents.splice(this.torrents.indexOf(n),1),n.destroy(t,i),this.dht&&this.dht._tables.remove(n.infoHash))}address(){return this.listening?this._connPool?this._connPool.tcpServer.address():{address:"0.0.0.0",family:"IPv4",port:0}:null}throttleDownload(e){return e=Number(e),!(isNaN(e)||!isFinite(e)||e<-1)&&(this._downloadLimit=e,this._downloadLimit<0?this.throttleGroups.down.setEnabled(!1):(this.throttleGroups.down.setEnabled(!0),void this.throttleGroups.down.setRate(this._downloadLimit)))}throttleUpload(e){return e=Number(e),!(isNaN(e)||!isFinite(e)||e<-1)&&(this._uploadLimit=e,this._uploadLimit<0?this.throttleGroups.up.setEnabled(!1):(this.throttleGroups.up.setEnabled(!0),void this.throttleGroups.up.setRate(this._uploadLimit)))}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 i=this.torrents.map((e=>t=>{e.destroy(t)}));this._connPool&&i.push((e=>{this._connPool.destroy(e)})),this.dht&&i.push((e=>{this.dht.destroy(e)})),u(i,t),e&&this.emit("error",e),this.torrents=[],this._connPool=null,this.dht=null,this.throttleGroups.down.destroy(),this.throttleGroups.up.destroy()}_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]}`,x(...e)}_getByHash(e){for(const t of this.torrents)if(t.infoHashHash||(t.infoHashHash=m.sync(i.from("72657132"+t.infoHash,"hex"))),e===t.infoHashHash)return t;return null}}E.WEBRTC_SUPPORT=d.WEBRTC_SUPPORT,E.UTP_SUPPORT=g.UTP_SUPPORT,E.VERSION=_,t.exports=E}).call(this)}).call(this,e("buffer").Buffer)},{"./lib/conn-pool.js":67,"./lib/peer":491,"./lib/torrent.js":493,"./package.json":495,"bittorrent-dht/client":67,buffer:110,"create-torrent":144,debug:161,events:193,"load-ip-set":67,"parse-torrent":332,path:333,"queue-microtask":354,randombytes:357,"run-parallel":381,"simple-concat":393,"simple-peer":395,"simple-sha1":411,"speed-limiter":429,speedometer:433}],489:[function(e,t,i){const n=e("stream"),r=e("debug"),s=e("end-of-stream"),a=r("webtorrent:file-stream");class o extends n.Readable{constructor(e,t){super(t),this._torrent=e._torrent;const i=t&&t.start||0,n=t&&t.end&&t.end{this._notify()})),s(this,(e=>{this.destroy(e)}))}_read(){this._reading||(this._reading=!0,this._notify())}_notify(){if(!this._reading||0===this._missing)return;if(!this._torrent.bitfield.get(this._piece))return this._torrent.critical(this._piece,this._piece+this._criticalLength);if(this._notifying)return;if(this._notifying=!0,this._torrent.destroyed)return this.destroy(new Error("Torrent removed"));const e=this._piece,t={};e===this._torrent.pieces.length-1&&(t.length=this._torrent.lastPieceLength),this._torrent.store.get(e,t,((t,i)=>{if(this._notifying=!1,!this.destroyed){if(a("read %s (length %s) (err %s)",e,i&&i.length,t&&t.message),t)return this.destroy(t);this._offset&&(i=i.slice(this._offset),this._offset=0),this._missing{const s=r===e.length-1?n:i;return t.get(r)?s:s-e[r].missing};let o=0;for(let t=r;t<=s;t+=1){const c=a(t);if(o+=c,t===r){const e=this.offset%i;o-=Math.min(e,c)}if(t===s){const t=(s===e.length-1?n:i)-(this.offset+this.length)%i;o-=Math.min(t,c)}}return o}get progress(){return this.length?this.downloaded/this.length:0}select(e){0!==this.length&&this._torrent.select(this._startPiece,this._endPiece,e)}deselect(){0!==this.length&&this._torrent.deselect(this._startPiece,this._endPiece,!1)}createReadStream(e){if(0===this.length){const e=new r;return u((()=>{e.end()})),e}const t=new h(this,e);return this._fileStreams.add(t),t.once("close",(()=>{this._fileStreams.delete(t)})),t}getBuffer(e){l(this.createReadStream(),this.length,e)}getBlob(e){if("undefined"==typeof window)throw new Error("browser-only method");o(this.createReadStream(),this._getMimeType()).then((t=>e(null,t)),(t=>e(t)))}getBlobURL(e){if("undefined"==typeof window)throw new Error("browser-only method");c(this.createReadStream(),this._getMimeType()).then((t=>e(null,t)),(t=>e(t)))}appendTo(e,t,i){if("undefined"==typeof window)throw new Error("browser-only method");a.append(this,e,t,i)}renderTo(e,t,i){if("undefined"==typeof window)throw new Error("browser-only method");a.render(this,e,t,i)}_serve(e){const t={status:200,headers:{"Accept-Ranges":"bytes","Content-Type":d.getType(this.name),"Cache-Control":"no-cache, no-store, must-revalidate, max-age=0",Expires:"0"},body:"HEAD"===e.method?"":"STREAM"};"document"===e.destination&&(t.headers["Content-Type"]="application/octet-stream",t.headers["Content-Disposition"]="attachment",t.body="DOWNLOAD");let i=p(this.length,e.headers.range||"");i.constructor===Array?(t.status=206,i=i[0],t.headers["Content-Range"]=`bytes ${i.start}-${i.end}/${this.length}`,t.headers["Content-Length"]=""+(i.end-i.start+1)):t.headers["Content-Length"]=this.length;const n="GET"===e.method&&this.createReadStream(i);let r=null;return n&&this.emit("stream",{stream:n,req:e,file:this},(e=>{r=e,f(e,(()=>{e&&e.destroy(),n.destroy()}))})),[t,r||n,r&&n]}getStreamURL(e=(()=>{})){if("undefined"==typeof window)throw new Error("browser-only method");if(!this._serviceWorker)throw new Error("No worker registered");if("activated"!==this._serviceWorker.state)throw new Error("Worker isn't activated");e(null,`${this._serviceWorker.scriptURL.substr(0,this._serviceWorker.scriptURL.lastIndexOf("/")+1).slice(window.location.origin.length)}webtorrent/${this._torrent.infoHash}/${encodeURI(this.path)}`)}streamTo(e,t=(()=>{})){if("undefined"==typeof window)throw new Error("browser-only method");if(!this._serviceWorker)throw new Error("No worker registered");if("activated"!==this._serviceWorker.state)throw new Error("Worker isn't activated");const i=this._serviceWorker.scriptURL.substr(0,this._serviceWorker.scriptURL.lastIndexOf("/")+1).slice(window.location.origin.length);e.src=`${i}webtorrent/${this._torrent.infoHash}/${encodeURI(this.path)}`,t(null,e)}_getMimeType(){return a.mime[s.extname(this.name).toLowerCase()]}_destroy(){this._destroyed=!0,this._torrent=null;for(const e of this._fileStreams)e.destroy();this._fileStreams.clear()}}},{"./file-stream.js":489,"end-of-stream":191,events:193,mime:282,path:333,"queue-microtask":354,"range-parser":359,"render-media":377,stream:434,"stream-to-blob":469,"stream-to-blob-url":468,"stream-with-known-length-to-buffer":470}],491:[function(e,t,i){const n=e("events"),{Transform:r}=e("stream"),s=e("unordered-array-remove"),a=e("debug"),o=e("bittorrent-protocol"),c=a("webtorrent:peer");let l=!1;i.enableSecure=()=>{l=!0},i.createWebRTCPeer=(e,t,i)=>{const n=new d(e.id,"webrtc");if(n.conn=e,n.swarm=t,n.throttleGroups=i,n.conn.connected)n.onConnect();else{const e=()=>{n.conn.removeListener("connect",t),n.conn.removeListener("error",i)},t=()=>{e(),n.onConnect()},i=t=>{e(),n.destroy(t)};n.conn.once("connect",t),n.conn.once("error",i),n.startConnectTimeout()}return n},i.createTCPIncomingPeer=(e,t)=>u(e,"tcpIncoming",t),i.createUTPIncomingPeer=(e,t)=>u(e,"utpIncoming",t),i.createTCPOutgoingPeer=(e,t,i)=>p(e,t,"tcpOutgoing",i),i.createUTPOutgoingPeer=(e,t,i)=>p(e,t,"utpOutgoing",i);const u=(e,t,i)=>{const n=`${e.remoteAddress}:${e.remotePort}`,r=new d(n,t);return r.conn=e,r.addr=n,r.throttleGroups=i,r.onConnect(),r},p=(e,t,i,n)=>{const r=new d(e,i);return r.addr=e,r.swarm=t,r.throttleGroups=n,r};i.createWebSeedPeer=(e,t,i,n)=>{const r=new d(t,"webSeed");return r.swarm=i,r.conn=e,r.throttleGroups=n,r.onConnect(),r};class d extends n{constructor(e,t){super(),this.id=e,this.type=t,c("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.sentPe1=!1,this.sentPe2=!1,this.sentPe3=!1,this.sentPe4=!1,this.sentHandshake=!1}onConnect(){if(this.destroyed)return;this.connected=!0,c("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(this.type,this.retries,l);t.once("end",(()=>{this.destroy()})),t.once("close",(()=>{this.destroy()})),t.once("finish",(()=>{this.destroy()})),t.once("error",(e=>{this.destroy(e)})),t.once("pe1",(()=>{this.onPe1()})),t.once("pe2",(()=>{this.onPe2()})),t.once("pe3",(()=>{this.onPe3()})),t.once("pe4",(()=>{this.onPe4()})),t.once("handshake",((e,t)=>{this.onHandshake(e,t)})),this.startHandshakeTimeout(),this.setThrottlePipes(),this.swarm&&("tcpOutgoing"===this.type?l&&0===this.retries&&!this.sentPe1?this.sendPe1():this.sentHandshake||this.handshake():"tcpIncoming"===this.type||this.sentHandshake||this.handshake())}sendPe1(){this.wire.sendPe1(),this.sentPe1=!0}onPe1(){this.sendPe2()}sendPe2(){this.wire.sendPe2(),this.sentPe2=!0}onPe2(){this.sendPe3()}sendPe3(){this.wire.sendPe3(this.swarm.infoHash),this.sentPe3=!0}onPe3(e){this.swarm&&(this.swarm.infoHashHash!==e&&this.destroy(new Error("unexpected crypto handshake info hash for this swarm")),this.sendPe4())}sendPe4(){this.wire.sendPe4(this.swarm.infoHash),this.sentPe4=!0}onPe4(){this.sentHandshake||this.handshake()}clearPipes(){this.conn.unpipe(),this.wire.unpipe()}setThrottlePipes(){const e=this;this.conn.pipe(this.throttleGroups.down.throttle()).pipe(new r({transform(t,i,n){e.emit("download",t.length),e.destroyed||n(null,t)}})).pipe(this.wire).pipe(this.throttleGroups.up.throttle()).pipe(new r({transform(t,i,n){e.emit("upload",t.length),e.destroyed||n(null,t)}})).pipe(this.conn)}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"));c("Peer %s got handshake %s",this.id,e),clearTimeout(this.handshakeTimeout),this.retries=0;let i=this.addr;!i&&this.conn.remoteAddress&&this.conn.remotePort&&(i=`${this.conn.remoteAddress}:${this.conn.remotePort}`),this.swarm._onWire(this.wire,i),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,c("destroy %s %s (error: %s)",this.type,this.id,e&&(e.message||e)),clearTimeout(this.connectTimeout),clearTimeout(this.handshakeTimeout);const t=this.swarm,i=this.conn,n=this.wire;this.swarm=null,this.conn=null,this.wire=null,t&&n&&s(t.wires,t.wires.indexOf(n)),i&&(i.on("error",(()=>{})),i.destroy()),n&&n.destroy(),t&&t.removePeer(this.id)}}},{"bittorrent-protocol":28,debug:161,events:193,stream:434,"unordered-array-remove":481}],492:[function(e,t,i){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=[],i=1/0;for(let n=0;n{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)}))):E.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._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&&n.WEBTORRENT_ANNOUNCE&&!e.private&&(e.announce=e.announce.concat(n.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=E.toMagnetURI(e),this.torrentFile=E.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:()=>{if(this.destroyed)return;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 m({infoHash:this.infoHash,announce:this.announce,peerId:this.client.peerId,dht:!this.private&&this.client.dht,tracker:e,port:this.client.torrentPort,userAgent:W,lsd:this.client.lsd}),this.discovery.on("error",(e=>{this._destroy(e)})),this.discovery.on("peer",((e,t)=>{this._debug("peer %s discovered via %s",e,t),"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=>i=>{!function(t,i){if(0!==t.indexOf("http://")&&0!==t.indexOf("https://"))return e.emit("warning",new Error(`skipping non-http xs param: ${t}`)),i(null);const n={url:t,method:"GET",headers:{"user-agent":W}};let r;try{r=v.concat(n,s)}catch(n){return e.emit("warning",new Error(`skipping invalid url xs param: ${t}`)),i(null)}function s(n,r,s){if(e.destroyed)return i(null);if(e.metadata)return i(null);if(n)return e.emit("warning",new Error(`http error from xs param: ${t}`)),i(null);if(200!==r.statusCode)return e.emit("warning",new Error(`non-200 status code ${r.statusCode} from xs param: ${t}`)),i(null);let a;try{a=E(s)}catch(n){}return a?a.infoHash!==e.infoHash?(e.emit("warning",new Error(`got torrent file with incorrect info hash from xs param: ${t}`)),i(null)):(e._onMetadata(a),void i(null)):(e.emit("warning",new Error(`got invalid torrent file from xs param: ${t}`)),i(null))}e._xsRequests.push(r)}(t,i)}));w(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=E(e)}catch(e){return this._destroy(e)}this._processParsedTorrent(t),this.metadata=this.torrentFile,this.client.enableWebSeeds&&this.urlList.forEach((e=>{this.addWebSeed(e)})),this._rarityMap=new O(this),this.files=this.files.map((e=>new R(this,e)));let i=this._preloadedStore;if(i||(i=new this._store(this.pieceLength,{...this.storeOpts,torrent:this,path:this.path,files:this.files,length:this.length,name:this.name+" - "+this.infoHash.slice(0,8),addUID:this.addUID})),this._storeCacheSlots>0&&!(i instanceof _)&&(i=new p(i,{max:this._storeCacheSlots})),this.store=new g(i),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 i=t===this.pieces.length-1?this.lastPieceLength:this.pieceLength;return new S(i)})),this._reservations=this.pieces.map((()=>[])),this.bitfield=new u(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===b?this.getFileModtimes(((t,i)=>{if(t)return this._destroy(t);this.files.map(((e,t)=>i[t]===this._fileModtimes[t])).every((e=>e))?(this._markAllVerified(),this._onStore()):this._verifyPieces(e)})):this._verifyPieces(e)}}getFileModtimes(e){const t=[];k(this.files.map(((e,i)=>n=>{const r=this.addUID?c.join(this.name+" - "+this.infoHash.slice(0,8)):c.join(this.path,e.path);s.stat(r,((e,r)=>{if(e&&"ENOENT"!==e.code)return n(e);t[i]=r&&r.mtime.getTime(),n(null)}))})),H,(i=>{this._debug("done getting file modtimes"),e(i,t)}))}_verifyPieces(e){k(this.pieces.map(((e,t)=>e=>{if(this.destroyed)return e(new Error("torrent is destroyed"));const i={};t===this.pieces.length-1&&(i.length=this.lastPieceLength),this.store.get(t,i,((i,n)=>this.destroyed?e(new Error("torrent is destroyed")):i?A((()=>e(null))):void I(n,(i=>{if(this.destroyed)return e(new Error("torrent is destroyed"));i===this._hashes[t]?(this._debug("piece verified %s",t),this._markVerified(t)):this._debug("piece invalid %s",t),e(null)}))))})),H,e)}rescanFiles(e){if(this.destroyed)throw new Error("torrent is destroyed");e||(e=$),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 R&&e._destroy()}));const n=this._servers.map((e=>t=>{e.destroy(t)}));if(this.discovery&&n.push((e=>{this.discovery.destroy(e)})),this.store){let e=this._destroyStoreOnDestroy;t&&void 0!==t.destroyStore&&(e=t.destroyStore),n.push((t=>{e?this.store.destroy(t):this.store.close(t)}))}w(n,i),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");let t;if(this.client.blocked){if("string"==typeof e){let i;try{i=l(e)}catch(t){return this._debug("ignoring peer: invalid %s",e),this.emit("invalidPeer",e),!1}t=i[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 i=this.client.utp&&this._isIPv4(t)?"utp":"tcp",n=!!this._addPeer(e,i);return n?this.emit("peer",e):this.emit("invalidPeer",e),n}_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 i=e&&e.id||e;if(this._peers[i])return this._debug("ignoring peer: duplicate (%s)",i),"string"!=typeof e&&e.destroy(),null;if(this.paused)return this._debug("ignoring peer: torrent is paused"),"string"!=typeof e&&e.destroy(),null;let n;return this._debug("add peer %s",i),n="string"==typeof e?"utp"===t?L.createUTPOutgoingPeer(e,this,this.client.throttleGroups):L.createTCPOutgoingPeer(e,this,this.client.throttleGroups):L.createWebRTCPeer(e,this,this.client.throttleGroups),this._registerPeer(n),"string"==typeof e&&(this._queue.push(n),this._drain()),n}addWebSeed(e){if(this.destroyed)throw new Error("torrent is destroyed");let t,i;if("string"==typeof e){if(t=e,!/^https?:\/\/.+/.test(t))return this.emit("warning",new Error(`ignoring invalid web seed: ${t}`)),void this.emit("invalidPeer",t);if(this._peers[t])return this.emit("warning",new Error(`ignoring duplicate web seed: ${t}`)),void this.emit("invalidPeer",t);i=new q(t,this)}else{if(!e||"string"!=typeof e.connId)return void this.emit("warning",new Error("addWebSeed must be passed a string or connection object with id property"));if(i=e,t=i.connId,this._peers[t])return this.emit("warning",new Error(`ignoring duplicate web seed: ${t}`)),void this.emit("invalidPeer",t)}this._debug("add web seed %s",t);const n=L.createWebSeedPeer(i,t,this,this.client.throttleGroups);this._registerPeer(n),this.emit("peer",t)}_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),void this._registerPeer(e))}_registerPeer(e){e.on("download",(e=>{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._peers[e.id]=e,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,i,n){if(this.destroyed)throw new Error("torrent is destroyed");if(e<0||tt.priority-e.priority)),this._updateSelections()}deselect(e,t,i){if(this.destroyed)throw new Error("torrent is destroyed");i=Number(i)||0,this._debug("deselect %s-%s (priority %s)",e,t,i);for(let n=0;n{if(!this.destroyed&&!this.client.dht.destroyed){if(!e.remoteAddress)return this._debug("ignoring PORT from peer with no address");if(0===i||i>65536)return this._debug("ignoring invalid PORT from peer");this._debug("port: %s (from %s)",i,t),this.client.dht.addNode({host:e.remoteAddress,port:i})}})),e.on("timeout",(()=>{this._debug("wire timeout (%s)",t),e.destroy()})),"webSeed"!==e.type&&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 B||this.private||(e.use(B()),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 i=this._peers[e];i&&!i.connected&&(this._debug("ut_pex: dropped peer: %s (from %s)",e,t),this.removePeer(e))})),e.once("close",(()=>{e.ut_pex.reset()}))),e.use(y()),this.emit("wire",e,t),this.metadata&&A((()=>{this._onWireWithMetadata(e)}))}_onWireWithMetadata(e){let t=null;const i=()=>{this.destroyed||e.destroyed||(this._numQueued>2*(this._numConns-this.numPeers)&&e.amInterested?e.destroy():(t=setTimeout(i,D),t.unref&&t.unref()))};let n;const r=()=>{if(e.peerPieces.buffer.length===this.bitfield.buffer.length){for(n=0;n{r(),this._update(),this._updateWireInterest(e)})),e.on("have",(()=>{r(),this._update(),this._updateWireInterest(e)})),e.lt_donthave.on("donthave",(()=>{r(),this._update(),this._updateWireInterest(e)})),e.once("interested",(()=>{e.unchoke()})),e.once("close",(()=>{clearTimeout(t)})),e.on("choke",(()=>{clearTimeout(t),t=setTimeout(i,D),t.unref&&t.unref()})),e.on("unchoke",(()=>{clearTimeout(t),this._update()})),e.on("request",((t,i,n,r)=>{if(n>131072)return e.destroy();this.pieces[t]||this.store.get(t,{offset:i,length:n},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(i,D),t.unref&&t.unref()),e.isSeeder=!1,r()}_updateSelections(){this.ready&&!this.destroyed&&(A((()=>{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 i=0;i{t._updateWire(e)}),{timeout:250}):t._updateWire(e)}_updateWire(e){const t=this;if(e.peerChoking)return;if(!e.downloaded)return function(){if(e.requests.length)return;let i=t._selections.length;for(;i--;){const n=t._selections[i];let s;if("rarest"===t.strategy){const i=n.from+n.offset,a=n.to,o=a-i+1,c={};let l=0;const u=r(i,a,c);for(;l=n.from+n.offset;--s)if(e.peerPieces.get(s)&&t._request(e,s,!1))return}}();const i=V(e,.5);if(e.requests.length>=i)return;const n=V(e,1);function r(t,i,n,r){return s=>s>=t&&s<=i&&!(s in n)&&e.peerPieces.get(s)&&(!r||r(s))}function s(e){let i=e;for(let n=e;n=n)return!0;const a=function(){const i=e.downloadSpeed()||1;if(i>z)return()=>!0;const n=Math.max(1,e.requests.length)*S.BLOCK_LENGTH/i;let r=10,s=0;return e=>{if(!r||t.bitfield.get(e))return!0;let a=t.pieces[e].missing;for(;s0))return r--,!1}return!0}}();for(let o=0;o({wire:e,random:Math.random()}))).sort(((e,t)=>{const i=e.wire,n=t.wire;return i.downloadSpeed()!==n.downloadSpeed()?i.downloadSpeed()-n.downloadSpeed():i.uploadSpeed()!==n.uploadSpeed()?i.uploadSpeed()-n.uploadSpeed():i.amChoking!==n.amChoking?i.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[(i=t.length,Math.random()*i|0)];e.unchoke(),this._rechokeOptimisticWire=e,this._rechokeOptimisticTime=2}}var i;e.filter((e=>e!==this._rechokeOptimisticWire)).forEach((e=>e.choke()))}_hotswap(e,t){const i=e.downloadSpeed();if(i=z||(2*o>i||o>a||(r=t,a=o))}if(!r)return!1;for(s=0;s=a)return!1;const o=n.pieces[t];let c=s?o.reserveRemaining():o.reserve();if(-1===c&&i&&n._hotswap(e,t)&&(c=s?o.reserveRemaining():o.reserve()),-1===c)return!1;let l=n._reservations[t];l||(l=n._reservations[t]=[]);let u=l.indexOf(null);-1===u&&(u=l.length),l[u]=e;const p=o.chunkOffset(c),d=s?o.chunkLengthRemaining(c):o.chunkLength(c);function f(){A((()=>{n._update()}))}return e.request(t,p,d,(function i(r,a){if(n.destroyed)return;if(!n.ready)return n.once("ready",(()=>{i(r,a)}));if(l[u]===e&&(l[u]=null),o!==n.pieces[t])return f();if(r)return n._debug("error getting piece %s (offset: %s length: %s) from %s: %s",t,p,d,`${e.remoteAddress}:${e.remotePort}`,r.message),s?o.cancelRemaining(c):o.cancel(c),void f();if(n._debug("got piece %s (offset: %s length: %s) from %s",t,p,d,`${e.remoteAddress}:${e.remotePort}`),!o.set(c,a,e))return f();const h=o.flush();I(h,(e=>{n.destroyed||(e===n._hashes[t]?(n._debug("piece verified %s",t),n.store.put(t,h,(e=>{e?n._destroy(e):(n.pieces[t]=null,n._markVerified(t),n.wires.forEach((e=>{e.have(t)})),n._checkDone()&&!n.destroyed&&n.discovery.complete(),f())}))):(n.pieces[t]=new S(o.length),n.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(const t of this._selections){for(let i=t.from;i<=t.to;i++)if(!this.bitfield.get(i)){e=!1;break}if(!e)break}return!this.done&&e?(this.done=!0,this._debug(`torrent done: ${this.infoHash}`),this.emit("done")):this.done=!1,this._gcSelections(),e}load(e,t){if(this.destroyed)throw new Error("torrent is destroyed");if(!this.ready)return this.once("ready",(()=>{this.load(e,t)}));Array.isArray(e)||(e=[e]),t||(t=$);const i=new x(e),n=new d(this.store,this.pieceLength);M(i,n,(e=>{if(e)return t(e);this._markAllVerified(),this._checkDone(),t(null)}))}createServer(e){if("function"!=typeof P)throw new Error("node.js-only method");if(this.destroyed)throw new Error("torrent is destroyed");const t=new P(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]}`,N(...e)}_drain(){if(this._debug("_drain numConns %s maxConns %s",this._numConns,this.client.maxConns),"function"!=typeof a.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=l(e.addr),i={host:t[0],port:t[1]};this.client.utp&&"utpOutgoing"===e.type?e.conn=U.connect(i.port,i.host):e.conn=a.connect(i);const n=e.conn;n.once("connect",(()=>{e.onConnect()})),n.once("error",(t=>{e.destroy(t)})),e.startConnectTimeout(),n.on("close",(()=>{if(this.destroyed)return;if(e.retries>=F.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,F.length);return}const t=F[e.retries];this._debug("conn %s closed: will re-add to queue in %sms (attempt %s)",e.addr,t,e.retries+1);const i=setTimeout((()=>{if(this.destroyed)return;const t=l(e.addr)[0],i=this.client.utp&&this._isIPv4(t)?"utp":"tcp",n=this._addPeer(e.addr,i);n&&(n.retries=e.retries+1)}),t);i.unref&&i.unref()}))}_validAddr(e){let t;try{t=l(e)}catch(e){return!1}const i=t[0],n=t[1];return n>0&&n<65535&&!("127.0.0.1"===i&&n===this.client.torrentPort)}_isIPv4(e){return/^((?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])[.]){3}(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])$/.test(e)}}}).call(this)}).call(this,e("_process"),"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"../package.json":495,"./file.js":490,"./peer.js":491,"./rarity-map.js":492,"./server.js":67,"./utp.js":67,"./webconn.js":494,_process:341,"addr-to-ip-port":3,bitfield:27,"cache-chunk-store":117,"chunk-store-stream/write":133,cpus:137,debug:161,events:193,fs:67,"fs-chunk-store":275,"immediate-chunk-store":245,lt_donthave:256,"memory-chunk-store":275,multistream:309,net:67,os:67,"parse-torrent":332,path:333,pump:349,"queue-microtask":354,"random-iterate":356,"run-parallel":381,"run-parallel-limit":380,"simple-get":394,"simple-sha1":411,speedometer:433,"torrent-discovery":477,"torrent-piece":478,ut_metadata:484,ut_pex:67}],494:[function(e,t,i){(function(i){(function(){const{default:n}=e("bitfield"),r=e("debug"),s=e("simple-get"),a=e("lt_donthave"),o=e("simple-sha1"),c=e("bittorrent-protocol"),l=r("webtorrent:webconn"),u=e("../package.json").version;t.exports=class extends c{constructor(e,t){super(),this.url=e,this.connId=e,this.webPeerId=o.sync(e),this._torrent=t,this._init()}_init(){this.setKeepAlive(!0),this.use(a()),this.once("handshake",((e,t)=>{if(this.destroyed)return;this.handshake(e,this.webPeerId);const i=this._torrent.pieces.length,r=new n(i);for(let e=0;e<=i;e++)r.set(e,!0);this.bitfield(r)})),this.once("interested",(()=>{l("interested"),this.unchoke()})),this.on("uninterested",(()=>{l("uninterested")})),this.on("choke",(()=>{l("choke")})),this.on("unchoke",(()=>{l("unchoke")})),this.on("bitfield",(()=>{l("bitfield")})),this.lt_donthave.on("donthave",(()=>{l("donthave")})),this.on("request",((e,t,i,n)=>{l("request pieceIndex=%d offset=%d length=%d",e,t,i),this.httpRequest(e,t,i,((t,i)=>{if(t){this.lt_donthave.donthave(e);const t=setTimeout((()=>{this.destroyed||this.have(e)}),1e4);t.unref&&t.unref()}n(t,i)}))}))}httpRequest(e,t,n,r){const a=e*this._torrent.pieceLength+t,o=a+n-1,c=this._torrent.files;let p;if(c.length<=1)p=[{url:this.url,start:a,end:o}];else{const e=c.filter((e=>e.offset<=o&&e.offset+e.length>a));if(e.length<1)return r(new Error("Could not find file corresponding to web seed range request"));p=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,o-e.offset)}}))}let d,f=0,h=!1;p.length>1&&(d=i.alloc(n)),p.forEach((i=>{const a=i.url,o=i.start,c=i.end;l("Requesting url=%s pieceIndex=%d offset=%d length=%d start=%d end=%d",a,e,t,n,o,c);const m={url:a,method:"GET",headers:{"user-agent":`WebTorrent/${u} (https://webtorrent.io)`,range:`bytes=${o}-${c}`},timeout:6e4};function b(e,t){if(e.statusCode<200||e.statusCode>=300){if(h)return;return h=!0,r(new Error(`Unexpected HTTP status code ${e.statusCode}`))}l("Got data of length %d",t.length),1===p.length?r(null,t):(t.copy(d,i.fileOffsetInRange),++f===p.length&&r(null,d))}s.concat(m,((e,t,i)=>{if(!h)return e?"undefined"==typeof window||a.startsWith(`${window.location.origin}/`)?(h=!0,r(e)):s.head(a,((t,i)=>{if(!h){if(t)return h=!0,r(t);if(i.statusCode<200||i.statusCode>=300)return h=!0,r(new Error(`Unexpected HTTP status code ${i.statusCode}`));if(i.url===a)return h=!0,r(e);m.url=i.url,s.concat(m,((e,t,i)=>{if(!h)return e?(h=!0,r(e)):void b(t,i)}))}})):void b(t,i)}))}))}destroy(){super.destroy(),this._torrent=null}}}).call(this)}).call(this,e("buffer").Buffer)},{"../package.json":495,bitfield:27,"bittorrent-protocol":28,buffer:110,debug:161,lt_donthave:256,"simple-get":394,"simple-sha1":411}],495:[function(e,t,i){t.exports={version:"1.5.8"}},{}],496:[function(e,t,i){t.exports=function e(t,i){if(t&&i)return e(t)(i);if("function"!=typeof t)throw new TypeError("need wrapper function");return Object.keys(t).forEach((function(e){n[e]=t[e]})),n;function n(){for(var e=new Array(arguments.length),i=0;i1080?(q.setProps({placement:"right"}),N.setProps({placement:"right"}),D.setProps({placement:"right"})):(q.setProps({placement:"top"}),N.setProps({placement:"top"}),D.setProps({placement:"top"}))}function W(e){Y();try{console.info("Attempting parse"),p=r(e),V(),p.xs&&(console.info("Magnet includes xs, attempting remote parse"),K(p.xs))}catch(t){console.warn(t),"magnet"==u?(console.info("Attempting remote parse"),K(e)):(H.error("Problem parsing input. Is this a .torrent file?"),console.error("Problem parsing input"))}}function K(e){r.remote(e,(function(e,t){if(e)return H.error("Problem remotely fetching that file or parsing result"),console.warn(e),void Y();u="remote-torrent-file",v.innerHTML='',g.setContent("Currently loaded information sourced from remotely fetched Torrent file"),p=t,V()}))}function V(){if(console.log(p),E.value=p.infoHash,y.value=p.name?p.name:"",p.created?(x.value=p.created.toISOString().slice(0,19),x.type="datetime-local"):x.type="text",w.value=p.createdBy?"by "+p.createdBy:"",k.value=p.comment?p.comment:"",j.innerHTML="",p.announce&&p.announce.length)for(let e=0;e',n.addEventListener("click",Q),t.appendChild(n),j.appendChild(t)}if(I.innerHTML="",p.urlList&&p.urlList.length)for(let e=0;e',n.addEventListener("click",Q),t.appendChild(n),I.appendChild(t)}if(B.innerHTML="",p.files&&p.files.length){if(R.style.display="none",p.files.length<100)for(let e of p.files){let t=G(o.lookup(e.name));B.appendChild($(t,e.name,e.length))}else{for(let e=0;e<100;e++){let t=G(o.lookup(p.files[e].name));B.appendChild($(t,p.files[e].name,p.files[e].length))}B.appendChild($("","...and another "+(p.files.length-100)+" more files",""))}B.appendChild($("folder-tree","",p.length)),D.setContent("Download Torrent file"),U.addEventListener("click",ne),U.disabled=!1}else z.torrents.length>0?(R.style.display="none",B.innerHTML=''):(R.style.display="block",B.innerHTML=''),D.setContent("Files metadata is required to generate a Torrent file. Try fetching files list from WebTorrent."),U.removeEventListener("click",ne),U.disabled=!0;L.setAttribute("data-clipboard-text",window.location.origin+"#"+r.toMagnetURI(p)),O.setAttribute("data-clipboard-text",r.toMagnetURI(p)),d.style.display="none",b.style.display="flex",window.location.hash=r.toMagnetURI(p),p.name?document.title="Torrent Parts | "+p.name:document.title="Torrent Parts | Inspect and edit what's in your Torrent file or Magnet link",g.enable(),gtag("event","view_item",{items:[{item_id:p.infoHash,item_name:p.name,item_category:u}]})}function $(e,t,i){let n=document.createElement("tr"),r=document.createElement("td");e&&(r.innerHTML=''),n.appendChild(r);let s=document.createElement("td");s.innerHTML=t,n.appendChild(s);let o=document.createElement("td");return o.innerHTML=a.format(i,{decimalPlaces:1,unitSeparator:" "}),n.appendChild(o),n}function G(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"):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 X(e){this.dataset.group?p[this.dataset.group][this.dataset.index]=this.value?this.value:"":p[this.id]=this.value?this.value:"",window.location.hash=r.toMagnetURI(p),te()}function Y(){document.getElementById("magnet").value="",document.getElementById("torrent").value="",d.style.display="flex",b.style.display="none",y.value="",x.value="",w.value="",k.value="",E.value="",j.innerHTML="",I.innerHTML="",z.torrents.forEach((e=>e.destroy())),R.style.display="block",B.innerHTML="",window.location.hash="",L.setAttribute("data-clipboard-text",""),O.setAttribute("data-clipboard-text",""),document.title="Torrent Parts | Inspect and edit what's in your Torrent file or Magnet link",g.disable(),gtag("event","reset")}async function Z(){S.className="disabled",S.innerHTML="Adding...";try{let e=await fetch("https://newtrackon.com/api/stable"),t=await e.text();p.announce=p.announce.concat(t.split("\n\n")),p.announce.push("http://bt1.archive.org:6969/announce"),p.announce.push("http://bt2.archive.org:6969/announce"),p.announce=p.announce.filter(((e,t)=>e&&p.announce.indexOf(e)===t)),H.success("Added known working trackers from newTrackon"),te()}catch(e){H.error("Problem fetching trackers from newTrackon"),console.warn(e)}S.className="",S.innerHTML="Add Known Working Trackers",V(),gtag("event","add_trackers")}function J(){p[this.dataset.type].unshift(""),V()}function Q(){p[this.parentElement.className].splice(this.parentElement.dataset.index,1),V()}function ee(e){p[e]=[],te(),V()}function te(){p.created=new Date,p.createdBy="Torrent Parts ",p.created?(x.value=p.created.toISOString().slice(0,19),x.type="datetime-local"):x.type="text",w.value=p.createdBy?"by "+p.createdBy:""}function ie(){console.info("Attempting fetching files from Webtorrent..."),R.style.display="none",p.announce.push("wss://tracker.webtorrent.io"),p.announce.push("wss://tracker.openwebtorrent.com"),p.announce.push("wss://tracker.btorrent.xyz"),p.announce.push("wss://tracker.fastcast.nz"),p.announce=p.announce.filter(((e,t)=>e&&p.announce.indexOf(e)===t)),z.add(r.toMagnetURI(p),(e=>{p.info=Object.assign({},e.info),p.files=e.files,p.infoBuffer=e.infoBuffer,p.length=e.length,p.lastPieceLength=e.lastPieceLength,te(),V(),H.success("Fetched file details from Webtorrent peers"),e.destroy()})),V(),gtag("event","attempt_webtorrent_fetch")}function ne(){let e=r.toTorrentFile(p);if(null!==e&&navigator.msSaveBlob)return navigator.msSaveBlob(new Blob([e],{type:"application/x-bittorrent"}),p.name+".torrent");let t=document.createElement("a");t.style.display="none";let i=window.URL.createObjectURL(new Blob([e],{type:"application/x-bittorrent"}));t.setAttribute("href",i),t.setAttribute("download",p.name+".torrent"),document.body.appendChild(t),t.click(),window.URL.revokeObjectURL(i),t.remove(),gtag("event","share",{method:"Torrent Download",content_id:p.name})}window.addEventListener("resize",F),F(),document.addEventListener("DOMContentLoaded",(function(){document.getElementById("magnet").addEventListener("keyup",(function(e){e.preventDefault(),"Enter"===e.key&&(u="magnet",v.innerHTML='',g.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){u="torrent-file",v.innerHTML='',g.setContent("Currently loaded information sourced from Torrent file"),W(s.from(e))}))})),document.addEventListener("dragover",(function(e){e.preventDefault()})),document.addEventListener("drop",(function(e){e.preventDefault(),e.dataTransfer.items[0].getAsFile().arrayBuffer().then((function(e){u="torrent-file",v.innerHTML='',g.setContent("Currently loaded information sourced from Torrent file"),W(s.from(e))}))})),f.addEventListener("click",(function(e){e.preventDefault(),H.success("Parsing Ubuntu 20.04 Magnet URL"),u="magnet",v.innerHTML='',g.setContent("Currently loaded information sourced from 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(),H.success("Fetching and Parsing “The WIRED CD” Torrent File..."),u="remote-torrent-file",v.innerHTML='',g.setContent("Currently loaded information sourced from remotely fetched Torrent file"),K("https://webtorrent.io/torrents/wired-cd.torrent")})),m.addEventListener("click",(async function(e){e.preventDefault(),H.success("Parsing Jack Johnson Archive.org Torrent File");let t=await fetch("/ext/jj2008-06-14.mk4_archive.torrent"),i=await t.arrayBuffer();u="torrent-file",v.innerHTML='',g.setContent("Currently loaded information sourced from Torrent file"),W(s.from(i))}));let e=new n("#copyURL");e.on("success",(function(e){H.success("Copied site URL to clipboard!"),console.info(e),gtag("event","share",{method:"Copy URL",content_id:e.text})})),e.on("failure",(function(e){H.error("Problem copying to clipboard"),console.warn(e)}));let t=new n("#copyMagnet");t.on("success",(function(e){H.success("Copied Magnet URL to clipboard!"),gtag("event","share",{method:"Copy Magnet",content_id:e.text})})),t.on("failure",(function(e){H.error("Problem copying to clipboard"),console.warn(e)})),y.addEventListener("input",X),y.addEventListener("change",X),y.addEventListener("reset",X),y.addEventListener("paste",X),_.addEventListener("click",Y),k.addEventListener("input",X),k.addEventListener("change",X),k.addEventListener("reset",X),k.addEventListener("paste",X),S.addEventListener("click",Z),M.addEventListener("click",J),A.addEventListener("click",(()=>ee("announce"))),T.addEventListener("click",J),C.addEventListener("click",(()=>ee("urlList"))),R.addEventListener("click",ie),l("[data-tippy-content]",{theme:"torrent-parts",animation:"shift-away-subtle"}),g.disable(),window.location.hash&&(u="shared-url",v.innerHTML='',g.setContent("Currently loaded information sourced from shared torrent.parts link"),W(window.location.hash.split("#")[1]))}))},{Buffer:2,bytes:116,clipboard:135,"mime-types":280,"parse-torrent":332,"tippy.js":475,webtorrent:488}]},{},[498]); \ No newline at end of file diff --git a/src/parse.js b/src/parse.js index f458458..e98ea95 100644 --- a/src/parse.js +++ b/src/parse.js @@ -120,12 +120,18 @@ function start() { example1.addEventListener('click', function(event) { event.preventDefault(); notyf.success("Parsing Ubuntu 20.04 Magnet URL"); + source = "magnet"; + originalSourceIcon.innerHTML = ''; + sourceTooltip.setContent("Currently loaded information sourced from 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..."); + source = "remote-torrent-file"; + originalSourceIcon.innerHTML = ''; + sourceTooltip.setContent("Currently loaded information sourced from remotely fetched Torrent file"); parseRemote("https://webtorrent.io/torrents/wired-cd.torrent"); }); @@ -134,6 +140,9 @@ function start() { notyf.success("Parsing Jack Johnson Archive.org Torrent File"); let response = await fetch("/ext/jj2008-06-14.mk4_archive.torrent"); let arrayBuffer = await response.arrayBuffer(); + source = "torrent-file"; + originalSourceIcon.innerHTML = ''; + sourceTooltip.setContent("Currently loaded information sourced from Torrent file"); parse(Buffer.from(arrayBuffer)); });