From 578e3709f8070ecd4d8b653abfd4364eb7f2b1cc Mon Sep 17 00:00:00 2001
From: NaiJi <naijiworld@protonmail.com>
Date: Thu, 2 Feb 2023 02:18:06 +0400
Subject: [PATCH] feat: Implement basic error handling

---
 bin/main.dart        |  6 ++-
 lib/funkblubber.dart | 91 ++++++++++++++++++++++++++++++++------------
 2 files changed, 71 insertions(+), 26 deletions(-)

diff --git a/bin/main.dart b/bin/main.dart
index b9cbe2d..d6fc23f 100644
--- a/bin/main.dart
+++ b/bin/main.dart
@@ -11,8 +11,12 @@ void main(final List<String> arguments) async {
     return;
   }
 
-  await funkblubber.download(
+  final bool success = await funkblubber.download(
     object: result.object!,
     path: result.localPath ?? '.',
   );
+
+  if (!success) {
+    console.error("couldn't execute request successfully.");
+  }
 }
diff --git a/lib/funkblubber.dart b/lib/funkblubber.dart
index f01678b..180091b 100644
--- a/lib/funkblubber.dart
+++ b/lib/funkblubber.dart
@@ -4,27 +4,30 @@ import 'package:dio/dio.dart';
 import 'package:funkblubber/funkentity.dart';
 import 'package:funkblubber/console.dart' as console;
 
-Future<void> download({
+Future<bool> download({
   required final FunkObject object,
   required final String path,
 }) async {
+  bool success = false;
   console.info('Downloading');
   switch (object.kind) {
     case FunkEntity.album:
-      await _downloadAlbum(object, path);
-      return;
+      success = await _downloadAlbum(object, path);
+      break;
 
     case FunkEntity.artist:
-      await _downloadArtist(object, path);
-      return;
+      success = await _downloadArtist(object, path);
+      break;
 
     default:
       console.info('   nothing...');
-      return;
+      break;
   }
+
+  return success;
 }
 
-Future<void> _downloadArtist(
+Future<bool> _downloadArtist(
   final FunkObject object,
   final String path,
 ) async {
@@ -34,7 +37,16 @@ Future<void> _downloadArtist(
   );
 
   final String pathAppend = response.data['name'];
-  await Directory('$path/$pathAppend').create();
+  bool folderCreated = true;
+  try {
+    await Directory('$path/$pathAppend').create();
+  } catch (e) {
+    console.error(e.toString());
+    folderCreated = false;
+  }
+  if (!folderCreated) {
+    return false;
+  }
   console.info('Artist: $pathAppend');
 
   response = await Dio().get(
@@ -43,8 +55,9 @@ Future<void> _downloadArtist(
     'page=1&page_size=16&scope=all',
   );
 
+  final List<Future<bool>> results = [];
   for (final albumResponse in response.data['results']) {
-    _downloadAlbum(
+    final result = _downloadAlbum(
       FunkObject(
         domain: object.domain,
         id: albumResponse['id'].toString(),
@@ -52,10 +65,15 @@ Future<void> _downloadArtist(
       ),
       '$path/$pathAppend',
     );
+
+    results.add(result);
   }
+
+  final List<bool> successes = await Future.wait(results);
+  return successes.every((final success) => success);
 }
 
-Future<void> _downloadAlbum(
+Future<bool> _downloadAlbum(
   final FunkObject object,
   final String path,
 ) async {
@@ -66,13 +84,23 @@ Future<void> _downloadAlbum(
   );
 
   final String pathAppend = response.data['results'][0]['album']['title'];
-  await Directory('$path/$pathAppend').create();
+  bool folderCreated = true;
+  try {
+    await Directory('$path/$pathAppend').create();
+  } catch (e) {
+    console.error(e.toString());
+    folderCreated = false;
+  }
+  if (!folderCreated) {
+    return false;
+  }
   console.info('Album: $pathAppend');
 
+  final List<Future<bool>> results = [];
   for (final songResponse in response.data['results']) {
     final String songTitle = songResponse['title'];
     final String ext = songResponse['uploads'][0]['extension'];
-    _downloadSongObject(
+    final result = _downloadSongObject(
       FunkObject(
         domain: object.domain,
         id: songResponse['listen_url'],
@@ -80,23 +108,36 @@ Future<void> _downloadAlbum(
       ),
       '$path/$pathAppend/$songTitle.$ext',
     );
+
+    results.add(result);
   }
+
+  final List<bool> successes = await Future.wait(results);
+  return successes.every((final success) => success);
 }
 
-Future<void> _downloadSongObject(
+Future<bool> _downloadSongObject(
   final FunkObject object,
   final String path,
 ) async {
-  final Response response = await Dio().get(
-    'https://${object.domain}${object.id}',
-    options: Options(
-      responseType: ResponseType.bytes,
-      followRedirects: false,
-    ),
-  );
-  console.info('- $path');
-  final File file = File(path);
-  final accessFile = file.openSync(mode: FileMode.write);
-  accessFile.writeFromSync(response.data);
-  await accessFile.close();
+  bool success = true;
+  try {
+    final Response response = await Dio().get(
+      'https://${object.domain}${object.id}',
+      options: Options(
+        responseType: ResponseType.bytes,
+        followRedirects: false,
+      ),
+    );
+    console.info('- $path');
+    final File file = File(path);
+    final accessFile = file.openSync(mode: FileMode.write);
+    accessFile.writeFromSync(response.data);
+    await accessFile.close();
+  } catch (e) {
+    console.error(e.toString());
+    success = false;
+  }
+
+  return success;
 }