diff --git a/lib/app_sources/whatsapp.dart b/lib/app_sources/whatsapp.dart new file mode 100644 index 0000000..6d08549 --- /dev/null +++ b/lib/app_sources/whatsapp.dart @@ -0,0 +1,75 @@ +import 'package:html/parser.dart'; +import 'package:http/http.dart'; +import 'package:obtainium/custom_errors.dart'; +import 'package:obtainium/providers/source_provider.dart'; + +class WhatsApp extends AppSource { + WhatsApp() { + host = 'whatsapp.com'; + } + + @override + String standardizeURL(String url) { + return 'https://$host'; + } + + @override + Future apkUrlPrefetchModifier(String apkUrl) async { + Response res = await get(Uri.parse('https://www.whatsapp.com/android')); + if (res.statusCode == 200) { + var targetLinks = parse(res.body) + .querySelectorAll('a') + .map((e) => e.attributes['href']) + .where((e) => e != null) + .where((e) => + e!.contains('scontent.whatsapp.net') && + e.contains('WhatsApp.apk')) + .toList(); + if (targetLinks.isEmpty) { + throw NoAPKError(); + } + return targetLinks[0]!; + } else { + throw getObtainiumHttpError(res); + } + } + + @override + Future getLatestAPKDetails( + String standardUrl, + Map additionalSettings, + ) async { + Response res = await get(Uri.parse('https://www.whatsapp.com/android')); + if (res.statusCode == 200) { + var targetElements = parse(res.body) + .querySelectorAll('p') + .where((element) => element.innerHtml.contains('Version ')) + .toList(); + if (targetElements.isEmpty) { + throw NoVersionError(); + } + var vLines = targetElements[0] + .innerHtml + .split('\n') + .where((element) => element.contains('Version ')) + .toList(); + if (vLines.isEmpty) { + throw NoVersionError(); + } + var versionMatch = RegExp('[0-9]+(\\.[0-9]+)+').firstMatch(vLines[0]); + if (versionMatch == null) { + throw NoVersionError(); + } + String version = + vLines[0].substring(versionMatch.start, versionMatch.end); + return APKDetails( + version, + [ + 'https://www.whatsapp.com/android?v=$version&=thisIsaPlaceholder&a=realURLPrefetchedAtDownloadTime' + ], + AppNames('Meta', 'WhatsApp')); + } else { + throw getObtainiumHttpError(res); + } + } +} diff --git a/lib/providers/source_provider.dart b/lib/providers/source_provider.dart index 1b19c19..0f3eb16 100644 --- a/lib/providers/source_provider.dart +++ b/lib/providers/source_provider.dart @@ -21,6 +21,7 @@ import 'package:obtainium/app_sources/sourceforge.dart'; import 'package:obtainium/app_sources/steammobile.dart'; import 'package:obtainium/app_sources/telegramapp.dart'; import 'package:obtainium/app_sources/vlc.dart'; +import 'package:obtainium/app_sources/whatsapp.dart'; import 'package:obtainium/components/generated_form.dart'; import 'package:obtainium/custom_errors.dart'; import 'package:obtainium/mass_app_sources/githubstars.dart'; @@ -342,14 +343,15 @@ class SourceProvider { Codeberg(), FDroid(), IzzyOnDroid(), - Mullvad(), - Signal(), + FDroidRepo(), SourceForge(), APKMirror(), - FDroidRepo(), - SteamMobile(), - TelegramApp(), + Mullvad(), + Signal(), VLC(), + // WhatsApp(), // As of 2023-03-20 this is unusable as the version on the webpage is months out of date + TelegramApp(), + SteamMobile(), NeutronCode(), HTML() // This should ALWAYS be the last option as they are tried in order ];