1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
use super::{Include, Relationship, Subquery};
use crate::date_format;
use crate::entity::alias::Alias;
use crate::entity::artist_credit::ArtistCredit;
use crate::entity::genre::Genre;
use crate::entity::rating::Rating;
use crate::entity::relations::Relation;
use crate::entity::release::Release;
use crate::entity::tag::Tag;
use crate::entity::BrowseBy;
use chrono::NaiveDate;
use lucene_query_builder::QueryBuilder;
use serde::{Deserialize, Serialize};

/// A release group, just as the name suggests, is used to group several different releases into a
/// single logical entity. Every release belongs to one, and only one release group.
#[derive(Debug, Default, Serialize, Deserialize, PartialEq, Clone)]
#[serde(rename_all(deserialize = "kebab-case"))]
#[serde(default)]
pub struct ReleaseGroup {
    /// See [MusicBrainz Identifier](https://musicbrainz.org/doc/MusicBrainz_Identifier).
    pub id: String,

    pub primary_type_id: Option<String>,

    /// The type describes what kind of releases the release group represents, for example album,
    /// single, soundtrack, compilation etc.
    /// See the Type subpage for a full list of release group types.
    pub primary_type: Option<ReleaseGroupPrimaryType>,

    pub secondary_type_ids: Vec<String>,
    pub secondary_types: Vec<ReleaseGroupSecondaryType>,

    #[serde(deserialize_with = "date_format::deserialize_opt")]
    pub first_release_date: Option<NaiveDate>,

    /// The title of a release group is usually very similar, if not the same, as the titles of the
    /// releases contained within it.
    pub title: String,
    /// The disambiguation comments are fields in the database used to help distinguish identically
    /// named artists, labels and other entities.
    pub disambiguation: String,
    /// Relationships are a way to represent all the different ways in which entities are connected
    /// to each other and to URLs outside MusicBrainz.
    pub relations: Option<Vec<Relation>>,
    /// Artist credits indicate who is the main credited artist (or artists) for releases, release
    /// groups, tracks and recordings, and how they are credited..
    pub artist_credit: Option<Vec<ArtistCredit>>,
    /// Releases present in this release group.
    pub releases: Option<Vec<Release>>,
    pub tags: Option<Vec<Tag>>,
    pub rating: Option<Rating>,
    /// Aliases are alternate names for a release group.
    pub aliases: Option<Vec<Alias>>,
    /// Genres are currently supported in MusicBrainz as part of the tag system.
    pub genres: Option<Vec<Genre>>,
    /// Annotations are text fields, functioning like a miniature wiki, that can be added to any
    /// existing artists, labels, recordings, releases, release groups and works.
    pub annotation: Option<String>,
}

/// The primary type of a MusicBrainz release group.
/// Note that this enum is `non_exhaustive`; The list of release types is subject to change and
/// these changes are only reflected in the DB, not in actual MB code.
/// Variants are derived from the `release_group_primary_type` table in the MusicBrainz database.
#[non_exhaustive]
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)]
pub enum ReleaseGroupPrimaryType {
    Album,
    Single,
    #[serde(rename = "EP")]
    Ep,
    Broadcast,
    Other,
    /// Any release_group_primary_type that does not yet have a corresponding variant in this enum.
    /// If you ever see a `ReleaseGroupPrimaryType::UnrecognizedReleaseGroupPrimaryType` in the wild, let us know and file an issue/pull request!
    #[serde(other)]
    UnrecognizedReleaseGroupPrimaryType,
}

/// The secondary type of a MusicBrainz release group entity.
/// Note that this enum is `non_exhaustive`; The list of release types is subject to change and
/// these changes are only reflected in the DB, not in actual MB code.
/// Variants are derived from the `release_group_secondary_type` table in the MusicBrainz database.
#[non_exhaustive]
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)]
pub enum ReleaseGroupSecondaryType {
    #[serde(rename = "Audio drama")]
    AudioDrama,
    Audiobook,
    Compilation,
    #[serde(rename = "DJ-mix")]
    DjMix,
    Demo,
    Interview,
    Live,
    #[serde(rename = "Mixtape/Street")]
    MixtapeStreet,
    Remix,
    Soundtrack,
    Spokenword,
    /// Any release_group_secondary_type that does not yet have a corresponding variant in this enum.
    /// If you ever see a `ReleaseGroupSecondaryType::UnrecognizedReleaseGroupSecondaryType` in the wild, let us know and file an issue/pull request!
    #[serde(other)]
    UnrecognizedReleaseGroupSecondaryType,
}

#[derive(Debug, QueryBuilder, Default)]
pub struct ReleaseGroupSearchQuery {
    /// (part of) any alias attached to the release group (diacritics are ignored)
    pub alias: String,
    /// the MBID of any of the release group artists
    pub arid: String,
    /// (part of) the combined credited artist name for the release group, including join phrases (e.g. "Artist X feat.")
    pub artist: String,
    /// (part of) the name of any of the release group artists
    #[query_builder_field = "artistname"]
    pub artist_name: String,
    /// (part of) the release group's disambiguation comment
    pub comment: String,
    /// (part of) the credited name of any of the release group artists on this particular release group
    #[query_builder_field = "creditname"]
    pub credit_name: String,
    /// the release date of the earliest release in this release group (e.g. "1980-01-22")
    #[query_builder_field = "firstreleasedate"]
    pub first_release_date: String,
    /// the primary type of the release group
    #[query_builder_field = "primarytype"]
    pub primary_type: String,
    /// the MBID of any of the releases in the release group
    pub reid: String,
    /// (part of) the title of any of the releases in the release group
    pub release: String,
    /// (part of) the release group's title (diacritics are ignored)
    #[query_builder_field = "releasegroup"]
    pub release_group: String,
    /// (part of) the release group's title (with the specified diacritics)
    #[query_builder_field = "releasegroupaccent"]
    pub release_group_accent: String,
    /// the number of releases in the release group
    pub releases: String,
    /// the release group's MBID
    pub rgid: String,
    /// any of the secondary types of the release group
    #[query_builder_field = "secondarytype"]
    pub secondary_type: String,
    /// the status of any of the releases in the release group
    pub status: String,
    /// the status of any of the releases in the release group
    pub tag: String,
    /// legacy release group type field that predates the ability to set multiple types (see calculation code)
    #[query_builder_field = "type"]
    pub release_type: String,
}

impl_browse! {
ReleaseGroup,
   (by_artist, BrowseBy::Artist),
   (by_release, BrowseBy::Release),
   (by_collection, BrowseBy::Collection)
}

impl_includes!(
    ReleaseGroup,
    (
        with_release_group_relations,
        Include::Relationship(Relationship::ReleaseGroup)
    ),
    (
        with_series_relations,
        Include::Relationship(Relationship::Series)
    ),
    (with_url_relations, Include::Relationship(Relationship::Url)),
    (with_artists, Include::Subquery(Subquery::Artists)),
    (with_releases, Include::Subquery(Subquery::Releases)),
    (with_tags, Include::Subquery(Subquery::Tags)),
    (with_aliases, Include::Subquery(Subquery::Aliases)),
    (with_genres, Include::Subquery(Subquery::Genres)),
    (with_ratings, Include::Subquery(Subquery::Rating)),
    (with_annotations, Include::Subquery(Subquery::Annotations))
);