/// <summary> /// Creates a SongInfo from a JObject. /// </summary> /// <param name="song"></param> /// <exception cref="ArgumentException">Thrown when a hash can't be found for the given song JObject.</exception> /// <returns></returns> public static ScrapedSong ParseSongFromJson(JToken song, Uri?sourceUri, bool storeRawData) { if (song == null) { throw new ArgumentNullException(nameof(song), "song cannot be null for BeatSaverReader.ParseSongFromJson."); } if (song["versions"] is JArray versions && versions.Count > 0) { JObject latest = GetLatestSongVersion(song); //JSONObject song = (JSONObject) aKeyValue; string? songKey = song["id"]?.Value <string>(); string? songHash = latest["hash"]?.Value <string>().ToUpper(); string? songName = song["metadata"]?["songName"]?.Value <string>(); string? mapperName = song["uploader"]?["name"]?.Value <string>(); DateTime uploadDate = song["uploaded"]?.Value <DateTime>() ?? DateTime.MinValue; if (songHash == null || songHash.Length == 0) { throw new ArgumentException("Unable to find hash for the provided song, is this a valid song JObject?"); } Uri downloadUri = WebUtils.GetDownloadUriByHash(songHash); ScrapedSong newSong = new ScrapedSong(songHash, songName, mapperName, downloadUri, sourceUri, storeRawData ? song as JObject : null) { Key = songKey, UploadDate = uploadDate }; return(newSong); }
/// <summary> /// Creates a SongInfo from a JObject. /// </summary> /// <param name="song"></param> /// <exception cref="ArgumentException">Thrown when a hash can't be found for the given song JObject.</exception> /// <returns></returns> public static ScrapedSong ParseSongFromJson(JObject song, Uri sourceUrl) { if (song == null) { throw new ArgumentNullException(nameof(song), "song cannot be null for BeatSaverReader.ParseSongFromJson."); } //JSONObject song = (JSONObject) aKeyValue; string songKey = song["key"]?.Value <string>(); string songHash = song["hash"]?.Value <string>().ToUpper(); var songName = song["name"]?.Value <string>(); var mapperName = song["uploader"]?["username"]?.Value <string>(); if (string.IsNullOrEmpty(songHash)) { throw new ArgumentException("Unable to find hash for the provided song, is this a valid song JObject?"); } string downloadUri = !string.IsNullOrEmpty(songKey) ? BEATSAVER_DOWNLOAD_URL_BASE + songKey : string.Empty; var newSong = new ScrapedSong(songHash) { DownloadUri = Utilities.GetUriFromString(downloadUri), SourceUri = sourceUrl, SongName = songName, SongKey = songKey, MapperName = mapperName, RawData = song.ToString() }; return(newSong); }
public async Task AndruzzProviderTest() { string filePath = Path.Combine("Data", "SongInfoProvider", "songDetails2_20210817"); var manager = new SongInfoManager(); SongFeedReaders.Logging.LoggingController.DefaultLogger = new SongFeedReaders.Logging.FeedReaderLogger(); var andruzz = new AndruzzScrapedInfoProvider(filePath) { CacheToDisk = false, AllowWebFetch = false }; manager.AddProvider(andruzz); Assert.IsFalse(andruzz.Available); var response = await manager.GetSongByKeyAsync("b"); Assert.IsTrue(andruzz.Available); Assert.IsTrue(response.Success); ScrapedSong song = response.Song ?? throw new AssertFailedException("Song is null"); Assert.AreEqual("B", song.Key); Assert.AreEqual("19F2879D11A91B51A5C090D63471C3E8D9B7AEE3", song.Hash); Assert.AreEqual("rustic", song.LevelAuthorName); Assert.AreEqual("Believer", song.Name); }
public void Success_Authors_LimitedSongs() { BeatSaverReader reader = new BeatSaverReader() { StoreRawData = true }; string[] authorList = new string[] { "BlackBlazon", "greatyazer", "joetastic" }; Dictionary <string, ScrapedSong> songList = new Dictionary <string, ScrapedSong>(); int maxSongs = 59; int maxPages = 10; SearchQueryBuilder queryBuilder = new SearchQueryBuilder(BeatSaverSearchType.author, null); foreach (string author in authorList) { queryBuilder.Criteria = author; BeatSaverFeedSettings settings = new BeatSaverFeedSettings((int)BeatSaverFeedName.Author) { SearchQuery = queryBuilder.GetQuery(), MaxSongs = maxSongs, MaxPages = maxPages }; FeedResult songsByAuthor = reader.GetSongsFromFeed(settings); Assert.IsTrue(songsByAuthor.Count > 0); Assert.IsTrue(songsByAuthor.Count <= maxSongs); int expectedPages = ExpectedPagesForSongs(songsByAuthor.Count); Assert.IsTrue(expectedPages <= songsByAuthor.PagesChecked); foreach (KeyValuePair <string, ScrapedSong> song in songsByAuthor.Songs) { songList.TryAdd(song.Key, song.Value); } } IEnumerable <string> detectedAuthors = songList.Values.Select(s => s.LevelAuthorName.ToLower()).Distinct(); foreach (KeyValuePair <string, ScrapedSong> song in songList) { Assert.IsTrue(song.Value.DownloadUri != null); Assert.IsTrue(authorList.Any(a => a.ToLower() == song.Value.LevelAuthorName.ToLower())); } foreach (string author in authorList) { Assert.IsTrue(songList.Any(s => s.Value.LevelAuthorName.ToLower() == author.ToLower())); } // BlackBlazon check string blazonHash = "58de2d709a45b68fdb1dbbfefb187f59f629bfc5".ToUpper(); ScrapedSong blazonSong = songList[blazonHash]; Assert.IsTrue(blazonSong != null); Assert.IsTrue(blazonSong.DownloadUri != null); // GreatYazer check string songHash = "bf8c016dc6b9832ece3030f05277bbbe67db790d".ToUpper(); ScrapedSong yazerSong = songList[songHash]; Assert.IsTrue(yazerSong != null); Assert.IsTrue(yazerSong.DownloadUri != null); var checkedPages = songList.Values.Select(s => s.SourceUri.OriginalString).Distinct().ToList(); checkedPages.ForEach(p => Console.WriteLine(p)); }
public void TryAdd_Song_NotInitialized() { var historyManager = new HistoryManager(HistoryTestPathDir); string hash = "LKSJDFLKJASDLFKJ"; string songName = "TestName"; string songKey = "aaaa"; string mapper = "SomeMapper"; ISong song = new ScrapedSong(hash, songName, mapper, songKey); Assert.ThrowsException <InvalidOperationException>(() => historyManager.TryAdd(song, 0)); }
public async Task BeatSaverProviderTest() { var manager = new SongInfoManager(); SongFeedReaders.Logging.LoggingController.DefaultLogger = new SongFeedReaders.Logging.FeedReaderLogger(); var beatSaver = new BeatSaverSongInfoProvider(); manager.AddProvider(beatSaver); var response = await manager.GetSongByKeyAsync("b"); Assert.IsTrue(response.Success); ScrapedSong song = response.Song ?? throw new AssertFailedException("Song is null"); Assert.AreEqual("B", song.Key); Assert.AreEqual("19F2879D11A91B51A5C090D63471C3E8D9B7AEE3", song.Hash); Assert.AreEqual("rustic", song.LevelAuthorName); Assert.AreEqual("Believer", song.Name); }
public void TryAdd_Song() { var path = Path.Combine(Path.Combine(HistoryTestPathDir, "BeatSyncHistory.json")); var historyManager = new HistoryManager(path); historyManager.Initialize(); string hash = "LKSJDFLKJASDLFKJ"; string songName = "TestName"; string songKey = "aaaa"; string mapper = "SomeMapper"; ISong song = new ScrapedSong(hash, songName, mapper, songKey); var success = historyManager.TryAdd(song, 0); Assert.IsTrue(success); success = historyManager.TryGetValue(hash, out var retrieved); Assert.IsTrue(success); Assert.AreEqual(song.ToString(), retrieved.SongInfo); }
public void TryAdd_Song_EmptyHash() { var path = Path.Combine(Path.Combine(HistoryTestPathDir, "BeatSyncHistory.json")); var historyManager = new HistoryManager(path); historyManager.Initialize(); string hash = ""; string songName = "TestName"; string songKey = "aaaa"; string mapper = "SomeMapper"; try { ISong song = new ScrapedSong(hash, songName, mapper, songKey); Assert.ThrowsException <InvalidOperationException>(() => historyManager.TryAdd(song, 0)); } catch (ArgumentNullException) { //Assert.Inconclusive("PlaylistSong.Hash can never be null or empty."); } }
public static PlaylistSong ToPlaylistSong(this ScrapedSong song) { return(new PlaylistSong(song.Hash, song.SongName, song.SongKey, song.MapperName)); }
public static async Task <ScrapedSong> GetSongByKeyAsync(string key, CancellationToken cancellationToken) { var uri = new Uri(BEATSAVER_DETAILS_BASE_URL + key); string pageText = ""; ScrapedSong song = null; IWebResponseMessage response = null; try { response = await WebUtils.GetBeatSaverAsync(uri, cancellationToken).ConfigureAwait(false); if (response.IsSuccessStatusCode) { pageText = await response.Content.ReadAsStringAsync().ConfigureAwait(false); } else { Logger?.Error($"Error getting song by key, {uri} responded with {response.StatusCode}:{response.ReasonPhrase}"); return(song); } if (string.IsNullOrEmpty(pageText)) { Logger?.Warning($"Unable to get web page at {uri}"); return(null); } } catch (WebClientException ex) { string errorText = string.Empty; if (ex.Response != null) { switch (ex.Response.StatusCode) { case 408: errorText = "Timeout"; break; default: errorText = "Site Error"; break; } } Logger?.Error($"{errorText} while trying to populate fields for {key}"); return(null); } catch (AggregateException ae) { ae.WriteExceptions($"Exception while trying to get details for {key}"); } catch (Exception ex) { Logger?.Exception($"Exception getting page {uri}", ex); throw; } finally { response?.Dispose(); response = null; } song = ParseSongsFromPage(pageText, uri).FirstOrDefault(); return(song); }
public static async Task <PageReadResult> GetSongByHashAsync(string hash, CancellationToken cancellationToken) { var uri = new Uri(BEATSAVER_GETBYHASH_BASE_URL + hash); ScrapedSong song = null; var pageError = PageErrorType.None; Exception exception = null; IWebResponseMessage response = null; try { response = await WebUtils.GetBeatSaverAsync(uri, cancellationToken).ConfigureAwait(false); response.EnsureSuccessStatusCode(); var pageText = await response.Content.ReadAsStringAsync().ConfigureAwait(false); song = ParseSongsFromPage(pageText, uri).FirstOrDefault(); } catch (WebClientException ex) { string errorText = string.Empty; if (ex.Response != null) { switch (ex.Response.StatusCode) { case 408: errorText = "Timeout"; break; default: errorText = "Site Error"; break; } } string message = $"{errorText} while trying to populate fields for {hash}"; Logger?.Error(message); exception = new FeedReaderException(message, ex, FeedReaderFailureCode.PageFailed); } catch (OperationCanceledException ex) { exception = new FeedReaderException(ex.Message, ex, FeedReaderFailureCode.Cancelled); } catch (AggregateException ae) { string message = $"Exception while trying to get details for {hash}"; ae.WriteExceptions(message); exception = new FeedReaderException(message, ae, FeedReaderFailureCode.Generic); } catch (Exception ex) { string message = $"Exception getting page {uri.ToString()}"; Logger?.Exception(message, ex); exception = new FeedReaderException(message, ex, FeedReaderFailureCode.Generic); } finally { response?.Dispose(); response = null; } List <ScrapedSong> retList = new List <ScrapedSong>(); if (song != null) { retList.Add(song); } return(new PageReadResult(uri, retList, exception, pageError)); }