Skip to content

Commit

Permalink
Implement album download
Browse files Browse the repository at this point in the history
  • Loading branch information
Metalnem committed Mar 16, 2024
1 parent 20b7255 commit 8c66868
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 10 deletions.
2 changes: 1 addition & 1 deletion Api/Client.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ public async Task<Album> GetAlbum(long id)
};

var collection = await GetCollection(queryString);
return collection.Items.Single();
return collection.Items.SingleOrDefault();
}

public async IAsyncEnumerable<Album> GetCollection()
Expand Down
1 change: 1 addition & 0 deletions Api/Model/Track.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@ namespace Api.Model;
public class Track
{
public string Title { get; set; }
public int TrackNumber { get; set; }
public string HqAudioUrl { get; set; }
}
60 changes: 51 additions & 9 deletions Api/Program.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.CommandLine;
using System.IO.Compression;
using Microsoft.Extensions.Logging.Abstractions;

namespace Api;
Expand All @@ -7,9 +8,9 @@ public class Program
{
public static async Task Main(string[] args)
{
var username = CreateOption("--username", "Your Bandcamp account username.");
var password = CreateOption("--password", "Your Bandcamp account password.");
var album = CreateOption("--album", "ID of the album you want to download.");
var username = CreateOption<string>("--username", "Your Bandcamp account username.");
var password = CreateOption<string>("--password", "Your Bandcamp account password.");
var albumId = CreateOption<long>("--album", "ID of the album you want to download.");

var listCommand = new RootCommand("List all albums in your Bandcamp collection.")
{
Expand All @@ -21,12 +22,12 @@ public static async Task Main(string[] args)
{
username,
password,
album
albumId
};

listCommand.AddCommand(downloadCommand);
listCommand.SetHandler(List, username, password);
downloadCommand.SetHandler(Download, username, password, album);
downloadCommand.SetHandler(Download, username, password, albumId);

await listCommand.InvokeAsync(args);
}
Expand All @@ -45,14 +46,55 @@ private static async Task List(string username, string password)
}
}

private static void Download(string username, string password, string album)
private static async Task Download(string username, string password, long albumId)
{
throw new NotImplementedException();
using var client = new Client(username, password, NullLoggerFactory.Instance);

var album = await client.GetAlbum(albumId);

if (album == null)
{
throw new Exception($"Album {albumId} is not available.");
}

if (album.Tracks == null)
{
throw new Exception($"{album.Title} doesn't have any tracks.");
}

using var output = new MemoryStream();
using var httpClient = new HttpClient();

using (var archive = new ZipArchive(output, ZipArchiveMode.Create, true))
{
foreach (var track in album.Tracks)
{
var fileName = $"{track.TrackNumber:00}. {Utils.GetSafeFileName(track.Title)}.mp3";
var entry = archive.CreateEntry(fileName);

using var entryStream = entry.Open();
using var audioStream = await httpClient.GetStreamAsync(track.HqAudioUrl);

await audioStream.CopyToAsync(entryStream);
}
}

var artist = album.Artist ?? album.BandInfo.Name;
var archiveName = $"{artist} - {album.Title}";

using var file = File.Create(
path: $"{Utils.GetSafeFileName(archiveName)}.zip",
bufferSize: 4096,
options: FileOptions.Asynchronous
);

output.Position = 0;
await output.CopyToAsync(file);
}

private static Option<string> CreateOption(string name, string description)
private static Option<T> CreateOption<T>(string name, string description)
{
return new Option<string>(name, description)
return new Option<T>(name, description)
{
IsRequired = true
};
Expand Down

0 comments on commit 8c66868

Please sign in to comment.