Files
lunasea/lib/modules/radarr/core/api_helper.dart
Jagandeep Brar dec1845764 [Release] (chore): Dirty v5.0.0+50000013 (#382) (#383)
* [iOS/Build] Add GoogleUtilities pod to prevent archive errors

* (chore) version bump

* [Git] Initialize blackbox

* [Git] Initialize blackbox

* [Git/Blackbox] Add me@jagandeepbrar.io as admin

* registered in blackbox: ios/ExportOptions.plist

* registered in blackbox: ios/GoogleService-Info.plist

* registered in blackbox: android/key.properties

* registered in blackbox: android/app/google-services.json

* Re-encrypted keys

* registered in blackbox: android/key.jks

* Updated key.properties, re-encrypted

* [Android/Keystore] Update same key.properties

* [Tautulli/Activity] Incorrectly localized "Transcodes" string

* [Radarr, UI] Implemented quick manual import, Implemented new design of ExpandableTile across UI (#378)

* Use local path for radarr package

* [Radarr/Manual Import] Browse filesystem, trigger quick import

* [UI/Buttons] Normalize the height of all buttons

* Update packages

* [ListView] Exposed itemExtent property

* [Lidarr/Releases] Move from LSExpandable to LunaExpandableListTile implementation

* [Tautulli/Logs] Use the new expandable table card styling

* [SABnzbd/History] Use the newer expandable table card styling

* [NZBGet/History] Use the newer expandable table card styling

* [UI/Button] Reduce size of the loader and icon to closer match text size

* [Sonarr/Releases] Use the newer expandable table card styling

* [Sonarr/Episodes] Use the newer expandable table card styling

* [UI/Table] Safe-guard title and body text, show emdash when receiving null data

* [Radarr/Details] Show monitor status and properly update the overview table on edit or monitor status changes

* Updated changelog

* [Sonarr/Queue & Episodes] Cleaned up implementation of expandable tile

* Translated using Weblate (Norwegian Bokmål)

Currently translated at 100.0% (14 of 14 strings)

Translation: LunaSea/LunaSea
Translate-URL: https://hosted.weblate.org/projects/lunasea/lunasea/nb_NO/

* Translated using Weblate (Swedish)

Currently translated at 100.0% (14 of 14 strings)

Translation: LunaSea/LunaSea
Translate-URL: https://hosted.weblate.org/projects/lunasea/lunasea/sv/

* Translated using Weblate (German)

Currently translated at 100.0% (68 of 68 strings)

Translation: LunaSea/Tautulli
Translate-URL: https://hosted.weblate.org/projects/lunasea/tautulli/de/

* Translated using Weblate (Norwegian Bokmål)

Currently translated at 80.8% (55 of 68 strings)

Translation: LunaSea/Tautulli
Translate-URL: https://hosted.weblate.org/projects/lunasea/tautulli/nb_NO/

* Translated using Weblate (Swedish)

Currently translated at 100.0% (68 of 68 strings)

Translation: LunaSea/Tautulli
Translate-URL: https://hosted.weblate.org/projects/lunasea/tautulli/sv/

* Translated using Weblate (Russian)

Currently translated at 57.3% (39 of 68 strings)

Translation: LunaSea/Tautulli
Translate-URL: https://hosted.weblate.org/projects/lunasea/tautulli/ru/

* (chore) Build localizations

* [Tautulli/Webhooks] Implement webhook data handlers for all Tautulli webhooks (#380)

* [Tautulli/Webhooks] Handle transcode decision change and watched event types
* [Radarr/Sonarr] Safe-guard webhooks by pushing the home route on invalid received data blocks
* [Tautulli/Webhooks] Implemented all webhooks

* Translated using Weblate (French)

Currently translated at 100.0% (78 of 78 strings)

Translation: LunaSea/Radarr
Translate-URL: https://hosted.weblate.org/projects/lunasea/radarr/fr/

* Translated using Weblate (German)

Currently translated at 100.0% (78 of 78 strings)

Translation: LunaSea/Radarr
Translate-URL: https://hosted.weblate.org/projects/lunasea/radarr/de/

* Translated using Weblate (Russian)

Currently translated at 92.8% (13 of 14 strings)

Translation: LunaSea/LunaSea
Translate-URL: https://hosted.weblate.org/projects/lunasea/lunasea/ru/

* [Release] (chore): Dirty v5.0.0+50000013 (#382)

* [Radarr/Manual Import] Add search bar for host system path, add stub manual import page

* [Radarr/Manual Import] Change path bar text to "File Browser..."

* [Radarr/Manual Import] Pass "/" if textController text is null

* [Radarr/Import] Stub details state

* [Database] Correctly register LunaIndexerIcon hive adapter

* [Radarr/Import] Filter directories when typing path, Fetch manual import results with stub cards

* [UI/Bottom Bar] Abstract bottom action bar, use on add movie page

* [UI/Navigation Bar] Add option to attach stickied top actions to navigation bar

* [Radarr/Edit] Use stickied bottom action bar for buttons

* [Radarr/Details] use sticky navigation actions for interactive and automatic search

* [Dialogs] CheckboxTiles were padded too aggressively in the X-axis

* [Sentry] Remove remaining references to Sentry

* (chore) Build localizations

* (chore) Update changelog

* Preparing to shift GitHub repository structure

Co-authored-by: Allan Nordhøy <epost@anotheragency.no>
Co-authored-by: Patrik Hauguth <patrik.hauguth@gmail.com>
Co-authored-by: cpt-kuesel <jln.sltr@pm.me>
Co-authored-by: Artem <KovalevArtem.ru@gmail.com>
Co-authored-by: Antoine C <contact+weblate@antoinecardon.fr>
2021-03-24 08:12:41 -05:00

392 lines
15 KiB
Dart

import 'package:flutter/material.dart';
import 'package:lunasea/core.dart';
import 'package:lunasea/modules/radarr.dart';
class RadarrAPIHelper {
/// Toggles the monitored state on a movie.
///
/// Updates the movie catalogue list in [RadarrState].
Future<bool> toggleMonitored({
@required BuildContext context,
@required RadarrMovie movie,
bool showSnackbar = true,
}) async {
assert(movie != null);
if(context.read<RadarrState>().enabled) {
RadarrMovie movieCopy = movie.clone();
movieCopy.monitored = !movie.monitored;
return await context.read<RadarrState>().api.movie.update(movie: movieCopy)
.then((data) async {
return await context.read<RadarrState>().setSingleMovie(movieCopy).then((_) {
if(showSnackbar) showLunaSuccessSnackBar(title: movieCopy.monitored ? 'Monitoring' : 'No Longer Monitoring', message: movie.title);
return true;
});
})
.catchError((error, stack) {
LunaLogger().error('Unable to toggle monitored state: ${movie.monitored.toString()} to ${movieCopy.monitored.toString()}', error, stack);
if(showSnackbar) showLunaErrorSnackBar(title: movie.monitored ? 'Failed to Unmonitor Movie' : 'Failed to Monitor Movie', error: error);
return false;
});
}
return false;
}
/// Refreshes a single movie.
Future<bool> refreshMovie({
@required BuildContext context,
@required RadarrMovie movie,
bool showSnackbar = true,
}) async {
assert(movie != null);
if(context.read<RadarrState>().enabled) {
return await context.read<RadarrState>().api.command.refreshMovie(movieIds: [movie.id])
.then((_) {
if(showSnackbar) showLunaSuccessSnackBar(title: 'Refreshing...', message: movie.title);
return true;
})
.catchError((error, stack) {
LunaLogger().error('Unable to refresh movie: ${movie.id}', error, stack);
if(showSnackbar) showLunaErrorSnackBar(title: 'Failed to Refresh', error: error);
return false;
});
}
return false;
}
/// Add a new movie.
///
/// Returns the newly added [RadarrMovie] instance.
Future<RadarrMovie> addMovie({
@required BuildContext context,
@required RadarrMovie movie,
@required RadarrRootFolder rootFolder,
@required bool monitored,
@required RadarrQualityProfile qualityProfile,
@required RadarrAvailability availability,
@required List<RadarrTag> tags,
@required bool searchForMovie,
bool showSnackbar = true,
}) async {
assert(movie != null);
assert(rootFolder != null);
assert(monitored != null);
assert(qualityProfile != null);
assert(availability != null);
assert(tags != null);
assert(searchForMovie != null);
if(context.read<RadarrState>().enabled) {
return await context.read<RadarrState>().api.movie.create(
movie: movie,
rootFolder: rootFolder,
monitored: monitored,
qualityProfile: qualityProfile,
minimumAvailability: availability,
tags: tags,
searchForMovie: searchForMovie,
)
.then((movie) {
if(showSnackbar) showLunaSuccessSnackBar(
context: context,
title: [
'Movie Added',
if(searchForMovie) '(Searching...)',
].join(' '),
message: movie.title,
);
return movie;
})
.catchError((error, stack) {
LunaLogger().error('Failed to add movie (tmdbId: ${movie.tmdbId})', error, stack);
if(showSnackbar) showLunaErrorSnackBar(title: 'Failed to Add Movie', error: error);
return null;
});
}
return null;
}
/// Backup the database.
Future<bool> backupDatabase({
@required BuildContext context,
bool showSnackbar = true,
}) async {
if(context.read<RadarrState>().enabled) {
return await context.read<RadarrState>().api.command.backup()
.then((_) {
if(showSnackbar) showLunaSuccessSnackBar(title: 'Backing Up Database${Constants.TEXT_ELLIPSIS}', message: 'Backing up the database in the background');
return true;
})
.catchError((error, stack) {
LunaLogger().error('Unable to backup database', error, stack);
if(showSnackbar) showLunaErrorSnackBar(title: 'Failed to Backup Database', error: error);
return false;
});
}
return false;
}
/// Search for all missing movies.
Future<bool> missingMovieSearch({
@required BuildContext context,
bool showSnackbar = true,
}) async {
if(context.read<RadarrState>().enabled) {
return await context.read<RadarrState>().api.command.missingMovieSearch()
.then((_) {
if(showSnackbar) showLunaSuccessSnackBar(title: 'Searching${Constants.TEXT_ELLIPSIS}', message: 'Searching for all missing movies');
return true;
})
.catchError((error, stack) {
LunaLogger().error('Unable to search for all missing movies', error, stack);
if(showSnackbar) showLunaErrorSnackBar(title: 'Failed to Search', error: error);
return false;
});
}
return false;
}
/// Run an RSS sync.
Future<bool> runRSSSync({
@required BuildContext context,
bool showSnackbar = true,
}) async {
if(context.read<RadarrState>().enabled) {
return await context.read<RadarrState>().api.command.rssSync()
.then((_) {
if(showSnackbar) showLunaSuccessSnackBar(title: 'Running RSS Sync${Constants.TEXT_ELLIPSIS}', message: 'Running RSS sync in the background');
return true;
})
.catchError((error, stack) {
LunaLogger().error('Unable to run RSS sync', error, stack);
if(showSnackbar) showLunaErrorSnackBar(title: 'Failed to Run RSS Sync', error: error);
return false;
});
}
return false;
}
/// Update all movies in your library.
Future<bool> updateLibrary({
@required BuildContext context,
bool showSnackbar = true,
}) async {
if(context.read<RadarrState>().enabled) {
return await context.read<RadarrState>().api.command.refreshMovie()
.then((_) {
if(showSnackbar) showLunaSuccessSnackBar(title: 'Updating Library${Constants.TEXT_ELLIPSIS}', message: 'Updating library in the background');
return true;
})
.catchError((error, stack) {
LunaLogger().error('Unable to update library', error, stack);
if(showSnackbar) showLunaErrorSnackBar(title: 'Failed to Update Library', error: error);
return false;
});
}
return false;
}
/// Delete a movie file.
Future<bool> deleteMovieFile({
@required BuildContext context,
@required RadarrMovieFile movieFile,
bool showSnackbar = true,
}) async {
assert(movieFile != null);
if(context.read<RadarrState>().enabled) {
return await context.read<RadarrState>().api.movieFile.delete(movieFileId: movieFile.id)
.then((_) {
if(showSnackbar) showLunaSuccessSnackBar(title: 'File Deleted', message: movieFile.relativePath);
return true;
})
.catchError((error, stack) {
LunaLogger().error('Failed to delete movie file: ${movieFile.id}', error, stack);
if(showSnackbar) showLunaErrorSnackBar(title: 'Failed to Delete File', error: error);
return false;
});
}
return false;
}
/// Update a movie in Radarr.
Future<bool> updateMovie({
@required BuildContext context,
@required RadarrMovie movie,
bool showSnackbar = true,
}) async {
assert(movie != null);
if(context.read<RadarrState>().enabled) {
return await context.read<RadarrState>().api.movie.update(movie: movie)
.then((_) async {
return await context.read<RadarrState>().setSingleMovie(movie).then((_) {
if(showSnackbar) showLunaSuccessSnackBar(title: 'Updated Movie', message: movie.title);
return true;
});
})
.catchError((error, stack) {
LunaLogger().error('Failed to update movie: ${movie.id}', error, stack);
showLunaErrorSnackBar(title: 'Failed to Update Movie', error: error);
return false;
});
}
return false;
}
/// Remove a movie.
Future<bool> removeMovie({
@required BuildContext context,
@required RadarrMovie movie,
bool showSnackbar = true,
}) async {
assert(movie != null);
if(context.read<RadarrState>().enabled) {
return await context.read<RadarrState>().api.movie.delete(
movieId: movie.id,
addImportExclusion: RadarrDatabaseValue.REMOVE_MOVIE_IMPORT_LIST.data,
deleteFiles: RadarrDatabaseValue.REMOVE_MOVIE_DELETE_FILES.data,
).then((_) async {
movie.id = null;
return await context.read<RadarrState>().setSingleMovie(movie).then((_) {
if(showSnackbar) showLunaSuccessSnackBar(
context: context,
title: [
'Removed Movie',
if(RadarrDatabaseValue.REMOVE_MOVIE_DELETE_FILES.data) '(With Files)',
].join(' '),
message: movie.title,
);
return true;
});
})
.catchError((error, stack) {
LunaLogger().error('Failed to remove movie: ${movie.id}', error, stack);
showLunaErrorSnackBar(title: 'Failed to Remove Movie', error: error);
return false;
});
}
return false;
}
/// Execute a quick import.
Future<bool> quickImport({
@required BuildContext context,
@required String path,
bool showSnackbar = true,
}) async {
assert(path != null && path.isNotEmpty);
if(context.read<RadarrState>().enabled) {
return await context.read<RadarrState>().api.command.downloadedMoviesScan(path: path)
.then((_) async {
if(showSnackbar) showLunaSuccessSnackBar(
context: context,
title: 'Running Quick Import${LunaUI.TEXT_ELLIPSIS}',
message: path,
);
return true;
})
.catchError((error, stack) {
LunaLogger().error('Failed to execute downloaded movies scan: $path', error, stack);
showLunaErrorSnackBar(title: 'Failed to Quick Import', error: error);
return false;
});
}
return false;
}
/// Trigger an automatic search of a movie.
Future<bool> automaticSearch({
@required BuildContext context,
@required int movieId,
@required String title,
bool showSnackbar = true,
}) async {
assert(movieId != null);
assert(title != null);
if(context.read<RadarrState>().enabled) {
return await context.read<RadarrState>().api.command.moviesSearch(movieIds: [movieId])
.then((_) async {
if(showSnackbar) showLunaSuccessSnackBar(
context: context,
title: 'Searching for Movie...',
message: title,
);
return true;
})
.catchError((error, stack) {
LunaLogger().error('Failed to search for movie: $movieId', error, stack);
if(showSnackbar) showLunaErrorSnackBar(title: 'Failed to Search', error: error);
return false;
});
}
return false;
}
/// Push a release to the download client(s) connected to Radarr.
Future<bool> pushRelease({
@required BuildContext context,
@required RadarrRelease release,
bool showSnackbar = true,
}) async {
assert(release != null);
if(context.read<RadarrState>().enabled) {
return await context.read<RadarrState>().api.release.push(indexerId: release.indexerId, guid: release.guid)
.then((value) {
if(showSnackbar) showLunaSuccessSnackBar(
context: context,
title: 'Downloading Release...',
message: release.title,
);
return true;
})
.catchError((error, stack) {
LunaLogger().error('Failed to download release: ${release.guid}', error, stack);
if(showSnackbar) showLunaErrorSnackBar(title: 'Failed to Download Release', error: error);
return false;
});
}
return false;
}
/// Add a new tag.
Future<bool> addTag({
@required BuildContext context,
@required String label,
bool showSnackbar = true,
}) async {
assert(label != null);
if(context.read<RadarrState>().enabled) {
return await context.read<RadarrState>().api.tag.create(label: label)
.then((tag) {
showLunaSuccessSnackBar(title: 'Added Tag', message: tag.label);
return true;
})
.catchError((error, stack) {
LunaLogger().error('Failed to add tag: $label', error, stack);
if(showSnackbar) showLunaErrorSnackBar(title: 'Failed to Add Tag', error: error);
return false;
});
}
return false;
}
/// Delete a tag.
Future<bool> deleteTag({
@required BuildContext context,
@required RadarrTag tag,
bool showSnackbar = true,
}) async {
assert(tag != null);
if(context.read<RadarrState>().enabled) {
return await context.read<RadarrState>().api.tag.delete(id: tag.id)
.then((_) {
showLunaSuccessSnackBar(title: 'Deleted Tag', message: tag.label);
return true;
})
.catchError((error, stack) {
LunaLogger().error('Failed to add tag: ${tag.id}', error, stack);
if(showSnackbar) showLunaErrorSnackBar(title: 'Failed to Delete Tag', error: error);
return false;
});
}
return false;
}
}