/// <summary> /// Returns the albums located at the specified URLs. /// </summary> /// <param name="urls">The URLs.</param> private async Task <List <Album> > GetAlbumsAsync(List <string> urls) { var albums = new List <Album>(); foreach (string url in urls) { LogAdded(this, new LogArgs($"Retrieving album data for {url}", LogType.Info)); // Retrieve URL HTML source code string htmlCode = ""; using (var webClient = new WebClient() { Encoding = Encoding.UTF8 }) { ProxyHelper.SetProxy(webClient); if (_cancelDownloads) { // Abort return(new List <Album>()); } try { htmlCode = await webClient.DownloadStringTaskAsync(url); } catch { LogAdded(this, new LogArgs($"Could not retrieve data for {url}", LogType.Error)); continue; } } // Get info on album try { Album album = BandcampHelper.GetAlbum(htmlCode); if (album.Tracks.Count > 0) { albums.Add(album); } else { LogAdded(this, new LogArgs($"No tracks found for {url}, album will not be downloaded", LogType.Warning)); } } catch { LogAdded(this, new LogArgs($"Could not retrieve album info for {url}", LogType.Error)); continue; } } return(albums); }
/// <summary> /// Downloads the changelog file and returns its content. /// </summary> private async Task <string> DownloadChangelogAsync() { string changelog; using (var webClient = new WebClient() { Encoding = Encoding.UTF8 }) { ProxyHelper.SetProxy(webClient); changelog = await webClient.DownloadStringTaskAsync(Constants.UrlChangelog); } return(changelog); }
private async void ButtonDownloadUpdate_Click(object sender, RoutedEventArgs e) { string[] parts = Constants.UrlReleaseZip.Split(new char[] { '/' }); string defaultFileName = parts[parts.Length - 1]; var dialog = new SaveFileDialog { FileName = defaultFileName, Filter = "Archive|*.zip", Title = Properties.Resources.saveFileDialogTitle, }; if (dialog.ShowDialog() != System.Windows.Forms.DialogResult.OK) { return; } string path = dialog.FileName; string zipUrl = string.Format(Constants.UrlReleaseZip, _latestVersion.ToString()); using (var webClient = new WebClient()) { ProxyHelper.SetProxy(webClient); await webClient.DownloadFileTaskAsync(zipUrl, path); } }
/// <summary> /// Returns the artists discography from any URL (artist, album, track). /// </summary> /// <param name="urls">The URLs.</param> private async Task <List <string> > GetArtistDiscographyAsync(List <string> urls) { var albumsUrls = new List <string>(); foreach (string url in urls) { LogAdded(this, new LogArgs($"Retrieving artist discography from {url}", LogType.Info)); // Retrieve URL HTML source code string htmlCode = ""; using (var webClient = new WebClient() { Encoding = Encoding.UTF8 }) { ProxyHelper.SetProxy(webClient); if (_cancelDownloads) { // Abort return(new List <string>()); } try { htmlCode = await webClient.DownloadStringTaskAsync(url); } catch { LogAdded(this, new LogArgs($"Could not retrieve data for {url}", LogType.Error)); continue; } } // Get artist "music" bandcamp page (http://artist.bandcamp.com/music) var regex = new Regex("band_url = \"(?<url>.*)\""); if (!regex.IsMatch(htmlCode)) { LogAdded(this, new LogArgs($"No discography could be found on {url}. Try to uncheck the \"Download artist discography\" option", LogType.Error)); continue; } string artistMusicPage = regex.Match(htmlCode).Groups["url"].Value + "/music"; // Retrieve artist "music" page HTML source code using (var webClient = new WebClient() { Encoding = Encoding.UTF8 }) { ProxyHelper.SetProxy(webClient); if (_cancelDownloads) { // Abort return(new List <string>()); } try { htmlCode = await webClient.DownloadStringTaskAsync(artistMusicPage); } catch { LogAdded(this, new LogArgs($"Could not retrieve data for {artistMusicPage}", LogType.Error)); continue; } } // Get albums referred on the page regex = new Regex("TralbumData.*\n.*url:.*'/music'\n"); if (!regex.IsMatch(htmlCode)) { // This seem to be a one-album artist with no "music" page => URL redirects to the unique album URL albumsUrls.Add(url); } else { // We are on a real "music" page try { albumsUrls.AddRange(BandcampHelper.GetAlbumsUrl(htmlCode)); } catch (NoAlbumFoundException) { LogAdded(this, new LogArgs($"No referred album could be found on {artistMusicPage}. Try to uncheck the \"Download artist discography\" option", LogType.Error)); continue; } } } return(albumsUrls.Distinct().ToList()); }
/// <summary> /// Downloads and returns the cover art of the specified album. Depending on UserSettings, save the cover art in /// the album folder. /// </summary> /// <param name="album">The album.</param> private async Task <TagLib.Picture> DownloadCoverArtAsync(Album album) { TagLib.Picture artworkInTags = null; int tries = 0; bool artworkDownloaded = false; TrackFile currentFile = DownloadingFiles.Where(f => f.Url == album.ArtworkUrl).First(); do { if (_cancelDownloads) { // Abort return(null); } using (var webClient = new WebClient()) { ProxyHelper.SetProxy(webClient); // Update progress bar when downloading webClient.DownloadProgressChanged += (s, e) => { currentFile.BytesReceived = e.BytesReceived; }; // Register current download _cancellationTokenSource.Token.Register(webClient.CancelAsync); // Start download try { await webClient.DownloadFileTaskAsync(album.ArtworkUrl, album.ArtworkTempPath); artworkDownloaded = true; } catch (WebException ex) when(ex.Status == WebExceptionStatus.RequestCanceled) { // Downloads cancelled by the user return(null); } catch (TaskCanceledException) { // Downloads cancelled by the user return(null); } catch (WebException) { // Connection closed probably because no response from Bandcamp if (tries < App.UserSettings.DownloadMaxTries) { LogAdded(this, new LogArgs($"Unable to download artwork for album \"{album.Title}\". Try {tries + 1} of {App.UserSettings.DownloadMaxTries}", LogType.Warning)); } else { LogAdded(this, new LogArgs($"Unable to download artwork for album \"{album.Title}\". Hit max retries of {App.UserSettings.DownloadMaxTries}", LogType.Error)); } } if (artworkDownloaded) { // Convert/resize artwork to be saved in album folder if (App.UserSettings.SaveCoverArtInFolder && (App.UserSettings.CoverArtInFolderConvertToJpg || App.UserSettings.CoverArtInFolderResize)) { var settings = new ResizeSettings(); if (App.UserSettings.CoverArtInFolderConvertToJpg) { settings.Format = "jpg"; settings.Quality = 90; } if (App.UserSettings.CoverArtInFolderResize) { settings.MaxHeight = App.UserSettings.CoverArtInFolderMaxSize; settings.MaxWidth = App.UserSettings.CoverArtInFolderMaxSize; } await Task.Run(() => { ImageBuilder.Current.Build(album.ArtworkTempPath, album.ArtworkPath, settings); // Save it to the album folder }); } else if (App.UserSettings.SaveCoverArtInFolder) { await FileHelper.CopyFileAsync(album.ArtworkTempPath, album.ArtworkPath); } // Convert/resize artwork to be saved in tags if (App.UserSettings.SaveCoverArtInTags && (App.UserSettings.CoverArtInTagsConvertToJpg || App.UserSettings.CoverArtInTagsResize)) { var settings = new ResizeSettings(); if (App.UserSettings.CoverArtInTagsConvertToJpg) { settings.Format = "jpg"; settings.Quality = 90; } if (App.UserSettings.CoverArtInTagsResize) { settings.MaxHeight = App.UserSettings.CoverArtInTagsMaxSize; settings.MaxWidth = App.UserSettings.CoverArtInTagsMaxSize; } await Task.Run(() => { ImageBuilder.Current.Build(album.ArtworkTempPath, album.ArtworkTempPath, settings); // Save it to %Temp% }); } artworkInTags = new TagLib.Picture(album.ArtworkTempPath) { Description = "Picture" }; try { File.Delete(album.ArtworkTempPath); } catch { // Could not delete the file. Nevermind, it's in %Temp% folder... } // Note the file as downloaded currentFile.Downloaded = true; LogAdded(this, new LogArgs($"Downloaded artwork for album \"{album.Title}\"", LogType.IntermediateSuccess)); } tries++; if (!artworkDownloaded && tries < App.UserSettings.DownloadMaxTries) { await WaitForCooldownAsync(tries); } } } while (!artworkDownloaded && tries < App.UserSettings.DownloadMaxTries); return(artworkInTags); }
/// <summary> /// Downloads and tags a track. Returns true if the track has been correctly downloaded; false otherwise. /// </summary> /// <param name="album">The album of the track to download.</param> /// <param name="track">The track to download.</param> /// <param name="artwork">The cover art.</param> private async Task <bool> DownloadAndTagTrackAsync(Album album, Track track, TagLib.Picture artwork) { LogAdded(this, new LogArgs($"Downloading track \"{track.Title}\" from url: {track.Mp3Url}", LogType.VerboseInfo)); int tries = 0; bool trackDownloaded = false; TrackFile currentFile = DownloadingFiles.Where(f => f.Url == track.Mp3Url).First(); if (File.Exists(track.Path)) { long length = new FileInfo(track.Path).Length; if (currentFile.Size > length - (currentFile.Size * App.UserSettings.AllowedFileSizeDifference) && currentFile.Size < length + (currentFile.Size * App.UserSettings.AllowedFileSizeDifference)) { LogAdded(this, new LogArgs($"Track already exists within allowed file size range: track \"{Path.GetFileName(track.Path)}\" from album \"{album.Title}\" - Skipping download!", LogType.IntermediateSuccess)); return(false); } } do { if (_cancelDownloads) { // Abort return(false); } using (var webClient = new WebClient()) { ProxyHelper.SetProxy(webClient); // Update progress bar when downloading webClient.DownloadProgressChanged += (s, e) => { currentFile.BytesReceived = e.BytesReceived; }; // Register current download _cancellationTokenSource.Token.Register(webClient.CancelAsync); // Start download try { await webClient.DownloadFileTaskAsync(track.Mp3Url, track.Path); trackDownloaded = true; LogAdded(this, new LogArgs($"Downloaded track \"{track.Title}\" from url: {track.Mp3Url}", LogType.VerboseInfo)); } catch (WebException ex) when(ex.Status == WebExceptionStatus.RequestCanceled) { // Downloads cancelled by the user return(false); } catch (TaskCanceledException) { // Downloads cancelled by the user return(false); } catch (WebException) { // Connection closed probably because no response from Bandcamp if (tries + 1 < App.UserSettings.DownloadMaxTries) { LogAdded(this, new LogArgs($"Unable to download track \"{Path.GetFileName(track.Path)}\" from album \"{album.Title}\". Try {tries + 1} of {App.UserSettings.DownloadMaxTries}", LogType.Warning)); } else { LogAdded(this, new LogArgs($"Unable to download track \"{Path.GetFileName(track.Path)}\" from album \"{album.Title}\". Hit max retries of {App.UserSettings.DownloadMaxTries}", LogType.Error)); } } if (trackDownloaded) { if (App.UserSettings.ModifyTags) { // Tag (ID3) the file when downloaded var tagFile = TagLib.File.Create(track.Path); tagFile = TagHelper.UpdateArtist(tagFile, album.Artist, App.UserSettings.TagArtist); tagFile = TagHelper.UpdateAlbumArtist(tagFile, album.Artist, App.UserSettings.TagAlbumArtist); tagFile = TagHelper.UpdateAlbumTitle(tagFile, album.Title, App.UserSettings.TagAlbumTitle); tagFile = TagHelper.UpdateAlbumYear(tagFile, (uint)album.ReleaseDate.Year, App.UserSettings.TagYear); tagFile = TagHelper.UpdateTrackNumber(tagFile, (uint)track.Number, App.UserSettings.TagTrackNumber); tagFile = TagHelper.UpdateTrackTitle(tagFile, track.Title, App.UserSettings.TagTrackTitle); tagFile = TagHelper.UpdateTrackLyrics(tagFile, track.Lyrics, App.UserSettings.TagLyrics); tagFile = TagHelper.UpdateComments(tagFile, App.UserSettings.TagComments); tagFile.Save(); LogAdded(this, new LogArgs($"Tags saved for track \"{Path.GetFileName(track.Path)}\" from album \"{album.Title}\"", LogType.VerboseInfo)); } if (App.UserSettings.SaveCoverArtInTags && artwork != null) { // Save cover in tags when downloaded var tagFile = TagLib.File.Create(track.Path); tagFile.Tag.Pictures = new TagLib.IPicture[1] { artwork }; tagFile.Save(); LogAdded(this, new LogArgs($"Cover art saved in tags for track \"{Path.GetFileName(track.Path)}\" from album \"{album.Title}\"", LogType.VerboseInfo)); } // Note the file as downloaded currentFile.Downloaded = true; LogAdded(this, new LogArgs($"Downloaded track \"{Path.GetFileName(track.Path)}\" from album \"{album.Title}\"", LogType.IntermediateSuccess)); } tries++; if (!trackDownloaded && tries < App.UserSettings.DownloadMaxTries) { await WaitForCooldownAsync(tries); } } } while (!trackDownloaded && tries < App.UserSettings.DownloadMaxTries); return(trackDownloaded); }
/// <summary> /// Returns the artists discography from any URL (artist, album, track). /// </summary> /// <param name="urls">The URLs.</param> private async Task <List <string> > GetArtistDiscographyAsync(List <string> urls) { var albumsUrls = new List <string>(); foreach (string url in urls) { LogAdded(this, new LogArgs($"Retrieving artist discography from {url}", LogType.Info)); // Retrieve URL HTML source code string htmlCode = ""; using (var webClient = new WebClient() { Encoding = Encoding.UTF8 }) { ProxyHelper.SetProxy(webClient); if (_cancelDownloads) { // Abort return(new List <string>()); } try { htmlCode = await webClient.DownloadStringTaskAsync(url); } catch { LogAdded(this, new LogArgs($"Could not retrieve data for {url}", LogType.Error)); continue; } } // Get artist "music" bandcamp page (http://artist.bandcamp.com/music) var regex = new Regex("https?://[^/]*"); string artistPage = regex.Match(url).ToString(); string artistMusicPage = artistPage + "/music"; // Retrieve artist "music" page HTML source code using (var webClient = new WebClient() { Encoding = Encoding.UTF8 }) { ProxyHelper.SetProxy(webClient); if (_cancelDownloads) { // Abort return(new List <string>()); } try { htmlCode = await webClient.DownloadStringTaskAsync(artistMusicPage); } catch { LogAdded(this, new LogArgs($"Could not retrieve data for {artistMusicPage}", LogType.Error)); continue; } } int count = albumsUrls.Count; try { albumsUrls.AddRange(BandcampHelper.GetAlbumsUrl(htmlCode, artistPage)); } catch (NoAlbumFoundException) { LogAdded(this, new LogArgs($"No referred album could be found on {artistMusicPage}. Try to uncheck the \"Download artist discography\" option", LogType.Error)); } if (albumsUrls.Count - count == 0) { // This seem to be a one-album artist with no "music" page => URL redirects to the unique album URL albumsUrls.Add(url); } } return(albumsUrls.Distinct().ToList()); }