/// <summary> /// Updates the ID3 tags for the song file, then moves it into iTunes if the setting is enabled. /// </summary> public override bool Finish(bool close = true) { View.Report("Finalizing"); try { UpdateId3Tags(); AddToiTunes(); } catch (Exception e) { // Should have been handled already View.Report("Invalid file!", true); CrashHandler.Throw("Invalid file was downloaded!", e); return(false); } // Log the song genre to see how SDownload is used if (Genre != null && !Genre.Equals(String.Empty)) { BugSenseHandler.Instance.SendEventAsync(Genre); } base.Finish(close); return(true); }
/// <summary> /// Downloads and installs the newest version /// </summary> /// <param name="size">The size of the new version to download</param> private void DownloadAndInstall(int size) { var downloader = new DownloadProgressDialog(_fileUrl, size); var fileLocation = String.Format("{0}\\sdownload_update.exe", Path.GetTempPath()); try { LogUpdate(); } catch (Exception) { } if (downloader.Download(fileLocation)) { // Launch the installer and close the running instance try { Process.Start(fileLocation); } catch (Exception) { CrashHandler.Throw("There was an issue launching the update! You'll need to manually start the file: " + fileLocation, false); } Close(); Application.Exit(); } else { // There was an issue downloading the file CrashHandler.Throw("There was an issue downloading the update!", downloader.LastException); Close(); } }
/// <summary> /// Downloads the necessary files and handles any exceptions /// </summary> /// <param name="ignoreExtras">If the extra files associated with the main resource should be skipped</param> /// <returns>A task representation for keeping track of the method's progress</returns> public override async Task <bool> Download(bool ignoreExtras = false) { var result = await base.Download(ignoreExtras); if (!result) { // If the last attempt was manual, it's impossible if (_forceManual) { // Can ignore this being called for every reattempt, view will close and ignore View.Report("Impossible! :/", true); // Ignore songs that have streaming blocked and can't be downloaded, throw everything else if (LastException.Message.Contains("401")) { View.Report("Impossible! :/", true); } else { View.Report("Error!", true); CrashHandler.Throw("There was an issue downloading the necessary file(s)!", LastException); } } else { result = await RetryDownload(); } } return(result && await Validate()); }
/// <summary> /// Parse the given link and send it to the appropriate stream downloader /// </summary> /// <param name="url">The link provided to the application from the view</param> /// <param name="view">The view to report progress back to</param> /// <param name="exit">Exit after download?</param> public static async void DownloadTrack(String url, InfoReportProxy view, bool exit = false) { CrashHandler.AddExtra("stream_url", url); try { BaseStream sound; if (url.Contains(@"/sets/")) sound = new SCSetStream(url, view); else sound = new SCTrackStream(url, view); var download = sound.Download(); if (download != null && await download) sound.Finish(); } catch (Exception e) { CrashHandler.Throw("There was an issue downloading the stream!", e); } finally { CrashHandler.ClearExtras(); if (exit) { Application.Exit(); } } }
/// <summary> /// Confirms the file tags can actually be read, proving the file is valid. /// TODO: Possibly find a better way to validate more file types quicker /// TODO: perhaps by reading the resolved url ending rather than assuming mp3 immediately /// </summary> /// <returns>True if the file was downloaded correctly and can be modified</returns> public override async Task <bool> Validate() { var valid = false; var retry = false; SFile file = null; try { // Test if the file is a valid mp3 file = SFile.Create(MainResource.AbsolutePath); } catch (CorruptFileException) // File isn't mp3 { try { // Check if the file is wma var old = MainResource.AbsolutePath; MainResource.AbsolutePath = MainResource.AbsolutePath.Substring(0, MainResource.AbsolutePath.Length - 3) + "wma"; File.Move(old, MainResource.AbsolutePath); file = SFile.Create(MainResource.AbsolutePath); } catch (CorruptFileException e) // File isn't any supported type { File.Delete(MainResource.AbsolutePath); // If manual has already been attempted, this isn't possible retry = !_forceManual; if (!retry) { View.Report("Error!", true); CrashHandler.Throw("Unable to download a valid song format for editing!", e); } } } finally { if (file != null) { valid = true; file.Dispose(); } } // Retry the download if necessary if (retry) { valid = await RetryDownload(); } return(valid); }
/// <summary> /// Opens a url in Chrome /// </summary> /// <param name="url">The url to browse to</param> private void OpenUrlInBrowser(String url) { try { Process.Start("firefox", url); } catch (Exception) { try { Process.Start("explorer.exe", url); } catch (Exception e) { CrashHandler.Throw("There was an issue opening your browser! You can try manually navigating to " + url, e); } } }
/// <summary> /// Downloads the Sound representation and any extra files that accompany it /// <param name="ignoreExtras">If true, extra files will not be downloaded. (Useful for retrying the main download)</param> /// <returns>A boolean value representing if the download was successful or not</returns> /// </summary> public virtual async Task <bool> Download(bool ignoreExtras = false) { View.Report("Downloading..."); try { // Download the main resource if (MainResource == null) { CrashHandler.Throw("No resource has been registered for download!"); return(false); } var mainDownloader = new WebClient(); mainDownloader.DownloadProgressChanged += (sender, e) => View.UpdateProgress(e.ProgressPercentage); var resourceDownload = mainDownloader.DownloadFileTaskAsync(MainResource.Uri, MainResource.AbsolutePath); IEnumerable <Task> extraTasks = null; // Download additional files if (!ignoreExtras) { extraTasks = (from extra in Extras select DownloadExtra(extra)).ToList(); } await resourceDownload; var ret = Validate(); if (extraTasks != null) { foreach (var extra in extraTasks) { await extra; } } return(await ret); } catch (Exception e) { LastException = e; } return(false); }
/// <summary> /// Gets the download url for the main resource /// </summary> /// <returns>The URL the main resource can be downloaded at</returns> private String GetDownloadUrl() { var songDownload = (_trackData.DownloadUrl != null && Settings.UseDownloadLink && !_forceStream) ? _trackData.DownloadUrl : _trackData.StreamUrl; if (songDownload == null || _forceManual) { // There was no stream URL or download URL for the song, manually parse the resource stream link from the original URL BugSenseHandler.Instance.LeaveBreadCrumb("Manually downloading sound"); // Manual was forced, on failure we should abort _forceManual = true; HttpWebResponse response; try { var request = (HttpWebRequest)WebRequest.Create(_origUrl); response = (HttpWebResponse)request.GetResponse(); } catch (Exception e) { CrashHandler.Throw("Song does not allow streaming and there was an issue manually downloading the song file!", e, false); return(null); } var doc = new HtmlDocument(); doc.Load(response.GetResponseStream()); var searchString = WebUtility.HtmlDecode(doc.DocumentNode.InnerHtml); var links = Regex.Matches(searchString, "((http:[/][/])(media.soundcloud.com/stream/)([a-z]|[A-Z]|[0-9]|[/.]|[~]|[?]|[_]|[=])*)"); songDownload = links[0].Value; } // Pretend we forced stream, so on failure we attempt manual next if (songDownload.Equals(_trackData.StreamUrl)) { _forceStream = true; } return(songDownload + "?client_id=" + SCTrackData.ClientId); }
/// <summary> /// Checks if the current version is the newest version /// </summary> private static void CheckVersion(bool force = false) { // Don't check the version if the setting is disabled and we aren't being forced if (!force || !Settings.CheckForUpdates) { return; } try { // Query the remote Github API for newer releases var request = (HttpWebRequest)WebRequest.Create("https://api.github.com/repos/brkastner/SDownload/releases"); request.Method = WebRequestMethods.Http.Get; request.Accept = "application/vnd.github.v3+json"; request.UserAgent = "SDownload"; // Process response var response = request.GetResponse().GetResponseStream(); if (response == null) { throw new HandledException("There was an issue checking for updates!"); } var contract = new DataContractJsonSerializer(typeof(GithubReleaseItemContract[])).ReadObject(response) as GithubReleaseItemContract[]; if (contract == null) { throw new HandledException("Could not deserialize the version update information!", true); } var currentVersion = new int[3]; var i = 0; foreach (var num in (Application.ProductVersion).Split('.')) { currentVersion[i++] = Int32.Parse(num); } // Combine any new releases to get the changelog from each var newerReleases = (from release in contract let versionNumbers = (release.TagName.Remove(0, 1)).Split('.') where ((Int32.Parse(versionNumbers[0]) > currentVersion[0]) || // Major (Int32.Parse(versionNumbers[0]) == currentVersion[0] && // Minor Int32.Parse(versionNumbers[1]) > currentVersion[1]) || (Int32.Parse(versionNumbers[0]) == currentVersion[0] && // Incremental Int32.Parse(versionNumbers[1]) == currentVersion[1] && Int32.Parse(versionNumbers[2]) > currentVersion[2])) && !release.Draft // Ignore drafts select release).ToList(); // Remove beta updates if the option is disabled if (!Settings.EnableBetaUpdates) { newerReleases = (from release in newerReleases where !release.PreRelease select release).ToList(); } if (newerReleases.Count < 1) { return; } // Current version is not up to date, prompt the user to download the new version UpdateAvailableDialog.Prompt(newerReleases[0].Assets[0].Url, newerReleases); } catch (WebException e) { CrashHandler.Throw("Unable to make a connection to the SDownload API to check for updates!", e); } }