Support Direct APK Links (#1292)

This commit is contained in:
Imran Remtulla
2024-01-19 18:54:01 -05:00
parent 56052bfd79
commit dc45334cb9
21 changed files with 165 additions and 18 deletions

View File

@@ -292,6 +292,10 @@
"useVersionCodeAsOSVersion": "Use app versionCode as OS-detected version",
"requestHeader": "Request header",
"useLatestAssetDateAsReleaseDate": "Use latest asset upload as release date",
"defaultPseudoVersioningMethod": "Default Pseudo-Versioning Method",
"partialAPKHash": "Partial APK Hash",
"APKLinkHash": "APK Link Hash",
"directAPKLink": "Direct APK Link",
"removeAppQuestion": {
"one": "Želite li ukloniti aplikaciju?",
"other": "Želite li ukloniti aplikacije?"

View File

@@ -292,6 +292,10 @@
"useVersionCodeAsOSVersion": "Use app versionCode as OS-detected version",
"requestHeader": "Request header",
"useLatestAssetDateAsReleaseDate": "Use latest asset upload as release date",
"defaultPseudoVersioningMethod": "Default Pseudo-Versioning Method",
"partialAPKHash": "Partial APK Hash",
"APKLinkHash": "APK Link Hash",
"directAPKLink": "Direct APK Link",
"removeAppQuestion": {
"one": "Odstranit Apku?",
"other": "Odstranit Apky?"

View File

@@ -294,6 +294,10 @@
"useVersionCodeAsOSVersion": "Verwende die Appversion als erkannte Version vom Betriebssystem",
"requestHeader": "Request Header",
"useLatestAssetDateAsReleaseDate": "Den letzten Asset-Upload als Veröffentlichungsdatum verwenden",
"defaultPseudoVersioningMethod": "Default Pseudo-Versioning Method",
"partialAPKHash": "Partial APK Hash",
"APKLinkHash": "APK Link Hash",
"directAPKLink": "Direct APK Link",
"removeAppQuestion": {
"one": "App entfernen?",
"other": "Apps entfernen?"

View File

@@ -294,6 +294,10 @@
"useVersionCodeAsOSVersion": "Use app versionCode as OS-detected version",
"requestHeader": "Request header",
"useLatestAssetDateAsReleaseDate": "Use latest asset upload as release date",
"defaultPseudoVersioningMethod": "Default Pseudo-Versioning Method",
"partialAPKHash": "Partial APK Hash",
"APKLinkHash": "APK Link Hash",
"directAPKLink": "Direct APK Link",
"removeAppQuestion": {
"one": "Remove App?",
"other": "Remove Apps?"

View File

@@ -292,6 +292,10 @@
"useVersionCodeAsOSVersion": "Use app versionCode as OS-detected version",
"requestHeader": "Request header",
"useLatestAssetDateAsReleaseDate": "Use latest asset upload as release date",
"defaultPseudoVersioningMethod": "Default Pseudo-Versioning Method",
"partialAPKHash": "Partial APK Hash",
"APKLinkHash": "APK Link Hash",
"directAPKLink": "Direct APK Link",
"removeAppQuestion": {
"one": "¿Eliminar Aplicación?",
"other": "¿Eliminar Aplicaciones?"

View File

@@ -292,6 +292,10 @@
"useVersionCodeAsOSVersion": "استفاده کد نسخه برنامه به جای نسخه شناسایی شده توسط سیستم عامل استفاده کنید",
"requestHeader": "درخواست سطر بالایی",
"useLatestAssetDateAsReleaseDate": "Use latest asset upload as release date",
"defaultPseudoVersioningMethod": "Default Pseudo-Versioning Method",
"partialAPKHash": "Partial APK Hash",
"APKLinkHash": "APK Link Hash",
"directAPKLink": "Direct APK Link",
"removeAppQuestion": {
"one": "برنامه حذف شود؟",
"other": "برنامه ها حذف شوند؟"

View File

@@ -292,6 +292,10 @@
"useVersionCodeAsOSVersion": "Use app versionCode as OS-detected version",
"requestHeader": "Request header",
"useLatestAssetDateAsReleaseDate": "Use latest asset upload as release date",
"defaultPseudoVersioningMethod": "Default Pseudo-Versioning Method",
"partialAPKHash": "Partial APK Hash",
"APKLinkHash": "APK Link Hash",
"directAPKLink": "Direct APK Link",
"removeAppQuestion": {
"one": "Supprimer l'application ?",
"other": "Supprimer les applications ?"

View File

@@ -292,6 +292,10 @@
"useVersionCodeAsOSVersion": "Az app versionCode használata a rendszer által észlelt verzióként",
"requestHeader": "Kérelem fejléc",
"useLatestAssetDateAsReleaseDate": "Use latest asset upload as release date",
"defaultPseudoVersioningMethod": "Default Pseudo-Versioning Method",
"partialAPKHash": "Partial APK Hash",
"APKLinkHash": "APK Link Hash",
"directAPKLink": "Direct APK Link",
"removeAppQuestion": {
"one": "Eltávolítja az alkalmazást?",
"other": "Eltávolítja az alkalmazást?"

View File

@@ -292,6 +292,10 @@
"useVersionCodeAsOSVersion": "Use app versionCode as OS-detected version",
"requestHeader": "Request header",
"useLatestAssetDateAsReleaseDate": "Use latest asset upload as release date",
"defaultPseudoVersioningMethod": "Default Pseudo-Versioning Method",
"partialAPKHash": "Partial APK Hash",
"APKLinkHash": "APK Link Hash",
"directAPKLink": "Direct APK Link",
"removeAppQuestion": {
"one": "Rimuovere l'app?",
"other": "Rimuovere le app?"

View File

@@ -294,6 +294,10 @@
"useVersionCodeAsOSVersion": "Use app versionCode as OS-detected version",
"requestHeader": "Request header",
"useLatestAssetDateAsReleaseDate": "Use latest asset upload as release date",
"defaultPseudoVersioningMethod": "Default Pseudo-Versioning Method",
"partialAPKHash": "Partial APK Hash",
"APKLinkHash": "APK Link Hash",
"directAPKLink": "Direct APK Link",
"removeAppQuestion": {
"one": "アプリを削除しますか?",
"other": "アプリを削除しますか?"

View File

@@ -292,6 +292,10 @@
"useVersionCodeAsOSVersion": "Use app versionCode as OS-detected version",
"requestHeader": "Request header",
"useLatestAssetDateAsReleaseDate": "Use latest asset upload as release date",
"defaultPseudoVersioningMethod": "Default Pseudo-Versioning Method",
"partialAPKHash": "Partial APK Hash",
"APKLinkHash": "APK Link Hash",
"directAPKLink": "Direct APK Link",
"removeAppQuestion": {
"one": "App verwijderen?",
"other": "Apps verwijderen?"

View File

@@ -292,6 +292,10 @@
"useVersionCodeAsOSVersion": "Use app versionCode as OS-detected version",
"requestHeader": "Request header",
"useLatestAssetDateAsReleaseDate": "Use latest asset upload as release date",
"defaultPseudoVersioningMethod": "Default Pseudo-Versioning Method",
"partialAPKHash": "Partial APK Hash",
"APKLinkHash": "APK Link Hash",
"directAPKLink": "Direct APK Link",
"removeAppQuestion": {
"one": "Usunąć aplikację?",
"few": "Usunąć aplikacje?",

View File

@@ -292,6 +292,10 @@
"useVersionCodeAsOSVersion": "Use app versionCode as OS-detected version",
"requestHeader": "Request header",
"useLatestAssetDateAsReleaseDate": "Use latest asset upload as release date",
"defaultPseudoVersioningMethod": "Default Pseudo-Versioning Method",
"partialAPKHash": "Partial APK Hash",
"APKLinkHash": "APK Link Hash",
"directAPKLink": "Direct APK Link",
"removeAppQuestion": {
"one": "Remover aplicativo?",
"other": "Remover aplicativos?"

View File

@@ -294,6 +294,10 @@
"useVersionCodeAsOSVersion": "Use app versionCode as OS-detected version",
"requestHeader": "Request header",
"useLatestAssetDateAsReleaseDate": "Use latest asset upload as release date",
"defaultPseudoVersioningMethod": "Default Pseudo-Versioning Method",
"partialAPKHash": "Partial APK Hash",
"APKLinkHash": "APK Link Hash",
"directAPKLink": "Direct APK Link",
"removeAppQuestion": {
"one": "Удалить приложение?",
"other": "Удалить приложения?"

View File

@@ -278,6 +278,10 @@
"useVersionCodeAsOSVersion": "Use app versionCode as OS-detected version",
"requestHeader": "Request header",
"useLatestAssetDateAsReleaseDate": "Use latest asset upload as release date",
"defaultPseudoVersioningMethod": "Default Pseudo-Versioning Method",
"partialAPKHash": "Partial APK Hash",
"APKLinkHash": "APK Link Hash",
"directAPKLink": "Direct APK Link",
"removeAppQuestion": {
"one": "Ta Bort App?",
"other": "Ta Bort Appar?"

View File

@@ -292,6 +292,10 @@
"useVersionCodeAsOSVersion": "Use app versionCode as OS-detected version",
"requestHeader": "Request header",
"useLatestAssetDateAsReleaseDate": "Use latest asset upload as release date",
"defaultPseudoVersioningMethod": "Default Pseudo-Versioning Method",
"partialAPKHash": "Partial APK Hash",
"APKLinkHash": "APK Link Hash",
"directAPKLink": "Direct APK Link",
"removeAppQuestion": {
"one": "Uygulamayı Kaldır?",
"other": "Uygulamaları Kaldır?"

View File

@@ -290,6 +290,10 @@
"root": "Root",
"shizukuBinderNotFound": "Shizuku chưa khởi động",
"useLatestAssetDateAsReleaseDate": "Use latest asset upload as release date",
"defaultPseudoVersioningMethod": "Default Pseudo-Versioning Method",
"partialAPKHash": "Partial APK Hash",
"APKLinkHash": "APK Link Hash",
"directAPKLink": "Direct APK Link",
"removeAppQuestion":{
"one": "Gỡ ứng dụng?",
"other": "Gỡ ứng dụng?"

View File

@@ -294,6 +294,10 @@
"useVersionCodeAsOSVersion": "Use app versionCode as OS-detected version",
"requestHeader": "Request header",
"useLatestAssetDateAsReleaseDate": "Use latest asset upload as release date",
"defaultPseudoVersioningMethod": "Default Pseudo-Versioning Method",
"partialAPKHash": "Partial APK Hash",
"APKLinkHash": "APK Link Hash",
"directAPKLink": "Direct APK Link",
"removeAppQuestion": {
"one": "是否删除应用?",
"other": "是否删除应用?"

View File

@@ -0,0 +1,44 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:obtainium/app_sources/html.dart';
import 'package:obtainium/providers/source_provider.dart';
class DirectAPKLink extends AppSource {
HTML html = HTML();
DirectAPKLink() {
neverAutoSelect = true;
name = tr('directAPKLink');
additionalSourceAppSpecificSettingFormItems = html
.additionalSourceAppSpecificSettingFormItems
.where((element) => element
.where((element) => element.key == 'requestHeader')
.isNotEmpty)
.toList();
excludeCommonSettingKeys = [
'versionExtractionRegEx',
'matchGroupToUse',
'versionDetection',
'useVersionCodeAsOSVersion',
'apkFilterRegEx',
'autoApkFilterByArch'
];
}
@override
Future<APKDetails> getLatestAPKDetails(
String standardUrl,
Map<String, dynamic> additionalSettings,
) async {
var additionalSettingsNew =
getDefaultValuesFromFormItems(html.combinedAppSpecificSettingFormItems);
for (var s in additionalSettings.keys) {
if (additionalSettingsNew.containsKey(s)) {
additionalSettingsNew[s] = additionalSettings[s];
}
}
additionalSettingsNew['defaultPseudoVersioningMethod'] = 'partialAPKHash';
additionalSettingsNew['directAPKLink'] = true;
additionalSettings['versionDetection'] = false;
return html.getLatestAPKDetails(standardUrl, additionalSettingsNew);
}
}

View File

@@ -108,11 +108,7 @@ class HTML extends AppSource {
[
GeneratedFormSwitch('versionExtractWholePage',
label: tr('versionExtractWholePage'))
],
[
GeneratedFormSwitch('supportFixedAPKURL',
defaultValue: true, label: tr('supportFixedAPKURL')),
],
]
];
var commonFormItems = [
[GeneratedFormSwitch('filterByLinkText', label: tr('filterByLinkText'))],
@@ -172,6 +168,16 @@ class HTML extends AppSource {
'User-Agent: Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Mobile Safari/537.36'
}
])
],
[
GeneratedFormDropdown(
'defaultPseudoVersioningMethod',
[
MapEntry('partialAPKHash', tr('partialAPKHash')),
MapEntry('APKLinkHash', tr('APKLinkHash'))
],
label: tr('defaultPseudoVersioningMethod'),
defaultValue: 'partialAPKHash')
]
];
}
@@ -286,17 +292,25 @@ class HTML extends AppSource {
currentUrl = intLinks.last.key;
}
}
var uri = Uri.parse(currentUrl);
Response res = await sourceRequest(currentUrl, additionalSettings);
var links = await grabLinksCommon(res, additionalSettings);
List<MapEntry<String, String>> links = [];
String versionExtractionWholePageString = currentUrl;
if (additionalSettings['directAPKLink'] != true) {
Response res = await sourceRequest(currentUrl, additionalSettings);
versionExtractionWholePageString =
res.body.split('\r\n').join('\n').split('\n').join('\\n');
links = await grabLinksCommon(res, additionalSettings);
if ((additionalSettings['apkFilterRegEx'] as String?)?.isNotEmpty == true) {
var reg = RegExp(additionalSettings['apkFilterRegEx']);
links = links.where((element) => reg.hasMatch(element.key)).toList();
}
if (links.isEmpty) {
throw NoReleasesError();
if ((additionalSettings['apkFilterRegEx'] as String?)?.isNotEmpty ==
true) {
var reg = RegExp(additionalSettings['apkFilterRegEx']);
links = links.where((element) => reg.hasMatch(element.key)).toList();
}
if (links.isEmpty) {
throw NoReleasesError();
}
} else {
links = [MapEntry(currentUrl, currentUrl)];
}
var rel = links.last.key;
String? version;
@@ -304,11 +318,12 @@ class HTML extends AppSource {
additionalSettings['versionExtractionRegEx'] as String?,
additionalSettings['matchGroupToUse'] as String?,
additionalSettings['versionExtractWholePage'] == true
? res.body.split('\r\n').join('\n').split('\n').join('\\n')
? versionExtractionWholePageString
: rel);
version ??= additionalSettings['supportFixedAPKURL'] != true
? rel.hashCode.toString()
: (await checkPartialDownloadHashDynamc(rel)).toString();
version ??=
additionalSettings['defaultPseudoVersioningMethod'] == 'APKLinkHash'
? rel.hashCode.toString()
: (await checkPartialDownloadHashDynamc(rel)).toString();
return APKDetails(version, [rel].map((e) => MapEntry(e, e)).toList(),
AppNames(uri.host, tr('app')));
}

View File

@@ -11,6 +11,7 @@ import 'package:obtainium/app_sources/apkmirror.dart';
import 'package:obtainium/app_sources/apkpure.dart';
import 'package:obtainium/app_sources/aptoide.dart';
import 'package:obtainium/app_sources/codeberg.dart';
import 'package:obtainium/app_sources/directAPKLink.dart';
import 'package:obtainium/app_sources/fdroid.dart';
import 'package:obtainium/app_sources/fdroidrepo.dart';
import 'package:obtainium/app_sources/github.dart';
@@ -112,6 +113,12 @@ appJSONCompatibilityModifiers(Map<String, dynamic> json) {
additionalSettings['versionDetection'] = false;
additionalSettings['releaseDateAsVersion'] = true;
}
// Convert bool style pseudo version method to dropdown style
if (originalAdditionalSettings['supportFixedAPKURL'] == true) {
additionalSettings['defaultPseudoVersioningMethod'] = 'partialAPKHash';
} else if (originalAdditionalSettings['supportFixedAPKURL'] == false) {
additionalSettings['defaultPseudoVersioningMethod'] = 'APKLinkHash';
}
// Ensure additionalSettings are correctly typed
for (var item in formItems) {
if (additionalSettings[item.key] != null) {
@@ -391,6 +398,7 @@ abstract class AppSource {
bool neverAutoSelect = false;
bool showReleaseDateAsVersionToggle = false;
bool versionDetectionDisallowed = false;
List<String> excludeCommonSettingKeys = [];
AppSource() {
name = runtimeType.toString();
@@ -536,6 +544,13 @@ abstract class AppSource {
]);
}
}
additionalAppSpecificSourceAgnosticSettingFormItemsNeverUseDirectly =
additionalAppSpecificSourceAgnosticSettingFormItemsNeverUseDirectly
.map((e) => e
.where((ee) => !excludeCommonSettingKeys.contains(ee.key))
.toList())
.where((e) => e.isNotEmpty)
.toList();
if (versionDetectionDisallowed) {
overrideAdditionalAppSpecificSourceAgnosticSettingSwitch(
'versionDetection',
@@ -715,6 +730,7 @@ class SourceProvider {
WhatsApp(),
TelegramApp(),
NeutronCode(),
DirectAPKLink(),
HTML() // This should ALWAYS be the last option as they are tried in order
];