/// <summary> /// Gets the lyrics for a track asynchronously (cached). /// </summary> /// <param name="artist">the artist name (e.g. Coldplay)</param> /// <param name="title">the title of the track (e.g. "Adventure of a Lifetime")</param> /// <param name="cancellationToken"> /// a cancellation token that can be used by other objects or threads to receive notice /// of cancellation. /// </param> /// <returns> /// a task that represents the asynchronous operation. The task result is the track /// found for the query /// </returns> /// <exception cref="ArgumentNullException"> /// thrown if the specified <paramref name="artist"/> is blank. /// </exception> /// <exception cref="ArgumentNullException"> /// thrown if the specified <paramref name="title"/> is blank. /// </exception> /// <exception cref="ObjectDisposedException">thrown if the instance is disposed.</exception> public async Task <string> GetLyricsAsync(string artist, string title, CancellationToken cancellationToken = default) { EnsureNotDisposed(); if (string.IsNullOrWhiteSpace(artist)) { throw new ArgumentException("The specified artist cannot be blank.", nameof(artist)); } if (string.IsNullOrWhiteSpace(title)) { throw new ArgumentException("The specified title cannot be blank.", nameof(title)); } // the cache key var key = $"lyrics-{artist}-{title}"; // check if the item is cached if (_cache != null && _cache.TryGetItem <string>(key, out var item)) { return(item); } var response = await RequestLyricsAsync(artist, title, cancellationToken); _cache?.AddItem(key, response, DateTimeOffset.UtcNow + _cacheTime); return(response); }
/// <summary> /// Loads the tracks specified by the <paramref name="query"/> asynchronously. /// </summary> /// <param name="query">the search query</param> /// <param name="mode">the track search mode</param> /// <param name="noCache"> /// a value indicating whether the track should be returned from cache, if it is cached. /// Note this parameter does only take any effect is a cache provider is specified in constructor. /// </param> /// <param name="cancellationToken"> /// a cancellation token that can be used by other objects or threads to receive notice /// of cancellation. /// </param> /// <returns> /// a task that represents the asynchronous operation. The task result is the request /// response for the specified <paramref name="query"/>. /// </returns> public async Task <TrackLoadResponsePayload> LoadTracksAsync(string query, SearchMode mode = SearchMode.None, bool noCache = false, CancellationToken cancellationToken = default) { cancellationToken.ThrowIfCancellationRequested(); var isUrl = query.StartsWith("http://", StringComparison.InvariantCultureIgnoreCase) || query.StartsWith("https://", StringComparison.InvariantCultureIgnoreCase); if (!isUrl) { if (mode == SearchMode.SoundCloud) { query = "scsearch:" + query; } else if (mode == SearchMode.YouTube) { query = "ytsearch:" + query; } } // escape query for passing via URI query = Uri.EscapeDataString(query); // check if a cache provider is specified in constructor and the track request is cached // and caching is wanted (see: "noCache" method parameter) if (_cache != null && !noCache && _cache.TryGetItem <TrackLoadResponsePayload>("track-" + query, out var track)) { _logger?.Log(this, string.Format("Loaded track from cache `{0}`.", query), LogLevel.Debug); return(track); } _logger?.Log(this, string.Format("Loading track '{0}'...", query), LogLevel.Debug); using (var response = await _httpClient.GetAsync($"loadtracks?identifier={query}", cancellationToken)) { VerifyResponse(response); var responseContent = await response.Content.ReadAsStringAsync(); if (_debugPayloads) { _logger?.Log(this, string.Format("Got response for track load: `{0}`: {1}.", query, responseContent), LogLevel.Debug); } var trackLoad = JsonConvert.DeserializeObject <TrackLoadResponsePayload>(responseContent); // cache (if a cache provider is specified) _cache?.AddItem("track-" + query, trackLoad, DateTimeOffset.UtcNow + _cacheTime); return(trackLoad); } }