mirror of
				https://github.com/ImranR98/Obtainium.git
				synced 2025-11-03 23:03:29 +01:00 
			
		
		
		
	Merge pull request #2305 from bernikr/apkpure-api
Rewrite APKPure Source to use the mobile API instead of web scraping
This commit is contained in:
		@@ -318,9 +318,11 @@
 | 
				
			|||||||
    "crowdsourcedConfigsShort": "Crowdsourced App Configurations",
 | 
					    "crowdsourcedConfigsShort": "Crowdsourced App Configurations",
 | 
				
			||||||
    "allowInsecure": "Allow insecure HTTP requests",
 | 
					    "allowInsecure": "Allow insecure HTTP requests",
 | 
				
			||||||
    "stayOneVersionBehind": "Stay one version behind latest",
 | 
					    "stayOneVersionBehind": "Stay one version behind latest",
 | 
				
			||||||
 | 
					    "useFirstApkOfVersion": "Auto-select first of multiple APKs",
 | 
				
			||||||
    "refreshBeforeDownload": "Refresh app details before download",
 | 
					    "refreshBeforeDownload": "Refresh app details before download",
 | 
				
			||||||
    "tencentAppStore": "Tencent App Store",
 | 
					    "tencentAppStore": "Tencent App Store",
 | 
				
			||||||
    "coolApk": "CoolApk",
 | 
					    "coolApk": "CoolApk",
 | 
				
			||||||
 | 
					    "vivoAppStore": "vivo App Store (CN)",
 | 
				
			||||||
    "name": "Name",
 | 
					    "name": "Name",
 | 
				
			||||||
    "smartname": "Name (Smart)",
 | 
					    "smartname": "Name (Smart)",
 | 
				
			||||||
    "sortMethod": "Sort Method",
 | 
					    "sortMethod": "Sort Method",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -318,9 +318,11 @@
 | 
				
			|||||||
    "crowdsourcedConfigsShort": "Configuració de les aplicacions crowdsourcing",
 | 
					    "crowdsourcedConfigsShort": "Configuració de les aplicacions crowdsourcing",
 | 
				
			||||||
    "allowInsecure": "Permet les sol·licituds HTTP insegures",
 | 
					    "allowInsecure": "Permet les sol·licituds HTTP insegures",
 | 
				
			||||||
    "stayOneVersionBehind": "Roman a la versió anterior a l'última",
 | 
					    "stayOneVersionBehind": "Roman a la versió anterior a l'última",
 | 
				
			||||||
 | 
					    "useFirstApkOfVersion": "Auto-select first of multiple APKs",
 | 
				
			||||||
    "refreshBeforeDownload": "Actualitza les dades de l'aplicació abans de descarregar-la",
 | 
					    "refreshBeforeDownload": "Actualitza les dades de l'aplicació abans de descarregar-la",
 | 
				
			||||||
    "tencentAppStore": "Tencent App Store",
 | 
					    "tencentAppStore": "Tencent App Store",
 | 
				
			||||||
    "coolApk": "CoolApk",
 | 
					    "coolApk": "CoolApk",
 | 
				
			||||||
 | 
					    "vivoAppStore": "vivo App Store (CN)",
 | 
				
			||||||
    "name": "Nom",
 | 
					    "name": "Nom",
 | 
				
			||||||
    "smartname": "Nom (smart)",
 | 
					    "smartname": "Nom (smart)",
 | 
				
			||||||
    "sortMethod": "Mètode d'ordenació",
 | 
					    "sortMethod": "Mètode d'ordenació",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -318,9 +318,11 @@
 | 
				
			|||||||
    "crowdsourcedConfigsShort": "Konfigurace aplikací s využitím crowdsourcingu",
 | 
					    "crowdsourcedConfigsShort": "Konfigurace aplikací s využitím crowdsourcingu",
 | 
				
			||||||
    "allowInsecure": "Povolení nezabezpečených požadavků HTTP",
 | 
					    "allowInsecure": "Povolení nezabezpečených požadavků HTTP",
 | 
				
			||||||
    "stayOneVersionBehind": "Zůstaňte o jednu verzi pozadu za nejnovější",
 | 
					    "stayOneVersionBehind": "Zůstaňte o jednu verzi pozadu za nejnovější",
 | 
				
			||||||
 | 
					    "useFirstApkOfVersion": "Auto-select first of multiple APKs",
 | 
				
			||||||
    "refreshBeforeDownload": "Obnovení údajů o aplikaci před stažením",
 | 
					    "refreshBeforeDownload": "Obnovení údajů o aplikaci před stažením",
 | 
				
			||||||
    "tencentAppStore": "Tencent App Store",
 | 
					    "tencentAppStore": "Tencent App Store",
 | 
				
			||||||
    "coolApk": "CoolApk",
 | 
					    "coolApk": "CoolApk",
 | 
				
			||||||
 | 
					    "vivoAppStore": "vivo App Store (CN)",
 | 
				
			||||||
    "name": "Název",
 | 
					    "name": "Název",
 | 
				
			||||||
    "smartname": "Název (Smart)",
 | 
					    "smartname": "Název (Smart)",
 | 
				
			||||||
    "sortMethod": "Metoda třídění",
 | 
					    "sortMethod": "Metoda třídění",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -318,9 +318,11 @@
 | 
				
			|||||||
    "crowdsourcedConfigsShort": "Crowdsourcede app-konfigurationer",
 | 
					    "crowdsourcedConfigsShort": "Crowdsourcede app-konfigurationer",
 | 
				
			||||||
    "allowInsecure": "Tillad usikre HTTP-anmodninger",
 | 
					    "allowInsecure": "Tillad usikre HTTP-anmodninger",
 | 
				
			||||||
    "stayOneVersionBehind": "Forbliv én version bagud den seneste",
 | 
					    "stayOneVersionBehind": "Forbliv én version bagud den seneste",
 | 
				
			||||||
 | 
					    "useFirstApkOfVersion": "Auto-select first of multiple APKs",
 | 
				
			||||||
    "refreshBeforeDownload": "Opdater app-detaljer før download",
 | 
					    "refreshBeforeDownload": "Opdater app-detaljer før download",
 | 
				
			||||||
    "tencentAppStore": "Tencent App Store",
 | 
					    "tencentAppStore": "Tencent App Store",
 | 
				
			||||||
    "coolApk": "CoolApk",
 | 
					    "coolApk": "CoolApk",
 | 
				
			||||||
 | 
					    "vivoAppStore": "vivo App Store (CN)",
 | 
				
			||||||
    "name": "Navn",
 | 
					    "name": "Navn",
 | 
				
			||||||
    "smartname": "Navn (Smart)",
 | 
					    "smartname": "Navn (Smart)",
 | 
				
			||||||
    "sortMethod": "Sorteringsmetode",
 | 
					    "sortMethod": "Sorteringsmetode",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -318,9 +318,11 @@
 | 
				
			|||||||
    "crowdsourcedConfigsShort": "Crowdsourced App-Konfigurationen",
 | 
					    "crowdsourcedConfigsShort": "Crowdsourced App-Konfigurationen",
 | 
				
			||||||
    "allowInsecure": "Unsichere HTTP-Anfragen zulassen",
 | 
					    "allowInsecure": "Unsichere HTTP-Anfragen zulassen",
 | 
				
			||||||
    "stayOneVersionBehind": "Eine Version hinter der neuesten Version bleiben",
 | 
					    "stayOneVersionBehind": "Eine Version hinter der neuesten Version bleiben",
 | 
				
			||||||
 | 
					    "useFirstApkOfVersion": "Auto-select first of multiple APKs",
 | 
				
			||||||
    "refreshBeforeDownload": "App-Details vor dem Download aktualisieren",
 | 
					    "refreshBeforeDownload": "App-Details vor dem Download aktualisieren",
 | 
				
			||||||
    "tencentAppStore": "Tencent App Store",
 | 
					    "tencentAppStore": "Tencent App Store",
 | 
				
			||||||
    "coolApk": "CoolApk",
 | 
					    "coolApk": "CoolApk",
 | 
				
			||||||
 | 
					    "vivoAppStore": "vivo App Store (CN)",
 | 
				
			||||||
    "name": "Name",
 | 
					    "name": "Name",
 | 
				
			||||||
    "smartname": "Name (Smart)",
 | 
					    "smartname": "Name (Smart)",
 | 
				
			||||||
    "sortMethod": "Sortierverfahren",
 | 
					    "sortMethod": "Sortierverfahren",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -318,9 +318,11 @@
 | 
				
			|||||||
    "crowdsourcedConfigsShort": "Crowdsourced App Configurations",
 | 
					    "crowdsourcedConfigsShort": "Crowdsourced App Configurations",
 | 
				
			||||||
    "allowInsecure": "Allow insecure HTTP requests",
 | 
					    "allowInsecure": "Allow insecure HTTP requests",
 | 
				
			||||||
    "stayOneVersionBehind": "Stay one version behind latest",
 | 
					    "stayOneVersionBehind": "Stay one version behind latest",
 | 
				
			||||||
 | 
					    "useFirstApkOfVersion": "Auto-select first of multiple APKs",
 | 
				
			||||||
    "refreshBeforeDownload": "Refresh app details before download",
 | 
					    "refreshBeforeDownload": "Refresh app details before download",
 | 
				
			||||||
    "tencentAppStore": "Tencent App Store",
 | 
					    "tencentAppStore": "Tencent App Store",
 | 
				
			||||||
    "coolApk": "CoolApk",
 | 
					    "coolApk": "CoolApk",
 | 
				
			||||||
 | 
					    "vivoAppStore": "vivo App Store (CN)",
 | 
				
			||||||
    "name": "Name",
 | 
					    "name": "Name",
 | 
				
			||||||
    "smartname": "Name (Smart)",
 | 
					    "smartname": "Name (Smart)",
 | 
				
			||||||
    "sortMethod": "Sort Method",
 | 
					    "sortMethod": "Sort Method",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -318,6 +318,7 @@
 | 
				
			|||||||
    "crowdsourcedConfigsShort": "Crowdsourced app configurations",
 | 
					    "crowdsourcedConfigsShort": "Crowdsourced app configurations",
 | 
				
			||||||
    "allowInsecure": "Allow insecure HTTP requests",
 | 
					    "allowInsecure": "Allow insecure HTTP requests",
 | 
				
			||||||
    "stayOneVersionBehind": "Stay one version behind latest",
 | 
					    "stayOneVersionBehind": "Stay one version behind latest",
 | 
				
			||||||
 | 
					    "useFirstApkOfVersion": "Auto-select first of multiple APKs",
 | 
				
			||||||
    "refreshBeforeDownload": "Refresh app details before download",
 | 
					    "refreshBeforeDownload": "Refresh app details before download",
 | 
				
			||||||
    "tencentAppStore": "Tencent App Store",
 | 
					    "tencentAppStore": "Tencent App Store",
 | 
				
			||||||
    "coolApk": "CoolApk",
 | 
					    "coolApk": "CoolApk",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -318,9 +318,11 @@
 | 
				
			|||||||
    "crowdsourcedConfigsShort": "Configuración de aplicaciones por crowdsourcing",
 | 
					    "crowdsourcedConfigsShort": "Configuración de aplicaciones por crowdsourcing",
 | 
				
			||||||
    "allowInsecure": "Permitir peticiones HTTP inseguras",
 | 
					    "allowInsecure": "Permitir peticiones HTTP inseguras",
 | 
				
			||||||
    "stayOneVersionBehind": "Mantenerse una versión por detrás de la última",
 | 
					    "stayOneVersionBehind": "Mantenerse una versión por detrás de la última",
 | 
				
			||||||
 | 
					    "useFirstApkOfVersion": "Auto-select first of multiple APKs",
 | 
				
			||||||
    "refreshBeforeDownload": "Actualiza los datos de la aplicación antes de descargarla",
 | 
					    "refreshBeforeDownload": "Actualiza los datos de la aplicación antes de descargarla",
 | 
				
			||||||
    "tencentAppStore": "Tencent App Store",
 | 
					    "tencentAppStore": "Tencent App Store",
 | 
				
			||||||
    "coolApk": "CoolApk",
 | 
					    "coolApk": "CoolApk",
 | 
				
			||||||
 | 
					    "vivoAppStore": "vivo App Store (CN)",
 | 
				
			||||||
    "name": "Nombre",
 | 
					    "name": "Nombre",
 | 
				
			||||||
    "smartname": "Nombre (Smart)",
 | 
					    "smartname": "Nombre (Smart)",
 | 
				
			||||||
    "sortMethod": "Método de clasificación",
 | 
					    "sortMethod": "Método de clasificación",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -318,9 +318,11 @@
 | 
				
			|||||||
    "crowdsourcedConfigsShort": "تنظیمات برنامه های مشارکت جمعی",
 | 
					    "crowdsourcedConfigsShort": "تنظیمات برنامه های مشارکت جمعی",
 | 
				
			||||||
    "allowInsecure": "درخواست های HTTP ناامن را مجاز کنید",
 | 
					    "allowInsecure": "درخواست های HTTP ناامن را مجاز کنید",
 | 
				
			||||||
    "stayOneVersionBehind": "یک نسخه از آخرین نسخه پشت سر بگذارید",
 | 
					    "stayOneVersionBehind": "یک نسخه از آخرین نسخه پشت سر بگذارید",
 | 
				
			||||||
 | 
					    "useFirstApkOfVersion": "Auto-select first of multiple APKs",
 | 
				
			||||||
    "refreshBeforeDownload": "قبل از دانلود، جزئیات برنامه را بازخوانی کنید",
 | 
					    "refreshBeforeDownload": "قبل از دانلود، جزئیات برنامه را بازخوانی کنید",
 | 
				
			||||||
    "tencentAppStore": "Tencent App Store",
 | 
					    "tencentAppStore": "Tencent App Store",
 | 
				
			||||||
    "coolApk": "CoolApk",
 | 
					    "coolApk": "CoolApk",
 | 
				
			||||||
 | 
					    "vivoAppStore": "vivo App Store (CN)",
 | 
				
			||||||
    "name": "Name",
 | 
					    "name": "Name",
 | 
				
			||||||
    "smartname": "Name (Smart)",
 | 
					    "smartname": "Name (Smart)",
 | 
				
			||||||
    "sortMethod": "Sort Method",
 | 
					    "sortMethod": "Sort Method",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -318,9 +318,11 @@
 | 
				
			|||||||
    "crowdsourcedConfigsShort": "Applications communautaires",
 | 
					    "crowdsourcedConfigsShort": "Applications communautaires",
 | 
				
			||||||
    "allowInsecure": "Autoriser les requêtes HTTP non sécurisées",
 | 
					    "allowInsecure": "Autoriser les requêtes HTTP non sécurisées",
 | 
				
			||||||
    "stayOneVersionBehind": "Rester une version en arrière de la dernière",
 | 
					    "stayOneVersionBehind": "Rester une version en arrière de la dernière",
 | 
				
			||||||
 | 
					    "useFirstApkOfVersion": "Auto-select first of multiple APKs",
 | 
				
			||||||
    "refreshBeforeDownload": "Actualiser les détails de l'application avant de la télécharger",
 | 
					    "refreshBeforeDownload": "Actualiser les détails de l'application avant de la télécharger",
 | 
				
			||||||
    "tencentAppStore": "Tencent App Store",
 | 
					    "tencentAppStore": "Tencent App Store",
 | 
				
			||||||
    "coolApk": "CoolApk",
 | 
					    "coolApk": "CoolApk",
 | 
				
			||||||
 | 
					    "vivoAppStore": "vivo App Store (CN)",
 | 
				
			||||||
    "name": "Nom",
 | 
					    "name": "Nom",
 | 
				
			||||||
    "smartname": "Nom (Smart)",
 | 
					    "smartname": "Nom (Smart)",
 | 
				
			||||||
    "sortMethod": "Méthode de tri",
 | 
					    "sortMethod": "Méthode de tri",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -318,9 +318,11 @@
 | 
				
			|||||||
    "crowdsourcedConfigsShort": "Alkalmazáslista",
 | 
					    "crowdsourcedConfigsShort": "Alkalmazáslista",
 | 
				
			||||||
    "allowInsecure": "Nem biztonságos HTTP-kérések engedélyezése",
 | 
					    "allowInsecure": "Nem biztonságos HTTP-kérések engedélyezése",
 | 
				
			||||||
    "stayOneVersionBehind": "Maradjon egy verzióval a legújabb mögött",
 | 
					    "stayOneVersionBehind": "Maradjon egy verzióval a legújabb mögött",
 | 
				
			||||||
 | 
					    "useFirstApkOfVersion": "Auto-select first of multiple APKs",
 | 
				
			||||||
    "refreshBeforeDownload": "Az alkalmazás adatainak frissítése a letöltés előtt",
 | 
					    "refreshBeforeDownload": "Az alkalmazás adatainak frissítése a letöltés előtt",
 | 
				
			||||||
    "tencentAppStore": "Tencent Appstore",
 | 
					    "tencentAppStore": "Tencent Appstore",
 | 
				
			||||||
    "coolApk": "CoolApk",
 | 
					    "coolApk": "CoolApk",
 | 
				
			||||||
 | 
					    "vivoAppStore": "vivo App Store (CN)",
 | 
				
			||||||
    "name": "Név",
 | 
					    "name": "Név",
 | 
				
			||||||
    "smartname": "Név (Okos)",
 | 
					    "smartname": "Név (Okos)",
 | 
				
			||||||
    "sortMethod": "Rendezési eljárás",
 | 
					    "sortMethod": "Rendezési eljárás",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -318,9 +318,11 @@
 | 
				
			|||||||
    "crowdsourcedConfigsShort": "Konfigurasi Aplikasi Crowdsourced",
 | 
					    "crowdsourcedConfigsShort": "Konfigurasi Aplikasi Crowdsourced",
 | 
				
			||||||
    "allowInsecure": "Izinkan permintaan HTTP yang tidak aman",
 | 
					    "allowInsecure": "Izinkan permintaan HTTP yang tidak aman",
 | 
				
			||||||
    "stayOneVersionBehind": "Tetap satu versi di belakang versi terbaru",
 | 
					    "stayOneVersionBehind": "Tetap satu versi di belakang versi terbaru",
 | 
				
			||||||
 | 
					    "useFirstApkOfVersion": "Auto-select first of multiple APKs",
 | 
				
			||||||
    "refreshBeforeDownload": "Segarkan detail aplikasi sebelum mengunduh",
 | 
					    "refreshBeforeDownload": "Segarkan detail aplikasi sebelum mengunduh",
 | 
				
			||||||
    "tencentAppStore": "Tencent App Store",
 | 
					    "tencentAppStore": "Tencent App Store",
 | 
				
			||||||
    "coolApk": "CoolApk",
 | 
					    "coolApk": "CoolApk",
 | 
				
			||||||
 | 
					    "vivoAppStore": "vivo App Store (CN)",
 | 
				
			||||||
    "name": "Nama",
 | 
					    "name": "Nama",
 | 
				
			||||||
    "smartname": "Nama (Cerdas)",
 | 
					    "smartname": "Nama (Cerdas)",
 | 
				
			||||||
    "sortMethod": "Metode Penyortiran",
 | 
					    "sortMethod": "Metode Penyortiran",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -318,9 +318,11 @@
 | 
				
			|||||||
    "crowdsourcedConfigsShort": "Configurazioni di app in crowdsourcing",
 | 
					    "crowdsourcedConfigsShort": "Configurazioni di app in crowdsourcing",
 | 
				
			||||||
    "allowInsecure": "Consentire le richieste HTTP non sicure",
 | 
					    "allowInsecure": "Consentire le richieste HTTP non sicure",
 | 
				
			||||||
    "stayOneVersionBehind": "Rimanere una versione indietro rispetto alla più recente",
 | 
					    "stayOneVersionBehind": "Rimanere una versione indietro rispetto alla più recente",
 | 
				
			||||||
 | 
					    "useFirstApkOfVersion": "Auto-select first of multiple APKs",
 | 
				
			||||||
    "refreshBeforeDownload": "Aggiornare i dettagli dell'app prima del download",
 | 
					    "refreshBeforeDownload": "Aggiornare i dettagli dell'app prima del download",
 | 
				
			||||||
    "tencentAppStore": "Tencent App Store",
 | 
					    "tencentAppStore": "Tencent App Store",
 | 
				
			||||||
    "coolApk": "CoolApk",
 | 
					    "coolApk": "CoolApk",
 | 
				
			||||||
 | 
					    "vivoAppStore": "vivo App Store (CN)",
 | 
				
			||||||
    "name": "Nome",
 | 
					    "name": "Nome",
 | 
				
			||||||
    "smartname": "Nome (intelligente)",
 | 
					    "smartname": "Nome (intelligente)",
 | 
				
			||||||
    "sortMethod": "Metodo di ordinamento",
 | 
					    "sortMethod": "Metodo di ordinamento",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -318,9 +318,11 @@
 | 
				
			|||||||
    "crowdsourcedConfigsShort": "クラウドソーシングによるアプリの設定",
 | 
					    "crowdsourcedConfigsShort": "クラウドソーシングによるアプリの設定",
 | 
				
			||||||
    "allowInsecure": "安全でないHTTPリクエストを許可する",
 | 
					    "allowInsecure": "安全でないHTTPリクエストを許可する",
 | 
				
			||||||
    "stayOneVersionBehind": "最新のバージョンから1つ前のものを使用する",
 | 
					    "stayOneVersionBehind": "最新のバージョンから1つ前のものを使用する",
 | 
				
			||||||
 | 
					    "useFirstApkOfVersion": "Auto-select first of multiple APKs",
 | 
				
			||||||
    "refreshBeforeDownload": "ダウンロード前にアプリの詳細を更新する",
 | 
					    "refreshBeforeDownload": "ダウンロード前にアプリの詳細を更新する",
 | 
				
			||||||
    "tencentAppStore": "Tencent App Store",
 | 
					    "tencentAppStore": "Tencent App Store",
 | 
				
			||||||
    "coolApk": "CoolApk",
 | 
					    "coolApk": "CoolApk",
 | 
				
			||||||
 | 
					    "vivoAppStore": "vivo App Store (CN)",
 | 
				
			||||||
    "name": "名称",
 | 
					    "name": "名称",
 | 
				
			||||||
    "smartname": "名前(スマート)",
 | 
					    "smartname": "名前(スマート)",
 | 
				
			||||||
    "sortMethod": "ソート方法",
 | 
					    "sortMethod": "ソート方法",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -318,9 +318,11 @@
 | 
				
			|||||||
    "crowdsourcedConfigsShort": "크라우드소싱 앱 구성",
 | 
					    "crowdsourcedConfigsShort": "크라우드소싱 앱 구성",
 | 
				
			||||||
    "allowInsecure": "안전하지 않은 HTTP 요청 허용",
 | 
					    "allowInsecure": "안전하지 않은 HTTP 요청 허용",
 | 
				
			||||||
    "stayOneVersionBehind": "최신 버전보다 한 버전 뒤에 머무르기",
 | 
					    "stayOneVersionBehind": "최신 버전보다 한 버전 뒤에 머무르기",
 | 
				
			||||||
 | 
					    "useFirstApkOfVersion": "Auto-select first of multiple APKs",
 | 
				
			||||||
    "refreshBeforeDownload": "다운로드 전에 앱 세부 정보 새로 고침",
 | 
					    "refreshBeforeDownload": "다운로드 전에 앱 세부 정보 새로 고침",
 | 
				
			||||||
    "tencentAppStore": "텐센트 앱 스토어",
 | 
					    "tencentAppStore": "텐센트 앱 스토어",
 | 
				
			||||||
    "coolApk": "CoolApk",
 | 
					    "coolApk": "CoolApk",
 | 
				
			||||||
 | 
					    "vivoAppStore": "vivo App Store (CN)",
 | 
				
			||||||
    "name": "이름",
 | 
					    "name": "이름",
 | 
				
			||||||
    "smartname": "이름(스마트)",
 | 
					    "smartname": "이름(스마트)",
 | 
				
			||||||
    "sortMethod": "정렬 방법",
 | 
					    "sortMethod": "정렬 방법",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -318,9 +318,11 @@
 | 
				
			|||||||
    "crowdsourcedConfigsShort": "App-configuraties door menigte",
 | 
					    "crowdsourcedConfigsShort": "App-configuraties door menigte",
 | 
				
			||||||
    "allowInsecure": "Onveilige HTTP-verzoeken toestaan",
 | 
					    "allowInsecure": "Onveilige HTTP-verzoeken toestaan",
 | 
				
			||||||
    "stayOneVersionBehind": "Blijf een versie achter op de nieuwste",
 | 
					    "stayOneVersionBehind": "Blijf een versie achter op de nieuwste",
 | 
				
			||||||
 | 
					    "useFirstApkOfVersion": "Auto-select first of multiple APKs",
 | 
				
			||||||
    "refreshBeforeDownload": "Vernieuw app details voor download",
 | 
					    "refreshBeforeDownload": "Vernieuw app details voor download",
 | 
				
			||||||
    "tencentAppStore": "Tencent App Store",
 | 
					    "tencentAppStore": "Tencent App Store",
 | 
				
			||||||
    "coolApk": "CoolApk",
 | 
					    "coolApk": "CoolApk",
 | 
				
			||||||
 | 
					    "vivoAppStore": "vivo App Store (CN)",
 | 
				
			||||||
    "name": "Naam",
 | 
					    "name": "Naam",
 | 
				
			||||||
    "smartname": "Naam (Slim)",
 | 
					    "smartname": "Naam (Slim)",
 | 
				
			||||||
    "sortMethod": "Sorteermethode",
 | 
					    "sortMethod": "Sorteermethode",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -318,9 +318,11 @@
 | 
				
			|||||||
    "crowdsourcedConfigsShort": "Baza konfiguracji",
 | 
					    "crowdsourcedConfigsShort": "Baza konfiguracji",
 | 
				
			||||||
    "allowInsecure": "Zezwalaj na niezabezpieczone żądania HTTP",
 | 
					    "allowInsecure": "Zezwalaj na niezabezpieczone żądania HTTP",
 | 
				
			||||||
    "stayOneVersionBehind": "Pozostań jedną wersję w tyle za najnowszą",
 | 
					    "stayOneVersionBehind": "Pozostań jedną wersję w tyle za najnowszą",
 | 
				
			||||||
 | 
					    "useFirstApkOfVersion": "Auto-select first of multiple APKs",
 | 
				
			||||||
    "refreshBeforeDownload": "Odśwież szczegóły aplikacji przed pobraniem",
 | 
					    "refreshBeforeDownload": "Odśwież szczegóły aplikacji przed pobraniem",
 | 
				
			||||||
    "tencentAppStore": "Tencent App Store",
 | 
					    "tencentAppStore": "Tencent App Store",
 | 
				
			||||||
    "coolApk": "CoolApk",
 | 
					    "coolApk": "CoolApk",
 | 
				
			||||||
 | 
					    "vivoAppStore": "vivo App Store (CN)",
 | 
				
			||||||
    "name": "Nazwa",
 | 
					    "name": "Nazwa",
 | 
				
			||||||
    "smartname": "Nazwa (Smart)",
 | 
					    "smartname": "Nazwa (Smart)",
 | 
				
			||||||
    "sortMethod": "Metoda sortowania",
 | 
					    "sortMethod": "Metoda sortowania",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -318,9 +318,11 @@
 | 
				
			|||||||
    "crowdsourcedConfigsShort": "Configurações de app da comunidade",
 | 
					    "crowdsourcedConfigsShort": "Configurações de app da comunidade",
 | 
				
			||||||
    "allowInsecure": "Permitir solicitações de HTTP inseguras",
 | 
					    "allowInsecure": "Permitir solicitações de HTTP inseguras",
 | 
				
			||||||
    "stayOneVersionBehind": "Ficar uma versão antes da mais recente",
 | 
					    "stayOneVersionBehind": "Ficar uma versão antes da mais recente",
 | 
				
			||||||
 | 
					    "useFirstApkOfVersion": "Auto-select first of multiple APKs",
 | 
				
			||||||
    "refreshBeforeDownload": "Atualizar detalhes do app antes de baixar",
 | 
					    "refreshBeforeDownload": "Atualizar detalhes do app antes de baixar",
 | 
				
			||||||
    "tencentAppStore": "Loja de Apps da Tencent",
 | 
					    "tencentAppStore": "Loja de Apps da Tencent",
 | 
				
			||||||
    "coolApk": "CoolApk",
 | 
					    "coolApk": "CoolApk",
 | 
				
			||||||
 | 
					    "vivoAppStore": "vivo App Store (CN)",
 | 
				
			||||||
    "name": "Nome",
 | 
					    "name": "Nome",
 | 
				
			||||||
    "smartname": "Nome (inteligente)",
 | 
					    "smartname": "Nome (inteligente)",
 | 
				
			||||||
    "sortMethod": "Método de ordenação",
 | 
					    "sortMethod": "Método de ordenação",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -318,9 +318,11 @@
 | 
				
			|||||||
    "crowdsourcedConfigsShort": "Configurações de aplicações com base em crowdsourcing",
 | 
					    "crowdsourcedConfigsShort": "Configurações de aplicações com base em crowdsourcing",
 | 
				
			||||||
    "allowInsecure": "Permitir pedidos HTTP inseguros",
 | 
					    "allowInsecure": "Permitir pedidos HTTP inseguros",
 | 
				
			||||||
    "stayOneVersionBehind": "Manter-se uma versão atrás da mais recente",
 | 
					    "stayOneVersionBehind": "Manter-se uma versão atrás da mais recente",
 | 
				
			||||||
 | 
					    "useFirstApkOfVersion": "Auto-select first of multiple APKs",
 | 
				
			||||||
    "refreshBeforeDownload": "Atualizar os detalhes da aplicação antes da transferência",
 | 
					    "refreshBeforeDownload": "Atualizar os detalhes da aplicação antes da transferência",
 | 
				
			||||||
    "tencentAppStore": "Tencent App Store",
 | 
					    "tencentAppStore": "Tencent App Store",
 | 
				
			||||||
    "coolApk": "CoolApk",
 | 
					    "coolApk": "CoolApk",
 | 
				
			||||||
 | 
					    "vivoAppStore": "vivo App Store (CN)",
 | 
				
			||||||
    "name": "Nome",
 | 
					    "name": "Nome",
 | 
				
			||||||
    "smartname": "Nome (Smart)",
 | 
					    "smartname": "Nome (Smart)",
 | 
				
			||||||
    "sortMethod": "Método de ordenação",
 | 
					    "sortMethod": "Método de ordenação",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -318,9 +318,11 @@
 | 
				
			|||||||
    "crowdsourcedConfigsShort": "Конфиги приложений с помощью краудсорсинга",
 | 
					    "crowdsourcedConfigsShort": "Конфиги приложений с помощью краудсорсинга",
 | 
				
			||||||
    "allowInsecure": "Разрешить небезопасные HTTP-запросы",
 | 
					    "allowInsecure": "Разрешить небезопасные HTTP-запросы",
 | 
				
			||||||
    "stayOneVersionBehind": "Не отставайте от последней версии",
 | 
					    "stayOneVersionBehind": "Не отставайте от последней версии",
 | 
				
			||||||
 | 
					    "useFirstApkOfVersion": "Auto-select first of multiple APKs",
 | 
				
			||||||
    "refreshBeforeDownload": "Обновляйте информацию о приложении перед загрузкой",
 | 
					    "refreshBeforeDownload": "Обновляйте информацию о приложении перед загрузкой",
 | 
				
			||||||
    "tencentAppStore": "Tencent App Store",
 | 
					    "tencentAppStore": "Tencent App Store",
 | 
				
			||||||
    "coolApk": "CoolApk",
 | 
					    "coolApk": "CoolApk",
 | 
				
			||||||
 | 
					    "vivoAppStore": "vivo App Store (CN)",
 | 
				
			||||||
    "name": "Имя",
 | 
					    "name": "Имя",
 | 
				
			||||||
    "smartname": "Имя (умное)",
 | 
					    "smartname": "Имя (умное)",
 | 
				
			||||||
    "sortMethod": "Метод сортировки",
 | 
					    "sortMethod": "Метод сортировки",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -318,9 +318,11 @@
 | 
				
			|||||||
    "crowdsourcedConfigsShort": "Appkonfigurationer med hjälp av crowdsourcing",
 | 
					    "crowdsourcedConfigsShort": "Appkonfigurationer med hjälp av crowdsourcing",
 | 
				
			||||||
    "allowInsecure": "Tillåt osäkra HTTP-förfrågningar",
 | 
					    "allowInsecure": "Tillåt osäkra HTTP-förfrågningar",
 | 
				
			||||||
    "stayOneVersionBehind": "Håll dig en version bakom den senaste",
 | 
					    "stayOneVersionBehind": "Håll dig en version bakom den senaste",
 | 
				
			||||||
 | 
					    "useFirstApkOfVersion": "Auto-select first of multiple APKs",
 | 
				
			||||||
    "refreshBeforeDownload": "Uppdatera appdetaljerna före nedladdning",
 | 
					    "refreshBeforeDownload": "Uppdatera appdetaljerna före nedladdning",
 | 
				
			||||||
    "tencentAppStore": "Tencent App Store",
 | 
					    "tencentAppStore": "Tencent App Store",
 | 
				
			||||||
    "coolApk": "CoolApk",
 | 
					    "coolApk": "CoolApk",
 | 
				
			||||||
 | 
					    "vivoAppStore": "vivo App Store (CN)",
 | 
				
			||||||
    "name": "Namn",
 | 
					    "name": "Namn",
 | 
				
			||||||
    "smartname": "Namn (Smart)",
 | 
					    "smartname": "Namn (Smart)",
 | 
				
			||||||
    "sortMethod": "Sorteringsmetod",
 | 
					    "sortMethod": "Sorteringsmetod",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -318,9 +318,11 @@
 | 
				
			|||||||
    "crowdsourcedConfigsShort": "Kitle Kaynaklı Uygulama Yapılandırmaları",
 | 
					    "crowdsourcedConfigsShort": "Kitle Kaynaklı Uygulama Yapılandırmaları",
 | 
				
			||||||
    "allowInsecure": "Güvensiz HTTP isteklerine izin ver",
 | 
					    "allowInsecure": "Güvensiz HTTP isteklerine izin ver",
 | 
				
			||||||
    "stayOneVersionBehind": "En son sürümün bir sürüm gerisinde kalın",
 | 
					    "stayOneVersionBehind": "En son sürümün bir sürüm gerisinde kalın",
 | 
				
			||||||
 | 
					    "useFirstApkOfVersion": "Auto-select first of multiple APKs",
 | 
				
			||||||
    "refreshBeforeDownload": "İndirmeden önce uygulama ayrıntılarını yenileyin",
 | 
					    "refreshBeforeDownload": "İndirmeden önce uygulama ayrıntılarını yenileyin",
 | 
				
			||||||
    "tencentAppStore": "Tencent App Store",
 | 
					    "tencentAppStore": "Tencent App Store",
 | 
				
			||||||
    "coolApk": "CoolApk",
 | 
					    "coolApk": "CoolApk",
 | 
				
			||||||
 | 
					    "vivoAppStore": "vivo App Store (CN)",
 | 
				
			||||||
    "name": "İsim",
 | 
					    "name": "İsim",
 | 
				
			||||||
    "smartname": "İsim (Akıllı)",
 | 
					    "smartname": "İsim (Akıllı)",
 | 
				
			||||||
    "sortMethod": "Sıralama Yöntemi",
 | 
					    "sortMethod": "Sıralama Yöntemi",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -318,9 +318,11 @@
 | 
				
			|||||||
    "crowdsourcedConfigsShort": "Налаштування краудсорсингових додатків",
 | 
					    "crowdsourcedConfigsShort": "Налаштування краудсорсингових додатків",
 | 
				
			||||||
    "allowInsecure": "Дозволити незахищені HTTP-запити",
 | 
					    "allowInsecure": "Дозволити незахищені HTTP-запити",
 | 
				
			||||||
    "stayOneVersionBehind": "Залишайтеся на одну версію актуальнішою",
 | 
					    "stayOneVersionBehind": "Залишайтеся на одну версію актуальнішою",
 | 
				
			||||||
 | 
					    "useFirstApkOfVersion": "Auto-select first of multiple APKs",
 | 
				
			||||||
    "refreshBeforeDownload": "Оновіть інформацію про програму перед завантаженням",
 | 
					    "refreshBeforeDownload": "Оновіть інформацію про програму перед завантаженням",
 | 
				
			||||||
    "tencentAppStore": "Tencent App Store",
 | 
					    "tencentAppStore": "Tencent App Store",
 | 
				
			||||||
    "coolApk": "CoolApk",
 | 
					    "coolApk": "CoolApk",
 | 
				
			||||||
 | 
					    "vivoAppStore": "vivo App Store (CN)",
 | 
				
			||||||
    "name": "Ім'я",
 | 
					    "name": "Ім'я",
 | 
				
			||||||
    "smartname": "Ім'я (Smart)",
 | 
					    "smartname": "Ім'я (Smart)",
 | 
				
			||||||
    "sortMethod": "Метод сортування",
 | 
					    "sortMethod": "Метод сортування",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -318,9 +318,11 @@
 | 
				
			|||||||
    "crowdsourcedConfigsShort": "Crowdsourced App Configurations",
 | 
					    "crowdsourcedConfigsShort": "Crowdsourced App Configurations",
 | 
				
			||||||
    "allowInsecure": "Allow insecure HTTP requests",
 | 
					    "allowInsecure": "Allow insecure HTTP requests",
 | 
				
			||||||
    "stayOneVersionBehind": "Stay one version behind latest",
 | 
					    "stayOneVersionBehind": "Stay one version behind latest",
 | 
				
			||||||
 | 
					    "useFirstApkOfVersion": "Auto-select first of multiple APKs",
 | 
				
			||||||
    "refreshBeforeDownload": "Refresh app details before download",
 | 
					    "refreshBeforeDownload": "Refresh app details before download",
 | 
				
			||||||
    "tencentAppStore": "Tencent App Store",
 | 
					    "tencentAppStore": "Tencent App Store",
 | 
				
			||||||
    "coolApk": "CoolApk",
 | 
					    "coolApk": "CoolApk",
 | 
				
			||||||
 | 
					    "vivoAppStore": "vivo App Store (CN)",
 | 
				
			||||||
    "name": "Name",
 | 
					    "name": "Name",
 | 
				
			||||||
    "smartname": "Name (Smart)",
 | 
					    "smartname": "Name (Smart)",
 | 
				
			||||||
    "sortMethod": "Sort Method",
 | 
					    "sortMethod": "Sort Method",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -318,9 +318,11 @@
 | 
				
			|||||||
    "crowdsourcedConfigsShort": "群眾外包的應用程式設定",
 | 
					    "crowdsourcedConfigsShort": "群眾外包的應用程式設定",
 | 
				
			||||||
    "allowInsecure": "允許不安全的 HTTP 請求",
 | 
					    "allowInsecure": "允許不安全的 HTTP 請求",
 | 
				
			||||||
    "stayOneVersionBehind": "保持比最新版本落後一個版本",
 | 
					    "stayOneVersionBehind": "保持比最新版本落後一個版本",
 | 
				
			||||||
 | 
					    "useFirstApkOfVersion": "Auto-select first of multiple APKs",
 | 
				
			||||||
    "refreshBeforeDownload": "下載前刷新應用程式詳細資訊",
 | 
					    "refreshBeforeDownload": "下載前刷新應用程式詳細資訊",
 | 
				
			||||||
    "tencentAppStore": "騰訊應用寶",
 | 
					    "tencentAppStore": "騰訊應用寶",
 | 
				
			||||||
    "coolApk": "CoolApk",
 | 
					    "coolApk": "CoolApk",
 | 
				
			||||||
 | 
					    "vivoAppStore": "vivo App Store (CN)",
 | 
				
			||||||
    "name": "名稱",
 | 
					    "name": "名稱",
 | 
				
			||||||
    "smartname": "名稱(智慧)",
 | 
					    "smartname": "名稱(智慧)",
 | 
				
			||||||
    "sortMethod": "排序方式",
 | 
					    "sortMethod": "排序方式",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -318,6 +318,7 @@
 | 
				
			|||||||
    "crowdsourcedConfigsShort": "众包应用程序配置",
 | 
					    "crowdsourcedConfigsShort": "众包应用程序配置",
 | 
				
			||||||
    "allowInsecure": "允许不安全的 HTTP 请求",
 | 
					    "allowInsecure": "允许不安全的 HTTP 请求",
 | 
				
			||||||
    "stayOneVersionBehind": "比最新版本晚一个版本",
 | 
					    "stayOneVersionBehind": "比最新版本晚一个版本",
 | 
				
			||||||
 | 
					    "useFirstApkOfVersion": "Auto-select first of multiple APKs",
 | 
				
			||||||
    "refreshBeforeDownload": "下载前刷新应用程序详细信息",
 | 
					    "refreshBeforeDownload": "下载前刷新应用程序详细信息",
 | 
				
			||||||
    "tencentAppStore": "腾讯应用宝",
 | 
					    "tencentAppStore": "腾讯应用宝",
 | 
				
			||||||
    "coolApk": "酷安",
 | 
					    "coolApk": "酷安",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,24 +1,18 @@
 | 
				
			|||||||
 | 
					import 'dart:convert';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import 'package:device_info_plus/device_info_plus.dart';
 | 
					import 'package:device_info_plus/device_info_plus.dart';
 | 
				
			||||||
import 'package:easy_localization/easy_localization.dart';
 | 
					import 'package:easy_localization/easy_localization.dart';
 | 
				
			||||||
import 'package:html/parser.dart';
 | 
					 | 
				
			||||||
import 'package:obtainium/app_sources/html.dart';
 | 
					 | 
				
			||||||
import 'package:obtainium/components/generated_form.dart';
 | 
					import 'package:obtainium/components/generated_form.dart';
 | 
				
			||||||
import 'package:obtainium/custom_errors.dart';
 | 
					import 'package:obtainium/custom_errors.dart';
 | 
				
			||||||
import 'package:obtainium/providers/source_provider.dart';
 | 
					import 'package:obtainium/providers/source_provider.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
parseDateTimeMMMddCommayyyy(String? dateString) {
 | 
					extension Unique<E, Id> on List<E> {
 | 
				
			||||||
  DateTime? releaseDate;
 | 
					  List<E> unique([Id Function(E element)? id, bool inplace = true]) {
 | 
				
			||||||
  try {
 | 
					    final ids = Set();
 | 
				
			||||||
    releaseDate = dateString != null
 | 
					    var list = inplace ? this : List<E>.from(this);
 | 
				
			||||||
        ? DateFormat('MMM dd, yyyy').parse(dateString)
 | 
					    list.retainWhere((x) => ids.add(id != null ? id(x) : x as Id));
 | 
				
			||||||
        : null;
 | 
					    return list;
 | 
				
			||||||
    releaseDate = dateString != null && releaseDate == null
 | 
					 | 
				
			||||||
        ? DateFormat('MMMM dd, yyyy').parse(dateString)
 | 
					 | 
				
			||||||
        : releaseDate;
 | 
					 | 
				
			||||||
  } catch (err) {
 | 
					 | 
				
			||||||
    // ignore
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  return releaseDate;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class APKPure extends AppSource {
 | 
					class APKPure extends AppSource {
 | 
				
			||||||
@@ -35,6 +29,10 @@ class APKPure extends AppSource {
 | 
				
			|||||||
      [
 | 
					      [
 | 
				
			||||||
        GeneratedFormSwitch('stayOneVersionBehind',
 | 
					        GeneratedFormSwitch('stayOneVersionBehind',
 | 
				
			||||||
            label: tr('stayOneVersionBehind'), defaultValue: false)
 | 
					            label: tr('stayOneVersionBehind'), defaultValue: false)
 | 
				
			||||||
 | 
					      ],
 | 
				
			||||||
 | 
					      [
 | 
				
			||||||
 | 
					        GeneratedFormSwitch('useFirstApkOfVersion',
 | 
				
			||||||
 | 
					            label: tr('useFirstApkOfVersion'), defaultValue: true)
 | 
				
			||||||
      ]
 | 
					      ]
 | 
				
			||||||
    ];
 | 
					    ];
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@@ -65,109 +63,73 @@ class APKPure extends AppSource {
 | 
				
			|||||||
    return Uri.parse(standardUrl).pathSegments.last;
 | 
					    return Uri.parse(standardUrl).pathSegments.last;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  getDetailsForVersionLink(
 | 
					  getDetailsForVersion(
 | 
				
			||||||
      String standardUrl,
 | 
					      List<Map<String, dynamic>> versionVariants,
 | 
				
			||||||
      String appId,
 | 
					 | 
				
			||||||
      String host,
 | 
					 | 
				
			||||||
      List<String> supportedArchs,
 | 
					      List<String> supportedArchs,
 | 
				
			||||||
      String link,
 | 
					 | 
				
			||||||
      Map<String, dynamic> additionalSettings) async {
 | 
					      Map<String, dynamic> additionalSettings) async {
 | 
				
			||||||
    var res = await sourceRequest(link, additionalSettings);
 | 
					    var apkUrls = versionVariants
 | 
				
			||||||
    if (res.statusCode == 200) {
 | 
					        .map((e) {
 | 
				
			||||||
      var html = parse(res.body);
 | 
					          String appId = e['package_name'];
 | 
				
			||||||
      var apksDiv =
 | 
					          String versionCode = e['version_code'];
 | 
				
			||||||
          html.querySelector('#version-list div div.show-more-content');
 | 
					
 | 
				
			||||||
      DateTime? topReleaseDate;
 | 
					          List<String> architectures = e['native_code']?.cast<String>();
 | 
				
			||||||
      var apkUrls = apksDiv
 | 
					          String architectureString = architectures.join(',');
 | 
				
			||||||
              ?.querySelectorAll('div.group-title')
 | 
					          if (architectures.contains("universal") ||
 | 
				
			||||||
              .map((e) {
 | 
					              architectures.contains("unlimited")) {
 | 
				
			||||||
                String architectureString = e.text.trim();
 | 
					            architectures = [];
 | 
				
			||||||
                if (architectureString.toLowerCase() == 'unlimited' ||
 | 
					          }
 | 
				
			||||||
                    architectureString.toLowerCase() == 'universal') {
 | 
					          if (additionalSettings['autoApkFilterByArch'] == true &&
 | 
				
			||||||
                  architectureString = '';
 | 
					              architectures.isNotEmpty &&
 | 
				
			||||||
                }
 | 
					              architectures.where((a) => supportedArchs.contains(a)).isEmpty) {
 | 
				
			||||||
                List<String> architectures = architectureString
 | 
					            return null;
 | 
				
			||||||
                    .split(',')
 | 
					          }
 | 
				
			||||||
                    .map((e) => e.trim())
 | 
					
 | 
				
			||||||
                    .where((e) => e.isNotEmpty)
 | 
					          String type = e['asset']['type'];
 | 
				
			||||||
                    .toList();
 | 
					          String downloadUri = e['asset']['url'];
 | 
				
			||||||
                // Only take the first APK for each architecture, ignore others for now, for simplicity
 | 
					
 | 
				
			||||||
                // Unclear why there can even be multiple APKs for the same version and arch
 | 
					          return MapEntry(
 | 
				
			||||||
                var apkInfo = e.nextElementSibling?.querySelector('div.info');
 | 
					              '$appId-$versionCode-$architectureString.${type.toLowerCase()}',
 | 
				
			||||||
                String? versionCode = RegExp('[0-9]+')
 | 
					              downloadUri);
 | 
				
			||||||
                    .firstMatch(
 | 
					        })
 | 
				
			||||||
                        apkInfo?.querySelector('div.info-top .code')?.text ??
 | 
					        .nonNulls
 | 
				
			||||||
                            '')
 | 
					        .toList()
 | 
				
			||||||
                    ?.group(0)
 | 
					        .unique((e) => e.key);
 | 
				
			||||||
                    ?.trim();
 | 
					
 | 
				
			||||||
                var types = apkInfo
 | 
					    if (apkUrls.isEmpty) {
 | 
				
			||||||
                        ?.querySelectorAll('div.info-top span.tag')
 | 
					      throw NoAPKError();
 | 
				
			||||||
                        .map((e) => e.text.trim())
 | 
					    }
 | 
				
			||||||
                        .map((t) => t == 'APKs' ? 'APK' : t) ??
 | 
					
 | 
				
			||||||
                    [];
 | 
					    // get version details from first variant
 | 
				
			||||||
                String type = types.isEmpty ? 'APK' : types.first;
 | 
					    var v = versionVariants.first;
 | 
				
			||||||
                String? dateString = apkInfo
 | 
					    String version = v['version_name'];
 | 
				
			||||||
                    ?.querySelector('div.info-bottom span.time')
 | 
					    String author = v['developer'];
 | 
				
			||||||
                    ?.text
 | 
					    String appName = v['title'];
 | 
				
			||||||
                    .trim();
 | 
					    DateTime releaseDate = DateTime.parse(v['update_date']);
 | 
				
			||||||
                DateTime? releaseDate = parseDateTimeMMMddCommayyyy(dateString);
 | 
					    String? changeLog = v['whatsnew'];
 | 
				
			||||||
                if (additionalSettings['autoApkFilterByArch'] == true &&
 | 
					    if (changeLog != null && changeLog.isEmpty) {
 | 
				
			||||||
                    architectures.isNotEmpty &&
 | 
					      changeLog = null;
 | 
				
			||||||
                    architectures
 | 
					    }
 | 
				
			||||||
                        .where((a) => supportedArchs.contains(a))
 | 
					
 | 
				
			||||||
                        .isEmpty) {
 | 
					    if (additionalSettings['useFirstApkOfVersion'] == true) {
 | 
				
			||||||
                  return const MapEntry('', '');
 | 
					      apkUrls = [apkUrls.first];
 | 
				
			||||||
                }
 | 
					    }
 | 
				
			||||||
                topReleaseDate ??=
 | 
					
 | 
				
			||||||
                    releaseDate; // Just use the release date of the first APK in the list as the release date for this version
 | 
					    return APKDetails(version, apkUrls, AppNames(author, appName),
 | 
				
			||||||
                return MapEntry(
 | 
					        releaseDate: releaseDate, changeLog: changeLog);
 | 
				
			||||||
                    '$appId-$versionCode-$architectureString.${type.toLowerCase()}',
 | 
					  }
 | 
				
			||||||
                    'https://d.${hosts.contains(host) ? 'cdnpure.com' : host}/b/$type/$appId?versionCode=$versionCode');
 | 
					
 | 
				
			||||||
              })
 | 
					  @override
 | 
				
			||||||
              .where((e) => e.key.isNotEmpty)
 | 
					  Future<Map<String, String>?> getRequestHeaders(
 | 
				
			||||||
              .toList() ??
 | 
					      Map<String, dynamic> additionalSettings,
 | 
				
			||||||
          [];
 | 
					      {bool forAPKDownload = false}) async {
 | 
				
			||||||
      if (apkUrls.isEmpty) {
 | 
					    if (forAPKDownload) {
 | 
				
			||||||
        var link =
 | 
					      return null;
 | 
				
			||||||
            html.querySelector("a.download-start-btn")?.attributes['href'];
 | 
					 | 
				
			||||||
        RegExp downloadLinkRegEx = RegExp(
 | 
					 | 
				
			||||||
            r'^https:\/\/d\.[^/]+\/b\/([^/]+)\/[^/?]+\?versionCode=([0-9]+)$',
 | 
					 | 
				
			||||||
            caseSensitive: false);
 | 
					 | 
				
			||||||
        RegExpMatch? match = downloadLinkRegEx.firstMatch(link ?? '');
 | 
					 | 
				
			||||||
        if (match == null) {
 | 
					 | 
				
			||||||
          throw NoAPKError();
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        String type = match.group(1)!;
 | 
					 | 
				
			||||||
        String versionCode = match.group(2)!;
 | 
					 | 
				
			||||||
        apkUrls = [
 | 
					 | 
				
			||||||
          MapEntry('$appId-$versionCode-.${type.toLowerCase()}',
 | 
					 | 
				
			||||||
              'https://d.${hosts.contains(host) ? 'cdnpure.com' : host}/b/$type/$appId?versionCode=$versionCode')
 | 
					 | 
				
			||||||
        ];
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      String version = Uri.parse(link).pathSegments.last;
 | 
					 | 
				
			||||||
      String? author;
 | 
					 | 
				
			||||||
      try {
 | 
					 | 
				
			||||||
        author = html
 | 
					 | 
				
			||||||
                .querySelector('span.info-sdk')
 | 
					 | 
				
			||||||
                ?.text
 | 
					 | 
				
			||||||
                .trim()
 | 
					 | 
				
			||||||
                .substring(version.length + 4) ??
 | 
					 | 
				
			||||||
            Uri.parse(standardUrl).pathSegments.reversed.last;
 | 
					 | 
				
			||||||
      } catch (e) {
 | 
					 | 
				
			||||||
        author = html.querySelector('span.info-sdk')?.text.trim() ??
 | 
					 | 
				
			||||||
            Uri.parse(standardUrl).pathSegments.reversed.last;
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      String appName =
 | 
					 | 
				
			||||||
          html.querySelector('h1.info-title')?.text.trim() ?? appId;
 | 
					 | 
				
			||||||
      String? changeLog = html
 | 
					 | 
				
			||||||
          .querySelector('div.module.change-log')
 | 
					 | 
				
			||||||
          ?.innerHtml
 | 
					 | 
				
			||||||
          .trim()
 | 
					 | 
				
			||||||
          .replaceAll("<br>", "  \n");
 | 
					 | 
				
			||||||
      return APKDetails(version, apkUrls, AppNames(author, appName),
 | 
					 | 
				
			||||||
          releaseDate: topReleaseDate, changeLog: changeLog);
 | 
					 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
      throw getObtainiumHttpError(res);
 | 
					      return {
 | 
				
			||||||
 | 
					        "Ual-Access-Businessid": "projecta",
 | 
				
			||||||
 | 
					        "Ual-Access-ProjectA":
 | 
				
			||||||
 | 
					            '{"device_info":{"os_ver":"${((await DeviceInfoPlugin().androidInfo).version.sdkInt)}"}}',
 | 
				
			||||||
 | 
					      };
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -177,41 +139,50 @@ class APKPure extends AppSource {
 | 
				
			|||||||
    Map<String, dynamic> additionalSettings,
 | 
					    Map<String, dynamic> additionalSettings,
 | 
				
			||||||
  ) async {
 | 
					  ) async {
 | 
				
			||||||
    String appId = (await tryInferringAppId(standardUrl))!;
 | 
					    String appId = (await tryInferringAppId(standardUrl))!;
 | 
				
			||||||
    String host = Uri.parse(standardUrl).host;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    var res0 = await sourceRequest('$standardUrl/versions', additionalSettings);
 | 
					    List<String> supportedArchs =
 | 
				
			||||||
    var decodedStandardUrl = standardUrl;
 | 
					        (await DeviceInfoPlugin().androidInfo).supportedAbis;
 | 
				
			||||||
    try {
 | 
					
 | 
				
			||||||
      decodedStandardUrl = Uri.decodeFull(decodedStandardUrl);
 | 
					    // request versions from API
 | 
				
			||||||
    } catch (e) {
 | 
					    var res = await sourceRequest(
 | 
				
			||||||
      //
 | 
					        "https://tapi.pureapk.com/v3/get_app_his_version?package_name=$appId&hl=en",
 | 
				
			||||||
 | 
					        additionalSettings);
 | 
				
			||||||
 | 
					    if (res.statusCode != 200) {
 | 
				
			||||||
 | 
					      throw getObtainiumHttpError(res);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    var versionLinks = await grabLinksCommon(res0, {
 | 
					    List<Map<String, dynamic>> apks =
 | 
				
			||||||
      'skipSort': true,
 | 
					        jsonDecode(res.body)['version_list'].cast<Map<String, dynamic>>();
 | 
				
			||||||
      'customLinkFilterRegex': '$decodedStandardUrl/download/[^/]+\$'
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    var supportedArchs = (await DeviceInfoPlugin().androidInfo).supportedAbis;
 | 
					    // group by version
 | 
				
			||||||
 | 
					    List<List<Map<String, dynamic>>> versions = apks
 | 
				
			||||||
 | 
					        .fold<Map<String, List<Map<String, dynamic>>>>({},
 | 
				
			||||||
 | 
					            (Map<String, List<Map<String, dynamic>>> val,
 | 
				
			||||||
 | 
					                Map<String, dynamic> element) {
 | 
				
			||||||
 | 
					          String v = element['version_name'];
 | 
				
			||||||
 | 
					          if (!val.containsKey(v)) {
 | 
				
			||||||
 | 
					            val[v] = [];
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					          val[v]?.add(element);
 | 
				
			||||||
 | 
					          return val;
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					        .values
 | 
				
			||||||
 | 
					        .toList();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (additionalSettings['autoApkFilterByArch'] != true) {
 | 
					    if (versions.isEmpty) {
 | 
				
			||||||
      // No need to request multiple versions when we're not going to filter them (always pick the top one)
 | 
					 | 
				
			||||||
      versionLinks = versionLinks.sublist(0, 1);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    if (versionLinks.isEmpty) {
 | 
					 | 
				
			||||||
      throw NoReleasesError();
 | 
					      throw NoReleasesError();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (var i = 0; i < versionLinks.length; i++) {
 | 
					    for (var i = 0; i < versions.length; i++) {
 | 
				
			||||||
      var link = versionLinks[i];
 | 
					      var v = versions[i];
 | 
				
			||||||
      try {
 | 
					      try {
 | 
				
			||||||
        if (i == 0 && additionalSettings['stayOneVersionBehind'] == true) {
 | 
					        if (i == 0 && additionalSettings['stayOneVersionBehind'] == true) {
 | 
				
			||||||
          throw NoReleasesError();
 | 
					          throw NoReleasesError();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        return await getDetailsForVersionLink(standardUrl, appId, host,
 | 
					        return await getDetailsForVersion(
 | 
				
			||||||
            supportedArchs, link.key, additionalSettings);
 | 
					            v, supportedArchs, additionalSettings);
 | 
				
			||||||
      } catch (e) {
 | 
					      } catch (e) {
 | 
				
			||||||
        if (additionalSettings['fallbackToOlderReleases'] != true ||
 | 
					        if (additionalSettings['fallbackToOlderReleases'] != true ||
 | 
				
			||||||
            i == versionLinks.length - 1) {
 | 
					            i == versions.length - 1) {
 | 
				
			||||||
          rethrow;
 | 
					          rethrow;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,9 +1,23 @@
 | 
				
			|||||||
import 'package:easy_localization/easy_localization.dart';
 | 
					import 'package:easy_localization/easy_localization.dart';
 | 
				
			||||||
import 'package:html/parser.dart';
 | 
					import 'package:html/parser.dart';
 | 
				
			||||||
import 'package:obtainium/app_sources/apkpure.dart';
 | 
					 | 
				
			||||||
import 'package:obtainium/custom_errors.dart';
 | 
					import 'package:obtainium/custom_errors.dart';
 | 
				
			||||||
import 'package:obtainium/providers/source_provider.dart';
 | 
					import 'package:obtainium/providers/source_provider.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					parseDateTimeMMMddCommayyyy(String? dateString) {
 | 
				
			||||||
 | 
					  DateTime? releaseDate;
 | 
				
			||||||
 | 
					  try {
 | 
				
			||||||
 | 
					    releaseDate = dateString != null
 | 
				
			||||||
 | 
					        ? DateFormat('MMM dd, yyyy').parse(dateString)
 | 
				
			||||||
 | 
					        : null;
 | 
				
			||||||
 | 
					    releaseDate = dateString != null && releaseDate == null
 | 
				
			||||||
 | 
					        ? DateFormat('MMMM dd, yyyy').parse(dateString)
 | 
				
			||||||
 | 
					        : releaseDate;
 | 
				
			||||||
 | 
					  } catch (err) {
 | 
				
			||||||
 | 
					    // ignore
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  return releaseDate;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Uptodown extends AppSource {
 | 
					class Uptodown extends AppSource {
 | 
				
			||||||
  Uptodown() {
 | 
					  Uptodown() {
 | 
				
			||||||
    hosts = ['uptodown.com'];
 | 
					    hosts = ['uptodown.com'];
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user