12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265 |
- 'use strict';
- const Express = require('express');
- const mongoose = require('mongoose');
- const gplay = require('google-play-scraper');
- const path = require('path');
- var fs = require('fs');
- const qs = require('querystring');
- const sentiment = require('sentiment');
- const requestLib = require('request');
- const async = require('async');
- var _ = require('underscore-node');
- const models = require("../models");
- const router = Express.Router();
- function factorial(x) {
- if (x == 0) {
- return 1;
- }
- return x * factorial(x - 1);
- }
- function toList(apps) {
- return { results: apps };
- }
- function cleanUrls(req) {
- return function (app) {
- app.playstoreUrl = app.playstoreUrl || app.url;
- app.url = buildUrl(req, 'apps/' + app.appId);
- app.permissions = buildUrl(req, 'apps/' + app.appId + '/permissions');
- app.similar = buildUrl(req, 'apps/' + app.appId + '/similar');
- app.reviewsCount = app.reviewsCount || app.reviews;
- app.reviews = buildUrl(req, 'apps/' + app.appId + '/reviews');
- app.developer = {
- devId: app.developer.devId || app.developer,
- url: buildUrl(req, 'developers/' + qs.escape(app.developer.devId || app.developer))
- };
- return app;
- };
- }
- function saveAppData(app) {
- return new Promise(function (resolve, reject) {
- //console.log("app: " + app);
- app.save()
- .then(function (result) {
- resolve(app);
- })
- .catch(function (e) {
- console.log("error saving one app:" + JSON.stringify(e));
- if (e.code === 11000 || e.code === 11001) {
- models.app.findOne({ "appId": app.appId })
- .then(function (result) {
- resolve(result);
- })
- .catch(function (e) {
- console.log("error finding one app:" + JSON.stringify(e));
- reject(e);
- });
- } else {
- reject(e);
- }
- });
- });
- }
- function fetchReviewAndSave(opts) {
- return function (app) {
- opts.page = opts.page || 0;
- opts.throttle = 1;
- console.log("Initial page no:" + JSON.stringify(opts));
- return new Promise(function (resolve, reject) {
- async.whilst(
- function () {
- return opts.page != -1;
- },
- function (next) {
- console.log("Inside loop " + opts.page);
- gplay
- .reviews(opts)
- .then((reviews) => reviews.map(addSentiment()))
- .then(function (reviews) {
- console.log("Reviews length: " + reviews.length);
- //if (!reviews.length) { opts.page = -1 }
- return new Promise(function (resolve, reject) {
- async.mapSeries(reviews, function (review, callback) {
- review.app = app._id;
- new models.review(review).save()
- .then(function (result) {
- app.reviews.push(result._id);
- return callback(null, result);
- })
- .catch(function (e) {
- console.log("error saving one review:" + JSON.stringify(e));
- if (e.code === 11000 || e.code === 11001) {
- models.review.findOne({ "reviewId": review.reviewId })
- .then(function (result) {
- return callback(null, result);
- })
- .catch(function (e) {
- console.log("error finding one review:" + JSON.stringify(e));
- return callback(e, null);
- });
- } else {
- return callback(e, null);
- }
- //return callback(e, null);
- });
- }, function (err, results) {
- //console.log("Error map series: " + JSON.stringify(err));
- //console.log("Finished map series!!!");
- console.log("Map Series finish review length: " + results.length);
- resolve(results);
- });
- });
- })
- .then(function (reviews) {
- if (!reviews.length) { opts.page = -1; }
- if (opts.page == 50) { opts.page = -1; };
- if (opts.page != -1) { opts.page++ };
- //console.log("Reviews length2: " + reviews.length);
- //console.log("Return counter1: " + opts.page);
- next();
- })
- .catch(function (e) {
- opts.page = -1;
- });
- },
- function (err) {
- if (err) {
- console.log("Error async:" + err);
- reject(err);
- } else {
- console.log("Finished!!!");
- //console.log("App reviews: " + JSON.stringify(app.reviews));
- resolve(app);
- }
- }
- );
- });
- };
- }
- function fetchPermissions(opts) {
- return function (app) {
- return new Promise(function (resolve, reject) {
- gplay.permissions(opts)
- .then(function (permissions) {
- app.permissions = permissions;
- resolve(app);
- })
- .catch(function (e) {
- reject(e);
- });
- });
- }
- }
- function saveReviewData(app) {
- return function (review) {
- review.app = app._id;
- //review.app = "";
- console.log("review: " + review.userName);
- requestLib({
- uri: "http://localhost:3000/db/review/",
- method: "POST",
- json: review
- }, function (error, response, body) {
- if (!error) {
- review._id = body._id;
- }
- });
- return review;
- };
- }
- function addSentiment() {
- return function (app) {//receives a single review actually
- const sentMin = -5;
- const sentMax = 5;
- app.sentiment = sentiment(app.text);
- app.sentiment.sentimentProportional = app.sentiment.score / Math.max(Math.sqrt(app.sentiment.tokens.length), app.sentiment.words.length);
- app.sentiment.sentimentScaled = (app.sentiment.sentimentProportional + Math.abs(0 - sentMin)) / (sentMax - sentMin);
- app.sentiment.sentimentConfidence = 1 - Math.abs(((app.score - 1) / 4) - app.sentiment.sentimentScaled);
- app.sentiment.scaledReviewRating = (app.score - 1) / 4;
- // app.sentiment.sentimentConfidence = 1 - Math.abs(app.score - app.sentiment.sentimentScaled);
- app.reviewId = qs.parse(app.url).reviewId || "";
- return app;
- };
- }
- function isAlreadyDownloaded(apps) {
- return new Promise(function (resolve, reject) {
- models.app.find({})
- .then((downloadedApps) => downloadedApps.map(function (app) {
- var currentApp = _(apps).findWhere({ appId: app.appId });//_.findWhere(apps, {appId: app.appId});
- //console.log("cur:" + currentApp);
- if (currentApp != undefined) {
- currentApp.isAlreadyDownloaded = "yes";
- }
- }))
- .then(function (downloadedApps) {
- resolve(apps);
- //console.log(apps);
- });
- });
- }
- function buildUrl(req, subpath) {
- return req.protocol + '://' + path.join(req.get('host'), req.baseUrl, subpath);
- }
- /* Index */
- router.get('/', function (req, res) {
- res.json({
- apps: buildUrl(req, 'apps'),
- developers: buildUrl(req, 'developers')
- });
- });
- /* App search */
- router.get('/apps/', function (req, res, next) {
- console.log('Inside app search1');
- if (!req.query.q) {
- return next();
- }
- console.log('Inside app search2');
- const opts = Object.assign({ term: req.query.q }, req.query);
- gplay.search(opts)
- .then((apps) => apps.map(cleanUrls(req)))
- .then(isAlreadyDownloaded)
- .then(toList)
- .then(res.json.bind(res))
- .catch(next);
- });
- /* Search suggest */
- router.get('/apps/', function (req, res, next) {
- console.log('Inside search suggest1');
- if (!req.query.suggest) {
- return next();
- }
- console.log('Inside search suggest2');
- function toJSON(term) {
- return {
- term,
- url: buildUrl(req, '/apps/') + '?' + qs.stringify({ q: term })
- };
- }
- gplay.suggest({ term: req.query.suggest })
- .then((terms) => terms.map(toJSON))
- .then(toList)
- .then(res.json.bind(res))
- .catch(next);
- });
- /* App list */
- router.get('/apps/', function (req, res, next) {
- console.log('Inside App list1');
- function paginate(apps) {
- const num = parseInt(req.query.num || '60');
- const start = parseInt(req.query.start || '0');
- if (start - num >= 0) {
- req.query.start = start - num;
- apps.prev = buildUrl(req, '/apps/') + '?' + qs.stringify(req.query);
- }
- if (start + num <= 500) {
- req.query.start = start + num;
- apps.next = buildUrl(req, '/apps/') + '?' + qs.stringify(req.query);
- }
- return apps;
- }
- console.log('Inside App list2');
- gplay.list(req.query)
- .then((apps) => apps.map(cleanUrls(req)))
- .then(toList).then(paginate)
- .then(res.json.bind(res))
- .catch(next);
- });
- /* App detail*/
- router.get('/apps/:appId', function (req, res, next) {
- const opts = Object.assign({ appId: req.params.appId }, req.query);
- gplay.app(opts)
- .then(cleanUrls(req))
- .then(function (app) {
- app.reviews = [];
- app.permissions = [];
- return new models.app(app);
- })
- //.then(saveAppData)//app data without permissions and reviews
- //.then(fetchReviewAndSave(opts))
- //.then(saveAppData)//save with reviews array
- //.then(fetchPermissions(opts))
- //.then(saveAppData)//save with permissions array
- .then(res.json.bind(res))
- .catch(next);
- });
- /* Similar apps */
- router.get('/apps/:appId/similar', function (req, res, next) {
- const opts = Object.assign({ appId: req.params.appId }, req.query);
- gplay.similar(opts)
- .then((apps) => apps.map(cleanUrls(req)))
- .then(toList)
- .then(res.json.bind(res))
- .catch(next);
- });
- /* App permissions */
- router.get('/apps/:appId/permissions', function (req, res, next) {
- const opts = Object.assign({ appId: req.params.appId }, req.query);
- gplay.permissions(opts)
- .then(toList)
- .then(res.json.bind(res))
- .catch(next);
- });
- /* App reviews */
- router.get('/apps/:appId/reviews', function (req, res, next) {
- function paginate(apps) {
- const page = parseInt(req.query.page || '0');
- const subpath = '/apps/' + req.params.appId + '/reviews/';
- if (page > 0) {
- req.query.page = page - 1;
- apps.prev = buildUrl(req, subpath) + '?' + qs.stringify(req.query);
- }
- if (apps.results.length) {
- req.query.page = page + 1;
- apps.next = buildUrl(req, subpath) + '?' + qs.stringify(req.query);
- }
- return apps;
- }
- const opts = Object.assign({ appId: req.params.appId }, req.query);
- gplay.reviews(opts)
- .then((reviews) => reviews.map(addSentiment()))
- .then(toList).then(paginate)
- .then(res.json.bind(res))
- .catch(next);
- });
- /* Apps by developer */
- router.get('/developers/:devId/', function (req, res, next) {
- const opts = Object.assign({ devId: req.params.devId }, req.query);
- gplay.developer(opts)
- .then((apps) => apps.map(cleanUrls(req)))
- .then((apps) => ({
- devId: req.params.devId,
- apps
- }))
- .then(res.json.bind(res))
- .catch(next);
- });
- /* Developer list (not supported) */
- router.get('/developers/', function (req, res) {
- res.status(400).json({
- message: 'Please specify a developer id.',
- example: buildUrl(req, '/developers/' + qs.escape('DxCo Games'))
- });
- });
- function errorHandler(err, req, res, next) {
- //res.status(400).json({ message: err.message + "\n" + err.stack.split("\n") });
- res.status(400).json({ message: err.message });
- next();
- }
- /* Test synchronous operation */
- router.get('/TestSync/', function (req, res, next) {
- const opts = Object.assign({ appId: req.params.appId, counter: 0 }, req.query);
- /*for (var i = 0; i < 20; i++) {
- gplay.reviews({
- appId: 'shree.hindi.gymguide',
- page: i,
- sort: gplay.sort.NEWEST,
- throttle: 5
- }).then(function (apps) {
- console.log("Return data length: "+ apps.length);
- }).catch(function (e) {
- console.log('There was an error fetching the reviews!');
- });
- }*/
- /*for (var i = 0; i < 5; i++) {
- doRequest({
- method: 'GET',
- uri: "http://localhost:3000/db/app/",
- json: true
- }).then(function (body) {
- console.log("Return id2: " + body[0]._id);
- });
- }*/
- /*async.whilst(
- function () {
- return opts.counter != 5;// && count < 5;
- },
- function (next) {
- console.log("Inside loop " + opts.counter);
- doRequest({
- method: 'GET',
- uri: "http://localhost:3000/db/app/",
- json: true
- }).then(function (body) {
- console.log("Return id1: " + body[0]._id);
- console.log("Return counter1: " + opts.counter);
- return body;
- }).then(function (body) {
- opts.counter++;
- console.log("Return id2: " + body[0]._id);
- console.log("Return counter2: " + opts.counter);
- next();
- });
- },
- function (err) {
- if (err) {
- console.log("Error async:" + err);
- } else {
- console.log("Finished!!!");
- }
- }
- );*/
- const reviewOpts = {
- appId: 'de.datenlotsen.campusnet.tuda',
- page: 0,
- sort: gplay.sort.NEWEST,
- throttle: 5
- };
- async.whilst(
- function () {
- return reviewOpts.page != -1;// && count < 5;
- },
- function (next) {
- console.log("Inside loop " + reviewOpts.page);
- gplay
- .reviews(reviewOpts)
- .then((reviews) => reviews.map(addSentiment()))
- .then(function (reviews) {
- console.log("Reviews length: " + reviews.length);
- if (!reviews.length) { reviewOpts.page = -1 }
- /*return doRequest({
- method: 'GET',
- uri: "http://localhost:3000/db/app/",
- json: true
- });*/
- /*return new Promise(function (resolve, reject) {
- reviews.map(function (review) {
- doRequest({
- method: 'GET',
- uri: "http://localhost:3000/db/app/",
- json: true
- }).then(function (body) {
- console.log("Return of Get requests: " + body[0]._id);
- });
- });
- resolve(reviews);
- });*/
- return new Promise(function (resolve, reject) {
- async.mapSeries(reviews, function (review, callback) {
- review.app = "582b633d8366b306c992c67f";
- console.log("Inside map series");
- doRequest({
- method: "POST",
- uri: "http://localhost:3000/db/review/",
- json: review
- }).then(function (body) {
- console.log("Return of Post requests: " + body._id);
- return callback(null, body);
- });
- }, function (err, results) {
- console.log("Finished map series!!!");
- console.log("Map Series finish review length: " + results.length);
- resolve(results);
- });
- });
- })
- /*.then(function (body) {
- console.log("Return id1: " + body[0]._id);
- console.log("Return counter1: " + reviewOpts.page);
- return body;
- })
- .then(function (body) {
- if (reviewOpts.page != -1) { reviewOpts.page++ };
- console.log("Return id2: " + body[0]._id);
- console.log("Return counter2: " + reviewOpts.page);
- next();
- })*/
- .then(function (reviews) {
- if (reviewOpts.page != -1) { reviewOpts.page++ };
- console.log("Reviews length2: " + reviews.length);
- console.log("Return counter1: " + reviewOpts.page);
- next();
- });
- },
- function (err) {
- if (err) {
- console.log("Error async:" + err);
- } else {
- console.log("Finished!!!");
- }
- }
- );
- res.json({ hi: "Finished!" });
- });
- router.get('/ShowAgg/:appId', function (req, res, next) {//Test Aggregation
- const opts = Object.assign({ appId: req.params.appId, counter: 0 }, req.query);
- models.app.findOne({ "appId": opts.appId })
- .then(function (result) {
- return result.toObject();
- })
- .then(function (app) {
- return new Promise(function (resolve, reject) {
- models.review.aggregate([
- {
- $match: {
- app: app._id
- }
- },
- {
- $group: {
- _id: "$app",
- total_reviews_confidence: { $sum: "$sentiment.sentimentConfidence" },
- total_reviews: { $sum: 1 }
- }
- }],
- function (err, res) {
- if (err) {
- console.log("err: " + JSON.stringify(err));
- reject(err);
- }
- console.log("total: " + JSON.stringify(res[0]));
- console.log("average: " + res[0].total_reviews_confidence / res[0].total_reviews);
- app.averageReviewConfidence = res[0].total_reviews_confidence / res[0].total_reviews;
- resolve(app);
- }
- );
- });
- //return app;
- })
- .then(res.json.bind(res))
- .catch(function (e) {
- console.log("error finding one app:" + JSON.stringify(e));
- next();
- });
- //res.json({ hi: "Finished!" });
- });
- /* Test end */
- router.get('/downloadedapps/', function (req, res, next) {
- var filter = {};
- var perPage = 10;
- var page = 0;
- if(req.query.genre) {
- filter.genreId = { $regex: '.*' + req.query.genre + '.*' };
- }
- if(req.query.page) {
- page = req.query.page;
- }
- models.app.find(filter).sort('title').skip(perPage * page).limit(20)
- .then((apps) => apps.map(function (app) {
- app.url = "http://localhost:3000/crawler/downloadedapps/" + app.appId;
- return app;
- }))
- .then(res.json.bind(res))
- .catch(function (e) {
- console.log("error fetching downloaded apps:" + JSON.stringify(e));
- next();
- });
- });
- router.get('/downloadedapps/:appId', function (req, res, next) {
- const opts = Object.assign({ appId: req.params.appId }, req.query);
- const posture = parseInt(req.query.posture || '0');
- var filter = {
- "appId": opts.appId
- };
- models.app.findOne(filter)
- .then(function (result) {
- return result.toObject();
- })
- .then(function (app) {
- return new Promise(function (resolve, reject) {
- models.review.aggregate([
- {
- $match: {
- app: app._id
- }
- },
- {
- $group: {
- _id: "$app",
- total_reviews_confidence: { $sum: "$sentiment.sentimentConfidence" },
- review_rating_sum: { $sum: "$sentiment.scaledReviewRating" },
- total_reviews: { $sum: 1 },
- total_ratingValue: { $sum: "$score" }
- }
- }],
- function (err, res) {
- if (err) {
- console.log("err: " + JSON.stringify(err));
- reject(err);
- }
- console.log("reviews total: " + JSON.stringify(res[0]));
- console.log("average: " + res[0].total_reviews_confidence / res[0].total_reviews);
- //source: http://stackoverflow.com/questions/929103/convert-a-number-range-to-another-range-maintaining-ratio
- //(((OldValue - OldMin) * (NewMax - NewMin)) / (OldMax - OldMin)) + NewMin
- app.reviewsTrustValue = ((((res[0].total_ratingValue / res[0].total_reviews) - 1) * (1 - 0)) / (5 - 1)) + 0;
- app.reviewsConfidenceValue = res[0].total_reviews_confidence / res[0].total_reviews;//averageReviewConfidence
- app.reviewMetric = res[0].review_rating_sum / res[0].total_reviews;
- resolve(app);
- }
- );
- });
- })
- .then(function (app) {
- return new Promise(function (resolve, reject) {
- models.app.aggregate([
- {
- $project: {
- genreId: 1,
- permissions_count: { $size: "$permissions" }
- }
- },
- {
- $match: {
- genreId: app.genreId
- }
- },
- {
- $group: {
- _id: "$genreId",
- same_genre_permissions_count: { $sum: "$permissions_count" },
- same_genre_count: { $sum: 1 }
- }
- }],
- function (err, res) {
- if (err) {
- console.log("err: " + JSON.stringify(err));
- reject(err);
- }
- //console.log("permissions total: " + JSON.stringify(res));
- app.categoryAveragePermission = Math.floor(res[0].same_genre_permissions_count / res[0].same_genre_count);
- console.log("categoryAveragePermission: " + app.categoryAveragePermission);
- let powerValue = app.permissions.length - app.categoryAveragePermission;
- app.permissionsTrustValue = (((app.score - 1) * (1 - 0)) / (5 - 1)) + 0;
- app.cofidenceInNumberofPermissions = (factorial(app.categoryAveragePermission) / factorial(app.permissions.length)) * Math.pow(app.categoryAveragePermission, powerValue);
- resolve(app);
- }
- );
- });
- })
- .then(function (app) {
- return new Promise(function (resolve, reject) {
- models.app.find({ "genreId": app.genreId })
- .then(function (results) {
- app.genreCount = results.length;
- resolve(app);
- })
- .catch(function (err) {
- reject(err);
- });
- });
- })
- .then(function (app) {
- console.log(app.histogram["1"]);
- let totalRatingsSum = (app.histogram["1"] * 1) + (app.histogram["2"] * 2) + (app.histogram["3"] * 3) + (app.histogram["4"] * 1) + (app.histogram["5"] * 5);
- let averageRating = totalRatingsSum / app.reviewsCount;
- console.log("rc: " + app.reviewsCount);
- console.log("av: " + averageRating);
- console.log("score: " + app.score);
- let wmd = 0;
- if (app.histogram["1"] + app.histogram["2"] + app.histogram["3"] == 0) {
- wmd = ((app.histogram["4"] * Math.abs(averageRating - 4)) / app.reviewsCount) + ((app.histogram["5"] * Math.abs(averageRating - 5)) / app.reviewsCount);
- } else if (app.histogram["3"] + app.histogram["4"] + app.histogram["5"] == 0) {
- wmd = ((app.histogram["1"] * Math.abs(averageRating - 1)) / app.reviewsCount) + ((app.histogram["2"] * Math.abs(averageRating - 2)) / app.reviewsCount);
- } else {
- let lowerRatingCount = app.histogram["1"] + app.histogram["2"] + app.histogram["3"];
- let upperRatingCount = app.histogram["5"] + app.histogram["4"] + app.histogram["3"];
- let lowerAverageRating = ((app.histogram["1"] * 1) + (app.histogram["2"] * 2) + (app.histogram["3"] * 3)) / lowerRatingCount;
- console.log("lowerAverageRating: " + lowerAverageRating);
- let upperAverageRating = ((app.histogram["5"] * 5) + (app.histogram["4"] * 4) + (app.histogram["3"] * 3)) / upperRatingCount;
- console.log("upperAverageRating: " + upperAverageRating);
- let lowerWeight = lowerRatingCount / (lowerRatingCount + upperRatingCount);
- console.log("lowerWeight: " + lowerWeight);
- let upperWeight = upperRatingCount / (lowerRatingCount + upperRatingCount);
- console.log("upperWeight: " + upperWeight);
- wmd = (lowerWeight * Math.abs(averageRating - lowerAverageRating)) + (upperWeight * Math.abs(averageRating - upperAverageRating));
- console.log("wmd: " + wmd);
- }
- app.averageRatingTrustValue = (((app.score - 1) * (1 - 0)) / (5 - 1)) + 0;
- app.averageRatingConfidenceValue = 1 - (wmd / 2);
- console.log("averageRatingConfidenceValue: " + app.averageRatingConfidenceValue);
- return app;
- })
- .then(function(app) {
- let sLength = 25;
- let pLength = 9;
- let sPositiveEvidences = 0;
- let sNegativeEvidences = 0;
- let pPositiveEvidences = 0;
- let pNegativeEvidences = 0;
- if(posture) {
- sLength--;
- pLength--;
- }
- _(app.appicaptor.indicator).each(function (element, index) {
- //console.log(element.attr);
- //console.log(index);//just the index 0....n
- if (element.attr.text == "Client communication used?") {
- if (element.attr.value == "yes") {
- sNegativeEvidences++;
- } else {
- sPositiveEvidences++;
- }
- }
- if (element.attr.text == "SSL/TLS used?") {
- if (element.attr.value == "no") {
- sNegativeEvidences++;
- } else {
- sPositiveEvidences++;
- }
- }
- if (element.attr.text == "Domains accessed with http AND https: ") {
- if (element.resultList[0].result.length > 0) {
- sNegativeEvidences++;
- } else {
- sPositiveEvidences++;
- }
- }
- if (element.attr.text == "Custom SSL/TLS trust manager implemented?") {
- if (element.attr.value == "yes") {
- sNegativeEvidences++;
- } else {
- sPositiveEvidences++;
- }
- }
- if (element.attr.text == "Faulty custom SSL/TLS trust manager implemented?") {
- if (element.attr.value == "yes") {
- sNegativeEvidences++;
- } else {
- sPositiveEvidences++;
- }
- }
- if (element.attr.text == "SSL/TLS using custom error handling?") {
- if (element.attr.value == "yes") {
- sNegativeEvidences++;
- } else {
- sPositiveEvidences++;
- }
- }
- if (element.attr.text == "SSL/TLS using faulty custom error handling?") {
- if (element.attr.value == "yes") {
- sNegativeEvidences++;
- } else {
- sPositiveEvidences++;
- }
- }
- if (element.attr.text == "SSL/TLS using manual domain name verification?") {
- if (element.attr.value == "yes") {
- sNegativeEvidences++;
- } else {
- sPositiveEvidences++;
- }
- }
- if (element.attr.text == "Unprotected communication?") {
- if (element.attr.value == "yes") {
- sNegativeEvidences++;
- } else {
- sPositiveEvidences++;
- }
- }
- if (element.attr.text == "Unprotected HTML?") {
- if (element.attr.value == "yes") {
- sNegativeEvidences++;
- } else {
- sPositiveEvidences++;
- }
- }
- if (element.attr.text == "Cryptographic Primitives: ") {
- if (element.resultList[0].result.length > 0) {
- sNegativeEvidences++;
- } else {
- sPositiveEvidences++;
- }
- }
- if (element.attr.text == "Application needs dangerous permissions? ") {
- if (element.attr.value == "yes") {
- sNegativeEvidences++;
- } else {
- sPositiveEvidences++;
- }
- }
- if (element.attr.text == "JavaScript to SDK API bridge usage?") {
- if (element.attr.value == "yes") {
- sNegativeEvidences++;
- } else {
- sPositiveEvidences++;
- }
- }
- if (element.attr.text == "Is application overprivileged?" && !posture) {
- if (element.attr.value == "yes") {
- sNegativeEvidences++;
- } else {
- sPositiveEvidences++;
- }
- }
- if (element.attr.text == "Userdefined permission usage: ") {
- if (element.resultList[0].result.length > 0) {
- sNegativeEvidences++;
- } else {
- sPositiveEvidences++;
- }
- }
- if (element.attr.text == "WiFi-Direct enabled?") {
- if (element.attr.value == "yes") {
- sNegativeEvidences++;
- } else {
- sPositiveEvidences++;
- }
- }
- if (element.attr.text == "App can handle documents of mimeType: ") {
- if (element.attr.value == "none") {
- sPositiveEvidences++;
- } else {
- sNegativeEvidences++;
- }
- }
- if (element.attr.text == "Screenshot protection used?") {
- if (element.attr.value == "yes") {
- sPositiveEvidences++;
- } else {
- sNegativeEvidences++;
- }
- }
- if (element.attr.text == "Tap Jacking Protection used?") {
- if (element.attr.value == "yes") {
- sPositiveEvidences++;
- } else {
- sNegativeEvidences++;
- }
- }
- if (element.attr.text == "Scheduled Alarm Manager registered?") {
- if (element.attr.value == "no") {
- sPositiveEvidences++;
- } else {
- sNegativeEvidences++;
- }
- }
- if (element.attr.text == "Dynamically loaded code at runtime?") {
- if (element.attr.value == "no") {
- sPositiveEvidences++;
- } else {
- sNegativeEvidences++;
- }
- }
- if (element.attr.text == "Allow app debugging Flag?") {
- if (element.attr.value == "no") {
- sPositiveEvidences++;
- } else {
- sNegativeEvidences++;
- }
- }
- if (element.attr.text == "Allow autoexecute after Phone Reboot?") {
- if (element.attr.value == "no") {
- sPositiveEvidences++;
- } else {
- sNegativeEvidences++;
- }
- }
- if (element.attr.text == "App uses outdated signature key?") {
- if (element.attr.value == "no") {
- sPositiveEvidences++;
- } else {
- sNegativeEvidences++;
- }
- }
- if (element.attr.text == "Contains native libraries: ") {
- if (element.attr.value == "no") {
- sPositiveEvidences++;
- } else {
- sNegativeEvidences++;
- }
- }
- //privacy
- if (element.attr.text == "Obfuscation used?") {
- if (element.attr.value == "yes") {
- pPositiveEvidences++;
- } else {
- pNegativeEvidences++;
- }
- }
- if (element.attr.text == "Device administration policy entries: ") {
- if (element.attr.value == "none") {
- pPositiveEvidences++;
- } else {
- pNegativeEvidences++;
- }
- }
- if (element.attr.text == "Accessed unique identifier(s): ") {
- if (element.resultList[0].result.length > 0) {
- pNegativeEvidences++;
- } else {
- pPositiveEvidences++;
- }
- }
- if (element.attr.text == "Advertisment-/tracking frameworks found: " && !posture) {
- if (element.attr.value == "none") {
- pPositiveEvidences++;
- } else if (element.resultList[0].result.length > 10) {
- pNegativeEvidences++;
- } else {
- pPositiveEvidences++;
- }
- }
- if (element.attr.text == "App provides public accessible activities?") {
- if (element.attr.value == "yes") {
- pNegativeEvidences++;
- } else {
- pPositiveEvidences++;
- }
- }
- if (element.attr.text == "Backup of app is allowed?") {
- if (element.attr.value == "yes") {
- pNegativeEvidences++;
- } else {
- pPositiveEvidences++;
- }
- }
- if (element.attr.text == "Log Statement Enabled?") {
- if (element.attr.value == "yes") {
- pNegativeEvidences++;
- } else {
- pPositiveEvidences++;
- }
- }
- if (element.attr.text == "Permission to access address book?") {
- if (element.attr.value == "yes") {
- pNegativeEvidences++;
- } else {
- pPositiveEvidences++;
- }
- }
- if (element.attr.text == "Unprotected preference files found?") {
- if (element.attr.value == "yes") {
- pNegativeEvidences++;
- } else {
- pPositiveEvidences++;
- }
- }
- })
- console.log("sPositiveEvidences " + sPositiveEvidences);
- console.log("sNegativeEvidences " + sNegativeEvidences);
- console.log("pPositiveEvidences " + pPositiveEvidences);
- console.log("pNegativeEvidences " + pNegativeEvidences);
- app.sTrustValue = sPositiveEvidences/(sPositiveEvidences+sNegativeEvidences);
- app.sConfidenceValue = (sLength*(sPositiveEvidences+sNegativeEvidences))/((2*(sLength-(sPositiveEvidences+sNegativeEvidences)))+(sLength*(sPositiveEvidences+sNegativeEvidences)));
- app.pTrustValue = pPositiveEvidences/(pPositiveEvidences+pNegativeEvidences);
- app.pConfidenceValue = (pLength*(pPositiveEvidences+pNegativeEvidences))/((2*(pLength-(pPositiveEvidences+pNegativeEvidences)))+(pLength*(pPositiveEvidences+pNegativeEvidences)));
- return app;
- })
- .then(res.json.bind(res))
- .catch(function (e) {
- console.log("error fetching downloaded app: " + JSON.stringify(e));
- next();
- });
- });
- function doRequest(opts) { //will be used in later phase may be
- return new Promise((resolve, reject) => requestLib(opts, function (error, response, body) {
- if (error) {
- return reject(error);
- }
- if (response.statusCode >= 400) {
- return reject({ response });
- }
- resolve(body);
- }));
- }
- router.get('/insertAppicaptorData/:appId', function (req, res, next) {
- var obj = JSON.parse(fs.readFileSync('./appicaptor/outputall.json', 'utf8'));
- var outputObj = {
- overprivilegedPermission: {},
- dangerousPermission: {},
- extensiveTrackingFrameworkUsage: {},
- outdatedCryptographicPrimitives: {},
- unprotectedCommunication: {}
- };
- for (var i = 0; i < obj.report.app.length; i++) {
- //console.log("ff: " + obj.report.app[i].$.appId.split(":")[0]);
- //console.log("ll: " + req.params.appId);
- if (obj.report.app[i].attr.appId.split(":")[0] == req.params.appId) {
- //console.log("isnersfsdf");
- for (var j = 0; j < obj.report.app[i].indicator.length; j++) {
- //do something with obj[i]
- for (var ind in obj.report.app[i].indicator[j]) {
- for (var vals in obj.report.app[i].indicator[j][ind]) {
- //Privacy Risks
- if (obj.report.app[i].indicator[j][ind][vals] == "Redundant permission correlation") {
- outputObj.overprivilegedPermission.Value = obj.report.app[i].indicator[j][ind]["value"];
- }
- if (obj.report.app[i].indicator[j][ind][vals] == "Overprivileged permission yes/no") {
- if (obj.report.app[i].indicator[j]["resultList"] != undefined) {
- outputObj.overprivilegedPermission.List = obj.report.app[i].indicator[j]["resultList"][0].result;
- }
- }
- if (obj.report.app[i].indicator[j][ind][vals] == "Dangerous Permission") {
- outputObj.dangerousPermission.Value = obj.report.app[i].indicator[j][ind]["value"];
- if (obj.report.app[i].indicator[j]["detailList"] != undefined) {
- outputObj.dangerousPermission.List = obj.report.app[i].indicator[j]["detailList"][0].detail;
- }
- }
- if (obj.report.app[i].indicator[j][ind][vals] == "privacy-risk") {
- outputObj.extensiveTrackingFrameworkUsage.Value = obj.report.app[i].indicator[j][ind]["value"];
- if (obj.report.app[i].indicator[j]["detailList"] != undefined) {
- outputObj.extensiveTrackingFrameworkUsage.Reason = obj.report.app[i].indicator[j]["detailList"][0].detail;
- }
- }
- if (obj.report.app[i].indicator[j][ind][vals] == "Advertisment/Tracking Usage") {
- if (obj.report.app[i].indicator[j]["resultList"] != undefined) {
- outputObj.extensiveTrackingFrameworkUsage.List = obj.report.app[i].indicator[j]["resultList"][0].result;
- }
- }
- //Security Risks
- if (obj.report.app[i].indicator[j][ind][vals] == "Cryptographic Primitives: ") {
- outputObj.outdatedCryptographicPrimitives.Value = obj.report.app[i].indicator[j][ind]["value"];
- if (obj.report.app[i].indicator[j]["resultList"] != undefined) {
- outputObj.outdatedCryptographicPrimitives.List = obj.report.app[i].indicator[j]["resultList"][0].result;
- }
- }
- if (obj.report.app[i].indicator[j][ind][vals] == "HTTP Access") {
- outputObj.unprotectedCommunication.Value = obj.report.app[i].indicator[j][ind]["value"];
- if (obj.report.app[i].indicator[j]["detailList"] != undefined) {
- outputObj.unprotectedCommunication.List = obj.report.app[i].indicator[j]["detailList"][0].detail;
- }
- }
- }
- }
- }
- }
- }
- models.app.findOne({ "appId": req.params.appId })
- .then(function (result) {
- //console.log(outputObj);
- result.appicaptor = outputObj;
- return result;
- })
- .then(saveAppData)
- .then(res.json.bind(res))
- .catch(function (e) {
- console.log("error fetching downloaded apps:" + JSON.stringify(e));
- next();
- });
- });
- router.get('/getDownloadInfo/:appId', function (req, res, next) {//if no data is avaiable it will first download app's data first
- const opts = Object.assign({ appId: req.params.appId }, req.query);
- models.app.findOne({ "appId": opts.appId })
- .then(function (result) {
- //console.log(result);
- if (result) {
- return result.toObject();
- } else {
- //return null;
- return new Promise(function (resolve, reject) {
- gplay.app(opts)
- .then(cleanUrls(req))
- .then(function (app) {
- app.reviews = [];
- app.permissions = [];
- return new models.app(app);
- })
- .then(saveAppData)
- .then(function(app) {
- resolve(app);
- })
- .catch(function(e) {
- reject(e);
- });
- });
- }
- })
- .then(res.json.bind(res));
- });
- router.get('/getReviews/:appId', function (req, res, next) {
- const opts = Object.assign({ appId: req.params.appId }, req.query);
- models.app.findOne({ "appId": opts.appId })
- .then(function (result) {
- //console.log(result);
- return result;
- })
- .then(fetchReviewAndSave(opts))
- .then(saveAppData)
- .then(res.json.bind(res));
- });
- //not used
- router.get('/getReviewsFromGoogle/:appId', function (req, res, next) {
- const opts = Object.assign({ appId: req.params.appId }, req.query);
- opts.page = parseInt(req.query.page || '0');
- gplay.reviews(opts)
- .then(toList)
- .then(res.json.bind(res))
- .catch(next);
- });
- //not used
- router.get('/fetchReview/:appId', function (req, res, next) {
- const opts = Object.assign({ appId: req.params.appId }, req.query);
- opts.page = parseInt(req.query.page || '0');
- console.log("review page no:" + opts.page);
- models.app.findOne({ "appId": opts.appId })
- .then(function (result) {
- return result;
- })
- .then(function (app) {
- return new Promise(function (resolve, reject) {
- gplay
- .reviews(opts)
- .then((reviews) => reviews.map(addSentiment()))
- .then(function (reviews) {
- console.log("Reviews length: " + reviews.length);
- return new Promise(function (resolve, reject) {
- async.mapSeries(reviews, function (review, callback) {
- review.app = app._id;
- new models.review(review).save()
- .then(function (result) {
- app.reviews.push(result._id);
- return callback(null, result);
- })
- .catch(function (e) {
- console.log("error saving one review:" + JSON.stringify(e));
- if (e.code === 11000 || e.code === 11001) {
- models.review.findOne({ "reviewId": review.reviewId })
- .then(function (result) {
- return callback(null, result);
- })
- .catch(function (e) {
- console.log("error finding one review:" + JSON.stringify(e));
- return callback(e, null);
- });
- } else {
- return callback(e, null);
- }
- //return callback(e, null);
- });
- }, function (err, results) {
- //console.log("Error map series: " + JSON.stringify(err));
- //console.log("Finished map series!!!");
- console.log("Map Series finish review length: " + results.length);
- resolve(reviews);
- });
- });
- })
- .then(function (reviews) {
- resolve(app);
- })
- .catch(function (e) {
- reject(e);
- })
- });
- })
- .then(saveAppData)
- .then(res.json.bind(res))
- .catch(next);
- });
- router.get('/getPermissions/:appId', function (req, res, next) {
- const opts = Object.assign({ appId: req.params.appId }, req.query);
-
- models.app.findOne({ "appId": opts.appId })
- .then(function (result) {
- //console.log(result);
- return result;
- })
- .then(fetchPermissions(opts))
- .then(saveAppData)
- .then(res.json.bind(res));
- });
- router.get('/getAppicaptorResult/:appId', function (req, res, next) {
- const opts = Object.assign({ appId: req.params.appId }, req.query);
- models.app.findOne({ "appId": opts.appId })
- .then(function (result) {
- //console.log(result);
- return result;
- })
- .then(function (app) {
- var obj = JSON.parse(fs.readFileSync('./appicaptor/outputall.json', 'utf8'));
- //var appicaptorObj = _(obj.report.app).findWhere({ appId: app.appId });
- var appicaptorObj = _.filter(obj.report.app, function (appicaptorApp) {
- return appicaptorApp.attr.appId.split(":")[0] == app.appId;
- })[0];
- app.appicaptor = appicaptorObj;
- return app;
- })
- .then(saveAppData)
- .then(res.json.bind(res));
- });
- router.use(errorHandler);
- module.exports = router;
|