Skip to content
This repository has been archived by the owner on Mar 12, 2022. It is now read-only.

Commit

Permalink
Add complete download info (#35)
Browse files Browse the repository at this point in the history
* added getCompleteDownloadInfo to be used before downloadApk
  • Loading branch information
dweinstein committed May 5, 2016
1 parent c648986 commit f1a8d88
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 10 deletions.
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,3 +110,18 @@ Call Google Play APIs from Node. You might want to check out the [CLI](https://g
}
```
## Complete Download info - complete object to be passed seamlessly to request.js
```javascript
± % node examples/completeDownloadInfo.js | jq '.'
{ url: 'https://android.clients.google.com/market/download/Download?packageName=com.viber.voip&versionCode=37&ssl=1&token=xxxxxxxxx&downloadId=-xxxxxxxxxxx',
jar:
RequestJar {
_jar:
CookieJar {
enableLooseMode: true,
store: { idx: { 'android.clients.google.com': { '/market/download': { MarketDA: Cookie="MarketDA=xxxxxxxx; Path=/market/download; hostOnly=true; aAge=29ms; cAge=29ms" } } } } } },
headers:
{ 'User-Agent': 'AndroidDownloadManager/4.2.2 (Linux; U; Android 4.2.2; Galaxy Nexus Build/JDQ39)',
'Accept-Encoding': '' } }
```
35 changes: 25 additions & 10 deletions lib/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -408,23 +408,35 @@ var GooglePlay = (function GooglePlay(username, password, androidId, useCache, _
}

/**
* Download a specific package, at a specific versionCode.
* @return {Promise} promise of request object, e.g., can use .pipe(..)
* returns complete and request-ready options object
* @param pkg
* @param versionCode
*/
function downloadApk(pkg, versionCode) {
function getCompleteDownloadInfo(pkg, versionCode) {
var headers = {
"User-Agent": DOWNLOAD_MANAGER_USER_AGENT,
"Accept-Encoding": ""
};

return getDownloadInfo(pkg, versionCode)
.then(function (res) {
assert(res.downloadUrl, 'require downloadUrl');
assert(res.downloadAuthCookie, 'require downloadAuthCookie');
var url = res.downloadUrl;
var cookieJar = _prepCookies(url, res.downloadAuthCookie);
return request.get({url: url, jar: cookieJar, headers: headers});
});
.then(function (res) {
assert(res.downloadUrl, 'require downloadUrl');
assert(res.downloadAuthCookie, 'require downloadAuthCookie');
var url = res.downloadUrl;
var cookieJar = _prepCookies(url, res.downloadAuthCookie);
return {url: url, jar: cookieJar, headers: headers};
})
}

/**
* Download a specific package, at a specific versionCode.
* @return {Promise} promise of request object, e.g., can use .pipe(..)
*/
function downloadApk(pkg, versionCode) {
return getCompleteDownloadInfo(pkg, versionCode)
.then(function (options) {
return request.get(options);
});
}

function cachedKeys() {
Expand Down Expand Up @@ -459,6 +471,9 @@ var GooglePlay = (function GooglePlay(username, password, androidId, useCache, _
downloadInfo: function downloadInfo(pkg, vc, cb) {
return getDownloadInfo(pkg, vc).nodeify(cb);
},
completeDownloadInfo: function completeDownloadInfo(pkg, vc, cb) {
return getCompleteDownloadInfo(pkg, vc).nodeify(cb);
},
download: function download(pkg, vc, cb) {
return downloadApk(pkg, vc).nodeify(cb);
},
Expand Down
46 changes: 46 additions & 0 deletions test/completeDownloadInfo.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
var api = require('./api');
var test = require('tape');
var AppNotFreeError = require('../lib/errors').AppNotFreeError;
var RequestError = require('../lib/errors').RequestError;

test('completeDownloadInfo api', function (t) {
t.plan(8);
api.completeDownloadInfo('com.viber.voip', 37, function (err, res) {
t.notOk(err, 'no error');
t.ok(res, 'returned results');

t.ok(res.hasOwnProperty('url'), 'url in response');
t.ok(res.url.indexOf('com.viber.voip') > -1, 'package name should be in response url');

t.ok(res.hasOwnProperty('jar'), 'response should have cookie jar');

t.ok(res.hasOwnProperty('headers'), 'response has headers');
t.ok(res.headers.hasOwnProperty('User-Agent'), 'User-Agent in response headers');
t.ok(res.headers.hasOwnProperty('Accept-Encoding'), 'Accept-Encoding in response headers');
});
});

// TODO: fix this test
test.skip('completeDownloadInfo api - Paid apps', function (t) {
t.plan(5);
api.completeDownloadInfo('com.mojang.minecraftpe', 740140009, function (err, res) {
t.ok(err, 'error expected');
t.ok(err instanceof AppNotFreeError, 'error instanceof AppNotFreeError');
t.ok(err.name === 'AppNotFreeError', 'error.name is AppNotFreeError');
t.ok(err.price, 'error has price');
t.notOk(res, 'no results');
t.comment('price: ' + err.price);
});
});

test('completeDownloadInfo api - Item not found ', function (t) {
t.plan(5);
api.completeDownloadInfo('i.should.probably.not.exist', 25, function (err, res) {
t.ok(err instanceof RequestError, 'RequestError');
t.ok(err, 'error returned');
t.notOk(res, 'no response');
t.ok(err.message = 'Item not found', 'error msg');
t.equal(err.statusCode, 403, 'status code');
});
});

0 comments on commit f1a8d88

Please sign in to comment.