def init_api(acct_email, acct_password, gsf, auth_sub_token=None, max_attempts=15, cooldown_secs=10): global api assert max_attempts > 0, 'max_attempts was %d, must be greater than 0' % max_attempts assert cooldown_secs > 0, 'cooldown_secs was %d, must be greater than 0' % cooldown_secs if api is None: # Ensure we have all the credentials we need assert acct_email is not None, 'Account email address is required' assert acct_password is not None, 'Account password is required' assert gsf is not None, 'Google Services Framework ID is required' # Authenticate the API, keep trying until it works api = GooglePlayAPI(androidId=gsf) for attempt in range(max(1, max_attempts)): attempt = attempt + 1 try: login(email=acct_email, password=acct_password, authSubToken=auth_sub_token) logging.info('Successfully logged in as %s' % acct_email) return except LoginError as e: logging.warning('BadAuthentication on attempt %d/%d' % (attempt, max_attempts)) if(attempt == max_attempts): raise e logging.warning('Retrying authentication in %d seconds' % cooldown_secs) time.sleep(cooldown_secs)
def _login(self): ''' user android_id, user name and password or AUTH_TOKEN to login ''' self._configTest() api = GooglePlayAPI(self._android_id) api.login(self._user, self._passwd, self._auth_token) return api
def __init__(self): try: creds = loadPlayStoreConfig() self.googleLogin = creds['GOOGLE_LOGIN'] self.googlePassword = creds['GOOGLE_PASSWORD'] self.androidID = creds['ANDROID_ID'] self.authToken = creds['AUTH_TOKEN'] self.api = GooglePlayAPI(self.androidID) # Login to the Play Store except Exception as e: prettyPrintError(e)
def init_api(acct_email, acct_password, gsf): global api if api is None: # Ensure we have all the credentials we need assert acct_email is not None, 'Account email address is required' assert acct_password is not None, 'Account password is required' assert gsf is not None, 'Google Services Framework ID is required' # Authenticate the API api = GooglePlayAPI(androidId=gsf) api.login(email=acct_email, password=acct_password)
def download_reference_apk(self): api = GooglePlayAPI(self.android_id) api.login(self.google_login, self.google_password) package = api.details(self.results['package']) doc = package.docV2 version = doc.details.appDetails.versionCode offer_type = doc.offer[0].offerType ref_path = path.join(self.tmpdir, "ref.apk") data = api.download(self.results['package'], version, offer_type) with open(ref_path, "wb") as out: out.write(data) return ref_path
def __init__(self, android_id=None, username=None, password=None, auth_token=None, proxy=None, max_login_retries=10, language=None, debug=False): self._api = GooglePlayAPI(android_id, language, debug) self._username = username self._password = password self._auth_token = auth_token self._proxy = proxy self._max_login_retries = max_login_retries self._login_lock = Lock() self._logged_in = False
ctr = None nb_results = None offset = None if (len(sys.argv) >= 3): ctr = sys.argv[2] if (len(sys.argv) >= 4): nb_results = sys.argv[3] if (len(sys.argv) == 5): offset = sys.argv[4] # read config from config.py config = GooglePlayAPI.read_config() # connect to GooglePlayStore api = GooglePlayAPI(config['ANDROID_ID']) api.login(config['GOOGLE_LOGIN'], config['GOOGLE_PASSWORD'], config['AUTH_TOKEN']) try: message = api.list(cat, ctr, nb_results, offset) except: print("Error: HTTP 500 - one of the provided parameters is invalid") sys.exit(1) if (ctr is None): print("Subcategory ID", "Name", sep=config['SEPARATOR']) for doc in message.doc: print(helpers.str_compat(doc.docid), helpers.str_compat(doc.title), sep=config['SEPARATOR'])
if (len(sys.argv) < 2): print "Usage: %s packagename [filename]" print "Download an app." print "If filename is not present, will write to packagename.apk." sys.exit(0) packagename = sys.argv[1] if (len(sys.argv) == 3): filename = sys.argv[2] else: filename = packagename + ".apk" # Connect api = GooglePlayAPI(ANDROID_ID) api.login(GOOGLE_LOGIN, GOOGLE_PASSWORD, AUTH_TOKEN) # Get the version code and the offer type from the app details m = api.details(packagename) doc = m.docV2 vc = doc.details.appDetails.versionCode ot = doc.offer[0].offerType # Download print "Downloading %s..." % sizeof_fmt( doc.details.appDetails.installationSize), data = api.download(packagename, vc, ot) open(filename, "wb").write(data) print "Done"
def main(): logging.basicConfig(level=logging.INFO) parser = argparse.ArgumentParser( description='Unofficial PlayStore python interface', add_help=True) parser.add_argument('--request', action="store", dest='request_path', help='Do a generic request, useful for deugging') parser.add_argument('--details', action="store", dest='package_to_detail', help='Shows various details for the ' 'given package') parser.add_argument('--search', action="store", dest='query', help='Search the playstore') parser.add_argument('--similar', action="store", dest='package_similar', help='Shows various packages similar ' 'to the given package') parser.add_argument('--bulk-details', action="store", dest='packages_to_detail', nargs='+', type=str, help='Shows details for a list of packages') list_group = parser.add_argument_group() list_group.add_argument( '--list', action="store_true", dest='list', help= 'List the categories avilable on playstore. If --category is specified, lists the ' 'subcategories of the specified category. If --subcategory is also specified, lists ' 'the app in the subcategory.') list_group.add_argument( '--category', action="store", dest='cat', help='Specify a certain category (e.g. GAME_ARCADE)') list_group.add_argument( '--subcategory', action="store", dest='subcat', help='Specify a certain subcategory (e.g. apps_topselling_free)') group = parser.add_argument_group() group.add_argument('--download', action="store", dest='package_to_download', help='Download the apk with given ' 'package name') group.add_argument('-o', action="store", dest='output_folder', help='(optional) Where to ' 'save the downloaded apk') group.add_argument('--version', action="store", dest='version_code', help='(optional) Version Code of the apk' 'to download (default: latest)') parser.add_argument('--remote-token', action="store", dest='token_url', help='If the authentication token should be' ' retrieved from a remote server') group_proxy = parser.add_argument_group() group_proxy.add_argument('--http-proxy', action="store", dest='http_proxy', help='http proxy, ONLY used for' 'Play Store requests!') group_proxy.add_argument('--https-proxy', action="store", dest='https_proxy', help='https proxy, ONLY used for' 'Play Store requests!') results = parser.parse_args() proxies = None if results.http_proxy: if proxies is None: proxies = {} proxies["http"] = results.http_proxy if results.https_proxy: if proxies is None: proxies = {} proxies["https"] = results.https_proxy global play_store play_store = GooglePlayAPI(throttle=True, proxies=proxies) token = None if results.token_url: response = requests.get(results.token_url) token = response.text print("Using auth token: {0}".format(token)) play_store.login(authSubToken=token) if results.request_path: get_message(results.request_path) return if results.package_to_detail: get_details(results.package_to_detail) return if results.query: search(results.query) return if results.packages_to_detail: get_bulk_details(results.packages_to_detail) return if results.package_similar: get_similar(results.package_similar) return if results.list: list_category(results.cat, results.subcat) return if results.package_to_download: package = results.package_to_download version = results.version_code output_folder = results.output_folder if output_folder: os.path.join(output_folder, package + ".apk") else: output_folder = package + ".apk" download_apk(results.package_to_download, version, output_folder) return parser.print_help()
class GooglePlayApiTest(unittest.TestCase): api = GooglePlayAPI() @classmethod def setUpClass(cls): details = get_access_details() api = GooglePlayApiTest.api api.androidId = os.environ.get('ANDROID_ID', details.get('androidId')) last_error = None for _ in xrange(10): try: api.login(email=os.environ.get('GOOGLE_USERNAME', details.get('username')), password=os.environ.get('GOOGLE_PASSWORD', details.get('password'))) break except LoginError as err: last_error = err time.sleep(0.2) else: raise last_error def test_search(self): results = self.api.search('hu.rycus') self.assertTrue(hasattr(results, 'doc'), msg='Main doc object not found') self.assertGreater(len(results.doc), 0) document = results.doc[0] self.assertTrue(hasattr(document, 'child'), msg='Child object not found') self.assertGreater(len(document.child), 0) for child in document.child: self._verify_item(child, simple=True) def test_details(self): details = self.api.details('hu.rycus.watchface.triangular') self.assertTrue(hasattr(details, 'docV2'), msg='Main docV2 object not found') document = details.docV2 self._verify_item(document, simple=False) def _verify_item(self, item, simple): for expected in ('title', 'creator', 'image', 'details', 'aggregateRating', 'shareUrl'): self.assertTrue( hasattr(item, expected), msg='Result document does not contain the %s field' % expected) if not simple: self.assertTrue( hasattr(item, 'descriptionHtml'), msg='Result document does not contain the descriptionHtml field' ) for image in item.image: for expected in ('imageType', 'imageUrl'): self.assertTrue(hasattr(image, expected), msg='Image does not contain the %s field' % expected) if not simple: for expected in ('dimension', 'positionInSequence'): self.assertTrue(hasattr(image, expected), msg='Image does not contain the %s field' % expected) dimension = image.dimension for expected in ('width', 'height'): self.assertTrue( hasattr(dimension, expected), msg='Image dimension does not contain the %s field' % expected) details = item.details self.assertTrue(hasattr(details, 'appDetails'), msg='Result does not contain the appDetails object') app_details = details.appDetails for expected in ('packageName', 'uploadDate', 'numDownloads', 'versionCode'): self.assertTrue(hasattr(app_details, expected), msg='App details do not contain the %s field' % expected) if not simple: for expected in ('developerName', 'versionString', 'developerWebsite', 'recentChangesHtml'): self.assertTrue(hasattr(app_details, expected), msg='App details do not contain the %s field' % expected) rating = item.aggregateRating for expected in ('starRating', 'ratingsCount', 'commentCount', 'oneStarRatings', 'twoStarRatings', 'threeStarRatings', 'fourStarRatings', 'fiveStarRatings'): self.assertTrue(hasattr(rating, expected), msg='App rating does not contain the %s field' % expected)