예제 #1
0
        ////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////

        /// <summary>
        /// Download a song
        /// </summary>
        /// <param name="p_Song">Beat map</param>
        /// <param name="p_Token">Cancellation token</param>
        /// <param name="p_Progress">Progress reporter</param>
        /// <param name="p_Direct">Skip download counter ?</param>
        /// <returns></returns>
        public static async Task <bool> DownloadSong(Beatmap p_Song, CancellationToken p_Token, IProgress <double> p_Progress = null, bool p_Direct = false)
        {
            /*
             * Code from https://github.com/Kylemc1413/BeatSaverDownloader
             *
             * MIT License
             *
             * Copyright (c) 2019 andruzzzhka
             *
             * Permission is hereby granted, free of charge, to any person obtaining a copy
             * of this software and associated documentation files (the "Software"), to deal
             * in the Software without restriction, including without limitation the rights
             * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
             * copies of the Software, and to permit persons to whom the Software is
             * furnished to do so, subject to the following conditions:
             *
             * The above copyright notice and this permission notice shall be included in all
             * copies or substantial portions of the Software.
             *
             * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
             * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
             * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
             * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
             * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
             * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
             * SOFTWARE.
             */

            p_Token.ThrowIfCancellationRequested();

            try
            {
                string l_CustomSongsPath = CustomLevelPathHelper.customLevelsDirectoryPath;

                if (!Directory.Exists(l_CustomSongsPath))
                {
                    Directory.CreateDirectory(l_CustomSongsPath);
                }

                var l_ZIPBytes = await p_Song.DownloadZip(p_Direct, p_Token, p_Progress).ConfigureAwait(false);

                Logger.Instance?.Info("[SDK.Game][BeatSaver] Downloaded zip!");

                return(await ExtractZipAsync(p_Token, p_Song, l_ZIPBytes, l_CustomSongsPath).ConfigureAwait(false));
            }
            catch (Exception p_Exception)
            {
                if (p_Exception is TaskCanceledException)
                {
                    Logger.Instance?.Warn("[SDK.Game][BeatSaver] Song Download Aborted.");
                    throw p_Exception;
                }
                else
                {
                    Logger.Instance?.Critical("[SDK.Game][BeatSaver] Failed to download Song!");
                }
            }

            return(false);
        }
예제 #2
0
        /// <summary>
        /// Download a song
        /// </summary>
        /// <param name="p_Song">Beat map</param>
        /// <param name="p_Token">Cancellation token</param>
        /// <param name="p_Progress">Progress reporter</param>
        /// <param name="p_Direct">Skip download counter ?</param>
        /// <returns></returns>
        public static async Task <bool> DownloadSong(Beatmap p_Song, CancellationToken p_Token, IProgress <double> p_Progress = null, bool p_Direct = false)
        {
            try
            {
                string l_CustomSongsPath = CustomLevelPathHelper.customLevelsDirectoryPath;

                if (!Directory.Exists(l_CustomSongsPath))
                {
                    Directory.CreateDirectory(l_CustomSongsPath);
                }

                var l_ZIPBytes = await p_Song.DownloadZip(p_Direct, p_Token, p_Progress).ConfigureAwait(false);

                Logger.Instance?.Info("Downloaded zip!");

                return(await ExtractZipAsync(p_Song, l_ZIPBytes, l_CustomSongsPath).ConfigureAwait(false));
            }
            catch (Exception p_Exception)
            {
                if (p_Exception is TaskCanceledException)
                {
                    Logger.Instance?.Warn("Song Download Aborted.");
                }
                else
                {
                    Logger.Instance?.Critical("Failed to download Song!");
                }
            }

            return(false);
        }
        private static async Task <byte[]> DownloadMap(Beatmap mapData)
        {
            try
            {
                byte[] zipData = await mapData.DownloadZip();

                return(zipData);
            }
            catch (Exception ex)
            {
                MessageBox.Show("Unable to download map zip: " + ex.ToString());
                return(null);
            }
        }
예제 #4
0
        private async Task DownloadAndExtractBeatMap(Beatmap beatMap, string bsFolderPath, int songNumber, int totalSongs)
        {
            var zipBytes = await beatMap.DownloadZip();

            var zipPath = Path.Combine($@"{bsFolderPath}\Beat Saber_Data\CustomLevels", $"{beatMap.Name}.zip");

            using (var memStream = new MemoryStream(zipBytes))
            {
                using (var writer = File.OpenWrite(zipPath))
                {
                    WriteToLog($"{songNumber + 1}/{totalSongs} | downloading {beatMap.Name}");

                    await memStream.CopyToAsync(writer).ConfigureAwait(false);

                    await writer.FlushAsync().ConfigureAwait(false);
                }
            }

            using (var beatMapZip = ZipFile.OpenRead(zipPath))
            {
                var beatMapFolderPath = Path.Combine($@"{bsFolderPath}\Beat Saber_Data\CustomLevels", $"{beatMap.Key} {beatMap.Name} - {beatMap.Uploader.Username}");
                Directory.CreateDirectory(beatMapFolderPath);
                WriteToLog($"{songNumber + 1}/{totalSongs} | unzipping {beatMap.Name}");

                foreach (var entry in beatMapZip.Entries)
                {
                    using (var zipEntryStream = entry.Open())
                        using (var writer = File.OpenWrite(Path.Combine(beatMapFolderPath, entry.Name)))
                        {
                            await zipEntryStream.CopyToAsync(writer).ConfigureAwait(false);

                            await writer.FlushAsync().ConfigureAwait(false);
                        }
                }
            }

            WriteToLog($"{songNumber + 1}/{totalSongs} | success downloading {beatMap.Name}");
            File.Delete(zipPath);
        }
예제 #5
0
        private static async Task <IPreviewBeatmapLevel?> DownloadSong(string hash, IProgress <double>?progress, CancellationToken cancellationToken)
        {
            Beatmap bm = await Plugin.BeatSaver.Hash(hash, cancellationToken);

            if (bm == null)
            {
                Plugin.Log?.Warn($"Could not find song '{hash}' on Beat Saver.");
                return(null);
            }

            byte[] beatmapBytes = await bm.DownloadZip(false, cancellationToken, progress);

            string folderPath = Utils.GetSongDirectoryName(bm.Key, bm.Metadata.SongName, bm.Metadata.SongAuthorName);

            folderPath = Path.Combine(CustomLevelsFolder, folderPath);
            using (var ms = new MemoryStream(beatmapBytes))
            {
                var result = await ZipUtils.ExtractZip(ms, folderPath);

                if (folderPath != result.OutputDirectory)
                {
                    folderPath = result.OutputDirectory ?? throw new Exception("Zip extract failed, no output directory.");
                }
                if (result.Exception != null)
                {
                    throw result.Exception;
                }
            }
            Plugin.Log.Info($"Downloaded song to '{folderPath}'");

            using (var awaiter = new EventAwaiter <SongCore.Loader, ConcurrentDictionary <string, CustomPreviewBeatmapLevel> >(cancellationToken))
            {
                try
                {
                    SongCore.Loader.SongsLoadedEvent += awaiter.OnEvent;

                    SongCore.Collections.AddSong($"custom_level_{hash}", folderPath);
                    SongCore.Loader.Instance.RefreshSongs(false);
                    await awaiter.Task;
                }
                catch (OperationCanceledException)
                {
                    return(null);
                }
                catch (Exception e)
                {
                    Plugin.Log?.Error($"Error waiting for songs to load: {e.Message}");
                    Plugin.Log?.Debug(e);
                    throw;
                }
                finally
                {
                    SongCore.Loader.SongsLoadedEvent -= awaiter.OnEvent;
                }
            }

            CustomPreviewBeatmapLevel?beatmap = SongCore.Loader.GetLevelByHash(hash);

            if (beatmap == null)
            {
                Plugin.Log?.Warn($"Couldn't get downloaded beatmap '{bm.Metadata.SongName ?? hash}' from SongCore, this shouldn't happen.");
            }
            return(beatmap);
        }