2023-01-26 16:35:58 -05:00
|
|
|
import 'dart:core';
|
2023-01-29 17:18:41 -05:00
|
|
|
import 'dart:io';
|
2023-01-26 16:35:58 -05:00
|
|
|
import 'package:dio/dio.dart';
|
|
|
|
import 'package:funkblubber/funkentity.dart';
|
|
|
|
import 'package:funkblubber/console.dart' as console;
|
2023-02-04 02:23:51 -05:00
|
|
|
import 'package:funkblubber/string_utils.dart' as utils;
|
2023-01-26 16:35:58 -05:00
|
|
|
|
2023-02-01 17:18:06 -05:00
|
|
|
Future<bool> download({
|
2023-01-29 17:18:41 -05:00
|
|
|
required final FunkObject object,
|
2023-02-01 16:00:23 -05:00
|
|
|
required final String path,
|
2023-01-29 17:18:41 -05:00
|
|
|
}) async {
|
2023-02-01 17:18:06 -05:00
|
|
|
bool success = false;
|
2023-01-31 02:37:32 -05:00
|
|
|
console.info('Downloading');
|
2023-01-26 16:35:58 -05:00
|
|
|
switch (object.kind) {
|
|
|
|
case FunkEntity.album:
|
2023-02-01 17:18:06 -05:00
|
|
|
success = await _downloadAlbum(object, path);
|
|
|
|
break;
|
2023-01-26 16:35:58 -05:00
|
|
|
|
2023-01-29 17:46:11 -05:00
|
|
|
case FunkEntity.artist:
|
2023-02-01 17:18:06 -05:00
|
|
|
success = await _downloadArtist(object, path);
|
|
|
|
break;
|
2023-01-29 17:46:11 -05:00
|
|
|
|
2023-02-04 01:24:05 -05:00
|
|
|
case FunkEntity.track:
|
|
|
|
success = await _downloadTrack(object, path);
|
|
|
|
break;
|
|
|
|
|
2023-01-26 16:35:58 -05:00
|
|
|
default:
|
2023-01-31 02:37:32 -05:00
|
|
|
console.info(' nothing...');
|
2023-02-01 17:18:06 -05:00
|
|
|
break;
|
2023-01-26 16:35:58 -05:00
|
|
|
}
|
2023-02-01 17:18:06 -05:00
|
|
|
|
|
|
|
return success;
|
2023-01-26 16:35:58 -05:00
|
|
|
}
|
|
|
|
|
2023-02-01 17:18:06 -05:00
|
|
|
Future<bool> _downloadArtist(
|
2023-01-29 17:46:11 -05:00
|
|
|
final FunkObject object,
|
|
|
|
final String path,
|
|
|
|
) async {
|
2023-01-29 17:55:35 -05:00
|
|
|
Response response = await Dio().get(
|
|
|
|
'https://${object.domain}/api/v1/artists/${object.id}/?'
|
|
|
|
'refresh=false',
|
|
|
|
);
|
|
|
|
|
2023-02-04 02:23:51 -05:00
|
|
|
final String pathAppend = utils.sanitizePath(response.data['name']);
|
2023-02-01 17:18:06 -05:00
|
|
|
bool folderCreated = true;
|
|
|
|
try {
|
|
|
|
await Directory('$path/$pathAppend').create();
|
|
|
|
} catch (e) {
|
|
|
|
console.error(e.toString());
|
|
|
|
folderCreated = false;
|
|
|
|
}
|
|
|
|
if (!folderCreated) {
|
|
|
|
return false;
|
|
|
|
}
|
2023-01-31 02:37:32 -05:00
|
|
|
console.info('Artist: $pathAppend');
|
2023-01-29 17:55:35 -05:00
|
|
|
|
|
|
|
response = await Dio().get(
|
2023-01-29 17:46:11 -05:00
|
|
|
'https://${object.domain}/api/v1/albums/?'
|
|
|
|
'artist=${object.id}&ordering=creation_date&'
|
|
|
|
'page=1&page_size=16&scope=all',
|
|
|
|
);
|
|
|
|
|
2023-02-01 17:18:06 -05:00
|
|
|
final List<Future<bool>> results = [];
|
2023-01-29 17:46:11 -05:00
|
|
|
for (final albumResponse in response.data['results']) {
|
2023-02-01 17:18:06 -05:00
|
|
|
final result = _downloadAlbum(
|
2023-01-29 17:46:11 -05:00
|
|
|
FunkObject(
|
|
|
|
domain: object.domain,
|
|
|
|
id: albumResponse['id'].toString(),
|
|
|
|
kind: FunkEntity.album,
|
|
|
|
),
|
2023-01-29 17:55:35 -05:00
|
|
|
'$path/$pathAppend',
|
2023-01-29 17:46:11 -05:00
|
|
|
);
|
2023-02-01 17:18:06 -05:00
|
|
|
|
|
|
|
results.add(result);
|
2023-01-29 17:46:11 -05:00
|
|
|
}
|
2023-02-01 17:18:06 -05:00
|
|
|
|
|
|
|
final List<bool> successes = await Future.wait(results);
|
|
|
|
return successes.every((final success) => success);
|
2023-01-29 17:46:11 -05:00
|
|
|
}
|
|
|
|
|
2023-02-01 17:18:06 -05:00
|
|
|
Future<bool> _downloadAlbum(
|
2023-01-29 17:18:41 -05:00
|
|
|
final FunkObject object,
|
|
|
|
final String path,
|
|
|
|
) async {
|
2023-01-26 16:35:58 -05:00
|
|
|
final response = await Dio().get(
|
|
|
|
'https://${object.domain}/api/v1/tracks/?'
|
|
|
|
'album=${object.id}&ordering=creation_date&'
|
|
|
|
'page=1&page_size=16&scope=all',
|
|
|
|
);
|
|
|
|
|
2023-02-04 02:23:51 -05:00
|
|
|
final String pathAppend = utils.sanitizePath(
|
|
|
|
response.data['results'][0]['album']['title'],
|
|
|
|
);
|
2023-02-01 17:18:06 -05:00
|
|
|
bool folderCreated = true;
|
|
|
|
try {
|
|
|
|
await Directory('$path/$pathAppend').create();
|
|
|
|
} catch (e) {
|
|
|
|
console.error(e.toString());
|
|
|
|
folderCreated = false;
|
|
|
|
}
|
|
|
|
if (!folderCreated) {
|
|
|
|
return false;
|
|
|
|
}
|
2023-01-31 02:37:32 -05:00
|
|
|
console.info('Album: $pathAppend');
|
2023-01-29 17:18:41 -05:00
|
|
|
|
2023-02-01 17:18:06 -05:00
|
|
|
final List<Future<bool>> results = [];
|
2023-01-29 17:18:41 -05:00
|
|
|
for (final songResponse in response.data['results']) {
|
2023-02-04 02:23:51 -05:00
|
|
|
final String songTitle = utils.sanitizePath(songResponse['title']);
|
2023-01-29 17:18:41 -05:00
|
|
|
final String ext = songResponse['uploads'][0]['extension'];
|
2023-02-04 01:24:05 -05:00
|
|
|
final result = _downloadTrackObject(
|
2023-01-29 17:18:41 -05:00
|
|
|
FunkObject(
|
|
|
|
domain: object.domain,
|
|
|
|
id: songResponse['listen_url'],
|
2023-02-04 01:24:05 -05:00
|
|
|
kind: FunkEntity.track,
|
2023-01-29 17:18:41 -05:00
|
|
|
),
|
|
|
|
'$path/$pathAppend/$songTitle.$ext',
|
|
|
|
);
|
2023-02-01 17:18:06 -05:00
|
|
|
|
|
|
|
results.add(result);
|
2023-01-29 17:18:41 -05:00
|
|
|
}
|
2023-02-01 17:18:06 -05:00
|
|
|
|
|
|
|
final List<bool> successes = await Future.wait(results);
|
|
|
|
return successes.every((final success) => success);
|
2023-01-29 17:18:41 -05:00
|
|
|
}
|
|
|
|
|
2023-02-04 01:24:05 -05:00
|
|
|
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',
|
|
|
|
);
|
|
|
|
|
2023-02-04 02:23:51 -05:00
|
|
|
final String songTitle = utils.sanitizePath(response.data['title']);
|
2023-02-04 01:24:05 -05:00
|
|
|
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(
|
2023-01-29 17:18:41 -05:00
|
|
|
final FunkObject object,
|
|
|
|
final String path,
|
|
|
|
) async {
|
2023-02-01 17:18:06 -05:00
|
|
|
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;
|
2023-01-26 16:35:58 -05:00
|
|
|
}
|