예제 #1
0
        /// <summary>
        /// Downloads a score zip file to the destination directory
        /// </summary>
        /// <param name="listing">Search result listing</param>
        /// <param name="directory">Directory to unzip to</param>
        /// <returns>The created file or an error message</returns>
        public async Task <Result <string, string> > DownloadZip(LibrarySearchListing listing, string directory)
        {
            try
            {
                WebClient client = new WebClient();
                var       data   = await client.DownloadDataTaskAsync(new Uri(listing.DownloadLink));

                string filename;
                if (!string.IsNullOrEmpty(client.ResponseHeaders["Content-Disposition"]))
                {
                    filename = client.ResponseHeaders["Content-Disposition"]
                               .Substring(client.ResponseHeaders["Content-Disposition"]
                                          .IndexOf("filename=", StringComparison.Ordinal) + 9)
                               .Replace("\"", "");
                }
                else
                {
                    filename = $"PPDownload-{DateTime.Now:s}.zip";
                }

                var filePath = Path.Join(directory, filename);
                File.WriteAllBytes(filePath, data);
                return(Result.Success <string, string>(filePath));
            }
            catch (Exception e)
            {
                return(Result.Failure <string, string>(e.Message));
            }
        }
예제 #2
0
        public async Task InstallScore(LibrarySearchListing listing)
        {
            var installResult = await _downloader.DownloadUnzipWithVideoDefault(listing);

            if (installResult.IsFailure)
            {
                return; //todo:return information
            }

            var directory = installResult.Value;
            await _tracker.AddInstalledScore(listing, directory);
        }
예제 #3
0
        internal async Task AddInstalledScore(LibrarySearchListing listing, string installPath)
        {
            var score = new InstalledScore()
            {
                ScoreID        = listing.ScoreID,
                ScoreName      = listing.Title,
                TargetVideoURL = listing.VideoLink,
                DirectoryPath  = installPath
            };

            ScoreList.Add(score);
            await SaveInstalledScoreList();
        }
예제 #4
0
        public async void News39SearchTest()
        {
            LibraryScraper lib          = new LibraryScraper();
            var            searchScores = await lib.SearchScores("news");

            LibrarySearchListing news39   = searchScores.First();
            LibrarySearchListing expected = new LibrarySearchListing()
            {
                Author      = "Sakura-san (桜-さん)",
                BPM         = 132,
                Description =
                    "I've been working on this song for two weeks, so I really hope you will enjoy it :)",
                DownloadLink =
                    "https://projectdxxx.me/score-library/download/id/13c2aaad8377b9890b7b4fb03fbaa4d0",
                Downloads  = 384,
                Easy       = null,
                Evaluation = 4.14m,
                Evaluators = 37,
                Extreme    = 21.08m,
                Hard       = null,
                Length     = "3:41",
                Normal     = null,
                Title      = "News 39 ver桜-さん",
                Uploaded   = new DateTime(2018, 7, 17, 1, 5, 42),
                VideoLink  = "https://www.youtube.com/watch?v=l69v6SVoE9k",
                ScoreID    = "13c2aaad8377b9890b7b4fb03fbaa4d0"
            };

            Assert.Equal(expected.Author, news39.Author);
            Assert.Equal(expected.BPM, news39.BPM);
            Assert.Equal(expected.Description, news39.Description);
            Assert.Equal(expected.DownloadLink, news39.DownloadLink);
            Assert.True(news39.Downloads > 380);
            Assert.Equal(expected.Easy, news39.Easy);
            Assert.Equal(expected.Evaluation, news39.Evaluation);
            Assert.Equal(expected.Evaluators, news39.Evaluators);
            Assert.Equal(expected.Extreme, news39.Extreme);
            Assert.Equal(expected.Hard, news39.Hard);
            Assert.Equal(expected.Length, news39.Length);
            Assert.Equal(expected.Normal, news39.Normal);
            Assert.Equal(expected.Title, news39.Title);
            Assert.Equal(expected.Uploaded, news39.Uploaded);
            Assert.Equal(expected.VideoLink, news39.VideoLink);
            Assert.Equal(expected.ScoreID, news39.ScoreID);
        }
예제 #5
0
        /// <summary>
        /// Downloads a score zip to memory, unzips it to the destination folder, and downloads the target video for the score
        /// </summary>
        /// <param name="listing">Search result listing</param>
        /// <param name="directory">Directory to unzip to</param>
        /// <returns>The created directory or an error message</returns>
        public async Task <Result <string, string> > DownloadUnzipWithVideo(LibrarySearchListing listing, string directory)
        {
            try
            {
                var unzipResult = await DownloadAndUnzip(listing, directory);

                if (unzipResult.IsFailure)
                {
                    return(unzipResult);
                }

                var directoryPath = unzipResult.Value;
                var youtube       = YouTube.Default;
                var video         = youtube.GetVideo(listing.VideoLink);
                var videoPath     = Path.Join(directoryPath, video.FullName);
                File.WriteAllBytes(videoPath, video.GetBytes());
                return(Result.Success <string, string>(directoryPath));
            }
            catch (Exception e)
            {
                return(Result.Failure <string, string>(e.Message));
            }
        }
예제 #6
0
        /// <summary>
        /// Downloads the score zip to memory, then unzips into the destination directory
        /// </summary>
        /// <param name="listing">Search result listing</param>
        /// <param name="directory">Directory to unzip to</param>
        /// <returns>The created directory or the error message</returns>
        public async Task <Result <string, string> > DownloadAndUnzip(LibrarySearchListing listing, string directory)
        {
            try
            {
                WebClient client = new WebClient();
                var       data   = await client.DownloadDataTaskAsync(new Uri(listing.DownloadLink));

                using var stream  = new MemoryStream(data);
                using var archive = new ZipArchive(stream, ZipArchiveMode.Read);
                var newDirectoryName = archive.Entries.FirstOrDefault()?.FullName.Split('/')[0];
                if (string.IsNullOrEmpty(newDirectoryName))
                {
                    return(Result.Failure <string, string>("Could not resolve new directory name, aborting."));
                }

                archive.ExtractToDirectory(directory, true);
                return(Result.Success <string, string>(Path.Join(directory, newDirectoryName)));
            }
            catch (Exception e)
            {
                return(Result.Failure <string, string>(e.Message));
            }
        }
예제 #7
0
        private Result <LibrarySearchListing, string> ParseSearchListing(IElement root)
        {
            var title = root.QuerySelector("div.panel-heading > h3 > div > a")?.InnerHtml.CleanInnerHtml() ?? "";

            if (string.IsNullOrEmpty(title))
            {
                return(Result.Failure <LibrarySearchListing, string>("Could not retrieve title."));
            }

            var id = root.QuerySelector("div.panel-heading > h3 > div > a")?.Attributes["href"].Value.Split('/')
                     .LastOrDefault() ?? "";

            if (string.IsNullOrEmpty(id))
            {
                return(Result.Failure <LibrarySearchListing, string>("Could not retrieve ID."));
            }

            var author = root.QuerySelector("div.panel-heading > div.pull-right > a")?.Text()?.CleanInnerHtml();

            if (string.IsNullOrEmpty(author))
            {
                return(Result.Failure <LibrarySearchListing, string>("Could not retrieve author."));
            }

            var description = root.QuerySelector("div.panel-body > div.clearfix")?.InnerHtml.CleanInnerHtml() ?? "";

            if (string.IsNullOrEmpty(description))
            {
                return(Result.Failure <LibrarySearchListing, string>("Could not retrieve description."));
            }

            var uploadedStr = root.QuerySelector("div.panel-body > div.pull-right > span")?.InnerHtml.Replace("投稿", "")
                              .Replace("Uploaded", "").CleanInnerHtml() ?? "";

            if (string.IsNullOrEmpty(uploadedStr))
            {
                return(Result.Failure <LibrarySearchListing, string>("Could not retrieve upload date."));
            }

            var vidLink = root.QuerySelector("div.panel-body > div.pull-right > input")?.Attributes?["value"]?.Value ??
                          "";

            if (string.IsNullOrEmpty(vidLink))
            {
                return(Result.Failure <LibrarySearchListing, string>("Could not retrieve youtube link."));
            }

            var downloadLink = root.QuerySelector("div.panel-body > div.pull-right > a:nth-child(3)")
                               ?.Attributes?["href"]?.Value ?? "";

            if (string.IsNullOrEmpty(downloadLink))
            {
                return(Result.Failure <LibrarySearchListing, string>("Could not retrieve download link."));
            }

            downloadLink = "https://projectdxxx.me" + downloadLink;

            var difficultyTable = root.QuerySelector("table > tbody > tr:nth-of-type(2)");
            var easyStr         = difficultyTable?.QuerySelector("td:nth-of-type(1)")?.InnerHtml.CleanInnerHtml()
                                  .Replace("pt", "") ?? "";
            var normalStr = difficultyTable?.QuerySelector("td:nth-of-type(2)")?.InnerHtml.CleanInnerHtml()
                            .Replace("pt", "") ?? "";
            var hardStr = difficultyTable?.QuerySelector("td:nth-of-type(3)")?.InnerHtml.CleanInnerHtml()
                          .Replace("pt", "") ?? "";
            var extremeStr = difficultyTable?.QuerySelector("td:nth-of-type(4)")?.InnerHtml.CleanInnerHtml()
                             .Replace("pt", "") ?? "";
            var downloadsStr = difficultyTable?.QuerySelector("td:nth-of-type(5)")?.InnerHtml.CleanInnerHtml() ?? "";
            var bpmStr       = difficultyTable?.QuerySelector("td:nth-of-type(6)")?.InnerHtml.CleanInnerHtml() ?? "";
            var evalStr      = difficultyTable?.QuerySelector("td:nth-of-type(7)")?.InnerHtml.CleanInnerHtml() ?? "";
            var length       = difficultyTable?.QuerySelector("td:nth-of-type(8)")?.InnerHtml.CleanInnerHtml() ?? "";

            var evalScoreStr = Regex.Match(evalStr, @"([0-9].[0-9]+)\(\<span").Groups[1].Captures.FirstOrDefault()
                               ?.Value;
            var evalCountStr = Regex.Match(evalStr, @"span\>([0-9]+)\)").Groups[1].Captures.FirstOrDefault()?.Value;


            var easy      = easyStr.ParseDecimalNullable();
            var normal    = normalStr.ParseDecimalNullable();
            var hard      = hardStr.ParseDecimalNullable();
            var extreme   = extremeStr.ParseDecimalNullable();
            var downloads = downloadsStr.ParseIntNullable();
            var bpm       = bpmStr.ParseIntNullable();
            var evalScore = evalScoreStr.ParseDecimalNullable();
            var evalCount = evalCountStr.ParseIntNullable();

            var uploadDate = DateTime.Parse(uploadedStr);

            var result = new LibrarySearchListing()
            {
                Author       = author,
                BPM          = bpm,
                Description  = description,
                DownloadLink = downloadLink,
                Downloads    = downloads,
                Easy         = easy,
                Normal       = normal,
                Hard         = hard,
                Extreme      = extreme,
                Evaluation   = evalScore,
                Evaluators   = evalCount,
                Length       = length,
                Title        = title,
                Uploaded     = uploadDate,
                VideoLink    = vidLink,
                ScoreID      = id
            };


            return(Result.Success <LibrarySearchListing, string>(result));
        }
예제 #8
0
 internal async Task UninstallScore(LibrarySearchListing listing)
 {
     ScoreList.RemoveAll(x => x.ScoreID == listing.ScoreID);
     await SaveInstalledScoreList();
 }
예제 #9
0
 internal bool IsInstalled(LibrarySearchListing listing) => ScoreList.Any(x => x.ScoreID == listing.ScoreID);
 public LibrarySearchResultViewModel(LibrarySearchListing listing, PpdManager manager)
 {
     _listing     = listing;
     _manager     = manager;
     DownloadSong = ReactiveCommand.Create(() => { _manager.InstallScore(_listing); });
 }
예제 #11
0
 public async Task DownloadSong(LibrarySearchListing listing)
 {
     await _downloader.DownloadUnzipWithVideoDefault(listing);
 }
예제 #12
0
 public async Task UninstallScore(LibrarySearchListing listing) => await _tracker.UninstallScore(listing);