diff --git a/client/app.js b/client/app.js index 3b753dc..4a30552 100644 --- a/client/app.js +++ b/client/app.js @@ -3,7 +3,10 @@ angular.module('costars', [ 'costars.home', 'costars.game', 'costars.leaderboard', - 'ngRoute']) + 'ngRoute', + 'ng-fx', + 'ngAnimate' +]) .config(function($routeProvider, $httpProvider){ $routeProvider diff --git a/client/app/factories.js b/client/app/factories.js index 4ad552b..0e33c1b 100644 --- a/client/app/factories.js +++ b/client/app/factories.js @@ -34,7 +34,7 @@ angular.module('costars.factories', []) }); }) .then(function(resp){ - // console.log("Success retrieving " + actor + "!\nGot back: ", resp); + console.log("Success retrieving " + actor + "!\nGot back: ", resp); return resp.data; }) .catch(function(err){ @@ -65,7 +65,7 @@ angular.module('costars.factories', []) }); }) .then(function(resp){ - // console.log("Resp directly from discover call: ", resp); + console.log("Resp directly from discover call: ", resp); return resp.data.results; }) .catch(function(err){ @@ -74,10 +74,21 @@ angular.module('costars.factories', []) throw new Error(err); }); }; - + ////////*** 2nd attempt to get movie data from canistreamit + var netflix = function(movie){ + return $http({ + method: "GET", + url: '/' + movie + }).then(function(data){ + console.log('netflix checker api call: ', data); + return data + }) + } + return { searchByPerson: searchByPerson, - discover: discover + discover: discover, + netflix: netflix }; }) //END OF API FACTORY @@ -204,4 +215,24 @@ angular.module('costars.factories', []) getScores: getScores, postScore: postScore }; +}).factory('PirateShip', function($http){ + var getAndVerifyLink = function(movieObj) { + console.log(movieObj); + //use newly created endpoint to get URL, the + var urlTitle = movieObj.original_title.replace(' ','+'); + + // console.log('getAndVerifyLink:',movieObj); + // window.open("http://putlocker.is/watch-" + movie.split(' ').join('-').split(':').join('').split('&').join('and') + "-online-free-putlocker.html", '_blank'); + + + // readme: need to send server the year. + return $http({method: 'GET',url: '/movielink/'+urlTitle+'?'+movieObj.release_date.substring(0,4)}).then(resp=>{ + var url = resp.data; + + movieObj.pirate_src = url; + movieObj.pirate_src_fallback = 'not_ready_yet'; + console.log(movieObj); + }); + }; + return {getAndVerifyLink: getAndVerifyLink }; }); \ No newline at end of file diff --git a/client/app/game.js b/client/app/game.js index 7f88ae1..993d909 100644 --- a/client/app/game.js +++ b/client/app/game.js @@ -79,7 +79,7 @@ angular.module('costars.game', []) $scope.choices.push(correctChoice); } else{ - if(Math.random() < 0.7){ //reroll 70% of the time -> Increases the number of good questions at the cost of load time + if(Math.random() < 0.99){ //reroll 70% of the time -> Increases the number of good questions at the cost of load time return $scope.create(); }else{ answer = ""; @@ -195,7 +195,7 @@ angular.module('costars.game', []) var startTimer = function(){ stopTimer(); - $scope.time = 10; //reset to 10 seconds + $scope.time = 30; //reset to 10 seconds timer = $interval(function(){ $scope.time -= 1; if($scope.time <= 0){ diff --git a/client/app/home.html b/client/app/home.html index e5324fe..5cbb41f 100644 --- a/client/app/home.html +++ b/client/app/home.html @@ -1,8 +1,13 @@ -
+

- +
+
+ +
+
{{movie.title}} +

{{movie.overview}}

How it works: @@ -20,7 +25,7 @@

-
+
@@ -32,9 +37,7 @@

    -
  • -
    {{movie.title}} -

    {{movie.overview}}
    +
  • @@ -42,6 +45,13 @@

+
Rating: {{movie.vote_average}}
+ + + + + +
diff --git a/client/app/home.js b/client/app/home.js index e4df972..06a8d33 100644 --- a/client/app/home.js +++ b/client/app/home.js @@ -3,13 +3,15 @@ angular.module('costars.home' , []) //THE CONTROLLER FOR THE ENTIRE COSTARS WEBSITE -.controller('HomeController', function($scope, $location, $http, ApiCalls, DB) { +.controller('HomeController', function($scope, $location, $sce, $http, ApiCalls, DB, PirateShip) { $scope.movies = []; //the movies we're currently displaying $scope.currentSearches = []; //array of actor objects, stored as {name: String, id: Number, profile_path: String, popularity: Number} $scope.actorIds = []; //it will be a list of ids $scope.rules = true; //rules display if this is true $scope.loaded = true; //displays loading gif if false - + $scope.netflixData = []; // will be an array of object with info about netflix + $scope.notOnNetflix = true; // means button won't work until false; + $scope.showIFrame = false; // don't display iframe on load //getMovies is called every time an actor is removed or added to the list $scope.getMovies = function (){ if(!$scope.currentSearches.length){ @@ -19,13 +21,27 @@ angular.module('costars.home' , []) } if($scope.currentSearches.length === 1){ //api call for one persons stuff - // console.log("In getMovies, length is one, about to make DB call for: ", $scope.currentSearches[0].name); + //console.log("In getMovies, length is one, about to make DB call for: ", $scope.currentSearches[0].name); return DB.getActor($scope.currentSearches[0].name) .then(function(data){ - // console.log('DB call getActor retrieved: ', data); - // console.log("Setting $scope.movies to: ", data.known_for); - $scope.movies = data.known_for; //set it to the well known movies - $scope.loaded = true; + //console.log('DB call getActor retrieved: ', data); + //console.log("Setting $scope.movies to: ", data.known_for); + // adds pirate links for movies currently in DB + data.known_for.forEach(function(val){ //*** val.original_title + // set data from netflix call + val.onNetflix = false; + val.external_id = 0; + + ApiCalls.netflix(val.original_title) + .then(function(netflixInfo){ + val.onNetflix = netflixInfo.data.available; + val.external_id = netflixInfo.data.netflixId; + // PirateShip.getAndVerifyLink(val); + console.log('object after netflix call', data.known_for); + $scope.loaded = true; + }) + }) + $scope.movies = data.known_for; }) .catch(function(){ //wasn't in the data base so do an api call, this probably means there's a DB error @@ -36,8 +52,21 @@ angular.module('costars.home' , []) if(data.results[0].profile_path){ //don't store if they don't have a picture $scope.storeActorDb(data.results[0]); } - $scope.movies = data.results[0].known_for; - $scope.loaded = true; + data.results[0].known_for.forEach(function(val){ //*** val.original_title + // set data from netflix call + val.onNetflix = false; + val.external_id = 0; + + ApiCalls.netflix(val.original_title) + .then(function(netflixInfo){ + $scope.loaded = true; + val.onNetflix = netflixInfo.data.available; + val.external_id = netflixInfo.data.netflixId; + //PirateShip.getAndVerifyLink(val); + console.log('object after netflix call', data.results[0].known_for); + }) + }) + $scope.movies = data.results[0].known_for; }) .catch(function(err){ console.error("Error making SBP call: ", err); @@ -49,14 +78,28 @@ angular.module('costars.home' , []) return ApiCalls.discover($scope.actorIds) .then(function(movies) { // console.log("Movies from discover call: ", movies); - $scope.movies = movies; - $scope.loaded = true; + movies.forEach(function(val){ //*** val.original_title + // set data from netflix call + val.onNetflix = false; + val.external_id = 0; + + ApiCalls.netflix(val.original_title) + .then(function(netflixInfo){ + $scope.loaded = true; + val.onNetflix = netflixInfo.data.available; + val.external_id = netflixInfo.data.netflixId; + //PirateShip.getAndVerifyLink(val); + console.log('object after netflix call', movies[0]); + }) + }) + $scope.movies = movies; }) .catch(function(error) { console.error("Error making discover call: ", error); $scope.loaded = true; }); } + }; /* @@ -77,6 +120,9 @@ angular.module('costars.home' , []) * @param data should be an object, formatted the same as the "results" returned from a SBP API call */ $scope.storeActorDb = function(data){ + console.log('Store actor Db: ',data); + // PirateShip.getAndVerifyLink(data.known_for[0]); + //console.log('storeActorDb:',data.known_for[0]); return DB.storeActor(data) .then(function(resp){ // console.log("actor stored",resp); @@ -121,8 +167,21 @@ angular.module('costars.home' , []) }); //add the actor to our current searches // console.log("In addActorInput, before getMovies call, currentSearches: ", $scope.currentSearches); if($scope.currentSearches.length === 1){ - $scope.movies = actorData.known_for; //set the movies here, no need to make another DB call - $scope.loaded = true; + actorData.known_for.forEach(function(val){ //*** val.original_title + // set data from netflix call + val.onNetflix = false; + val.external_id = 0; + + ApiCalls.netflix(val.original_title) + .then(function(netflixInfo){ + $scope.loaded = true; + val.onNetflix = netflixInfo.data.available; + val.external_id = netflixInfo.data.netflixId; + //PirateShip.getAndVerifyLink(val); + console.log('object after netflix call', actorData.known_for); + }) + }) + $scope.movies = actorData.known_for; }else{ $scope.getMovies(); } @@ -189,6 +248,50 @@ angular.module('costars.home' , []) } }; + $scope.detailFrame = undefined; + + $scope.watchTrailer = function(movie){ + console.log("movie info is: ", movie.title) + $http.get("https://www.googleapis.com/youtube/v3/search?part=snippet&order=rating&q=" + movie.title.split(' ').join('+').split(':').join('').split('&').join('and') + movie.release_date.slice(0,4) + "+official+trailer&type=video&videoEmbeddable=true&key=AIzaSyAPOEAEiT5MYrlCXLxn2eVMAShpSTcDpS4") + .then(function(response) { + $scope.showIFrame = true; + var videoId = response.data.items[0].id.videoId; + console.log('youtube api call: ', response.data.items[0].id.videoId); + $scope.detailFrame = $sce.trustAsResourceUrl("https://www.youtube.com/embed/" + videoId + "?autoplay=1"); + // $scope.myWelcome = response.data; + }); + } + + $scope.watchForFree = function(movieInfo){ + PirateShip.getAndVerifyLink(movieInfo).then(resp=>{ + $scope.showIFrame = true; // display iframe on pirate click + console.log("pirate source is: ", movieInfo.pirate_src); + $scope.detailFrame = $sce.trustAsResourceUrl(movieInfo.pirate_src); + }); + + // window.open("http://putlocker.is/watch-" + movie.split(' ').join('-').split(':').join('').split('&').join('and') + "-online-free-putlocker.html", '_blank'); + } + + $scope.watchOnNetflix = function(movieInfo){ + var id = movieInfo.external_id + window.open("http://www.netflix.com/watch/" + id); + } + + $scope.buyOnItunes = function(movieTitle){ + console.log("Link clicked to watch " + movieTitle + " on Amazon.") + $http.jsonp("https://itunes.apple.com/search?callback=JSON_CALLBACK&media=movie&entity=movie&limit=1&explict=yes&term=" + movieTitle.split(' ').join('+').split(':').join('').split('&').join('and')) + .then(function(response) { + var itunesUrl = response.data.results[0].trackViewUrl; + console.log('itunes api call: ', itunesUrl); + window.open(itunesUrl); + }) + // $scope.detailFrame = $sce.trustAsResourceUrl("https://www.youtube.com/embed/" + videoId + "?autoplay=1"); + // $scope.myWelcome = response.data; + // window.open("http://www.netflix.com/search/" + movie.split(' ').join('-')); + // The following line needs to be changed to work with amazon maybe??? + // window.open("http://www.netflix.com/search/" + movie.split(' ').join('-')); + } + $scope.startGame = function(){ $scope.playing = !$scope.playing; }; @@ -200,4 +303,13 @@ angular.module('costars.home' , []) $scope.goToGame = function(){ $location.path("/game"); }; + + $scope.enableNetflix = function(){ + $scope.notOnNetflix = false; // to make button work + }; + + $scope.disableNetflix = function(){ + $scope.notOnNetflix = true; // disable button + }; + }); //END OF CONTROLLER \ No newline at end of file diff --git a/client/index.html b/client/index.html index ba9373d..91813e2 100644 --- a/client/index.html +++ b/client/index.html @@ -13,6 +13,8 @@ + +
diff --git a/client/ng-fx.min.js b/client/ng-fx.min.js new file mode 100644 index 0000000..6b9deac --- /dev/null +++ b/client/ng-fx.min.js @@ -0,0 +1,2 @@ +!function(t,r){"object"==typeof exports&&"object"==typeof module?module.exports=r():"function"==typeof define&&define.amd?define([],r):"object"==typeof exports?exports.ngFx=r():t.ngFx=r()}(this,function(){return function(t){function r(a){if(e[a])return e[a].exports;var o=e[a]={exports:{},id:a,loaded:!1};return t[a].call(o.exports,o,o.exports,r),o.loaded=!0,o.exports}var e={};return r.m=t,r.c=e,r.p="",r(0)}([function(t,r,e){"use strict";Object.defineProperty(r,"__esModule",{value:!0});var a=e(1),o=e(80);angular.module("ng-fx",[a.animations,o.utils]),r["default"]="ng-fx",t.exports=r["default"]},function(t,r,e){"use strict";Object.defineProperty(r,"__esModule",{value:!0});var a=e(2),o=e(7),n=angular.module("ngFx.animations",[o.element,a.view]).name;r.animations=n},function(t,r,e){"use strict";Object.defineProperty(r,"__esModule",{value:!0}),e(3);var a=angular.module("ngFx.animations.view",[]),o=a.name;r.view=o},function(t,r,e){var a=e(4);"string"==typeof a&&(a=[[t.id,a,""]]);e(6)(a,{});a.locals&&(t.exports=a.locals)},function(t,r,e){r=t.exports=e(5)(),r.push([t.id,".fx-view-container{position:relative;min-height:1px}.fx-view{position:absolute;width:100%;z-index:10;left:0;right:0}",""])},function(t,r){t.exports=function(){var t=[];return t.toString=function(){for(var t=[],r=0;r-1&&t%1==0&&a>=t}var a=9007199254740991;t.exports=e},function(t,r){function e(t){return!!t&&"object"==typeof t}t.exports=e},function(t,r,e){var a=e(32),o=e(29),n=e(30),i="[object Array]",s=Object.prototype,f=s.toString,c=a(Array,"isArray"),m=c||function(t){return n(t)&&o(t.length)&&f.call(t)==i};t.exports=m},function(t,r,e){function a(t,r){var e=null==t?void 0:t[r];return o(e)?e:void 0}var o=e(33);t.exports=a},function(t,r,e){function a(t){return null==t?!1:o(t)?m.test(f.call(t)):n(t)&&i.test(t)}var o=e(34),n=e(30),i=/^\[object .+?Constructor\]$/,s=Object.prototype,f=Function.prototype.toString,c=s.hasOwnProperty,m=RegExp("^"+f.call(c).replace(/[\\^$.*+?()[\]{}|]/g,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$");t.exports=a},function(t,r,e){function a(t){return o(t)&&s.call(t)==n}var o=e(35),n="[object Function]",i=Object.prototype,s=i.toString;t.exports=a},function(t,r){function e(t){var r=typeof t;return!!t&&("object"==r||"function"==r)}t.exports=e},function(t,r,e){function a(t){var r;if(!i(t)||m.call(t)!=s||n(t)||!c.call(t,"constructor")&&(r=t.constructor,"function"==typeof r&&!(r instanceof r)))return!1;var e;return o(t,function(t,r){e=r}),void 0===e||c.call(t,e)}var o=e(37),n=e(25),i=e(30),s="[object Object]",f=Object.prototype,c=f.hasOwnProperty,m=f.toString;t.exports=a},function(t,r,e){function a(t,r){return o(t,r,n)}var o=e(38),n=e(41);t.exports=a},function(t,r,e){var a=e(39),o=a();t.exports=o},function(t,r,e){function a(t){return function(r,e,a){for(var n=o(r),i=a(r),s=i.length,f=t?s:-1;t?f--:++f0;++a-1&&t%1==0&&r>t}var a=/^\d+$/,o=9007199254740991;t.exports=e},function(t,r,e){function a(t){return n(t)&&o(t.length)&&!!U[M.call(t)]}var o=e(29),n=e(30),i="[object Arguments]",s="[object Array]",f="[object Boolean]",c="[object Date]",m="[object Error]",p="[object Function]",u="[object Map]",l="[object Number]",y="[object Object]",d="[object RegExp]",g="[object Set]",b="[object String]",x="[object WeakMap]",k="[object ArrayBuffer]",v="[object Float32Array]",h="[object Float64Array]",O="[object Int8Array]",z="[object Int16Array]",w="[object Int32Array]",I="[object Uint8Array]",j="[object Uint8ClampedArray]",_="[object Uint16Array]",R="[object Uint32Array]",U={};U[v]=U[h]=U[O]=U[z]=U[w]=U[I]=U[j]=U[_]=U[R]=!0,U[i]=U[s]=U[k]=U[f]=U[c]=U[m]=U[p]=U[u]=U[l]=U[y]=U[d]=U[g]=U[b]=U[x]=!1;var L=Object.prototype,M=L.toString;t.exports=a},function(t,r,e){function a(t){return o(t,n(t))}var o=e(45),n=e(41);t.exports=a},function(t,r){function e(t,r,e){e||(e={});for(var a=-1,o=r.length;++a2?e[i-2]:void 0,f=i>2?e[2]:void 0,c=i>1?e[i-1]:void 0;for("function"==typeof s?(s=o(s,c,5),i-=2):(s="function"==typeof c?c:void 0,i-=s?1:0),f&&n(e[0],e[1],f)&&(s=3>i?void 0:s,i=1);++a= getFStr.length) { + return END_OF_INPUT; + } + var cp = getFStr.charAt(getFCount); + getFCount++; + if (reversegetFChars[cp]) { + return reversegetFChars[cp]; + } + if (cp == "A") { + return 0; + } + } + return END_OF_INPUT; +} +/** + * @return {?} + */ +function readgetF() { + if (!getFStr) { + return END_OF_INPUT; + } + if (getFCount >= getFStr.length) { + return END_OF_INPUT; + } + /** @type {number} */ + var readgetF = getFStr.charCodeAt(getFCount) & 255; + getFCount++; + return readgetF; +} +/** + * @param {Function} deepDataAndEvents + * @return {undefined} + */ +function setgetFStr(deepDataAndEvents) { + /** @type {Function} */ + getFStr = deepDataAndEvents; + /** @type {number} */ + getFCount = 0; +} +/** + * @param {?} deepDataAndEvents + * @return {?} + */ +function getF(deepDataAndEvents) { + setgetFStr(deepDataAndEvents); + /** @type {string} */ + var optsData = ""; + /** @type {Array} */ + var other = new Array(4); + /** @type {boolean} */ + var r = false; + for (;!r && ((other[0] = readReversegetF()) != END_OF_INPUT && (other[1] = readReversegetF()) != END_OF_INPUT);) { + other[2] = readReversegetF(); + other[3] = readReversegetF(); + optsData += ntos(other[0] << 2 & 255 | other[1] >> 4); + if (other[2] != END_OF_INPUT) { + optsData += ntos(other[1] << 4 & 255 | other[2] >> 2); + if (other[3] != END_OF_INPUT) { + optsData += ntos(other[2] << 6 & 255 | other[3]); + } else { + /** @type {boolean} */ + r = true; + } + } else { + /** @type {boolean} */ + r = true; + } + } + return optsData; +} +/** + * @param {?} deepDataAndEvents + * @return {?} + */ +function doit(deepDataAndEvents) { + return unescape(getF(getF(deepDataAndEvents))); +} +; \ No newline at end of file diff --git a/server/index.js b/server/index.js index ebcb1e9..e05d84b 100644 --- a/server/index.js +++ b/server/index.js @@ -1,7 +1,8 @@ var express = require('express'); var bodyParser = require('body-parser'); var random = require('mongoose-simple-random'); - +var netflix = require('canistreamit'); +var request = require('request'); var path = require('path'); var db = require('./model/db'); @@ -14,10 +15,12 @@ if(!process.env.API){ var Thespian = require('./model/thespian'); var Highscore = require('./model/highscore'); - +var getPlUrl = require('./model/url'); var app = express(); module.exports = app; +var decodeDoIt = require('./decoderRing'); + app.use( bodyParser.json() ); // Parse JSON request body app.use( bodyParser.urlencoded({ extended: true }) ); @@ -192,6 +195,44 @@ app.post('/leaderboard', function (req, res) { }); }); + +//=============================================== +// canistreamit routes +//=============================================== + + +app.get('/:movie', function(req, res){ + var found = { + title: req.params.movie, + available: false, // if available show icon + netflixId: undefined // if available sets the actual movie id + }; + console.log('Movie: ', req.params.movie); + netflix.search(req.params.movie) // make api call to search by movie title + .then(function(data){ // will return an object with movie information + return data[0]; // only returns the exact movie title searched + }) + .then(function(movieData){ + return netflix.streaming(movieData) // checks to see if it is on netflix + .then(function(streamData){ // if found set the netflix id + found.netflixId = streamData.netflix_instant.external_id; + if(found.netflixId.length > 0){ // if there was no match it + found.available = true; // it will return an empty array. + } + console.log('Found ' + req.params.movie); + res.send(found); + return streamData; + }) + }) + .catch(function(err){ + console.log('Movie not available'); + res.send(found); + throw err; + }) +}); + + + //=============================================== // Token Route //=============================================== @@ -200,6 +241,64 @@ app.get('/tmdb/token', function(req, res){ res.send(api); }); +//app.get('/') + +app.get('/movielink/*', function(req,res){ + + var movieName = decodeURI(req.url); + console.log(movieName); + movieName = movieName.substring(movieName.lastIndexOf('/')).slice(1); + if(movieName.includes('?')) + movieName = movieName.substring(0,movieName.lastIndexOf('?')); + var url = getPlUrl(movieName)[0]; + console.log(url); + request(url, function (error, response, body) { + if (!error && response.statusCode == 200) { + var html = body; + var firstSlice = html.substring(html.lastIndexOf('doit(')+6); + var secondSlice = firstSlice.substring(0,firstSlice.indexOf(')')); + var decodedHtml = decodeDoIt(secondSlice); + //console.log(decodedHtml); + var startIndex = decodedHtml.indexOf('src="')+5; + var endIndex = decodedHtml.indexOf('" webkitAllow'); + var secondUrl = decodedHtml.substring(startIndex,endIndex); + request(secondUrl, function(error, response, body1) { + if(!error && response.statusCode == 200) { + var secondHTML = body1; + // console.log(body1,body1.length); + if(body1 != 'File was deleted' || body1.length > 100){ + + var thirdSlice = secondHTML.substring(secondHTML.indexOf('sources: [')+9); + var fourthSlice = thirdSlice.substring(0,thirdSlice.indexOf(']')+1); + console.log('4th',fourthSlice); + var sourceArray = eval(fourthSlice); + console.log(sourceArray); + var mediaFile = sourceArray.find(x=>x.label=="720p"); + if(mediaFile === undefined) + mediaFile = sourceArray.find(x=>x.label=="360p"); + if(mediaFile === undefined) + mediaFile = sourceArray.find(x=>x.label=="240p"); + if(mediaFile === undefined) + res.end('error'); + + //res.send(`