mirror of
https://github.com/ImranR98/Obtainium.git
synced 2025-07-13 13:26:43 +02:00
Add Huawei AppGallery (#756)
This commit is contained in:
@ -18,6 +18,7 @@ Currently supported App sources:
|
|||||||
- [SourceHut](https://git.sr.ht/)
|
- [SourceHut](https://git.sr.ht/)
|
||||||
- [APKMirror](https://apkmirror.com/) (Track-Only)
|
- [APKMirror](https://apkmirror.com/) (Track-Only)
|
||||||
- [APKPure](https://apkpure.com/)
|
- [APKPure](https://apkpure.com/)
|
||||||
|
- [Huawei AppGallery](https://appgallery.huawei.com/)
|
||||||
- Third Party F-Droid Repos
|
- Third Party F-Droid Repos
|
||||||
- Jenkins Jobs
|
- Jenkins Jobs
|
||||||
- [Steam](https://store.steampowered.com/mobile)
|
- [Steam](https://store.steampowered.com/mobile)
|
||||||
|
90
lib/app_sources/huaweiappgallery.dart
Normal file
90
lib/app_sources/huaweiappgallery.dart
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
|
import 'package:http/http.dart';
|
||||||
|
import 'package:obtainium/custom_errors.dart';
|
||||||
|
import 'package:obtainium/providers/source_provider.dart';
|
||||||
|
|
||||||
|
class HuaweiAppGallery extends AppSource {
|
||||||
|
HuaweiAppGallery() {
|
||||||
|
name = 'Huawei AppGallery';
|
||||||
|
host = 'appgallery.huawei.com';
|
||||||
|
overrideVersionDetectionFormDefault('releaseDateAsVersion', true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String sourceSpecificStandardizeURL(String url) {
|
||||||
|
RegExp standardUrlRegEx = RegExp('^https?://$host/app/[^/]+');
|
||||||
|
RegExpMatch? match = standardUrlRegEx.firstMatch(url.toLowerCase());
|
||||||
|
if (match == null) {
|
||||||
|
throw InvalidURLError(name);
|
||||||
|
}
|
||||||
|
return url.substring(0, match.end);
|
||||||
|
}
|
||||||
|
|
||||||
|
getDlUrl(String standardUrl) =>
|
||||||
|
'https://${host!.replaceAll('appgallery.', 'appgallery.cloud.')}/appdl/${standardUrl.split('/').last}';
|
||||||
|
|
||||||
|
requestAppdlRedirect(String dlUrl) async {
|
||||||
|
Response res = await sourceRequest(dlUrl, followRedirects: false);
|
||||||
|
if (res.statusCode == 200 ||
|
||||||
|
res.statusCode == 302 ||
|
||||||
|
res.statusCode == 304) {
|
||||||
|
return res;
|
||||||
|
} else {
|
||||||
|
throw getObtainiumHttpError(res);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
appIdFromRedirectDlUrl(String redirectDlUrl) {
|
||||||
|
var parts = redirectDlUrl
|
||||||
|
.split('?')[0]
|
||||||
|
.split('/')
|
||||||
|
.last
|
||||||
|
.split('.')
|
||||||
|
.reversed
|
||||||
|
.toList();
|
||||||
|
parts.removeAt(0);
|
||||||
|
parts.removeAt(0);
|
||||||
|
return parts.reversed.join('.');
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<String?> tryInferringAppId(String standardUrl,
|
||||||
|
{Map<String, dynamic> additionalSettings = const {}}) async {
|
||||||
|
String dlUrl = getDlUrl(standardUrl);
|
||||||
|
Response res = await requestAppdlRedirect(dlUrl);
|
||||||
|
return res.headers['location'] != null
|
||||||
|
? appIdFromRedirectDlUrl(res.headers['location']!)
|
||||||
|
: null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<APKDetails> getLatestAPKDetails(
|
||||||
|
String standardUrl,
|
||||||
|
Map<String, dynamic> additionalSettings,
|
||||||
|
) async {
|
||||||
|
String dlUrl = getDlUrl(standardUrl);
|
||||||
|
Response res = await requestAppdlRedirect(dlUrl);
|
||||||
|
if (res.headers['location'] == null) {
|
||||||
|
throw NoReleasesError();
|
||||||
|
}
|
||||||
|
String appId = appIdFromRedirectDlUrl(res.headers['location']!);
|
||||||
|
var relDateStr =
|
||||||
|
res.headers['location']?.split('?')[0].split('.').reversed.toList()[1];
|
||||||
|
var relDateStrAdj = relDateStr?.split('');
|
||||||
|
var tempLen = relDateStrAdj?.length ?? 0;
|
||||||
|
var i = 2;
|
||||||
|
while (i < tempLen) {
|
||||||
|
relDateStrAdj?.insert((i + i ~/ 2 - 1), '-');
|
||||||
|
i += 2;
|
||||||
|
}
|
||||||
|
var relDate = relDateStrAdj == null
|
||||||
|
? null
|
||||||
|
: DateFormat('yy-MM-dd-HH-mm').parse(relDateStrAdj.join(''));
|
||||||
|
if (relDateStr == null) {
|
||||||
|
throw NoVersionError();
|
||||||
|
}
|
||||||
|
return APKDetails(
|
||||||
|
relDateStr, [MapEntry('$appId.apk', dlUrl)], AppNames(name, appId),
|
||||||
|
releaseDate: relDate);
|
||||||
|
}
|
||||||
|
}
|
@ -14,6 +14,7 @@ import 'package:obtainium/app_sources/fdroid.dart';
|
|||||||
import 'package:obtainium/app_sources/fdroidrepo.dart';
|
import 'package:obtainium/app_sources/fdroidrepo.dart';
|
||||||
import 'package:obtainium/app_sources/github.dart';
|
import 'package:obtainium/app_sources/github.dart';
|
||||||
import 'package:obtainium/app_sources/gitlab.dart';
|
import 'package:obtainium/app_sources/gitlab.dart';
|
||||||
|
import 'package:obtainium/app_sources/huaweiappgallery.dart';
|
||||||
import 'package:obtainium/app_sources/izzyondroid.dart';
|
import 'package:obtainium/app_sources/izzyondroid.dart';
|
||||||
import 'package:obtainium/app_sources/html.dart';
|
import 'package:obtainium/app_sources/html.dart';
|
||||||
import 'package:obtainium/app_sources/jenkins.dart';
|
import 'package:obtainium/app_sources/jenkins.dart';
|
||||||
@ -355,10 +356,14 @@ abstract class AppSource {
|
|||||||
|
|
||||||
Map<String, String>? get requestHeaders => null;
|
Map<String, String>? get requestHeaders => null;
|
||||||
|
|
||||||
Future<Response> sourceRequest(String url) async {
|
Future<Response> sourceRequest(String url,
|
||||||
if (requestHeaders != null) {
|
{bool followRedirects = true}) async {
|
||||||
|
if (requestHeaders != null || followRedirects == false) {
|
||||||
var req = Request('GET', Uri.parse(url));
|
var req = Request('GET', Uri.parse(url));
|
||||||
req.headers.addAll(requestHeaders!);
|
req.followRedirects = followRedirects;
|
||||||
|
if (requestHeaders != null) {
|
||||||
|
req.headers.addAll(requestHeaders!);
|
||||||
|
}
|
||||||
return Response.fromStream(await Client().send(req));
|
return Response.fromStream(await Client().send(req));
|
||||||
} else {
|
} else {
|
||||||
return get(Uri.parse(url));
|
return get(Uri.parse(url));
|
||||||
@ -508,6 +513,7 @@ class SourceProvider {
|
|||||||
SourceHut(),
|
SourceHut(),
|
||||||
APKMirror(),
|
APKMirror(),
|
||||||
APKPure(),
|
APKPure(),
|
||||||
|
HuaweiAppGallery(),
|
||||||
// APKCombo(), // Can't get past their scraping blocking yet (get 403 Forbidden)
|
// APKCombo(), // Can't get past their scraping blocking yet (get 403 Forbidden)
|
||||||
Mullvad(),
|
Mullvad(),
|
||||||
Signal(),
|
Signal(),
|
||||||
|
Reference in New Issue
Block a user