From e72b33ebf242b7c968d0e561dbbd64f950508cc6 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 23 Apr 2023 01:19:31 -0400 Subject: [PATCH] Added fallback option to GitLab Source (#456) --- lib/app_sources/gitlab.dart | 84 ++++++++++++++++++++++++------------- 1 file changed, 55 insertions(+), 29 deletions(-) diff --git a/lib/app_sources/gitlab.dart b/lib/app_sources/gitlab.dart index 7d813d7..5b8db8c 100644 --- a/lib/app_sources/gitlab.dart +++ b/lib/app_sources/gitlab.dart @@ -3,10 +3,19 @@ import 'package:http/http.dart'; import 'package:obtainium/app_sources/github.dart'; import 'package:obtainium/custom_errors.dart'; import 'package:obtainium/providers/source_provider.dart'; +import 'package:obtainium/components/generated_form.dart'; +import 'package:easy_localization/easy_localization.dart'; class GitLab extends AppSource { GitLab() { host = 'gitlab.com'; + + additionalSourceAppSpecificSettingFormItems = [ + [ + GeneratedFormSwitch('fallbackToOlderReleases', + label: tr('fallbackToOlderReleases'), defaultValue: true) + ] + ]; } @override @@ -28,41 +37,58 @@ class GitLab extends AppSource { String standardUrl, Map additionalSettings, ) async { + bool fallbackToOlderReleases = + additionalSettings['fallbackToOlderReleases'] == true; Response res = await get(Uri.parse('$standardUrl/-/tags?format=atom')); if (res.statusCode == 200) { var standardUri = Uri.parse(standardUrl); var parsedHtml = parse(res.body); - var entry = parsedHtml.querySelector('entry'); - var entryContent = - parse(parseFragment(entry?.querySelector('content')!.innerHtml).text); - var apkUrls = [ - ...getLinksFromParsedHTML( - entryContent, - RegExp( - '^${standardUri.path.replaceAllMapped(RegExp(r'[.*+?^${}()|[\]\\]'), (x) { - return '\\${x[0]}'; - })}/uploads/[^/]+/[^/]+\\.apk\$', - caseSensitive: false), - standardUri.origin), - // GitLab releases may contain links to externally hosted APKs - ...getLinksFromParsedHTML(entryContent, - RegExp('/[^/]+\\.apk\$', caseSensitive: false), '') - .where((element) => Uri.parse(element).host != '') - .toList() - ]; + var apkDetailsList = parsedHtml.querySelectorAll('entry').map((entry) { + var entryContent = parse( + parseFragment(entry.querySelector('content')!.innerHtml).text); + var apkUrls = [ + ...getLinksFromParsedHTML( + entryContent, + RegExp( + '^${standardUri.path.replaceAllMapped(RegExp(r'[.*+?^${}()|[\]\\]'), (x) { + return '\\${x[0]}'; + })}/uploads/[^/]+/[^/]+\\.apk\$', + caseSensitive: false), + standardUri.origin), + // GitLab releases may contain links to externally hosted APKs + ...getLinksFromParsedHTML(entryContent, + RegExp('/[^/]+\\.apk\$', caseSensitive: false), '') + .where((element) => Uri.parse(element).host != '') + .toList() + ]; - var entryId = entry?.querySelector('id')?.innerHtml; - var version = - entryId == null ? null : Uri.parse(entryId).pathSegments.last; - var releaseDateString = entry?.querySelector('updated')?.innerHtml; - DateTime? releaseDate = - releaseDateString != null ? DateTime.parse(releaseDateString) : null; - if (version == null) { - throw NoVersionError(); + var entryId = entry.querySelector('id')?.innerHtml; + var version = + entryId == null ? null : Uri.parse(entryId).pathSegments.last; + var releaseDateString = entry.querySelector('updated')?.innerHtml; + DateTime? releaseDate = releaseDateString != null + ? DateTime.parse(releaseDateString) + : null; + if (version == null) { + throw NoVersionError(); + } + return APKDetails(version, getApkUrlsFromUrls(apkUrls), + GitHub().getAppNames(standardUrl), + releaseDate: releaseDate); + }); + if (apkDetailsList.isEmpty) { + throw NoReleasesError(); } - return APKDetails(version, getApkUrlsFromUrls(apkUrls), - GitHub().getAppNames(standardUrl), - releaseDate: releaseDate); + if (fallbackToOlderReleases) { + if (additionalSettings['trackOnly'] != true) { + apkDetailsList = + apkDetailsList.where((e) => e.apkUrls.isNotEmpty).toList(); + } + if (apkDetailsList.isEmpty) { + throw NoReleasesError(); + } + } + return apkDetailsList.first; } else { throw getObtainiumHttpError(res); }