permissions.js•3.04 kB
'use strict';
const debug = require('debug')('google-play-scraper:permissions');
const R = require('ramda');
const request = require('./utils/request');
const scriptData = require('./utils/scriptData');
const { BASE_URL } = require('./constants');
const c = require('./constants');
function permissions (opts) {
return new Promise(function (resolve, reject) {
if (!opts && !opts.appId) {
throw Error('appId missing');
}
opts.lang = opts.lang || 'en';
processPermissions(opts)
.then(resolve)
.catch(reject);
});
}
function processPermissions (opts) {
const body = `f.req=%5B%5B%5B%22xdSrCf%22%2C%22%5B%5Bnull%2C%5B%5C%22${opts.appId}%5C%22%2C7%5D%2C%5B%5D%5D%5D%22%2Cnull%2C%221%22%5D%5D%5D`;
const url = `${BASE_URL}/_/PlayStoreUi/data/batchexecute?rpcids=qnKhOb&f.sid=-697906427155521722&bl=boq_playuiserver_20190903.08_p0&hl=${opts.lang}&authuser&soc-app=121&soc-platform=1&soc-device=1&_reqid=1065213`;
debug('batchexecute URL: %s', url);
debug('with body: %s', body);
const requestOptions = Object.assign({
url,
method: 'POST',
body,
followRedirect: true,
headers: {
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
}
}, opts.requestOptions);
return request(requestOptions, opts.throttle)
.then((html) => {
const input = JSON.parse(html.substring(5));
const data = JSON.parse(input[0][2]);
if (data === null) {
return [];
}
return (opts.short)
? processShortPermissionsData(data)
: processPermissionData(data);
});
}
const MAPPINGS = {
permissions: [2],
type: 0
};
function processShortPermissionsData (html) {
if (R.is(String, html)) {
html = scriptData.parse(html);
}
const commonPermissions = html[c.permission.COMMON];
if (!commonPermissions) {
return [];
}
const validPermissions = commonPermissions.filter(permission => permission.length);
const permissionNames = R.chain(permission => permission[MAPPINGS.type], validPermissions);
return permissionNames;
}
function processPermissionData (html) {
if (R.is(String, html)) {
html = scriptData.parse(html);
}
debug(`html %o`, html);
const permissions = Object.values(c.permission).reduce((permissionAccummulator, permission) => {
if (!html[permission]) {
return permissionAccummulator;
}
permissionAccummulator.push(
...R.chain(flatMapPermissions, html[permission])
);
return permissionAccummulator;
}, []);
debug(`Permissions %o`, permissions);
return permissions;
}
function flatMapPermissions (permission) {
const input = R.path(MAPPINGS.permissions, permission);
if (typeof input === 'undefined') {
return [];
}
const mappings = getPermissionMappings(permission[MAPPINGS.type]);
return R.map(scriptData.extractor(mappings), input);
}
function getPermissionMappings (type) {
return {
permission: [1],
type: {
path: 0,
fun: () => type
}
};
}
module.exports = permissions;