You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

171 lines
4.2 KiB
Dart

import 'dart:core';
import 'dart:io';
import 'package:dio/dio.dart';
import 'package:funkblubber/funkentity.dart';
import 'package:funkblubber/console.dart' as console;
import 'package:funkblubber/string_utils.dart' as utils;
Future<bool> download({
required final FunkObject object,
required final String path,
}) async {
bool success = false;
console.info('Downloading');
switch (object.kind) {
case FunkEntity.album:
success = await _downloadAlbum(object, path);
break;
case FunkEntity.artist:
success = await _downloadArtist(object, path);
break;
case FunkEntity.track:
success = await _downloadTrack(object, path);
break;
default:
console.info(' nothing...');
break;
}
return success;
}
Future<bool> _downloadArtist(
final FunkObject object,
final String path,
) async {
Response response = await Dio().get(
'https://${object.domain}/api/v1/artists/${object.id}/?'
'refresh=false',
);
final String pathAppend = utils.sanitizePath(response.data['name']);
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(
'https://${object.domain}/api/v1/albums/?'
'artist=${object.id}&ordering=creation_date&'
'page=1&page_size=16&scope=all',
);
final List<Future<bool>> results = [];
for (final albumResponse in response.data['results']) {
final result = _downloadAlbum(
FunkObject(
domain: object.domain,
id: albumResponse['id'].toString(),
kind: FunkEntity.album,
),
'$path/$pathAppend',
);
results.add(result);
}
final List<bool> successes = await Future.wait(results);
return successes.every((final success) => success);
}
Future<bool> _downloadAlbum(
final FunkObject object,
final String path,
) async {
final response = await Dio().get(
'https://${object.domain}/api/v1/tracks/?'
'album=${object.id}&ordering=creation_date&'
'page=1&page_size=16&scope=all',
);
final String pathAppend = utils.sanitizePath(
response.data['results'][0]['album']['title'],
);
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 = utils.sanitizePath(songResponse['title']);
final String ext = songResponse['uploads'][0]['extension'];
final result = _downloadTrackObject(
FunkObject(
domain: object.domain,
id: songResponse['listen_url'],
kind: FunkEntity.track,
),
'$path/$pathAppend/$songTitle.$ext',
);
results.add(result);
}
final List<bool> successes = await Future.wait(results);
return successes.every((final success) => success);
}
Future<bool> _downloadTrack(
final FunkObject object,
final String path,
) async {
final response = await Dio().get(
'https://${object.domain}/api/v1/tracks/${object.id}/?refresh=false',
);
final String songTitle = utils.sanitizePath(response.data['title']);
final String ext = response.data['uploads'][0]['extension'];
return _downloadTrackObject(
FunkObject(
domain: object.domain,
id: response.data['uploads'][0]['listen_url'],
kind: FunkEntity.track,
),
'$path/$songTitle.$ext',
);
}
Future<bool> _downloadTrackObject(
final FunkObject object,
final String path,
) async {
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;
}