├── DiscogsClient ├── Data │ ├── Result │ │ ├── DiscogsSortOrder.cs │ │ ├── DiscogsImageType.cs │ │ ├── DiscogsEntity.cs │ │ ├── DiscogsTrack.cs │ │ ├── DiscogsArtistSortType.cs │ │ ├── DiscogsRating.cs │ │ ├── DiscogsUser.cs │ │ ├── DiscogsCommunityInfo.cs │ │ ├── DiscogsSublabel.cs │ │ ├── DiscogsCommunityReleaseRating.cs │ │ ├── DiscogsIdentifier.cs │ │ ├── DiscogsReleaseRating.cs │ │ ├── DiscogsGroupOrBandMember.cs │ │ ├── DiscogsPaginableResults.cs │ │ ├── DiscogsIdentity.cs │ │ ├── DiscogsFormat.cs │ │ ├── DiscogsPaginedUrls.cs │ │ ├── DiscogsVideo.cs │ │ ├── DiscogsPaginedResult.cs │ │ ├── DiscogsLabelReleases.cs │ │ ├── DiscogsSearchResults.cs │ │ ├── DiscogsArtistReleases.cs │ │ ├── DiscogsReleaseVersions.cs │ │ ├── DiscogsReleaseLabel.cs │ │ ├── DiscogsCommunity.cs │ │ ├── DiscogsReleaseArtist.cs │ │ ├── DiscogsLabelRelease.cs │ │ ├── DiscogsMaster.cs │ │ ├── DiscogsImage.cs │ │ ├── DiscogsSubtrack.cs │ │ ├── DiscogsArtistRelease.cs │ │ ├── DiscogsLabel.cs │ │ ├── DiscogsReleaseBase.cs │ │ ├── DiscogsReleaseVersion.cs │ │ ├── DiscogsArtist.cs │ │ ├── DiscogsSearchResult.cs │ │ └── DiscogsRelease.cs │ └── Query │ │ ├── DiscogsImageType.cs │ │ ├── DiscogsEntityType.cs │ │ ├── DiscogsPaginable.cs │ │ ├── DiscogsSortInformation.cs │ │ └── DiscogsSearch.cs ├── DiscogsException.cs ├── Internal │ ├── TokenAuthenticationInformation.cs │ ├── IDiscogsWebClient.cs │ └── DiscogsWebClient.cs ├── DiscogsAuthentifierClient.cs ├── IDiscogsUserIdentityClient.cs ├── DiscogsClient.csproj ├── IDiscogsReleaseRatingClient.cs ├── DiscogsClient.cs └── IDiscogsDataBaseClient.cs ├── DiscogsAuthenticationConsole ├── App.config ├── packages.config ├── Program.cs ├── Properties │ └── AssemblyInfo.cs └── DiscogsAuthenticationConsole.csproj ├── LICENSE ├── DiscogsClient.Test ├── DiscogsClient.Test.csproj ├── DiscogsArtistDeserializationTest.cs ├── TrackDeserializationTest.cs ├── ImageDeserializationTest.cs ├── MasterDeserializationTest.cs ├── VersionDeserializationTest.cs ├── DiscogsClientTest.cs ├── ResultDeserializationTest.cs └── ReleaseDeserializationTest.cs ├── DiscogsClient.sln ├── .gitattributes ├── .gitignore └── README.md /DiscogsClient/Data/Result/DiscogsSortOrder.cs: -------------------------------------------------------------------------------- 1 | namespace DiscogsClient.Data.Result 2 | { 3 | public enum DiscogsSortOrderType 4 | { 5 | asc, 6 | desc 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /DiscogsClient/Data/Result/DiscogsImageType.cs: -------------------------------------------------------------------------------- 1 | namespace DiscogsClient.Data.Result 2 | { 3 | public enum DiscogsImageType 4 | { 5 | secondary, 6 | primary 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /DiscogsClient/Data/Query/DiscogsImageType.cs: -------------------------------------------------------------------------------- 1 | namespace DiscogsClient.Data.Query 2 | { 3 | public enum DiscogsImageFormatType 4 | { 5 | Normal, 6 | Thumbnail 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /DiscogsClient/Data/Result/DiscogsEntity.cs: -------------------------------------------------------------------------------- 1 | namespace DiscogsClient.Data.Result 2 | { 3 | public abstract class DiscogsEntity 4 | { 5 | public int id { get; set; } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /DiscogsClient/Data/Result/DiscogsTrack.cs: -------------------------------------------------------------------------------- 1 | namespace DiscogsClient.Data.Result 2 | { 3 | public class DiscogsTrack : DiscogsSubtrack 4 | { 5 | public DiscogsSubtrack[] sub_tracks { get; set; } 6 | } 7 | } -------------------------------------------------------------------------------- /DiscogsClient/Data/Result/DiscogsArtistSortType.cs: -------------------------------------------------------------------------------- 1 | namespace DiscogsClient.Data.Result 2 | { 3 | public enum DiscogsArtistSortType 4 | { 5 | year, 6 | title, 7 | format 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /DiscogsClient/Data/Result/DiscogsRating.cs: -------------------------------------------------------------------------------- 1 | namespace DiscogsClient.Data.Result 2 | { 3 | public class DiscogsRating 4 | { 5 | public decimal average { get; set; } 6 | public int count { get; set; } 7 | } 8 | } -------------------------------------------------------------------------------- /DiscogsAuthenticationConsole/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /DiscogsClient/Data/Result/DiscogsUser.cs: -------------------------------------------------------------------------------- 1 | namespace DiscogsClient.Data.Result 2 | { 3 | public class DiscogsUser 4 | { 5 | public string resource_url { get; set; } 6 | public string username { get; set; } 7 | } 8 | } -------------------------------------------------------------------------------- /DiscogsClient/Data/Query/DiscogsEntityType.cs: -------------------------------------------------------------------------------- 1 | namespace DiscogsClient.Data.Query 2 | { 3 | public enum DiscogsEntityType 4 | { 5 | release, 6 | master, 7 | artist, 8 | label 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /DiscogsClient/Data/Result/DiscogsCommunityInfo.cs: -------------------------------------------------------------------------------- 1 | namespace DiscogsClient.Data.Result 2 | { 3 | public class DiscogsCommunityInfo 4 | { 5 | public int want { get; set; } 6 | public int have { get; set; } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /DiscogsClient/Data/Result/DiscogsSublabel.cs: -------------------------------------------------------------------------------- 1 | namespace DiscogsClient.Data.Result 2 | { 3 | public class DiscogsSimplifiedLabel : DiscogsEntity 4 | { 5 | public string resource_url { get; set; } 6 | public string name { get; set; } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /DiscogsClient/Data/Result/DiscogsCommunityReleaseRating.cs: -------------------------------------------------------------------------------- 1 | namespace DiscogsClient.Data.Result 2 | { 3 | public class DiscogsCommunityReleaseRating 4 | { 5 | public DiscogsRating rating { get; set; } 6 | 7 | public int release_id { get; set; } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /DiscogsClient/Data/Result/DiscogsIdentifier.cs: -------------------------------------------------------------------------------- 1 | namespace DiscogsClient.Data.Result 2 | { 3 | public class DiscogsIdentifier 4 | { 5 | public string type { get; set; } 6 | public string value { get; set; } 7 | public string description { get; set; } 8 | } 9 | } -------------------------------------------------------------------------------- /DiscogsClient/Data/Result/DiscogsReleaseRating.cs: -------------------------------------------------------------------------------- 1 | namespace DiscogsClient.Data.Result 2 | { 3 | public class DiscogsReleaseRating 4 | { 5 | public string username { get; set; } 6 | public int release_id { get; set; } 7 | public int rating { get; set; } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /DiscogsClient/DiscogsException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace DiscogsClient 4 | { 5 | public class DiscogsException : Exception 6 | { 7 | public DiscogsException(string message, Exception innerException): base(message, innerException) 8 | { 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /DiscogsClient/Data/Result/DiscogsGroupOrBandMember.cs: -------------------------------------------------------------------------------- 1 | namespace DiscogsClient.Data.Result 2 | { 3 | public class DiscogsGroupOrBandMember : DiscogsEntity 4 | { 5 | public bool active { get; set; } 6 | public string name { get; set; } 7 | public string resource_url { get; set; } 8 | } 9 | } -------------------------------------------------------------------------------- /DiscogsClient/Data/Result/DiscogsPaginableResults.cs: -------------------------------------------------------------------------------- 1 | namespace DiscogsClient.Data.Result 2 | { 3 | public abstract class DiscogsPaginableResults where T: DiscogsEntity 4 | { 5 | public DiscogsPaginedResult pagination { get; set; } 6 | 7 | public abstract T[] GetResults(); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /DiscogsClient/Data/Result/DiscogsIdentity.cs: -------------------------------------------------------------------------------- 1 | namespace DiscogsClient.Data.Result 2 | { 3 | public class DiscogsIdentity : DiscogsEntity 4 | { 5 | public string username { get; set; } 6 | public string resource_url { get; set; } 7 | public string consumer_name { get; set; } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /DiscogsClient/Data/Result/DiscogsFormat.cs: -------------------------------------------------------------------------------- 1 | namespace DiscogsClient.Data.Result 2 | { 3 | public class DiscogsFormat 4 | { 5 | public string[] descriptions { get; set; } 6 | public string name { get; set; } 7 | public string qty { get; set; } 8 | public string text { get; set; } 9 | } 10 | } -------------------------------------------------------------------------------- /DiscogsClient/Data/Result/DiscogsPaginedUrls.cs: -------------------------------------------------------------------------------- 1 | namespace DiscogsClient.Data.Result 2 | { 3 | public class DiscogsPaginedUrls 4 | { 5 | public string first { get; set; } 6 | public string last { get; set; } 7 | public string prev { get; set; } 8 | public string next { get; set; } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /DiscogsClient/Data/Result/DiscogsVideo.cs: -------------------------------------------------------------------------------- 1 | namespace DiscogsClient.Data.Result 2 | { 3 | public class DiscogsVideo 4 | { 5 | public string description { get; set; } 6 | public int duration { get; set; } 7 | public bool embed { get; set; } 8 | public string title { get; set; } 9 | public string uri { get; set; } 10 | } 11 | } -------------------------------------------------------------------------------- /DiscogsClient/Data/Result/DiscogsPaginedResult.cs: -------------------------------------------------------------------------------- 1 | namespace DiscogsClient.Data.Result 2 | { 3 | public class DiscogsPaginedResult 4 | { 5 | public int per_page { get; set; } 6 | public int pages { get; set; } 7 | public int page { get; set; } 8 | public int items { get; set; } 9 | public DiscogsPaginedUrls urls { get; set; } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /DiscogsClient/Data/Result/DiscogsLabelReleases.cs: -------------------------------------------------------------------------------- 1 | namespace DiscogsClient.Data.Result 2 | { 3 | public sealed class DiscogsLabelReleases: DiscogsPaginableResults 4 | { 5 | public DiscogsLabelRelease[] releases { get; set; } 6 | 7 | public override DiscogsLabelRelease[] GetResults() 8 | { 9 | return releases; 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /DiscogsClient/Data/Result/DiscogsSearchResults.cs: -------------------------------------------------------------------------------- 1 | namespace DiscogsClient.Data.Result 2 | { 3 | public sealed class DiscogsSearchResults : DiscogsPaginableResults 4 | { 5 | public DiscogsSearchResult[] results { get; set; } 6 | 7 | public override DiscogsSearchResult[] GetResults() 8 | { 9 | return results; 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /DiscogsAuthenticationConsole/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /DiscogsClient/Data/Result/DiscogsArtistReleases.cs: -------------------------------------------------------------------------------- 1 | namespace DiscogsClient.Data.Result 2 | { 3 | public sealed class DiscogsArtistReleases : DiscogsPaginableResults 4 | { 5 | public DiscogsArtistRelease[] releases { get; set; } 6 | 7 | public override DiscogsArtistRelease[] GetResults() 8 | { 9 | return releases; 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /DiscogsClient/Data/Result/DiscogsReleaseVersions.cs: -------------------------------------------------------------------------------- 1 | namespace DiscogsClient.Data.Result 2 | { 3 | public sealed class DiscogsReleaseVersions : DiscogsPaginableResults 4 | { 5 | public DiscogsReleaseVersion[] versions { get; set; } 6 | 7 | public override DiscogsReleaseVersion[] GetResults() 8 | { 9 | return versions; 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /DiscogsClient/Data/Result/DiscogsReleaseLabel.cs: -------------------------------------------------------------------------------- 1 | namespace DiscogsClient.Data.Result 2 | { 3 | public class DiscogsReleaseLabel : DiscogsEntity 4 | { 5 | public string catno { get; set; } 6 | public string entity_type { get; set; } 7 | public string entity_type_name { get; set; } 8 | public string name { get; set; } 9 | public string resource_url { get; set; } 10 | } 11 | } -------------------------------------------------------------------------------- /DiscogsClient/Data/Result/DiscogsCommunity.cs: -------------------------------------------------------------------------------- 1 | namespace DiscogsClient.Data.Result 2 | { 3 | public class DiscogsCommunity : DiscogsCommunityInfo 4 | { 5 | public DiscogsUser[] contributors { get; set; } 6 | public string data_quality { get; set; } 7 | public DiscogsRating rating { get; set; } 8 | public string status { get; set; } 9 | public DiscogsUser submitter { get; set; } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /DiscogsClient/Data/Result/DiscogsReleaseArtist.cs: -------------------------------------------------------------------------------- 1 | namespace DiscogsClient.Data.Result 2 | { 3 | public class DiscogsReleaseArtist : DiscogsEntity 4 | { 5 | public string name { get; set; } 6 | public string anv { get; set; } 7 | public string join { get; set; } 8 | public string resource_url { get; set; } 9 | public string role { get; set; } 10 | public string tracks { get; set; } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /DiscogsClient/Data/Query/DiscogsPaginable.cs: -------------------------------------------------------------------------------- 1 | namespace DiscogsClient.Data.Query 2 | { 3 | public class DiscogsPaginable 4 | { 5 | /// 6 | /// number(optional) Example: 3 7 | /// The page you want to request 8 | /// 9 | public int? page { get; set; } 10 | 11 | /// 12 | /// number(optional) Example: 25 13 | /// The number of item per page 14 | /// 15 | public int? per_page { get; set; } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /DiscogsClient/Data/Result/DiscogsLabelRelease.cs: -------------------------------------------------------------------------------- 1 | namespace DiscogsClient.Data.Result 2 | { 3 | public class DiscogsLabelRelease : DiscogsEntity 4 | { 5 | public string artist { get; set; } 6 | public string catno { get; set; } 7 | public string format { get; set; } 8 | public string resource_url { get; set; } 9 | public string status { get; set; } 10 | public string thumb { get; set; } 11 | public string title { get; set; } 12 | public int year { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /DiscogsClient/Data/Result/DiscogsMaster.cs: -------------------------------------------------------------------------------- 1 | namespace DiscogsClient.Data.Result 2 | { 3 | public class DiscogsMaster : DiscogsReleaseBase 4 | { 5 | public int main_release { get; set; } 6 | public string main_release_url { get; set; } 7 | public int most_recent_release { get; set; } 8 | public string most_recent_release_url { get; set; } 9 | public int num_for_sale { get; set; } 10 | public decimal lowest_price { get; set; } 11 | public string versions_url { get; set; } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /DiscogsClient/Data/Query/DiscogsSortInformation.cs: -------------------------------------------------------------------------------- 1 | using DiscogsClient.Data.Result; 2 | 3 | namespace DiscogsClient.Data.Query 4 | { 5 | public class DiscogsSortInformation 6 | { 7 | /// 8 | /// Sort items by this field 9 | /// 10 | public DiscogsArtistSortType sort { get; set; } 11 | 12 | /// 13 | /// Sort items in a particular order (one of asc, desc) 14 | /// 15 | public DiscogsSortOrderType sort_order { get; set; } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /DiscogsClient/Data/Result/DiscogsImage.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using Newtonsoft.Json.Converters; 3 | 4 | namespace DiscogsClient.Data.Result 5 | { 6 | public class DiscogsImage 7 | { 8 | public string uri { get; set; } 9 | public string resource_url { get; set; } 10 | public string uri150 { get; set; } 11 | [JsonConverter(typeof(StringEnumConverter))] 12 | public DiscogsImageType type { get; set; } 13 | public int height { get; set; } 14 | public int width { get; set; } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /DiscogsClient/Internal/TokenAuthenticationInformation.cs: -------------------------------------------------------------------------------- 1 | namespace DiscogsClient.Internal 2 | { 3 | public class TokenAuthenticationInformation 4 | { 5 | public string Token { get; } 6 | private readonly string _SecretToken; 7 | 8 | public TokenAuthenticationInformation(string token) 9 | { 10 | Token = token; 11 | _SecretToken = $"Discogs token={token}"; 12 | } 13 | 14 | public string GetDiscogsSecretToken() 15 | { 16 | return _SecretToken; 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /DiscogsClient/Data/Result/DiscogsSubtrack.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using System; 3 | using RestSharpHelper; 4 | 5 | namespace DiscogsClient.Data.Result 6 | { 7 | public class DiscogsSubtrack 8 | { 9 | public string title { get; set; } 10 | public string type_ { get; set; } 11 | [JsonConverter(typeof(BasicTimeSpanConverter))] 12 | public TimeSpan? duration { get; set; } 13 | public string position { get; set; } 14 | public DiscogsReleaseArtist[] extraartists { get; set; } 15 | public DiscogsReleaseArtist[] artists { get; set; } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /DiscogsClient/DiscogsAuthentifierClient.cs: -------------------------------------------------------------------------------- 1 | using RestSharpHelper.OAuth1; 2 | 3 | namespace DiscogsClient 4 | { 5 | /// 6 | /// Discogs implementation of 7 | /// 8 | public class DiscogsAuthentifierClient : OAuthAuthentifierClient 9 | { 10 | protected override string RequestUrl => @"https://api.discogs.com"; 11 | 12 | protected override string AuthorizeUrl => @"https://www.discogs.com"; 13 | 14 | public DiscogsAuthentifierClient(OAuthConsumerInformation consumerInformation) : base(consumerInformation) 15 | { 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /DiscogsClient/Data/Result/DiscogsArtistRelease.cs: -------------------------------------------------------------------------------- 1 | namespace DiscogsClient.Data.Result 2 | { 3 | public class DiscogsArtistRelease : DiscogsEntity 4 | { 5 | public string artist { get; set; } 6 | public int main_release { get; set; } 7 | public string resource_url { get; set; } 8 | public string role { get; set; } 9 | public string thumb { get; set; } 10 | public string title { get; set; } 11 | public string type { get; set; } 12 | public int year { get; set; } 13 | public string format { get; set; } 14 | public string label { get; set; } 15 | public string status { get; set; } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /DiscogsClient/Data/Result/DiscogsLabel.cs: -------------------------------------------------------------------------------- 1 | namespace DiscogsClient.Data.Result 2 | { 3 | public class DiscogsLabel : DiscogsEntity 4 | { 5 | public DiscogsImage[] images { get; set; } 6 | public DiscogsSimplifiedLabel[] sublabels { get; set; } 7 | public DiscogsSimplifiedLabel parent_label { get; set; } 8 | public string[] urls { get; set; } 9 | public string profile { get; set; } 10 | public string releases_url { get; set; } 11 | public string name { get; set; } 12 | public string contact_info { get; set; } 13 | public string uri { get; set; } 14 | public string resource_url { get; set; } 15 | public string data_quality { get; set; } 16 | } 17 | } -------------------------------------------------------------------------------- /DiscogsClient/Data/Result/DiscogsReleaseBase.cs: -------------------------------------------------------------------------------- 1 | namespace DiscogsClient.Data.Result 2 | { 3 | public class DiscogsReleaseBase : DiscogsEntity 4 | { 5 | public DiscogsReleaseArtist[] artists { get; set; } 6 | public DiscogsVideo[] videos { get; set; } 7 | public DiscogsImage[] images { get; set; } 8 | public DiscogsTrack[] tracklist { get; set; } 9 | public string resource_url { get; set; } 10 | public string data_quality { get; set; } 11 | public int year { get; set; } 12 | public string title { get; set; } 13 | public string uri { get; set; } 14 | public string[] genres { get; set; } 15 | public string[] styles { get; set; } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /DiscogsClient/Data/Result/DiscogsReleaseVersion.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Newtonsoft.Json; 3 | using RestSharpHelper; 4 | 5 | namespace DiscogsClient.Data.Result 6 | { 7 | public class DiscogsReleaseVersion : DiscogsEntity 8 | { 9 | public string catno { get; set; } 10 | public string country { get; set; } 11 | public string format { get; set; } 12 | public string label { get; set; } 13 | [JsonConverter(typeof(BasicDateTimeConverter))] 14 | public DateTime? released { get; set; } 15 | public string resource_url { get; set; } 16 | public string status { get; set; } 17 | public string thumb { get; set; } 18 | public string title { get; set; } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /DiscogsClient/Data/Result/DiscogsArtist.cs: -------------------------------------------------------------------------------- 1 | namespace DiscogsClient.Data.Result 2 | { 3 | public class DiscogsArtist : DiscogsEntity 4 | { 5 | public string name { get; set; } 6 | public string realname { get; set; } 7 | public DiscogsImage[] images { get; set; } 8 | public DiscogsGroupOrBandMember[] members { get; set; } 9 | public DiscogsGroupOrBandMember[] groups { get; set; } 10 | public string[] urls { get; set; } 11 | public string[] namevariations { get; set; } 12 | public string profile { get; set; } 13 | public string releases_url { get; set; } 14 | public string resource_url { get; set; } 15 | public string uri { get; set; } 16 | public string data_quality { get; set; } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /DiscogsClient/Data/Result/DiscogsSearchResult.cs: -------------------------------------------------------------------------------- 1 | using DiscogsClient.Data.Query; 2 | using Newtonsoft.Json; 3 | using Newtonsoft.Json.Converters; 4 | 5 | namespace DiscogsClient.Data.Result 6 | { 7 | public class DiscogsSearchResult : DiscogsEntity 8 | { 9 | public string[] genre { get; set; } 10 | public string[] style { get; set; } 11 | public string[] label { get; set; } 12 | public string[] format { get; set; } 13 | public string[] barcode { get; set; } 14 | public int? year { get; set; } 15 | public string title { get; set; } 16 | public string thumb { get; set; } 17 | public string country { get; set; } 18 | public DiscogsCommunityInfo community { get; set; } 19 | public string catno { get; set; } 20 | public string resource_url { get; set; } 21 | public string uri { get; set; } 22 | [JsonConverter(typeof(StringEnumConverter))] 23 | public DiscogsEntityType type { get; set; } 24 | } 25 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | Copyright (c) 2016-2017 David Desmaisons 3 | 4 | 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: 5 | 6 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 7 | 8 | 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. 9 | -------------------------------------------------------------------------------- /DiscogsClient.Test/DiscogsClient.Test.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp2.0 5 | 6 | false 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /DiscogsAuthenticationConsole/Program.cs: -------------------------------------------------------------------------------- 1 | using DiscogsClient; 2 | using System; 3 | using System.Diagnostics; 4 | using System.Threading.Tasks; 5 | using RestSharpHelper.OAuth1; 6 | 7 | namespace DiscogsAuthenticationConsole 8 | { 9 | public class Program 10 | { 11 | public static void Main(string[] args) 12 | { 13 | var oAuthConsumerInformation = new OAuthConsumerInformation("", ""); 14 | var discogsClient = new DiscogsAuthentifierClient(oAuthConsumerInformation); 15 | 16 | var aouth = discogsClient.Authorize(s => Task.FromResult(GetToken(s))).Result; 17 | 18 | Console.WriteLine($"{((aouth != null)? "Success": "Fail")}"); 19 | Console.WriteLine($"Token:{aouth?.TokenInformation?.Token}, Token:{aouth?.TokenInformation?.TokenSecret}"); 20 | } 21 | 22 | private static string GetToken(string url) 23 | { 24 | Console.WriteLine("Please authourize the application and enter the final key in the console"); 25 | Process.Start(url); 26 | string tokenKey = Console.ReadLine(); 27 | tokenKey = string.IsNullOrEmpty(tokenKey) ? null : tokenKey; 28 | return tokenKey; 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /DiscogsClient/Data/Result/DiscogsRelease.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace DiscogsClient.Data.Result 4 | { 5 | public class DiscogsRelease : DiscogsReleaseBase 6 | { 7 | public DiscogsReleaseArtist[] extraartists { get; set; } 8 | public DiscogsReleaseLabel[] labels { get; set; } 9 | public DiscogsReleaseLabel[] companies { get; set; } 10 | public DiscogsFormat[] formats { get; set; } 11 | public DiscogsIdentifier[] identifiers { get; set; } 12 | public DiscogsCommunity community { get; set; } 13 | public DiscogsReleaseLabel[] series { get; set; } 14 | public string artists_sort { get; set; } 15 | public string catno { get; set; } 16 | public string country { get; set; } 17 | public DateTime date_added { get; set; } 18 | public DateTime date_changed { get; set; } 19 | public int estimated_weight { get; set; } 20 | public int format_quantity { get; set; } 21 | public decimal? lowest_price { get; set; } 22 | public int master_id { get; set; } 23 | public string master_url { get; set; } 24 | public string notes { get; set; } 25 | public int num_for_sale { get; set; } 26 | public string released { get; set; } 27 | public string released_formatted { get; set; } 28 | public string status { get; set; } 29 | public string thumb { get; set; } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /DiscogsClient/IDiscogsUserIdentityClient.cs: -------------------------------------------------------------------------------- 1 | using DiscogsClient.Data.Result; 2 | using System.Threading; 3 | using System.Threading.Tasks; 4 | 5 | namespace DiscogsClient 6 | { 7 | public interface IDiscogsUserIdentityClient 8 | { 9 | /// 10 | /// Retrieve basic information about the authenticated user. 11 | /// You can use this resource to find out who you’re authenticated as, and 12 | /// it also doubles as a good sanity check to ensure that you’re using OAuth correctly. 13 | /// See https://www.discogs.com/developers/#page:user-identity,header:user-identity-identity 14 | /// 15 | /// Cancellation Token 16 | /// The current discogs user identity 17 | Task GetUserIdentityAsync(CancellationToken cancellationToken); 18 | 19 | /// 20 | /// Retrieve basic information about the authenticated user. 21 | /// You can use this resource to find out who you’re authenticated as, and 22 | /// it also doubles as a good sanity check to ensure that you’re using OAuth correctly. 23 | /// See https://www.discogs.com/developers/#page:user-identity,header:user-identity-identity 24 | /// 25 | /// The current discogs user identity 26 | Task GetUserIdentityAsync(); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /DiscogsClient.Test/DiscogsArtistDeserializationTest.cs: -------------------------------------------------------------------------------- 1 | using DiscogsClient.Data.Result; 2 | using FluentAssertions; 3 | using Newtonsoft.Json; 4 | using Xunit; 5 | 6 | namespace DiscogsClient.Test 7 | { 8 | public class DiscogsArtistDeserializationTest 9 | { 10 | private const string _JsonResponse = "{\"profile\": \"\", \"realname\": \"Steve Destailleur\", \"releases_url\": \"https://api.discogs.com/artists/20861/releases\", \"name\": \"Tevatron\", \"uri\": \"https://www.discogs.com/artist/20861-Tevatron\", \"images\": [{\"uri\": \"\", \"height\": 113, \"width\": 150, \"resource_url\": \"\", \"type\": \"primary\", \"uri150\": \"\"}], \"resource_url\": \"https://api.discogs.com/artists/20861\", \"aliases\": [{\"resource_url\": \"https://api.discogs.com/artists/575215\", \"id\": 575215, \"name\": \"St\\u00e9phane Destailleur\"}, {\"resource_url\": \"https://api.discogs.com/artists/8324\", \"id\": 8324, \"name\": \"Steve D\"}], \"id\": 20861, \"data_quality\": \"Needs Vote\", \"namevariations\": [\"Tevathron\"]}"; 11 | private readonly DiscogsArtist _Result; 12 | 13 | public DiscogsArtistDeserializationTest() 14 | { 15 | _Result = JsonConvert.DeserializeObject(_JsonResponse); 16 | } 17 | 18 | [Fact] 19 | public void DeserializeResult_IsNotNull() 20 | { 21 | _Result.Should().NotBeNull(); 22 | } 23 | 24 | [Fact] 25 | public void DeserializeResult_Has_RealName() 26 | { 27 | _Result.realname.Should().Be("Steve Destailleur"); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /DiscogsAuthenticationConsole/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("DiscogsAuthenticationConsole")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("DiscogsAuthenticationConsole")] 13 | [assembly: AssemblyCopyright("Copyright © 2016")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("1c7e9ecb-f292-440a-ba38-b2a0c63e31ed")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /DiscogsClient/Internal/IDiscogsWebClient.cs: -------------------------------------------------------------------------------- 1 | using RestSharp; 2 | using System.IO; 3 | using System.Net; 4 | using System.Threading; 5 | using System.Threading.Tasks; 6 | 7 | namespace DiscogsClient.Internal 8 | { 9 | internal interface IDiscogsWebClient 10 | { 11 | IRestRequest GetSearchRequest(); 12 | 13 | IRestRequest GetReleaseRequest(int relaseId); 14 | 15 | IRestRequest GetMasterRequest(int masterId); 16 | 17 | IRestRequest GetMasterReleaseVersionRequest(int masterId); 18 | 19 | IRestRequest GetArtistRequest(int artistId); 20 | 21 | IRestRequest GetLabelRequest(int artistId); 22 | 23 | IRestRequest GetArtistReleaseVersionRequest(int artistId); 24 | 25 | IRestRequest GetAllLabelReleasesRequest(int labelId); 26 | 27 | IRestRequest GetGetUserReleaseRatingRequest(string userName, int releaseId); 28 | 29 | IRestRequest GetPutUserReleaseRatingRequest(string username, int releaseId); 30 | 31 | IRestRequest GetDeleteUserReleaseRatingRequest(string userName, int releaseId); 32 | 33 | IRestRequest GetCommunityReleaseRatingRequest(int releaseId); 34 | 35 | IRestRequest GetUserIdentityRequest(); 36 | 37 | Task Execute(IRestRequest request, CancellationToken cancellationToken); 38 | 39 | Task Execute(IRestRequest request, CancellationToken cancellationToken); 40 | 41 | Task Download(string url, Stream copyStream, CancellationToken cancellationToken, int timeOut=15000); 42 | 43 | Task SaveFile(string url, string path, string fileName, CancellationToken cancellationToken, int timeOut = 15000); 44 | } 45 | } -------------------------------------------------------------------------------- /DiscogsClient/DiscogsClient.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard2.0;net461 5 | true 6 | DiscogsClient 7 | DiscogsClient 8 | David Desmaisons 9 | 2.7.1 10 | 11 | https://github.com/David-Desmaisons/DiscogsClient 12 | https://github.com/David-Desmaisons/DiscogsClient/blob/master/LICENSE 13 | C# Client library for Discogs API v2.0 14 | 15 | Features 16 | 17 | Include API to authorize user (generating OAuth1.0 token and token secret) 18 | Full support to DataBase API including image download 19 | Support of identity API 20 | Asynchroneous and cancellable API using Tasks 21 | Transparent management of pagination using none blocking API (Reactive IObservable) or IEnumerable 22 | DiscogsClient 23 | true 24 | DiscogsClient, Asynchronous, Client 25 | 2.7.1.0 26 | 2.7.1.0 27 | Add async method for paginated queries 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /DiscogsClient.Test/TrackDeserializationTest.cs: -------------------------------------------------------------------------------- 1 | using DiscogsClient.Data.Result; 2 | using FluentAssertions; 3 | using Newtonsoft.Json; 4 | using System; 5 | using Xunit; 6 | 7 | namespace DiscogsClient.Test 8 | { 9 | public class TrackDeserializationTest 10 | { 11 | private const string _Track = "{\"duration\": \"7:13\",\"position\": \"2\",\"type_\": \"track\",\"extraartists\": [ {\"join\": \"\",\"name\": \"DJ Sangeet\",\"anv\": \"\",\"tracks\": \"\",\"role\": \"Written-By, Producer\",\"resource_url\": \"https://api.discogs.com/ReleaseArtists/25460\",\"id\": 25460 }],\"title\": \"From The Heart\"}"; 12 | 13 | private readonly DiscogsTrack _Result; 14 | 15 | public TrackDeserializationTest() 16 | { 17 | _Result = JsonConvert.DeserializeObject(_Track); 18 | } 19 | 20 | [Fact] 21 | public void DeserializeResult_IsNotNull() 22 | { 23 | _Result.Should().NotBeNull(); 24 | } 25 | 26 | [Fact] 27 | public void DeserializeDuration_IsOK() 28 | { 29 | _Result.duration.Should().Be(new TimeSpan(0,7,13)); 30 | } 31 | 32 | [Fact] 33 | public void DeserializePosition_IsCorrect() 34 | { 35 | _Result.position.Should().Be("2"); 36 | } 37 | 38 | [Fact] 39 | public void DeserializeTitle_IsCorrect() 40 | { 41 | _Result.title.Should().Be("From The Heart"); 42 | } 43 | 44 | [Fact] 45 | public void DeserializeExtraArtists_HasCorrectSize() 46 | { 47 | _Result.extraartists.Should().NotBeNull(); 48 | _Result.extraartists.Should().HaveCount(1); 49 | } 50 | 51 | [Fact] 52 | public void DeserializeExtraArtists_HasCorrectInformation() 53 | { 54 | _Result.extraartists[0].name.Should().Be("DJ Sangeet"); 55 | _Result.extraartists[0].resource_url.Should().Be("https://api.discogs.com/ReleaseArtists/25460"); 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /DiscogsClient.Test/ImageDeserializationTest.cs: -------------------------------------------------------------------------------- 1 | using DiscogsClient.Data.Result; 2 | using FluentAssertions; 3 | using Newtonsoft.Json; 4 | using Xunit; 5 | 6 | namespace DiscogsClient.Test 7 | { 8 | public class ImageDeserializationTest 9 | { 10 | private const string _Image = "{ \"height\": 569, \"resource_url\": \"https://api-img.discogs.com/_0K5t_iLs6CzLPKTB4mwHVI3Vy0=/fit-in/600x569/filters:strip_icc():format(jpeg):mode_rgb():quality(96)/discogs-images/R-66785-1213949871.jpeg.jpg\", \"type\": \"primary\", \"uri\": \"https://api-img.discogs.com/_0K5t_iLs6CzLPKTB4mwHVI3Vy0=/fit-in/600x569/filters:strip_icc():format(jpeg):mode_rgb():quality(96)/discogs-images/R-66785-1213949871.jpeg.jpg\", \"uri150\": \"https://api-img.discogs.com/sSWjXKczZseDjX2QohG1Lc77F-w=/fit-in/150x150/filters:strip_icc():format(jpeg):mode_rgb()/discogs-images/R-66785-1213949871.jpeg.jpg\", \"width\": 600}"; 11 | private readonly DiscogsImage _Result; 12 | 13 | public ImageDeserializationTest() 14 | { 15 | _Result = JsonConvert.DeserializeObject(_Image); 16 | } 17 | 18 | [Fact] 19 | public void DeserializeResult_IsNotNull() 20 | { 21 | _Result.Should().NotBeNull(); 22 | } 23 | 24 | [Fact] 25 | public void DeserializeHeight_IsOK() 26 | { 27 | _Result.height.Should().Be(569); 28 | } 29 | 30 | [Fact] 31 | public void DeserializeWidth_IsCorrect() 32 | { 33 | _Result.width.Should().Be(600); 34 | } 35 | 36 | [Fact] 37 | public void DeserializeResource_url_IsCorrect() 38 | { 39 | _Result.resource_url.Should().Be(@"https://api-img.discogs.com/_0K5t_iLs6CzLPKTB4mwHVI3Vy0=/fit-in/600x569/filters:strip_icc():format(jpeg):mode_rgb():quality(96)/discogs-images/R-66785-1213949871.jpeg.jpg"); 40 | } 41 | 42 | [Fact] 43 | public void Deserializetype_HasCorrectValue() 44 | { 45 | _Result.type.Should().Be(DiscogsImageType.primary); 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /DiscogsClient.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.23107.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DiscogsClient", "DiscogsClient\DiscogsClient.csproj", "{F0138D25-8712-4DCA-880A-507067AC1326}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DiscogsClient.Test", "DiscogsClient.Test\DiscogsClient.Test.csproj", "{532D1353-37AA-4548-A711-0E54B04A590A}" 9 | EndProject 10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DiscogsAuthenticationConsole", "DiscogsAuthenticationConsole\DiscogsAuthenticationConsole.csproj", "{1C7E9ECB-F292-440A-BA38-B2A0C63E31ED}" 11 | EndProject 12 | Global 13 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 14 | Debug|Any CPU = Debug|Any CPU 15 | Release|Any CPU = Release|Any CPU 16 | EndGlobalSection 17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 18 | {F0138D25-8712-4DCA-880A-507067AC1326}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 19 | {F0138D25-8712-4DCA-880A-507067AC1326}.Debug|Any CPU.Build.0 = Debug|Any CPU 20 | {F0138D25-8712-4DCA-880A-507067AC1326}.Release|Any CPU.ActiveCfg = Release|Any CPU 21 | {F0138D25-8712-4DCA-880A-507067AC1326}.Release|Any CPU.Build.0 = Release|Any CPU 22 | {532D1353-37AA-4548-A711-0E54B04A590A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 23 | {532D1353-37AA-4548-A711-0E54B04A590A}.Debug|Any CPU.Build.0 = Debug|Any CPU 24 | {532D1353-37AA-4548-A711-0E54B04A590A}.Release|Any CPU.ActiveCfg = Release|Any CPU 25 | {532D1353-37AA-4548-A711-0E54B04A590A}.Release|Any CPU.Build.0 = Release|Any CPU 26 | {1C7E9ECB-F292-440A-BA38-B2A0C63E31ED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 27 | {1C7E9ECB-F292-440A-BA38-B2A0C63E31ED}.Debug|Any CPU.Build.0 = Debug|Any CPU 28 | {1C7E9ECB-F292-440A-BA38-B2A0C63E31ED}.Release|Any CPU.ActiveCfg = Release|Any CPU 29 | {1C7E9ECB-F292-440A-BA38-B2A0C63E31ED}.Release|Any CPU.Build.0 = Release|Any CPU 30 | EndGlobalSection 31 | GlobalSection(SolutionProperties) = preSolution 32 | HideSolutionNode = FALSE 33 | EndGlobalSection 34 | EndGlobal 35 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /DiscogsClient/Data/Query/DiscogsSearch.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | namespace DiscogsClient.Data.Query 4 | { 5 | public class DiscogsSearch 6 | { 7 | /// 8 | /// Your search query. Example: nirvana 9 | /// 10 | [Description("q")] 11 | public string query { get; set; } 12 | 13 | /// 14 | /// Example: release 15 | /// 16 | public DiscogsEntityType? type { get; set; } 17 | 18 | /// 19 | /// Search by combined “Artist Name - Release Title” title field. 20 | /// Example: nirvana - nevermind 21 | /// 22 | public string title { get; set; } 23 | 24 | /// 25 | /// Search release titles. Example: nevermind 26 | /// 27 | public string release_title { get; set; } 28 | 29 | /// 30 | /// Search release credits.Example: kurt 31 | /// 32 | public string credit { get; set; } 33 | 34 | /// 35 | /// Search artist names. Example: nirvana 36 | /// 37 | public string artist { get; set; } 38 | 39 | /// 40 | /// Search artist ANV. Example: nirvana 41 | /// 42 | public string anv { get; set; } 43 | 44 | /// 45 | /// Search label names. Example: dgc 46 | /// 47 | public string label { get; set; } 48 | 49 | /// 50 | /// Search genres. Example: rock 51 | /// 52 | public string genre { get; set; } 53 | 54 | /// 55 | /// Search style. Example: grunge 56 | /// 57 | public string style { get; set; } 58 | 59 | /// 60 | /// Search country. Example: canada 61 | /// 62 | public string country { get; set; } 63 | 64 | /// 65 | /// Search release year. Example: 1991 66 | /// 67 | public int? year { get; set; } 68 | 69 | /// 70 | /// Search formats. Example: album 71 | /// 72 | public string format { get; set; } 73 | 74 | /// 75 | /// Search catalog number. Example: DGCD-24425 76 | /// 77 | public string catno { get; set; } 78 | 79 | /// 80 | /// Search barcodes. Example: 7 2064-24425-2 4 81 | /// 82 | public string barcode { get; set; } 83 | 84 | /// 85 | /// Search track titles. Example: smells like teen spirit 86 | /// 87 | public string track { get; set; } 88 | 89 | /// 90 | /// Search submitter username. Example: milKt 91 | /// 92 | public string submitter { get; set; } 93 | 94 | /// 95 | /// Search contributor usernames. Example: jerome99 96 | /// 97 | public string contributor { get; set; } 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /DiscogsClient.Test/MasterDeserializationTest.cs: -------------------------------------------------------------------------------- 1 | using DiscogsClient.Data.Result; 2 | using FluentAssertions; 3 | using Newtonsoft.Json; 4 | using Xunit; 5 | 6 | namespace DiscogsClient.Test 7 | { 8 | public class MasterDeserializationTest 9 | { 10 | private const string _Master = "{\"styles\": [\"Techno\", \"Deep Techno\", \"Deep House\", \"Disco\"], \"genres\": [\"Electronic\"], \"num_for_sale\": 7, \"title\": \"Conceptions Inspirations b/w Sweet Love \", \"most_recent_release\": 13111150, \"main_release\": 13111150, \"main_release_url\": \"https://api.discogs.com/releases/13111150\", \"uri\": \"https://www.discogs.com/Vintage-Future-ft-Vann-Johnson-and-Syndicate-Of-Swing-Conceptions-Inspirations-bw-Sweet-Love-/master/1489926\", \"artists\": [{\"join\": \"ft.\", \"name\": \"Vintage Future\", \"anv\": \"\", \"tracks\": \"\", \"role\": \"\", \"resource_url\": \"https://api.discogs.com/artists/65478\", \"id\": 65478}, {\"join\": \"and\", \"name\": \"Vann Johnson\", \"anv\": \"\", \"tracks\": \"\", \"role\": \"\", \"resource_url\": \"https://api.discogs.com/artists/603935\", \"id\": 603935}, {\"join\": \"\", \"name\": \"Syndicate Of Swing\", \"anv\": \"\", \"tracks\": \"\", \"role\": \"\", \"resource_url\": \"https://api.discogs.com/artists/1185799\", \"id\": 1185799}], \"versions_url\": \"https://api.discogs.com/masters/1489926/versions\", \"data_quality\": \"Correct\", \"most_recent_release_url\": \"https://api.discogs.com/releases/13111150\", \"year\": 2019, \"images\": [{\"uri\": \"\", \"height\": 600, \"width\": 600, \"resource_url\": \"\", \"type\": \"primary\", \"uri150\": \"\"}, {\"uri\": \"\", \"height\": 600, \"width\": 600, \"resource_url\": \"\", \"type\": \"secondary\", \"uri150\": \"\"}, {\"uri\": \"\", \"height\": 600, \"width\": 600, \"resource_url\": \"\", \"type\": \"secondary\", \"uri150\": \"\"}], \"resource_url\": \"https://api.discogs.com/masters/1489926\", \"lowest_price\": 13.51, \"id\": 1489926, \"tracklist\": [{\"duration\": \"08:05\", \"position\": \"A\", \"type_\": \"track\", \"title\": \"Conceptions Inspirations\"}, {\"duration\": \"13:18\", \"position\": \"B\", \"type_\": \"track\", \"title\": \"Sweet Love\"}]}"; 11 | private readonly DiscogsMaster _Result; 12 | public MasterDeserializationTest() 13 | { 14 | _Result = JsonConvert.DeserializeObject(_Master); 15 | } 16 | 17 | [Fact] 18 | public void DeserializeResult_IsNotNull() 19 | { 20 | _Result.Should().NotBeNull(); 21 | } 22 | 23 | [Fact] 24 | public void DeserializeResult_Deserialize_most_recent_release() 25 | { 26 | _Result.most_recent_release.Should().Be(13111150); 27 | } 28 | 29 | [Fact] 30 | public void DeserializeResult_Deserialize_most_recent_release_url() 31 | { 32 | _Result.most_recent_release_url.Should().Be("https://api.discogs.com/releases/13111150"); 33 | } 34 | 35 | [Fact] 36 | public void DeserializeResult_Deserialize_num_for_sale() 37 | { 38 | _Result.num_for_sale.Should().Be(7); 39 | } 40 | 41 | [Fact] 42 | public void DeserializeResult_Deserialize_lowest_price() 43 | { 44 | _Result.lowest_price.Should().Be(13.51m); 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /DiscogsClient.Test/VersionDeserializationTest.cs: -------------------------------------------------------------------------------- 1 | using DiscogsClient.Data.Result; 2 | using FluentAssertions; 3 | using Newtonsoft.Json; 4 | using System; 5 | using System.Collections.Generic; 6 | using Xunit; 7 | 8 | namespace DiscogsClient.Test 9 | { 10 | public class VersionDeserializationTest 11 | { 12 | private const string _Version = "{ \"catno\": \"2078-2\", \"country\": \"Israel\", \"format\": \"CD, Album, Mixed\", \"id\": 528753, \"label\": \"Phonokol\", \"released\": \"1997\", \"resource_url\": \"http://api.discogs.com/releases/528753\", \"status\": \"Accepted\", \"thumb\": \"https://api-img.discogs.com/53aTwkmfs6fwWZhq5ma7-vbU7TY=/fit-in/150x150/filters:strip_icc():format(jpeg):mode_rgb()/discogs-images/R-528753-1127942810.jpeg.jpg\", \"title\": \"Stardiver\" }"; 13 | private const string _Version2 = " { \"catno\": \"SPIRIT ZONE 027\", \"country\": \"Germany\", \"format\": \"CD, Album, Mixed\", \"id\": 66785, \"label\": \"Spirit Zone Recordings\", \"released\": \"1997-03-14\", \"resource_url\": \"http://api.discogs.com/releases/66785\", \"status\": \"Accepted\", \"thumb\": \"https://api-img.discogs.com/sSWjXKczZseDjX2QohG1Lc77F-w=/fit-in/150x150/filters:strip_icc():format(jpeg):mode_rgb()/discogs-images/R-66785-1213949871.jpeg.jpg\", \"title\": \"Stardiver\" }"; 14 | private const string _Version3 = " { \"catno\": \"SPIRIT ZONE 027\", \"country\": \"Germany\", \"format\": \"CD, Album, Mixed\", \"id\": 66785, \"label\": \"Spirit Zone Recordings\", \"released\": \"1997-03-0\", \"resource_url\": \"http://api.discogs.com/releases/66785\", \"status\": \"Accepted\", \"thumb\": \"https://api-img.discogs.com/sSWjXKczZseDjX2QohG1Lc77F-w=/fit-in/150x150/filters:strip_icc():format(jpeg):mode_rgb()/discogs-images/R-66785-1213949871.jpeg.jpg\", \"title\": \"Stardiver\" }"; 15 | private const string _Version4 = " { \"catno\": \"SPIRIT ZONE 027\", \"country\": \"Germany\", \"format\": \"CD, Album, Mixed\", \"id\": 66785, \"label\": \"Spirit Zone Recordings\", \"resource_url\": \"http://api.discogs.com/releases/66785\", \"status\": \"Accepted\", \"thumb\": \"https://api-img.discogs.com/sSWjXKczZseDjX2QohG1Lc77F-w=/fit-in/150x150/filters:strip_icc():format(jpeg):mode_rgb()/discogs-images/R-66785-1213949871.jpeg.jpg\", \"title\": \"Stardiver\" }"; 16 | 17 | public static IEnumerable BasicData => new[] 18 | { 19 | new object[] { _Version }, 20 | new object[] { _Version2 } 21 | }; 22 | 23 | [Theory, MemberData(nameof(BasicData))] 24 | public void DeserializeResult_IsNotNull(string version) 25 | { 26 | var result = JsonConvert.DeserializeObject(version); 27 | result.Should().NotBeNull(); 28 | } 29 | 30 | public static IEnumerable Data => new[] 31 | { 32 | new object[] { _Version, new DateTime(1997, 1, 1) }, 33 | new object[] { _Version2, new DateTime(1997, 3, 14) }, 34 | new object[] { _Version3, new DateTime(1997, 3, 1) }, 35 | new object[] { _Version4, null } 36 | }; 37 | 38 | [Theory, MemberData(nameof(Data))] 39 | public void DeserializeResult_DateTimeIsCorrect(string version, DateTime? expected) 40 | { 41 | var result = JsonConvert.DeserializeObject(version); 42 | result.Should().NotBeNull(); 43 | result.released.Should().Be(expected); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /DiscogsAuthenticationConsole/DiscogsAuthenticationConsole.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {1C7E9ECB-F292-440A-BA38-B2A0C63E31ED} 8 | Exe 9 | Properties 10 | DiscogsAuthenticationConsole 11 | DiscogsAuthenticationConsole 12 | v4.6.1 13 | 512 14 | true 15 | 16 | 17 | 18 | AnyCPU 19 | true 20 | full 21 | false 22 | bin\Debug\ 23 | DEBUG;TRACE 24 | prompt 25 | 4 26 | 27 | 28 | AnyCPU 29 | pdbonly 30 | true 31 | bin\Release\ 32 | TRACE 33 | prompt 34 | 4 35 | 36 | 37 | 38 | ..\packages\Newtonsoft.Json.8.0.2\lib\net45\Newtonsoft.Json.dll 39 | True 40 | 41 | 42 | ..\packages\RateLimiter.1.0.0\lib\net45\RateLimiter.dll 43 | True 44 | 45 | 46 | ..\packages\RestSharp.105.2.3\lib\net46\RestSharp.dll 47 | True 48 | 49 | 50 | ..\packages\RestSharpHelper.1.1.0\lib\net461\RestSharpHelper.dll 51 | True 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | {f0138d25-8712-4dca-880a-507067ac1326} 73 | DiscogsClient 74 | 75 | 76 | 77 | 84 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | x64/ 19 | x86/ 20 | build/ 21 | bld/ 22 | [Bb]in/ 23 | [Oo]bj/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | 28 | # MSTest test Results 29 | [Tt]est[Rr]esult*/ 30 | [Bb]uild[Ll]og.* 31 | 32 | # NUNIT 33 | *.VisualState.xml 34 | TestResult.xml 35 | 36 | # Build Results of an ATL Project 37 | [Dd]ebugPS/ 38 | [Rr]eleasePS/ 39 | dlldata.c 40 | 41 | # DNX 42 | project.lock.json 43 | artifacts/ 44 | 45 | *_i.c 46 | *_p.c 47 | *_i.h 48 | *.ilk 49 | *.meta 50 | *.obj 51 | *.pch 52 | *.pdb 53 | *.pgc 54 | *.pgd 55 | *.rsp 56 | *.sbr 57 | *.tlb 58 | *.tli 59 | *.tlh 60 | *.tmp 61 | *.tmp_proj 62 | *.log 63 | *.vspscc 64 | *.vssscc 65 | .builds 66 | *.pidb 67 | *.svclog 68 | *.scc 69 | 70 | # Chutzpah Test files 71 | _Chutzpah* 72 | 73 | # Visual C++ cache files 74 | ipch/ 75 | *.aps 76 | *.ncb 77 | *.opensdf 78 | *.sdf 79 | *.cachefile 80 | 81 | # Visual Studio profiler 82 | *.psess 83 | *.vsp 84 | *.vspx 85 | 86 | # TFS 2012 Local Workspace 87 | $tf/ 88 | 89 | # Guidance Automation Toolkit 90 | *.gpState 91 | 92 | # ReSharper is a .NET coding add-in 93 | _ReSharper*/ 94 | *.[Rr]e[Ss]harper 95 | *.DotSettings.user 96 | 97 | # JustCode is a .NET coding add-in 98 | .JustCode 99 | 100 | # TeamCity is a build add-in 101 | _TeamCity* 102 | 103 | # DotCover is a Code Coverage Tool 104 | *.dotCover 105 | 106 | # NCrunch 107 | _NCrunch_* 108 | .*crunch*.local.xml 109 | 110 | # MightyMoose 111 | *.mm.* 112 | AutoTest.Net/ 113 | 114 | # Web workbench (sass) 115 | .sass-cache/ 116 | 117 | # Installshield output folder 118 | [Ee]xpress/ 119 | 120 | # DocProject is a documentation generator add-in 121 | DocProject/buildhelp/ 122 | DocProject/Help/*.HxT 123 | DocProject/Help/*.HxC 124 | DocProject/Help/*.hhc 125 | DocProject/Help/*.hhk 126 | DocProject/Help/*.hhp 127 | DocProject/Help/Html2 128 | DocProject/Help/html 129 | 130 | # Click-Once directory 131 | publish/ 132 | 133 | # Publish Web Output 134 | *.[Pp]ublish.xml 135 | *.azurePubxml 136 | ## TODO: Comment the next line if you want to checkin your 137 | ## web deploy settings but do note that will include unencrypted 138 | ## passwords 139 | #*.pubxml 140 | 141 | *.publishproj 142 | 143 | # NuGet Packages 144 | *.nupkg 145 | # The packages folder can be ignored because of Package Restore 146 | **/packages/* 147 | # except build/, which is used as an MSBuild target. 148 | !**/packages/build/ 149 | # Uncomment if necessary however generally it will be regenerated when needed 150 | #!**/packages/repositories.config 151 | 152 | # Windows Azure Build Output 153 | csx/ 154 | *.build.csdef 155 | 156 | # Windows Store app package directory 157 | AppPackages/ 158 | 159 | # Visual Studio cache files 160 | # files ending in .cache can be ignored 161 | *.[Cc]ache 162 | # but keep track of directories ending in .cache 163 | !*.[Cc]ache/ 164 | 165 | # Others 166 | ClientBin/ 167 | [Ss]tyle[Cc]op.* 168 | ~$* 169 | *~ 170 | *.dbmdl 171 | *.dbproj.schemaview 172 | *.pfx 173 | *.publishsettings 174 | node_modules/ 175 | orleans.codegen.cs 176 | 177 | # RIA/Silverlight projects 178 | Generated_Code/ 179 | 180 | # Backup & report files from converting an old project file 181 | # to a newer Visual Studio version. Backup files are not needed, 182 | # because we have git ;-) 183 | _UpgradeReport_Files/ 184 | Backup*/ 185 | UpgradeLog*.XML 186 | UpgradeLog*.htm 187 | 188 | # SQL Server files 189 | *.mdf 190 | *.ldf 191 | 192 | # Business Intelligence projects 193 | *.rdl.data 194 | *.bim.layout 195 | *.bim_*.settings 196 | 197 | # Microsoft Fakes 198 | FakesAssemblies/ 199 | 200 | # Node.js Tools for Visual Studio 201 | .ntvs_analysis.dat 202 | 203 | # Visual Studio 6 build log 204 | *.plg 205 | 206 | # Visual Studio 6 workspace options file 207 | *.opt 208 | 209 | # LightSwitch generated files 210 | GeneratedArtifacts/ 211 | _Pvt_Extensions/ 212 | ModelManifest.xml 213 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DiscogsClient 2 | 3 | [![Build status](https://img.shields.io/appveyor/ci/David-Desmaisons/DiscogsClient.svg)](https://ci.appveyor.com/project/David-Desmaisons/DiscogsClient) 4 | [![NuGet Badge](https://img.shields.io/nuget/v/DiscogsClient.svg)](https://www.nuget.org/packages/DiscogsClient/) 5 | [![MIT License](https://img.shields.io/github/license/David-Desmaisons/DiscogsClient.svg)](https://github.com/David-Desmaisons/DiscogsClient/blob/master/LICENSE) 6 | 7 | 8 | C# Client library for [Discogs API v2.0](https://www.discogs.com/developers/) 9 | 10 | Check demo application [Music.Cover.Finder](https://github.com/David-Desmaisons/Music.Cover.Finder) 11 | 12 | ## Features 13 | * Include API to authorize user (generating OAuth1.0 token and token secret) 14 | * Full support to [DataBase API](https://www.discogs.com/developers/#page:database) including image download 15 | * Support of identity API 16 | * Transparent support of rate limit 17 | * Asynchroneous and cancellable API using Tasks 18 | * Transparent management of pagination using none blocking API (Reactive IObservable) or IEnumerable 19 | 20 | ## Sample usage 21 | 22 | ### Create discogs client 23 | 24 | #### Oauth authentication 25 | ```C# 26 | //Create authentication object using private and public keys: you should fournish real keys here 27 | var oAuthCompleteInformation = new OAuthCompleteInformation("consumerKey", 28 | "consumerSecret", "token", "tokenSecret"); 29 | //Create discogs client using the authentication 30 | var discogsClient = new DiscogsClient(oAuthCompleteInformation); 31 | ``` 32 | #### Token based authentication 33 | ```C# 34 | //Create authentication based on Discogs token 35 | var tokenInformation = new TokenAuthenticationInformation("my-token"); 36 | //Create discogs client using the authentication 37 | var discogsClient = new DiscogsClient(tokenInformation); 38 | ``` 39 | #### Search The DataBase 40 | 41 | Using IObservable: 42 | ```C# 43 | var discogsSearch = new DiscogsSearch() 44 | { 45 | artist = "Ornette Coleman", 46 | release_title = "The Shape Of Jazz To Come" 47 | }; 48 | 49 | //Retrieve observable result from search 50 | var observable = _DiscogsClient.Search(discogsSearch); 51 | ``` 52 | 53 | Using IEnumerable: 54 | ```C# 55 | //Alternatively retreive same result as enumerable 56 | var enumerable = _DiscogsClient.SearchAsEnumerable(discogsSearch); 57 | ``` 58 | 59 | #### Get Release, Master, Artist or Label Information 60 | ```C# 61 | var release = await _DiscogsClient.GetReleaseAsync(1704673); 62 | ``` 63 | 64 | ```C# 65 | var master = await _DiscogsClient.GetMasterAsync(47813); 66 | ``` 67 | 68 | ```C# 69 | var artist = await _DiscogsClient.GetArtistAsync(224506); 70 | ``` 71 | 72 | ```C# 73 | var label = await _DiscogsClient.GetLabelAsync(125); 74 | ``` 75 | 76 | #### Download Image 77 | ```C# 78 | //Retrieve Release information 79 | var res = await _DiscogsClient.GetMasterAsync(47813); 80 | 81 | //Download the first image of the release 82 | await _DiscogsClient.SaveImageAsync(res.images[0], Path.GetTempPath(), "Ornette-TSOAJTC"); 83 | ``` 84 | 85 | #### OAuth: Authorize new user 86 | ```C# 87 | //Create authentificator information: you should fournish real keys here 88 | var oAuthConsumerInformation = new OAuthConsumerInformation("consumerKey", "consumerSecret"); 89 | 90 | //Create Authentifier client 91 | var discogsAuthentifierClient = new DiscogsAuthentifierClient(oAuthConsumerInformation); 92 | 93 | //Retreive Token and Token secret 94 | var oauth = discogsClient.Authorize(s => Task.FromResult(GetToken(s))).Result; 95 | ``` 96 | 97 | Authorize takes a Func< string, Task< string>> as parameter, receiving the authentication url and returning the corresponding access key. Trivial implementation: 98 | 99 | ```C# 100 | private static string GetToken(string url) 101 | { 102 | Console.WriteLine("Please authorize the application and enter the final key in the console"); 103 | Process.Start(url); 104 | return Console.ReadLine(); 105 | } 106 | ``` 107 | See [DiscogsClientTest](https://github.com/David-Desmaisons/DiscogsClient/blob/master/DiscogsClient.Test/DiscogsClientTest.cs) and [DiscogsAuthenticationConsole](https://github.com/David-Desmaisons/DiscogsClient/blob/master/DiscogsAuthenticationConsole/Program.cs) for full samples of available APIs. 108 | -------------------------------------------------------------------------------- /DiscogsClient/IDiscogsReleaseRatingClient.cs: -------------------------------------------------------------------------------- 1 | using DiscogsClient.Data.Result; 2 | using System.Threading; 3 | using System.Threading.Tasks; 4 | 5 | namespace DiscogsClient 6 | { 7 | public interface IDiscogsReleaseRatingClient 8 | { 9 | /// 10 | /// Retrieves the release’s rating for a given user. 11 | /// See https://www.discogs.com/developers/#page:database,header:database-release-rating-by-user 12 | /// 13 | /// The username of the rating you are trying to request. 14 | /// The Release ID 15 | /// Cancellation Token 16 | /// The corresponding release’s rating 17 | Task GetUserReleaseRatingAsync(string userName, int releaseId, CancellationToken cancellationToken); 18 | 19 | /// 20 | /// Retrieves the release’s rating for a given user. 21 | /// See https://www.discogs.com/developers/#page:database,header:database-release-rating-by-user 22 | /// 23 | /// The username of the rating you are trying to request. 24 | /// The Release ID 25 | /// The corresponding release’s rating 26 | Task GetUserReleaseRatingAsync(string userName, int releaseId); 27 | 28 | /// 29 | /// Updates the release’s rating for a given user. 30 | /// See https://www.discogs.com/developers/#page:database,header:database-release-rating-by-user-put 31 | /// 32 | /// The Release ID 33 | /// The rating 34 | /// The corresponding updated release’s rating 35 | Task SetUserReleaseRatingAsync(int releaseId, int rating); 36 | 37 | /// 38 | /// Updates the release’s rating for a given user. 39 | /// See https://www.discogs.com/developers/#page:database,header:database-release-rating-by-user-put 40 | /// 41 | /// The Release ID 42 | /// The rating 43 | /// The corresponding updated release’s rating 44 | Task SetUserReleaseRatingAsync(int releaseId, int rating, CancellationToken cancellationToken); 45 | 46 | /// 47 | /// Deletes the release’s rating for the current user. 48 | /// See https://www.discogs.com/developers/#page:database,header:database-release-rating-by-user-delete 49 | /// 50 | /// The Release ID 51 | /// Cancellation Token 52 | /// True if the operation is sucessfull 53 | Task DeleteUserReleaseRatingAsync(int releaseId, CancellationToken token); 54 | 55 | /// 56 | /// Deletes the release’s rating for the current user. 57 | /// See https://www.discogs.com/developers/#page:database,header:database-release-rating-by-user-delete 58 | /// 59 | /// The Release ID 60 | /// True if the operation is sucessfull 61 | Task DeleteUserReleaseRatingAsync(int releaseId); 62 | 63 | /// 64 | /// Retrieves the community release rating average and count. 65 | /// See https://www.discogs.com/developers/#page:database,header:database-community-release-rating 66 | /// 67 | /// The Release ID 68 | /// Cancellation Token 69 | /// The community release rating 70 | Task GetCommunityReleaseRatingAsync(int releaseId, CancellationToken cancellationToken); 71 | 72 | /// 73 | /// Retrieves the community release rating average and count. 74 | /// See https://www.discogs.com/developers/#page:database,header:database-community-release-rating 75 | /// 76 | /// The Release ID 77 | /// The community release rating 78 | Task GetCommunityReleaseRatingAsync(int releaseId); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /DiscogsClient/Internal/DiscogsWebClient.cs: -------------------------------------------------------------------------------- 1 | using RateLimiter; 2 | using RestSharp; 3 | using System; 4 | using RestSharpHelper; 5 | using RestSharpHelper.OAuth1; 6 | 7 | namespace DiscogsClient.Internal 8 | { 9 | internal class DiscogsWebClient : RestSharpWebClient, IDiscogsWebClient 10 | { 11 | private const string _SearchUrl = "database/search"; 12 | private const string _ReleaseUrl = "releases/{releaseId}"; 13 | private const string _MasterUrl = "masters/{masterId}"; 14 | private const string _MasterReleaseVersionUrl = "masters/{masterId}/versions"; 15 | private const string _ArtistUrl = "artists/{artistId}"; 16 | private const string _ArtistReleaseUrl = "artists/{artistId}/releases"; 17 | private const string _AllLabelReleasesUrl = "labels/{labelId}/releases"; 18 | private const string _LabeltUrl = "labels/{labelId}"; 19 | private const string _ReleaseRatingByUserUrl = "releases/{releaseId}/rating/{userName}"; 20 | private const string _CommunityReleaseRatingUrl = "releases/{releaseId}/rating"; 21 | private const string _IdendityUrl = "oauth/identity"; 22 | private readonly OAuthCompleteInformation _OAuthCompleteInformation; 23 | private readonly TokenAuthenticationInformation _TokenAuthenticationInformation; 24 | 25 | protected override string UrlBase => "https://api.discogs.com"; 26 | protected override string UserAgentFallBack => @"DiscogsClient https://github.com/David-Desmaisons/DiscogsClient"; 27 | protected override TimeLimiter TimeLimiter => SharedTimeLimiter; 28 | 29 | private static TimeLimiter SharedTimeLimiter { get; } 30 | 31 | public DiscogsWebClient(OAuthCompleteInformation oAuthCompleteInformation, string userAgent, int timeOut = 10000): 32 | base(userAgent, timeOut) 33 | { 34 | _OAuthCompleteInformation = oAuthCompleteInformation; 35 | } 36 | 37 | public DiscogsWebClient(TokenAuthenticationInformation tokenAuthenticationInformation, string userAgent, int timeOut = 10000) 38 | : base(userAgent, timeOut) 39 | { 40 | _TokenAuthenticationInformation = tokenAuthenticationInformation; 41 | } 42 | 43 | static DiscogsWebClient() 44 | { 45 | SharedTimeLimiter = TimeLimiter.GetFromMaxCountByInterval(60, TimeSpan.FromMinutes(1)); 46 | } 47 | 48 | protected override IRestClient Mature(IRestClient client) 49 | { 50 | client.Authenticator = _OAuthCompleteInformation?.GetAuthenticatorForProtectedResource(); 51 | return client; 52 | } 53 | 54 | public IRestRequest GetUserIdentityRequest() 55 | { 56 | return GetRequest(_IdendityUrl); 57 | } 58 | 59 | public IRestRequest GetSearchRequest() 60 | { 61 | return GetRequest(_SearchUrl); 62 | } 63 | 64 | public IRestRequest GetReleaseRequest(int releaseId) 65 | { 66 | return GetRequest(_ReleaseUrl).AddUrlSegment(nameof(releaseId), releaseId.ToString()); 67 | } 68 | 69 | public IRestRequest GetMasterRequest(int masterId) 70 | { 71 | return GetRequest(_MasterUrl).AddUrlSegment(nameof(masterId), masterId.ToString()); 72 | } 73 | 74 | public IRestRequest GetMasterReleaseVersionRequest(int masterId) 75 | { 76 | return GetRequest(_MasterReleaseVersionUrl).AddUrlSegment(nameof(masterId), masterId.ToString()); 77 | } 78 | 79 | public IRestRequest GetArtistRequest(int artistId) 80 | { 81 | return GetRequest(_ArtistUrl).AddUrlSegment(nameof(artistId), artistId.ToString()); 82 | } 83 | 84 | public IRestRequest GetLabelRequest(int labelId) 85 | { 86 | return GetRequest(_LabeltUrl).AddUrlSegment(nameof(labelId), labelId.ToString()); 87 | } 88 | 89 | public IRestRequest GetArtistReleaseVersionRequest(int artistId) 90 | { 91 | return GetRequest(_ArtistReleaseUrl).AddUrlSegment(nameof(artistId), artistId.ToString()); 92 | } 93 | 94 | public IRestRequest GetAllLabelReleasesRequest(int labelId) 95 | { 96 | return GetRequest(_AllLabelReleasesUrl).AddUrlSegment(nameof(labelId), labelId.ToString()); 97 | } 98 | 99 | public IRestRequest GetGetUserReleaseRatingRequest(string userName, int releaseId) 100 | { 101 | return GetUserReleaseRatingRequestRaw(userName, releaseId, Method.GET); 102 | } 103 | 104 | public IRestRequest GetPutUserReleaseRatingRequest(string userName, int releaseId) 105 | { 106 | return GetUserReleaseRatingRequestRaw(userName, releaseId, Method.PUT); 107 | } 108 | 109 | public IRestRequest GetDeleteUserReleaseRatingRequest(string userName, int releaseId) 110 | { 111 | return GetUserReleaseRatingRequestRaw(userName, releaseId, Method.DELETE); 112 | } 113 | 114 | private IRestRequest GetUserReleaseRatingRequestRaw(string userName, int releaseId, Method method) 115 | { 116 | return GetRequest(_ReleaseRatingByUserUrl, method) 117 | .AddUrlSegment(nameof(userName), userName) 118 | .AddUrlSegment(nameof(releaseId), releaseId.ToString()); 119 | } 120 | 121 | public IRestRequest GetCommunityReleaseRatingRequest(int releaseId) 122 | { 123 | return GetRequest(_CommunityReleaseRatingUrl).AddUrlSegment(nameof(releaseId), releaseId.ToString()); 124 | } 125 | 126 | private IRestRequest GetRequest(string url, Method method = Method.GET) 127 | { 128 | var request = new RestRequest(url, method).AddHeader("Accept-Encoding", "gzip"); 129 | if (_TokenAuthenticationInformation != null) 130 | request.AddHeader("Authorization", _TokenAuthenticationInformation.GetDiscogsSecretToken()); 131 | 132 | return request; 133 | } 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /DiscogsClient.Test/DiscogsClientTest.cs: -------------------------------------------------------------------------------- 1 | using DiscogsClient.Data.Query; 2 | using DiscogsClient.Data.Result; 3 | using FluentAssertions; 4 | using System.Diagnostics; 5 | using System.IO; 6 | using System.Reactive.Linq; 7 | using System.Threading.Tasks; 8 | using DiscogsClient.Internal; 9 | using RestSharpHelper.OAuth1; 10 | using Xunit; 11 | using Xunit.Abstractions; 12 | 13 | namespace DiscogsClient.Test 14 | { 15 | public class DiscogsClientTest 16 | { 17 | private readonly DiscogsClient _DiscogsClient; 18 | private readonly ITestOutputHelper _TestOutputHelper; 19 | private int _Count; 20 | private const string Token = ""; 21 | 22 | public DiscogsClientTest(ITestOutputHelper testOutputHelper) 23 | { 24 | _TestOutputHelper = testOutputHelper; 25 | var tokenInformation = new TokenAuthenticationInformation(Token); 26 | _DiscogsClient = new DiscogsClient(tokenInformation); 27 | } 28 | 29 | [Fact(Skip = "Need internet access and valid token and keys.")] 30 | public async Task Search() 31 | { 32 | var discogsSearch = new DiscogsSearch() 33 | { 34 | artist = "Ornette Coleman", 35 | release_title = "The Shape Of Jazz To Come" 36 | }; 37 | 38 | var observable = _DiscogsClient.Search(discogsSearch); 39 | await observable.ForEachAsync(OnResult); 40 | } 41 | 42 | [Fact(Skip = "Need internet access and valid token and keys.")] 43 | public async Task SearchAsync() 44 | { 45 | var discogsSearch = new DiscogsSearch() 46 | { 47 | artist = "Ornette Coleman", 48 | release_title = "The Shape Of Jazz To Come" 49 | }; 50 | 51 | var res = await _DiscogsClient.SearchAsync(discogsSearch); 52 | foreach (var searchResult in res.GetResults()) 53 | { 54 | OnResult(searchResult); 55 | } 56 | } 57 | 58 | [Fact(Skip = "Need internet access and valid token and keys.")] 59 | public async Task GetUserIdentityAsync() 60 | { 61 | var res = await _DiscogsClient.GetUserIdentityAsync(); 62 | res.Should().NotBeNull(); 63 | } 64 | 65 | [Fact(Skip = "Need internet access and valid token and keys.")] 66 | public async Task SetUserReleaseRatingAsync() 67 | { 68 | var res = await _DiscogsClient.SetUserReleaseRatingAsync(488973, 5); 69 | res.Should().NotBeNull(); 70 | } 71 | 72 | [Fact(Skip = "Need internet access and valid token and keys.")] 73 | public async Task DeleteUserReleaseRatingAsync() 74 | { 75 | var res = await _DiscogsClient.DeleteUserReleaseRatingAsync(488973); 76 | res.Should().BeTrue(); 77 | } 78 | 79 | [Fact(Skip = "Need internet access and valid token and keys.")] 80 | public async Task Search_ArtistAsync() 81 | { 82 | var discogsSearch = new DiscogsSearch() 83 | { 84 | query = "Ornette Coleman", 85 | type = DiscogsEntityType.artist 86 | }; 87 | 88 | var observable = _DiscogsClient.Search(discogsSearch); 89 | await observable.ForEachAsync(OnResult); 90 | } 91 | 92 | private void OnResult(DiscogsSearchResult result) 93 | { 94 | _Count++; 95 | Trace.WriteLine($"{_Count} - {result.title}"); 96 | } 97 | 98 | [Fact(Skip = "Need internet access.")] 99 | public async Task GetMasterReleaseVersions() 100 | { 101 | var observable = _DiscogsClient.GetMasterReleaseVersions(47813); 102 | await observable.ForEachAsync(OnResult); 103 | } 104 | 105 | [Fact(Skip = "Need internet access.")] 106 | public async Task GetMasterReleaseVersionAsync() 107 | { 108 | var res = await _DiscogsClient.GetMasterReleaseVersionsAsync(47813); 109 | foreach (var searchResult in res.GetResults()) 110 | { 111 | OnResult(searchResult); 112 | } 113 | } 114 | 115 | private void OnResult(DiscogsReleaseVersion result) 116 | { 117 | _Count++; 118 | Trace.WriteLine($"{_Count} - {result.title}"); 119 | } 120 | 121 | [Fact(Skip = "Need internet access.")] 122 | public async Task GetReleaseAsync() 123 | { 124 | var res = await _DiscogsClient.GetReleaseAsync(1704673); 125 | res.Should().NotBeNull(); 126 | } 127 | 128 | [Fact(Skip = "Need internet access.")] 129 | public async Task GetMasterAsync() 130 | { 131 | var res = await _DiscogsClient.GetMasterAsync(47813); 132 | res.Should().NotBeNull(); 133 | } 134 | 135 | [Fact (Skip = "Need internet access.")] 136 | public async Task GetArtistAsync() 137 | { 138 | var res = await _DiscogsClient.GetArtistAsync(224506); 139 | res.Should().NotBeNull(); 140 | } 141 | 142 | [Fact(Skip = "Need internet access.")] 143 | public async Task GetArtistReleaseAsync() 144 | { 145 | var observable = _DiscogsClient.GetArtistRelease(200818); 146 | await observable.ForEachAsync(OnResult); 147 | } 148 | 149 | private void OnResult(DiscogsArtistRelease result) 150 | { 151 | _Count++; 152 | Trace.WriteLine($"{_Count} - {result.title}"); 153 | } 154 | 155 | [Fact(Skip = "Need internet access.")] 156 | public async Task GetLabelAsync() 157 | { 158 | var res = await _DiscogsClient.GetLabelAsync(125); 159 | res.Should().NotBeNull(); 160 | } 161 | 162 | [Fact(Skip = "Need internet access.")] 163 | public async Task GetAllLabelReleases() 164 | { 165 | var observable = _DiscogsClient.GetAllLabelReleases(26557); 166 | await observable.ForEachAsync(OnResult); 167 | } 168 | 169 | [Fact(Skip = "Need internet access.")] 170 | public async Task GetAllLabelReleasesAsync() 171 | { 172 | var res = await _DiscogsClient.GetAllLabelReleasesAsync(26557); 173 | foreach (var searchResult in res.GetResults()) 174 | { 175 | OnResult(searchResult); 176 | } 177 | } 178 | 179 | private void OnResult(DiscogsLabelRelease result) 180 | { 181 | _Count++; 182 | _TestOutputHelper.WriteLine($"{_Count} - {result.title}"); 183 | } 184 | 185 | [Fact(Skip = "Need internet access.")] 186 | public async Task GetUserReleaseRatingAsync() 187 | { 188 | var res = await _DiscogsClient.GetUserReleaseRatingAsync("andersinstockholm", 488973); 189 | res.Should().NotBeNull(); 190 | } 191 | 192 | [Fact(Skip = "Need internet access.")] 193 | public async Task GetCommunityReleaseRatingAsync() 194 | { 195 | var res = await _DiscogsClient.GetCommunityReleaseRatingAsync(488973); 196 | res.Should().NotBeNull(); 197 | } 198 | 199 | [Fact(Skip = "Need internet access and valid token and keys.")] 200 | public async Task SaveImageAsync() 201 | { 202 | var res = await _DiscogsClient.GetMasterAsync(47813); 203 | res.Should().NotBeNull(); 204 | 205 | await _DiscogsClient.SaveImageAsync(res.images[0], Path.GetTempPath(), "Ornette-TSOAJTC"); 206 | } 207 | } 208 | } 209 | -------------------------------------------------------------------------------- /DiscogsClient/DiscogsClient.cs: -------------------------------------------------------------------------------- 1 | using DiscogsClient.Data.Query; 2 | using DiscogsClient.Data.Result; 3 | using DiscogsClient.Internal; 4 | using RestSharp; 5 | using RestSharpHelper; 6 | using RestSharpHelper.OAuth1; 7 | using System; 8 | using System.Collections.Generic; 9 | using System.IO; 10 | using System.Net; 11 | using System.Reactive.Linq; 12 | using System.Threading; 13 | using System.Threading.Tasks; 14 | 15 | namespace DiscogsClient 16 | { 17 | public class DiscogsClient : IDiscogsDataBaseClient, IDiscogsUserIdentityClient 18 | { 19 | private readonly IDiscogsWebClient _Client; 20 | private DiscogsIdentity _DiscogsIdentity; 21 | 22 | public DiscogsClient(OAuthCompleteInformation oAuthCompleteInformation, string userAgent = null, int timeOut = 5000) 23 | { 24 | _Client = new DiscogsWebClient(oAuthCompleteInformation, userAgent, timeOut); 25 | } 26 | 27 | public DiscogsClient(TokenAuthenticationInformation tokenAuthenticationInformation, string userAgent = null, int timeOut = 5000) 28 | { 29 | _Client = new DiscogsWebClient(tokenAuthenticationInformation, userAgent, timeOut); 30 | } 31 | 32 | public Task GetUserIdentityAsync() 33 | { 34 | return GetUserIdentityAsync(CancellationToken.None); 35 | } 36 | 37 | public async Task GetUserIdentityAsync(CancellationToken token) 38 | { 39 | if (_DiscogsIdentity != null) 40 | return _DiscogsIdentity; 41 | 42 | var request = _Client.GetUserIdentityRequest(); 43 | return _DiscogsIdentity = await _Client.Execute(request, token); 44 | } 45 | 46 | public Task GetReleaseAsync(int releaseId) 47 | { 48 | return GetReleaseAsync(releaseId, CancellationToken.None); 49 | } 50 | 51 | public async Task GetReleaseAsync(int releaseId, CancellationToken token) 52 | { 53 | var request = _Client.GetReleaseRequest(releaseId); 54 | return await _Client.Execute(request, token); 55 | } 56 | 57 | public Task GetMasterAsync(int masterId) 58 | { 59 | return GetMasterAsync(masterId, CancellationToken.None); 60 | } 61 | 62 | public async Task GetMasterAsync(int masterId, CancellationToken token) 63 | { 64 | var request = _Client.GetMasterRequest(masterId); 65 | return await _Client.Execute(request, token); 66 | } 67 | 68 | public Task GetArtistAsync(int artistId) 69 | { 70 | return GetArtistAsync(artistId, CancellationToken.None); 71 | } 72 | 73 | public async Task GetArtistAsync(int artistId, CancellationToken token) 74 | { 75 | var request = _Client.GetArtistRequest(artistId); 76 | return await _Client.Execute(request, token); 77 | } 78 | 79 | public Task GetLabelAsync(int labelId) 80 | { 81 | return GetLabelAsync(labelId, CancellationToken.None); 82 | } 83 | 84 | public async Task GetLabelAsync(int labelId, CancellationToken token) 85 | { 86 | var request = _Client.GetLabelRequest(labelId); 87 | return await _Client.Execute(request, token); 88 | } 89 | 90 | public Task GetUserReleaseRatingAsync(string userName, int releaseId) 91 | { 92 | return GetUserReleaseRatingAsync(userName, releaseId, CancellationToken.None); 93 | } 94 | 95 | public async Task GetUserReleaseRatingAsync(string userName, int releaseId, CancellationToken token) 96 | { 97 | var request = _Client.GetGetUserReleaseRatingRequest(userName, releaseId); 98 | return await _Client.Execute(request, token); 99 | } 100 | 101 | public Task SetUserReleaseRatingAsync(int releaseId, int rating) 102 | { 103 | return SetUserReleaseRatingAsync(releaseId, rating, CancellationToken.None); 104 | } 105 | 106 | public async Task SetUserReleaseRatingAsync(int releaseId, int rating, CancellationToken token) 107 | { 108 | var userIdentity = await GetUserIdentityAsync(token); 109 | var request = _Client.GetPutUserReleaseRatingRequest(userIdentity.username, releaseId); 110 | request.AddJsonBody(new { rating = rating }); 111 | return await _Client.Execute(request, token); 112 | } 113 | 114 | public Task DeleteUserReleaseRatingAsync(int releaseId) 115 | { 116 | return DeleteUserReleaseRatingAsync(releaseId, CancellationToken.None); 117 | } 118 | 119 | public async Task DeleteUserReleaseRatingAsync(int releaseId, CancellationToken token) 120 | { 121 | var userIdentity = await GetUserIdentityAsync(token); 122 | var request = _Client.GetDeleteUserReleaseRatingRequest(userIdentity.username, releaseId); 123 | return await _Client.Execute(request, token) == HttpStatusCode.NoContent; 124 | } 125 | 126 | public Task GetCommunityReleaseRatingAsync(int releaseId) 127 | { 128 | return GetCommunityReleaseRatingAsync(releaseId, CancellationToken.None); 129 | } 130 | 131 | public async Task GetCommunityReleaseRatingAsync(int releaseId, CancellationToken token) 132 | { 133 | var request = _Client.GetCommunityReleaseRatingRequest(releaseId); 134 | return await _Client.Execute(request, token); 135 | } 136 | 137 | public IEnumerable SearchAsEnumerable(DiscogsSearch search, int? max = null) 138 | { 139 | return Search(search, max).ToEnumerable(); 140 | } 141 | 142 | public IObservable Search(DiscogsSearch search, int? max = null) 143 | { 144 | var observable = RawSearchAll(search, max); 145 | return max.HasValue ? observable.Take(max.Value) : observable; 146 | } 147 | 148 | public Task SearchAsync(DiscogsSearch search, DiscogsPaginable paginable, CancellationToken token) 149 | { 150 | IRestRequest RequestBuilder() => _Client.GetSearchRequest().AddAsParameter(search); 151 | return GetPaginableAsync(RequestBuilder, paginable, token); 152 | } 153 | 154 | public Task SearchAsync(DiscogsSearch search, DiscogsPaginable paginable = null) 155 | { 156 | return SearchAsync(search, paginable, CancellationToken.None); 157 | } 158 | 159 | private IObservable RawSearchAll(DiscogsSearch search, int? max = null) 160 | { 161 | IRestRequest RequestBuilder() => _Client.GetSearchRequest().AddAsParameter(search); 162 | return GenerateFromPaginable(RequestBuilder, max); 163 | } 164 | 165 | public IEnumerable GetMasterReleaseVersionsAsEnumerable(int masterId, int? max = default(int?)) 166 | { 167 | return GetMasterReleaseVersions(masterId, max).ToEnumerable(); 168 | } 169 | 170 | public IObservable GetMasterReleaseVersions(int masterId, int? max = default(int?)) 171 | { 172 | var observable = GetMasterReleaseVersionseRaw(masterId, max); 173 | return max.HasValue ? observable.Take(max.Value) : observable; 174 | } 175 | 176 | public Task GetMasterReleaseVersionsAsync(int masterId, DiscogsPaginable paginable, CancellationToken token) 177 | { 178 | IRestRequest RequestBuilder() => _Client.GetMasterReleaseVersionRequest(masterId); 179 | return GetPaginableAsync(RequestBuilder, paginable, token); 180 | } 181 | 182 | public Task GetMasterReleaseVersionsAsync(int masterId, DiscogsPaginable paginable = null) 183 | { 184 | return GetMasterReleaseVersionsAsync(masterId, paginable, CancellationToken.None); 185 | } 186 | 187 | private IObservable GetMasterReleaseVersionseRaw(int masterId, int? max = default(int?)) 188 | { 189 | IRestRequest RequestBuilder() => _Client.GetMasterReleaseVersionRequest(masterId); 190 | return GenerateFromPaginable(RequestBuilder, max); 191 | } 192 | 193 | public IEnumerable GetArtistReleaseAsEnumerable(int artistId, DiscogsSortInformation sort = null, int? max = null) 194 | { 195 | return GetArtistRelease(artistId, sort, max).ToEnumerable(); 196 | } 197 | 198 | public IObservable GetArtistRelease(int artistId, DiscogsSortInformation sort = null, int? max = null) 199 | { 200 | var observable = GetArtistReleaseRaw(artistId, sort, max); 201 | return max.HasValue ? observable.Take(max.Value) : observable; 202 | } 203 | 204 | public Task GetArtistReleaseAsync(int artistId, DiscogsSortInformation sort, DiscogsPaginable paginable, CancellationToken token) 205 | { 206 | IRestRequest RequestBuilder() => _Client.GetArtistReleaseVersionRequest(artistId).AddAsParameter(sort); 207 | return GetPaginableAsync(RequestBuilder, paginable, token); 208 | } 209 | 210 | public Task GetArtistReleaseAsync(int artistId, DiscogsSortInformation sort = null, DiscogsPaginable paginable = null) 211 | { 212 | return GetArtistReleaseAsync(artistId, sort, paginable, CancellationToken.None); 213 | } 214 | 215 | private IObservable GetArtistReleaseRaw(int artistId, DiscogsSortInformation sort = null, int? max = null) 216 | { 217 | IRestRequest RequestBuilder() => _Client.GetArtistReleaseVersionRequest(artistId).AddAsParameter(sort); 218 | return GenerateFromPaginable(RequestBuilder, max); 219 | } 220 | 221 | public IEnumerable GetAllLabelReleasesAsEnumerable(int labelId, int? max = null) 222 | { 223 | return GetAllLabelReleases(labelId, max).ToEnumerable(); 224 | } 225 | 226 | public IObservable GetAllLabelReleases(int labelId, int? max = null) 227 | { 228 | var observable = GetAllLabelReleasesRaw(labelId, max); 229 | return max.HasValue ? observable.Take(max.Value) : observable; 230 | } 231 | 232 | public Task GetAllLabelReleasesAsync(int labelId, DiscogsPaginable paginable, CancellationToken token) 233 | { 234 | IRestRequest RequestBuilder() => _Client.GetAllLabelReleasesRequest(labelId); 235 | return GetPaginableAsync(RequestBuilder, paginable, token); 236 | } 237 | 238 | public Task GetAllLabelReleasesAsync(int labelId, DiscogsPaginable paginable = null) 239 | { 240 | return GetAllLabelReleasesAsync(labelId, paginable, CancellationToken.None); 241 | } 242 | 243 | private IObservable GetAllLabelReleasesRaw(int labelId, int? max = null) 244 | { 245 | IRestRequest RequestBuilder() => _Client.GetAllLabelReleasesRequest(labelId); 246 | return GenerateFromPaginable(RequestBuilder, max); 247 | } 248 | 249 | private IObservable GenerateFromPaginable(Func requestBuilder, int? max = null) where T : DiscogsEntity 250 | where TRes : DiscogsPaginableResults 251 | { 252 | var paginable = new DiscogsPaginable() 253 | { 254 | per_page = (max > 0) ? Math.Min(50, max.Value) : new int?(), 255 | page = 1 256 | }; 257 | 258 | return Observable.Create(async (observer, cancel) => 259 | { 260 | DiscogsPaginedResult pagination; 261 | do 262 | { 263 | cancel.ThrowIfCancellationRequested(); 264 | var request = requestBuilder().AddAsParameter(paginable); 265 | paginable.page++; 266 | 267 | var res = await _Client.Execute(request, cancel); 268 | var elements = res?.GetResults(); 269 | if (elements == null) 270 | return; 271 | 272 | foreach (var result in elements) 273 | { 274 | cancel.ThrowIfCancellationRequested(); 275 | observer.OnNext(result); 276 | } 277 | 278 | pagination = res.pagination; 279 | } 280 | while (pagination.page != pagination.pages); 281 | }); 282 | } 283 | 284 | private async Task GetPaginableAsync(Func requestBuilder, DiscogsPaginable paginable, CancellationToken token) 285 | { 286 | paginable = paginable ?? new DiscogsPaginable() 287 | { 288 | per_page = 50, 289 | page = 1 290 | }; 291 | 292 | var request = requestBuilder().AddAsParameter(paginable); 293 | return await _Client.Execute(request, token); 294 | } 295 | 296 | public Task DownloadImageAsync(DiscogsImage image, Stream copyStream, DiscogsImageFormatType type = DiscogsImageFormatType.Normal) 297 | { 298 | return DownloadImageAsync(image, copyStream, CancellationToken.None, type); 299 | } 300 | 301 | public async Task DownloadImageAsync(DiscogsImage image, Stream copyStream, CancellationToken cancellationToken, DiscogsImageFormatType type = DiscogsImageFormatType.Normal) 302 | { 303 | var url = (type == DiscogsImageFormatType.Normal) ? image.uri : image.uri150; 304 | await _Client.Download(url, copyStream, cancellationToken); 305 | } 306 | 307 | public Task SaveImageAsync(DiscogsImage image, string path, string fileName, DiscogsImageFormatType type = DiscogsImageFormatType.Normal) 308 | { 309 | return SaveImageAsync(image, path, fileName, CancellationToken.None, type); 310 | } 311 | 312 | public async Task SaveImageAsync(DiscogsImage image, string path, string fileName, CancellationToken cancellationToken, DiscogsImageFormatType type = DiscogsImageFormatType.Normal) 313 | { 314 | var url = (type == DiscogsImageFormatType.Normal) ? image.uri : image.uri150; 315 | return await _Client.SaveFile(url, path, fileName, cancellationToken); 316 | } 317 | } 318 | } 319 | -------------------------------------------------------------------------------- /DiscogsClient/IDiscogsDataBaseClient.cs: -------------------------------------------------------------------------------- 1 | using DiscogsClient.Data.Query; 2 | using DiscogsClient.Data.Result; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.IO; 6 | using System.Threading; 7 | using System.Threading.Tasks; 8 | 9 | namespace DiscogsClient 10 | { 11 | public interface IDiscogsDataBaseClient : IDiscogsReleaseRatingClient 12 | { 13 | /// 14 | /// Get a release 15 | /// See https://www.discogs.com/developers/#page:database,header:database-release 16 | /// 17 | /// The Release ID 18 | /// Cancellation Token 19 | /// The corresponding release 20 | Task GetReleaseAsync(int releaseId, CancellationToken token); 21 | 22 | /// 23 | /// Get a release 24 | /// See https://www.discogs.com/developers/#page:database,header:database-release 25 | /// 26 | /// The Release ID 27 | /// The corresponding release 28 | Task GetReleaseAsync(int releaseId); 29 | 30 | /// 31 | /// Get a master release 32 | /// See https://www.discogs.com/developers/#page:database,header:database-master-release 33 | /// 34 | /// The Master ID 35 | /// Cancellation Token 36 | /// The corresponding master 37 | Task GetMasterAsync(int masterId, CancellationToken token); 38 | 39 | /// 40 | /// Get a master release 41 | /// see https://www.discogs.com/developers/#page:database,header:database-master-release 42 | /// 43 | /// The Master ID 44 | /// The corresponding master 45 | Task GetMasterAsync(int masterId); 46 | 47 | /// 48 | /// Retrieves an observable of all Releases that are versions of this master. 49 | /// See https://www.discogs.com/developers/#page:database,header:database-master-release-versions 50 | /// 51 | /// The Master ID 52 | /// Number maximum of elements. If null return all elements. 53 | /// The corresponding releases 54 | IObservable GetMasterReleaseVersions(int masterId, int? max = null); 55 | 56 | /// 57 | /// Retrieves an enumerable of all Releases that are versions of this master. 58 | /// See https://www.discogs.com/developers/#page:database,header:database-master-release-versions 59 | /// 60 | /// The Master ID 61 | /// Number maximum of elements. If null return all elements. 62 | /// The corresponding releases 63 | IEnumerable GetMasterReleaseVersionsAsEnumerable(int masterId, int? max = null); 64 | 65 | /// 66 | /// Retrieves an enumerable of all Releases that are versions of this master. 67 | /// See https://www.discogs.com/developers/#page:database,header:database-master-release-versions 68 | /// 69 | /// The Master ID 70 | /// Paginable information 71 | /// CancellationToken 72 | /// The corresponding releases 73 | Task GetMasterReleaseVersionsAsync(int masterId, 74 | DiscogsPaginable paginable, CancellationToken token); 75 | 76 | /// 77 | /// Retrieves an enumerable of all Releases that are versions of this master. 78 | /// See https://www.discogs.com/developers/#page:database,header:database-master-release-versions 79 | /// 80 | /// The Master ID 81 | /// Paginable information 82 | /// The corresponding releases 83 | Task GetMasterReleaseVersionsAsync(int masterId, 84 | DiscogsPaginable paginable = null); 85 | 86 | /// 87 | /// Get an artist 88 | /// See https://www.discogs.com/developers/#page:database,header:database-artist 89 | /// 90 | /// The Release ID 91 | /// Cancellation Token 92 | /// The corresponding artist 93 | Task GetArtistAsync(int artistId, CancellationToken token); 94 | 95 | /// 96 | /// Get an artist 97 | /// See https://www.discogs.com/developers/#page:database,header:database-artist 98 | /// 99 | /// The Release ID 100 | /// The corresponding artist 101 | Task GetArtistAsync(int artistId); 102 | 103 | /// 104 | /// Returns a observable of Releases and Masters associated with the Artist. 105 | /// See https://www.discogs.com/developers/#page:database,header:database-artist-releases 106 | /// 107 | /// The artist ID 108 | /// Sorting information. 109 | /// Number maximum of elements. If null return all elements. 110 | /// The corresponding releases 111 | IObservable GetArtistRelease(int artistId, DiscogsSortInformation sort = null, int? max = null); 112 | 113 | /// 114 | /// Returns a enumerable of Releases and Masters associated with the Artist. 115 | /// See https://www.discogs.com/developers/#page:database,header:database-artist-releases 116 | /// 117 | /// The artist ID 118 | /// Sorting information 119 | /// Number maximum of elements. If null return all elements. 120 | /// The corresponding releases 121 | IEnumerable GetArtistReleaseAsEnumerable(int artistId, DiscogsSortInformation sort = null, int? max = null); 122 | 123 | /// 124 | /// Returns a enumerable of Releases and Masters associated with the Artist. 125 | /// See https://www.discogs.com/developers/#page:database,header:database-artist-releases 126 | /// 127 | /// The artist ID 128 | /// Sorting information 129 | /// Paginable information 130 | /// CancellationToken 131 | /// The corresponding releases 132 | Task GetArtistReleaseAsync(int artistId, 133 | DiscogsSortInformation sort, DiscogsPaginable paginable, CancellationToken token); 134 | 135 | /// 136 | /// Returns a enumerable of Releases and Masters associated with the Artist. 137 | /// See https://www.discogs.com/developers/#page:database,header:database-artist-releases 138 | /// 139 | /// The artist ID 140 | /// Sorting information 141 | /// Paginable information 142 | /// The corresponding releases 143 | Task GetArtistReleaseAsync(int artistId, 144 | DiscogsSortInformation sort = null, DiscogsPaginable paginable = null); 145 | 146 | /// 147 | /// Get a label 148 | /// See https://www.discogs.com/developers/#page:database,header:database-label 149 | /// 150 | /// The Label ID 151 | /// Cancellation Token 152 | /// The corresponding label 153 | Task GetLabelAsync(int labelId, CancellationToken token); 154 | 155 | /// 156 | /// Get a label 157 | /// See https://www.discogs.com/developers/#page:database,header:database-label 158 | /// 159 | /// The Label ID 160 | /// The corresponding label 161 | Task GetLabelAsync(int labelId); 162 | 163 | /// 164 | /// Returns an observable of Releases associated with the label. 165 | /// See https://www.discogs.com/developers/#page:database,header:database-all-label-releases 166 | /// 167 | /// The label ID 168 | /// Number maximum of elements. If null return all elements. 169 | /// The corresponding releases 170 | IObservable GetAllLabelReleases(int labelId, int? max = null); 171 | 172 | /// 173 | /// Returns an enumerable of Releases associated with the label. 174 | /// See https://www.discogs.com/developers/#page:database,header:database-all-label-releases 175 | /// 176 | /// The label ID 177 | /// Number maximum of elements. If null return all elements. 178 | /// The corresponding label releases 179 | IEnumerable GetAllLabelReleasesAsEnumerable(int labelId, int? max = null); 180 | 181 | /// 182 | /// Returns an enumerable of Releases associated with the label. 183 | /// See https://www.discogs.com/developers/#page:database,header:database-all-label-releases 184 | /// 185 | /// The label ID 186 | /// Paginable information 187 | /// CancellationToken 188 | /// The corresponding label releases 189 | Task GetAllLabelReleasesAsync(int labelId, 190 | DiscogsPaginable paginable, CancellationToken token); 191 | 192 | /// 193 | /// Returns an enumerable of Releases associated with the label. 194 | /// See https://www.discogs.com/developers/#page:database,header:database-all-label-releases 195 | /// 196 | /// The label ID 197 | /// Paginable information 198 | /// The corresponding label releases 199 | Task GetAllLabelReleasesAsync(int labelId, 200 | DiscogsPaginable paginable = null); 201 | 202 | /// 203 | /// Issue a search query to Discogs database. 204 | /// See https://www.discogs.com/developers/#page:database,header:database-search. 205 | /// 206 | /// The Corresponding query 207 | /// Number maximum of elements. If null return all elements. 208 | /// The corresponding search result 209 | IObservable Search(DiscogsSearch search, int? max = null); 210 | 211 | /// 212 | /// Issue a search query to Discogs database. 213 | /// See https://www.discogs.com/developers/#page:database,header:database-search. 214 | /// 215 | /// The Corresponding query 216 | /// Number maximum of elements. If null return all elements. 217 | /// The corresponding search result 218 | IEnumerable SearchAsEnumerable(DiscogsSearch search, int? max = null); 219 | 220 | /// 221 | /// Issue a search query to Discogs database. 222 | /// See https://www.discogs.com/developers/#page:database,header:database-search. 223 | /// 224 | /// The Corresponding query 225 | /// paginable information 226 | /// CancellationToken 227 | /// The corresponding search result 228 | Task SearchAsync(DiscogsSearch search, DiscogsPaginable paginable, 229 | CancellationToken token); 230 | 231 | /// 232 | /// Issue a search query to Discogs database. 233 | /// See https://www.discogs.com/developers/#page:database,header:database-search. 234 | /// 235 | /// The Corresponding query 236 | /// paginable information 237 | /// The corresponding search result 238 | Task SearchAsync(DiscogsSearch search, DiscogsPaginable paginable = null); 239 | 240 | /// 241 | /// Download the stream corresponding to a given image 242 | /// 243 | /// The image to download 244 | /// Stream where image stream will be copied 245 | /// Cancellation Token 246 | /// Type of image to download: thumbnail or normal 247 | Task DownloadImageAsync(DiscogsImage image, Stream copyStream, CancellationToken cancellationToken, DiscogsImageFormatType type = DiscogsImageFormatType.Normal); 248 | 249 | /// 250 | /// Download the stream corresponding to a given image 251 | /// 252 | /// The image to download 253 | /// Stream where image stream will be copied 254 | /// Type of image to download: thumbnail or normal 255 | Task DownloadImageAsync(DiscogsImage image, Stream copyStream, DiscogsImageFormatType type = DiscogsImageFormatType.Normal); 256 | 257 | /// 258 | /// Save a given image to disk. 259 | /// 260 | /// The image to download 261 | /// Type of image to download: thumbnail or normal 262 | /// Type of image to download: thumbnail or normal 263 | /// Type of image to download: thumbnail or normal 264 | /// Cancellation Token 265 | /// the file path 266 | Task SaveImageAsync(DiscogsImage image, string path, string fileName, CancellationToken cancellationToken, DiscogsImageFormatType type = DiscogsImageFormatType.Normal); 267 | 268 | /// 269 | /// Download the stream corresponding to a given image 270 | /// 271 | /// The image to download 272 | /// Type of image to download: thumbnail or normal 273 | /// Type of image to download: thumbnail or normal 274 | /// Type of image to download: thumbnail or normal 275 | /// the file path 276 | Task SaveImageAsync(DiscogsImage image, string path, string fileName, DiscogsImageFormatType type = DiscogsImageFormatType.Normal); 277 | } 278 | } -------------------------------------------------------------------------------- /DiscogsClient.Test/ResultDeserializationTest.cs: -------------------------------------------------------------------------------- 1 | using DiscogsClient.Data.Query; 2 | using DiscogsClient.Data.Result; 3 | using FluentAssertions; 4 | using Newtonsoft.Json; 5 | using Xunit; 6 | 7 | namespace DiscogsClient.Test 8 | { 9 | public class ResultDeserializationTest 10 | { 11 | private const string _SearchAnswer = "{\"pagination\": {\"per_page\": 50, \"pages\": 2, \"page\": 1, \"urls\": {\"last\": \"https://api.discogs.com/database/search?per_page=50&page=2&release_title=The+Shape+Of+Jazz+To+Come&artist=Ornette+Coleman\", \"next\": \"https://api.discogs.com/database/search?per_page=50&page=2&release_title=The+Shape+Of+Jazz+To+Come&artist=Ornette+Coleman\"}, \"items\": 61}, \"results\": [{\"style\": [\"Free Jazz\", \"Avant-garde Jazz\", \"Post Bop\"], \"thumb\": \"https://api-img.discogs.com/_6n5rHvc0IUcFhnS6TsiZNn9Vvk=/fit-in/150x150/filters:strip_icc():format(jpeg):mode_rgb():quality(40)/discogs-images/R-1704673-1457578226-9192.jpeg.jpg\", \"format\": [\"Vinyl\", \"LP\", \"Album\", \"Limited Edition\", \"Reissue\", \"Stereo\"], \"country\": \"US\", \"barcode\": [\"5032 SD1317-1 (A) S 42460\", \"5032 SD1317-1 B S 42461\", \"Lee Ba S\"], \"uri\": \"/Ornette-Coleman-The-Shape-Of-Jazz-To-Come/release/1704673\", \"community\": {\"want\": 149, \"have\": 351}, \"label\": [\"Atlantic\", \"Atlantic\"], \"catno\": \"1317\", \"year\": \"2006\", \"genre\": [\"Jazz\"], \"title\": \"Ornette Coleman - The Shape Of Jazz To Come\", \"resource_url\": \"https://api.discogs.com/releases/1704673\", \"type\": \"release\", \"id\": 1704673}, {\"style\": [], \"thumb\": \"https://api-img.discogs.com/s03VAP-WU-FqiM6oEwXMQsYvzOE=/fit-in/150x150/filters:strip_icc():format(jpeg):mode_rgb():quality(40)/discogs-images/R-5245666-1438947228-6715.jpeg.jpg\", \"format\": [\"SACD\", \"Stereo\"], \"country\": \"Japan\", \"barcode\": [\"711574707225\"], \"uri\": \"/Ornette-Coleman-The-Shape-Of-Jazz-To-Come/release/5245666\", \"community\": {\"want\": 46, \"have\": 4}, \"label\": [\"Atlantic\", \"ORG Music\"], \"catno\": \"SD-1317\", \"genre\": [\"Jazz\"], \"title\": \"Ornette Coleman - The Shape Of Jazz To Come\", \"resource_url\": \"https://api.discogs.com/releases/5245666\", \"type\": \"release\", \"id\": 5245666}, {\"style\": [\"Free Jazz\"], \"thumb\": \"https://api-img.discogs.com/2514IUVrhi89w5aoxRq5doZC_Pw=/fit-in/150x150/filters:strip_icc():format(jpeg):mode_rgb():quality(40)/discogs-images/R-4706785-1375012730-4204.jpeg.jpg\", \"format\": [\"Vinyl\", \"LP\", \"Album\", \"Stereo\", \"Reissue\"], \"country\": \"Europe\", \"barcode\": [\"8 89397 10191 6\"], \"uri\": \"/Ornette-Coleman-The-Shape-Of-Jazz-To-Come/release/4706785\", \"community\": {\"want\": 107, \"have\": 41}, \"label\": [\"So Far Out\"], \"catno\": \"OUT5007LP\", \"year\": \"2013\", \"genre\": [\"Jazz\"], \"title\": \"Ornette Coleman - The Shape Of Jazz To Come\", \"resource_url\": \"https://api.discogs.com/releases/4706785\", \"type\": \"release\", \"id\": 4706785}, {\"style\": [\"Free Jazz\"], \"thumb\": \"https://api-img.discogs.com/_XXjdeW18yheGMovfrR9sZW2hhU=/fit-in/150x150/filters:strip_icc():format(jpeg):mode_rgb():quality(40)/discogs-images/R-3579270-1336048223.png.jpg\", \"format\": [\"Vinyl\", \"LP\", \"Album\", \"Stereo\", \"Reissue\"], \"country\": \"US\", \"barcode\": [], \"uri\": \"/Ornette-Coleman-The-Shape-Of-Jazz-To-Come/release/3579270\", \"community\": {\"want\": 159, \"have\": 31}, \"label\": [\"Atlantic\"], \"catno\": \"SD 1317\", \"year\": \"1965\", \"genre\": [\"Jazz\"], \"title\": \"Ornette Coleman - The Shape Of Jazz To Come\", \"resource_url\": \"https://api.discogs.com/releases/3579270\", \"type\": \"release\", \"id\": 3579270}, {\"style\": [\"Free Jazz\"], \"thumb\": \"https://api-img.discogs.com/m_QjpfrDYQlKGDMJ13pxuM7tw3Q=/fit-in/150x150/filters:strip_icc():format(jpeg):mode_rgb():quality(40)/discogs-images/R-5963584-1407527470-2375.jpeg.jpg\", \"format\": [\"Vinyl\", \"LP\", \"Album\"], \"country\": \"Italy\", \"barcode\": [\"BIEM\", \"IT 11611\", \"IT 11612\", \"11611\", \"11612\"], \"uri\": \"/Ornette-Coleman-The-Shape-Of-Jazz-To-Come/release/5963584\", \"community\": {\"want\": 71, \"have\": 3}, \"label\": [\"Atlantic\"], \"catno\": \"1317\", \"genre\": [\"Jazz\"], \"title\": \"Ornette Coleman - The Shape Of Jazz To Come\", \"resource_url\": \"https://api.discogs.com/releases/5963584\", \"type\": \"release\", \"id\": 5963584}, {\"style\": [\"Free Jazz\"], \"thumb\": \"https://api-img.discogs.com/zeqRveHrT0VmMiVTtZEZOT2mAiA=/fit-in/150x150/filters:strip_icc():format(jpeg):mode_rgb():quality(40)/discogs-images/R-4429896-1364659508-2148.png.jpg\", \"format\": [\"Vinyl\", \"LP\", \"Album\", \"Mono\"], \"country\": \"US\", \"barcode\": [\"11 611 AT\", \"A-11612-B AT\"], \"uri\": \"/Ornette-Coleman-The-Shape-Of-Jazz-To-Come/release/4429896\", \"community\": {\"want\": 112, \"have\": 19}, \"label\": [\"Atlantic\", \"Atlantic Recording Corporation\"], \"catno\": \"1317\", \"genre\": [\"Jazz\"], \"title\": \"Ornette Coleman - The Shape Of Jazz To Come\", \"resource_url\": \"https://api.discogs.com/releases/4429896\", \"type\": \"release\", \"id\": 4429896}, {\"style\": [\"Free Jazz\"], \"thumb\": \"https://api-img.discogs.com/q3-UZo285ibf50iJpEGwNxUFnpQ=/fit-in/150x150/filters:strip_icc():format(jpeg):mode_rgb():quality(40)/discogs-images/R-2343705-1283108409.jpeg.jpg\", \"format\": [\"Vinyl\", \"7\\\"\", \"EP\"], \"country\": \"US\", \"barcode\": [], \"uri\": \"/Ornette-Coleman-The-Shape-Of-Jazz-To-Come/release/2343705\", \"community\": {\"want\": 20, \"have\": 5}, \"label\": [\"Atlantic\"], \"catno\": \"ATL.EP 80.016\", \"genre\": [\"Jazz\"], \"title\": \"Ornette Coleman - The Shape Of Jazz To Come\", \"resource_url\": \"https://api.discogs.com/releases/2343705\", \"type\": \"release\", \"id\": 2343705}, {\"style\": [\"Free Jazz\"], \"thumb\": \"https://api-img.discogs.com/-DE6YjrJehLaZ1nVFplyWyL9fMk=/fit-in/150x150/filters:strip_icc():format(jpeg):mode_rgb():quality(40)/discogs-images/R-2776761-1300552697.jpeg.jpg\", \"format\": [\"Vinyl\", \"LP\", \"Album\", \"Stereo\", \"Reissue\"], \"country\": \"Japan\", \"barcode\": [\"P-7510A1 ST-A-59175 H\", \"P-7510A2 ST-A-59176 H\", \"\\u00a5 2,200 \"], \"uri\": \"/Ornette-Coleman-The-Shape-Of-Jazz-To-Come/release/2776761\", \"community\": {\"want\": 127, \"have\": 30}, \"label\": [\"Atlantic\", \"Atlantic\", \"Jazz-Forever Excellent\", \"Warner-Pioneer Corporation\"], \"catno\": \"P-7510A\", \"year\": \"1976\", \"genre\": [\"Jazz\"], \"title\": \"Ornette Coleman - The Shape Of Jazz To Come\", \"resource_url\": \"https://api.discogs.com/releases/2776761\", \"type\": \"release\", \"id\": 2776761}, {\"style\": [\"Free Jazz\"], \"thumb\": \"https://api-img.discogs.com/OsBMC5QXJuTtKGhWvWvhqCnkHXE=/fit-in/150x150/filters:strip_icc():format(jpeg):mode_rgb():quality(40)/discogs-images/R-6803658-1426963198-2864.jpeg.jpg\", \"format\": [\"Vinyl\", \"LP\", \"Album\", \"Stereo\"], \"country\": \"Denmark\", \"barcode\": [\"ST-A-59175\", \"ST-A-59176\", \"ST-A-59175 AVCO\", \"ST-A-59175 AVCO\"], \"uri\": \"/Ornette-Coleman-The-Shape-Of-Jazz-To-Come/release/6803658\", \"community\": {\"want\": 83, \"have\": 12}, \"label\": [\"Atlantic\"], \"catno\": \"SD 1317\", \"year\": \"1959\", \"genre\": [\"Jazz\"], \"title\": \"Ornette Coleman - The Shape Of Jazz To Come\", \"resource_url\": \"https://api.discogs.com/releases/6803658\", \"type\": \"release\", \"id\": 6803658}, {\"style\": [\"Free Jazz\", \"Post Bop\"], \"thumb\": \"https://api-img.discogs.com/yzLLeCx8YzJDu1Jk4IcqC3vBF1I=/fit-in/150x150/filters:strip_icc():format(jpeg):mode_rgb():quality(40)/discogs-images/R-8466360-1462155768-5415.jpeg.jpg\", \"format\": [\"CD\", \"Album\", \"Club Edition\", \"Reissue\"], \"country\": \"US\", \"barcode\": [], \"uri\": \"/Ornette-Coleman-The-Shape-Of-Jazz-To-Come/release/8466360\", \"community\": {\"want\": 4, \"have\": 0}, \"label\": [\"Atlantic\", \"Atlantic Recording Corporation\", \"WEA Manufacturing Inc.\", \"Radio Recorders\", \"Atlantic Studios\", \"BMG Direct Marketing, Inc.\"], \"catno\": \"1317-2\", \"year\": \"1990\", \"genre\": [\"Jazz\"], \"title\": \"Ornette Coleman - The Shape Of Jazz To Come\", \"resource_url\": \"https://api.discogs.com/releases/8466360\", \"type\": \"release\", \"id\": 8466360}, {\"style\": [\"Free Jazz\"], \"thumb\": \"https://api-img.discogs.com/kxAT_nAqeszx_P7ROluZcFTbWjo=/fit-in/150x150/filters:strip_icc():format(jpeg):mode_rgb():quality(40)/discogs-images/R-2048812-1425357495-7370.jpeg.jpg\", \"format\": [\"CD\", \"Album\", \"Reissue\"], \"country\": \"Europe\", \"barcode\": [\"081227313326\", \"0 81227 31332 6\", \"IFPI L012\", \"IFPI 05R5\", \"[Warners Logo] CD 812273133-2 V01\", \"BIEM / GEMA\", \"LC: 000325\", \"ATLANTIC 1317\"], \"uri\": \"/Ornette-Coleman-The-Shape-Of-Jazz-To-Come/release/2048812\", \"community\": {\"want\": 55, \"have\": 99}, \"label\": [\"Atlantic\", \"Warner Jazz\", \"Warner Strategic Marketing\", \"Atlantic Masters\", \"Atlantic Recording Corporation\", \"Atlantic Recording Corporation\", \"Radio Recorders\"], \"catno\": \"8122731332\", \"year\": \"2005\", \"genre\": [\"Jazz\"], \"title\": \"Ornette Coleman - The Shape Of Jazz To Come\", \"resource_url\": \"https://api.discogs.com/releases/2048812\", \"type\": \"release\", \"id\": 2048812}, {\"style\": [\"Free Jazz\", \"Post Bop\"], \"thumb\": \"https://api-img.discogs.com/GQyPPdp4M5YLERd5ha9rEMv13zo=/fit-in/150x150/filters:strip_icc():format(jpeg):mode_rgb():quality(40)/discogs-images/R-2141508-1266253347.jpeg.jpg\", \"format\": [\"CD\", \"Album\", \"Reissue\"], \"country\": \"Europe\", \"barcode\": [\"8436028694501\"], \"uri\": \"/Ornette-Coleman-The-Shape-Of-Jazz-To-Come/release/2141508\", \"community\": {\"want\": 55, \"have\": 22}, \"label\": [\"Essential Jazz Classics\"], \"catno\": \"EJC55450\", \"year\": \"2010\", \"genre\": [\"Jazz\"], \"title\": \"Ornette Coleman - The Shape Of Jazz To Come\", \"resource_url\": \"https://api.discogs.com/releases/2141508\", \"type\": \"release\", \"id\": 2141508}, {\"style\": [\"Free Jazz\"], \"thumb\": \"https://api-img.discogs.com/7VgGOSv1FKjQCeQADraxkoh_FRY=/fit-in/150x150/filters:strip_icc():format(jpeg):mode_rgb():quality(40)/discogs-images/R-6228343-1414867715-3338.jpeg.jpg\", \"format\": [\"Vinyl\", \"LP\", \"Album\", \"Reissue\"], \"country\": \"Europe\", \"barcode\": [\"5060397601063\", \"122053E1/A\", \"122053E2/A\"], \"uri\": \"/Ornette-Coleman-The-Shape-Of-Jazz-To-Come/release/6228343\", \"community\": {\"want\": 88, \"have\": 58}, \"label\": [\"Not Now Music\", \"GZ Media\"], \"catno\": \"CATLP106\", \"year\": \"2014\", \"genre\": [\"Jazz\"], \"title\": \"Ornette Coleman - The Shape Of Jazz To Come\", \"resource_url\": \"https://api.discogs.com/releases/6228343\", \"type\": \"release\", \"id\": 6228343}, {\"style\": [\"Free Jazz\"], \"thumb\": \"https://api-img.discogs.com/sIcSmgcMolfiha9DHiWrXNLMFAY=/fit-in/150x150/filters:strip_icc():format(jpeg):mode_rgb():quality(40)/discogs-images/R-8407445-1461006305-7845.jpeg.jpg\", \"format\": [\"Cassette\", \"Album\", \"Stereo\"], \"country\": \"US\", \"barcode\": [\"075678133947\"], \"uri\": \"/Ornette-Coleman-The-Shape-Of-Jazz-To-Come/release/8407445\", \"community\": {\"want\": 5, \"have\": 1}, \"label\": [\"Atlantic\"], \"catno\": \"CS 1317\", \"genre\": [\"Jazz\"], \"title\": \"Ornette Coleman - The Shape Of Jazz To Come\", \"resource_url\": \"https://api.discogs.com/releases/8407445\", \"type\": \"release\", \"id\": 8407445}, {\"style\": [\"Free Jazz\"], \"thumb\": \"https://api-img.discogs.com/eMpQ9MOscoBbqfpPQeadZPfx9hs=/fit-in/150x150/filters:strip_icc():format(jpeg):mode_rgb():quality(40)/discogs-images/R-7735097-1447696567-9673.jpeg.jpg\", \"format\": [\"Vinyl\", \"LP\", \"Album\", \"Reissue\"], \"country\": \"Europe\", \"barcode\": [\"889397287016\"], \"uri\": \"/Ornette-Coleman-The-Shape-Of-Jazz-To-Come/release/7735097\", \"community\": {\"want\": 30, \"have\": 13}, \"label\": [\"DOL\"], \"catno\": \"DOL870H\", \"year\": \"2015\", \"genre\": [\"Jazz\"], \"title\": \"Ornette Coleman - The Shape Of Jazz To Come\", \"resource_url\": \"https://api.discogs.com/releases/7735097\", \"type\": \"release\", \"id\": 7735097}, {\"style\": [\"Free Jazz\"], \"thumb\": \"https://api-img.discogs.com/twqGnCjft0sj8lcoPsU9z8O1bJk=/fit-in/150x150/filters:strip_icc():format(jpeg):mode_rgb():quality(40)/discogs-images/R-6341913-1416891458-7813.jpeg.jpg\", \"format\": [\"CD\", \"Club Edition\"], \"country\": \"US\", \"barcode\": [\"0 7567-81339-2 3 \"], \"uri\": \"/Ornette-Coleman-The-Shape-Of-Jazz-To-Come/release/6341913\", \"community\": {\"want\": 37, \"have\": 3}, \"label\": [\"Atlantic\", \"Columbia House\"], \"catno\": \"A2 1317\", \"genre\": [\"Jazz\"], \"title\": \"Ornette Coleman - The Shape Of Jazz To Come\", \"resource_url\": \"https://api.discogs.com/releases/6341913\", \"type\": \"release\", \"id\": 6341913}, {\"style\": [\"Free Jazz\"], \"thumb\": \"https://api-img.discogs.com/55UVRDKd9Rt7PnHdOvlYzkUBGY4=/fit-in/150x150/filters:strip_icc():format(jpeg):mode_rgb():quality(40)/discogs-images/R-4785542-1409405676-5203.jpeg.jpg\", \"format\": [\"CD\", \"Reissue\"], \"country\": \"Germany\", \"barcode\": [], \"uri\": \"/Ornette-Coleman-The-Shape-Of-Jazz-To-Come/release/4785542\", \"community\": {\"want\": 42, \"have\": 8}, \"label\": [\"Atlantic\"], \"catno\": \"781 339-2\", \"genre\": [\"Jazz\"], \"title\": \"Ornette Coleman - The Shape Of Jazz To Come\", \"resource_url\": \"https://api.discogs.com/releases/4785542\", \"type\": \"release\", \"id\": 4785542}, {\"style\": [\"Free Jazz\"], \"thumb\": \"https://api-img.discogs.com/b9c_RIkcWkMO4qw1bbAFeAKPYdk=/fit-in/150x150/filters:strip_icc():format(jpeg):mode_rgb():quality(40)/discogs-images/R-6078923-1410516334-8105.jpeg.jpg\", \"format\": [\"Vinyl\", \"LP\", \"Album\", \"Reissue\", \"Stereo\"], \"country\": \"US\", \"barcode\": [\"ST-A-59175-K sf/atl.[Stamped] SRC\", \"ST-A-59176-I\", \"ST-A-59175-SP\", \"ST-A-59176-SP\", \"0 7567-81339-1 6\"], \"uri\": \"/Ornette-Coleman-The-Shape-Of-Jazz-To-Come/release/6078923\", \"community\": {\"want\": 75, \"have\": 19}, \"label\": [\"Atlantic\", \"Atlantic\", \"Atlantic Recording Corporation\", \"Warner Communications\", \"MJQ Music\", \"Atlantic Studios\", \"Specialty Records Corporation\"], \"catno\": \"1317\", \"genre\": [\"Jazz\"], \"title\": \"Ornette Coleman - The Shape Of Jazz To Come\", \"resource_url\": \"https://api.discogs.com/releases/6078923\", \"type\": \"release\", \"id\": 6078923}, {\"style\": [], \"thumb\": \"https://api-img.discogs.com/GD54R2RrQ9JD91EvwlAaDChLN2A=/fit-in/150x150/filters:strip_icc():format(jpeg):mode_rgb():quality(40)/discogs-images/R-2527331-1325004183.jpeg.jpg\", \"format\": [\"Vinyl\", \"LP\", \"Album\", \"Mono\"], \"country\": \"US\", \"barcode\": [], \"uri\": \"/Ornette-Coleman-The-Shape-Of-Jazz-To-Come/release/2527331\", \"community\": {\"want\": 252, \"have\": 63}, \"label\": [\"Atlantic\"], \"catno\": \"1317\", \"year\": \"1959\", \"genre\": [\"Jazz\"], \"title\": \"Ornette Coleman - The Shape Of Jazz To Come\", \"resource_url\": \"https://api.discogs.com/releases/2527331\", \"type\": \"release\", \"id\": 2527331}, {\"style\": [\"Free Jazz\"], \"thumb\": \"https://api-img.discogs.com/iBUz7f-bvr610MR_QyAAkGKwbLI=/fit-in/150x150/filters:strip_icc():format(jpeg):mode_rgb():quality(40)/discogs-images/R-488973-1346069023-3559.jpeg.jpg\", \"format\": [\"Vinyl\", \"LP\", \"Album\", \"Stereo\"], \"country\": \"US\", \"barcode\": [], \"uri\": \"/Ornette-Coleman-The-Shape-Of-Jazz-To-Come/release/488973\", \"community\": {\"want\": 566, \"have\": 202}, \"label\": [\"Atlantic\"], \"catno\": \"SD 1317\", \"year\": \"1959\", \"genre\": [\"Jazz\"], \"title\": \"Ornette Coleman - The Shape Of Jazz To Come\", \"resource_url\": \"https://api.discogs.com/releases/488973\", \"type\": \"release\", \"id\": 488973}, {\"style\": [], \"thumb\": \"https://api-img.discogs.com/0N_Z9L7w07lXTrzSGIKlp-1oecg=/fit-in/150x150/filters:strip_icc():format(jpeg):mode_rgb():quality(40)/discogs-images/R-2576568-1291304114.jpeg.jpg\", \"format\": [\"Vinyl\", \"LP\", \"Album\"], \"country\": \"Italy\", \"barcode\": [], \"uri\": \"/Ornette-Coleman-The-Shape-Of-Jazz-To-Come/release/2576568\", \"community\": {\"want\": 117, \"have\": 4}, \"label\": [\"Atlantic\"], \"catno\": \"ATL-LP 09042\", \"year\": \"1967\", \"genre\": [\"Jazz\"], \"title\": \"Ornette Coleman - The Shape Of Jazz To Come\", \"resource_url\": \"https://api.discogs.com/releases/2576568\", \"type\": \"release\", \"id\": 2576568}, {\"style\": [\"Free Jazz\"], \"thumb\": \"https://api-img.discogs.com/q3-UZo285ibf50iJpEGwNxUFnpQ=/fit-in/150x150/filters:strip_icc():format(jpeg):mode_rgb():quality(40)/discogs-images/R-2343705-1283108409.jpeg.jpg\", \"format\": [\"Vinyl\", \"7\\\"\", \"EP\"], \"country\": \"US\", \"barcode\": [], \"uri\": \"/Ornette-Coleman-The-Shape-Of-Jazz-To-Come/master/473844\", \"community\": {\"want\": 46, \"have\": 17}, \"label\": [\"Atlantic\"], \"catno\": \"ATL.EP 80.016\", \"genre\": [\"Jazz\"], \"title\": \"Ornette Coleman - The Shape Of Jazz To Come\", \"resource_url\": \"https://api.discogs.com/masters/473844\", \"type\": \"master\", \"id\": 473844}, {\"style\": [\"Free Jazz\"], \"thumb\": \"https://api-img.discogs.com/-5F9SMgTc1UJNy25ZScq68l6kRg=/fit-in/150x150/filters:strip_icc():format(jpeg):mode_rgb():quality(40)/discogs-images/R-3957076-1364331299-1447.jpeg.jpg\", \"format\": [\"CD\", \"Album\", \"Reissue\"], \"country\": \"Japan\", \"barcode\": [\"30XD-1032 1\", \"none\", \"JASRAC\"], \"uri\": \"/Ornette-Coleman-The-Shape-Of-Jazz-To-Come/release/3957076\", \"community\": {\"want\": 47, \"have\": 9}, \"label\": [\"Atlantic\", \"Atlantic\", \"Warner-Pioneer Corporation\"], \"catno\": \"30XD-1032\", \"year\": \"1988\", \"genre\": [\"Jazz\"], \"title\": \"Ornette Coleman - The Shape Of Jazz To Come\", \"resource_url\": \"https://api.discogs.com/releases/3957076\", \"type\": \"release\", \"id\": 3957076}, {\"style\": [\"Free Jazz\"], \"thumb\": \"https://api-img.discogs.com/ZPbPD4I3ke4QvS8DQcnPQtMB8Fo=/fit-in/150x150/filters:strip_icc():format(jpeg):mode_rgb():quality(40)/discogs-images/R-4427710-1364587999-9103.jpeg.jpg\", \"format\": [\"Vinyl\", \"12\\\"\", \"45 RPM\", \"Album\", \"Reissue\", \"Remastered\", \"Stereo\"], \"country\": \"US\", \"barcode\": [\"7 11574 70721 8\", \"711574707218\"], \"uri\": \"/Ornette-Coleman-The-Shape-Of-Jazz-To-Come/release/4427710\", \"community\": {\"want\": 127, \"have\": 75}, \"label\": [\"ORG Music\", \"Atlantic\", \"Rhino Entertainment Company\", \"Pallas\"], \"catno\": \"ORGM-1081\", \"year\": \"2013\", \"genre\": [\"Jazz\"], \"title\": \"Ornette Coleman - The Shape Of Jazz To Come\", \"resource_url\": \"https://api.discogs.com/releases/4427710\", \"type\": \"release\", \"id\": 4427710}, {\"style\": [\"Free Jazz\"], \"thumb\": \"https://api-img.discogs.com/jYbaFyoEfw1E79JdodK3miT1vfA=/fit-in/150x150/filters:strip_icc():format(jpeg):mode_rgb():quality(40)/discogs-images/R-3897500-1348484747-5731.png.jpg\", \"format\": [\"Vinyl\", \"7\\\"\", \"EP\"], \"country\": \"Spain\", \"barcode\": [], \"uri\": \"/Ornette-Coleman-The-Shape-Of-Jazz-To-Come/release/3897500\", \"community\": {\"want\": 15, \"have\": 1}, \"label\": [\"Belter\"], \"catno\": \"50.340\", \"genre\": [\"Jazz\"], \"title\": \"Ornette Coleman - The Shape Of Jazz To Come\", \"resource_url\": \"https://api.discogs.com/releases/3897500\", \"type\": \"release\", \"id\": 3897500}, {\"style\": [\"Free Jazz\"], \"thumb\": \"https://api-img.discogs.com/TAI4OYxFjXUbSeaQwWt8UXHy2Ew=/fit-in/150x150/filters:strip_icc():format(jpeg):mode_rgb():quality(40)/discogs-images/R-3483563-1386687132-5895.jpeg.jpg\", \"format\": [\"Vinyl\", \"7\\\"\", \"EP\"], \"country\": \"Sweden\", \"barcode\": [\"NCB\"], \"uri\": \"/Ornette-Coleman-The-Shape-Of-Jazz-To-Come/release/3483563\", \"community\": {\"want\": 11, \"have\": 11}, \"label\": [\"Atlantic\", \"MJQ Music\", \"Metronome Records AB\", \"Atlantic Recording Corporation\"], \"catno\": \"ATL-EP 80.016\", \"genre\": [\"Jazz\"], \"title\": \"Ornette Coleman - The Shape Of Jazz To Come\", \"resource_url\": \"https://api.discogs.com/releases/3483563\", \"type\": \"release\", \"id\": 3483563}, {\"style\": [\"Free Jazz\"], \"thumb\": \"https://api-img.discogs.com/iBUz7f-bvr610MR_QyAAkGKwbLI=/fit-in/150x150/filters:strip_icc():format(jpeg):mode_rgb():quality(40)/discogs-images/R-488973-1346069023-3559.jpeg.jpg\", \"format\": [\"Vinyl\", \"LP\", \"Album\", \"Stereo\"], \"country\": \"US\", \"barcode\": [], \"uri\": \"/Ornette-Coleman-The-Shape-Of-Jazz-To-Come/master/47813\", \"community\": {\"want\": 5249, \"have\": 2733}, \"label\": [\"Atlantic\"], \"catno\": \"SD 1317\", \"year\": \"1959\", \"genre\": [\"Jazz\"], \"title\": \"Ornette Coleman - The Shape Of Jazz To Come\", \"resource_url\": \"https://api.discogs.com/masters/47813\", \"type\": \"master\", \"id\": 47813}, {\"style\": [\"Free Jazz\"], \"thumb\": \"https://api-img.discogs.com/GYpyG3kByIZpQics8rU6Qs_M0B0=/fit-in/150x150/filters:strip_icc():format(jpeg):mode_rgb():quality(40)/discogs-images/R-7831243-1449709113-9954.jpeg.jpg\", \"format\": [\"Vinyl\", \"LP\", \"Album\", \"Reissue\"], \"country\": \"US\", \"barcode\": [\"081227980443\"], \"uri\": \"/Ornette-Coleman-The-Shape-Of-Jazz-To-Come/release/7831243\", \"community\": {\"want\": 28, \"have\": 24}, \"label\": [\"Rhino Vinyl\", \"Atlantic\", \"Record Technology Incorporated\"], \"catno\": \"R1 1317\", \"year\": \"2015\", \"genre\": [\"Jazz\"], \"title\": \"Ornette Coleman - The Shape Of Jazz To Come\", \"resource_url\": \"https://api.discogs.com/releases/7831243\", \"type\": \"release\", \"id\": 7831243}, {\"style\": [\"Free Jazz\"], \"thumb\": \"https://api-img.discogs.com/euI50-r5CunzFb0wzuAXzqD5LR4=/fit-in/150x150/filters:strip_icc():format(jpeg):mode_rgb():quality(40)/discogs-images/R-5344815-1391077627-1509.jpeg.jpg\", \"format\": [\"Vinyl\", \"LP\", \"Album\", \"Limited Edition\", \"Reissue\", \"Stereo\"], \"country\": \"US\", \"barcode\": [\"9990405070337\"], \"uri\": \"/Ornette-Coleman-The-Shape-Of-Jazz-To-Come/release/5344815\", \"community\": {\"want\": 98, \"have\": 96}, \"label\": [\"Atlantic\", \"Atlantic Recording Corporation\", \"Scorpio Music, Inc.\", \"Rhino Records\"], \"catno\": \"SD-1317\", \"genre\": [\"Jazz\"], \"title\": \"Ornette Coleman - The Shape Of Jazz To Come\", \"resource_url\": \"https://api.discogs.com/releases/5344815\", \"type\": \"release\", \"id\": 5344815}, {\"style\": [\"Bop\", \"Avant-garde Jazz\"], \"thumb\": \"https://api-img.discogs.com/vPLchEEy4c746Nggc_8gtFoDvb0=/fit-in/150x150/filters:strip_icc():format(jpeg):mode_rgb():quality(40)/discogs-images/R-3319376-1343378797-4224.jpeg.jpg\", \"format\": [\"Vinyl\", \"LP\", \"Album\", \"Reissue\"], \"country\": \"Spain\", \"barcode\": [\"8436028696987\"], \"uri\": \"/Ornette-Coleman-The-Shape-Of-Jazz-To-Come/release/3319376\", \"community\": {\"want\": 111, \"have\": 115}, \"label\": [\"WaxTime\"], \"catno\": \"771665\", \"year\": \"2010\", \"genre\": [\"Jazz\"], \"title\": \"Ornette Coleman - The Shape Of Jazz To Come\", \"resource_url\": \"https://api.discogs.com/releases/3319376\", \"type\": \"release\", \"id\": 3319376}, {\"style\": [\"Free Jazz\"], \"thumb\": \"https://api-img.discogs.com/Im2PXh37b4YqMelegEsNL60i368=/fit-in/150x150/filters:strip_icc():format(jpeg):mode_rgb():quality(40)/discogs-images/R-2339540-1340111875-2180.jpeg.jpg\", \"format\": [\"Vinyl\", \"LP\", \"Album\", \"Mono\"], \"country\": \"UK\", \"barcode\": [], \"uri\": \"/Ornette-Coleman-The-Shape-Of-Jazz-To-Come/release/2339540\", \"community\": {\"want\": 133, \"have\": 25}, \"label\": [\"Atlantic\"], \"catno\": \"587022\", \"year\": \"1966\", \"genre\": [\"Jazz\"], \"title\": \"Ornette Coleman - The Shape Of Jazz To Come\", \"resource_url\": \"https://api.discogs.com/releases/2339540\", \"type\": \"release\", \"id\": 2339540}, {\"style\": [\"Free Jazz\"], \"thumb\": \"https://api-img.discogs.com/JGDedhNuIfI6jAhTbV9W-31nwfk=/fit-in/150x150/filters:strip_icc():format(jpeg):mode_rgb():quality(40)/discogs-images/R-3974872-1446131572-4158.jpeg.jpg\", \"format\": [\"Vinyl\", \"LP\", \"Album\", \"Reissue\"], \"country\": \"Europe\", \"barcode\": [\"5060143491283\"], \"uri\": \"/Ornette-Coleman-The-Shape-Of-Jazz-To-Come/release/3974872\", \"community\": {\"want\": 93, \"have\": 26}, \"label\": [\"Not Now Music\"], \"catno\": \"NOTLP128\", \"year\": \"2011\", \"genre\": [\"Jazz\"], \"title\": \"Ornette Coleman - The Shape Of Jazz To Come\", \"resource_url\": \"https://api.discogs.com/releases/3974872\", \"type\": \"release\", \"id\": 3974872}, {\"style\": [\"Free Jazz\"], \"thumb\": \"https://api-img.discogs.com/lIyq_VKI00paQKiIHuw3BnMw-tU=/fit-in/150x150/filters:strip_icc():format(jpeg):mode_rgb():quality(40)/discogs-images/R-6645625-1423763941-3597.jpeg.jpg\", \"format\": [\"Vinyl\", \"LP\", \"Album\", \"Mono\"], \"country\": \"US\", \"barcode\": [\"EX 11 611 AT\", \"EX 11612 AT\"], \"uri\": \"/Ornette-Coleman-The-Shape-Of-Jazz-To-Come/release/6645625\", \"community\": {\"want\": 97, \"have\": 3}, \"label\": [\"Atlantic\", \"Atlantic Recording Corporation\"], \"catno\": \"1317\", \"year\": \"1960\", \"genre\": [\"Jazz\"], \"title\": \"Ornette Coleman - The Shape Of Jazz To Come\", \"resource_url\": \"https://api.discogs.com/releases/6645625\", \"type\": \"release\", \"id\": 6645625}, {\"style\": [\"Free Jazz\", \"Post Bop\"], \"thumb\": \"https://api-img.discogs.com/u65nIrr3I7DDHXkOOYFSJpzGjsw=/fit-in/150x150/filters:strip_icc():format(jpeg):mode_rgb():quality(40)/discogs-images/R-385271-1428827632-1606.jpeg.jpg\", \"format\": [\"CD\", \"Album\", \"Reissue\"], \"country\": \"US\", \"barcode\": [\"0 7567-81339-2 3\", \"075678133923\", \"3 1317-2 SRC=3 M1S13\"], \"uri\": \"/Ornette-Coleman-The-Shape-Of-Jazz-To-Come/release/385271\", \"community\": {\"want\": 54, \"have\": 129}, \"label\": [\"Atlantic\", \"Atlantic Recording Corporation\", \"WEA Manufacturing Inc.\", \"Specialty Records Corporation\", \"Radio Recorders\", \"Atlantic Studios\"], \"catno\": \"1317-2\", \"year\": \"1990\", \"genre\": [\"Jazz\"], \"title\": \"Ornette Coleman - The Shape Of Jazz To Come\", \"resource_url\": \"https://api.discogs.com/releases/385271\", \"type\": \"release\", \"id\": 385271}, {\"style\": [\"Free Jazz\"], \"thumb\": \"https://api-img.discogs.com/rCIVSQbP4ILgtL50jeRhoUBGFZw=/fit-in/150x150/filters:strip_icc():format(jpeg):mode_rgb():quality(40)/discogs-images/R-8426602-1461392106-3822.jpeg.jpg\", \"format\": [\"Vinyl\", \"LP\", \"Album\", \"Reissue\", \"Stereo\"], \"country\": \"Europe\", \"barcode\": [\"02982\", \"BA 16099-01 A1\", \"BA 16099-01 B1\", \"8122798044\"], \"uri\": \"/Ornette-Coleman-The-Shape-Of-Jazz-To-Come/release/8426602\", \"community\": {\"want\": 6, \"have\": 2}, \"label\": [\"Rhino Vinyl\", \"Atlantic\"], \"catno\": \"RI-1317\", \"year\": \"2010\", \"genre\": [\"Jazz\"], \"title\": \"Ornette Coleman - The Shape Of Jazz To Come\", \"resource_url\": \"https://api.discogs.com/releases/8426602\", \"type\": \"release\", \"id\": 8426602}, {\"style\": [\"Free Jazz\"], \"thumb\": \"https://api-img.discogs.com/2ioOiIzUlfaCnVMVVCMnZ92g9Vk=/fit-in/150x150/filters:strip_icc():format(jpeg):mode_rgb():quality(40)/discogs-images/R-6885963-1428763511-2170.jpeg.jpg\", \"format\": [\"CD\", \"Album\", \"Reissue\"], \"country\": \"Japan\", \"barcode\": [\"4988029100849\"], \"uri\": \"/Ornette-Coleman-The-Shape-Of-Jazz-To-Come/release/6885963\", \"community\": {\"want\": 32, \"have\": 1}, \"label\": [\"Atlantic\", \"MMG Inc.\"], \"catno\": \"AMCY-1008\", \"year\": \"1990\", \"genre\": [\"Jazz\"], \"title\": \"Ornette Coleman - The Shape Of Jazz To Come\", \"resource_url\": \"https://api.discogs.com/releases/6885963\", \"type\": \"release\", \"id\": 6885963}, {\"style\": [\"Free Jazz\"], \"thumb\": \"https://api-img.discogs.com/9B-7eAMkX2u8XETEKrqcFZo1ysM=/fit-in/150x150/filters:strip_icc():format(jpeg):mode_rgb():quality(40)/discogs-images/R-3400248-1403082711-5253.jpeg.jpg\", \"format\": [\"Vinyl\", \"LP\", \"Album\", \"Mono\", \"Repress\"], \"country\": \"US\", \"barcode\": [\"11611\", \"11612\", \"11611 \\u2b20 1 AT \", \"11612 1 AT\", \"BMI\"], \"uri\": \"/Ornette-Coleman-The-Shape-Of-Jazz-To-Come/release/3400248\", \"community\": {\"want\": 137, \"have\": 30}, \"label\": [\"Atlantic\", \"MJQ Music\", \"Atlantic Recording Corporation\"], \"catno\": \"1317\", \"year\": \"1960\", \"genre\": [\"Jazz\"], \"title\": \"Ornette Coleman - The Shape Of Jazz To Come\", \"resource_url\": \"https://api.discogs.com/releases/3400248\", \"type\": \"release\", \"id\": 3400248}, {\"style\": [\"Free Jazz\"], \"thumb\": \"https://api-img.discogs.com/GHKsS3QWENKz63B6YNhgpS_yjpQ=/fit-in/150x150/filters:strip_icc():format(jpeg):mode_rgb():quality(40)/discogs-images/R-2339592-1278071641.jpeg.jpg\", \"format\": [\"Vinyl\", \"LP\", \"Album\", \"Stereo\", \"Reissue\"], \"country\": \"US\", \"barcode\": [\"ST-A-59175 II\", \"ST-A-59176 II\", \"(ST-A-59175 SP)\", \"(ST-A-59176 SP)\"], \"uri\": \"/Ornette-Coleman-The-Shape-Of-Jazz-To-Come/release/2339592\", \"community\": {\"want\": 133, \"have\": 137}, \"label\": [\"Atlantic\", \"Atlantic Recording Corporation\", \"Warner Communications Company\"], \"catno\": \"SD 1317\", \"genre\": [\"Jazz\"], \"title\": \"Ornette Coleman - The Shape Of Jazz To Come\", \"resource_url\": \"https://api.discogs.com/releases/2339592\", \"type\": \"release\", \"id\": 2339592}, {\"style\": [\"Free Jazz\"], \"thumb\": \"https://api-img.discogs.com/7-DPzGC_aKhn8r8NN6dapJMSOag=/fit-in/150x150/filters:strip_icc():format(jpeg):mode_rgb():quality(40)/discogs-images/R-3157909-1322878422.jpeg.jpg\", \"format\": [\"CD\", \"Compilation\"], \"country\": \"Europe\", \"barcode\": [\"5060143493485\"], \"uri\": \"/Ornette-Coleman-The-Shape-Of-Jazz-To-Come/release/3157909\", \"community\": {\"want\": 39, \"have\": 30}, \"label\": [\"Not Now Music\"], \"catno\": \"NOT2CD348\", \"year\": \"2010\", \"genre\": [\"Jazz\"], \"title\": \"Ornette Coleman - The Shape Of Jazz To Come\", \"resource_url\": \"https://api.discogs.com/releases/3157909\", \"type\": \"release\", \"id\": 3157909}, {\"style\": [\"Free Jazz\"], \"thumb\": \"https://api-img.discogs.com/OJqIg3CZ8V69Q3AeaTK6Q_p2Aas=/fit-in/150x150/filters:strip_icc():format(jpeg):mode_rgb():quality(40)/discogs-images/R-5802456-1403080861-1373.jpeg.jpg\", \"format\": [\"Vinyl\", \"LP\", \"Album\", \"Stereo\"], \"country\": \"US\", \"barcode\": [\"AVCO ST-A-59176\", \"AVCO ST-A-59175\", \"(ST-A-59176)\", \"(ST-A-59175)\", \"BMI\"], \"uri\": \"/Ornette-Coleman-The-Shape-Of-Jazz-To-Come/release/5802456\", \"community\": {\"want\": 137, \"have\": 17}, \"label\": [\"Atlantic\", \"Atlantic\", \"MJQ Music\", \"Atlantic Recording Corporation\"], \"catno\": \"SD 1317\", \"year\": \"1960\", \"genre\": [\"Jazz\"], \"title\": \"Ornette Coleman - The Shape Of Jazz To Come\", \"resource_url\": \"https://api.discogs.com/releases/5802456\", \"type\": \"release\", \"id\": 5802456}, {\"style\": [], \"thumb\": \"\", \"format\": [\"Vinyl\", \"LP\", \"Album\", \"Mono\"], \"country\": \"Denmark\", \"barcode\": [], \"uri\": \"/Ornette-Coleman-The-Shape-Of-Jazz-To-Come/release/7256884\", \"community\": {\"want\": 53, \"have\": 4}, \"label\": [\"Atlantic\"], \"catno\": \"1317\", \"year\": \"1959\", \"genre\": [\"Jazz\"], \"title\": \"Ornette Coleman - The Shape Of Jazz To Come\", \"resource_url\": \"https://api.discogs.com/releases/7256884\", \"type\": \"release\", \"id\": 7256884}, {\"style\": [\"Free Jazz\", \"Post Bop\"], \"thumb\": \"https://api-img.discogs.com/HOHomayEYCWVtFivrIWHW7Fcvxc=/fit-in/150x150/filters:strip_icc():format(jpeg):mode_rgb():quality(40)/discogs-images/R-2202962-1301881062.jpeg.jpg\", \"format\": [\"CD\", \"Album\", \"Reissue\"], \"country\": \"US\", \"barcode\": [\"0 7567-81339-2 3\", \"wea mfg. OLYPHANT X17725 3 1317-2 RE-1 03 M1S1\", \"ifpi L902\", \"IFPI 20F4\", \"wea mfg. OLYPHANT X17725 3 1317-2 RE-1 03 M1S2 CI\", \"ifpi L902\", \"IFPI 2U7N\", \"BMI\"], \"uri\": \"/Ornette-Coleman-The-Shape-Of-Jazz-To-Come/release/2202962\", \"community\": {\"want\": 57, \"have\": 82}, \"label\": [\"Atlantic\", \"Atlantic Recording Corporation\", \"WEA Manufacturing Inc.\", \"Radio Recorders\", \"Atlantic Studios\", \"WEA Mfg. Olyphant\", \"Cinram, Olyphant, PA\"], \"catno\": \"1317-2\", \"genre\": [\"Jazz\"], \"title\": \"Ornette Coleman - The Shape Of Jazz To Come\", \"resource_url\": \"https://api.discogs.com/releases/2202962\", \"type\": \"release\", \"id\": 2202962}, {\"style\": [\"Free Jazz\"], \"thumb\": \"https://api-img.discogs.com/tDzuc2x6IvdvWQkWv3ufwSer9PI=/fit-in/150x150/filters:strip_icc():format(jpeg):mode_rgb():quality(40)/discogs-images/R-4429970-1364661452-3364.jpeg.jpg\", \"format\": [\"Vinyl\", \"LP\", \"Album\", \"Reissue\", \"Stereo\"], \"country\": \"US\", \"barcode\": [\"ST-A-59175 PR | ST-A-59176 PR\", \"ST-A-59175-C | ST-A-59176-C\"], \"uri\": \"/Ornette-Coleman-The-Shape-Of-Jazz-To-Come/release/4429970\", \"community\": {\"want\": 125, \"have\": 62}, \"label\": [\"Atlantic\", \"Atlantic Recording Corporation\", \"Atlantic Recording Corporation\"], \"catno\": \"SD 1317\", \"year\": \"1972\", \"genre\": [\"Jazz\"], \"title\": \"Ornette Coleman - The Shape Of Jazz To Come\", \"resource_url\": \"https://api.discogs.com/releases/4429970\", \"type\": \"release\", \"id\": 4429970}, {\"style\": [\"Free Jazz\"], \"thumb\": \"https://api-img.discogs.com/5aC_7xrEA-7_Iaf1sVYOj5Q-BkQ=/fit-in/150x150/filters:strip_icc():format(jpeg):mode_rgb():quality(40)/discogs-images/R-2943706-1308446836.jpeg.jpg\", \"format\": [\"Vinyl\", \"LP\", \"Album\", \"Reissue\", \"Stereo\"], \"country\": \"France\", \"barcode\": [], \"uri\": \"/Ornette-Coleman-The-Shape-Of-Jazz-To-Come/release/2943706\", \"community\": {\"want\": 113, \"have\": 5}, \"label\": [\"Atlantic\"], \"catno\": \"40 441\", \"year\": \"1972\", \"genre\": [\"Jazz\"], \"title\": \"Ornette Coleman - The Shape Of Jazz To Come\", \"resource_url\": \"https://api.discogs.com/releases/2943706\", \"type\": \"release\", \"id\": 2943706}, {\"style\": [], \"thumb\": \"https://api-img.discogs.com/Kvw4F9-LyEloBb9tWcTQgwviF6s=/fit-in/150x150/filters:strip_icc():format(jpeg):mode_rgb():quality(40)/discogs-images/R-5245649-1460642424-5865.jpeg.jpg\", \"format\": [\"SACD\", \"Album\", \"Reissue\"], \"country\": \"Japan\", \"barcode\": [\"4943674103386\", \"JASRAC\"], \"uri\": \"/Ornette-Coleman-The-Shape-Of-Jazz-To-Come/release/5245649\", \"community\": {\"want\": 46, \"have\": 3}, \"label\": [\"Atlantic\"], \"catno\": \"WPGR-10005\", \"year\": \"2011\", \"genre\": [\"Jazz\"], \"title\": \"Ornette Coleman - The Shape Of Jazz To Come\", \"resource_url\": \"https://api.discogs.com/releases/5245649\", \"type\": \"release\", \"id\": 5245649}, {\"style\": [\"Free Jazz\"], \"thumb\": \"https://api-img.discogs.com/zoiRev1wH0GzW-qByFWiT_VEXWw=/fit-in/150x150/filters:strip_icc():format(jpeg):mode_rgb():quality(40)/discogs-images/R-1151114-1260019899.jpeg.jpg\", \"format\": [\"Vinyl\", \"LP\", \"Album\", \"Stereo\", \"Reissue\"], \"country\": \"US\", \"barcode\": [\"ST-A-59175 PR\", \"ST-A-59176 PR\", \"ST-A-59175H HT/9P\", \"ST-A-59176H HT/9P\", \"BMI\"], \"uri\": \"/Ornette-Coleman-The-Shape-Of-Jazz-To-Come/release/1151114\", \"community\": {\"want\": 185, \"have\": 187}, \"label\": [\"Atlantic\", \"Atlantic\", \"Atlantic Recording Corporation\"], \"catno\": \"1317\", \"year\": \"1972\", \"genre\": [\"Jazz\"], \"title\": \"Ornette Coleman - The Shape Of Jazz To Come\", \"resource_url\": \"https://api.discogs.com/releases/1151114\", \"type\": \"release\", \"id\": 1151114}, {\"style\": [\"Free Jazz\"], \"thumb\": \"https://api-img.discogs.com/n-dOWsjiJCHrrjpkCErNskejTYs=/fit-in/150x150/filters:strip_icc():format(jpeg):mode_rgb():quality(40)/discogs-images/R-944355-1188784124.jpeg.jpg\", \"format\": [\"CD\", \"Album\", \"Reissue\"], \"country\": \"Europe\", \"barcode\": [\"0 81227 23982 4\"], \"uri\": \"/Ornette-Coleman-The-Shape-Of-Jazz-To-Come/release/944355\", \"community\": {\"want\": 52, \"have\": 137}, \"label\": [\"Atlantic\", \"Atlantic Original Sound\", \"Atlantic Recording Corporation\", \"WEA\", \"Mtx Mastering Studio\"], \"catno\": \"8122-72398-2\", \"year\": \"1998\", \"genre\": [\"Jazz\"], \"title\": \"Ornette Coleman - The Shape Of Jazz To Come\", \"resource_url\": \"https://api.discogs.com/releases/944355\", \"type\": \"release\", \"id\": 944355}, {\"style\": [\"Free Jazz\"], \"thumb\": \"https://api-img.discogs.com/ezKnzMNhm-KT3g5Azuc-924bTDE=/fit-in/150x150/filters:strip_icc():format(jpeg):mode_rgb():quality(40)/discogs-images/R-5699381-1402763340-2786.jpeg.jpg\", \"format\": [\"Vinyl\", \"LP\", \"Album\", \"Stereo\"], \"country\": \"Japan\", \"barcode\": [\"ATL-1317-A\", \"ATL-1317-B\", \"BMI\"], \"uri\": \"/Ornette-Coleman-The-Shape-Of-Jazz-To-Come/release/5699381\", \"community\": {\"want\": 77, \"have\": 4}, \"label\": [\"Atlantic\", \"Atlantic\", \"Victor Record Company Ltd.\", \"Cosdel Inc.\", \"MJQ Music\"], \"catno\": \"ATL-5038\", \"genre\": [\"Jazz\"], \"title\": \"Ornette Coleman - The Shape Of Jazz To Come\", \"resource_url\": \"https://api.discogs.com/releases/5699381\", \"type\": \"release\", \"id\": 5699381}, {\"style\": [\"Free Jazz\"], \"thumb\": \"https://api-img.discogs.com/2WolPOUsiinN_FzdWtnJF30EG0c=/fit-in/150x150/filters:strip_icc():format(jpeg):mode_rgb():quality(40)/discogs-images/R-4063884-1368816596-2634.jpeg.jpg\", \"format\": [\"Vinyl\", \"LP\", \"Album\", \"Reissue\"], \"country\": \"US\", \"barcode\": [], \"uri\": \"/Ornette-Coleman-The-Shape-Of-Jazz-To-Come/release/4063884\", \"community\": {\"want\": 104, \"have\": 64}, \"label\": [\"Atlantic\", \"Rhino Records\"], \"catno\": \"SD 1317\", \"genre\": [\"Jazz\"], \"title\": \"Ornette Coleman - The Shape Of Jazz To Come\", \"resource_url\": \"https://api.discogs.com/releases/4063884\", \"type\": \"release\", \"id\": 4063884}, {\"style\": [\"Post Bop\", \"Avant-garde Jazz\", \"Free Jazz\"], \"thumb\": \"https://api-img.discogs.com/o5GMY5B61vAEZb1i-3XAe3Z6izg=/fit-in/150x150/filters:strip_icc():format(jpeg):mode_rgb():quality(40)/discogs-images/R-6924522-1429974747-8086.jpeg.jpg\", \"format\": [\"Vinyl\", \"LP\", \"Album\", \"Reissue\", \"Stereo\"], \"country\": \"US\", \"barcode\": [\"ST-A-59175 PR\", \"ST-A-59176 PR\", \"ST-A-59175H HT/9P PR-P\", \"ST-A-59176H HT/9P (PR)P\", \"BMI\"], \"uri\": \"/Ornette-Coleman-The-Shape-Of-Jazz-To-Come/release/6924522\", \"community\": {\"want\": 63, \"have\": 15}, \"label\": [\"Atlantic\", \"Atlantic\", \"Warner Communications\", \"Atlantic Recording Corporation\", \"MJQ Music\"], \"catno\": \"1317\", \"genre\": [\"Jazz\"], \"title\": \"Ornette Coleman - The Shape Of Jazz To Come\", \"resource_url\": \"https://api.discogs.com/releases/6924522\", \"type\": \"release\", \"id\": 6924522}]}"; 12 | private const string _SearchArtistAnswer = "{\"pagination\": {\"per_page\": 50, \"pages\": 1, \"page\": 1, \"urls\": {}, \"items\": 39}, \"results\": [{\"thumb\": \"https://api-img.discogs.com/v4F_stUvfwJQ4fjo1quKMRRGu8c=/150x150/smart/filters:strip_icc():format(jpeg):mode_rgb():quality(40)/discogs-images/A-224506-1106059827.jpg.jpg\", \"title\": \"Ornette Coleman\", \"uri\": \"/artist/224506-Ornette-Coleman\", \"resource_url\": \"https://api.discogs.com/ReleaseArtists/224506\", \"type\": \"artist\", \"id\": 224506}, {\"thumb\": \"https://api-img.discogs.com/e5ZuwqiEOqCn3jEAi0t4_IFmjj0=/150x150/smart/filters:strip_icc():format(jpeg):mode_rgb():quality(40)/discogs-images/A-317878-1406808935-3970.jpeg.jpg\", \"title\": \"The Ornette Coleman Quartet\", \"uri\": \"/artist/317878-The-Ornette-Coleman-Quartet\", \"resource_url\": \"https://api.discogs.com/ReleaseArtists/317878\", \"type\": \"artist\", \"id\": 317878}, {\"thumb\": \"https://api-img.discogs.com/cEzGKT2KbEkiJN1qluJAl7Vtqvs=/150x150/smart/filters:strip_icc():format(jpeg):mode_rgb():quality(40)/discogs-images/A-627558-1377442662-3125.png.jpg\", \"title\": \"The Ornette Coleman Trio\", \"uri\": \"/artist/627558-The-Ornette-Coleman-Trio\", \"resource_url\": \"https://api.discogs.com/ReleaseArtists/627558\", \"type\": \"artist\", \"id\": 627558}, {\"thumb\": \"\", \"title\": \"The Ornette Coleman Double Quartet\", \"uri\": \"/artist/317886-The-Ornette-Coleman-Double-Quartet\", \"resource_url\": \"https://api.discogs.com/ReleaseArtists/317886\", \"type\": \"artist\", \"id\": 317886}, {\"thumb\": \"https://api-img.discogs.com/x5MKqH3BpSrP500ViDu-LI-WXtM=/150x150/smart/filters:strip_icc():format(jpeg):mode_rgb():quality(40)/discogs-images/A-366729-1406809086-5491.jpeg.jpg\", \"title\": \"Denardo Coleman\", \"uri\": \"/artist/366729-Denardo-Coleman\", \"resource_url\": \"https://api.discogs.com/ReleaseArtists/366729\", \"type\": \"artist\", \"id\": 366729}, {\"thumb\": \"https://api-img.discogs.com/EQNxC2UxQSOtK1ESqsDq-mNqoxE=/150x150/smart/filters:strip_icc():format(jpeg):mode_rgb():quality(40)/discogs-images/A-2082992-1452950806-4407.jpeg.jpg\", \"title\": \"Ornette\", \"uri\": \"/artist/2082992-Ornette\", \"resource_url\": \"https://api.discogs.com/ReleaseArtists/2082992\", \"type\": \"artist\", \"id\": 2082992}, {\"thumb\": \"\", \"title\": \"Ornette Coleman 11 Piece Studio Orchestra\", \"uri\": \"/artist/1868061-Ornette-Coleman-11-Piece-Studio-Orchestra\", \"resource_url\": \"https://api.discogs.com/ReleaseArtists/1868061\", \"type\": \"artist\", \"id\": 1868061}, {\"thumb\": \"\", \"title\": \"Ornette Coleman Quintet\", \"uri\": \"/artist/1608840-Ornette-Coleman-Quintet\", \"resource_url\": \"https://api.discogs.com/ReleaseArtists/1608840\", \"type\": \"artist\", \"id\": 1608840}, {\"thumb\": \"\", \"title\": \"The Ornette Coleman Group\", \"uri\": \"/artist/4380001-The-Ornette-Coleman-Group\", \"resource_url\": \"https://api.discogs.com/ReleaseArtists/4380001\", \"type\": \"artist\", \"id\": 4380001}, {\"thumb\": \"https://api-img.discogs.com/AJPpERvptYA3Zc9STeDsai1QK3E=/150x150/smart/filters:strip_icc():format(jpeg):mode_rgb():quality(40)/discogs-images/A-42757-1400952736-7468.jpeg.jpg\", \"title\": \"Don Cherry\", \"uri\": \"/artist/42757-Don-Cherry\", \"resource_url\": \"https://api.discogs.com/ReleaseArtists/42757\", \"type\": \"artist\", \"id\": 42757}, {\"thumb\": \"\", \"title\": \"Ornette Coleman Ensemble\", \"uri\": \"/artist/2190163-Ornette-Coleman-Ensemble\", \"resource_url\": \"https://api.discogs.com/ReleaseArtists/2190163\", \"type\": \"artist\", \"id\": 2190163}, {\"thumb\": \"https://api-img.discogs.com/sFYK60_ry9CHGfC8-HM15NsJSbQ=/150x150/smart/filters:strip_icc():format(jpeg):mode_rgb():quality(40)/discogs-images/A-252924-1160871597.jpeg.jpg\", \"title\": \"Greg Ginn\", \"uri\": \"/artist/252924-Greg-Ginn\", \"resource_url\": \"https://api.discogs.com/ReleaseArtists/252924\", \"type\": \"artist\", \"id\": 252924}, {\"thumb\": \"https://api-img.discogs.com/gFUOuJAB3DtYLMe0FMgtm72_OQA=/150x150/smart/filters:strip_icc():format(jpeg):mode_rgb():quality(40)/discogs-images/A-272982-1347392616-4955.jpeg.jpg\", \"title\": \"Scott LaFaro\", \"uri\": \"/artist/272982-Scott-LaFaro\", \"resource_url\": \"https://api.discogs.com/ReleaseArtists/272982\", \"type\": \"artist\", \"id\": 272982}, {\"thumb\": \"https://api-img.discogs.com/YsPwjb7RWZ4OO8DIRUhfWlQY0J4=/150x150/smart/filters:strip_icc():format(jpeg):mode_rgb():quality(40)/discogs-images/A-171780-1209267454.jpeg.jpg\", \"title\": \"Jamaaladeen Tacuma\", \"uri\": \"/artist/171780-Jamaaladeen-Tacuma\", \"resource_url\": \"https://api.discogs.com/ReleaseArtists/171780\", \"type\": \"artist\", \"id\": 171780}, {\"thumb\": \"https://api-img.discogs.com/uaV1VaGn6BjpjzUmgCxZw1IBHaE=/150x150/smart/filters:strip_icc():format(jpeg):mode_rgb():quality(40)/discogs-images/A-149965-1460531669-2768.jpeg.jpg\", \"title\": \"James Blood Ulmer\", \"uri\": \"/artist/149965-James-Blood-Ulmer\", \"resource_url\": \"https://api.discogs.com/ReleaseArtists/149965\", \"type\": \"artist\", \"id\": 149965}, {\"thumb\": \"https://api-img.discogs.com/upBhMmJlrMtdssD0Wxhp7xc_DA0=/150x150/smart/filters:strip_icc():format(jpeg):mode_rgb():quality(40)/discogs-images/A-231518-1125322370.jpg.jpg\", \"title\": \"Chris Walker\", \"uri\": \"/artist/231518-Chris-Walker\", \"resource_url\": \"https://api.discogs.com/ReleaseArtists/231518\", \"type\": \"artist\", \"id\": 231518}, {\"thumb\": \"\", \"title\": \"John Litweiler\", \"uri\": \"/artist/1649825-John-Litweiler\", \"resource_url\": \"https://api.discogs.com/ReleaseArtists/1649825\", \"type\": \"artist\", \"id\": 1649825}, {\"thumb\": \"https://api-img.discogs.com/yu05QPrf5POBJi43bkThP30JHFg=/150x150/smart/filters:strip_icc():format(jpeg):mode_rgb():quality(40)/discogs-images/A-2026738-1318118642.jpeg.jpg\", \"title\": \"LaMont Johnson (2)\", \"uri\": \"/artist/2026738-LaMont-Johnson-2\", \"resource_url\": \"https://api.discogs.com/ReleaseArtists/2026738\", \"type\": \"artist\", \"id\": 2026738}, {\"thumb\": \"\", \"title\": \"Martin Williams (6)\", \"uri\": \"/artist/1632896-Martin-Williams-6\", \"resource_url\": \"https://api.discogs.com/ReleaseArtists/1632896\", \"type\": \"artist\", \"id\": 1632896}, {\"thumb\": \"https://api-img.discogs.com/0JWTDPPB16mFwPy_PItLqkfXxnU=/150x150/smart/filters:strip_icc():format(jpeg):mode_rgb():quality(40)/discogs-images/A-695870-1269302365.jpeg.jpg\", \"title\": \"The Drones (2)\", \"uri\": \"/artist/695870-The-Drones-2\", \"resource_url\": \"https://api.discogs.com/ReleaseArtists/695870\", \"type\": \"artist\", \"id\": 695870}, {\"thumb\": \"https://api-img.discogs.com/5T79OdKjI98sZiiMPXLLF2p_oEo=/150x150/smart/filters:strip_icc():format(jpeg):mode_rgb():quality(40)/discogs-images/A-320328-1343748627-4095.jpeg.jpg\", \"title\": \"Bern Nix\", \"uri\": \"/artist/320328-Bern-Nix\", \"resource_url\": \"https://api.discogs.com/ReleaseArtists/320328\", \"type\": \"artist\", \"id\": 320328}, {\"thumb\": \"https://api-img.discogs.com/-ZI10sMGLNDZG8xcVoA5D8BDVmI=/150x150/smart/filters:strip_icc():format(jpeg):mode_rgb():quality(40)/discogs-images/A-757403-1334147879.jpeg.jpg\", \"title\": \"Jayne Cortez\", \"uri\": \"/artist/757403-Jayne-Cortez\", \"resource_url\": \"https://api.discogs.com/ReleaseArtists/757403\", \"type\": \"artist\", \"id\": 757403}, {\"thumb\": \"https://api-img.discogs.com/J7eLp5Rts5ojkkIKh7fvxKRpntQ=/150x150/smart/filters:strip_icc():format(jpeg):mode_rgb():quality(40)/discogs-images/A-189505-1250819226.jpeg.jpg\", \"title\": \"No Self Control And The Band\", \"uri\": \"/artist/189505-No-Self-Control-And-The-Band\", \"resource_url\": \"https://api.discogs.com/ReleaseArtists/189505\", \"type\": \"artist\", \"id\": 189505}, {\"thumb\": \"https://api-img.discogs.com/ecSutd1M3Knzt2Uq910LIRmdb18=/150x150/smart/filters:strip_icc():format(jpeg):mode_rgb():quality(40)/discogs-images/A-621049-1445978771-2068.jpeg.jpg\", \"title\": \"Steve Shapiro\", \"uri\": \"/artist/621049-Steve-Shapiro\", \"resource_url\": \"https://api.discogs.com/ReleaseArtists/621049\", \"type\": \"artist\", \"id\": 621049}, {\"thumb\": \"https://api-img.discogs.com/RAxO5xNClgLNQEuxYJbTmJNB6ro=/150x150/smart/filters:strip_icc():format(jpeg):mode_rgb():quality(40)/discogs-images/A-98150-001.jpg.jpg\", \"title\": \"Ralf Wehowsky\", \"uri\": \"/artist/98150-Ralf-Wehowsky\", \"resource_url\": \"https://api.discogs.com/ReleaseArtists/98150\", \"type\": \"artist\", \"id\": 98150}, {\"thumb\": \"https://api-img.discogs.com/g1Zi-y3qEY_4aT3qi79T3lQtCA8=/150x150/smart/filters:strip_icc():format(jpeg):mode_rgb():quality(40)/discogs-images/A-1123304-1210870594.jpeg.jpg\", \"title\": \"David Henderson (5)\", \"uri\": \"/artist/1123304-David-Henderson-5\", \"resource_url\": \"https://api.discogs.com/ReleaseArtists/1123304\", \"type\": \"artist\", \"id\": 1123304}, {\"thumb\": \"https://api-img.discogs.com/AB883m00QjAk_knxGEsGLgUN7So=/150x150/smart/filters:strip_icc():format(jpeg):mode_rgb():quality(40)/discogs-images/A-32889-1264396267.jpeg.jpg\", \"title\": \"Martin Ng\", \"uri\": \"/artist/32889-Martin-Ng\", \"resource_url\": \"https://api.discogs.com/ReleaseArtists/32889\", \"type\": \"artist\", \"id\": 32889}, {\"thumb\": \"https://api-img.discogs.com/UtlOlj_bnZcOwYm3NrOgEUob-m0=/150x150/smart/filters:strip_icc():format(jpeg):mode_rgb():quality(40)/discogs-images/A-336476-1432113428-3020.jpeg.jpg\", \"title\": \"Vito Ricci\", \"uri\": \"/artist/336476-Vito-Ricci\", \"resource_url\": \"https://api.discogs.com/ReleaseArtists/336476\", \"type\": \"artist\", \"id\": 336476}, {\"thumb\": \"https://api-img.discogs.com/mw6_ecri5-YBv0NxozUisPnJFk8=/150x150/smart/filters:strip_icc():format(jpeg):mode_rgb():quality(40)/discogs-images/A-761942-1208509500.jpeg.jpg\", \"title\": \"John Marshall (7)\", \"uri\": \"/artist/761942-John-Marshall-7\", \"resource_url\": \"https://api.discogs.com/ReleaseArtists/761942\", \"type\": \"artist\", \"id\": 761942}, {\"thumb\": \"\", \"title\": \"Gail Powers\", \"uri\": \"/artist/100316-Gail-Powers\", \"resource_url\": \"https://api.discogs.com/ReleaseArtists/100316\", \"type\": \"artist\", \"id\": 100316}, {\"thumb\": \"https://api-img.discogs.com/vdumGyIprt-eI9jS9tROHRyyMLU=/150x150/smart/filters:strip_icc():format(jpeg):mode_rgb():quality(40)/discogs-images/A-3378680-1461481660-2409.png.jpg\", \"title\": \"Clay Wilson (2)\", \"uri\": \"/artist/3378680-Clay-Wilson-2\", \"resource_url\": \"https://api.discogs.com/ReleaseArtists/3378680\", \"type\": \"artist\", \"id\": 3378680}, {\"thumb\": \"https://api-img.discogs.com/53MrmGkdZMb64WcPpR3wiDcYvX8=/150x150/smart/filters:strip_icc():format(jpeg):mode_rgb():quality(40)/discogs-images/A-70515-1171273556.jpeg.jpg\", \"title\": \"School Days\", \"uri\": \"/artist/70515-School-Days\", \"resource_url\": \"https://api.discogs.com/ReleaseArtists/70515\", \"type\": \"artist\", \"id\": 70515}, {\"thumb\": \"https://api-img.discogs.com/OdF2-7H6Xsz8TrAjs4grMu_CJL0=/150x150/smart/filters:strip_icc():format(jpeg):mode_rgb():quality(40)/discogs-images/A-1737889-1365813990-5283.jpeg.jpg\", \"title\": \"Ted Sirota's Rebel Souls\", \"uri\": \"/artist/1737889-Ted-Sirotas-Rebel-Souls\", \"resource_url\": \"https://api.discogs.com/ReleaseArtists/1737889\", \"type\": \"artist\", \"id\": 1737889}, {\"thumb\": \"https://api-img.discogs.com/ouY-htBXLZSFt3YAPn8D3f7bMpk=/150x150/smart/filters:strip_icc():format(jpeg):mode_rgb():quality(40)/discogs-images/A-2294110-1381011004-8007.jpeg.jpg\", \"title\": \"Johnny Case\", \"uri\": \"/artist/2294110-Johnny-Case\", \"resource_url\": \"https://api.discogs.com/ReleaseArtists/2294110\", \"type\": \"artist\", \"id\": 2294110}, {\"thumb\": \"https://api-img.discogs.com/3jLBJBwCb8-FfMCbUlF3Zyv18Ag=/150x150/smart/filters:strip_icc():format(jpeg):mode_rgb():quality(40)/discogs-images/A-1260042-1272147995.jpeg.jpg\", \"title\": \"Toups Bebey\", \"uri\": \"/artist/1260042-Toups-Bebey\", \"resource_url\": \"https://api.discogs.com/ReleaseArtists/1260042\", \"type\": \"artist\", \"id\": 1260042}, {\"thumb\": \"https://api-img.discogs.com/t8a_UJ_fOpkVN_shIp9QqCiSjpc=/150x150/smart/filters:strip_icc():format(jpeg):mode_rgb():quality(40)/discogs-images/A-4305403-1426536841-1162.jpeg.jpg\", \"title\": \"Coax Orchestra\", \"uri\": \"/artist/4305403-Coax-Orchestra\", \"resource_url\": \"https://api.discogs.com/ReleaseArtists/4305403\", \"type\": \"artist\", \"id\": 4305403}, {\"thumb\": \"https://api-img.discogs.com/BL-Dd-fQMQuYHj5gHA2tc0X6zmc=/150x150/smart/filters:strip_icc():format(jpeg):mode_rgb():quality(40)/discogs-images/A-3841414-1400919217-5846.jpeg.jpg\", \"title\": \"Pavees Dance\", \"uri\": \"/artist/3841414-Pavees-Dance\", \"resource_url\": \"https://api.discogs.com/ReleaseArtists/3841414\", \"type\": \"artist\", \"id\": 3841414}, {\"thumb\": \"\", \"title\": \"Chris Lee (27)\", \"uri\": \"/artist/3796976-Chris-Lee-27\", \"resource_url\": \"https://api.discogs.com/ReleaseArtists/3796976\", \"type\": \"artist\", \"id\": 3796976}, {\"thumb\": \"https://api-img.discogs.com/97yjNyfuwaUQGie0gTYEbl-klbI=/150x150/smart/filters:strip_icc():format(jpeg):mode_rgb():quality(40)/discogs-images/A-4533471-1438343828-6533.jpeg.jpg\", \"title\": \"Doug Yokoyama\", \"uri\": \"/artist/4533471-Doug-Yokoyama\", \"resource_url\": \"https://api.discogs.com/ReleaseArtists/4533471\", \"type\": \"artist\", \"id\": 4533471}]}"; 13 | 14 | private readonly DiscogsSearchResults _Result; 15 | private readonly DiscogsSearchResults _ResultArtist; 16 | 17 | public ResultDeserializationTest() 18 | { 19 | _Result = JsonConvert.DeserializeObject(_SearchAnswer); 20 | _ResultArtist = JsonConvert.DeserializeObject(_SearchArtistAnswer); 21 | } 22 | 23 | [Fact] 24 | public void DeserializeSearch_IsNotNull() 25 | { 26 | _Result.Should().NotBeNull(); 27 | } 28 | 29 | [Fact] 30 | public void DeserializeSearchPagination_IsNotNull() 31 | { 32 | _Result.pagination.Should().NotBeNull(); 33 | } 34 | 35 | [Fact] 36 | public void DeserializeSearchPaginationUrls_IsNotNull() 37 | { 38 | _Result.pagination.urls.Should().NotBeNull(); 39 | } 40 | 41 | [Fact] 42 | public void DeserializeSearchResult_HasRightCount() 43 | { 44 | _Result.results.Should().HaveCount(50); 45 | } 46 | 47 | [Fact] 48 | public void DeserializeSearchResultDiscogsType_IsCorrect_artist() 49 | { 50 | _ResultArtist.results[0].type.Should().Be(DiscogsEntityType.artist); 51 | } 52 | 53 | [Fact] 54 | public void DeserializeSearchResultDiscogsType_IsCorrect_release() 55 | { 56 | _Result.results[0].type.Should().Be(DiscogsEntityType.release); 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /DiscogsClient.Test/ReleaseDeserializationTest.cs: -------------------------------------------------------------------------------- 1 | using DiscogsClient.Data.Result; 2 | using FluentAssertions; 3 | using Newtonsoft.Json; 4 | using System.Collections.Generic; 5 | using Xunit; 6 | using Xunit.Abstractions; 7 | 8 | namespace DiscogsClient.Test 9 | { 10 | public class ReleaseDeserializationTest 11 | { 12 | private const string _ReleaseJSON = "{ \"title\": \"Never Gonna Give You Up\", \"id\": 249504, \"ReleaseArtists\": [ { \"anv\": \"\", \"id\": 72872, \"join\": \"\", \"name\": \"Rick Astley\", \"resource_url\": \"https://api.discogs.com/ReleaseArtists/72872\", \"role\": \"\", \"tracks\": \"\" } ], \"data_quality\": \"Correct\", \"thumb\": \"https://api-img.discogs.com/kAXVhuZuh_uat5NNr50zMjN7lho=/fit-in/300x300/filters:strip_icc():format(jpeg):mode_rgb()/discogs-images/R-249504-1334592212.jpeg.jpg\", \"community\": { \"contributors\": [ { \"resource_url\": \"https://api.discogs.com/users/memory\", \"username\": \"memory\" }, { \"resource_url\": \"https://api.discogs.com/users/_80_\", \"username\": \"_80_\" } ], \"data_quality\": \"Correct\", \"have\": 252, \"rating\": { \"average\": 3.42, \"count\": 45 }, \"status\": \"Accepted\", \"submitter\": { \"resource_url\": \"https://api.discogs.com/users/memory\", \"username\": \"memory\" }, \"want\": 42 }, \"companies\": [ { \"catno\": \"\", \"entity_type\": \"13\", \"entity_type_name\": \"Phonographic Copyright (p)\", \"id\": 82835, \"name\": \"BMG Records (UK) Ltd.\", \"resource_url\": \"https://api.discogs.com/labels/82835\" }, { \"catno\": \"\", \"entity_type\": \"29\", \"entity_type_name\": \"Mastered At\", \"id\": 266218, \"name\": \"Utopia Studios\", \"resource_url\": \"https://api.discogs.com/labels/266218\" } ], \"country\": \"UK\", \"date_added\": \"2004-04-30T08:10:05-07:00\", \"date_changed\": \"2012-12-03T02:50:12-07:00\", \"estimated_weight\": 60, \"extraartists\": [ { \"anv\": \"Me Co\", \"id\": 547352, \"join\": \"\", \"name\": \"Me Company\", \"resource_url\": \"https://api.discogs.com/ReleaseArtists/547352\", \"role\": \"Design\", \"tracks\": \"\" }, { \"anv\": \"Stock / Aitken / Waterman\", \"id\": 20942, \"join\": \"\", \"name\": \"Stock, Aitken & Waterman\", \"resource_url\": \"https://api.discogs.com/ReleaseArtists/20942\", \"role\": \"Producer, Written-By\", \"tracks\": \"\" } ], \"format_quantity\": 1, \"formats\": [ { \"descriptions\": [ \"7\\\"\", \"Single\", \"45 RPM\" ], \"name\": \"Vinyl\", \"qty\": \"1\" } ], \"genres\": [ \"Electronic\", \"Pop\" ], \"identifiers\": [ { \"type\": \"Barcode\", \"value\": \"5012394144777\" } ], \"images\": [ { \"height\": 600, \"resource_url\": \"https://api-img.discogs.com/z_u8yqxvDcwVnR4tX2HLNLaQO2Y=/fit-in/600x600/filters:strip_icc():format(jpeg):mode_rgb():quality(96)/discogs-images/R-249504-1334592212.jpeg.jpg\", \"type\": \"primary\", \"uri\": \"https://api-img.discogs.com/z_u8yqxvDcwVnR4tX2HLNLaQO2Y=/fit-in/600x600/filters:strip_icc():format(jpeg):mode_rgb():quality(96)/discogs-images/R-249504-1334592212.jpeg.jpg\", \"uri150\": \"https://api-img.discogs.com/0ZYgPR4X2HdUKA_jkhPJF4SN5mM=/fit-in/150x150/filters:strip_icc():format(jpeg):mode_rgb()/discogs-images/R-249504-1334592212.jpeg.jpg\", \"width\": 600 }, { \"height\": 600, \"resource_url\": \"https://api-img.discogs.com/EnQXaDOs5T6YI9zq-R5I_mT7hSk=/fit-in/600x600/filters:strip_icc():format(jpeg):mode_rgb():quality(96)/discogs-images/R-249504-1334592228.jpeg.jpg\", \"type\": \"secondary\", \"uri\": \"https://api-img.discogs.com/EnQXaDOs5T6YI9zq-R5I_mT7hSk=/fit-in/600x600/filters:strip_icc():format(jpeg):mode_rgb():quality(96)/discogs-images/R-249504-1334592228.jpeg.jpg\", \"uri150\": \"https://api-img.discogs.com/abk0FWgWsRDjU4bkCDwk0gyMKBo=/fit-in/150x150/filters:strip_icc():format(jpeg):mode_rgb()/discogs-images/R-249504-1334592228.jpeg.jpg\", \"width\": 600 } ], \"labels\": [{ \"catno\": \"PB 41447\", \"entity_type\": \"1\", \"id\": 895, \"name\": \"RCA\", \"resource_url\": \"https://api.discogs.com/labels/895\" } ], \"master_id\": 96559, \"master_url\": \"https://api.discogs.com/masters/96559\", \"notes\": \"UK Release has a black label with the text \\\"Manufactured In England\\\" printed on it.\r\n\r\nSleeve:\r\n\u2117 1987 \u2022 BMG Records (UK) Ltd. \u00a9 1987 \u2022 BMG Records (UK) Ltd.\r\nDistributed in the UK by BMG Records \u2022 Distribu\u00e9 en Europe par BMG/Ariola \u2022 Vertrieb en Europa d\u00fcrch BMG/Ariola.\r\n\r\nCenter labels:\r\n\u2117 1987 Pete Waterman Ltd.\r\nOriginal Sound Recording made by PWL.\r\nBMG Records (UK) Ltd. are the exclusive licensees for the world.\r\n\r\nDurations do not appear on the release.\r\n\", \"released\": \"1987\", \"released_formatted\": \"1987\", \"resource_url\": \"https://api.discogs.com/releases/249504\", \"series\": [], \"status\": \"Accepted\", \"styles\": [ \"Synth-pop\" ], \"tracklist\": [ { \"duration\": \"3:32\", \"position\": \"A\", \"title\": \"Never Gonna Give You Up\", \"type_\": \"track\" }, { \"duration\": \"3:30\", \"position\": \"B\", \"title\": \"Never Gonna Give You Up (Instrumental)\", \"type_\": \"track\" } ], \"uri\": \"http://www.discogs.com/Rick-Astley-Never-Gonna-Give-You-Up/release/249504\", \"videos\": [ { \"description\": \"Rick Astley - Never Gonna Give You Up (Extended Version)\", \"duration\": 330, \"embed\": true, \"title\": \"Rick Astley - Never Gonna Give You Up (Extended Version)\", \"uri\": \"https://www.youtube.com/watch?v=te2jJncBVG4\" } ], \"year\": 1987 }"; 13 | private const string _ReleaseJSON2 = "{\"styles\": [\"House\", \"Pop Rap\", \"Downtempo\"], \"series\": [], \"labels\": [{\"name\": \"Dino Music\", \"entity_type\": \"1\", \"catno\": \"DCD 2573\", \"resource_url\": \"https://api.discogs.com/labels/1608\", \"id\": 1608, \"entity_type_name\": \"Label\"}, {\"name\": \"TELDEC\", \"entity_type\": \"1\", \"catno\": \"2292-41957-2\", \"resource_url\": \"https://api.discogs.com/labels/5748\", \"id\": 5748, \"entity_type_name\": \"Label\"}], \"year\": 1990, \"community\": {\"status\": \"Accepted\", \"rating\": {\"count\": 3, \"average\": 4.33}, \"have\": 27, \"contributors\": [{\"username\": \"didatote\", \"resource_url\": \"https://api.discogs.com/users/didatote\"}, {\"username\": \"steady-j\", \"resource_url\": \"https://api.discogs.com/users/steady-j\"}, {\"username\": \"davidone\", \"resource_url\": \"https://api.discogs.com/users/davidone\"}, {\"username\": \"sjcee\", \"resource_url\": \"https://api.discogs.com/users/sjcee\"}, {\"username\": \"wax_junkie\", \"resource_url\": \"https://api.discogs.com/users/wax_junkie\"}, {\"username\": \"laatr\", \"resource_url\": \"https://api.discogs.com/users/laatr\"}, {\"username\": \"djindio\", \"resource_url\": \"https://api.discogs.com/users/djindio\"}, {\"username\": \"bausl\", \"resource_url\": \"https://api.discogs.com/users/bausl\"}, {\"username\": \"DiscogsUpdateBot\", \"resource_url\": \"https://api.discogs.com/users/DiscogsUpdateBot\"}, {\"username\": \"littleislander\", \"resource_url\": \"https://api.discogs.com/users/littleislander\"}], \"want\": 15, \"submitter\": {\"username\": \"didatote\", \"resource_url\": \"https://api.discogs.com/users/didatote\"}, \"data_quality\": \"Needs Vote\"}, \"artists\": [{\"join\": \",\", \"name\": \"Various\", \"anv\": \"\", \"tracks\": \"\", \"role\": \"\", \"resource_url\": \"https://api.discogs.com/artists/194\", \"id\": 194}], \"images\": [{\"uri\": \"\", \"height\": 470, \"width\": 600, \"resource_url\": \"\", \"type\": \"primary\", \"uri150\": \"\"}, {\"uri\": \"\", \"height\": 467, \"width\": 600, \"resource_url\": \"\", \"type\": \"secondary\", \"uri150\": \"\"}, {\"uri\": \"\", \"height\": 600, \"width\": 600, \"resource_url\": \"\", \"type\": \"secondary\", \"uri150\": \"\"}, {\"uri\": \"\", \"height\": 600, \"width\": 600, \"resource_url\": \"\", \"type\": \"secondary\", \"uri150\": \"\"}, {\"uri\": \"\", \"height\": 600, \"width\": 600, \"resource_url\": \"\", \"type\": \"secondary\", \"uri150\": \"\"}, {\"uri\": \"\", \"height\": 600, \"width\": 600, \"resource_url\": \"\", \"type\": \"secondary\", \"uri150\": \"\"}, {\"uri\": \"\", \"height\": 600, \"width\": 600, \"resource_url\": \"\", \"type\": \"secondary\", \"uri150\": \"\"}, {\"uri\": \"\", \"height\": 600, \"width\": 600, \"resource_url\": \"\", \"type\": \"secondary\", \"uri150\": \"\"}], \"format_quantity\": 2, \"id\": 696229, \"genres\": [\"Electronic\", \"Hip Hop\"], \"thumb\": \"\", \"num_for_sale\": 11, \"title\": \"Get Up - The Ultimate Dance Collection\", \"date_changed\": \"2016-12-17T08:31:44-08:00\", \"master_id\": 79533, \"lowest_price\": 2.1591277124041888, \"status\": \"Accepted\", \"released_formatted\": \"1990\", \"estimated_weight\": 170, \"master_url\": \"https://api.discogs.com/masters/79533\", \"released\": \"1990\", \"date_added\": \"2006-08-03T03:42:44-07:00\", \"tracklist\": [{\"extraartists\": [{\"join\": \"\", \"name\": \"Andre 'L.A.Dre' Bolton\", \"anv\": \"\", \"tracks\": \"\", \"role\": \"Producer\", \"resource_url\": \"https://api.discogs.com/artists/199679\", \"id\": 199679}, {\"join\": \"\", \"name\": \"Dr. Dre\", \"anv\": \"\", \"tracks\": \"\", \"role\": \"Producer, Remix\", \"resource_url\": \"https://api.discogs.com/artists/50513\", \"id\": 50513}, {\"join\": \"\", \"name\": \"Yella\", \"anv\": \"DJ Yella\", \"tracks\": \"\", \"role\": \"Remix\", \"resource_url\": \"https://api.discogs.com/artists/12330\", \"id\": 12330}], \"title\": \"No More Lies (Extended Dance Mix)\", \"type_\": \"track\", \"artists\": [{\"join\": \",\", \"name\": \"Michel'le\", \"anv\": \"\", \"tracks\": \"\", \"role\": \"\", \"resource_url\": \"https://api.discogs.com/artists/105614\", \"id\": 105614}], \"duration\": \"6:18\", \"position\": \"1-1\"}, {\"duration\": \"6:39\", \"position\": \"1-2\", \"type_\": \"track\", \"title\": \"Natural Thing (Sunset Mix)\", \"artists\": [{\"join\": \",\", \"name\": \"Innocence\", \"anv\": \"\", \"tracks\": \"\", \"role\": \"\", \"resource_url\": \"https://api.discogs.com/artists/30662\", \"id\": 30662}]}, {\"extraartists\": [{\"join\": \"\", \"name\": \"Soul II Soul\", \"anv\": \"\", \"tracks\": \"\", \"role\": \"Remix\", \"resource_url\": \"https://api.discogs.com/artists/4970\", \"id\": 4970}], \"title\": \"Ghetto Heaven (Soul II Soul Remix)\", \"type_\": \"track\", \"artists\": [{\"join\": \",\", \"name\": \"The Family Stand\", \"anv\": \"\", \"tracks\": \"\", \"role\": \"\", \"resource_url\": \"https://api.discogs.com/artists/34521\", \"id\": 34521}], \"duration\": \"4:47\", \"position\": \"1-3\"}, {\"extraartists\": [{\"join\": \"\", \"name\": \"Soul II Soul\", \"anv\": \"\", \"tracks\": \"\", \"role\": \"Producer\", \"resource_url\": \"https://api.discogs.com/artists/4970\", \"id\": 4970}], \"title\": \"1-2-3\", \"type_\": \"track\", \"artists\": [{\"join\": \",\", \"name\": \"The Chimes\", \"anv\": \"\", \"tracks\": \"\", \"role\": \"\", \"resource_url\": \"https://api.discogs.com/artists/34547\", \"id\": 34547}], \"duration\": \"3:23\", \"position\": \"1-4\"}, {\"extraartists\": [{\"join\": \"\", \"name\": \"Bert Bevans\", \"anv\": \"\", \"tracks\": \"\", \"role\": \"DJ Mix [Megamix]\", \"resource_url\": \"https://api.discogs.com/artists/40300\", \"id\": 40300}, {\"join\": \"\", \"name\": \"Ian Grimble\", \"anv\": \"\", \"tracks\": \"\", \"role\": \"Engineer\", \"resource_url\": \"https://api.discogs.com/artists/91507\", \"id\": 91507}, {\"join\": \"\", \"name\": \"Jimmy Polo\", \"anv\": \"\", \"tracks\": \"\", \"role\": \"Keyboards\", \"resource_url\": \"https://api.discogs.com/artists/51101\", \"id\": 51101}], \"title\": \"Mega Chic\", \"type_\": \"track\", \"artists\": [{\"join\": \",\", \"name\": \"Chic\", \"anv\": \"\", \"tracks\": \"\", \"role\": \"\", \"resource_url\": \"https://api.discogs.com/artists/9081\", \"id\": 9081}], \"duration\": \"4:36\", \"position\": \"1-5\"}, {\"duration\": \"\", \"position\": \"1-5a\", \"type_\": \"track\", \"title\": \"Le Freak\", \"artists\": [{\"join\": \",\", \"name\": \"Chic\", \"anv\": \"\", \"tracks\": \"\", \"role\": \"\", \"resource_url\": \"https://api.discogs.com/artists/9081\", \"id\": 9081}]}, {\"duration\": \"\", \"position\": \"1-5b\", \"type_\": \"track\", \"title\": \"Everybody Dance\", \"artists\": [{\"join\": \",\", \"name\": \"Chic\", \"anv\": \"\", \"tracks\": \"\", \"role\": \"\", \"resource_url\": \"https://api.discogs.com/artists/9081\", \"id\": 9081}]}, {\"duration\": \"\", \"position\": \"1-5c\", \"type_\": \"track\", \"title\": \"Good Times\", \"artists\": [{\"join\": \",\", \"name\": \"Chic\", \"anv\": \"\", \"tracks\": \"\", \"role\": \"\", \"resource_url\": \"https://api.discogs.com/artists/9081\", \"id\": 9081}]}, {\"duration\": \"\", \"position\": \"1-5d\", \"type_\": \"track\", \"title\": \"I Want Your Love\", \"artists\": [{\"join\": \",\", \"name\": \"Chic\", \"anv\": \"\", \"tracks\": \"\", \"role\": \"\", \"resource_url\": \"https://api.discogs.com/artists/9081\", \"id\": 9081}]}, {\"extraartists\": [{\"join\": \"\", \"name\": \"Smack\", \"anv\": \"Smack Productions\", \"tracks\": \"\", \"role\": \"Producer\", \"resource_url\": \"https://api.discogs.com/artists/29780\", \"id\": 29780}], \"title\": \"Treat Me Right (Trumped Mix)\", \"type_\": \"track\", \"artists\": [{\"join\": \",\", \"name\": \"Adeva\", \"anv\": \"\", \"tracks\": \"\", \"role\": \"\", \"resource_url\": \"https://api.discogs.com/artists/15169\", \"id\": 15169}], \"duration\": \"6:39\", \"position\": \"1-6\"}, {\"extraartists\": [{\"join\": \"\", \"name\": \"Lloyd Roberts (3)\", \"anv\": \"Lloyd\", \"tracks\": \"\", \"role\": \"Bass\", \"resource_url\": \"https://api.discogs.com/artists/4438368\", \"id\": 4438368}, {\"join\": \"\", \"name\": \"Afrika Islam\", \"anv\": \"\", \"tracks\": \"\", \"role\": \"Co-producer\", \"resource_url\": \"https://api.discogs.com/artists/22915\", \"id\": 22915}, {\"join\": \"\", \"name\": \"Ernie C\", \"anv\": \"\", \"tracks\": \"\", \"role\": \"Guitar\", \"resource_url\": \"https://api.discogs.com/artists/191182\", \"id\": 191182}], \"title\": \"What Ya Wanna Do? (LP Version)\", \"type_\": \"track\", \"artists\": [{\"join\": \",\", \"name\": \"Ice-T\", \"anv\": \"\", \"tracks\": \"\", \"role\": \"\", \"resource_url\": \"https://api.discogs.com/artists/66147\", \"id\": 66147}], \"duration\": \"8:57\", \"position\": \"1-7\"}, {\"extraartists\": [{\"join\": \"\", \"name\": \"Markell Riley\", \"anv\": \"\", \"tracks\": \"\", \"role\": \"Co-producer\", \"resource_url\": \"https://api.discogs.com/artists/167347\", \"id\": 167347}, {\"join\": \"\", \"name\": \"Gene Griffin\", \"anv\": \"\", \"tracks\": \"\", \"role\": \"Remix\", \"resource_url\": \"https://api.discogs.com/artists/116235\", \"id\": 116235}], \"title\": \"We Rock The Mic (Party Version)\", \"type_\": \"track\", \"artists\": [{\"join\": \",\", \"name\": \"Redhead Kingpin And The FBI\", \"anv\": \"Redhead Kingpin + The FBI\", \"tracks\": \"\", \"role\": \"\", \"resource_url\": \"https://api.discogs.com/artists/32418\", \"id\": 32418}], \"duration\": \"4:18\", \"position\": \"1-8\"}, {\"extraartists\": [{\"join\": \"\", \"name\": \"CJ Mackintosh\", \"anv\": \"\", \"tracks\": \"\", \"role\": \"Remix\", \"resource_url\": \"https://api.discogs.com/artists/23005\", \"id\": 23005}, {\"join\": \"\", \"name\": \"Dave Dorrell\", \"anv\": \"\", \"tracks\": \"\", \"role\": \"Remix\", \"resource_url\": \"https://api.discogs.com/artists/13912\", \"id\": 13912}], \"title\": \"What 'U' Waitin' 4? (Jungle Fever Mix)\", \"type_\": \"track\", \"artists\": [{\"join\": \",\", \"name\": \"Jungle Brothers\", \"anv\": \"\", \"tracks\": \"\", \"role\": \"\", \"resource_url\": \"https://api.discogs.com/artists/1781\", \"id\": 1781}], \"duration\": \"4:25\", \"position\": \"1-9\"}, {\"extraartists\": [{\"join\": \"\", \"name\": \"Cameron Paul\", \"anv\": \"\", \"tracks\": \"\", \"role\": \"Edited By\", \"resource_url\": \"https://api.discogs.com/artists/65292\", \"id\": 65292}, {\"join\": \"\", \"name\": \"The Wild Boys\", \"anv\": \"\", \"tracks\": \"\", \"role\": \"Remix\", \"resource_url\": \"https://api.discogs.com/artists/35700\", \"id\": 35700}], \"title\": \"Ah! Freak Out (Jause, Jause, Jause Remix)\", \"type_\": \"track\", \"artists\": [{\"join\": \",\", \"name\": \"The Macho Man MC Romeo\", \"anv\": \"\", \"tracks\": \"\", \"role\": \"\", \"resource_url\": \"https://api.discogs.com/artists/760545\", \"id\": 760545}], \"duration\": \"2:59\", \"position\": \"1-10\"}, {\"extraartists\": [{\"join\": \"\", \"name\": \"BomKrash\", \"anv\": \"\", \"tracks\": \"\", \"role\": \"Co-producer\", \"resource_url\": \"https://api.discogs.com/artists/51230\", \"id\": 51230}, {\"join\": \"\", \"name\": \"Leila K\", \"anv\": \"\", \"tracks\": \"\", \"role\": \"Featuring\", \"resource_url\": \"https://api.discogs.com/artists/49529\", \"id\": 49529}], \"title\": \"Got To Get (Extended Mix)\", \"type_\": \"track\", \"artists\": [{\"join\": \"Featuring\", \"name\": \"Rob 'N' Raz\", \"anv\": \"\", \"tracks\": \"\", \"role\": \"\", \"resource_url\": \"https://api.discogs.com/artists/11913\", \"id\": 11913}, {\"join\": \",\", \"name\": \"Leila K\", \"anv\": \"\", \"tracks\": \"\", \"role\": \"\", \"resource_url\": \"https://api.discogs.com/artists/49529\", \"id\": 49529}], \"duration\": \"4:27\", \"position\": \"1-11\"}, {\"extraartists\": [{\"join\": \"\", \"name\": \"The 45 King\", \"anv\": \"\", \"tracks\": \"\", \"role\": \"Producer\", \"resource_url\": \"https://api.discogs.com/artists/21125\", \"id\": 21125}, {\"join\": \"\", \"name\": \"\\'Fast' Eddie Smith\", \"anv\": \"Fast Eddie\", \"tracks\": \"\", \"role\": \"Remix\", \"resource_url\": \"https://api.discogs.com/artists/228032\", \"id\": 228032}], \"title\": \"Come Into My House (Fast Eddie Hip House)\", \"type_\": \"track\", \"artists\": [{\"join\": \",\", \"name\": \"Queen Latifah\", \"anv\": \"\", \"tracks\": \"\", \"role\": \"\", \"resource_url\": \"https://api.discogs.com/artists/14488\", \"id\": 14488}], \"duration\": \"4:26\", \"position\": \"1-12\"}, {\"extraartists\": [{\"join\": \"\", \"name\": \"MC Eric\", \"anv\": \"\", \"tracks\": \"\", \"role\": \"Featuring\", \"resource_url\": \"https://api.discogs.com/artists/57587\", \"id\": 57587}], \"title\": \"This Beat Is Technotronic ('My Favourite Club' Mix)\", \"type_\": \"track\", \"artists\": [{\"join\": \"Featuring\", \"name\": \"Technotronic\", \"anv\": \"\", \"tracks\": \"\", \"role\": \"\", \"resource_url\": \"https://api.discogs.com/artists/14457\", \"id\": 14457}, {\"join\": \",\", \"name\": \"MC Eric\", \"anv\": \"\", \"tracks\": \"\", \"role\": \"\", \"resource_url\": \"https://api.discogs.com/artists/57587\", \"id\": 57587}], \"duration\": \"5:59\", \"position\": \"2-1\"}, {\"extraartists\": [{\"join\": \"\", \"name\": \"Aldo Marin\", \"anv\": \"\", \"tracks\": \"\", \"role\": \"Producer\", \"resource_url\": \"https://api.discogs.com/artists/34873\", \"id\": 34873}, {\"join\": \"\", \"name\": \"Dose (2)\", \"anv\": \"\", \"tracks\": \"\", \"role\": \"Producer\", \"resource_url\": \"https://api.discogs.com/artists/195764\", \"id\": 195764}, {\"join\": \"\", \"name\": \"Roger Pauletta\", \"anv\": \"\", \"tracks\": \"\", \"role\": \"Producer\", \"resource_url\": \"https://api.discogs.com/artists/50823\", \"id\": 50823}], \"title\": \"Do What You Want (12 Inch Remix)\", \"type_\": \"track\", \"artists\": [{\"join\": \",\", \"name\": \"2 In A Room\", \"anv\": \"\", \"tracks\": \"\", \"role\": \"\", \"resource_url\": \"https://api.discogs.com/artists/13196\", \"id\": 13196}], \"duration\": \"4:02\", \"position\": \"2-2\"}, {\"duration\": \"5:10\", \"position\": \"2-3\", \"type_\": \"track\", \"title\": \"Ritmo De La Noche (Freestyle-Mix)\", \"artists\": [{\"join\": \",\", \"name\": \"Chocolate\", \"anv\": \"\", \"tracks\": \"\", \"role\": \"\", \"resource_url\": \"https://api.discogs.com/artists/68807\", \"id\": 68807}]}, {\"extraartists\": [{\"join\": \"\", \"name\": \"Bass Bumpers\", \"anv\": \"\", \"tracks\": \"\", \"role\": \"Remix\", \"resource_url\": \"https://api.discogs.com/artists/7618\", \"id\": 7618}], \"title\": \"Move Your Body (Bass Bumpers Remix)\", \"type_\": \"track\", \"artists\": [{\"join\": \",\", \"name\": \"Sydney Fresh\", \"anv\": \"\", \"tracks\": \"\", \"role\": \"\", \"resource_url\": \"https://api.discogs.com/artists/81445\", \"id\": 81445}], \"duration\": \"4:39\", \"position\": \"2-4\"}, {\"duration\": \"5:07\", \"position\": \"2-5\", \"type_\": \"track\", \"title\": \"Hold Me Back\", \"artists\": [{\"join\": \",\", \"name\": \"WestBam\", \"anv\": \"\", \"tracks\": \"\", \"role\": \"\", \"resource_url\": \"https://api.discogs.com/artists/6092\", \"id\": 6092}]}, {\"extraartists\": [{\"join\": \"\", \"name\": \"Captain Hollywood\", \"anv\": \"\", \"tracks\": \"\", \"role\": \"Featuring\", \"resource_url\": \"https://api.discogs.com/artists/31937\", \"id\": 31937}], \"title\": \"I Can't Stand It!\", \"type_\": \"track\", \"artists\": [{\"join\": \",\", \"name\": \"Twenty 4 Seven\", \"anv\": \"\", \"tracks\": \"\", \"role\": \"\", \"resource_url\": \"https://api.discogs.com/artists/14472\", \"id\": 14472}], \"duration\": \"4:08\", \"position\": \"2-6\"}, {\"extraartists\": [{\"join\": \"\", \"name\": \"Seal\", \"anv\": \"\", \"tracks\": \"\", \"role\": \"Vocals\", \"resource_url\": \"https://api.discogs.com/artists/10643\", \"id\": 10643}], \"title\": \"Killer\", \"type_\": \"track\", \"artists\": [{\"join\": \",\", \"name\": \"Adamski\", \"anv\": \"\", \"tracks\": \"\", \"role\": \"\", \"resource_url\": \"https://api.discogs.com/artists/5545\", \"id\": 5545}], \"duration\": \"5:30\", \"position\": \"2-7\"}, {\"duration\": \"5:55\", \"position\": \"2-8\", \"type_\": \"track\", \"title\": \"Don't You Love Me (90's Mix)\", \"artists\": [{\"join\": \",\", \"name\": \"49ers\", \"anv\": \"\", \"tracks\": \"\", \"role\": \"\", \"resource_url\": \"https://api.discogs.com/artists/34155\", \"id\": 34155}]}, {\"extraartists\": [{\"join\": \"\", \"name\": \"Kelvin Andrews\", \"anv\": \"\", \"tracks\": \"\", \"role\": \"Remix\", \"resource_url\": \"https://api.discogs.com/artists/199422\", \"id\": 199422}], \"title\": \"Strawberry Fields Forever (Raspberry Ripple Remix)\", \"type_\": \"track\", \"artists\": [{\"join\": \",\", \"name\": \"Candy Flip\", \"anv\": \"\", \"tracks\": \"\", \"role\": \"\", \"resource_url\": \"https://api.discogs.com/artists/40467\", \"id\": 40467}], \"duration\": \"5:51\", \"position\": \"2-9\"}, {\"duration\": \"3:45\", \"position\": \"2-10\", \"type_\": \"track\", \"title\": \"So What\", \"artists\": [{\"join\": \",\", \"name\": \"Go'Ss\", \"anv\": \"G O's\", \"tracks\": \"\", \"role\": \"\", \"resource_url\": \"https://api.discogs.com/artists/202622\", \"id\": 202622}]}, {\"duration\": \"4:13\", \"position\": \"2-11\", \"type_\": \"track\", \"title\": \"Time After Time\", \"artists\": [{\"join\": \",\", \"name\": \"Timmy T\", \"anv\": \"\", \"tracks\": \"\", \"role\": \"\", \"resource_url\": \"https://api.discogs.com/artists/59632\", \"id\": 59632}]}, {\"duration\": \"3:09\", \"position\": \"2-12\", \"type_\": \"track\", \"title\": \"Don't Kill The Rain Forest (Dance Mix)\", \"artists\": [{\"join\": \",\", \"name\": \"C.C.C.P.\", \"anv\": \"CCCP\", \"tracks\": \"\", \"role\": \"\", \"resource_url\": \"https://api.discogs.com/artists/61730\", \"id\": 61730}]}], \"extraartists\": [{\"join\": \"\", \"name\": \"David Fascher\", \"anv\": \"\", \"tracks\": \"\", \"role\": \"Compiled By\", \"resource_url\": \"https://api.discogs.com/artists/374233\", \"id\": 374233}], \"country\": \"Germany\", \"identifiers\": [{\"type\": \"Barcode\", \"value\": \"none\"}, {\"type\": \"Matrix / Runout\", \"description\": \"CD 1\", \"value\": \"229241957-2/1 RS\"}, {\"type\": \"Matrix / Runout\", \"description\": \"CD 2\", \"value\": \"229241957-2/2 RS\"}, {\"type\": \"Rights Society\", \"value\": \"GEMA BIEM\"}, {\"type\": \"Label Code\", \"value\": \"LC 8410\"}], \"companies\": [{\"name\": \"TELDEC Record Service GmbH\", \"entity_type\": \"13\", \"catno\": \"\", \"resource_url\": \"https://api.discogs.com/labels/46562\", \"id\": 46562, \"entity_type_name\": \"Phonographic Copyright (p)\"}, {\"name\": \"TELDEC Record Service GmbH\", \"entity_type\": \"14\", \"catno\": \"\", \"resource_url\": \"https://api.discogs.com/labels/46562\", \"id\": 46562, \"entity_type_name\": \"Copyright (c)\"}, {\"name\": \"Record Service GmbH\", \"entity_type\": \"10\", \"catno\": \"\", \"resource_url\": \"https://api.discogs.com/labels/264652\", \"id\": 264652, \"entity_type_name\": \"Manufactured By\"}, {\"name\": \"Dino Music AG\", \"entity_type\": \"9\", \"catno\": \"\", \"resource_url\": \"https://api.discogs.com/labels/284090\", \"id\": 284090, \"entity_type_name\": \"Distributed By\"}, {\"name\": \"Dino Music Ges.m.b.H.\", \"entity_type\": \"9\", \"catno\": \"\", \"resource_url\": \"https://api.discogs.com/labels/284091\", \"id\": 284091, \"entity_type_name\": \"Distributed By\"}, {\"name\": \"EMI Columbia Austria Ges.m.b.H.\", \"entity_type\": \"9\", \"catno\": \"\", \"resource_url\": \"https://api.discogs.com/labels/293178\", \"id\": 293178, \"entity_type_name\": \"Distributed By\"}, {\"name\": \"EMI Records (Switzerland) AG\", \"entity_type\": \"9\", \"catno\": \"\", \"resource_url\": \"https://api.discogs.com/labels/174089\", \"id\": 174089, \"entity_type_name\": \"Distributed By\"}, {\"name\": \"DMC\", \"entity_type\": \"9\", \"catno\": \"\", \"resource_url\": \"https://api.discogs.com/labels/4243\", \"id\": 4243, \"entity_type_name\": \"Distributed By\"}], \"uri\": \"https://www.discogs.com/Various-Get-Up-The-Ultimate-Dance-Collection/release/696229\", \"formats\": [{\"descriptions\": [\"Compilation\"], \"name\": \"CD\", \"qty\": \"2\"}], \"resource_url\": \"https://api.discogs.com/releases/696229\", \"data_quality\": \"Needs Vote\"}"; 14 | private const string _ReleaseJSON3 = "{\"styles\": [\"Psychedelic Rock\", \"Prog Rock\"], \"series\": [], \"labels\": [{\"name\": \"EMI\", \"entity_type\": \"1\", \"catno\": \"SLEM-384\", \"resource_url\": \"https://api.discogs.com/labels/26126\", \"id\": 26126, \"entity_type_name\": \"Label\"}, {\"name\": \"Capitol Records\", \"entity_type\": \"1\", \"catno\": \"SLEM-384\", \"resource_url\": \"https://api.discogs.com/labels/654\", \"id\": 654, \"entity_type_name\": \"Label\"}], \"year\": 1979, \"community\": {\"status\": \"Accepted\", \"rating\": {\"count\": 8, \"average\": 4.75}, \"have\": 53, \"contributors\": [{\"username\": \"svent\", \"resource_url\": \"https://api.discogs.com/users/svent\"}, {\"username\": \"oziel\", \"resource_url\": \"https://api.discogs.com/users/oziel\"}, {\"username\": \"xjoxjox\", \"resource_url\": \"https://api.discogs.com/users/xjoxjox\"}, {\"username\": \"ubongo\", \"resource_url\": \"https://api.discogs.com/users/ubongo\"}, {\"username\": \"Kurtcobainfan\", \"resource_url\": \"https://api.discogs.com/users/Kurtcobainfan\"}, {\"username\": \"Deadspace117\", \"resource_url\": \"https://api.discogs.com/users/Deadspace117\"}, {\"username\": \"vinyljunkie66\", \"resource_url\": \"https://api.discogs.com/users/vinyljunkie66\"}, {\"username\": \"crapino\", \"resource_url\": \"https://api.discogs.com/users/crapino\"}, {\"username\": \"Opdiner\", \"resource_url\": \"https://api.discogs.com/users/Opdiner\"}], \"want\": 243, \"submitter\": {\"username\": \"svent\", \"resource_url\": \"https://api.discogs.com/users/svent\"}, \"data_quality\": \"Needs Vote\"}, \"artists\": [{\"join\": \"\", \"name\": \"Pink Floyd\", \"anv\": \"\", \"tracks\": \"\", \"role\": \"\", \"resource_url\": \"https://api.discogs.com/artists/45467\", \"id\": 45467}], \"images\": [{\"uri\": \"\", \"height\": 265, \"width\": 250, \"resource_url\": \"\", \"type\": \"primary\", \"uri150\": \"\"}, {\"uri\": \"\", \"height\": 593, \"width\": 600, \"resource_url\": \"\", \"type\": \"secondary\", \"uri150\": \"\"}, {\"uri\": \"\", \"height\": 434, \"width\": 600, \"resource_url\": \"\", \"type\": \"secondary\", \"uri150\": \"\"}, {\"uri\": \"\", \"height\": 584, \"width\": 600, \"resource_url\": \"\", \"type\": \"secondary\", \"uri150\": \"\"}, {\"uri\": \"\", \"height\": 538, \"width\": 600, \"resource_url\": \"\", \"type\": \"secondary\", \"uri150\": \"\"}, {\"uri\": \"\", \"height\": 632, \"width\": 600, \"resource_url\": \"\", \"type\": \"secondary\", \"uri150\": \"\"}, {\"uri\": \"\", \"height\": 563, \"width\": 600, \"resource_url\": \"\", \"type\": \"secondary\", \"uri150\": \"\"}, {\"uri\": \"\", \"height\": 651, \"width\": 600, \"resource_url\": \"\", \"type\": \"secondary\", \"uri150\": \"\"}, {\"uri\": \"\", \"height\": 639, \"width\": 600, \"resource_url\": \"\", \"type\": \"secondary\", \"uri150\": \"\"}], \"format_quantity\": 1, \"id\": 2106643, \"artists_sort\": \"Pink Floyd\", \"genres\": [\"Rock\"], \"thumb\": \"\", \"num_for_sale\": 6, \"title\": \"Atom Heart Mother\", \"date_changed\": \"2017-06-22T23:37:41-07:00\", \"master_id\": 12676, \"lowest_price\": 24.9, \"status\": \"Accepted\", \"released_formatted\": \"1979\", \"estimated_weight\": 230, \"master_url\": \"https://api.discogs.com/masters/12676\", \"released\": \"1979\", \"date_added\": \"2010-01-24T09:36:07-08:00\", \"tracklist\": [{\"duration\": \"23:51\", \"position\": \"\", \"type_\": \"index\", \"sub_tracks\": [{\"duration\": \"\", \"position\": \"A.a\", \"type_\": \"track\", \"title\": \"Father\'s Shout\"}, {\"duration\": \"\", \"position\": \"A.b\", \"type_\": \"track\", \"title\": \"Breast Milky\"}, {\"duration\": \"\", \"position\": \"A.c\", \"type_\": \"track\", \"title\": \"Mother Fore\"}, {\"duration\": \"\", \"position\": \"A.d\", \"type_\": \"track\", \"title\": \"Funky Dung\"}, {\"duration\": \"\", \"position\": \"A.e\", \"type_\": \"track\", \"title\": \"Mind Your Throats Please\"}, {\"duration\": \"\", \"position\": \"A.f\", \"type_\": \"track\", \"title\": \"Remergence\"}], \"title\": \"Atom Heart Mother\"}, {\"duration\": \"4:24\", \"position\": \"B1\", \"type_\": \"track\", \"title\": \"If\"}, {\"duration\": \"5:26\", \"position\": \"B2\", \"type_\": \"track\", \"title\": \"Summer 68\"}, {\"duration\": \"5:17\", \"position\": \"B3\", \"type_\": \"track\", \"title\": \"Fat Old Sun\"}, {\"duration\": \"12:56\", \"position\": \"\", \"type_\": \"index\", \"sub_tracks\": [{\"duration\": \"\", \"position\": \"B4.a\", \"type_\": \"track\", \"title\": \"Rise And Shine\"}, {\"duration\": \"\", \"position\": \"B4.b\", \"type_\": \"track\", \"title\": \"Sunny Side Up\"}, {\"duration\": \"\", \"position\": \"B4.c\", \"type_\": \"track\", \"title\": \"Morning Glory\"}], \"title\": \"Alan\'s Psychedelic Breakfast\"}], \"extraartists\": [{\"join\": \"\", \"name\": \"Alan Parsons\", \"anv\": \"Allan Parsons\", \"tracks\": \"\", \"role\": \"Engineer\", \"resource_url\": \"https://api.discogs.com/artists/157075\", \"id\": 157075}, {\"join\": \"\", \"name\": \"Peter Bown\", \"anv\": \"\", \"tracks\": \"\", \"role\": \"Engineer\", \"resource_url\": \"https://api.discogs.com/artists/256111\", \"id\": 256111}, {\"join\": \"\", \"name\": \"Norman Smith\", \"anv\": \"\", \"tracks\": \"\", \"role\": \"Executive-Producer\", \"resource_url\": \"https://api.discogs.com/artists/252775\", \"id\": 252775}, {\"join\": \"\", \"name\": \"Pink Floyd\", \"anv\": \"\", \"tracks\": \"\", \"role\": \"Producer\", \"resource_url\": \"https://api.discogs.com/artists/45467\", \"id\": 45467}], \"country\": \"Mexico\", \"notes\": \"Recorded at EMI Studios - Abbey Road.\\r\\n\", \"identifiers\": [], \"companies\": [{\"name\": \"EMI Capitol De Mexico, S.A. De C.V.\", \"entity_type\": \"10\", \"catno\": \"\", \"resource_url\": \"https://api.discogs.com/labels/271148\", \"id\": 271148, \"entity_type_name\": \"Manufactured By\"}, {\"name\": \"EMI Studios\", \"entity_type\": \"23\", \"catno\": \"\", \"resource_url\": \"https://api.discogs.com/labels/274057\", \"id\": 274057, \"entity_type_name\": \"Recorded At\"}], \"uri\": \"https://www.discogs.com/Pink-Floyd-Atom-Heart-Mother/release/2106643\", \"formats\": [{\"descriptions\": [\"LP\", \"Album\", \"Reissue\"], \"text\": \"Gatefold\", \"name\": \"Vinyl\", \"qty\": \"1\"}], \"resource_url\": \"https://api.discogs.com/releases/2106643\", \"data_quality\": \"Needs Vote\"}"; 15 | private const string _ReleaseJSON4 = "{ \"styles\": [ \"Psychedelic Rock\", \"Prog Rock\" ], \"series\": [], \"labels\": [ { \"name\": \"Pink Floyd Records\", \"entity_type\": \"1\", \"catno\": \"PFRLP5\", \"resource_url\": \"https://api.discogs.com/labels/983890\", \"id\": 983890, \"entity_type_name\": \"Label\" } ], \"year\": 2016, \"community\": { \"status\": \"Accepted\", \"rating\": { \"count\": 128, \"average\": 4.47 }, \"have\": 962, \"contributors\": [ { \"username\": \"foreveryoungrecords\", \"resource_url\": \"https://api.discogs.com/users/foreveryoungrecords\" }, { \"username\": \"vinyl_fred\", \"resource_url\": \"https://api.discogs.com/users/vinyl_fred\" }, { \"username\": \"William-Lee\", \"resource_url\": \"https://api.discogs.com/users/William-Lee\" }, { \"username\": \"Toine_Damen\", \"resource_url\": \"https://api.discogs.com/users/Toine_Damen\" }, { \"username\": \"Lorenzo15\", \"resource_url\": \"https://api.discogs.com/users/Lorenzo15\" } ], \"want\": 244, \"submitter\": { \"username\": \"foreveryoungrecords\", \"resource_url\": \"https://api.discogs.com/users/foreveryoungrecords\" }, \"data_quality\": \"Needs Vote\" }, \"artists\": [ { \"join\": \"\", \"name\": \"Pink Floyd\", \"anv\": \"\", \"tracks\": \"\", \"role\": \"\", \"resource_url\": \"https://api.discogs.com/artists/45467\", \"id\": 45467 } ], \"images\": [ { \"uri\": \"\", \"height\": 600, \"width\": 600, \"resource_url\": \"\", \"type\": \"primary\", \"uri150\": \"\" }, { \"uri\": \"\", \"height\": 600, \"width\": 600, \"resource_url\": \"\", \"type\": \"secondary\", \"uri150\": \"\" }, { \"uri\": \"\", \"height\": 588, \"width\": 600, \"resource_url\": \"\", \"type\": \"secondary\", \"uri150\": \"\" }, { \"uri\": \"\", \"height\": 600, \"width\": 600, \"resource_url\": \"\", \"type\": \"secondary\", \"uri150\": \"\" }, { \"uri\": \"\", \"height\": 600, \"width\": 600, \"resource_url\": \"\", \"type\": \"secondary\", \"uri150\": \"\" }, { \"uri\": \"\", \"height\": 294, \"width\": 600, \"resource_url\": \"\", \"type\": \"secondary\", \"uri150\": \"\" }, { \"uri\": \"\", \"height\": 292, \"width\": 600, \"resource_url\": \"\", \"type\": \"secondary\", \"uri150\": \"\" }, { \"uri\": \"\", \"height\": 600, \"width\": 600, \"resource_url\": \"\", \"type\": \"secondary\", \"uri150\": \"\" }, { \"uri\": \"\", \"height\": 600, \"width\": 600, \"resource_url\": \"\", \"type\": \"secondary\", \"uri150\": \"\" }, { \"uri\": \"\", \"height\": 600, \"width\": 600, \"resource_url\": \"\", \"type\": \"secondary\", \"uri150\": \"\" }, { \"uri\": \"\", \"height\": 600, \"width\": 600, \"resource_url\": \"\", \"type\": \"secondary\", \"uri150\": \"\" }, { \"uri\": \"\", \"height\": 600, \"width\": 337, \"resource_url\": \"\", \"type\": \"secondary\", \"uri150\": \"\" } ], \"format_quantity\": 1, \"id\": 9093776, \"artists_sort\": \"Pink Floyd\", \"genres\": [ \"Rock\" ], \"thumb\": \"\", \"num_for_sale\": 36, \"title\": \"Atom Heart Mother\", \"date_changed\": \"2017-12-10T17:53:27-08:00\", \"master_id\": 12676, \"lowest_price\": 15.0, \"status\": \"Accepted\", \"released_formatted\": \"2016\", \"estimated_weight\": 230, \"master_url\": \"https://api.discogs.com/masters/12676\", \"released\": \"2016\", \"date_added\": \"2016-09-23T13:41:43-07:00\", \"tracklist\": [ { \"duration\": \"\", \"position\": \"\", \"type_\": \"index\", \"sub_tracks\": [ { \"duration\": \"\", \"position\": \"A.a\", \"type_\": \"track\", \"extraartists\": [ { \"join\": \"\", \"name\": \"David Gilmour\", \"anv\": \"Gilmour\", \"tracks\": \"\", \"role\": \"Written-By\", \"resource_url\": \"https://api.discogs.com/artists/110863\", \"id\": 110863 }, { \"join\": \"\", \"name\": \"Nick Mason\", \"anv\": \"Mason\", \"tracks\": \"\", \"role\": \"Written-By\", \"resource_url\": \"https://api.discogs.com/artists/246097\", \"id\": 246097 }, { \"join\": \"\", \"name\": \"Richard Wright\", \"anv\": \"Wright\", \"tracks\": \"\", \"role\": \"Written-By\", \"resource_url\": \"https://api.discogs.com/artists/110861\", \"id\": 110861 }, { \"join\": \"\", \"name\": \"Roger Waters\", \"anv\": \"Waters\", \"tracks\": \"\", \"role\": \"Written-By\", \"resource_url\": \"https://api.discogs.com/artists/110862\", \"id\": 110862 }, { \"join\": \"\", \"name\": \"Ron Geesin\", \"anv\": \"Geesin\", \"tracks\": \"\", \"role\": \"Written-By\", \"resource_url\": \"https://api.discogs.com/artists/51850\", \"id\": 51850 } ], \"title\": \"Father\'s Shout\" }, { \"duration\": \"\", \"position\": \"A.b\", \"type_\": \"track\", \"extraartists\": [ { \"join\": \"\", \"name\": \"David Gilmour\", \"anv\": \"Gilmour\", \"tracks\": \"\", \"role\": \"Written-By\", \"resource_url\": \"https://api.discogs.com/artists/110863\", \"id\": 110863 }, { \"join\": \"\", \"name\": \"Nick Mason\", \"anv\": \"Mason\", \"tracks\": \"\", \"role\": \"Written-By\", \"resource_url\": \"https://api.discogs.com/artists/246097\", \"id\": 246097 }, { \"join\": \"\", \"name\": \"Richard Wright\", \"anv\": \"Wright\", \"tracks\": \"\", \"role\": \"Written-By\", \"resource_url\": \"https://api.discogs.com/artists/110861\", \"id\": 110861 }, { \"join\": \"\", \"name\": \"Roger Waters\", \"anv\": \"Waters\", \"tracks\": \"\", \"role\": \"Written-By\", \"resource_url\": \"https://api.discogs.com/artists/110862\", \"id\": 110862 }, { \"join\": \"\", \"name\": \"Ron Geesin\", \"anv\": \"Geesin\", \"tracks\": \"\", \"role\": \"Written-By\", \"resource_url\": \"https://api.discogs.com/artists/51850\", \"id\": 51850 } ], \"title\": \"Breast Milky\" }, { \"duration\": \"\", \"position\": \"A.c\", \"type_\": \"track\", \"extraartists\": [ { \"join\": \"\", \"name\": \"David Gilmour\", \"anv\": \"Gilmour\", \"tracks\": \"\", \"role\": \"Written-By\", \"resource_url\": \"https://api.discogs.com/artists/110863\", \"id\": 110863 }, { \"join\": \"\", \"name\": \"Nick Mason\", \"anv\": \"Mason\", \"tracks\": \"\", \"role\": \"Written-By\", \"resource_url\": \"https://api.discogs.com/artists/246097\", \"id\": 246097 }, { \"join\": \"\", \"name\": \"Richard Wright\", \"anv\": \"Wright\", \"tracks\": \"\", \"role\": \"Written-By\", \"resource_url\": \"https://api.discogs.com/artists/110861\", \"id\": 110861 }, { \"join\": \"\", \"name\": \"Roger Waters\", \"anv\": \"Waters\", \"tracks\": \"\", \"role\": \"Written-By\", \"resource_url\": \"https://api.discogs.com/artists/110862\", \"id\": 110862 }, { \"join\": \"\", \"name\": \"Ron Geesin\", \"anv\": \"Geesin\", \"tracks\": \"\", \"role\": \"Written-By\", \"resource_url\": \"https://api.discogs.com/artists/51850\", \"id\": 51850 } ], \"title\": \"Mother Fore\" }, { \"duration\": \"\", \"position\": \"A.d\", \"type_\": \"track\", \"extraartists\": [ { \"join\": \"\", \"name\": \"David Gilmour\", \"anv\": \"Gilmour\", \"tracks\": \"\", \"role\": \"Written-By\", \"resource_url\": \"https://api.discogs.com/artists/110863\", \"id\": 110863 }, { \"join\": \"\", \"name\": \"Nick Mason\", \"anv\": \"Mason\", \"tracks\": \"\", \"role\": \"Written-By\", \"resource_url\": \"https://api.discogs.com/artists/246097\", \"id\": 246097 }, { \"join\": \"\", \"name\": \"Richard Wright\", \"anv\": \"Wright\", \"tracks\": \"\", \"role\": \"Written-By\", \"resource_url\": \"https://api.discogs.com/artists/110861\", \"id\": 110861 }, { \"join\": \"\", \"name\": \"Roger Waters\", \"anv\": \"Waters\", \"tracks\": \"\", \"role\": \"Written-By\", \"resource_url\": \"https://api.discogs.com/artists/110862\", \"id\": 110862 }, { \"join\": \"\", \"name\": \"Ron Geesin\", \"anv\": \"Geesin\", \"tracks\": \"\", \"role\": \"Written-By\", \"resource_url\": \"https://api.discogs.com/artists/51850\", \"id\": 51850 } ], \"title\": \"Funky Dung\" }, { \"duration\": \"\", \"position\": \"A.e\", \"type_\": \"track\", \"extraartists\": [ { \"join\": \"\", \"name\": \"David Gilmour\", \"anv\": \"Gilmour\", \"tracks\": \"\", \"role\": \"Written-By\", \"resource_url\": \"https://api.discogs.com/artists/110863\", \"id\": 110863 }, { \"join\": \"\", \"name\": \"Nick Mason\", \"anv\": \"Mason\", \"tracks\": \"\", \"role\": \"Written-By\", \"resource_url\": \"https://api.discogs.com/artists/246097\", \"id\": 246097 }, { \"join\": \"\", \"name\": \"Richard Wright\", \"anv\": \"Wright\", \"tracks\": \"\", \"role\": \"Written-By\", \"resource_url\": \"https://api.discogs.com/artists/110861\", \"id\": 110861 }, { \"join\": \"\", \"name\": \"Roger Waters\", \"anv\": \"Waters\", \"tracks\": \"\", \"role\": \"Written-By\", \"resource_url\": \"https://api.discogs.com/artists/110862\", \"id\": 110862 }, { \"join\": \"\", \"name\": \"Ron Geesin\", \"anv\": \"Geesin\", \"tracks\": \"\", \"role\": \"Written-By\", \"resource_url\": \"https://api.discogs.com/artists/51850\", \"id\": 51850 } ], \"title\": \"Mind Your Throats Please\" }, { \"duration\": \"\", \"position\": \"A.f\", \"type_\": \"track\", \"extraartists\": [ { \"join\": \"\", \"name\": \"David Gilmour\", \"anv\": \"Gilmour\", \"tracks\": \"\", \"role\": \"Written-By\", \"resource_url\": \"https://api.discogs.com/artists/110863\", \"id\": 110863 }, { \"join\": \"\", \"name\": \"Nick Mason\", \"anv\": \"Mason\", \"tracks\": \"\", \"role\": \"Written-By\", \"resource_url\": \"https://api.discogs.com/artists/246097\", \"id\": 246097 }, { \"join\": \"\", \"name\": \"Richard Wright\", \"anv\": \"Wright\", \"tracks\": \"\", \"role\": \"Written-By\", \"resource_url\": \"https://api.discogs.com/artists/110861\", \"id\": 110861 }, { \"join\": \"\", \"name\": \"Roger Waters\", \"anv\": \"Waters\", \"tracks\": \"\", \"role\": \"Written-By\", \"resource_url\": \"https://api.discogs.com/artists/110862\", \"id\": 110862 }, { \"join\": \"\", \"name\": \"Ron Geesin\", \"anv\": \"Geesin\", \"tracks\": \"\", \"role\": \"Written-By\", \"resource_url\": \"https://api.discogs.com/artists/51850\", \"id\": 51850 } ], \"title\": \"Remergence\" } ], \"title\": \"Atom Heart Mother\" }, { \"duration\": \"\", \"position\": \"B1\", \"type_\": \"track\", \"extraartists\": [ { \"join\": \"\", \"name\": \"Roger Waters\", \"anv\": \"Waters\", \"tracks\": \"\", \"role\": \"Written-By\", \"resource_url\": \"https://api.discogs.com/artists/110862\", \"id\": 110862 } ], \"title\": \"If\" }, { \"duration\": \"\", \"position\": \"B2\", \"type_\": \"track\", \"extraartists\": [ { \"join\": \"\", \"name\": \"Richard Wright\", \"anv\": \"Wright\", \"tracks\": \"\", \"role\": \"Written-By\", \"resource_url\": \"https://api.discogs.com/artists/110861\", \"id\": 110861 } ], \"title\": \"Summer \'68\" }, { \"duration\": \"\", \"position\": \"B3\", \"type_\": \"track\", \"extraartists\": [ { \"join\": \"\", \"name\": \"David Gilmour\", \"anv\": \"Gilmour\", \"tracks\": \"\", \"role\": \"Written-By\", \"resource_url\": \"https://api.discogs.com/artists/110863\", \"id\": 110863 } ], \"title\": \"Fat Old Sun\" }, { \"duration\": \"\", \"position\": \"\", \"type_\": \"index\", \"sub_tracks\": [ { \"duration\": \"\", \"position\": \"B4.a\", \"type_\": \"track\", \"extraartists\": [ { \"join\": \"\", \"name\": \"David Gilmour\", \"anv\": \"Gilmour\", \"tracks\": \"\", \"role\": \"Written-By\", \"resource_url\": \"https://api.discogs.com/artists/110863\", \"id\": 110863 }, { \"join\": \"\", \"name\": \"Nick Mason\", \"anv\": \"Mason\", \"tracks\": \"\", \"role\": \"Written-By\", \"resource_url\": \"https://api.discogs.com/artists/246097\", \"id\": 246097 }, { \"join\": \"\", \"name\": \"Richard Wright\", \"anv\": \"Wright\", \"tracks\": \"\", \"role\": \"Written-By\", \"resource_url\": \"https://api.discogs.com/artists/110861\", \"id\": 110861 }, { \"join\": \"\", \"name\": \"Roger Waters\", \"anv\": \"Waters\", \"tracks\": \"\", \"role\": \"Written-By\", \"resource_url\": \"https://api.discogs.com/artists/110862\", \"id\": 110862 } ], \"title\": \"Rise And Shine\" }, { \"duration\": \"\", \"position\": \"B4.b\", \"type_\": \"track\", \"extraartists\": [ { \"join\": \"\", \"name\": \"David Gilmour\", \"anv\": \"Gilmour\", \"tracks\": \"\", \"role\": \"Written-By\", \"resource_url\": \"https://api.discogs.com/artists/110863\", \"id\": 110863 }, { \"join\": \"\", \"name\": \"Nick Mason\", \"anv\": \"Mason\", \"tracks\": \"\", \"role\": \"Written-By\", \"resource_url\": \"https://api.discogs.com/artists/246097\", \"id\": 246097 }, { \"join\": \"\", \"name\": \"Richard Wright\", \"anv\": \"Wright\", \"tracks\": \"\", \"role\": \"Written-By\", \"resource_url\": \"https://api.discogs.com/artists/110861\", \"id\": 110861 }, { \"join\": \"\", \"name\": \"Roger Waters\", \"anv\": \"Waters\", \"tracks\": \"\", \"role\": \"Written-By\", \"resource_url\": \"https://api.discogs.com/artists/110862\", \"id\": 110862 } ], \"title\": \"Sunny Side Up\" }, { \"duration\": \"\", \"position\": \"B4.c\", \"type_\": \"track\", \"extraartists\": [ { \"join\": \"\", \"name\": \"David Gilmour\", \"anv\": \"Gilmour\", \"tracks\": \"\", \"role\": \"Written-By\", \"resource_url\": \"https://api.discogs.com/artists/110863\", \"id\": 110863 }, { \"join\": \"\", \"name\": \"Nick Mason\", \"anv\": \"Mason\", \"tracks\": \"\", \"role\": \"Written-By\", \"resource_url\": \"https://api.discogs.com/artists/246097\", \"id\": 246097 }, { \"join\": \"\", \"name\": \"Richard Wright\", \"anv\": \"Wright\", \"tracks\": \"\", \"role\": \"Written-By\", \"resource_url\": \"https://api.discogs.com/artists/110861\", \"id\": 110861 }, { \"join\": \"\", \"name\": \"Roger Waters\", \"anv\": \"Waters\", \"tracks\": \"\", \"role\": \"Written-By\", \"resource_url\": \"https://api.discogs.com/artists/110862\", \"id\": 110862 } ], \"title\": \"Morning Glory\" } ], \"title\": \"Alan\'s Psychedelic Breakfast\" } ], \"extraartists\": [ { \"join\": \"\", \"name\": \"Hipgnosis (2)\", \"anv\": \"\", \"tracks\": \"\", \"role\": \"Design [Cover], Photography By\", \"resource_url\": \"https://api.discogs.com/artists/1826972\", \"id\": 1826972 }, { \"join\": \"\", \"name\": \"Alan Parsons\", \"anv\": \"\", \"tracks\": \"\", \"role\": \"Engineer\", \"resource_url\": \"https://api.discogs.com/artists/157075\", \"id\": 157075 }, { \"join\": \"\", \"name\": \"Peter Bown\", \"anv\": \"\", \"tracks\": \"\", \"role\": \"Engineer\", \"resource_url\": \"https://api.discogs.com/artists/256111\", \"id\": 256111 }, { \"join\": \"\", \"name\": \"Norman Smith\", \"anv\": \"\", \"tracks\": \"\", \"role\": \"Executive-Producer\", \"resource_url\": \"https://api.discogs.com/artists/252775\", \"id\": 252775 }, { \"join\": \"\", \"name\": \"Bernie Grundman\", \"anv\": \"BG\", \"tracks\": \"\", \"role\": \"Lacquer Cut By\", \"resource_url\": \"https://api.discogs.com/artists/307942\", \"id\": 307942 }, { \"join\": \"\", \"name\": \"Pink Floyd\", \"anv\": \"\", \"tracks\": \"\", \"role\": \"Producer\", \"resource_url\": \"https://api.discogs.com/artists/45467\", \"id\": 45467 }, { \"join\": \"\", \"name\": \"Bernie Grundman\", \"anv\": \"\", \"tracks\": \"\", \"role\": \"Remastered By\", \"resource_url\": \"https://api.discogs.com/artists/307942\", \"id\": 307942 }, { \"join\": \"\", \"name\": \"James Guthrie\", \"anv\": \"\", \"tracks\": \"\", \"role\": \"Remastered By\", \"resource_url\": \"https://api.discogs.com/artists/171450\", \"id\": 171450 }, { \"join\": \"\", \"name\": \"Joel Plante\", \"anv\": \"\", \"tracks\": \"\", \"role\": \"Remastered By\", \"resource_url\": \"https://api.discogs.com/artists/409280\", \"id\": 409280 } ], \"country\": \"US\", \"notes\": \"Original UK release date: October 1970\\n\\n\\u2117 2016 Pink Floyd Music Ltd. \\u00a9 2016 Pink Floyd Music Ltd.\\nMade in the U.S \\n\\nRemastered from the original analoque tapes by JAMES GUTHRIE, JOEL PLANTE and BERNIE GRUNDMAN\\n\\nPressed By information is not listed. Information is derived from runouts. \", \"identifiers\": [ { \"type\": \"Barcode\", \"description\": \"Scanned\", \"value\": \"888751842212\" }, { \"type\": \"Matrix / Runout\", \"description\": \"Runout, Side A\", \"value\": \"0190295997083-A BG 16908 1A\" }, { \"type\": \"Matrix / Runout\", \"description\": \"Runout, Side B\", \"value\": \"0190295997083-B BG 16908 1B\" } ], \"companies\": [ { \"name\": \"Pink Floyd Music Ltd.\", \"entity_type\": \"13\", \"catno\": \"\", \"resource_url\": \"https://api.discogs.com/labels/272650\", \"id\": 272650, \"entity_type_name\": \"Phonographic Copyright (p)\" }, { \"name\": \"Pink Floyd Music Ltd.\", \"entity_type\": \"14\", \"catno\": \"\", \"resource_url\": \"https://api.discogs.com/labels/272650\", \"id\": 272650, \"entity_type_name\": \"Copyright (c)\" }, { \"name\": \"Sony Music Entertainment\", \"entity_type\": \"8\", \"catno\": \"\", \"resource_url\": \"https://api.discogs.com/labels/29073\", \"id\": 29073, \"entity_type_name\": \"Marketed By\" }, { \"name\": \"Sony Music Entertainment\", \"entity_type\": \"9\", \"catno\": \"\", \"resource_url\": \"https://api.discogs.com/labels/29073\", \"id\": 29073, \"entity_type_name\": \"Distributed By\" }, { \"name\": \"Pink Floyd Music Publishers Ltd.\", \"entity_type\": \"21\", \"catno\": \"\", \"resource_url\": \"https://api.discogs.com/labels/276178\", \"id\": 276178, \"entity_type_name\": \"Published By\" }, { \"name\": \"Roger Waters Music Overseas Ltd.\", \"entity_type\": \"21\", \"catno\": \"\", \"resource_url\": \"https://api.discogs.com/labels/406408\", \"id\": 406408, \"entity_type_name\": \"Published By\" }, { \"name\": \"TRO-Hampshire House Publishing Corp.\", \"entity_type\": \"21\", \"catno\": \"\", \"resource_url\": \"https://api.discogs.com/labels/347248\", \"id\": 347248, \"entity_type_name\": \"Published By\" }, { \"name\": \"Lupus Music Co. Ltd.\", \"entity_type\": \"21\", \"catno\": \"\", \"resource_url\": \"https://api.discogs.com/labels/277461\", \"id\": 277461, \"entity_type_name\": \"Published By\" }, { \"name\": \"Abbey Road Studios\", \"entity_type\": \"23\", \"catno\": \"\", \"resource_url\": \"https://api.discogs.com/labels/217694\", \"id\": 217694, \"entity_type_name\": \"Recorded At\" }, { \"name\": \"Record Industry\", \"entity_type\": \"17\", \"catno\": \"16908\", \"resource_url\": \"https://api.discogs.com/labels/267164\", \"id\": 267164, \"entity_type_name\": \"Pressed By\" } ], \"uri\": \"https://www.discogs.com/Pink-Floyd-Atom-Heart-Mother/release/9093776\", \"formats\": [ { \"descriptions\": [ \"LP\", \"Album\", \"Reissue\", \"Remastered\", \"Stereo\" ], \"text\": \"180 Gram. Gatefold\", \"name\": \"Vinyl\", \"qty\": \"1\" } ], \"resource_url\": \"https://api.discogs.com/releases/9093776\", \"data_quality\": \"Needs Vote\" }"; 16 | private const string _ReleaseJSON5 = "{\"styles\": [\"Pop Rock\", \"Classic Rock\"], \"series\": [{\"name\": \"Fontana Special\", \"entity_type\": \"2\", \"catno\": \"\", \"resource_url\": \"https://api.discogs.com/labels/233498\", \"id\": 233498, \"entity_type_name\": \"Series\"}], \"labels\": [{\"name\": \"Fontana\", \"entity_type\": \"1\", \"catno\": \"6492 042\", \"resource_url\": \"https://api.discogs.com/labels/205\", \"id\": 205, \"entity_type_name\": \"Label\"}], \"year\": 1977, \"community\": {\"status\": \"Accepted\", \"rating\": {\"count\": 11, \"average\": 4.18}, \"have\": 65, \"contributors\": [{\"username\": \"marilen1965\", \"resource_url\": \"https://api.discogs.com/users/marilen1965\"}, {\"username\": \"les-plaisirs-demodes\", \"resource_url\": \"https://api.discogs.com/users/les-plaisirs-demodes\"}, {\"username\": \"turingrao\", \"resource_url\": \"https://api.discogs.com/users/turingrao\"}], \"want\": 8, \"submitter\": {\"username\": \"marilen1965\", \"resource_url\": \"https://api.discogs.com/users/marilen1965\"}, \"data_quality\": \"Needs Vote\"}, \"artists\": [{\"join\": \"\", \"name\": \"Le Orme\", \"anv\": \"\", \"tracks\": \"\", \"role\": \"\", \"resource_url\": \"https://api.discogs.com/artists/359000\", \"id\": 359000}], \"images\": [{\"uri\": \"\", \"height\": 611, \"width\": 600, \"resource_url\": \"\", \"type\": \"primary\", \"uri150\": \"\"}, {\"uri\": \"\", \"height\": 594, \"width\": 600, \"resource_url\": \"\", \"type\": \"secondary\", \"uri150\": \"\"}, {\"uri\": \"\", \"height\": 600, \"width\": 600, \"resource_url\": \"\", \"type\": \"secondary\", \"uri150\": \"\"}, {\"uri\": \"\", \"height\": 600, \"width\": 600, \"resource_url\": \"\", \"type\": \"secondary\", \"uri150\": \"\"}], \"format_quantity\": 1, \"id\": 2221110, \"artists_sort\": \"Le Orme\", \"genres\": [\"Rock\", \"Pop\"], \"thumb\": \"\", \"num_for_sale\": 9, \"title\": \"Le Orme Vol. 1\", \"date_changed\": \"2018-03-13T10:55:07-07:00\", \"lowest_price\": 3.52, \"status\": \"Accepted\", \"released_formatted\": \"30 Aug 1977\", \"estimated_weight\": 230, \"released\": \"1977-08-30\", \"date_added\": \"2010-04-07T09:20:58-07:00\", \"tracklist\": [{\"duration\": \"5:00\", \"position\": \"A1\", \"type_\": \"track\", \"title\": \"Era Inverno\"}, {\"duration\": \"4:00\", \"position\": \"A2\", \"type_\": \"track\", \"title\": \"Cemento Armato\"}, {\"duration\": \"4:42\", \"position\": \"A3\", \"type_\": \"track\", \"title\": \"Collage\"}, {\"duration\": \"4:12\", \"position\": \"A4\", \"type_\": \"track\", \"title\": \"Sguardo Verso Il Cielo\"}, {\"duration\": \"2:54\", \"position\": \"A5\", \"type_\": \"track\", \"title\": \"Gioco Di Bimba\"}, {\"duration\": \"7:28\", \"position\": \"B1\", \"type_\": \"track\", \"title\": \"La Porta Chiusa\"}, {\"duration\": \"3:48\", \"position\": \"B2\", \"type_\": \"track\", \"title\": \"Figure Di Cartone\"}, {\"duration\": \"3:08\", \"position\": \"B3\", \"type_\": \"track\", \"title\": \"Sera\"}, {\"duration\": \"3:30\", \"position\": \"B4\", \"type_\": \"track\", \"title\": \"Amico Di Ieri\"}], \"extraartists\": [{\"join\": \"\", \"name\": \"Gian Piero Reverberi\", \"anv\": \"\", \"tracks\": \"\", \"role\": \"Producer\", \"resource_url\": \"https://api.discogs.com/artists/281531\", \"id\": 281531}, {\"join\": \"\", \"name\": \"Aldo Tagliapietra\", \"anv\": \"\", \"tracks\": \"\", \"role\": \"Written-By, Lyrics By\", \"resource_url\": \"https://api.discogs.com/artists/701964\", \"id\": 701964}, {\"join\": \"\", \"name\": \"Tony Pagliuca\", \"anv\": \"\", \"tracks\": \"\", \"role\": \"Written-By, Lyrics By\", \"resource_url\": \"https://api.discogs.com/artists/1208005\", \"id\": 1208005}], \"country\": \"Italy\", \"notes\": \"Printed and Made in Italy.\", \"identifiers\": [{\"type\": \"Rights Society\", \"value\": \"S.I.A.E.\"}], \"companies\": [], \"uri\": \"https://www.discogs.com/Le-Orme-Le-Orme-Vol-1/release/2221110\", \"formats\": [{\"descriptions\": [\"LP\", \"Compilation\"], \"name\": \"Vinyl\", \"qty\": \"1\"}], \"resource_url\": \"https://api.discogs.com/releases/2221110\", \"data_quality\": \"Needs Vote\"}"; 17 | 18 | public static IEnumerable Data => new[] 19 | { 20 | new object[] { _ReleaseJSON }, 21 | new object[] { _ReleaseJSON2 } 22 | }; 23 | 24 | private readonly ITestOutputHelper _OutputHelper; 25 | public ReleaseDeserializationTest(ITestOutputHelper outputHelper) 26 | { 27 | _OutputHelper = outputHelper; 28 | } 29 | 30 | [Theory, MemberData(nameof(Data))] 31 | public void DeserializeResult_IsNotNull(string json) 32 | { 33 | var release = JsonConvert.DeserializeObject(json); 34 | release.Should().NotBeNull(); 35 | } 36 | 37 | [Fact] 38 | public void DeserializeResult_Deserialize_lowest_price() 39 | { 40 | var release = JsonConvert.DeserializeObject(_ReleaseJSON2); 41 | release.lowest_price.Should().Be(2.1591277124041888m); 42 | } 43 | 44 | [Fact] 45 | public void DeserializeResult_Deserialize_num_for_sale() 46 | { 47 | var release = JsonConvert.DeserializeObject(_ReleaseJSON2); 48 | release.num_for_sale.Should().Be(11); 49 | } 50 | 51 | [Fact] 52 | public void DeserializeResult_Deserialize_Track_Artists() 53 | { 54 | var release = JsonConvert.DeserializeObject(_ReleaseJSON2); 55 | release.tracklist[0].artists.Should().HaveCount(1); 56 | } 57 | 58 | [Fact] 59 | public void DeserializeResult_Deserialize_SubTracks() 60 | { 61 | var release = JsonConvert.DeserializeObject(_ReleaseJSON3); 62 | release.tracklist[0].sub_tracks[0].title.Should().Be("Father\'s Shout"); 63 | } 64 | 65 | [Fact] 66 | public void DeserializeResult_Deserialize_ExtraArtits_From_SubTracks() 67 | { 68 | var release = JsonConvert.DeserializeObject(_ReleaseJSON4); 69 | release.tracklist[0].sub_tracks[0].extraartists[0].name.Should().Be("David Gilmour"); 70 | } 71 | 72 | [Fact] 73 | public void DeserializeResult_Deserialize_Series() 74 | { 75 | var expected = new DiscogsReleaseLabel 76 | { 77 | name = "Fontana Special", 78 | entity_type = "2", 79 | catno = "", 80 | resource_url = "https://api.discogs.com/labels/233498", 81 | id=233498, 82 | entity_type_name = "Series" 83 | }; 84 | var release = JsonConvert.DeserializeObject(_ReleaseJSON5); 85 | release.series.Should().HaveCount(1); 86 | release.series[0].Should().BeEquivalentTo(expected); 87 | } 88 | 89 | [Fact] 90 | public void DeserializeResult_Deserialize_Artists_sort() 91 | { 92 | var release = JsonConvert.DeserializeObject(_ReleaseJSON5); 93 | release.artists_sort.Should().Be("Le Orme"); 94 | } 95 | 96 | [Fact] 97 | public void DeserializeResult_Deserialize_Text_Format() 98 | { 99 | var release = JsonConvert.DeserializeObject(_ReleaseJSON3); 100 | release.formats[0].text.Should().Be("Gatefold"); 101 | } 102 | } 103 | } 104 | --------------------------------------------------------------------------------