From a9159fc8a0cea79f8d3d5801f68a13122107d9bb Mon Sep 17 00:00:00 2001 From: Achim Date: Sat, 9 Mar 2024 09:23:48 +0100 Subject: [PATCH 1/4] Remove .apk retrieval from tags-feed So this code does focus on the official Gitlab REST API. With this the retrieval logic changes. --- lib/app_sources/gitlab.dart | 113 ++++++++++++------------------------ 1 file changed, 36 insertions(+), 77 deletions(-) diff --git a/lib/app_sources/gitlab.dart b/lib/app_sources/gitlab.dart index 3e1e701..dac4469 100644 --- a/lib/app_sources/gitlab.dart +++ b/lib/app_sources/gitlab.dart @@ -113,84 +113,43 @@ class GitLab extends AppSource { additionalSettings['fallbackToOlderReleases'] == true; String? PAT = await getPATIfAny(hostChanged ? additionalSettings : {}); Iterable apkDetailsList = []; - if (PAT != null) { - var names = GitHub().getAppNames(standardUrl); - Response res = await sourceRequest( - 'https://${hosts[0]}/api/v4/projects/${names.author}%2F${names.name}/releases?private_token=$PAT', - additionalSettings); - if (res.statusCode != 200) { - throw getObtainiumHttpError(res); - } - var json = jsonDecode(res.body) as List; - apkDetailsList = json.map((e) { - var apkUrlsFromAssets = (e['assets']?['links'] as List? ?? []) - .map((e) { - return (e['direct_asset_url'] ?? e['url'] ?? '') as String; - }) - .where((s) => s.isNotEmpty) - .toList(); - List uploadedAPKsFromDescription = - ((e['description'] ?? '') as String) - .split('](') - .join('\n') - .split('.apk)') - .join('.apk\n') - .split('\n') - .where((s) => s.startsWith('/uploads/') && s.endsWith('apk')) - .map((s) => '$standardUrl$s') - .toList(); - var apkUrlsSet = apkUrlsFromAssets.toSet(); - apkUrlsSet.addAll(uploadedAPKsFromDescription); - var releaseDateString = e['released_at'] ?? e['created_at']; - DateTime? releaseDate = releaseDateString != null - ? DateTime.parse(releaseDateString) - : null; - return APKDetails( - e['tag_name'] ?? e['name'], - getApkUrlsFromUrls(apkUrlsSet.toList()), - GitHub().getAppNames(standardUrl), - releaseDate: releaseDate); - }); - } else { - Response res = await sourceRequest( - '$standardUrl/-/tags?format=atom', additionalSettings); - if (res.statusCode != 200) { - throw getObtainiumHttpError(res); - } - var standardUri = Uri.parse(standardUrl); - var parsedHtml = parse(res.body); - 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 != '') - ]; - 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); - }); + var names = GitHub().getAppNames(standardUrl); + Response res = await sourceRequest( + 'https://${hosts[0]}/api/v4/projects/${names.author}%2F${names.name}/releases?private_token=$PAT', + additionalSettings); + if (res.statusCode != 200) { + throw getObtainiumHttpError(res); } + var json = jsonDecode(res.body) as List; + apkDetailsList = json.map((e) { + var apkUrlsFromAssets = (e['assets']?['links'] as List? ?? []) + .map((e) { + return (e['direct_asset_url'] ?? e['url'] ?? '') as String; + }) + .where((s) => s.isNotEmpty) + .toList(); + List uploadedAPKsFromDescription = + ((e['description'] ?? '') as String) + .split('](') + .join('\n') + .split('.apk)') + .join('.apk\n') + .split('\n') + .where((s) => s.startsWith('/uploads/') && s.endsWith('apk')) + .map((s) => '$standardUrl$s') + .toList(); + var apkUrlsSet = apkUrlsFromAssets.toSet(); + apkUrlsSet.addAll(uploadedAPKsFromDescription); + var releaseDateString = e['released_at'] ?? e['created_at']; + DateTime? releaseDate = releaseDateString != null + ? DateTime.parse(releaseDateString) + : null; + return APKDetails( + e['tag_name'] ?? e['name'], + getApkUrlsFromUrls(apkUrlsSet.toList()), + GitHub().getAppNames(standardUrl), + releaseDate: releaseDate); + }); if (apkDetailsList.isEmpty) { throw NoReleasesError(note: tr('gitlabSourceNote')); } From 3824b386d7a51207fcb68114be85f2698e778d0f Mon Sep 17 00:00:00 2001 From: Achim Date: Sat, 9 Mar 2024 10:11:54 +0100 Subject: [PATCH 2/4] Regroup functions by their intention This may prepare for later refactorings and code simplification --- lib/app_sources/gitlab.dart | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/lib/app_sources/gitlab.dart b/lib/app_sources/gitlab.dart index dac4469..df200f7 100644 --- a/lib/app_sources/gitlab.dart +++ b/lib/app_sources/gitlab.dart @@ -109,17 +109,20 @@ class GitLab extends AppSource { String standardUrl, Map additionalSettings, ) async { - bool fallbackToOlderReleases = - additionalSettings['fallbackToOlderReleases'] == true; - String? PAT = await getPATIfAny(hostChanged ? additionalSettings : {}); - Iterable apkDetailsList = []; + // Prepare request params var names = GitHub().getAppNames(standardUrl); + String? PAT = await getPATIfAny(hostChanged ? additionalSettings : {}); + + // Request data from REST API Response res = await sourceRequest( 'https://${hosts[0]}/api/v4/projects/${names.author}%2F${names.name}/releases?private_token=$PAT', additionalSettings); if (res.statusCode != 200) { throw getObtainiumHttpError(res); } + + // Extract .apk details from received data + Iterable apkDetailsList = []; var json = jsonDecode(res.body) as List; apkDetailsList = json.map((e) { var apkUrlsFromAssets = (e['assets']?['links'] as List? ?? []) @@ -153,6 +156,10 @@ class GitLab extends AppSource { if (apkDetailsList.isEmpty) { throw NoReleasesError(note: tr('gitlabSourceNote')); } + + // Fallback procedure + bool fallbackToOlderReleases = + additionalSettings['fallbackToOlderReleases'] == true; if (fallbackToOlderReleases) { if (additionalSettings['trackOnly'] != true) { apkDetailsList = @@ -162,6 +169,7 @@ class GitLab extends AppSource { throw NoReleasesError(note: tr('gitlabSourceNote')); } } + return apkDetailsList.first; } } From bb1dd4ecfd8a0f7bcc024cb5e049397c1aa2a80b Mon Sep 17 00:00:00 2001 From: Achim Date: Sat, 9 Mar 2024 10:16:54 +0100 Subject: [PATCH 3/4] Inject Private Access Token as optional request param It turned out: If the parameter `private_token` is given but empty, the Gitlab REST API does expect a valid access token otherwise responds with an authorization error --- lib/app_sources/gitlab.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/app_sources/gitlab.dart b/lib/app_sources/gitlab.dart index df200f7..cf33826 100644 --- a/lib/app_sources/gitlab.dart +++ b/lib/app_sources/gitlab.dart @@ -112,10 +112,11 @@ class GitLab extends AppSource { // Prepare request params var names = GitHub().getAppNames(standardUrl); String? PAT = await getPATIfAny(hostChanged ? additionalSettings : {}); + String optionalAuth = (PAT != null) ? 'private_token=$PAT' : ''; // Request data from REST API Response res = await sourceRequest( - 'https://${hosts[0]}/api/v4/projects/${names.author}%2F${names.name}/releases?private_token=$PAT', + 'https://${hosts[0]}/api/v4/projects/${names.author}%2F${names.name}/releases?$optionalAuth', additionalSettings); if (res.statusCode != 200) { throw getObtainiumHttpError(res); From d8cd3b6c9258a17749efcbe14fb352c76f394a2d Mon Sep 17 00:00:00 2001 From: Achim Date: Sat, 9 Mar 2024 10:17:27 +0100 Subject: [PATCH 4/4] Remove unused package import --- lib/app_sources/gitlab.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/app_sources/gitlab.dart b/lib/app_sources/gitlab.dart index cf33826..f3c21ae 100644 --- a/lib/app_sources/gitlab.dart +++ b/lib/app_sources/gitlab.dart @@ -1,7 +1,6 @@ import 'dart:convert'; import 'package:flutter/material.dart'; -import 'package:html/parser.dart'; import 'package:http/http.dart'; import 'package:obtainium/app_sources/github.dart'; import 'package:obtainium/custom_errors.dart';