mirror of
				https://github.com/ImranR98/Obtainium.git
				synced 2025-10-31 13:33:28 +01:00 
			
		
		
		
	Compare commits
	
		
			1 Commits
		
	
	
		
			v1.1.47
			...
			experiment
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | ab43856b90 | 
| @@ -45,7 +45,7 @@ class APKCombo extends AppSource { | |||||||
|     if (res.statusCode != 200) { |     if (res.statusCode != 200) { | ||||||
|       throw getObtainiumHttpError(res); |       throw getObtainiumHttpError(res); | ||||||
|     } |     } | ||||||
|     var html = parse(res.body); |     var html = parse(res.data); | ||||||
|     return html |     return html | ||||||
|         .querySelectorAll('#variants-tab > div > ul > li') |         .querySelectorAll('#variants-tab > div > ul > li') | ||||||
|         .map((e) { |         .map((e) { | ||||||
| @@ -96,7 +96,7 @@ class APKCombo extends AppSource { | |||||||
|     if (preres.statusCode != 200) { |     if (preres.statusCode != 200) { | ||||||
|       throw getObtainiumHttpError(preres); |       throw getObtainiumHttpError(preres); | ||||||
|     } |     } | ||||||
|     var res = parse(preres.body); |     var res = parse(preres.data); | ||||||
|     String? version = res.querySelector('div.version')?.text.trim(); |     String? version = res.querySelector('div.version')?.text.trim(); | ||||||
|     if (version == null) { |     if (version == null) { | ||||||
|       throw NoVersionError(); |       throw NoVersionError(); | ||||||
|   | |||||||
| @@ -1,8 +1,8 @@ | |||||||
| import 'dart:io'; | import 'dart:io'; | ||||||
|  |  | ||||||
|  | import 'package:dio/dio.dart'; | ||||||
| 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:http/http.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'; | ||||||
| @@ -62,7 +62,7 @@ class APKMirror extends AppSource { | |||||||
|             : null; |             : null; | ||||||
|     Response res = await sourceRequest('$standardUrl/feed', additionalSettings); |     Response res = await sourceRequest('$standardUrl/feed', additionalSettings); | ||||||
|     if (res.statusCode == 200) { |     if (res.statusCode == 200) { | ||||||
|       var items = parse(res.body).querySelectorAll('item'); |       var items = parse(res.data).querySelectorAll('item'); | ||||||
|       dynamic targetRelease; |       dynamic targetRelease; | ||||||
|       for (int i = 0; i < items.length; i++) { |       for (int i = 0; i < items.length; i++) { | ||||||
|         if (!fallbackToOlderReleases && i > 0) break; |         if (!fallbackToOlderReleases && i > 0) break; | ||||||
|   | |||||||
| @@ -61,8 +61,8 @@ class APKPure extends AppSource { | |||||||
|     var res = await sourceRequest('$standardUrl/download', additionalSettings); |     var res = await sourceRequest('$standardUrl/download', additionalSettings); | ||||||
|     var resChangelog = await sourceRequest(standardUrl, additionalSettings); |     var resChangelog = await sourceRequest(standardUrl, additionalSettings); | ||||||
|     if (res.statusCode == 200 && resChangelog.statusCode == 200) { |     if (res.statusCode == 200 && resChangelog.statusCode == 200) { | ||||||
|       var html = parse(res.body); |       var html = parse(res.data); | ||||||
|       var htmlChangelog = parse(resChangelog.body); |       var htmlChangelog = parse(resChangelog.data); | ||||||
|       String? version = html.querySelector('span.info-sdk span')?.text.trim(); |       String? version = html.querySelector('span.info-sdk span')?.text.trim(); | ||||||
|       if (version == null) { |       if (version == null) { | ||||||
|         throw NoVersionError(); |         throw NoVersionError(); | ||||||
|   | |||||||
| @@ -38,10 +38,10 @@ class Aptoide extends AppSource { | |||||||
|     if (res.statusCode != 200) { |     if (res.statusCode != 200) { | ||||||
|       throw getObtainiumHttpError(res); |       throw getObtainiumHttpError(res); | ||||||
|     } |     } | ||||||
|     var idMatch = RegExp('"app":{"id":[0-9]+').firstMatch(res.body); |     var idMatch = RegExp('"app":{"id":[0-9]+').firstMatch(res.data); | ||||||
|     String? id; |     String? id; | ||||||
|     if (idMatch != null) { |     if (idMatch != null) { | ||||||
|       id = res.body.substring(idMatch.start + 12, idMatch.end); |       id = res.data.substring(idMatch.start + 12, idMatch.end); | ||||||
|     } else { |     } else { | ||||||
|       throw NoReleasesError(); |       throw NoReleasesError(); | ||||||
|     } |     } | ||||||
| @@ -50,7 +50,7 @@ class Aptoide extends AppSource { | |||||||
|     if (res2.statusCode != 200) { |     if (res2.statusCode != 200) { | ||||||
|       throw getObtainiumHttpError(res); |       throw getObtainiumHttpError(res); | ||||||
|     } |     } | ||||||
|     return jsonDecode(res2.body)?['nodes']?['meta']?['data']; |     return jsonDecode(res2.data)?['nodes']?['meta']?['data']; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   @override |   @override | ||||||
|   | |||||||
| @@ -1,8 +1,8 @@ | |||||||
| import 'dart:convert'; | import 'dart:convert'; | ||||||
|  |  | ||||||
|  | import 'package:dio/dio.dart'; | ||||||
| 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:http/http.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/components/generated_form.dart'; | import 'package:obtainium/components/generated_form.dart'; | ||||||
| @@ -82,7 +82,7 @@ class FDroid extends AppSource { | |||||||
|         var res = await sourceRequest( |         var res = await sourceRequest( | ||||||
|             'https://gitlab.com/fdroid/fdroiddata/-/raw/master/metadata/$appId.yml', |             'https://gitlab.com/fdroid/fdroiddata/-/raw/master/metadata/$appId.yml', | ||||||
|             additionalSettings); |             additionalSettings); | ||||||
|         var lines = res.body.split('\n'); |         var lines = res.data.split('\n'); | ||||||
|         var authorLines = lines.where((l) => l.startsWith('AuthorName: ')); |         var authorLines = lines.where((l) => l.startsWith('AuthorName: ')); | ||||||
|         if (authorLines.isNotEmpty) { |         if (authorLines.isNotEmpty) { | ||||||
|           details.names.author = |           details.names.author = | ||||||
| @@ -112,7 +112,7 @@ class FDroid extends AppSource { | |||||||
|             details.changeLog = (await sourceRequest( |             details.changeLog = (await sourceRequest( | ||||||
|                     details.changeLog!.replaceFirst('/blob/', '/raw/'), |                     details.changeLog!.replaceFirst('/blob/', '/raw/'), | ||||||
|                     additionalSettings)) |                     additionalSettings)) | ||||||
|                 .body; |                 .data; | ||||||
|           } |           } | ||||||
|         } |         } | ||||||
|       } catch (e) { |       } catch (e) { | ||||||
| @@ -132,7 +132,7 @@ class FDroid extends AppSource { | |||||||
|         'https://search.${hosts[0]}/?q=${Uri.encodeQueryComponent(query)}', {}); |         'https://search.${hosts[0]}/?q=${Uri.encodeQueryComponent(query)}', {}); | ||||||
|     if (res.statusCode == 200) { |     if (res.statusCode == 200) { | ||||||
|       Map<String, List<String>> urlsWithDescriptions = {}; |       Map<String, List<String>> urlsWithDescriptions = {}; | ||||||
|       parse(res.body).querySelectorAll('.package-header').forEach((e) { |       parse(res.data).querySelectorAll('.package-header').forEach((e) { | ||||||
|         String? url = e.attributes['href']; |         String? url = e.attributes['href']; | ||||||
|         if (url != null) { |         if (url != null) { | ||||||
|           try { |           try { | ||||||
| @@ -172,7 +172,7 @@ class FDroid extends AppSource { | |||||||
|             ? additionalSettings['apkFilterRegEx'] |             ? additionalSettings['apkFilterRegEx'] | ||||||
|             : null; |             : null; | ||||||
|     if (res.statusCode == 200) { |     if (res.statusCode == 200) { | ||||||
|       var response = jsonDecode(res.body); |       var response = jsonDecode(res.data); | ||||||
|       List<dynamic> releases = response['packages'] ?? []; |       List<dynamic> releases = response['packages'] ?? []; | ||||||
|       if (apkFilterRegEx != null) { |       if (apkFilterRegEx != null) { | ||||||
|         releases = releases.where((rel) { |         releases = releases.where((rel) { | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
|  | import 'package:dio/dio.dart'; | ||||||
| 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:http/http.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'; | ||||||
| @@ -61,9 +61,10 @@ class FDroidRepo extends AppSource { | |||||||
|       throw NoReleasesError(); |       throw NoReleasesError(); | ||||||
|     } |     } | ||||||
|     url = removeQueryParamsFromUrl(standardizeUrl(url)); |     url = removeQueryParamsFromUrl(standardizeUrl(url)); | ||||||
|     var res = await sourceRequestWithURLVariants(url, {}); |     var ress = await sourceRequestWithURLVariants(url, {}); | ||||||
|  |     var res = ress.value; | ||||||
|     if (res.statusCode == 200) { |     if (res.statusCode == 200) { | ||||||
|       var body = parse(res.body); |       var body = parse(res.data); | ||||||
|       Map<String, List<String>> results = {}; |       Map<String, List<String>> results = {}; | ||||||
|       body.querySelectorAll('application').toList().forEach((app) { |       body.querySelectorAll('application').toList().forEach((app) { | ||||||
|         String appId = app.attributes['id']!; |         String appId = app.attributes['id']!; | ||||||
| @@ -74,7 +75,7 @@ class FDroidRepo extends AppSource { | |||||||
|             appName.contains(query) || |             appName.contains(query) || | ||||||
|             appDesc.contains(query)) { |             appDesc.contains(query)) { | ||||||
|           results[ |           results[ | ||||||
|               '${res.request!.url.toString().split('/').reversed.toList().sublist(1).reversed.join('/')}?appId=$appId'] = [ |               '${ress.value.toString().split('/').reversed.toList().sublist(1).reversed.join('/')}?appId=$appId'] = [ | ||||||
|             appName, |             appName, | ||||||
|             appDesc |             appDesc | ||||||
|           ]; |           ]; | ||||||
| @@ -107,24 +108,24 @@ class FDroidRepo extends AppSource { | |||||||
|     return app; |     return app; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   Future<Response> sourceRequestWithURLVariants( |   Future<MapEntry<String, Response>> sourceRequestWithURLVariants( | ||||||
|     String url, |     String url, | ||||||
|     Map<String, dynamic> additionalSettings, |     Map<String, dynamic> additionalSettings, | ||||||
|   ) async { |   ) async { | ||||||
|     var res = await sourceRequest( |     var finalUrl = '$url${url.endsWith('/index.xml') ? '' : '/index.xml'}'; | ||||||
|         '$url${url.endsWith('/index.xml') ? '' : '/index.xml'}', |     var res = await sourceRequest(finalUrl, additionalSettings); | ||||||
|         additionalSettings); |  | ||||||
|     if (res.statusCode != 200) { |     if (res.statusCode != 200) { | ||||||
|       var base = url.endsWith('/index.xml') |       var base = url.endsWith('/index.xml') | ||||||
|           ? url.split('/').reversed.toList().sublist(1).reversed.join('/') |           ? url.split('/').reversed.toList().sublist(1).reversed.join('/') | ||||||
|           : url; |           : url; | ||||||
|       res = await sourceRequest('$base/repo/index.xml', additionalSettings); |       finalUrl = '$base/repo/index.xml'; | ||||||
|  |       res = await sourceRequest(finalUrl, additionalSettings); | ||||||
|       if (res.statusCode != 200) { |       if (res.statusCode != 200) { | ||||||
|         res = await sourceRequest( |         finalUrl = '$base/fdroid/repo/index.xml'; | ||||||
|             '$base/fdroid/repo/index.xml', additionalSettings); |         res = await sourceRequest(finalUrl, additionalSettings); | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|     return res; |     return MapEntry(finalUrl, res); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   @override |   @override | ||||||
| @@ -142,10 +143,11 @@ class FDroidRepo extends AppSource { | |||||||
|     if (appIdOrName == null) { |     if (appIdOrName == null) { | ||||||
|       throw NoReleasesError(); |       throw NoReleasesError(); | ||||||
|     } |     } | ||||||
|     var res = |     var ress = | ||||||
|         await sourceRequestWithURLVariants(standardUrl, additionalSettings); |         await sourceRequestWithURLVariants(standardUrl, additionalSettings); | ||||||
|  |     var res = ress.value; | ||||||
|     if (res.statusCode == 200) { |     if (res.statusCode == 200) { | ||||||
|       var body = parse(res.body); |       var body = parse(res.data); | ||||||
|       var foundApps = body.querySelectorAll('application').where((element) { |       var foundApps = body.querySelectorAll('application').where((element) { | ||||||
|         return element.attributes['id'] == appIdOrName; |         return element.attributes['id'] == appIdOrName; | ||||||
|       }).toList(); |       }).toList(); | ||||||
| @@ -193,7 +195,7 @@ class FDroidRepo extends AppSource { | |||||||
|       } |       } | ||||||
|       List<String> apkUrls = latestVersionReleases |       List<String> apkUrls = latestVersionReleases | ||||||
|           .map((e) => |           .map((e) => | ||||||
|               '${res.request!.url.toString().split('/').reversed.toList().sublist(1).reversed.join('/')}/${e.querySelector('apkname')!.innerHtml}') |               '${ress.value.toString().split('/').reversed.toList().sublist(1).reversed.join('/')}/${e.querySelector('apkname')!.innerHtml}') | ||||||
|           .toList(); |           .toList(); | ||||||
|       return APKDetails(latestVersion, getApkUrlsFromUrls(apkUrls), |       return APKDetails(latestVersion, getApkUrlsFromUrls(apkUrls), | ||||||
|           AppNames(authorName, appName), |           AppNames(authorName, appName), | ||||||
|   | |||||||
| @@ -1,8 +1,8 @@ | |||||||
| import 'dart:convert'; | import 'dart:convert'; | ||||||
| import 'dart:io'; | import 'dart:io'; | ||||||
|  | import 'package:dio/dio.dart'; | ||||||
| import 'package:easy_localization/easy_localization.dart'; | import 'package:easy_localization/easy_localization.dart'; | ||||||
| import 'package:flutter/material.dart'; | import 'package:flutter/material.dart'; | ||||||
| import 'package:http/http.dart'; |  | ||||||
| import 'package:obtainium/app_sources/html.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'; | ||||||
| @@ -112,12 +112,12 @@ class GitHub extends AppSource { | |||||||
|     ]; |     ]; | ||||||
|     for (var path in possibleBuildGradleLocations) { |     for (var path in possibleBuildGradleLocations) { | ||||||
|       try { |       try { | ||||||
|         var res = await sourceRequest( |         var finalUrl = | ||||||
|             '${await convertStandardUrlToAPIUrl(standardUrl, additionalSettings)}/contents/$path', |             '${await convertStandardUrlToAPIUrl(standardUrl, additionalSettings)}/contents/$path'; | ||||||
|             additionalSettings); |         var res = await sourceRequest(finalUrl, additionalSettings); | ||||||
|         if (res.statusCode == 200) { |         if (res.statusCode == 200) { | ||||||
|           try { |           try { | ||||||
|             var body = jsonDecode(res.body); |             var body = jsonDecode(res.data); | ||||||
|             var trimmedLines = utf8 |             var trimmedLines = utf8 | ||||||
|                 .decode(base64 |                 .decode(base64 | ||||||
|                     .decode(body['content'].toString().split('\n').join(''))) |                     .decode(body['content'].toString().split('\n').join(''))) | ||||||
| @@ -143,7 +143,7 @@ class GitHub extends AppSource { | |||||||
|             } |             } | ||||||
|           } catch (err) { |           } catch (err) { | ||||||
|             LogsProvider().add( |             LogsProvider().add( | ||||||
|                 'Error parsing build.gradle from ${res.request!.url.toString()}: ${err.toString()}'); |                 'Error parsing build.gradle from $finalUrl: ${err.toString()}'); | ||||||
|           } |           } | ||||||
|         } |         } | ||||||
|       } catch (err) { |       } catch (err) { | ||||||
| @@ -256,11 +256,11 @@ class GitHub extends AppSource { | |||||||
|         } |         } | ||||||
|         throw getObtainiumHttpError(res); |         throw getObtainiumHttpError(res); | ||||||
|       } |       } | ||||||
|       latestRelease = jsonDecode(res.body); |       latestRelease = jsonDecode(res.data); | ||||||
|     } |     } | ||||||
|     Response res = await sourceRequest(requestUrl, additionalSettings); |     Response res = await sourceRequest(requestUrl, additionalSettings); | ||||||
|     if (res.statusCode == 200) { |     if (res.statusCode == 200) { | ||||||
|       var releases = jsonDecode(res.body) as List<dynamic>; |       var releases = jsonDecode(res.data) as List<dynamic>; | ||||||
|       if (latestRelease != null) { |       if (latestRelease != null) { | ||||||
|         var latestTag = latestRelease['tag_name'] ?? latestRelease['name']; |         var latestTag = latestRelease['tag_name'] ?? latestRelease['name']; | ||||||
|         if (releases |         if (releases | ||||||
| @@ -466,7 +466,7 @@ class GitHub extends AppSource { | |||||||
|           ? int.parse(querySettings['minStarCount']) |           ? int.parse(querySettings['minStarCount']) | ||||||
|           : 0; |           : 0; | ||||||
|       Map<String, List<String>> urlsWithDescriptions = {}; |       Map<String, List<String>> urlsWithDescriptions = {}; | ||||||
|       for (var e in (jsonDecode(res.body)[rootProp] as List<dynamic>)) { |       for (var e in (jsonDecode(res.data)[rootProp] as List<dynamic>)) { | ||||||
|         if ((e['stargazers_count'] ?? e['stars_count'] ?? 0) >= minStarCount) { |         if ((e['stargazers_count'] ?? e['stars_count'] ?? 0) >= minStarCount) { | ||||||
|           urlsWithDescriptions.addAll({ |           urlsWithDescriptions.addAll({ | ||||||
|             e['html_url'] as String: [ |             e['html_url'] as String: [ | ||||||
| @@ -500,11 +500,13 @@ class GitHub extends AppSource { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   rateLimitErrorCheck(Response res) { |   rateLimitErrorCheck(Response res) { | ||||||
|     if (res.headers['x-ratelimit-remaining'] == '0') { |     String? rateLimitHeader; | ||||||
|  |     if (res.headers.map['x-ratelimit-remaining']?.isNotEmpty == true) { | ||||||
|  |       rateLimitHeader = res.headers.map['x-ratelimit-remaining']![0]; | ||||||
|  |     } | ||||||
|  |     if (rateLimitHeader == '0') { | ||||||
|       throw RateLimitError( |       throw RateLimitError( | ||||||
|           (int.parse(res.headers['x-ratelimit-reset'] ?? '1800000000') / |           (int.parse(rateLimitHeader ?? '1800000000') / 60000000).round()); | ||||||
|                   60000000) |  | ||||||
|               .round()); |  | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -1,8 +1,8 @@ | |||||||
| import 'dart:convert'; | import 'dart:convert'; | ||||||
| import 'dart:io'; | import 'dart:io'; | ||||||
|  |  | ||||||
|  | import 'package:dio/dio.dart'; | ||||||
| import 'package:flutter/material.dart'; | import 'package:flutter/material.dart'; | ||||||
| import 'package:http/http.dart'; |  | ||||||
| import 'package:obtainium/app_sources/github.dart'; | import 'package:obtainium/app_sources/github.dart'; | ||||||
| import 'package:obtainium/custom_errors.dart'; | import 'package:obtainium/custom_errors.dart'; | ||||||
| import 'package:obtainium/providers/settings_provider.dart'; | import 'package:obtainium/providers/settings_provider.dart'; | ||||||
| @@ -81,7 +81,7 @@ class GitLab extends AppSource { | |||||||
|     if (res.statusCode != 200) { |     if (res.statusCode != 200) { | ||||||
|       throw getObtainiumHttpError(res); |       throw getObtainiumHttpError(res); | ||||||
|     } |     } | ||||||
|     var json = jsonDecode(res.body) as List<dynamic>; |     var json = jsonDecode(res.data) as List<dynamic>; | ||||||
|     Map<String, List<String>> results = {}; |     Map<String, List<String>> results = {}; | ||||||
|     for (var element in json) { |     for (var element in json) { | ||||||
|       results['https://${hosts[0]}/${element['path_with_namespace']}'] = [ |       results['https://${hosts[0]}/${element['path_with_namespace']}'] = [ | ||||||
| @@ -131,7 +131,7 @@ class GitLab extends AppSource { | |||||||
|  |  | ||||||
|     // Extract .apk details from received data |     // Extract .apk details from received data | ||||||
|     Iterable<APKDetails> apkDetailsList = []; |     Iterable<APKDetails> apkDetailsList = []; | ||||||
|     var json = jsonDecode(res.body) as List<dynamic>; |     var json = jsonDecode(res.data) as List<dynamic>; | ||||||
|     apkDetailsList = json.map((e) { |     apkDetailsList = json.map((e) { | ||||||
|       var apkUrlsFromAssets = (e['assets']?['links'] as List<dynamic>? ?? []) |       var apkUrlsFromAssets = (e['assets']?['links'] as List<dynamic>? ?? []) | ||||||
|           .map((e) { |           .map((e) { | ||||||
| @@ -152,9 +152,8 @@ class GitLab extends AppSource { | |||||||
|       var apkUrlsSet = apkUrlsFromAssets.toSet(); |       var apkUrlsSet = apkUrlsFromAssets.toSet(); | ||||||
|       apkUrlsSet.addAll(uploadedAPKsFromDescription); |       apkUrlsSet.addAll(uploadedAPKsFromDescription); | ||||||
|       var releaseDateString = e['released_at'] ?? e['created_at']; |       var releaseDateString = e['released_at'] ?? e['created_at']; | ||||||
|       DateTime? releaseDate = releaseDateString != null |       DateTime? releaseDate = | ||||||
|           ? DateTime.parse(releaseDateString) |           releaseDateString != null ? DateTime.parse(releaseDateString) : null; | ||||||
|           : null; |  | ||||||
|       return APKDetails( |       return APKDetails( | ||||||
|           e['tag_name'] ?? e['name'], |           e['tag_name'] ?? e['name'], | ||||||
|           getApkUrlsFromUrls(apkUrlsSet.toList()), |           getApkUrlsFromUrls(apkUrlsSet.toList()), | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
|  | import 'package:dio/dio.dart'; | ||||||
| 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:http/http.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/apps_provider.dart'; | import 'package:obtainium/providers/apps_provider.dart'; | ||||||
| @@ -213,11 +213,11 @@ class HTML extends AppSource { | |||||||
|   // Given an HTTP response, grab some links according to the common additional settings |   // Given an HTTP response, grab some links according to the common additional settings | ||||||
|   // (those that apply to intermediate and final steps) |   // (those that apply to intermediate and final steps) | ||||||
|   Future<List<MapEntry<String, String>>> grabLinksCommon( |   Future<List<MapEntry<String, String>>> grabLinksCommon( | ||||||
|       Response res, Map<String, dynamic> additionalSettings) async { |       Response res, Uri url, Map<String, dynamic> additionalSettings) async { | ||||||
|     if (res.statusCode != 200) { |     if (res.statusCode != 200) { | ||||||
|       throw getObtainiumHttpError(res); |       throw getObtainiumHttpError(res); | ||||||
|     } |     } | ||||||
|     var html = parse(res.body); |     var html = parse(res.data); | ||||||
|     List<MapEntry<String, String>> allLinks = html |     List<MapEntry<String, String>> allLinks = html | ||||||
|         .querySelectorAll('a') |         .querySelectorAll('a') | ||||||
|         .map((element) => MapEntry( |         .map((element) => MapEntry( | ||||||
| @@ -226,13 +226,12 @@ class HTML extends AppSource { | |||||||
|                 ? element.text |                 ? element.text | ||||||
|                 : (element.attributes['href'] ?? '').split('/').last)) |                 : (element.attributes['href'] ?? '').split('/').last)) | ||||||
|         .where((element) => element.key.isNotEmpty) |         .where((element) => element.key.isNotEmpty) | ||||||
|         .map((e) => |         .map((e) => MapEntry(ensureAbsoluteUrl(e.key, url), e.value)) | ||||||
|             MapEntry(ensureAbsoluteUrl(e.key, res.request!.url), e.value)) |  | ||||||
|         .toList(); |         .toList(); | ||||||
|     if (allLinks.isEmpty) { |     if (allLinks.isEmpty) { | ||||||
|       allLinks = RegExp( |       allLinks = RegExp( | ||||||
|               r'(http|ftp|https)://([\w_-]+(?:(?:\.[\w_-]+)+))([\w.,@?^=%&:/~+#-]*[\w@?^=%&/~+#-])?') |               r'(http|ftp|https)://([\w_-]+(?:(?:\.[\w_-]+)+))([\w.,@?^=%&:/~+#-]*[\w@?^=%&/~+#-])?') | ||||||
|           .allMatches(res.body) |           .allMatches(res.data) | ||||||
|           .map((match) => |           .map((match) => | ||||||
|               MapEntry(match.group(0)!, match.group(0)?.split('/').last ?? '')) |               MapEntry(match.group(0)!, match.group(0)?.split('/').last ?? '')) | ||||||
|           .toList(); |           .toList(); | ||||||
| @@ -285,6 +284,7 @@ class HTML extends AppSource { | |||||||
|     for (int i = 0; i < (additionalSettings['intermediateLink'].length); i++) { |     for (int i = 0; i < (additionalSettings['intermediateLink'].length); i++) { | ||||||
|       var intLinks = await grabLinksCommon( |       var intLinks = await grabLinksCommon( | ||||||
|           await sourceRequest(currentUrl, additionalSettings), |           await sourceRequest(currentUrl, additionalSettings), | ||||||
|  |           Uri.parse(currentUrl), | ||||||
|           additionalSettings['intermediateLink'][i]); |           additionalSettings['intermediateLink'][i]); | ||||||
|       if (intLinks.isEmpty) { |       if (intLinks.isEmpty) { | ||||||
|         throw NoReleasesError(); |         throw NoReleasesError(); | ||||||
| @@ -298,8 +298,9 @@ class HTML extends AppSource { | |||||||
|     if (additionalSettings['directAPKLink'] != true) { |     if (additionalSettings['directAPKLink'] != true) { | ||||||
|       Response res = await sourceRequest(currentUrl, additionalSettings); |       Response res = await sourceRequest(currentUrl, additionalSettings); | ||||||
|       versionExtractionWholePageString = |       versionExtractionWholePageString = | ||||||
|           res.body.split('\r\n').join('\n').split('\n').join('\\n'); |           res.data.split('\r\n').join('\n').split('\n').join('\\n'); | ||||||
|       links = await grabLinksCommon(res, additionalSettings); |       links = | ||||||
|  |           await grabLinksCommon(res, Uri.parse(currentUrl), additionalSettings); | ||||||
|       links = filterApks(links, additionalSettings['apkFilterRegEx'], |       links = filterApks(links, additionalSettings['apkFilterRegEx'], | ||||||
|           additionalSettings['invertAPKFilter']); |           additionalSettings['invertAPKFilter']); | ||||||
|       if (links.isEmpty) { |       if (links.isEmpty) { | ||||||
|   | |||||||
| @@ -1,5 +1,5 @@ | |||||||
|  | import 'package:dio/dio.dart'; | ||||||
| import 'package:easy_localization/easy_localization.dart'; | import 'package:easy_localization/easy_localization.dart'; | ||||||
| import 'package:http/http.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'; | ||||||
|  |  | ||||||
| @@ -57,8 +57,8 @@ class HuaweiAppGallery extends AppSource { | |||||||
|       {Map<String, dynamic> additionalSettings = const {}}) async { |       {Map<String, dynamic> additionalSettings = const {}}) async { | ||||||
|     String dlUrl = getDlUrl(standardUrl); |     String dlUrl = getDlUrl(standardUrl); | ||||||
|     Response res = await requestAppdlRedirect(dlUrl, additionalSettings); |     Response res = await requestAppdlRedirect(dlUrl, additionalSettings); | ||||||
|     return res.headers['location'] != null |     return res.headers.map['location']?.isNotEmpty == true | ||||||
|         ? appIdFromRedirectDlUrl(res.headers['location']!) |         ? appIdFromRedirectDlUrl(res.headers.map['location']![0]) | ||||||
|         : null; |         : null; | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -72,9 +72,12 @@ class HuaweiAppGallery extends AppSource { | |||||||
|     if (res.headers['location'] == null) { |     if (res.headers['location'] == null) { | ||||||
|       throw NoReleasesError(); |       throw NoReleasesError(); | ||||||
|     } |     } | ||||||
|     String appId = appIdFromRedirectDlUrl(res.headers['location']!); |     String appId = appIdFromRedirectDlUrl(res.headers.map['location']![0]); | ||||||
|     var relDateStr = |     var relDateStr = res.headers.map['location']?[0] | ||||||
|         res.headers['location']?.split('?')[0].split('.').reversed.toList()[1]; |         .split('?')[0] | ||||||
|  |         .split('.') | ||||||
|  |         .reversed | ||||||
|  |         .toList()[1]; | ||||||
|     var relDateStrAdj = relDateStr?.split(''); |     var relDateStrAdj = relDateStr?.split(''); | ||||||
|     var tempLen = relDateStrAdj?.length ?? 0; |     var tempLen = relDateStrAdj?.length ?? 0; | ||||||
|     var i = 2; |     var i = 2; | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| import 'dart:convert'; | import 'dart:convert'; | ||||||
|  |  | ||||||
| import 'package:http/http.dart'; | import 'package:dio/dio.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'; | ||||||
|  |  | ||||||
| @@ -33,7 +33,7 @@ class Jenkins extends AppSource { | |||||||
|     Response res = await sourceRequest( |     Response res = await sourceRequest( | ||||||
|         '$standardUrl/lastSuccessfulBuild/api/json', additionalSettings); |         '$standardUrl/lastSuccessfulBuild/api/json', additionalSettings); | ||||||
|     if (res.statusCode == 200) { |     if (res.statusCode == 200) { | ||||||
|       var json = jsonDecode(res.body); |       var json = jsonDecode(res.data); | ||||||
|       var releaseDate = json['timestamp'] == null |       var releaseDate = json['timestamp'] == null | ||||||
|           ? null |           ? null | ||||||
|           : DateTime.fromMillisecondsSinceEpoch(json['timestamp'] as int); |           : DateTime.fromMillisecondsSinceEpoch(json['timestamp'] as int); | ||||||
|   | |||||||
| @@ -1,5 +1,5 @@ | |||||||
|  | import 'package:dio/dio.dart'; | ||||||
| import 'package:html/parser.dart'; | import 'package:html/parser.dart'; | ||||||
| import 'package:http/http.dart'; |  | ||||||
| import 'package:obtainium/app_sources/github.dart'; | import 'package:obtainium/app_sources/github.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'; | ||||||
| @@ -33,7 +33,7 @@ class Mullvad extends AppSource { | |||||||
|     Response res = await sourceRequest( |     Response res = await sourceRequest( | ||||||
|         '$standardUrl/en/download/android', additionalSettings); |         '$standardUrl/en/download/android', additionalSettings); | ||||||
|     if (res.statusCode == 200) { |     if (res.statusCode == 200) { | ||||||
|       var versions = parse(res.body) |       var versions = parse(res.data) | ||||||
|           .querySelectorAll('p') |           .querySelectorAll('p') | ||||||
|           .map((e) => e.innerHtml) |           .map((e) => e.innerHtml) | ||||||
|           .where((p) => p.contains('Latest version: ')) |           .where((p) => p.contains('Latest version: ')) | ||||||
|   | |||||||
| @@ -1,5 +1,5 @@ | |||||||
|  | import 'package:dio/dio.dart'; | ||||||
| import 'package:html/parser.dart'; | import 'package:html/parser.dart'; | ||||||
| import 'package:http/http.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'; | ||||||
|  |  | ||||||
| @@ -83,7 +83,7 @@ class NeutronCode extends AppSource { | |||||||
|   ) async { |   ) async { | ||||||
|     Response res = await sourceRequest(standardUrl, additionalSettings); |     Response res = await sourceRequest(standardUrl, additionalSettings); | ||||||
|     if (res.statusCode == 200) { |     if (res.statusCode == 200) { | ||||||
|       var http = parse(res.body); |       var http = parse(res.data); | ||||||
|       var name = http.querySelector('.pd-title')?.innerHtml; |       var name = http.querySelector('.pd-title')?.innerHtml; | ||||||
|       var filename = http.querySelector('.pd-filename .pd-float')?.innerHtml; |       var filename = http.querySelector('.pd-filename .pd-float')?.innerHtml; | ||||||
|       if (filename == null) { |       if (filename == null) { | ||||||
|   | |||||||
| @@ -1,5 +1,5 @@ | |||||||
| import 'dart:convert'; | import 'dart:convert'; | ||||||
| import 'package:http/http.dart'; | import 'package:dio/dio.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'; | ||||||
|  |  | ||||||
| @@ -21,7 +21,7 @@ class Signal extends AppSource { | |||||||
|     Response res = await sourceRequest( |     Response res = await sourceRequest( | ||||||
|         'https://updates.${hosts[0]}/android/latest.json', additionalSettings); |         'https://updates.${hosts[0]}/android/latest.json', additionalSettings); | ||||||
|     if (res.statusCode == 200) { |     if (res.statusCode == 200) { | ||||||
|       var json = jsonDecode(res.body); |       var json = jsonDecode(res.data); | ||||||
|       String? apkUrl = json['url']; |       String? apkUrl = json['url']; | ||||||
|       List<String> apkUrls = apkUrl == null ? [] : [apkUrl]; |       List<String> apkUrls = apkUrl == null ? [] : [apkUrl]; | ||||||
|       String? version = json['versionName']; |       String? version = json['versionName']; | ||||||
|   | |||||||
| @@ -1,5 +1,5 @@ | |||||||
|  | import 'package:dio/dio.dart'; | ||||||
| import 'package:html/parser.dart'; | import 'package:html/parser.dart'; | ||||||
| import 'package:http/http.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'; | ||||||
|  |  | ||||||
| @@ -49,7 +49,7 @@ class SourceForge extends AppSource { | |||||||
|         '${standardUri.origin}/${standardUri.pathSegments.sublist(0, 2).join('/')}/rss?path=/', |         '${standardUri.origin}/${standardUri.pathSegments.sublist(0, 2).join('/')}/rss?path=/', | ||||||
|         additionalSettings); |         additionalSettings); | ||||||
|     if (res.statusCode == 200) { |     if (res.statusCode == 200) { | ||||||
|       var parsedHtml = parse(res.body); |       var parsedHtml = parse(res.data); | ||||||
|       var allDownloadLinks = parsedHtml |       var allDownloadLinks = parsedHtml | ||||||
|           .querySelectorAll('guid') |           .querySelectorAll('guid') | ||||||
|           .map((e) => e.innerHtml) |           .map((e) => e.innerHtml) | ||||||
|   | |||||||
| @@ -1,5 +1,5 @@ | |||||||
|  | import 'package:dio/dio.dart'; | ||||||
| import 'package:html/parser.dart'; | import 'package:html/parser.dart'; | ||||||
| import 'package:http/http.dart'; |  | ||||||
| import 'package:obtainium/app_sources/html.dart'; | import 'package:obtainium/app_sources/html.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'; | ||||||
| @@ -55,7 +55,7 @@ class SourceHut extends AppSource { | |||||||
|     Response res = |     Response res = | ||||||
|         await sourceRequest('$standardUrl/refs/rss.xml', additionalSettings); |         await sourceRequest('$standardUrl/refs/rss.xml', additionalSettings); | ||||||
|     if (res.statusCode == 200) { |     if (res.statusCode == 200) { | ||||||
|       var parsedHtml = parse(res.body); |       var parsedHtml = parse(res.data); | ||||||
|       List<APKDetails> apkDetailsList = []; |       List<APKDetails> apkDetailsList = []; | ||||||
|       int ind = 0; |       int ind = 0; | ||||||
|  |  | ||||||
| @@ -85,7 +85,7 @@ class SourceHut extends AppSource { | |||||||
|         var res2 = await sourceRequest(releasePage, additionalSettings); |         var res2 = await sourceRequest(releasePage, additionalSettings); | ||||||
|         List<MapEntry<String, String>> apkUrls = []; |         List<MapEntry<String, String>> apkUrls = []; | ||||||
|         if (res2.statusCode == 200) { |         if (res2.statusCode == 200) { | ||||||
|           apkUrls = getApkUrlsFromUrls(parse(res2.body) |           apkUrls = getApkUrlsFromUrls(parse(res2.data) | ||||||
|               .querySelectorAll('a') |               .querySelectorAll('a') | ||||||
|               .map((e) => e.attributes['href'] ?? '') |               .map((e) => e.attributes['href'] ?? '') | ||||||
|               .where((e) => e.toLowerCase().endsWith('.apk')) |               .where((e) => e.toLowerCase().endsWith('.apk')) | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
|  | import 'package:dio/dio.dart'; | ||||||
| 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:http/http.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'; | ||||||
| @@ -38,7 +38,7 @@ class SteamMobile extends AppSource { | |||||||
|       } |       } | ||||||
|       String apkInURLRegexPattern = |       String apkInURLRegexPattern = | ||||||
|           '/$apkNamePrefix-([0-9]+\\.)*[0-9]+\\.apk\$'; |           '/$apkNamePrefix-([0-9]+\\.)*[0-9]+\\.apk\$'; | ||||||
|       var links = parse(res.body) |       var links = parse(res.data) | ||||||
|           .querySelectorAll('a') |           .querySelectorAll('a') | ||||||
|           .map((e) => e.attributes['href'] ?? '') |           .map((e) => e.attributes['href'] ?? '') | ||||||
|           .where((e) => RegExp('https://.*$apkInURLRegexPattern').hasMatch(e)) |           .where((e) => RegExp('https://.*$apkInURLRegexPattern').hasMatch(e)) | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
|  | import 'package:dio/dio.dart'; | ||||||
| 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:http/http.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'; | ||||||
|  |  | ||||||
| @@ -23,7 +23,7 @@ class TelegramApp extends AppSource { | |||||||
|     Response res = |     Response res = | ||||||
|         await sourceRequest('https://t.me/s/TAndroidAPK', additionalSettings); |         await sourceRequest('https://t.me/s/TAndroidAPK', additionalSettings); | ||||||
|     if (res.statusCode == 200) { |     if (res.statusCode == 200) { | ||||||
|       var http = parse(res.body); |       var http = parse(res.data); | ||||||
|       var messages = |       var messages = | ||||||
|           http.querySelectorAll('.tgme_widget_message_text.js-message_text'); |           http.querySelectorAll('.tgme_widget_message_text.js-message_text'); | ||||||
|       var version = messages.isNotEmpty |       var version = messages.isNotEmpty | ||||||
|   | |||||||
| @@ -37,7 +37,7 @@ class Uptodown extends AppSource { | |||||||
|     if (res.statusCode != 200) { |     if (res.statusCode != 200) { | ||||||
|       throw getObtainiumHttpError(res); |       throw getObtainiumHttpError(res); | ||||||
|     } |     } | ||||||
|     var html = parse(res.body); |     var html = parse(res.data); | ||||||
|     String? version = html.querySelector('div.version')?.innerHtml; |     String? version = html.querySelector('div.version')?.innerHtml; | ||||||
|     String? apkUrl = |     String? apkUrl = | ||||||
|         '${standardUrl.split('/').reversed.toList().sublist(1).reversed.join('/')}/post-download'; |         '${standardUrl.split('/').reversed.toList().sublist(1).reversed.join('/')}/post-download'; | ||||||
| @@ -94,7 +94,7 @@ class Uptodown extends AppSource { | |||||||
|     if (res.statusCode != 200) { |     if (res.statusCode != 200) { | ||||||
|       throw getObtainiumHttpError(res); |       throw getObtainiumHttpError(res); | ||||||
|     } |     } | ||||||
|     var html = parse(res.body); |     var html = parse(res.data); | ||||||
|     var finalUrlKey = |     var finalUrlKey = | ||||||
|         html.querySelector('.post-download')?.attributes['data-url']; |         html.querySelector('.post-download')?.attributes['data-url']; | ||||||
|     if (finalUrlKey == null) { |     if (finalUrlKey == null) { | ||||||
|   | |||||||
| @@ -1,7 +1,8 @@ | |||||||
|  | import 'package:dio/dio.dart'; | ||||||
| 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:http/http.dart'; |  | ||||||
| import 'package:obtainium/custom_errors.dart'; | import 'package:obtainium/custom_errors.dart'; | ||||||
|  | import 'package:obtainium/main.dart'; | ||||||
| import 'package:obtainium/providers/source_provider.dart'; | import 'package:obtainium/providers/source_provider.dart'; | ||||||
|  |  | ||||||
| class VLC extends AppSource { | class VLC extends AppSource { | ||||||
| @@ -29,7 +30,7 @@ class VLC extends AppSource { | |||||||
|       String standardUrl, Map<String, dynamic> additionalSettings) async { |       String standardUrl, Map<String, dynamic> additionalSettings) async { | ||||||
|     Response res = await sourceRequest(dwUrlBase, additionalSettings); |     Response res = await sourceRequest(dwUrlBase, additionalSettings); | ||||||
|     if (res.statusCode == 200) { |     if (res.statusCode == 200) { | ||||||
|       var dwLinks = parse(res.body) |       var dwLinks = parse(res.data) | ||||||
|           .querySelectorAll('a') |           .querySelectorAll('a') | ||||||
|           .where((element) => element.attributes['href'] != 'last/') |           .where((element) => element.attributes['href'] != 'last/') | ||||||
|           .map((e) => e.attributes['href']?.split('/')[0]) |           .map((e) => e.attributes['href']?.split('/')[0]) | ||||||
| @@ -49,11 +50,11 @@ class VLC extends AppSource { | |||||||
|     String standardUrl, |     String standardUrl, | ||||||
|     Map<String, dynamic> additionalSettings, |     Map<String, dynamic> additionalSettings, | ||||||
|   ) async { |   ) async { | ||||||
|     Response res = await get( |     Response res = | ||||||
|         Uri.parse('https://www.videolan.org/vlc/download-android.html')); |         await dio.get('https://www.videolan.org/vlc/download-android.html'); | ||||||
|     if (res.statusCode == 200) { |     if (res.statusCode == 200) { | ||||||
|       var dwUrlBase = 'get.videolan.org/vlc-android'; |       var dwUrlBase = 'get.videolan.org/vlc-android'; | ||||||
|       var dwLinks = parse(res.body) |       var dwLinks = parse(res.data) | ||||||
|           .querySelectorAll('a') |           .querySelectorAll('a') | ||||||
|           .where((element) => |           .where((element) => | ||||||
|               element.attributes['href']?.contains(dwUrlBase) ?? false) |               element.attributes['href']?.contains(dwUrlBase) ?? false) | ||||||
| @@ -84,14 +85,14 @@ class VLC extends AppSource { | |||||||
|     Response res = await sourceRequest(apkUrl, additionalSettings); |     Response res = await sourceRequest(apkUrl, additionalSettings); | ||||||
|     if (res.statusCode == 200) { |     if (res.statusCode == 200) { | ||||||
|       String? apkUrl = |       String? apkUrl = | ||||||
|           parse(res.body).querySelector('#alt_link')?.attributes['href']; |           parse(res.data).querySelector('#alt_link')?.attributes['href']; | ||||||
|       if (apkUrl == null) { |       if (apkUrl == null) { | ||||||
|         throw NoAPKError(); |         throw NoAPKError(); | ||||||
|       } |       } | ||||||
|       return apkUrl; |       return apkUrl; | ||||||
|     } else if (res.statusCode == 500 && |     } else if (res.statusCode == 500 && | ||||||
|         res.body.toLowerCase().indexOf('mirror') > 0) { |         res.data.toLowerCase().indexOf('mirror') > 0) { | ||||||
|       var html = parse(res.body); |       var html = parse(res.data); | ||||||
|       var err = ''; |       var err = ''; | ||||||
|       html.body?.nodes.forEach((element) { |       html.body?.nodes.forEach((element) { | ||||||
|         if (element.text != null) { |         if (element.text != null) { | ||||||
|   | |||||||
| @@ -1,5 +1,5 @@ | |||||||
|  | import 'package:dio/dio.dart'; | ||||||
| import 'package:html/parser.dart'; | import 'package:html/parser.dart'; | ||||||
| import 'package:http/http.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'; | ||||||
|  |  | ||||||
| @@ -20,7 +20,7 @@ class WhatsApp extends AppSource { | |||||||
|     Response res = |     Response res = | ||||||
|         await sourceRequest('$standardUrl/android', additionalSettings); |         await sourceRequest('$standardUrl/android', additionalSettings); | ||||||
|     if (res.statusCode == 200) { |     if (res.statusCode == 200) { | ||||||
|       var targetLinks = parse(res.body) |       var targetLinks = parse(res.data) | ||||||
|           .querySelectorAll('a') |           .querySelectorAll('a') | ||||||
|           .map((e) => e.attributes['href'] ?? '') |           .map((e) => e.attributes['href'] ?? '') | ||||||
|           .where((e) => e.isNotEmpty) |           .where((e) => e.isNotEmpty) | ||||||
|   | |||||||
| @@ -18,6 +18,7 @@ import 'package:easy_localization/easy_localization.dart'; | |||||||
| import 'package:easy_localization/src/easy_localization_controller.dart'; | import 'package:easy_localization/src/easy_localization_controller.dart'; | ||||||
| // ignore: implementation_imports | // ignore: implementation_imports | ||||||
| import 'package:easy_localization/src/localization.dart'; | import 'package:easy_localization/src/localization.dart'; | ||||||
|  | import 'package:dio/dio.dart'; | ||||||
|  |  | ||||||
| List<MapEntry<Locale, String>> supportedLocales = const [ | List<MapEntry<Locale, String>> supportedLocales = const [ | ||||||
|   MapEntry(Locale('en'), 'English'), |   MapEntry(Locale('en'), 'English'), | ||||||
| @@ -46,6 +47,9 @@ var fdroid = false; | |||||||
|  |  | ||||||
| final globalNavigatorKey = GlobalKey<NavigatorState>(); | final globalNavigatorKey = GlobalKey<NavigatorState>(); | ||||||
|  |  | ||||||
|  | final dio = Dio(BaseOptions( | ||||||
|  |     responseType: ResponseType.plain, receiveDataWhenStatusError: true)); | ||||||
|  |  | ||||||
| Future<void> loadTranslations() async { | Future<void> loadTranslations() async { | ||||||
|   // See easy_localization/issues/210 |   // See easy_localization/issues/210 | ||||||
|   await EasyLocalizationController.initEasyLocation(); |   await EasyLocalizationController.initEasyLocation(); | ||||||
|   | |||||||
| @@ -1,9 +1,10 @@ | |||||||
| import 'dart:convert'; | import 'dart:convert'; | ||||||
|  |  | ||||||
|  | import 'package:dio/dio.dart'; | ||||||
| import 'package:easy_localization/easy_localization.dart'; | import 'package:easy_localization/easy_localization.dart'; | ||||||
| import 'package:http/http.dart'; |  | ||||||
| import 'package:obtainium/app_sources/github.dart'; | import 'package:obtainium/app_sources/github.dart'; | ||||||
| import 'package:obtainium/custom_errors.dart'; | import 'package:obtainium/custom_errors.dart'; | ||||||
|  | import 'package:obtainium/main.dart'; | ||||||
| import 'package:obtainium/providers/source_provider.dart'; | import 'package:obtainium/providers/source_provider.dart'; | ||||||
|  |  | ||||||
| class GitHubStars implements MassAppUrlSource { | class GitHubStars implements MassAppUrlSource { | ||||||
| @@ -15,13 +16,12 @@ class GitHubStars implements MassAppUrlSource { | |||||||
|  |  | ||||||
|   Future<Map<String, List<String>>> getOnePageOfUserStarredUrlsWithDescriptions( |   Future<Map<String, List<String>>> getOnePageOfUserStarredUrlsWithDescriptions( | ||||||
|       String username, int page) async { |       String username, int page) async { | ||||||
|     Response res = await get( |     Response res = await dio.get( | ||||||
|         Uri.parse( |         'https://api.github.com/users/$username/starred?per_page=100&page=$page', | ||||||
|             'https://api.github.com/users/$username/starred?per_page=100&page=$page'), |         options: Options(headers: await GitHub().getRequestHeaders({}))); | ||||||
|         headers: await GitHub().getRequestHeaders({})); |  | ||||||
|     if (res.statusCode == 200) { |     if (res.statusCode == 200) { | ||||||
|       Map<String, List<String>> urlsWithDescriptions = {}; |       Map<String, List<String>> urlsWithDescriptions = {}; | ||||||
|       for (var e in (jsonDecode(res.body) as List<dynamic>)) { |       for (var e in (jsonDecode(res.data) as List<dynamic>)) { | ||||||
|         urlsWithDescriptions.addAll({ |         urlsWithDescriptions.addAll({ | ||||||
|           e['html_url'] as String: [ |           e['html_url'] as String: [ | ||||||
|             e['full_name'] as String, |             e['full_name'] as String, | ||||||
|   | |||||||
| @@ -5,14 +5,15 @@ import 'dart:async'; | |||||||
| import 'dart:convert'; | import 'dart:convert'; | ||||||
| import 'dart:io'; | import 'dart:io'; | ||||||
| import 'dart:math'; | import 'dart:math'; | ||||||
| import 'package:http/http.dart' as http; |  | ||||||
| import 'package:crypto/crypto.dart'; | import 'package:crypto/crypto.dart'; | ||||||
|  | import 'package:http/http.dart' as http; | ||||||
|  |  | ||||||
| import 'package:android_intent_plus/flag.dart'; | import 'package:android_intent_plus/flag.dart'; | ||||||
| import 'package:android_package_installer/android_package_installer.dart'; | import 'package:android_package_installer/android_package_installer.dart'; | ||||||
| import 'package:android_package_manager/android_package_manager.dart'; | import 'package:android_package_manager/android_package_manager.dart'; | ||||||
| import 'package:connectivity_plus/connectivity_plus.dart'; | import 'package:connectivity_plus/connectivity_plus.dart'; | ||||||
| import 'package:device_info_plus/device_info_plus.dart'; | import 'package:device_info_plus/device_info_plus.dart'; | ||||||
|  | import 'package:dio/dio.dart'; | ||||||
| import 'package:easy_localization/easy_localization.dart'; | import 'package:easy_localization/easy_localization.dart'; | ||||||
| import 'package:flutter/material.dart'; | import 'package:flutter/material.dart'; | ||||||
| import 'package:flutter/services.dart'; | import 'package:flutter/services.dart'; | ||||||
| @@ -28,7 +29,6 @@ import 'package:provider/provider.dart'; | |||||||
| import 'package:path_provider/path_provider.dart'; | import 'package:path_provider/path_provider.dart'; | ||||||
| import 'package:flutter_fgbg/flutter_fgbg.dart'; | import 'package:flutter_fgbg/flutter_fgbg.dart'; | ||||||
| import 'package:obtainium/providers/source_provider.dart'; | import 'package:obtainium/providers/source_provider.dart'; | ||||||
| import 'package:http/http.dart'; |  | ||||||
| import 'package:android_intent_plus/android_intent.dart'; | import 'package:android_intent_plus/android_intent.dart'; | ||||||
| import 'package:flutter_archive/flutter_archive.dart'; | import 'package:flutter_archive/flutter_archive.dart'; | ||||||
| import 'package:shared_storage/shared_storage.dart' as saf; | import 'package:shared_storage/shared_storage.dart' as saf; | ||||||
| @@ -146,10 +146,10 @@ Future<File> downloadFileWithRetry( | |||||||
|     Map<String, String>? headers, |     Map<String, String>? headers, | ||||||
|     int retries = 3}) async { |     int retries = 3}) async { | ||||||
|   try { |   try { | ||||||
|     return await downloadFile(url, fileNameNoExt, onProgress, destDir, |     return await downloadApk(url, fileNameNoExt, onProgress, destDir, | ||||||
|         useExisting: useExisting, headers: headers); |         useExisting: useExisting, headers: headers); | ||||||
|   } catch (e) { |   } catch (e) { | ||||||
|     if (retries > 0 && e is ClientException) { |     if (retries > 0 && e is DioException) { | ||||||
|       await Future.delayed(const Duration(seconds: 5)); |       await Future.delayed(const Duration(seconds: 5)); | ||||||
|       return await downloadFileWithRetry( |       return await downloadFileWithRetry( | ||||||
|           url, fileNameNoExt, onProgress, destDir, |           url, fileNameNoExt, onProgress, destDir, | ||||||
| @@ -183,9 +183,162 @@ Future<String> checkPartialDownloadHashDynamic(String url, | |||||||
|   throw NoVersionError(); |   throw NoVersionError(); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | Future<File> downloadApk( | ||||||
|  |     String url, String fileNameNoExt, Function? onProgress, String destDir, | ||||||
|  |     {bool useExisting = true, Map<String, String>? headers}) async { | ||||||
|  |   var resHeaders = await getHeaders(url, headers: headers); | ||||||
|  |  | ||||||
|  |   String ext = resHeaders['content-disposition']?.split('.').last ?? 'apk'; | ||||||
|  |   if (ext.endsWith('"') || ext.endsWith("other")) { | ||||||
|  |     ext = ext.substring(0, ext.length - 1); | ||||||
|  |   } | ||||||
|  |   if (url.toLowerCase().endsWith('.apk') && ext != 'apk') { | ||||||
|  |     ext = 'apk'; | ||||||
|  |   } | ||||||
|  |   File file = File('$destDir/$fileNameNoExt.$ext'); | ||||||
|  |  | ||||||
|  |   final contentLength = await getContentLengthIfRangeSupported(resHeaders); | ||||||
|  |  | ||||||
|  |   if (useExisting && file.existsSync()) { | ||||||
|  |     var length = file.lengthSync(); | ||||||
|  |     if (contentLength == null) { | ||||||
|  |       return file; | ||||||
|  |     } else { | ||||||
|  |       if (length == contentLength) { | ||||||
|  |         return file; | ||||||
|  |       } | ||||||
|  |       if (length > contentLength) { | ||||||
|  |         useExisting = false; | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   double progress = -1; | ||||||
|  |  | ||||||
|  |   try { | ||||||
|  |     if (contentLength == null) { | ||||||
|  |       Response response = await dio.download( | ||||||
|  |         url, | ||||||
|  |         file.path, | ||||||
|  |         options: Options(headers: headers), | ||||||
|  |         onReceiveProgress: (count, total) { | ||||||
|  |           progress = (total > 0 ? count / total * 100 : 30); | ||||||
|  |           if (onProgress != null) { | ||||||
|  |             onProgress(progress); | ||||||
|  |           } | ||||||
|  |         }, | ||||||
|  |       ); | ||||||
|  |       if ((response.statusCode ?? 200) < 200 || | ||||||
|  |           (response.statusCode ?? 200) > 299) { | ||||||
|  |         throw response.statusMessage ?? tr('unexpectedError'); | ||||||
|  |       } | ||||||
|  |     } else { | ||||||
|  |       var targetFileLength = | ||||||
|  |           useExisting && file.existsSync() ? file.lengthSync() : null; | ||||||
|  |       int bufferSize = 1024 * 1024; // 1 Megabyte | ||||||
|  |       final sink = file.openWrite( | ||||||
|  |         mode: useExisting ? FileMode.writeOnlyAppend : FileMode.writeOnly, | ||||||
|  |       ); | ||||||
|  |       int rangeStart = targetFileLength ?? 0; | ||||||
|  |       int rangeEnd = min( | ||||||
|  |         rangeStart + bufferSize - 1, | ||||||
|  |         contentLength - 1, | ||||||
|  |       ); | ||||||
|  |       if (onProgress != null) { | ||||||
|  |         progress = ((rangeStart / contentLength) * 100); | ||||||
|  |         onProgress(progress); | ||||||
|  |       } | ||||||
|  |       while (true) { | ||||||
|  |         var headersCurrent = headers ?? {}; | ||||||
|  |         headersCurrent['range'] = 'bytes=$rangeStart-$rangeEnd'; | ||||||
|  |         Response response = await dio.get( | ||||||
|  |           url, | ||||||
|  |           onReceiveProgress: (count, total) { | ||||||
|  |             if (onProgress != null) { | ||||||
|  |               final newProgress = | ||||||
|  |                   (((rangeStart + count) / contentLength) * 100); | ||||||
|  |               if (newProgress != progress) { | ||||||
|  |                 progress = newProgress; | ||||||
|  |                 onProgress(progress); | ||||||
|  |               } | ||||||
|  |             } | ||||||
|  |           }, | ||||||
|  |           options: Options( | ||||||
|  |             headers: headersCurrent, | ||||||
|  |             responseType: ResponseType.bytes, | ||||||
|  |           ), | ||||||
|  |         ); | ||||||
|  |  | ||||||
|  |         if ((response.statusCode ?? 200) < 200 || | ||||||
|  |             (response.statusCode ?? 200) > 299) { | ||||||
|  |           throw response.statusMessage ?? tr('unexpectedError'); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         final Uint8List data = response.data; | ||||||
|  |         sink.add(data); | ||||||
|  |         if (rangeEnd == contentLength - 1) { | ||||||
|  |           break; | ||||||
|  |         } | ||||||
|  |         rangeStart = rangeEnd + 1; | ||||||
|  |         rangeEnd = min( | ||||||
|  |           rangeStart + bufferSize - 1, | ||||||
|  |           contentLength - 1, | ||||||
|  |         ); | ||||||
|  |       } | ||||||
|  |       await sink.flush(); | ||||||
|  |       await sink.close(); | ||||||
|  |     } | ||||||
|  |   } finally { | ||||||
|  |     if (onProgress != null) { | ||||||
|  |       onProgress(null); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |   return file; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | Future<int?> getContentLengthIfRangeSupported( | ||||||
|  |     Map<String, String> headers) async { | ||||||
|  |   try { | ||||||
|  |     int? contentLength; | ||||||
|  |     { | ||||||
|  |       var contentLengthHeaderValue = headers['content-length']; | ||||||
|  |       if (contentLengthHeaderValue?.isNotEmpty == true) { | ||||||
|  |         contentLength = int.tryParse(contentLengthHeaderValue!); | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |     bool rangeFeatureEnabled = false; | ||||||
|  |     if (headers['accept-ranges']?.isNotEmpty == true) { | ||||||
|  |       rangeFeatureEnabled = | ||||||
|  |           headers['accept-ranges']!.trim().toLowerCase() == 'bytes'; | ||||||
|  |     } | ||||||
|  |     if (!rangeFeatureEnabled) { | ||||||
|  |       contentLength = null; | ||||||
|  |     } | ||||||
|  |     return contentLength; | ||||||
|  |   } catch (e) { | ||||||
|  |     return null; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | Future<Map<String, String>> getHeaders(String url, | ||||||
|  |     {Map<String, String>? headers}) async { | ||||||
|  |   var req = http.Request('GET', Uri.parse(url)); | ||||||
|  |   if (headers != null) { | ||||||
|  |     req.headers.addAll(headers); | ||||||
|  |   } | ||||||
|  |   var client = http.Client(); | ||||||
|  |   var response = await client.send(req); | ||||||
|  |   if (response.statusCode < 200 || response.statusCode > 299) { | ||||||
|  |     throw ObtainiumError(response.reasonPhrase ?? tr('unexpectedError')); | ||||||
|  |   } | ||||||
|  |   var returnHeaders = response.headers; | ||||||
|  |   client.close(); | ||||||
|  |   return returnHeaders; | ||||||
|  | } | ||||||
|  |  | ||||||
| Future<String> checkPartialDownloadHash(String url, int bytesToGrab, | Future<String> checkPartialDownloadHash(String url, int bytesToGrab, | ||||||
|     {Map<String, String>? headers}) async { |     {Map<String, String>? headers}) async { | ||||||
|   var req = Request('GET', Uri.parse(url)); |   var req = http.Request('GET', Uri.parse(url)); | ||||||
|   if (headers != null) { |   if (headers != null) { | ||||||
|     req.headers.addAll(headers); |     req.headers.addAll(headers); | ||||||
|   } |   } | ||||||
| @@ -199,58 +352,41 @@ Future<String> checkPartialDownloadHash(String url, int bytesToGrab, | |||||||
|   return hashListOfLists(bytes); |   return hashListOfLists(bytes); | ||||||
| } | } | ||||||
|  |  | ||||||
| Future<File> downloadFile( | // Future<File> downloadFile( | ||||||
|     String url, String fileNameNoExt, Function? onProgress, String destDir, | //     String url, String fileNameNoExt, Function? onProgress, String destDir, | ||||||
|     {bool useExisting = true, Map<String, String>? headers}) async { | //     {bool useExisting = true, Map<String, String>? headers}) async { | ||||||
|   var req = Request('GET', Uri.parse(url)); | //   var resHead = await dio.head(url); | ||||||
|   if (headers != null) { | //   String ext = | ||||||
|     req.headers.addAll(headers); | //       resHead.headers.map['content-disposition']?[0].split('.').last ?? 'apk'; | ||||||
|   } | //   if (ext.endsWith('"') || ext.endsWith("other")) { | ||||||
|   var client = http.Client(); | //     ext = ext.substring(0, ext.length - 1); | ||||||
|   StreamedResponse response = await client.send(req); | //   } | ||||||
|   String ext = | //   if (url.toLowerCase().endsWith('.apk') && ext != 'apk') { | ||||||
|       response.headers['content-disposition']?.split('.').last ?? 'apk'; | //     ext = 'apk'; | ||||||
|   if (ext.endsWith('"') || ext.endsWith("other")) { | //   } | ||||||
|     ext = ext.substring(0, ext.length - 1); | //   File downloadedFile = File('$destDir/$fileNameNoExt.$ext'); | ||||||
|   } | //   if (!(downloadedFile.existsSync() && useExisting)) { | ||||||
|   if (url.toLowerCase().endsWith('.apk') && ext != 'apk') { | //     double? progress; | ||||||
|     ext = 'apk'; | //     var response = await dio.download( | ||||||
|   } | //       url, | ||||||
|   File downloadedFile = File('$destDir/$fileNameNoExt.$ext'); | //       downloadedFile.path, | ||||||
|   if (!(downloadedFile.existsSync() && useExisting)) { | //       options: Options(headers: headers), | ||||||
|     File tempDownloadedFile = File('${downloadedFile.path}.part'); | //       onReceiveProgress: (count, total) { | ||||||
|     if (tempDownloadedFile.existsSync()) { | //         progress = (total > 0 ? count / total * 100 : 30); | ||||||
|       tempDownloadedFile.deleteSync(recursive: true); | //         if (onProgress != null) { | ||||||
|     } | //           onProgress(progress); | ||||||
|     var length = response.contentLength; | //         } | ||||||
|     var received = 0; | //       }, | ||||||
|     double? progress; | //     ); | ||||||
|     var sink = tempDownloadedFile.openWrite(); | //     if (onProgress != null) { | ||||||
|     await response.stream.map((s) { | //       onProgress(null); | ||||||
|       received += s.length; | //     } | ||||||
|       progress = (length != null ? received / length * 100 : 30); | //     if (response.statusCode != 200) { | ||||||
|       if (onProgress != null) { | //       throw response.statusMessage ?? tr('unexpectedError'); | ||||||
|         onProgress(progress); | //     } | ||||||
|       } | //   } | ||||||
|       return s; | //   return downloadedFile; | ||||||
|     }).pipe(sink); | // } | ||||||
|     await sink.close(); |  | ||||||
|     progress = null; |  | ||||||
|     if (onProgress != null) { |  | ||||||
|       onProgress(progress); |  | ||||||
|     } |  | ||||||
|     if (response.statusCode != 200) { |  | ||||||
|       tempDownloadedFile.deleteSync(recursive: true); |  | ||||||
|       throw response.reasonPhrase ?? tr('unexpectedError'); |  | ||||||
|     } |  | ||||||
|     if (tempDownloadedFile.existsSync()) { |  | ||||||
|       tempDownloadedFile.renameSync(downloadedFile.path); |  | ||||||
|     } |  | ||||||
|   } else { |  | ||||||
|     client.close(); |  | ||||||
|   } |  | ||||||
|   return downloadedFile; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| Future<PackageInfo?> getInstalledInfo(String? packageName, | Future<PackageInfo?> getInstalledInfo(String? packageName, | ||||||
|     {bool printErr = true}) async { |     {bool printErr = true}) async { | ||||||
| @@ -1621,7 +1757,7 @@ Future<void> bgUpdateCheck(String taskId, Map<String, dynamic>? params) async { | |||||||
|             // Next task interval is based on the error with the longest retry time |             // Next task interval is based on the error with the longest retry time | ||||||
|             int minRetryIntervalForThisApp = err is RateLimitError |             int minRetryIntervalForThisApp = err is RateLimitError | ||||||
|                 ? (err.remainingMinutes * 60) |                 ? (err.remainingMinutes * 60) | ||||||
|                 : e is ClientException |                 : e is DioException | ||||||
|                     ? (15 * 60) |                     ? (15 * 60) | ||||||
|                     : (toCheckApp.value + 1); |                     : (toCheckApp.value + 1); | ||||||
|             if (minRetryIntervalForThisApp > maxRetryWaitSeconds) { |             if (minRetryIntervalForThisApp > maxRetryWaitSeconds) { | ||||||
|   | |||||||
| @@ -4,9 +4,9 @@ | |||||||
| import 'dart:convert'; | import 'dart:convert'; | ||||||
|  |  | ||||||
| import 'package:device_info_plus/device_info_plus.dart'; | import 'package:device_info_plus/device_info_plus.dart'; | ||||||
|  | import 'package:dio/dio.dart'; | ||||||
| import 'package:easy_localization/easy_localization.dart'; | import 'package:easy_localization/easy_localization.dart'; | ||||||
| import 'package:html/dom.dart'; | import 'package:html/dom.dart'; | ||||||
| import 'package:http/http.dart'; |  | ||||||
| import 'package:obtainium/app_sources/apkmirror.dart'; | import 'package:obtainium/app_sources/apkmirror.dart'; | ||||||
| import 'package:obtainium/app_sources/apkpure.dart'; | import 'package:obtainium/app_sources/apkpure.dart'; | ||||||
| import 'package:obtainium/app_sources/aptoide.dart'; | import 'package:obtainium/app_sources/aptoide.dart'; | ||||||
| @@ -31,6 +31,7 @@ import 'package:obtainium/app_sources/vlc.dart'; | |||||||
| import 'package:obtainium/app_sources/whatsapp.dart'; | import 'package:obtainium/app_sources/whatsapp.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/main.dart'; | ||||||
| import 'package:obtainium/mass_app_sources/githubstars.dart'; | import 'package:obtainium/mass_app_sources/githubstars.dart'; | ||||||
| import 'package:obtainium/providers/settings_provider.dart'; | import 'package:obtainium/providers/settings_provider.dart'; | ||||||
|  |  | ||||||
| @@ -442,16 +443,9 @@ abstract class AppSource { | |||||||
|       String url, Map<String, dynamic> additionalSettings, |       String url, Map<String, dynamic> additionalSettings, | ||||||
|       {bool followRedirects = true}) async { |       {bool followRedirects = true}) async { | ||||||
|     var requestHeaders = await getRequestHeaders(additionalSettings); |     var requestHeaders = await getRequestHeaders(additionalSettings); | ||||||
|     if (requestHeaders != null || followRedirects == false) { |     return await dio.get(url, | ||||||
|       var req = Request('GET', Uri.parse(url)); |         options: | ||||||
|       req.followRedirects = followRedirects; |             Options(headers: requestHeaders, followRedirects: followRedirects)); | ||||||
|       if (requestHeaders != null) { |  | ||||||
|         req.headers.addAll(requestHeaders); |  | ||||||
|       } |  | ||||||
|       return Response.fromStream(await Client().send(req)); |  | ||||||
|     } else { |  | ||||||
|       return get(Uri.parse(url)); |  | ||||||
|     } |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   String sourceSpecificStandardizeURL(String url) { |   String sourceSpecificStandardizeURL(String url) { | ||||||
| @@ -618,10 +612,10 @@ abstract class AppSource { | |||||||
| } | } | ||||||
|  |  | ||||||
| ObtainiumError getObtainiumHttpError(Response res) { | ObtainiumError getObtainiumHttpError(Response res) { | ||||||
|   return ObtainiumError((res.reasonPhrase != null && |   return ObtainiumError((res.statusMessage != null && | ||||||
|           res.reasonPhrase != null && |           res.statusMessage != null && | ||||||
|           res.reasonPhrase!.isNotEmpty) |           res.statusMessage!.isNotEmpty) | ||||||
|       ? res.reasonPhrase! |       ? res.statusMessage! | ||||||
|       : tr('errorWithHttpStatusCode', args: [res.statusCode.toString()])); |       : tr('errorWithHttpStatusCode', args: [res.statusCode.toString()])); | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -202,6 +202,14 @@ packages: | |||||||
|       url: "https://pub.dev" |       url: "https://pub.dev" | ||||||
|     source: hosted |     source: hosted | ||||||
|     version: "7.0.0" |     version: "7.0.0" | ||||||
|  |   dio: | ||||||
|  |     dependency: "direct main" | ||||||
|  |     description: | ||||||
|  |       name: dio | ||||||
|  |       sha256: "49af28382aefc53562459104f64d16b9dfd1e8ef68c862d5af436cc8356ce5a8" | ||||||
|  |       url: "https://pub.dev" | ||||||
|  |     source: hosted | ||||||
|  |     version: "5.4.1" | ||||||
|   dynamic_color: |   dynamic_color: | ||||||
|     dependency: "direct main" |     dependency: "direct main" | ||||||
|     description: |     description: | ||||||
|   | |||||||
| @@ -68,6 +68,7 @@ dependencies: | |||||||
|   crypto: ^3.0.3 |   crypto: ^3.0.3 | ||||||
|   app_links: ^3.5.0 |   app_links: ^3.5.0 | ||||||
|   background_fetch: ^1.2.1 |   background_fetch: ^1.2.1 | ||||||
|  |   dio: ^5.4.1 | ||||||
|  |  | ||||||
| dev_dependencies: | dev_dependencies: | ||||||
|   flutter_test: |   flutter_test: | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user