diff --git a/README.md b/README.md index 2b4b120..ddd731b 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,7 @@ Currently supported App sources: - Third Party F-Droid Repos - Any URLs ending with `/fdroid/`, where `` can be anything - most often `repo` - [Steam](https://store.steampowered.com/mobile) +- [Neutron Code](https://neutroncode.com) - "HTML" (Fallback) - Any other URL that returns an HTML page with links to APK files (if multiple, the last file alphabetically is picked) diff --git a/lib/app_sources/neutroncode.dart b/lib/app_sources/neutroncode.dart new file mode 100644 index 0000000..6baa0a1 --- /dev/null +++ b/lib/app_sources/neutroncode.dart @@ -0,0 +1,108 @@ +import 'package:html/parser.dart'; +import 'package:http/http.dart'; +import 'package:obtainium/custom_errors.dart'; +import 'package:obtainium/providers/source_provider.dart'; + +class NeutronCode extends AppSource { + NeutronCode() { + host = 'neutroncode.com'; + } + + @override + String standardizeURL(String url) { + RegExp standardUrlRegEx = RegExp('^https?://$host/downloads/file/[^/]+'); + RegExpMatch? match = standardUrlRegEx.firstMatch(url.toLowerCase()); + if (match == null) { + throw InvalidURLError(name); + } + return url.substring(0, match.end); + } + + @override + String? changeLogPageFromStandardUrl(String standardUrl) => standardUrl; + + String monthNameToNumberString(String s) { + switch (s.toLowerCase()) { + case 'january': + return '01'; + case 'february': + return '02'; + case 'march': + return '03'; + case 'april': + return '04'; + case 'may': + return '05'; + case 'june': + return '06'; + case 'july': + return '07'; + case 'august': + return '08'; + case 'september': + return '09'; + case 'october': + return '10'; + case 'november': + return '11'; + case 'december': + return '12'; + default: + throw ArgumentError('Invalid month name: $s'); + } + } + + customDateParse(String dateString) { + List parts = dateString.split(' '); + if (parts.length != 3) { + return null; + } + String result = ''; + for (var s in parts.reversed) { + try { + try { + int.parse(s); + result += '$s-'; + } catch (e) { + result += '${monthNameToNumberString(s)}-'; + } + } catch (e) { + return null; + } + } + return result.substring(0, result.length - 1); + } + + @override + Future getLatestAPKDetails( + String standardUrl, + Map additionalSettings, + ) async { + Response res = await get(Uri.parse(standardUrl)); + if (res.statusCode == 200) { + var http = parse(res.body); + var name = http.querySelector('.pd-title')?.innerHtml; + var filename = http.querySelector('.pd-filename .pd-float')?.innerHtml; + if (filename == null) { + throw NoReleasesError(); + } + var version = + http.querySelector('.pd-version-txt')?.nextElementSibling?.innerHtml; + if (version == null) { + throw NoVersionError(); + } + String? apkUrl = 'https://$host/download/$filename'; + var dateStringOriginal = + http.querySelector('.pd-date-txt')?.nextElementSibling?.innerHtml; + var dateString = dateStringOriginal != null + ? (customDateParse(dateStringOriginal)) + : null; + + return APKDetails(version, [apkUrl], + AppNames(runtimeType.toString(), name ?? standardUrl.split('/').last), + releaseDate: dateString != null ? DateTime.parse(dateString) : null); + } else { + throw getObtainiumHttpError(res); + } + } +} diff --git a/lib/app_sources/telegramapp.dart b/lib/app_sources/telegramapp.dart new file mode 100644 index 0000000..6b249fd --- /dev/null +++ b/lib/app_sources/telegramapp.dart @@ -0,0 +1,43 @@ +import 'package:easy_localization/easy_localization.dart'; +import 'package:html/parser.dart'; +import 'package:http/http.dart'; +import 'package:obtainium/custom_errors.dart'; +import 'package:obtainium/providers/source_provider.dart'; + +class TelegramApp extends AppSource { + TelegramApp() { + host = 'telegram.org'; + name = 'Telegram ${tr('app')}'; + } + + @override + String standardizeURL(String url) { + return 'https://$host'; + } + + @override + String? changeLogPageFromStandardUrl(String standardUrl) => null; + + @override + Future getLatestAPKDetails( + String standardUrl, + Map additionalSettings, + ) async { + Response res = await get(Uri.parse('https://t.me/s/TAndroidAPK')); + if (res.statusCode == 200) { + var http = parse(res.body); + var messages = + http.querySelectorAll('.tgme_widget_message_text.js-message_text'); + var version = messages.isNotEmpty + ? messages.last.innerHtml.split('\n').first.trim().split(' ').first + : null; + if (version == null) { + throw NoVersionError(); + } + String? apkUrl = 'https://telegram.org/dl/android/apk'; + return APKDetails(version, [apkUrl], AppNames('Telegram', 'Telegram')); + } else { + throw getObtainiumHttpError(res); + } + } +} diff --git a/lib/main.dart b/lib/main.dart index 3843c79..5e49a1a 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -21,7 +21,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.11.9'; +const String currentVersion = '0.11.10'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index b79b89e..dc4f9c0 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -145,6 +145,9 @@ class AppsProvider with ChangeNotifier { } Future downloadApp(App app, BuildContext? context) async { + NotificationsProvider? notificationsProvider = + context?.read(); + var notifId = DownloadNotification(app.name, 0).id; if (apps[app.id] != null) { apps[app.id]!.downloadProgress = 0; notifyListeners(); @@ -155,8 +158,6 @@ class AppsProvider with ChangeNotifier { String downloadUrl = await SourceProvider() .getSource(app.url) .apkUrlPrefetchModifier(app.apkUrls[app.preferredApkIndex]); - NotificationsProvider? notificationsProvider = - context?.read(); var notif = DownloadNotification(app.name, 100); notificationsProvider?.cancel(notif.id); int? prevProg; @@ -173,7 +174,6 @@ class AppsProvider with ChangeNotifier { } prevProg = prog; }); - notificationsProvider?.cancel(notif.id); // Delete older versions of the APK if any for (var file in downloadedFile.parent.listSync()) { var fn = file.path.split('/').last; @@ -201,6 +201,7 @@ class AppsProvider with ChangeNotifier { } return DownloadedApk(app.id, downloadedFile); } finally { + notificationsProvider?.cancel(notifId); if (apps[app.id] != null) { apps[app.id]!.downloadProgress = null; notifyListeners(); diff --git a/lib/providers/source_provider.dart b/lib/providers/source_provider.dart index 8cead1e..f2b7afd 100644 --- a/lib/providers/source_provider.dart +++ b/lib/providers/source_provider.dart @@ -15,9 +15,11 @@ import 'package:obtainium/app_sources/gitlab.dart'; import 'package:obtainium/app_sources/izzyondroid.dart'; import 'package:obtainium/app_sources/html.dart'; import 'package:obtainium/app_sources/mullvad.dart'; +import 'package:obtainium/app_sources/neutroncode.dart'; import 'package:obtainium/app_sources/signal.dart'; import 'package:obtainium/app_sources/sourceforge.dart'; import 'package:obtainium/app_sources/steammobile.dart'; +import 'package:obtainium/app_sources/telegramapp.dart'; import 'package:obtainium/components/generated_form.dart'; import 'package:obtainium/custom_errors.dart'; import 'package:obtainium/mass_app_sources/githubstars.dart'; @@ -338,6 +340,8 @@ class SourceProvider { APKMirror(), FDroidRepo(), SteamMobile(), + TelegramApp(), + NeutronCode(), HTML() // This should ALWAYS be the last option as they are tried in order ]; diff --git a/pubspec.yaml b/pubspec.yaml index 6962da3..f3871a6 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -17,7 +17,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 0.11.9+130 # When changing this, update the tag in main() accordingly +version: 0.11.10+131 # When changing this, update the tag in main() accordingly environment: sdk: '>=2.18.2 <3.0.0'