// Generated by CoffeeScript 1.10.0 (function() { var app, client, dbg, er, opts, trackers; trackers = [['wss://tracker.webtorrent.io'], ['wss://tracker.btorrent.xyz']]; opts = { announce: trackers, announceList: trackers, rtcConfig: { "iceServers": [ { "url": "stun:23.21.150.121", "urls": "stun:23.21.150.121" }, { "url": "stun:stun.l.google.com:19302", "urls": "stun:stun.l.google.com:19302" }, { "url": "stun:stun1.l.google.com:19302", "urls": "stun:stun1.l.google.com:19302" }, { "url": "stun:stun2.l.google.com:19302", "urls": "stun:stun2.l.google.com:19302" }, { "url": "stun:stun3.l.google.com:19302", "urls": "stun:stun3.l.google.com:19302" }, { "url": "stun:stun4.l.google.com:19302", "urls": "stun:stun4.l.google.com:19302" }, { "url": "turn:global.turn.twilio.com:3478?transport=udp", "urls": "turn:global.turn.twilio.com:3478?transport=udp", "username": "857315a4616be37252127d4ff924c3a3536dd3fa729b56206dfa0e6808a80478", "credential": "EEEr7bxx8umMHC4sOoWDC/4MxU/4JCfL+W7KeSJEsBQ=" }, { "url": "turn:numb.viagenie.ca", "urls": "turn:numb.viagenie.ca", "credential": "webrtcdemo", "username": "louis%40mozilla.com" } ] } }; client = new WebTorrent(opts); dbg = function(string, torrent, color) { color = color != null ? color : '#333333'; if (window.localStorage.getItem('debug') != null) { if ((torrent != null) && torrent.name) { console.debug('%cβTorrent:torrent:' + torrent.name + ' (' + torrent.infoHash + ') %c' + string, 'color: #33C3F0', 'color: ' + color); return; } else { console.debug('%cβTorrent:client %c' + string, 'color: #33C3F0', 'color: ' + color); return; } } }; er = function(err, torrent) { return dbg(err, torrent, '#FF0000'); }; app = angular.module('bTorrent', ['ui.grid', 'ui.grid.resizeColumns', 'ui.grid.selection', 'ngFileUpload', 'ngNotify'], [ '$compileProvider', '$locationProvider', function($compileProvider, $locationProvider) { $compileProvider.aHrefSanitizationWhitelist(/^\s*(https?|magnet|blob|javascript):/); return $locationProvider.html5Mode({ enabled: true, requireBase: false }).hashPrefix('#'); } ]); app.controller('bTorrentCtrl', [ '$scope', '$http', '$log', '$location', 'ngNotify', function($scope, $http, $log, $location, ngNotify) { var updateAll; $scope.client = client; $scope.seedIt = true; $scope.client.validTorrents = []; $scope.columns = [ { field: 'name', cellTooltip: true, minWidth: '200' }, { field: 'length', name: 'Size', cellFilter: 'pbytes', width: '80' }, { field: 'received', displayName: 'Downloaded', cellFilter: 'pbytes', width: '135' }, { field: 'downloadSpeed()', displayName: '↓ Speed', cellFilter: 'pbytes:1', width: '100' }, { field: 'progress', displayName: 'Progress', cellFilter: 'progress', width: '100' }, { field: 'timeRemaining', displayName: 'ETA', cellFilter: 'humanTime', width: '150' }, { field: 'uploaded', displayName: 'Uploaded', cellFilter: 'pbytes', width: '125' }, { field: 'uploadSpeed()', displayName: '↑ Speed', cellFilter: 'pbytes:1', width: '100' }, { field: 'numPeers', displayName: 'Peers', width: '80' }, { field: 'ratio', cellFilter: 'number:2', width: '80' } ]; $scope.gridOptions = { columnDefs: $scope.columns, data: $scope.client.validTorrents, enableColumnResizing: true, enableColumnMenus: false, enableRowSelection: true, enableRowHeaderSelection: false, multiSelect: false }; updateAll = function() { if ($scope.client.processing) { return; } $scope.$apply(); }; setInterval(updateAll, 500); $scope.gridOptions.onRegisterApi = function(gridApi) { $scope.gridApi = gridApi; return gridApi.selection.on.rowSelectionChanged($scope, function(row) { if (!row.isSelected && ($scope.selectedTorrent != null) && ($scope.selectedTorrent.infoHash = row.entity.infoHash)) { return $scope.selectedTorrent = null; } else { return $scope.selectedTorrent = row.entity; } }); }; $scope.seedFile = function(file) { if (file != null) { dbg('Seeding file ' + file.name); $scope.client.processing = true; $scope.client.seed(file, opts, $scope.onSeed); } }; $scope.openTorrentFile = function(file) { if (file != null) { dbg('Adding torrent file ' + file.name); $scope.client.processing = true; return $scope.client.add(file, opts, $scope.onTorrent); } }; $scope.client.on('error', function(err, torrent) { $scope.client.processing = false; ngNotify.set(err, 'error'); return er(err, torrent); }); $scope.addMagnet = function() { if ($scope.torrentInput !== '') { dbg('Adding magnet/hash ' + $scope.torrentInput); $scope.client.processing = true; $scope.client.add($scope.torrentInput, opts, $scope.onTorrent); $scope.torrentInput = ''; } }; $scope.destroyedTorrent = function(err) { $scope.client.processing = false; if (err) { throw err; } dbg('Destroyed torrent'); }; $scope.onTorrent = function(torrent, isSeed) { $scope.client.validTorrents.push(torrent); torrent.safeTorrentFileURL = torrent.torrentFileURL; torrent.fileName = torrent.name + '.torrent'; if (!isSeed) { $scope.client.processing = false; } if (!($scope.selectedTorrent != null) || isSeed) { $scope.selectedTorrent = torrent; } torrent.files.forEach(function(file) { file.getBlobURL(function(err, url) { if (err) { throw err; } if (isSeed) { dbg('Started seeding', torrent); $scope.client.processing = false; } file.url = url; if (!isSeed) { dbg('Finished downloading file ' + file.name, torrent); } }); if (!isSeed) { dbg('Received file ' + file.name + ' metadata', torrent); } }); torrent.on('download', function(chunkSize) { if (!isSeed) { dbg('Downloaded chunk', torrent); } }); torrent.on('upload', function(chunkSize) { dbg('Uploaded chunk', torrent); }); torrent.on('done', function() { if (!isSeed) { dbg('Done', torrent); return; } torrent.update(); }); torrent.on('wire', function(wire, addr) { dbg('Wire ' + addr, torrent); }); }; $scope.onSeed = function(torrent) { $scope.onTorrent(torrent, true); }; if ($location.hash() !== '') { $scope.client.processing = true; setTimeout(function() { dbg('Adding ' + $location.hash()); return $scope.client.add($location.hash(), $scope.onTorrent); }, 500); } } ]); app.filter('html', [ '$sce', function($sce) { return function(input) { $sce.trustAsHtml(input); }; } ]); app.filter('pbytes', function() { return function(num, speed) { var exponent, unit, units; if (isNaN(num)) { return ''; } exponent = void 0; unit = void 0; units = ['B', 'kB', 'MB', 'GB', 'TB']; if (num < 1) { return (speed ? '' : '0 B'); } exponent = Math.min(Math.floor(Math.log(num) / Math.log(1000)), 8); num = (num / Math.pow(1000, exponent)).toFixed(1) * 1; unit = units[exponent]; return num + ' ' + unit + (speed ? '/s' : ''); }; }); app.filter('humanTime', function() { return function(millis) { var remaining; if (millis < 1000) { return ''; } remaining = moment.duration(millis / 1000, 'seconds').humanize(); return remaining[0].toUpperCase() + remaining.substr(1); }; }); app.filter('progress', function() { return function(num) { return (100 * num).toFixed(1) + '%'; }; }); }).call(this);