├── src ├── app │ ├── views │ │ ├── 404.html │ │ ├── cast │ │ │ └── index.html │ │ ├── donate │ │ │ └── index.html │ │ ├── recording │ │ │ └── index.html │ │ └── home │ │ │ └── index.html │ ├── app.js │ ├── controllers │ │ ├── donatecontroller.js │ │ ├── castcontroller.js │ │ ├── homecontroller.js │ │ └── recordingcontroller.js │ └── routes.js ├── google17e988616126521e.html ├── assets │ ├── img │ │ ├── icons │ │ │ ├── favicon.ico │ │ │ ├── apple-icon.png │ │ │ ├── favicon-16x16.png │ │ │ ├── favicon-32x32.png │ │ │ ├── favicon-96x96.png │ │ │ ├── ms-icon-70x70.png │ │ │ ├── ms-icon-144x144.png │ │ │ ├── ms-icon-150x150.png │ │ │ ├── ms-icon-310x310.png │ │ │ ├── android-icon-36x36.png │ │ │ ├── android-icon-48x48.png │ │ │ ├── android-icon-72x72.png │ │ │ ├── android-icon-96x96.png │ │ │ ├── apple-icon-114x114.png │ │ │ ├── apple-icon-120x120.png │ │ │ ├── apple-icon-144x144.png │ │ │ ├── apple-icon-152x152.png │ │ │ ├── apple-icon-180x180.png │ │ │ ├── apple-icon-57x57.png │ │ │ ├── apple-icon-60x60.png │ │ │ ├── apple-icon-72x72.png │ │ │ ├── apple-icon-76x76.png │ │ │ ├── android-icon-144x144.png │ │ │ ├── android-icon-192x192.png │ │ │ └── apple-icon-precomposed.png │ │ ├── logos │ │ │ ├── logo-icon.png │ │ │ └── logo-white-bg.png │ │ └── sponsors │ │ │ ├── agiles.png │ │ │ └── CodeCampSDQ2.jpg │ ├── js │ │ └── shared.js │ └── css │ │ └── style.css ├── browserconfig.xml ├── manifest.json ├── streamelopers_donations.csv ├── sw.js ├── .htaccess ├── index.html └── playlists.json ├── .gitignore ├── bower.json ├── server.js ├── package.json ├── Readme.md └── Gruntfile.js /src/app/views/404.html: -------------------------------------------------------------------------------- 1 |

Error 404

2 | -------------------------------------------------------------------------------- /src/app/app.js: -------------------------------------------------------------------------------- 1 | var app = angular.module('StreamelopersApp', ['ngRoute']); 2 | -------------------------------------------------------------------------------- /src/google17e988616126521e.html: -------------------------------------------------------------------------------- 1 | google-site-verification: google17e988616126521e.html -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | package-lock.json 2 | node_modules/ 3 | .DS_Store 4 | build/ 5 | bower_components/ 6 | .idea 7 | cert/ 8 | -------------------------------------------------------------------------------- /src/assets/img/icons/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eatskolnikov/streamelopers/HEAD/src/assets/img/icons/favicon.ico -------------------------------------------------------------------------------- /src/assets/img/icons/apple-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eatskolnikov/streamelopers/HEAD/src/assets/img/icons/apple-icon.png -------------------------------------------------------------------------------- /src/assets/img/logos/logo-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eatskolnikov/streamelopers/HEAD/src/assets/img/logos/logo-icon.png -------------------------------------------------------------------------------- /src/assets/img/sponsors/agiles.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eatskolnikov/streamelopers/HEAD/src/assets/img/sponsors/agiles.png -------------------------------------------------------------------------------- /src/app/controllers/donatecontroller.js: -------------------------------------------------------------------------------- 1 | app.controller("DonateCtrl", [ '$window', '$scope', function($window,$scope) 2 | { 3 | }]); 4 | -------------------------------------------------------------------------------- /src/assets/img/icons/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eatskolnikov/streamelopers/HEAD/src/assets/img/icons/favicon-16x16.png -------------------------------------------------------------------------------- /src/assets/img/icons/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eatskolnikov/streamelopers/HEAD/src/assets/img/icons/favicon-32x32.png -------------------------------------------------------------------------------- /src/assets/img/icons/favicon-96x96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eatskolnikov/streamelopers/HEAD/src/assets/img/icons/favicon-96x96.png -------------------------------------------------------------------------------- /src/assets/img/icons/ms-icon-70x70.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eatskolnikov/streamelopers/HEAD/src/assets/img/icons/ms-icon-70x70.png -------------------------------------------------------------------------------- /src/assets/img/logos/logo-white-bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eatskolnikov/streamelopers/HEAD/src/assets/img/logos/logo-white-bg.png -------------------------------------------------------------------------------- /src/assets/img/icons/ms-icon-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eatskolnikov/streamelopers/HEAD/src/assets/img/icons/ms-icon-144x144.png -------------------------------------------------------------------------------- /src/assets/img/icons/ms-icon-150x150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eatskolnikov/streamelopers/HEAD/src/assets/img/icons/ms-icon-150x150.png -------------------------------------------------------------------------------- /src/assets/img/icons/ms-icon-310x310.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eatskolnikov/streamelopers/HEAD/src/assets/img/icons/ms-icon-310x310.png -------------------------------------------------------------------------------- /src/assets/img/sponsors/CodeCampSDQ2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eatskolnikov/streamelopers/HEAD/src/assets/img/sponsors/CodeCampSDQ2.jpg -------------------------------------------------------------------------------- /src/assets/img/icons/android-icon-36x36.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eatskolnikov/streamelopers/HEAD/src/assets/img/icons/android-icon-36x36.png -------------------------------------------------------------------------------- /src/assets/img/icons/android-icon-48x48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eatskolnikov/streamelopers/HEAD/src/assets/img/icons/android-icon-48x48.png -------------------------------------------------------------------------------- /src/assets/img/icons/android-icon-72x72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eatskolnikov/streamelopers/HEAD/src/assets/img/icons/android-icon-72x72.png -------------------------------------------------------------------------------- /src/assets/img/icons/android-icon-96x96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eatskolnikov/streamelopers/HEAD/src/assets/img/icons/android-icon-96x96.png -------------------------------------------------------------------------------- /src/assets/img/icons/apple-icon-114x114.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eatskolnikov/streamelopers/HEAD/src/assets/img/icons/apple-icon-114x114.png -------------------------------------------------------------------------------- /src/assets/img/icons/apple-icon-120x120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eatskolnikov/streamelopers/HEAD/src/assets/img/icons/apple-icon-120x120.png -------------------------------------------------------------------------------- /src/assets/img/icons/apple-icon-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eatskolnikov/streamelopers/HEAD/src/assets/img/icons/apple-icon-144x144.png -------------------------------------------------------------------------------- /src/assets/img/icons/apple-icon-152x152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eatskolnikov/streamelopers/HEAD/src/assets/img/icons/apple-icon-152x152.png -------------------------------------------------------------------------------- /src/assets/img/icons/apple-icon-180x180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eatskolnikov/streamelopers/HEAD/src/assets/img/icons/apple-icon-180x180.png -------------------------------------------------------------------------------- /src/assets/img/icons/apple-icon-57x57.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eatskolnikov/streamelopers/HEAD/src/assets/img/icons/apple-icon-57x57.png -------------------------------------------------------------------------------- /src/assets/img/icons/apple-icon-60x60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eatskolnikov/streamelopers/HEAD/src/assets/img/icons/apple-icon-60x60.png -------------------------------------------------------------------------------- /src/assets/img/icons/apple-icon-72x72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eatskolnikov/streamelopers/HEAD/src/assets/img/icons/apple-icon-72x72.png -------------------------------------------------------------------------------- /src/assets/img/icons/apple-icon-76x76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eatskolnikov/streamelopers/HEAD/src/assets/img/icons/apple-icon-76x76.png -------------------------------------------------------------------------------- /src/assets/img/icons/android-icon-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eatskolnikov/streamelopers/HEAD/src/assets/img/icons/android-icon-144x144.png -------------------------------------------------------------------------------- /src/assets/img/icons/android-icon-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eatskolnikov/streamelopers/HEAD/src/assets/img/icons/android-icon-192x192.png -------------------------------------------------------------------------------- /src/assets/img/icons/apple-icon-precomposed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eatskolnikov/streamelopers/HEAD/src/assets/img/icons/apple-icon-precomposed.png -------------------------------------------------------------------------------- /src/app/controllers/castcontroller.js: -------------------------------------------------------------------------------- 1 | app.controller("CastCtrl", ['$scope', '$http',"$timeout",'$filter', function($scope, $http, $timeout, $filter) 2 | { 3 | 4 | }]); 5 | -------------------------------------------------------------------------------- /src/app/views/cast/index.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |
5 | Streamelopers 6 |
7 |
8 |
9 |
10 | -------------------------------------------------------------------------------- /src/browserconfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | #ffffff 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/app/views/donate/index.html: -------------------------------------------------------------------------------- 1 |
2 | Streamelopers 3 | 4 | 5 |
6 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "streamelopers", 3 | "version": "0.0.1", 4 | "authors": [ 5 | "Enmanuel Toribio " 6 | ], 7 | "main": "src/index.html", 8 | "dependencies": { 9 | "jquery-2.1.4.min": "http://code.jquery.com/jquery-2.1.4.min.js", 10 | "angular-sanitize": "~1.4.7", 11 | "angular": "~1.4.7", 12 | "angular-route": "~1.4.7", 13 | "uikit": "~2.23.0", 14 | "papaparse": "~4.1.2", 15 | "firebase": "^2.4.2", 16 | "angularfire": "^1.2.0" 17 | }, 18 | "devDependencies": { 19 | "recordrtc": "^5.2.7" 20 | }, 21 | "resolutions": { 22 | "angular": "1.4.10" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /server.js: -------------------------------------------------------------------------------- 1 | var connect = require('connect'); 2 | var https = require('http'); 3 | var serveStatic = require('serve-static'); 4 | var crypto = require('crypto'); 5 | var fs = require("fs"); 6 | var app = connect(); 7 | var port = 8000; 8 | app.use( serveStatic("./build")); 9 | var options = { 10 | //key: fs.readFileSync('./cert/myserver.key'), 11 | // cert: fs.readFileSync('./cert/myserver.crt'), 12 | requestCert: false, 13 | rejectUnauthorized: false 14 | }; 15 | 16 | console.log("Serving ./build content on port " + port +". Go to https://localhost:" + port); 17 | //app.listen(port); 18 | 19 | https.createServer(options, app).listen(port); 20 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "streamelopers", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "src/index.html", 6 | "dependencies": { 7 | "angular-youtube-embed": "^1.1.1", 8 | "grunt": "^0.4.5" 9 | }, 10 | "devDependencies": { 11 | "connect": "*", 12 | "grunt-angular-templates": "^0.5.9", 13 | "grunt-contrib-clean": "^0.6.0", 14 | "grunt-contrib-concat": "^0.5.1", 15 | "grunt-contrib-copy": "^0.8.0", 16 | "grunt-contrib-cssmin": "^0.12.3", 17 | "grunt-contrib-htmlmin": "^0.4.0", 18 | "grunt-contrib-imagemin": "^1.0.0", 19 | "grunt-contrib-jshint": "^0.11.2", 20 | "grunt-contrib-uglify": "^0.9.1", 21 | "grunt-contrib-watch": "^0.6.1", 22 | "grunt-notify": "^0.4.1", 23 | "grunt-remove": "^0.1.0", 24 | "grunt-string-replace": "^1.2.1", 25 | "serve-static": "*", 26 | "vinyl-fs": "^2.2.1" 27 | }, 28 | "author": "Enmanuel Toribio" 29 | } 30 | -------------------------------------------------------------------------------- /src/assets/js/shared.js: -------------------------------------------------------------------------------- 1 | $(document).ready(function(){ 2 | var showModal = (Math.floor((Math.random() * 10) + 1) % 3) == 1; 3 | if(showModal) { 4 | if($("#modalDonate").data('show')){ 5 | $("#modalDonate").on({ 6 | 'show.uk.modal': function(){ 7 | $("#btnCloseModalDonate").removeAttr("disabled"); 8 | }, 9 | 'hide.uk.modal': function(){ 10 | } 11 | }); 12 | var modal = UIkit.modal("#modalDonate"); 13 | modal.options.bgclose=false; 14 | if (!modal.isActive()) 15 | { 16 | modal.show(); 17 | } 18 | } 19 | } 20 | }); 21 | var intallFirefoxScreenCapturingExtension = function () { 22 | InstallTrigger.install({ 23 | 'Foo': { 24 | URL: 'https://addons.mozilla.org/firefox/downloads/file/355418/enable_screen_capturing_in_firefox-1.0.006-fx.xpi?src=cb-dl-hotness', 25 | toString: function() { 26 | return this.URL; 27 | } 28 | } 29 | }); 30 | }; 31 | -------------------------------------------------------------------------------- /src/app/controllers/homecontroller.js: -------------------------------------------------------------------------------- 1 | app.controller("HomeCtrl", ['$scope', '$http','$filter', function($scope, $http, $filter) 2 | { 3 | var orderBy = $filter('orderBy'); 4 | this.getSuperDonors = function(value, index, array){ 5 | return value.Amount >= 60 && value['url a imagen']; 6 | }; 7 | this.playlists = []; 8 | this.donors = []; 9 | var playlistsUrl = '/playlists.json';//'https://www.googleapis.com/youtube/v3/playlists?key=AIzaSyAh2nl1KKOOliBVN0oTsnfzy1cZgtVdxhs&channelId=UCznWXigAvBa1ZtrgRmJGZgg&part=id,snippet&maxResults=24'; 10 | this.init = function(){ 11 | $http.get(playlistsUrl).success(angular.bind(this, function(data){ 12 | this.playlists = orderBy(data.items,'title', false); 13 | })); 14 | Papa.parse("/streamelopers_donations.csv?v=STREAMELOPERS_CURRENT_VERSION", { 15 | download: true, 16 | header: true, 17 | complete: angular.bind(this, function(results) { 18 | this.donors = orderBy(results.data,'Amount',true); 19 | }) 20 | }); 21 | }; 22 | this.init(); 23 | }]); 24 | -------------------------------------------------------------------------------- /src/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Streamelopers", 3 | "short_name": "Streamelopers", 4 | "start_url": "/index.html", 5 | "display": "stand_alone", 6 | "icons": [ 7 | { 8 | "src": "\/assets\/img\/icons\/android-icon-36x36.png", 9 | "sizes": "36x36", 10 | "type": "image\/png", 11 | "density": "0.75" 12 | }, 13 | { 14 | "src": "\/assets\/img\/icons\/android-icon-48x48.png", 15 | "sizes": "48x48", 16 | "type": "image\/png", 17 | "density": "1.0" 18 | }, 19 | { 20 | "src": "\/assets\/img\/icons\/android-icon-72x72.png", 21 | "sizes": "72x72", 22 | "type": "image\/png", 23 | "density": "1.5" 24 | }, 25 | { 26 | "src": "\/assets\/img\/icons\/android-icon-96x96.png", 27 | "sizes": "96x96", 28 | "type": "image\/png", 29 | "density": "2.0" 30 | }, 31 | { 32 | "src": "\/assets\/img\/icons\/android-icon-144x144.png", 33 | "sizes": "144x144", 34 | "type": "image\/png", 35 | "density": "3.0" 36 | }, 37 | { 38 | "src": "\/assets\/img\/icons\/android-icon-192x192.png", 39 | "sizes": "192x192", 40 | "type": "image\/png", 41 | "density": "4.0" 42 | } 43 | ] 44 | } 45 | -------------------------------------------------------------------------------- /src/streamelopers_donations.csv: -------------------------------------------------------------------------------- 1 | Name,First Name,Last Name,Amount,Comment,Date Donated,url,��_��__��_��__quieres suscribirte a nuestro bolet��_��__��_��_n?,url a imagen Arturo Mejia Marmol,Arturo,Mejia Marmol,25,,2015-12-28 19:31:26 UTC,#,, CodeCampSDQ,CodeCampSDQ,Conf,300,,2016-02-10 19:31:26 UTC,http://codecampsdq.com/,,./assets/img/sponsors/CodeCampSDQ2.jpg Mitra Mejia,Mitra,Mejia,10,,2016-01-30 21:34:30 UTC,,, Jhonatas Miguel Rodríguez,Jhonatas Miguel,Rodriguez,20,,2016-01-30 21:34:30 UTC,,, Jhuliano Skittberg Moreno,Jhuliano Skittberg,Moreno,10,,2016-01-30 21:34:30 UTC,,, Alberto Espinal Cruz,Alberto Espinal,Cruz,10,,2016-01-30 21:34:30 UTC,,, Efraín Reyes,Efrain,Reyes,45,,2016-02-25 20:05:30 UTC,https://github.com/EfrainReyes,, Yeral Yamil,Yeral,Yamil,25,,2016-02-25 20:05:30 UTC,https://www.linkedin.com/in/yeralyamil,, Frankely Diaz,Frankely,Diaz,60,,2016-02-26 18:53:30 UTC,https://www.facebook.com/agilesrd,,./assets/img/sponsors/agiles.png Francis Brito,Francis,Brito,60,,2016-02-26 18:53:30 UTC,https://github.com/francisbrito,, Raul Roa,Raul,Roa,20,,2016-03-16 01:07:39 UTC,http://portfolio.mrroa.com,"",http://blog.mrroa.com/content/images/2014/Oct/about-me4.jpg -------------------------------------------------------------------------------- /src/app/views/recording/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
5 | 6 | 7 | 8 | 9 | 10 |
11 | -------------------------------------------------------------------------------- /src/app/routes.js: -------------------------------------------------------------------------------- 1 | app.config(['$routeProvider','$locationProvider', function($routeProvider, $locationProvider) { 2 | $routeProvider 3 | .when('/', { 4 | templateUrl: 'src/app/views/home/index.html', 5 | controller: 'HomeCtrl', 6 | controllerAs: 'home' 7 | }) 8 | /* .when('/recording', { 9 | templateUrl: 'src/app/views/recording/index.html', 10 | controller: 'RecordingCtrl', 11 | controllerAs: 'recording' 12 | }) 13 | .when('/cast', { 14 | templateUrl: 'src/app/views/cast/index.html', 15 | controller: 'CastCtrl', 16 | controllerAs: 'cast' 17 | })*/ 18 | .when('/donate', { 19 | //templateUrl: 'src/app/views/donate/index.html', 20 | //controller: 'DonateCtrl', 21 | //controllerAs: 'donate' 22 | redirectTo: "https://www.patreon.com/streamelopers" 23 | }) 24 | .when('/_=_', { 25 | redirectTo: '/' 26 | }) 27 | .otherwise({ 28 | templateUrl: 'src/app/views/404.html', 29 | }); 30 | $locationProvider.html5Mode({ 31 | enabled: true 32 | }); 33 | }]); 34 | -------------------------------------------------------------------------------- /src/sw.js: -------------------------------------------------------------------------------- 1 | var CACHE_NAME = 'my-site-cache-vSTREAMELOPERS_CURRENT_VERSION'; 2 | var urlsToCache = [ 3 | '/assets/img/logos/logo-white-bg.png', 4 | '/assets/css/main.min.css?v=STREAMELOPERS_CURRENT_VERSION', 5 | '/app.min.js?v=STREAMELOPERS_CURRENT_VERSION' 6 | ]; 7 | self.addEventListener('install', function(event) { 8 | event.waitUntil( 9 | caches.open(CACHE_NAME) 10 | .then(function(cache) { 11 | return cache.addAll(urlsToCache); 12 | }) 13 | ); 14 | }); 15 | self.addEventListener('fetch', function(event) { 16 | event.respondWith( 17 | caches.match(event.request) 18 | .then(function(response) { 19 | if (response) { 20 | return response; 21 | } 22 | var fetchRequest = event.request.clone(); 23 | return fetch(fetchRequest).then( 24 | function(response) { 25 | if(!response || response.status !== 200 || response.type !== 'basic') { 26 | return response; 27 | } 28 | var responseToCache = response.clone(); 29 | 30 | caches.open(CACHE_NAME) 31 | .then(function(cache) { 32 | cache.put(event.request, responseToCache); 33 | }); 34 | return response; 35 | }); 36 | }) 37 | ); 38 | }); 39 | -------------------------------------------------------------------------------- /src/assets/css/style.css: -------------------------------------------------------------------------------- 1 | .streamingContainer iframe 2 | { 3 | min-height: 400px; 4 | height: 100%; 5 | } 6 | .signup-form input, .signup-form input[type=email]{ 7 | margin-right: 0; 8 | border-top-right-radius: 0; 9 | border-bottom-right-radius: 0; 10 | } 11 | .signup-form button{ 12 | margin-left: 0; 13 | border-top-left-radius: 0; 14 | border-bottom-left-radius: 0; 15 | } 16 | .uk-navbar{ 17 | background:0; 18 | } 19 | 20 | 21 | .navbar-logo{ 22 | width:140px; 23 | } 24 | 25 | .shadowed-text{ 26 | text-shadow: -1px 0 black, 0 1px black, 1px 0 black, 0 -1px black; 27 | } 28 | 29 | #desktop{ 30 | width:1280px; 31 | height:720px; 32 | left:0; 33 | top:0; 34 | background:black; 35 | position:absolute; 36 | } 37 | #camera{ 38 | height:240px; 39 | left:0; 40 | top:478px; 41 | border:1px white solid; 42 | position:absolute; 43 | } 44 | .control-panel{ 45 | position: absolute; 46 | top: 10px; 47 | left: 5px; 48 | width:100%; 49 | } 50 | #btnFirefoxExtension{ 51 | position:absolute; 52 | right:15px; 53 | } 54 | 55 | .donor-image-big{ 56 | width:300px; 57 | display:block; 58 | } 59 | .donor-image{ 60 | width:150px; 61 | display:block; 62 | } 63 | 64 | .list-inline>li{ 65 | display: inline-block; 66 | padding-right:5px; 67 | } 68 | 69 | @media(max-width:400px){ 70 | #content{ 71 | padding: 0 5px; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | # Streamelopers 2 | About 3 | ============== 4 | 5 | [Streamelopers](https://streamelopers.org) is a project made to support the Dominican software development community by providing access to talks and workshops to those who missed them. It has the intention to become a video index site and streaming platform. 6 | 7 | Setup and installation for development 8 | ============== 9 | 10 | Install nodejs 11 | -------------- 12 | [Here](https://goo.gl/YcOsZP) you can check how to do so. There's an issue when installing Node in Ubuntu, check it out how to solve it [here](https://goo.gl/uSfZXo) 13 | 14 | Open the command line and update npm 15 | -------------- 16 | 17 | ```shell 18 | npm install npm -g 19 | ``` 20 | 21 | Install bower 22 | -------------- 23 | 24 | ```shell 25 | npm install -g bower 26 | ``` 27 | 28 | **Before proceeding make sure you are in the project's root folder within the terminal** 29 | 30 | Install npm packages 31 | -------------- 32 | 33 | ```shell 34 | npm install 35 | ``` 36 | 37 | Install bower packages 38 | -------------- 39 | 40 | ```shell 41 | bower install 42 | ``` 43 | 44 | Building 45 | -------------- 46 | 47 | ```shell 48 | grunt build 49 | ``` 50 | 51 | You can run the build task with this. It will validate js files and create a build folder where it will copy all the css, js, images and html minified. 52 | 53 | Watching 54 | -------------- 55 | 56 | ```shell 57 | grunt watch 58 | ``` 59 | 60 | Watches any changes made to code files inside the src/ folder. If the watcher sees a change it starts the building process 61 | 62 | Security 63 | -------------- 64 | 65 | Some features (like webRTC and ServiceWorker) only work with https so you need to install a security certificate, follow the instructions (here)[https://gist.github.com/kyledrake/d7457a46a03d7408da31] 66 | Running 67 | -------------- 68 | 69 | ```shell 70 | npm start 71 | ``` 72 | 73 | Executes the "node server.js" command and serve the content of the ./build directory via the port 8000 , accessible via https://localhost:8000 74 | -------------------------------------------------------------------------------- /src/.htaccess: -------------------------------------------------------------------------------- 1 | RewriteEngine on 2 | #RewriteCond %{HTTPS} off 3 | #RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L] 4 | RewriteCond %{REQUEST_FILENAME} -s [OR] 5 | RewriteCond %{REQUEST_FILENAME} -l [OR] 6 | RewriteCond %{REQUEST_FILENAME} -d 7 | RewriteRule ^.*$ - [NC,L] 8 | RewriteRule ^(.*) /index.html [NC,L] 9 | 10 | 11 | SetOutputFilter DEFLATE 12 | SetEnvIfNoCase Request_URI \ 13 | \.(?:gif|jpe?g|png)$ no-gzip dont-vary 14 | AddOutputFilterByType DEFLATE text/html 15 | AddOutputFilterByType DEFLATE text/plain 16 | AddOutputFilterByType DEFLATE text/xml 17 | AddOutputFilterByType DEFLATE text/css 18 | AddOutputFilterByType DEFLATE application/x-javascript 19 | AddOutputFilterByType DEFLATE application/xhtml+xml 20 | AddOutputFilterByType DEFLATE text/javascript 21 | AddOutputFilterByType DEFLATE text/x-js 22 | AddOutputFilterByType DEFLATE text/js 23 | AddOutputFilterByType DEFLATE application/json 24 | AddOutputFilterByType DEFLATE application/xml 25 | AddOutputFilterByType DEFLATE application/javascript 26 | 27 | 28 | 29 | ExpiresActive on 30 | ExpiresByType image/jpg "access 2 month" 31 | ExpiresByType image/gif "access 2 month" 32 | ExpiresByType image/jpeg "access 2 month" 33 | ExpiresByType image/png "access 2 month" 34 | ExpiresByType text/css "access 2 month" 35 | ExpiresByType application/font-woff "access 2 month" 36 | ExpiresByType application/x-font-woff "access 2 month" 37 | 38 | ExpiresByType text/js "access plus 2 month" 39 | ExpiresByType text/javascript "access plus 2 month" 40 | ExpiresByType application/javascript "access plus 2 month" 41 | ExpiresByType application/x-javascript "access plus 2 month" 42 | 43 | ExpiresByType image/x-icon "access plus 12 month" 44 | ExpiresByType image/icon "access plus 12 month" 45 | ExpiresByType application/x-ico "access plus 12 month" 46 | ExpiresByType application/ico "access plus 12 month" 47 | 48 | 49 | 50 | 51 | Header append Vary: Accept-Encoding 52 | 53 | 54 | 55 | mod_gzip_on Yes 56 | mod_gzip_dechunk Yes 57 | mod_gzip_item_include file .(html?|txt|css|js|php|pl)$ 58 | mod_gzip_item_include handler ^cgi-script$ 59 | mod_gzip_item_include mime ^text/.* 60 | mod_gzip_item_include mime ^application/x-javascript.* 61 | mod_gzip_item_exclude mime ^image/.* 62 | mod_gzip_item_exclude rspheader ^Content-Encoding:.*gzip.* 63 | 64 | -------------------------------------------------------------------------------- /src/app/views/home/index.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |
5 |
6 | Streamelopers 7 | 18 |
19 |
20 |
21 |
22 |
23 |
24 | 25 |
26 |
27 |
28 |
29 |
30 |
31 |

Transmisiones anteriores

32 |
33 | 43 |
44 |
45 |
46 |
47 |

Estamos aquí gracias a las contribuciones de

48 |
49 |
50 | 57 |
58 |
59 | 65 |
66 |
67 |
68 |
69 | -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | Streamelopers 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 39 | 40 | 41 | 60 | 61 |
62 |
63 | Streamelopers
64 | 65 |
66 |
67 | 68 | 73 | 74 | 75 | 83 | 84 | 98 | 99 | -------------------------------------------------------------------------------- /src/app/controllers/recordingcontroller.js: -------------------------------------------------------------------------------- 1 | app.controller("RecordingCtrl", ['$scope', '$http',"$timeout",'$filter', function($scope, $http, $timeout, $filter) 2 | { 3 | $(document).mousemove(function(event) { 4 | if(event.clientY < 200){ 5 | $(".control-panel").fadeIn(); 6 | }else{ 7 | $(".control-panel").fadeOut(); 8 | } 9 | }); 10 | var recordedBlobs = { 11 | camera:[], 12 | desktop:[] 13 | }; 14 | var downloadHandler = function (name){ 15 | return function(){ 16 | console.log(name); 17 | console.log(recordedBlobs.camera); 18 | var blob = new Blob(recordedBlobs.camera, {type: 'video/mpeg4'}); 19 | var url = window.URL.createObjectURL(blob); 20 | var a = document.createElement('a'); 21 | a.style.display = 'none'; 22 | a.href = url; 23 | a.download = name+'.webm'; 24 | document.body.appendChild(a); 25 | a.click(); 26 | setTimeout(function() { 27 | document.body.removeChild(a); 28 | window.URL.revokeObjectURL(url); 29 | }, 100); 30 | }; 31 | }; 32 | var mediaSource = new MediaSource(); 33 | mediaSource.addEventListener('sourceopen', function(){ 34 | mediaSource.addSourceBuffer('video/mpeg4'); 35 | }, false); 36 | var mediaRecorder; 37 | var sourceBuffer; 38 | var recordedVideo = document.getElementById('recordedVideo'); 39 | var recordButton = document.getElementById('btnRecord'); 40 | var playButton = document.getElementById('btnPlay'); 41 | var downloadButton = document.getElementById('btnDownloadDesktop'); 42 | var downloadCameraButton = document.getElementById('btnDownloadCamera'); 43 | var camera = document.getElementById("camera"); 44 | var cameraRecorder; 45 | var desktop = document.getElementById("desktop"); 46 | var desktopStream; 47 | var desktopRecorder; 48 | 49 | var gotStream = function(videoElement, mediaStream, callback){ 50 | return function(stream){ 51 | window[mediaStream] = stream; 52 | videoElement.src = window.URL.createObjectURL(stream); 53 | videoElement.play(); 54 | if(typeof(callback)!=='undefined'){ 55 | callback(); 56 | } 57 | }; 58 | }; 59 | var errorHandler = function(error){ 60 | console.log('navigator.getUserMedia error: '); 61 | console.log(error); 62 | }; 63 | var handleDataAvailable = function(blob){ 64 | return function (event) { 65 | console.log(blob); 66 | if (event.data && event.data.size > 0) { 67 | blob.push(event.data); 68 | } 69 | }; 70 | }; 71 | var toggleRecording = function() { 72 | if (recordButton.style.color === 'red') { 73 | startRecording(); 74 | } else { 75 | stopRecording(); 76 | } 77 | }; 78 | 79 | var startRecording = function () { 80 | var options = {mimeType: 'video/mpeg4'}; 81 | recordedBlobs.camera = []; 82 | recordedBlobs.desktop = []; 83 | console.log("cameraStream"); 84 | console.log(cameraStream); 85 | var cameraStream = window.cameraStream; 86 | try { 87 | cameraRecorder = new MediaRecorder(cameraStream, options); 88 | } catch (e0) { 89 | console.log('Unable to create MediaRecorder with options Object: ', e0); 90 | try { 91 | options = {mimeType: 'video/webm,codecs=vp9'}; 92 | cameraRecorder = new MediaRecorder(cameraStream, options); 93 | } catch (e1) { 94 | console.log('Unable to create MediaRecorder with options Object: ', e1); 95 | try { 96 | options = 'video/vp8'; 97 | cameraRecorder = new MediaRecorder(cameraStream, options); 98 | } catch (e2) { 99 | alert('MediaRecorder is not supported by this browser.\n\n' + 100 | 'Try Firefox 29 or later, or Chrome 47 or later, with Enable experimental Web Platform features enabled from chrome://flags.'); 101 | console.error('Exception while creating MediaRecorder:', e2); 102 | return false; 103 | } 104 | } 105 | } 106 | console.log('Created MediaRecorder', mediaRecorder, 'with options', options); 107 | recordButton.innerHTML = ''; 108 | recordButton.style.color="blue"; 109 | playButton.disabled = true; 110 | downloadButton.disabled = true; 111 | downloadCameraButton.disabled = false; 112 | cameraRecorder.ondataavailable = handleDataAvailable(recordedBlobs.camera); 113 | cameraRecorder.start(10); // collect 10ms of data 114 | console.log('MediaRecorder started', cameraRecorder); 115 | return true; 116 | }; 117 | var stopRecording = function () { 118 | cameraRecorder.stop(); 119 | recordButton.innerHTML = ''; 120 | recordButton.style.color = 'red'; 121 | playButton.disabled = false; 122 | downloadButton.disabled = false; 123 | downloadCameraButton.disabled = false; 124 | // recordedVideo.controls = true; 125 | }; 126 | 127 | var play = function () { 128 | var superBuffer = new Blob(recordedBlobs.camera, {type: 'video/webm'}); 129 | recordedVideo.src = window.URL.createObjectURL(superBuffer); 130 | }; 131 | var userMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mediaDevices.getUserMedia || navigator.msGetUserMedia; 132 | this.init = function() 133 | { 134 | recordButton.onclick = toggleRecording; 135 | playButton.onclick = play; 136 | downloadButton.onclick = downloadHandler("desktop"); 137 | downloadCameraButton.onclick = downloadHandler("camera"); 138 | window.postMessage({ 139 | enableScreenCapturing: true, 140 | domains: ["streamelopers.org", "stream.meta.do", "localhost"] 141 | }, "*"); 142 | }; 143 | this.init(); 144 | getScreenId(function (error, sourceId, screen_constraints) { 145 | if(sourceId === "firefox"){ 146 | screen_constraints.video.mediaSource = "screen"; 147 | } 148 | var captureScreen = function(){ 149 | navigator.getUserMedia(screen_constraints, gotStream(desktop, 'desktopStream'), errorHandler); 150 | }; 151 | navigator.getUserMedia({video:true, audio:true }, gotStream(camera, 'cameraStream', captureScreen), errorHandler); 152 | }); 153 | }]); 154 | -------------------------------------------------------------------------------- /Gruntfile.js: -------------------------------------------------------------------------------- 1 | module.exports = function(grunt) { 2 | var pad = function (number, length) { 3 | var str = '' + number; 4 | while (str.length < length) { 5 | str = '0' + str; 6 | } 7 | return str; 8 | }; 9 | Date.prototype.YYYYMMDDHHMMSS = function () { 10 | var yyyy = this.getFullYear().toString(); 11 | var MM = pad(this.getMonth() + 1,2); 12 | var dd = pad(this.getDate(), 2); 13 | var hh = pad(this.getHours(), 2); 14 | var mm = pad(this.getMinutes(), 2); 15 | var ss = pad(this.getSeconds(), 2); 16 | return yyyy + MM + dd+ hh + mm + ss; 17 | }; 18 | var date = new Date().YYYYMMDDHHMMSS(); 19 | grunt.initConfig({ 20 | pkg: grunt.file.readJSON('package.json'), 21 | jshint: { 22 | all: ['Gruntfile.js', 'src/app/**/*.js', 'src/sw.js'] 23 | }, 24 | watch: { 25 | build: { 26 | files: ['src/**/*.js','src/**/*.css', 'src/**/*.html', 'src/**/*.json'], 27 | tasks: ['jshint', 'clean:build', 'ngtemplates', 'concat', 'uglify', 'cssmin', 'htmlmin', 'copy', 'imagemin', 'string-replace'], 28 | options: { 29 | spawn: false 30 | } 31 | } 32 | }, 33 | cssmin: { 34 | target: { 35 | files: [{ 36 | expand: true, 37 | report: 'gzip', 38 | cwd: 'build/assets/css', 39 | src: ['*.css', '!*.min.css'], 40 | dest: 'build/assets/css', 41 | ext: '.min.css' 42 | }] 43 | } 44 | }, 45 | concat: { 46 | options: { 47 | separator: '\n' 48 | }, 49 | css: { 50 | src: ['bower_components/uikit/css/uikit.min.css', 51 | 'bower_components/uikit/css/uikit.almost-flat.min.css', 52 | 'src/assets/css/style.css'], 53 | dest: 'build/assets/css/main.css' 54 | }, 55 | app:{ 56 | src:['bower_components/jquery-2.1.4.min/index.js', 57 | 'bower_components/uikit/js/uikit.min.js', 58 | 'bower_components/papaparse/papaparse.min.js', 59 | 'bower_components/angular/angular.min.js', 60 | 'bower_components/angular-route/angular-route.min.js', 61 | 'bower_components/firebase/firebase.js', 62 | 'bower_components/angularfire/dist/angularfire.min.js', 63 | 'bower_components/recordrtc/RecordRTC.min.js', 64 | 'src/assets/js/shared.js', 65 | 'src/app/app.js', 66 | 'build/templates.js', 67 | 'src/app/routes.js', 68 | 'src/app/controllers/*'], 69 | dest:'build/app.js' 70 | } 71 | }, 72 | ngtemplates: { 73 | StreamelopersApp:{ 74 | src: 'src/app/views/**/*.html', 75 | dest: 'build/templates.js', 76 | options: { 77 | htmlmin: { collapseWhitespace: true, removeComments: true } 78 | } 79 | } 80 | }, 81 | uglify: { 82 | app:{ 83 | src: 'build/app.js', 84 | dest: 'build/app.min.js' 85 | } 86 | }, 87 | htmlmin: { 88 | main: { 89 | options: { 90 | removeIgnored: true, 91 | removeEmptyAttributes: false, 92 | removeComments: true, 93 | collapseWhitespace: true 94 | }, 95 | files: { 96 | 'build/index.html': 'src/index.html' 97 | } 98 | } 99 | }, 100 | copy: { 101 | main: { 102 | files: [ 103 | {expand: true, flatten: true, src: ['src/.htaccess'], dest: 'build/', filter: 'isFile'}, 104 | {expand: true, flatten: true, src: ['bower_components/uikit/fonts/*'], dest: 'build/assets/fonts', filter:'isFile'}, 105 | {expand: true, flatten: true, src: ['src/manifest.json'], dest: 'build/', filter:'isFile'}, 106 | {expand: true, flatten: true, src: ['src/browserconfig.xml'], dest: 'build/', filter:'isFile'}, 107 | {expand: true, flatten: true, src: ['src/streamelopers_donations.csv'], dest: 'build/', filter:'isFile'}, 108 | {expand: true, flatten: true, src: ['src/google17e988616126521e.html'], dest: 'build/', filter:'isFile'}, 109 | {expand: true, flatten: true, src: ['src/sw.js'], dest: 'build/', filter:'isFile'}, 110 | {expand: true, flatten: true, src: ['src/playlists.json'], dest: 'build/', filter:'isFile'} 111 | ] 112 | } 113 | }, 114 | clean:{ 115 | build: { 116 | src:['build/'] 117 | } 118 | }, 119 | imagemin: { 120 | options: { 121 | optimizationLevel: 5 122 | }, 123 | dynamic: { 124 | files: [{ 125 | expand: true, 126 | cwd: 'src/', 127 | src: ['**/*.{png,jpg,gif,ico}'], 128 | dest: 'build' 129 | }] 130 | } 131 | }, 132 | notify_hooks: { 133 | options: { 134 | enabled: true, 135 | max_jshint_notifications: 5, 136 | duration: 3 137 | } 138 | }, 139 | remove: { 140 | clean: { 141 | trace: true, 142 | fileList: ['build/app.js', 'build/assets/css/main.css', 'build/templates.js'] 143 | } 144 | }, 145 | 'string-replace':{ 146 | dist:{ 147 | files:[{ 148 | expand:true, 149 | cwd:'build/', 150 | src: ['**/*.js','**/*.html'], 151 | dest:'build/' 152 | }], 153 | options: { 154 | replacements: [{ 155 | pattern: /STREAMELOPERS_CURRENT_VERSION/ig, 156 | replacement: date 157 | },{ 158 | pattern: /STREAMELOPERS_CURRENT_VERSION/ig, 159 | replacement: date 160 | }] 161 | } 162 | } 163 | } 164 | }); 165 | grunt.loadNpmTasks('grunt-string-replace'); 166 | grunt.loadNpmTasks('grunt-angular-templates'); 167 | grunt.loadNpmTasks('grunt-contrib-clean'); 168 | grunt.loadNpmTasks('grunt-contrib-concat'); 169 | grunt.loadNpmTasks('grunt-contrib-copy'); 170 | grunt.loadNpmTasks('grunt-contrib-cssmin'); 171 | grunt.loadNpmTasks('grunt-contrib-htmlmin'); 172 | grunt.loadNpmTasks('grunt-contrib-imagemin'); 173 | grunt.loadNpmTasks('grunt-contrib-jshint'); 174 | grunt.loadNpmTasks('grunt-contrib-uglify'); 175 | grunt.loadNpmTasks('grunt-contrib-watch'); 176 | grunt.loadNpmTasks('grunt-notify'); 177 | grunt.loadNpmTasks('grunt-remove'); 178 | grunt.registerTask('build', function () { 179 | grunt.task.run(['jshint', 'clean:build', 'ngtemplates', 'concat', 'uglify', 'cssmin', 'htmlmin', 'copy', 'imagemin', 'remove', 'string-replace']); 180 | }); 181 | grunt.registerTask('default', ['watch']); 182 | }; 183 | -------------------------------------------------------------------------------- /src/playlists.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "youtube#playlistListResponse", 3 | "etag": "\"I_8xdZu766_FSaexEaDXTIfEWc0/WjN-9mKXhXvIdBXFdViwx-XmlX8\"", 4 | "pageInfo": { 5 | "totalResults": 11, 6 | "resultsPerPage": 24 7 | }, 8 | "items": [ 9 | { 10 | "kind": "youtube#playlist", 11 | "etag": "\"I_8xdZu766_FSaexEaDXTIfEWc0/cDT3lPFES7i8SW_vkZhuJXH0EmQ\"", 12 | "id": "PLW-4dWdTuQryqh6JPM9UfDBJ5HaTsYkM6", 13 | "snippet": { 14 | "publishedAt": "2016-05-08T17:33:09.000Z", 15 | "channelId": "UCznWXigAvBa1ZtrgRmJGZgg", 16 | "title": "DEVCA2016 Webinars", 17 | "description": "Webinars del eventp DEVCA2016", 18 | "thumbnails": { 19 | "default": { 20 | "url": "https://i.ytimg.com/vi/0csOoum0fq8/default.jpg", 21 | "width": 120, 22 | "height": 90 23 | }, 24 | "medium": { 25 | "url": "https://i.ytimg.com/vi/0csOoum0fq8/mqdefault.jpg", 26 | "width": 320, 27 | "height": 180 28 | }, 29 | "high": { 30 | "url": "https://i.ytimg.com/vi/0csOoum0fq8/hqdefault.jpg", 31 | "width": 480, 32 | "height": 360 33 | }, 34 | "standard": { 35 | "url": "https://i.ytimg.com/vi/0csOoum0fq8/sddefault.jpg", 36 | "width": 640, 37 | "height": 480 38 | }, 39 | "maxres": { 40 | "url": "https://i.ytimg.com/vi/0csOoum0fq8/maxresdefault.jpg", 41 | "width": 1280, 42 | "height": 720 43 | } 44 | }, 45 | "channelTitle": "Streamelopers", 46 | "localized": { 47 | "title": "DEVCA2016 Webinars", 48 | "description": "Webinars del eventp DEVCA2016" 49 | } 50 | } 51 | }, 52 | { 53 | "kind": "youtube#playlist", 54 | "etag": "\"I_8xdZu766_FSaexEaDXTIfEWc0/Xd4_dYiGs73s7oJ5ooVAHR2BD9g\"", 55 | "id": "PLW-4dWdTuQrz2bNrZdhotuw-p6F6LlIlj", 56 | "snippet": { 57 | "publishedAt": "2016-04-27T14:12:44.000Z", 58 | "channelId": "UCznWXigAvBa1ZtrgRmJGZgg", 59 | "title": "Python Dominicana", 60 | "description": "Videos de la comunidad de Python dominicana", 61 | "thumbnails": { 62 | "default": { 63 | "url": "https://i.ytimg.com/vi/EEVleKeDv_I/default.jpg", 64 | "width": 120, 65 | "height": 90 66 | }, 67 | "medium": { 68 | "url": "https://i.ytimg.com/vi/EEVleKeDv_I/mqdefault.jpg", 69 | "width": 320, 70 | "height": 180 71 | }, 72 | "high": { 73 | "url": "https://i.ytimg.com/vi/EEVleKeDv_I/hqdefault.jpg", 74 | "width": 480, 75 | "height": 360 76 | }, 77 | "standard": { 78 | "url": "https://i.ytimg.com/vi/EEVleKeDv_I/sddefault.jpg", 79 | "width": 640, 80 | "height": 480 81 | } 82 | }, 83 | "channelTitle": "Streamelopers", 84 | "localized": { 85 | "title": "Python Dominicana", 86 | "description": "Videos de la comunidad de Python dominicana" 87 | } 88 | } 89 | }, 90 | { 91 | "kind": "youtube#playlist", 92 | "etag": "\"I_8xdZu766_FSaexEaDXTIfEWc0/M4RE9i2A4tqfSshH4rheJ2tzX7s\"", 93 | "id": "PLW-4dWdTuQryzhz1YWfb-JLKmah1f5l1k", 94 | "snippet": { 95 | "publishedAt": "2016-02-09T12:37:15.000Z", 96 | "channelId": "UCznWXigAvBa1ZtrgRmJGZgg", 97 | "title": "Emplea.do", 98 | "description": "emplea.do es un proyecto open source de la comunidad de desarrolladores dominicanos para el mundo. Pull-requests are welcome from everyone https://github.com/developersdo/empleo-dot-net", 99 | "thumbnails": { 100 | "default": { 101 | "url": "https://i.ytimg.com/vi/2QtPf4wQtVo/default.jpg", 102 | "width": 120, 103 | "height": 90 104 | }, 105 | "medium": { 106 | "url": "https://i.ytimg.com/vi/2QtPf4wQtVo/mqdefault.jpg", 107 | "width": 320, 108 | "height": 180 109 | }, 110 | "high": { 111 | "url": "https://i.ytimg.com/vi/2QtPf4wQtVo/hqdefault.jpg", 112 | "width": 480, 113 | "height": 360 114 | }, 115 | "standard": { 116 | "url": "https://i.ytimg.com/vi/2QtPf4wQtVo/sddefault.jpg", 117 | "width": 640, 118 | "height": 480 119 | } 120 | }, 121 | "channelTitle": "Streamelopers", 122 | "localized": { 123 | "title": "Emplea.do", 124 | "description": "emplea.do es un proyecto open source de la comunidad de desarrolladores dominicanos para el mundo. Pull-requests are welcome from everyone https://github.com/developersdo/empleo-dot-net" 125 | } 126 | } 127 | }, 128 | { 129 | "kind": "youtube#playlist", 130 | "etag": "\"I_8xdZu766_FSaexEaDXTIfEWc0/ZL0CEb6Fe-2xfILmQGnadYeziDY\"", 131 | "id": "PLW-4dWdTuQrz5tI5G-sLirxOQHqxQzQph", 132 | "snippet": { 133 | "publishedAt": "2016-01-19T03:01:57.000Z", 134 | "channelId": "UCznWXigAvBa1ZtrgRmJGZgg", 135 | "title": "UI/UX", 136 | "description": "", 137 | "thumbnails": { 138 | "default": { 139 | "url": "https://i.ytimg.com/vi/TzMdISyYtw4/default.jpg", 140 | "width": 120, 141 | "height": 90 142 | }, 143 | "medium": { 144 | "url": "https://i.ytimg.com/vi/TzMdISyYtw4/mqdefault.jpg", 145 | "width": 320, 146 | "height": 180 147 | }, 148 | "high": { 149 | "url": "https://i.ytimg.com/vi/TzMdISyYtw4/hqdefault.jpg", 150 | "width": 480, 151 | "height": 360 152 | } 153 | }, 154 | "channelTitle": "Streamelopers", 155 | "localized": { 156 | "title": "UI/UX", 157 | "description": "" 158 | } 159 | } 160 | }, 161 | { 162 | "kind": "youtube#playlist", 163 | "etag": "\"I_8xdZu766_FSaexEaDXTIfEWc0/AlXyCcCR3DgCmzK_33xZJXUW0CE\"", 164 | "id": "PLW-4dWdTuQrxhXPpa-3SaQkQgfgTuH9bL", 165 | "snippet": { 166 | "publishedAt": "2015-12-30T13:56:32.000Z", 167 | "channelId": "UCznWXigAvBa1ZtrgRmJGZgg", 168 | "title": "GNU/Linux", 169 | "description": "Charlas y actividades de la comunidad de Linux Dominicana, puedes enterarte de más actividades en el grupo de facebook https://www.facebook.com/groups/GNULinuxDominicana/", 170 | "thumbnails": { 171 | "default": { 172 | "url": "https://i.ytimg.com/vi/mCUUZvSEW48/default.jpg", 173 | "width": 120, 174 | "height": 90 175 | }, 176 | "medium": { 177 | "url": "https://i.ytimg.com/vi/mCUUZvSEW48/mqdefault.jpg", 178 | "width": 320, 179 | "height": 180 180 | }, 181 | "high": { 182 | "url": "https://i.ytimg.com/vi/mCUUZvSEW48/hqdefault.jpg", 183 | "width": 480, 184 | "height": 360 185 | } 186 | }, 187 | "channelTitle": "Streamelopers", 188 | "localized": { 189 | "title": "GNU/Linux", 190 | "description": "Charlas y actividades de la comunidad de Linux Dominicana, puedes enterarte de más actividades en el grupo de facebook https://www.facebook.com/groups/GNULinuxDominicana/" 191 | } 192 | } 193 | }, 194 | { 195 | "kind": "youtube#playlist", 196 | "etag": "\"I_8xdZu766_FSaexEaDXTIfEWc0/r6o6y3iw2BE7jP0F-fQb5Ro6fm4\"", 197 | "id": "PLW-4dWdTuQrzjrCg0iPmdVoBiAJ_YE670", 198 | "snippet": { 199 | "publishedAt": "2015-12-29T01:21:27.000Z", 200 | "channelId": "UCznWXigAvBa1ZtrgRmJGZgg", 201 | "title": "CDDV", 202 | "description": "Comunidad Dominicana de Desarrolladores de Videojuegos", 203 | "thumbnails": { 204 | "default": { 205 | "url": "https://i.ytimg.com/vi/Y4wEeRGming/default.jpg", 206 | "width": 120, 207 | "height": 90 208 | }, 209 | "medium": { 210 | "url": "https://i.ytimg.com/vi/Y4wEeRGming/mqdefault.jpg", 211 | "width": 320, 212 | "height": 180 213 | }, 214 | "high": { 215 | "url": "https://i.ytimg.com/vi/Y4wEeRGming/hqdefault.jpg", 216 | "width": 480, 217 | "height": 360 218 | }, 219 | "standard": { 220 | "url": "https://i.ytimg.com/vi/Y4wEeRGming/sddefault.jpg", 221 | "width": 640, 222 | "height": 480 223 | }, 224 | "maxres": { 225 | "url": "https://i.ytimg.com/vi/Y4wEeRGming/maxresdefault.jpg", 226 | "width": 1280, 227 | "height": 720 228 | } 229 | }, 230 | "channelTitle": "Streamelopers", 231 | "localized": { 232 | "title": "CDDV", 233 | "description": "Comunidad Dominicana de Desarrolladores de Videojuegos" 234 | } 235 | } 236 | }, 237 | { 238 | "kind": "youtube#playlist", 239 | "etag": "\"I_8xdZu766_FSaexEaDXTIfEWc0/tMpcKOYTqFUs1gIrWfxygUgtNt0\"", 240 | "id": "PLW-4dWdTuQryBWRITX1CLFj-QxNXGsQ2x", 241 | "snippet": { 242 | "publishedAt": "2015-12-22T16:50:02.000Z", 243 | "channelId": "UCznWXigAvBa1ZtrgRmJGZgg", 244 | "title": "Cocos2d-x", 245 | "description": "", 246 | "thumbnails": { 247 | "default": { 248 | "url": "https://i.ytimg.com/vi/57wqAaH3EV8/default.jpg", 249 | "width": 120, 250 | "height": 90 251 | }, 252 | "medium": { 253 | "url": "https://i.ytimg.com/vi/57wqAaH3EV8/mqdefault.jpg", 254 | "width": 320, 255 | "height": 180 256 | }, 257 | "high": { 258 | "url": "https://i.ytimg.com/vi/57wqAaH3EV8/hqdefault.jpg", 259 | "width": 480, 260 | "height": 360 261 | }, 262 | "standard": { 263 | "url": "https://i.ytimg.com/vi/57wqAaH3EV8/sddefault.jpg", 264 | "width": 640, 265 | "height": 480 266 | } 267 | }, 268 | "channelTitle": "Streamelopers", 269 | "localized": { 270 | "title": "Cocos2d-x", 271 | "description": "" 272 | } 273 | } 274 | }, 275 | { 276 | "kind": "youtube#playlist", 277 | "etag": "\"I_8xdZu766_FSaexEaDXTIfEWc0/lqPmgURg3FCzHid9DU40ljvjX3s\"", 278 | "id": "PLW-4dWdTuQryU9mhcmR5YQcNbaTVvs-is", 279 | "snippet": { 280 | "publishedAt": "2015-12-12T23:58:40.000Z", 281 | "channelId": "UCznWXigAvBa1ZtrgRmJGZgg", 282 | "title": "Eventos Especiales", 283 | "description": "", 284 | "thumbnails": { 285 | "default": { 286 | "url": "https://i.ytimg.com/vi/GTpOQvsk0aQ/default.jpg", 287 | "width": 120, 288 | "height": 90 289 | }, 290 | "medium": { 291 | "url": "https://i.ytimg.com/vi/GTpOQvsk0aQ/mqdefault.jpg", 292 | "width": 320, 293 | "height": 180 294 | }, 295 | "high": { 296 | "url": "https://i.ytimg.com/vi/GTpOQvsk0aQ/hqdefault.jpg", 297 | "width": 480, 298 | "height": 360 299 | }, 300 | "standard": { 301 | "url": "https://i.ytimg.com/vi/GTpOQvsk0aQ/sddefault.jpg", 302 | "width": 640, 303 | "height": 480 304 | } 305 | }, 306 | "channelTitle": "Streamelopers", 307 | "localized": { 308 | "title": "Eventos Especiales", 309 | "description": "" 310 | } 311 | } 312 | }, 313 | { 314 | "kind": "youtube#playlist", 315 | "etag": "\"I_8xdZu766_FSaexEaDXTIfEWc0/UNOWzWc_LBm5h_xK_Uxipec7cX8\"", 316 | "id": "PLW-4dWdTuQrwswsfMqTz7zjrFxm_-MBUX", 317 | "snippet": { 318 | "publishedAt": "2015-12-08T17:55:45.000Z", 319 | "channelId": "UCznWXigAvBa1ZtrgRmJGZgg", 320 | "title": "Startup Weekend Santo Domingo 2015", 321 | "description": "Videos de preparación para el Startup Weekend 2015", 322 | "thumbnails": { 323 | "default": { 324 | "url": "https://i.ytimg.com/vi/4M3vYRa3uFk/default.jpg", 325 | "width": 120, 326 | "height": 90 327 | }, 328 | "medium": { 329 | "url": "https://i.ytimg.com/vi/4M3vYRa3uFk/mqdefault.jpg", 330 | "width": 320, 331 | "height": 180 332 | }, 333 | "high": { 334 | "url": "https://i.ytimg.com/vi/4M3vYRa3uFk/hqdefault.jpg", 335 | "width": 480, 336 | "height": 360 337 | }, 338 | "standard": { 339 | "url": "https://i.ytimg.com/vi/4M3vYRa3uFk/sddefault.jpg", 340 | "width": 640, 341 | "height": 480 342 | }, 343 | "maxres": { 344 | "url": "https://i.ytimg.com/vi/4M3vYRa3uFk/maxresdefault.jpg", 345 | "width": 1280, 346 | "height": 720 347 | } 348 | }, 349 | "channelTitle": "Streamelopers", 350 | "localized": { 351 | "title": "Startup Weekend Santo Domingo 2015", 352 | "description": "Videos de preparación para el Startup Weekend 2015" 353 | } 354 | } 355 | }, 356 | { 357 | "kind": "youtube#playlist", 358 | "etag": "\"I_8xdZu766_FSaexEaDXTIfEWc0/CvAtpL3P5TirEgc36YtVeQjEOoE\"", 359 | "id": "PLW-4dWdTuQryJZDiu_yTBsiRZ0PIt6hYK", 360 | "snippet": { 361 | "publishedAt": "2015-12-08T17:50:19.000Z", 362 | "channelId": "UCznWXigAvBa1ZtrgRmJGZgg", 363 | "title": "Lean Startup", 364 | "description": "", 365 | "thumbnails": { 366 | "default": { 367 | "url": "https://i.ytimg.com/vi/7xDRdWDQkf0/default.jpg", 368 | "width": 120, 369 | "height": 90 370 | }, 371 | "medium": { 372 | "url": "https://i.ytimg.com/vi/7xDRdWDQkf0/mqdefault.jpg", 373 | "width": 320, 374 | "height": 180 375 | }, 376 | "high": { 377 | "url": "https://i.ytimg.com/vi/7xDRdWDQkf0/hqdefault.jpg", 378 | "width": 480, 379 | "height": 360 380 | } 381 | }, 382 | "channelTitle": "Streamelopers", 383 | "localized": { 384 | "title": "Lean Startup", 385 | "description": "" 386 | } 387 | } 388 | }, 389 | { 390 | "kind": "youtube#playlist", 391 | "etag": "\"I_8xdZu766_FSaexEaDXTIfEWc0/K_Eb2Xgay8hHQ7RzRmCMytd4srE\"", 392 | "id": "PLW-4dWdTuQrxwsljznWB_w2ydZtB0AQq3", 393 | "snippet": { 394 | "publishedAt": "2015-11-28T00:52:21.000Z", 395 | "channelId": "UCznWXigAvBa1ZtrgRmJGZgg", 396 | "title": "Grupo Agnóstico", 397 | "description": "Videos del Grupo Agnóstico", 398 | "thumbnails": { 399 | "default": { 400 | "url": "https://i.ytimg.com/vi/-IfU8U3J7NI/default.jpg", 401 | "width": 120, 402 | "height": 90 403 | }, 404 | "medium": { 405 | "url": "https://i.ytimg.com/vi/-IfU8U3J7NI/mqdefault.jpg", 406 | "width": 320, 407 | "height": 180 408 | }, 409 | "high": { 410 | "url": "https://i.ytimg.com/vi/-IfU8U3J7NI/hqdefault.jpg", 411 | "width": 480, 412 | "height": 360 413 | }, 414 | "standard": { 415 | "url": "https://i.ytimg.com/vi/-IfU8U3J7NI/sddefault.jpg", 416 | "width": 640, 417 | "height": 480 418 | }, 419 | "maxres": { 420 | "url": "https://i.ytimg.com/vi/-IfU8U3J7NI/maxresdefault.jpg", 421 | "width": 1280, 422 | "height": 720 423 | } 424 | }, 425 | "channelTitle": "Streamelopers", 426 | "localized": { 427 | "title": "Grupo Agnóstico", 428 | "description": "Videos del Grupo Agnóstico" 429 | } 430 | } 431 | } 432 | ] 433 | } 434 | --------------------------------------------------------------------------------