Add Support for RuStore as a Source for App Downloads in Obtainium
Describe the Feature I propose adding RuStore as a new source for downloading and updating Android applications through Obtainium. RuStore is a popular Russian app store, and integrating it would benefit users by providing direct access to apps available in this market.
Implementation Reference A method to retrieve app version information and download links via the RuStore API can be found here: RuStore API Implementation. This implementation details how to fetch application details and initiate downloads correctly.
Example RuStore App Link An example of a RuStore app listing is: Telegram on RuStore
Implementation Details
Below is the content from rustore.py, which outlines the method to obtain app details and download APKs from RuStore.
import logging
import os
import requests
logger = logging.getLogger(__name__)
def get_app_info(package_name):
req = requests.get(f'https://backapi.rustore.ru/applicationData/overallInfo/{package_name}')
if req.status_code == 200:
body_info = req.json()['body']
logger.info(f"Rustore - Successfully found app with package name: {package_name},"
f" version:{body_info['versionName']}, company: {body_info['companyName']}")
else:
raise RuntimeError(f'Rustore - Failed to get application info. Request return status code: {req.status_code}')
headers = {
'Content-Type': 'application/json; charset=utf-8'
}
body = {
'appId': body_info['appId'],
'firstInstall': True
}
download_link_resp = requests.post('https://backapi.rustore.ru/applicationData/download-link',
headers=headers, json=body)
if req.status_code == 200:
download_link = download_link_resp.json()['body']['apkUrl']
else:
raise RuntimeError(f'Rustore - Failed to get application download link.'
f' Request return status code: {req.status_code}')
return {
'integration_type': 'rustore',
'download_url': download_link,
'package_name': body_info['packageName'],
'version_name': body_info['versionName'],
'version_code': body_info['versionCode'],
'min_sdk_version': body_info['minSdkVersion'],
'max_sdk_version': body_info['maxSdkVersion'],
'target_sdk_version': body_info['targetSdkVersion'],
'file_size': body_info['fileSize'],
'icon_url': body_info['iconUrl']
}
def rustore_download_app(package_name, download_path):
app_info = get_app_info(package_name)
logger.info('Rustore - Start downloading application')
r = requests.get(app_info['download_url'])
if r.status_code == 401:
raise RuntimeError(f'Rustore - Failed to download application. '
f'Something goes wrong. Request return status code: {r.status_code}')
file_path = f"{download_path}/{app_info['package_name']}-{app_info['version_name']}.apk"
if not os.path.exists(download_path):
os.mkdir(download_path)
logger.info(f'Rustore - Creating directory {download_path} for downloading app from Rustore')
f = open(file_path, 'wb')
for chunk in r.iter_content(chunk_size=512 * 1024):
if chunk:
f.write(chunk)
f.close()
logger.info(f'Rustore - Apk was downloaded from rustore to {file_path}')
return file_path
Additional Context For methods related to other distribution platforms like Huawei AppGallery, AppCenter, rumarket, and Google Play, please refer to the following directory: Distribution Systems Directory
This addition would align with Obtainium's goal of fetching Android app updates directly from their sources, providing users with a broader range of app stores to choose from.
I have a question about the Google Play download at https://github.com/Dynamic-Mobile-Security/mdast-cli/tree/main/mdast_cli/distribution_systems. According to the description, you have to switch off 2FA. As far as I know, this is no longer possible with Google.
This opportunity with RuStore is very necessary
I have only 1 single app available exclusively in RuStore and I use this script to get it.
I've collected info about installation from RuStore in a doc. Not all API is known, but it seems sufficient to implement what's needed by Obtainium.
Added (thanks @PadowYT2): https://github.com/ImranR98/Obtainium/releases/tag/v1.1.41
this implementation has tiny problem that RuStore temporarily banned my home ip for using this, bruh