Header usage bugfix

This commit is contained in:
Imran Remtulla
2024-01-11 19:23:59 -05:00
parent 7a03561ff6
commit 76a6a509cd
25 changed files with 118 additions and 90 deletions

View File

@@ -27,8 +27,8 @@ class APKCombo extends AppSource {
@override @override
Future<Map<String, String>?> getRequestHeaders( Future<Map<String, String>?> getRequestHeaders(
{Map<String, dynamic> additionalSettings = const <String, dynamic>{}, Map<String, dynamic> additionalSettings,
bool forAPKDownload = false}) async { {bool forAPKDownload = false}) async {
return { return {
"User-Agent": "curl/8.0.1", "User-Agent": "curl/8.0.1",
"Accept": "*/*", "Accept": "*/*",
@@ -37,8 +37,9 @@ class APKCombo extends AppSource {
}; };
} }
Future<List<MapEntry<String, String>>> getApkUrls(String standardUrl) async { Future<List<MapEntry<String, String>>> getApkUrls(
var res = await sourceRequest('$standardUrl/download/apk'); String standardUrl, Map<String, dynamic> additionalSettings) async {
var res = await sourceRequest('$standardUrl/download/apk', {});
if (res.statusCode != 200) { if (res.statusCode != 200) {
throw getObtainiumHttpError(res); throw getObtainiumHttpError(res);
} }
@@ -71,9 +72,9 @@ class APKCombo extends AppSource {
} }
@override @override
Future<String> apkUrlPrefetchModifier( Future<String> apkUrlPrefetchModifier(String apkUrl, String standardUrl,
String apkUrl, String standardUrl) async { Map<String, dynamic> additionalSettings) async {
var freshURLs = await getApkUrls(standardUrl); var freshURLs = await getApkUrls(standardUrl, additionalSettings);
var path2Match = Uri.parse(apkUrl).path; var path2Match = Uri.parse(apkUrl).path;
for (var url in freshURLs) { for (var url in freshURLs) {
if (Uri.parse(url.value).path == path2Match) { if (Uri.parse(url.value).path == path2Match) {
@@ -89,7 +90,7 @@ class APKCombo extends AppSource {
Map<String, dynamic> additionalSettings, Map<String, dynamic> additionalSettings,
) async { ) async {
String appId = (await tryInferringAppId(standardUrl))!; String appId = (await tryInferringAppId(standardUrl))!;
var preres = await sourceRequest(standardUrl); var preres = await sourceRequest(standardUrl, additionalSettings);
if (preres.statusCode != 200) { if (preres.statusCode != 200) {
throw getObtainiumHttpError(preres); throw getObtainiumHttpError(preres);
} }
@@ -113,7 +114,9 @@ class APKCombo extends AppSource {
} }
} }
return APKDetails( return APKDetails(
version, await getApkUrls(standardUrl), AppNames(author, appName), version,
await getApkUrls(standardUrl, additionalSettings),
AppNames(author, appName),
releaseDate: releaseDate); releaseDate: releaseDate);
} }
} }

View File

@@ -58,7 +58,7 @@ class APKMirror extends AppSource {
true true
? additionalSettings['filterReleaseTitlesByRegEx'] ? additionalSettings['filterReleaseTitlesByRegEx']
: null; : null;
Response res = await sourceRequest('$standardUrl/feed'); 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.body).querySelectorAll('item');
dynamic targetRelease; dynamic targetRelease;

View File

@@ -55,8 +55,8 @@ class APKPure extends AppSource {
) async { ) async {
String appId = (await tryInferringAppId(standardUrl))!; String appId = (await tryInferringAppId(standardUrl))!;
String host = Uri.parse(standardUrl).host; String host = Uri.parse(standardUrl).host;
var res = await sourceRequest('$standardUrl/download'); var res = await sourceRequest('$standardUrl/download', additionalSettings);
var resChangelog = await sourceRequest(standardUrl); 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.body);
var htmlChangelog = parse(resChangelog.body); var htmlChangelog = parse(resChangelog.body);

View File

@@ -26,11 +26,13 @@ class Aptoide extends AppSource {
@override @override
Future<String?> tryInferringAppId(String standardUrl, Future<String?> tryInferringAppId(String standardUrl,
{Map<String, dynamic> additionalSettings = const {}}) async { {Map<String, dynamic> additionalSettings = const {}}) async {
return (await getAppDetailsJSON(standardUrl))['package']; return (await getAppDetailsJSON(
standardUrl, additionalSettings))['package'];
} }
Future<Map<String, dynamic>> getAppDetailsJSON(String standardUrl) async { Future<Map<String, dynamic>> getAppDetailsJSON(
var res = await sourceRequest(standardUrl); String standardUrl, Map<String, dynamic> additionalSettings) async {
var res = await sourceRequest(standardUrl, additionalSettings);
if (res.statusCode != 200) { if (res.statusCode != 200) {
throw getObtainiumHttpError(res); throw getObtainiumHttpError(res);
} }
@@ -41,8 +43,8 @@ class Aptoide extends AppSource {
} else { } else {
throw NoReleasesError(); throw NoReleasesError();
} }
var res2 = var res2 = await sourceRequest(
await sourceRequest('https://ws2.aptoide.com/api/7/getApp/app_id/$id'); 'https://ws2.aptoide.com/api/7/getApp/app_id/$id', additionalSettings);
if (res2.statusCode != 200) { if (res2.statusCode != 200) {
throw getObtainiumHttpError(res); throw getObtainiumHttpError(res);
} }
@@ -54,7 +56,7 @@ class Aptoide extends AppSource {
String standardUrl, String standardUrl,
Map<String, dynamic> additionalSettings, Map<String, dynamic> additionalSettings,
) async { ) async {
var appDetails = await getAppDetailsJSON(standardUrl); var appDetails = await getAppDetailsJSON(standardUrl, additionalSettings);
String appName = appDetails['name'] ?? tr('app'); String appName = appDetails['name'] ?? tr('app');
String author = appDetails['developer']?['name'] ?? name; String author = appDetails['developer']?['name'] ?? name;
String? dateStr = appDetails['updated']; String? dateStr = appDetails['updated'];

View File

@@ -67,7 +67,8 @@ class FDroid extends AppSource {
String? appId = await tryInferringAppId(standardUrl); String? appId = await tryInferringAppId(standardUrl);
String host = Uri.parse(standardUrl).host; String host = Uri.parse(standardUrl).host;
var details = getAPKUrlsFromFDroidPackagesAPIResponse( var details = getAPKUrlsFromFDroidPackagesAPIResponse(
await sourceRequest('https://$host/api/v1/packages/$appId'), await sourceRequest(
'https://$host/api/v1/packages/$appId', additionalSettings),
'https://$host/repo/$appId', 'https://$host/repo/$appId',
standardUrl, standardUrl,
name, name,
@@ -84,7 +85,8 @@ class FDroid extends AppSource {
if (!hostChanged) { if (!hostChanged) {
try { try {
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);
var lines = res.body.split('\n'); var lines = res.body.split('\n');
var authorLines = lines.where((l) => l.startsWith('AuthorName: ')); var authorLines = lines.where((l) => l.startsWith('AuthorName: '));
if (authorLines.isNotEmpty) { if (authorLines.isNotEmpty) {
@@ -94,11 +96,13 @@ class FDroid extends AppSource {
var changelogUrls = lines.where((l) => l.startsWith('Changelog: ')); var changelogUrls = lines.where((l) => l.startsWith('Changelog: '));
if (changelogUrls.isNotEmpty) { if (changelogUrls.isNotEmpty) {
details.changeLog = changelogUrls.first; details.changeLog = changelogUrls.first;
details.changeLog = (await sourceRequest(details.changeLog! details.changeLog = (await sourceRequest(
.split(': ') details.changeLog!
.sublist(1) .split(': ')
.join(': ') .sublist(1)
.replaceFirst('/blob/', '/raw/'))) .join(': ')
.replaceFirst('/blob/', '/raw/'),
additionalSettings))
.body; .body;
} }
} catch (e) { } catch (e) {
@@ -115,7 +119,7 @@ class FDroid extends AppSource {
Future<Map<String, List<String>>> search(String query, Future<Map<String, List<String>>> search(String query,
{Map<String, dynamic> querySettings = const {}}) async { {Map<String, dynamic> querySettings = const {}}) async {
Response res = await sourceRequest( Response res = await sourceRequest(
'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.body).querySelectorAll('.package-header').forEach((e) {

View File

@@ -59,7 +59,7 @@ class FDroidRepo extends AppSource {
throw NoReleasesError(); throw NoReleasesError();
} }
url = removeQueryParamsFromUrl(standardizeUrl(url)); url = removeQueryParamsFromUrl(standardizeUrl(url));
var res = await sourceRequest('$url/index.xml'); var res = await sourceRequest('$url/index.xml', {});
if (res.statusCode == 200) { if (res.statusCode == 200) {
var body = parse(res.body); var body = parse(res.body);
Map<String, List<String>> results = {}; Map<String, List<String>> results = {};
@@ -117,7 +117,8 @@ class FDroidRepo extends AppSource {
throw NoReleasesError(); throw NoReleasesError();
} }
var res = await sourceRequest( var res = await sourceRequest(
'$standardUrl${standardUrl.endsWith('/index.xml') ? '' : '/index.xml'}'); '$standardUrl${standardUrl.endsWith('/index.xml') ? '' : '/index.xml'}',
additionalSettings);
if (res.statusCode == 200) { if (res.statusCode == 200) {
var body = parse(res.body); var body = parse(res.body);
var foundApps = body.querySelectorAll('application').where((element) { var foundApps = body.querySelectorAll('application').where((element) {

View File

@@ -108,7 +108,8 @@ class GitHub extends AppSource {
for (var path in possibleBuildGradleLocations) { for (var path in possibleBuildGradleLocations) {
try { try {
var res = await sourceRequest( var res = await sourceRequest(
'${await convertStandardUrlToAPIUrl(standardUrl, additionalSettings)}/contents/$path'); '${await convertStandardUrlToAPIUrl(standardUrl, additionalSettings)}/contents/$path',
additionalSettings);
if (res.statusCode == 200) { if (res.statusCode == 200) {
try { try {
var body = jsonDecode(res.body); var body = jsonDecode(res.body);
@@ -160,8 +161,8 @@ class GitHub extends AppSource {
@override @override
Future<Map<String, String>?> getRequestHeaders( Future<Map<String, String>?> getRequestHeaders(
{Map<String, dynamic> additionalSettings = const <String, dynamic>{}, Map<String, dynamic> additionalSettings,
bool forAPKDownload = false}) async { {bool forAPKDownload = false}) async {
var token = await getTokenIfAny(additionalSettings); var token = await getTokenIfAny(additionalSettings);
var headers = <String, String>{}; var headers = <String, String>{};
if (token != null) { if (token != null) {
@@ -239,7 +240,8 @@ class GitHub extends AppSource {
if (verifyLatestTag) { if (verifyLatestTag) {
var temp = requestUrl.split('?'); var temp = requestUrl.split('?');
Response res = await sourceRequest( Response res = await sourceRequest(
'${temp[0]}/latest${temp.length > 1 ? '?${temp.sublist(1).join('?')}' : ''}'); '${temp[0]}/latest${temp.length > 1 ? '?${temp.sublist(1).join('?')}' : ''}',
additionalSettings);
if (res.statusCode != 200) { if (res.statusCode != 200) {
if (onHttpErrorCode != null) { if (onHttpErrorCode != null) {
onHttpErrorCode(res); onHttpErrorCode(res);
@@ -248,7 +250,7 @@ class GitHub extends AppSource {
} }
latestRelease = jsonDecode(res.body); latestRelease = jsonDecode(res.body);
} }
Response res = await sourceRequest(requestUrl); 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.body) as List<dynamic>;
if (latestRelease != null) { if (latestRelease != null) {
@@ -425,7 +427,7 @@ class GitHub extends AppSource {
String query, String requestUrl, String rootProp, String query, String requestUrl, String rootProp,
{Function(Response)? onHttpErrorCode, {Function(Response)? onHttpErrorCode,
Map<String, dynamic> querySettings = const {}}) async { Map<String, dynamic> querySettings = const {}}) async {
Response res = await sourceRequest(requestUrl); Response res = await sourceRequest(requestUrl, {});
if (res.statusCode == 200) { if (res.statusCode == 200) {
int minStarCount = querySettings['minStarCount'] != null int minStarCount = querySettings['minStarCount'] != null
? int.parse(querySettings['minStarCount']) ? int.parse(querySettings['minStarCount'])

View File

@@ -83,7 +83,7 @@ class GitLab extends AppSource {
{Map<String, dynamic> querySettings = const {}}) async { {Map<String, dynamic> querySettings = const {}}) async {
var url = var url =
'https://${hosts[0]}/api/v4/projects?search=${Uri.encodeQueryComponent(query)}'; 'https://${hosts[0]}/api/v4/projects?search=${Uri.encodeQueryComponent(query)}';
var res = await sourceRequest(url); var res = await sourceRequest(url, {});
if (res.statusCode != 200) { if (res.statusCode != 200) {
throw getObtainiumHttpError(res); throw getObtainiumHttpError(res);
} }
@@ -114,7 +114,8 @@ class GitLab extends AppSource {
if (PAT != null) { if (PAT != null) {
var names = GitHub().getAppNames(standardUrl); var names = GitHub().getAppNames(standardUrl);
Response res = await sourceRequest( 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?private_token=$PAT',
additionalSettings);
if (res.statusCode != 200) { if (res.statusCode != 200) {
throw getObtainiumHttpError(res); throw getObtainiumHttpError(res);
} }
@@ -149,7 +150,8 @@ class GitLab extends AppSource {
releaseDate: releaseDate); releaseDate: releaseDate);
}); });
} else { } else {
Response res = await sourceRequest('$standardUrl/-/tags?format=atom'); Response res = await sourceRequest(
'$standardUrl/-/tags?format=atom', additionalSettings);
if (res.statusCode != 200) { if (res.statusCode != 200) {
throw getObtainiumHttpError(res); throw getObtainiumHttpError(res);
} }

View File

@@ -179,8 +179,8 @@ class HTML extends AppSource {
@override @override
Future<Map<String, String>?> getRequestHeaders( Future<Map<String, String>?> getRequestHeaders(
{Map<String, dynamic> additionalSettings = const <String, dynamic>{}, Map<String, dynamic> additionalSettings,
bool forAPKDownload = false}) async { {bool forAPKDownload = false}) async {
if (additionalSettings.isNotEmpty) { if (additionalSettings.isNotEmpty) {
if (additionalSettings['requestHeader']?.isNotEmpty != true) { if (additionalSettings['requestHeader']?.isNotEmpty != true) {
additionalSettings['requestHeader'] = []; additionalSettings['requestHeader'] = [];
@@ -278,7 +278,8 @@ class HTML extends AppSource {
.where((l) => l['customLinkFilterRegex'].isNotEmpty == true) .where((l) => l['customLinkFilterRegex'].isNotEmpty == true)
.toList(); .toList();
for (int i = 0; i < (additionalSettings['intermediateLink'].length); i++) { for (int i = 0; i < (additionalSettings['intermediateLink'].length); i++) {
var intLinks = await grabLinksCommon(await sourceRequest(currentUrl), var intLinks = await grabLinksCommon(
await sourceRequest(currentUrl, additionalSettings),
additionalSettings['intermediateLink'][i]); additionalSettings['intermediateLink'][i]);
if (intLinks.isEmpty) { if (intLinks.isEmpty) {
throw NoReleasesError(); throw NoReleasesError();
@@ -288,7 +289,7 @@ class HTML extends AppSource {
} }
var uri = Uri.parse(currentUrl); var uri = Uri.parse(currentUrl);
Response res = await sourceRequest(currentUrl); Response res = await sourceRequest(currentUrl, additionalSettings);
var links = await grabLinksCommon(res, additionalSettings); var links = await grabLinksCommon(res, additionalSettings);
if ((additionalSettings['apkFilterRegEx'] as String?)?.isNotEmpty == true) { if ((additionalSettings['apkFilterRegEx'] as String?)?.isNotEmpty == true) {

View File

@@ -25,8 +25,10 @@ class HuaweiAppGallery extends AppSource {
getDlUrl(String standardUrl) => getDlUrl(String standardUrl) =>
'https://${hosts[0].replaceAll('appgallery.', 'appgallery.cloud.')}/appdl/${standardUrl.split('/').last}'; 'https://${hosts[0].replaceAll('appgallery.', 'appgallery.cloud.')}/appdl/${standardUrl.split('/').last}';
requestAppdlRedirect(String dlUrl) async { requestAppdlRedirect(
Response res = await sourceRequest(dlUrl, followRedirects: false); String dlUrl, Map<String, dynamic> additionalSettings) async {
Response res =
await sourceRequest(dlUrl, additionalSettings, followRedirects: false);
if (res.statusCode == 200 || if (res.statusCode == 200 ||
res.statusCode == 302 || res.statusCode == 302 ||
res.statusCode == 304) { res.statusCode == 304) {
@@ -53,7 +55,7 @@ class HuaweiAppGallery extends AppSource {
Future<String?> tryInferringAppId(String standardUrl, Future<String?> tryInferringAppId(String standardUrl,
{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); Response res = await requestAppdlRedirect(dlUrl, additionalSettings);
return res.headers['location'] != null return res.headers['location'] != null
? appIdFromRedirectDlUrl(res.headers['location']!) ? appIdFromRedirectDlUrl(res.headers['location']!)
: null; : null;
@@ -65,7 +67,7 @@ class HuaweiAppGallery extends AppSource {
Map<String, dynamic> additionalSettings, Map<String, dynamic> additionalSettings,
) async { ) async {
String dlUrl = getDlUrl(standardUrl); String dlUrl = getDlUrl(standardUrl);
Response res = await requestAppdlRedirect(dlUrl); Response res = await requestAppdlRedirect(dlUrl, additionalSettings);
if (res.headers['location'] == null) { if (res.headers['location'] == null) {
throw NoReleasesError(); throw NoReleasesError();
} }

View File

@@ -43,7 +43,8 @@ class IzzyOnDroid extends AppSource {
String? appId = await tryInferringAppId(standardUrl); String? appId = await tryInferringAppId(standardUrl);
return fd.getAPKUrlsFromFDroidPackagesAPIResponse( return fd.getAPKUrlsFromFDroidPackagesAPIResponse(
await sourceRequest( await sourceRequest(
'https://apt.izzysoft.de/fdroid/api/v1/packages/$appId'), 'https://apt.izzysoft.de/fdroid/api/v1/packages/$appId',
additionalSettings),
'https://android.izzysoft.de/frepo/$appId', 'https://android.izzysoft.de/frepo/$appId',
standardUrl, standardUrl,
name, name,

View File

@@ -29,8 +29,8 @@ class Jenkins extends AppSource {
Map<String, dynamic> additionalSettings, Map<String, dynamic> additionalSettings,
) async { ) async {
standardUrl = trimJobUrl(standardUrl); standardUrl = trimJobUrl(standardUrl);
Response res = Response res = await sourceRequest(
await sourceRequest('$standardUrl/lastSuccessfulBuild/api/json'); '$standardUrl/lastSuccessfulBuild/api/json', additionalSettings);
if (res.statusCode == 200) { if (res.statusCode == 200) {
var json = jsonDecode(res.body); var json = jsonDecode(res.body);
var releaseDate = json['timestamp'] == null var releaseDate = json['timestamp'] == null

View File

@@ -29,7 +29,8 @@ class Mullvad extends AppSource {
String standardUrl, String standardUrl,
Map<String, dynamic> additionalSettings, Map<String, dynamic> additionalSettings,
) async { ) async {
Response res = await sourceRequest('$standardUrl/en/download/android'); Response res = await sourceRequest(
'$standardUrl/en/download/android', additionalSettings);
if (res.statusCode == 200) { if (res.statusCode == 200) {
var versions = parse(res.body) var versions = parse(res.body)
.querySelectorAll('p') .querySelectorAll('p')

View File

@@ -79,7 +79,7 @@ class NeutronCode extends AppSource {
String standardUrl, String standardUrl,
Map<String, dynamic> additionalSettings, Map<String, dynamic> additionalSettings,
) async { ) async {
Response res = await sourceRequest(standardUrl); Response res = await sourceRequest(standardUrl, additionalSettings);
if (res.statusCode == 200) { if (res.statusCode == 200) {
var http = parse(res.body); var http = parse(res.body);
var name = http.querySelector('.pd-title')?.innerHtml; var name = http.querySelector('.pd-title')?.innerHtml;

View File

@@ -18,8 +18,8 @@ class Signal extends AppSource {
String standardUrl, String standardUrl,
Map<String, dynamic> additionalSettings, Map<String, dynamic> additionalSettings,
) async { ) async {
Response res = Response res = await sourceRequest(
await sourceRequest('https://updates.${hosts[0]}/android/latest.json'); '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.body);
String? apkUrl = json['url']; String? apkUrl = json['url'];

View File

@@ -31,7 +31,8 @@ class SourceForge extends AppSource {
String standardUrl, String standardUrl,
Map<String, dynamic> additionalSettings, Map<String, dynamic> additionalSettings,
) async { ) async {
Response res = await sourceRequest('$standardUrl/rss?path=/'); Response res =
await sourceRequest('$standardUrl/rss?path=/', additionalSettings);
if (res.statusCode == 200) { if (res.statusCode == 200) {
var parsedHtml = parse(res.body); var parsedHtml = parse(res.body);
var allDownloadLinks = var allDownloadLinks =

View File

@@ -41,7 +41,8 @@ class SourceHut extends AppSource {
String appName = standardUri.pathSegments.last; String appName = standardUri.pathSegments.last;
bool fallbackToOlderReleases = bool fallbackToOlderReleases =
additionalSettings['fallbackToOlderReleases'] == true; additionalSettings['fallbackToOlderReleases'] == true;
Response res = await sourceRequest('$standardUrl/refs/rss.xml'); Response res =
await sourceRequest('$standardUrl/refs/rss.xml', additionalSettings);
if (res.statusCode == 200) { if (res.statusCode == 200) {
var parsedHtml = parse(res.body); var parsedHtml = parse(res.body);
List<APKDetails> apkDetailsList = []; List<APKDetails> apkDetailsList = [];
@@ -70,7 +71,7 @@ class SourceHut extends AppSource {
} catch (e) { } catch (e) {
// ignore // ignore
} }
var res2 = await sourceRequest(releasePage); 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.body)

View File

@@ -29,7 +29,8 @@ class SteamMobile extends AppSource {
String standardUrl, String standardUrl,
Map<String, dynamic> additionalSettings, Map<String, dynamic> additionalSettings,
) async { ) async {
Response res = await sourceRequest('https://${hosts[0]}/mobile'); Response res =
await sourceRequest('https://${hosts[0]}/mobile', additionalSettings);
if (res.statusCode == 200) { if (res.statusCode == 200) {
var apkNamePrefix = additionalSettings['app'] as String?; var apkNamePrefix = additionalSettings['app'] as String?;
if (apkNamePrefix == null) { if (apkNamePrefix == null) {

View File

@@ -20,7 +20,8 @@ class TelegramApp extends AppSource {
String standardUrl, String standardUrl,
Map<String, dynamic> additionalSettings, Map<String, dynamic> additionalSettings,
) async { ) async {
Response res = await sourceRequest('https://t.me/s/TAndroidAPK'); Response res =
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.body);
var messages = var messages =

View File

@@ -25,11 +25,13 @@ class Uptodown extends AppSource {
@override @override
Future<String?> tryInferringAppId(String standardUrl, Future<String?> tryInferringAppId(String standardUrl,
{Map<String, dynamic> additionalSettings = const {}}) async { {Map<String, dynamic> additionalSettings = const {}}) async {
return (await getAppDetailsFromPage(standardUrl))['appId']; return (await getAppDetailsFromPage(
standardUrl, additionalSettings))['appId'];
} }
Future<Map<String, String?>> getAppDetailsFromPage(String standardUrl) async { Future<Map<String, String?>> getAppDetailsFromPage(
var res = await sourceRequest(standardUrl); String standardUrl, Map<String, dynamic> additionalSettings) async {
var res = await sourceRequest(standardUrl, additionalSettings);
if (res.statusCode != 200) { if (res.statusCode != 200) {
throw getObtainiumHttpError(res); throw getObtainiumHttpError(res);
} }
@@ -57,7 +59,8 @@ class Uptodown extends AppSource {
String standardUrl, String standardUrl,
Map<String, dynamic> additionalSettings, Map<String, dynamic> additionalSettings,
) async { ) async {
var appDetails = await getAppDetailsFromPage(standardUrl); var appDetails =
await getAppDetailsFromPage(standardUrl, additionalSettings);
var version = appDetails['version']; var version = appDetails['version'];
var apkUrl = appDetails['apkUrl']; var apkUrl = appDetails['apkUrl'];
var appId = appDetails['appId']; var appId = appDetails['appId'];
@@ -83,9 +86,9 @@ class Uptodown extends AppSource {
} }
@override @override
Future<String> apkUrlPrefetchModifier( Future<String> apkUrlPrefetchModifier(String apkUrl, String standardUrl,
String apkUrl, String standardUrl) async { Map<String, dynamic> additionalSettings) async {
var res = await sourceRequest(apkUrl); var res = await sourceRequest(apkUrl, additionalSettings);
if (res.statusCode != 200) { if (res.statusCode != 200) {
throw getObtainiumHttpError(res); throw getObtainiumHttpError(res);
} }

View File

@@ -12,8 +12,8 @@ class VLC extends AppSource {
@override @override
Future<Map<String, String>?> getRequestHeaders( Future<Map<String, String>?> getRequestHeaders(
{Map<String, dynamic> additionalSettings = const <String, dynamic>{}, Map<String, dynamic> additionalSettings,
bool forAPKDownload = false}) async { {bool forAPKDownload = false}) async {
return { return {
"User-Agent": "User-Agent":
"Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Mobile Safari/537.36" "Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Mobile Safari/537.36"
@@ -25,8 +25,9 @@ class VLC extends AppSource {
return 'https://${hosts[0]}'; return 'https://${hosts[0]}';
} }
Future<String?> getLatestVersion(String standardUrl) async { Future<String?> getLatestVersion(
Response res = await sourceRequest(dwUrlBase); String standardUrl, Map<String, dynamic> additionalSettings) async {
Response res = await sourceRequest(dwUrlBase, additionalSettings);
if (res.statusCode == 200) { if (res.statusCode == 200) {
var dwLinks = parse(res.body) var dwLinks = parse(res.body)
.querySelectorAll('a') .querySelectorAll('a')
@@ -78,9 +79,9 @@ class VLC extends AppSource {
} }
@override @override
Future<String> apkUrlPrefetchModifier( Future<String> apkUrlPrefetchModifier(String apkUrl, String standardUrl,
String apkUrl, String standardUrl) async { Map<String, dynamic> additionalSettings) async {
Response res = await sourceRequest(apkUrl); 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.body).querySelector('#alt_link')?.attributes['href'];

View File

@@ -16,9 +16,10 @@ class WhatsApp extends AppSource {
} }
@override @override
Future<String> apkUrlPrefetchModifier( Future<String> apkUrlPrefetchModifier(String apkUrl, String standardUrl,
String apkUrl, String standardUrl) async { Map<String, dynamic> additionalSettings) async {
Response res = await sourceRequest('$standardUrl/android'); Response res =
await sourceRequest('$standardUrl/android', additionalSettings);
if (res.statusCode == 200) { if (res.statusCode == 200) {
var targetLinks = parse(res.body) var targetLinks = parse(res.body)
.querySelectorAll('a') .querySelectorAll('a')
@@ -42,8 +43,8 @@ class WhatsApp extends AppSource {
) async { ) async {
// This is a CDN link that is consistent per version // This is a CDN link that is consistent per version
// But it has query params that change constantly // But it has query params that change constantly
Uri apkUri = Uri apkUri = Uri.parse(await apkUrlPrefetchModifier(
Uri.parse(await apkUrlPrefetchModifier(standardUrl, standardUrl)); standardUrl, standardUrl, additionalSettings));
var unusableApkUrl = '${apkUri.origin}/${apkUri.path}'; var unusableApkUrl = '${apkUri.origin}/${apkUri.path}';
// So we use the param-less URL is a pseudo-version to add the app and check for updates // So we use the param-less URL is a pseudo-version to add the app and check for updates
// See #357 for why we can't scrape the version number directly // See #357 for why we can't scrape the version number directly

View File

@@ -18,7 +18,7 @@ class GitHubStars implements MassAppUrlSource {
Response res = await get( Response res = await get(
Uri.parse( 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'),
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.body) as List<dynamic>)) {

View File

@@ -326,13 +326,15 @@ class AppsProvider with ChangeNotifier {
AppSource source = SourceProvider() AppSource source = SourceProvider()
.getSource(app.url, overrideSource: app.overrideSource); .getSource(app.url, overrideSource: app.overrideSource);
String downloadUrl = await source.apkUrlPrefetchModifier( String downloadUrl = await source.apkUrlPrefetchModifier(
app.apkUrls[app.preferredApkIndex].value, app.url); app.apkUrls[app.preferredApkIndex].value,
app.url,
app.additionalSettings);
var notif = DownloadNotification(app.finalName, 100); var notif = DownloadNotification(app.finalName, 100);
notificationsProvider?.cancel(notif.id); notificationsProvider?.cancel(notif.id);
int? prevProg; int? prevProg;
var fileNameNoExt = '${app.id}-${downloadUrl.hashCode}'; var fileNameNoExt = '${app.id}-${downloadUrl.hashCode}';
var headers = await source.getRequestHeaders( var headers = await source.getRequestHeaders(app.additionalSettings,
additionalSettings: app.additionalSettings, forAPKDownload: true); forAPKDownload: true);
var downloadedFile = await downloadFileWithRetry( var downloadedFile = await downloadFileWithRetry(
downloadUrl, fileNameNoExt, downloadUrl, fileNameNoExt,
headers: headers, (double? progress) { headers: headers, (double? progress) {

View File

@@ -417,8 +417,8 @@ abstract class AppSource {
} }
Future<Map<String, String>?> getRequestHeaders( Future<Map<String, String>?> getRequestHeaders(
{Map<String, dynamic> additionalSettings = const <String, dynamic>{}, Map<String, dynamic> additionalSettings,
bool forAPKDownload = false}) async { {bool forAPKDownload = false}) async {
return null; return null;
} }
@@ -426,12 +426,10 @@ abstract class AppSource {
return app; return app;
} }
Future<Response> sourceRequest(String url, Future<Response> sourceRequest(
{bool followRedirects = true, String url, Map<String, dynamic> additionalSettings,
Map<String, dynamic> additionalSettings = {bool followRedirects = true}) async {
const <String, dynamic>{}}) async { var requestHeaders = await getRequestHeaders(additionalSettings);
var requestHeaders =
await getRequestHeaders(additionalSettings: additionalSettings);
if (requestHeaders != null || followRedirects == false) { if (requestHeaders != null || followRedirects == false) {
var req = Request('GET', Uri.parse(url)); var req = Request('GET', Uri.parse(url));
req.followRedirects = followRedirects; req.followRedirects = followRedirects;
@@ -548,8 +546,8 @@ abstract class AppSource {
return null; return null;
} }
Future<String> apkUrlPrefetchModifier( Future<String> apkUrlPrefetchModifier(String apkUrl, String standardUrl,
String apkUrl, String standardUrl) async { Map<String, dynamic> additionalSettings) async {
return apkUrl; return apkUrl;
} }