mirror of
https://github.com/ImranR98/Obtainium.git
synced 2025-07-13 21:36:42 +02:00
Compare commits
7 Commits
v0.13.5-be
...
v0.13.6-be
Author | SHA1 | Date | |
---|---|---|---|
6169915e63 | |||
a0d466a074 | |||
6f9ef6d51e | |||
feb4c2eabc | |||
c2cf39125d | |||
833ece1ef5 | |||
fee23cadfa |
@ -233,6 +233,7 @@
|
||||
"about": "Über",
|
||||
"requiresCredentialsInSettings": "Benötigt zusätzliche Anmeldedaten (in den Einstellungen)",
|
||||
"checkOnStart": "Überprüfe einmalig beim Start",
|
||||
"tryInferAppIdFromCode": "Try inferring App ID from source code",
|
||||
"removeAppQuestion": {
|
||||
"one": "App entfernen?",
|
||||
"other": "Apps entfernen?"
|
||||
|
@ -233,6 +233,7 @@
|
||||
"about": "About",
|
||||
"requiresCredentialsInSettings": "This needs additional credentials (in Settings)",
|
||||
"checkOnStart": "Check Once on Start",
|
||||
"tryInferAppIdFromCode": "Try inferring App ID from source code",
|
||||
"removeAppQuestion": {
|
||||
"one": "Remove App?",
|
||||
"other": "Remove Apps?"
|
||||
|
@ -233,6 +233,7 @@
|
||||
"about": "About",
|
||||
"requiresCredentialsInSettings": "This needs additional credentials (in Settings)",
|
||||
"checkOnStart": "Check Once on Start",
|
||||
"tryInferAppIdFromCode": "Try inferring App ID from source code",
|
||||
"removeAppQuestion": {
|
||||
"one": "¿Eliminar Aplicación?",
|
||||
"other": "¿Eliminar Aplicaciones?"
|
||||
|
@ -233,6 +233,7 @@
|
||||
"about": "About",
|
||||
"requiresCredentialsInSettings": "This needs additional credentials (in Settings)",
|
||||
"checkOnStart": "Check Once on Start",
|
||||
"tryInferAppIdFromCode": "Try inferring App ID from source code",
|
||||
"removeAppQuestion": {
|
||||
"one": "برنامه حذف شود؟",
|
||||
"other": "برنامه ها حذف شوند؟"
|
||||
|
@ -233,6 +233,7 @@
|
||||
"about": "About",
|
||||
"requiresCredentialsInSettings": "This needs additional credentials (in Settings)",
|
||||
"checkOnStart": "Check Once on Start",
|
||||
"tryInferAppIdFromCode": "Try inferring App ID from source code",
|
||||
"removeAppQuestion": {
|
||||
"one": "Supprimer l'application ?",
|
||||
"other": "Supprimer les applications ?"
|
||||
|
@ -227,11 +227,12 @@
|
||||
"dontShowAgain": "Ne mutassa ezt újra",
|
||||
"dontShowTrackOnlyWarnings": "Ne jelenítsen meg 'Csak nyomon követés' figyelmeztetést",
|
||||
"dontShowAPKOriginWarnings": "Ne jelenítsen meg az APK eredetére vonatkozó figyelmeztetéseket",
|
||||
"moveNonInstalledAppsToBottom": "Move Non-Installed Apps to Bottom of Apps View",
|
||||
"gitlabPATLabel": "GitLab Personal Access Token (Enables Search)",
|
||||
"about": "About",
|
||||
"requiresCredentialsInSettings": "This needs additional credentials (in Settings)",
|
||||
"checkOnStart": "Check Once on Start",
|
||||
"moveNonInstalledAppsToBottom": "Helyezze át a nem telepített appokat az App nézet aljára",
|
||||
"gitlabPATLabel": "GitLab Personal Access Token (Engedélyezi a Keresést)",
|
||||
"about": "Rólunk",
|
||||
"requiresCredentialsInSettings": "Ehhez további hitelesítő adatokra van szükség (a Beállításokban)",
|
||||
"checkOnStart": "Egyszer az indításkor",
|
||||
"tryInferAppIdFromCode": "Try inferring App ID from source code",
|
||||
"removeAppQuestion": {
|
||||
"one": "Eltávolítja az alkalmazást?",
|
||||
"other": "Eltávolítja az alkalmazást?"
|
||||
|
@ -233,6 +233,7 @@
|
||||
"about": "About",
|
||||
"requiresCredentialsInSettings": "This needs additional credentials (in Settings)",
|
||||
"checkOnStart": "Check Once on Start",
|
||||
"tryInferAppIdFromCode": "Try inferring App ID from source code",
|
||||
"removeAppQuestion": {
|
||||
"one": "Rimuovere l'App?",
|
||||
"other": "Rimuovere le App?"
|
||||
|
@ -233,6 +233,7 @@
|
||||
"about": "概要",
|
||||
"requiresCredentialsInSettings": "これには追加の認証が必要です (設定にて)",
|
||||
"checkOnStart": "Check Once on Start",
|
||||
"tryInferAppIdFromCode": "Try inferring App ID from source code",
|
||||
"removeAppQuestion": {
|
||||
"one": "アプリを削除しますか?",
|
||||
"other": "アプリを削除しますか?"
|
||||
|
@ -233,6 +233,7 @@
|
||||
"about": "相关文档",
|
||||
"requiresCredentialsInSettings": "此功能需要额外的凭据(在“设置”中添加)",
|
||||
"checkOnStart": "启动时进行一次检查",
|
||||
"tryInferAppIdFromCode": "Try inferring App ID from source code",
|
||||
"removeAppQuestion": {
|
||||
"one": "是否删除应用?",
|
||||
"other": "是否删除应用?"
|
||||
|
@ -19,8 +19,8 @@ class APKCombo extends AppSource {
|
||||
}
|
||||
|
||||
@override
|
||||
String? tryInferringAppId(String standardUrl,
|
||||
{Map<String, dynamic> additionalSettings = const {}}) {
|
||||
Future<String?> tryInferringAppId(String standardUrl,
|
||||
{Map<String, dynamic> additionalSettings = const {}}) async {
|
||||
return Uri.parse(standardUrl).pathSegments.last;
|
||||
}
|
||||
|
||||
@ -83,7 +83,7 @@ class APKCombo extends AppSource {
|
||||
String standardUrl,
|
||||
Map<String, dynamic> additionalSettings,
|
||||
) async {
|
||||
String appId = tryInferringAppId(standardUrl)!;
|
||||
String appId = (await tryInferringAppId(standardUrl))!;
|
||||
var preres = await sourceRequest(standardUrl);
|
||||
if (preres.statusCode != 200) {
|
||||
throw getObtainiumHttpError(preres);
|
||||
|
@ -24,8 +24,8 @@ class APKPure extends AppSource {
|
||||
}
|
||||
|
||||
@override
|
||||
String? tryInferringAppId(String standardUrl,
|
||||
{Map<String, dynamic> additionalSettings = const {}}) {
|
||||
Future<String?> tryInferringAppId(String standardUrl,
|
||||
{Map<String, dynamic> additionalSettings = const {}}) async {
|
||||
return Uri.parse(standardUrl).pathSegments.last;
|
||||
}
|
||||
|
||||
@ -34,7 +34,7 @@ class APKPure extends AppSource {
|
||||
String standardUrl,
|
||||
Map<String, dynamic> additionalSettings,
|
||||
) async {
|
||||
String appId = tryInferringAppId(standardUrl)!;
|
||||
String appId = (await tryInferringAppId(standardUrl))!;
|
||||
String host = Uri.parse(standardUrl).host;
|
||||
var res = await sourceRequest('$standardUrl/download');
|
||||
if (res.statusCode == 200) {
|
||||
|
@ -31,8 +31,8 @@ class FDroid extends AppSource {
|
||||
}
|
||||
|
||||
@override
|
||||
String? tryInferringAppId(String standardUrl,
|
||||
{Map<String, dynamic> additionalSettings = const {}}) {
|
||||
Future<String?> tryInferringAppId(String standardUrl,
|
||||
{Map<String, dynamic> additionalSettings = const {}}) async {
|
||||
return Uri.parse(standardUrl).pathSegments.last;
|
||||
}
|
||||
|
||||
@ -63,7 +63,7 @@ class FDroid extends AppSource {
|
||||
String standardUrl,
|
||||
Map<String, dynamic> additionalSettings,
|
||||
) async {
|
||||
String? appId = tryInferringAppId(standardUrl);
|
||||
String? appId = await tryInferringAppId(standardUrl);
|
||||
String host = Uri.parse(standardUrl).host;
|
||||
return getAPKUrlsFromFDroidPackagesAPIResponse(
|
||||
await sourceRequest('https://$host/api/v1/packages/$appId'),
|
||||
|
@ -6,6 +6,7 @@ import 'package:obtainium/app_sources/html.dart';
|
||||
import 'package:obtainium/components/generated_form.dart';
|
||||
import 'package:obtainium/custom_errors.dart';
|
||||
import 'package:obtainium/providers/apps_provider.dart';
|
||||
import 'package:obtainium/providers/logs_provider.dart';
|
||||
import 'package:obtainium/providers/settings_provider.dart';
|
||||
import 'package:obtainium/providers/source_provider.dart';
|
||||
import 'package:url_launcher/url_launcher_string.dart';
|
||||
@ -13,6 +14,7 @@ import 'package:url_launcher/url_launcher_string.dart';
|
||||
class GitHub extends AppSource {
|
||||
GitHub() {
|
||||
host = 'github.com';
|
||||
appIdInferIsOptional = true;
|
||||
|
||||
additionalSourceSpecificSettingFormItems = [
|
||||
GeneratedFormTextField('github-creds',
|
||||
@ -79,6 +81,44 @@ class GitHub extends AppSource {
|
||||
canSearch = true;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<String?> tryInferringAppId(String standardUrl,
|
||||
{Map<String, dynamic> additionalSettings = const {}}) async {
|
||||
const possibleBuildGradleLocations = [
|
||||
'/app/build.gradle',
|
||||
'android/app/build.gradle',
|
||||
'src/app/build.gradle'
|
||||
];
|
||||
for (var path in possibleBuildGradleLocations) {
|
||||
try {
|
||||
var res = await sourceRequest(
|
||||
'${await convertStandardUrlToAPIUrl(standardUrl)}/contents/$path');
|
||||
if (res.statusCode == 200) {
|
||||
try {
|
||||
var body = jsonDecode(res.body);
|
||||
var appId = utf8
|
||||
.decode(base64
|
||||
.decode(body['content'].toString().split('\n').join('')))
|
||||
.split('\n')
|
||||
.map((e) => e.trim())
|
||||
.where((l) => l.startsWith('applicationId "'))
|
||||
.first
|
||||
.split('"')[1];
|
||||
if (appId.isNotEmpty) {
|
||||
return appId;
|
||||
}
|
||||
} catch (err) {
|
||||
LogsProvider().add(
|
||||
'Error parsing build.gradle from ${res.request!.url.toString()}: ${err.toString()}');
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
// Ignore - ID will be extracted from the APK
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@override
|
||||
String sourceSpecificStandardizeURL(String url) {
|
||||
RegExp standardUrlRegEx = RegExp('^https?://$host/[^/]+/[^/]+');
|
||||
@ -97,6 +137,12 @@ class GitHub extends AppSource {
|
||||
return creds != null && creds.isNotEmpty ? '$creds@' : '';
|
||||
}
|
||||
|
||||
Future<String> getAPIHost() async =>
|
||||
'https://${await getCredentialPrefixIfAny()}api.$host';
|
||||
|
||||
Future<String> convertStandardUrlToAPIUrl(String standardUrl) async =>
|
||||
'${await getAPIHost()}/repos${standardUrl.substring('https://$host'.length)}';
|
||||
|
||||
@override
|
||||
String? changeLogPageFromStandardUrl(String standardUrl) =>
|
||||
'$standardUrl/releases';
|
||||
@ -239,7 +285,7 @@ class GitHub extends AppSource {
|
||||
) async {
|
||||
return await getLatestAPKDetailsCommon2(standardUrl, additionalSettings,
|
||||
(bool useTagUrl) async {
|
||||
return 'https://${await getCredentialPrefixIfAny()}api.$host/repos${standardUrl.substring('https://$host'.length)}/${useTagUrl ? 'tags' : 'releases'}?per_page=100';
|
||||
return '${await convertStandardUrlToAPIUrl(standardUrl)}/${useTagUrl ? 'tags' : 'releases'}?per_page=100';
|
||||
}, (Response res) {
|
||||
rateLimitErrorCheck(res);
|
||||
});
|
||||
@ -281,7 +327,7 @@ class GitHub extends AppSource {
|
||||
Future<Map<String, List<String>>> search(String query) async {
|
||||
return searchCommon(
|
||||
query,
|
||||
'https://${await getCredentialPrefixIfAny()}api.$host/search/repositories?q=${Uri.encodeQueryComponent(query)}&per_page=100',
|
||||
'${await getAPIHost()}/search/repositories?q=${Uri.encodeQueryComponent(query)}&per_page=100',
|
||||
'items', onHttpErrorCode: (Response res) {
|
||||
rateLimitErrorCheck(res);
|
||||
});
|
||||
|
@ -18,8 +18,8 @@ class IzzyOnDroid extends AppSource {
|
||||
}
|
||||
|
||||
@override
|
||||
String? tryInferringAppId(String standardUrl,
|
||||
{Map<String, dynamic> additionalSettings = const {}}) {
|
||||
Future<String?> tryInferringAppId(String standardUrl,
|
||||
{Map<String, dynamic> additionalSettings = const {}}) async {
|
||||
return FDroid().tryInferringAppId(standardUrl);
|
||||
}
|
||||
|
||||
@ -28,7 +28,7 @@ class IzzyOnDroid extends AppSource {
|
||||
String standardUrl,
|
||||
Map<String, dynamic> additionalSettings,
|
||||
) async {
|
||||
String? appId = tryInferringAppId(standardUrl);
|
||||
String? appId = await tryInferringAppId(standardUrl);
|
||||
return FDroid().getAPKUrlsFromFDroidPackagesAPIResponse(
|
||||
await sourceRequest(
|
||||
'https://apt.izzysoft.de/fdroid/api/v1/packages/$appId'),
|
||||
|
@ -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.13.5';
|
||||
const String currentVersion = '0.13.6';
|
||||
const String currentReleaseTag =
|
||||
'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES
|
||||
|
||||
|
@ -33,6 +33,7 @@ class _AddAppPageState extends State<AddAppPage> {
|
||||
AppSource? pickedSource;
|
||||
Map<String, dynamic> additionalSettings = {};
|
||||
bool additionalSettingsValid = true;
|
||||
bool inferAppIdIfOptional = true;
|
||||
List<String> pickedCategories = [];
|
||||
int searchnum = 0;
|
||||
SourceProvider sourceProvider = SourceProvider();
|
||||
@ -78,6 +79,7 @@ class _AddAppPageState extends State<AddAppPage> {
|
||||
additionalSettingsValid = source != null
|
||||
? !sourceProvider.ifRequiredAppSpecificSettingsExist(source)
|
||||
: true;
|
||||
inferAppIdIfOptional = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -147,7 +149,8 @@ class _AddAppPageState extends State<AddAppPage> {
|
||||
app = await sourceProvider.getApp(
|
||||
pickedSource!, userInput, additionalSettings,
|
||||
trackOnlyOverride: trackOnly,
|
||||
overrideSource: pickedSourceOverride);
|
||||
overrideSource: pickedSourceOverride,
|
||||
inferAppIdIfOptional: inferAppIdIfOptional);
|
||||
// Only download the APK here if you need to for the package ID
|
||||
if (sourceProvider.isTempId(app) &&
|
||||
app.additionalSettings['trackOnly'] != true) {
|
||||
@ -428,6 +431,23 @@ class _AddAppPageState extends State<AddAppPage> {
|
||||
}),
|
||||
],
|
||||
),
|
||||
if (pickedSource != null && pickedSource!.appIdInferIsOptional)
|
||||
GeneratedForm(
|
||||
key: const Key('inferAppIdIfOptional'),
|
||||
items: [
|
||||
[
|
||||
GeneratedFormSwitch('inferAppIdIfOptional',
|
||||
label: tr('tryInferAppIdFromCode'),
|
||||
defaultValue: inferAppIdIfOptional)
|
||||
]
|
||||
],
|
||||
onValueChanges: (values, valid, isBuilding) {
|
||||
if (!isBuilding) {
|
||||
setState(() {
|
||||
inferAppIdIfOptional = values['inferAppIdIfOptional'];
|
||||
});
|
||||
}
|
||||
}),
|
||||
],
|
||||
);
|
||||
|
||||
|
@ -317,6 +317,7 @@ abstract class AppSource {
|
||||
late String name;
|
||||
bool enforceTrackOnly = false;
|
||||
bool changeLogIfAnyIsMarkDown = true;
|
||||
bool appIdInferIsOptional = false;
|
||||
|
||||
AppSource() {
|
||||
name = runtimeType.toString();
|
||||
@ -434,8 +435,8 @@ abstract class AppSource {
|
||||
throw NotImplementedError();
|
||||
}
|
||||
|
||||
String? tryInferringAppId(String standardUrl,
|
||||
{Map<String, dynamic> additionalSettings = const {}}) {
|
||||
Future<String?> tryInferringAppId(String standardUrl,
|
||||
{Map<String, dynamic> additionalSettings = const {}}) async {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@ -552,7 +553,8 @@ class SourceProvider {
|
||||
AppSource source, String url, Map<String, dynamic> additionalSettings,
|
||||
{App? currentApp,
|
||||
bool trackOnlyOverride = false,
|
||||
String? overrideSource}) async {
|
||||
String? overrideSource,
|
||||
bool inferAppIdIfOptional = false}) async {
|
||||
if (trackOnlyOverride || source.enforceTrackOnly) {
|
||||
additionalSettings['trackOnly'] = true;
|
||||
}
|
||||
@ -592,8 +594,11 @@ class SourceProvider {
|
||||
: apk.names.name[0].toUpperCase() + apk.names.name.substring(1);
|
||||
return App(
|
||||
currentApp?.id ??
|
||||
source.tryInferringAppId(standardUrl,
|
||||
additionalSettings: additionalSettings) ??
|
||||
((!source.appIdInferIsOptional ||
|
||||
(source.appIdInferIsOptional && inferAppIdIfOptional))
|
||||
? await source.tryInferringAppId(standardUrl,
|
||||
additionalSettings: additionalSettings)
|
||||
: null) ??
|
||||
generateTempID(standardUrl, additionalSettings),
|
||||
standardUrl,
|
||||
apk.names.author[0].toUpperCase() + apk.names.author.substring(1),
|
||||
|
@ -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.13.5+169 # When changing this, update the tag in main() accordingly
|
||||
version: 0.13.6+170 # When changing this, update the tag in main() accordingly
|
||||
|
||||
environment:
|
||||
sdk: '>=2.18.2 <3.0.0'
|
||||
|
Reference in New Issue
Block a user