listenbrainz 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: aa91d4869adbba2530463a1a70dac945046de4f49701cda50e28fd3d87c243bb
4
- data.tar.gz: 921fbcd3b84c5cb3212fc713c8662f31a216784d6c874b5fddba0527c67f5a5b
3
+ metadata.gz: 24eb87f56c901614053a518a7f89dceac0f6ce6173198c57a589f644b930504c
4
+ data.tar.gz: 5f5a6f5d788ffcc43cd5eed5419188e3fdf596b3746df72b3791251242c7f506
5
5
  SHA512:
6
- metadata.gz: 6c32fdddb83cff2bbbcd74f36904ae4d8869cf5718cd4c05f0c6313afa9532b485b888965b828c72660a79316540ccecd670932aa9d30abc3d2ac4b63b47ff78
7
- data.tar.gz: 9b11e3008645817ba78d4d00aaa8322057e7d3da3dcfe4c842acdd44da3f46fa80a35b4e6e9f58c8e6be672281c70b6b289774fc0738a96c60748e4036c4b223
6
+ metadata.gz: f456a05f56fda45159f312cbb75587308879eb301611cb4e28b7039ea5252a3ee50899a7cd35e15d6fc11ab966e0144c036a8fe836925d02d47df859ae3750ec
7
+ data.tar.gz: 25e5a72d6b0b957482f5cda29a2f7809ff4767ee9f568c8034ad515aa05e09fe148db5f0a623e94a6fc41eff640cfb97b517aa4da1338e862c883e8fda91beda
@@ -0,0 +1,26 @@
1
+ # Bug report
2
+
3
+ /label ~bug
4
+
5
+ ## Context
6
+
7
+ - [ ] Ruby version:
8
+ - [ ] ListenBrainz version:
9
+
10
+ ## Steps to reproduce
11
+
12
+ - [ ] *Provide a Minimal, Verifiable, Complete Example (MVCE) highlighting the
13
+ problem.*
14
+
15
+ ```ruby
16
+ # Steps to reproduce
17
+ ```
18
+
19
+ ### Expected behavior
20
+
21
+ - [ ] *Describe what the MVCE should do.*
22
+
23
+ ### Actual behavior
24
+
25
+ - [ ] *Describe what the MVCE does, and highlight the difference with the
26
+ expected behavior.*
@@ -0,0 +1,20 @@
1
+ # User story
2
+
3
+ /label ~feature
4
+
5
+ ## Description
6
+
7
+ - [ ] *Describe the feature and its added value.*
8
+
9
+ As a user,
10
+ I want to ...
11
+ In order to...
12
+
13
+ ## Definition of Done
14
+
15
+ - [ ] *Describe the expected outcome of the feature.*
16
+ - [ ] *Include code examples of the expected syntax.*
17
+
18
+ ```ruby
19
+ # Add examples
20
+ ```
data/CHANGELOG.md CHANGED
@@ -8,6 +8,15 @@ The format is based on [Keep a Changelog][kac], and this project adheres to
8
8
  [kac]: https://keepachangelog.com/en/1.1.0/
9
9
  [semver]: https://semver.org/spec/v2.0.0.html
10
10
 
11
+ ## [0.2.0] - 2025-02-15
12
+
13
+ ### Added
14
+
15
+ - Added `Artist`
16
+ - Added `ArtistMap`
17
+ - Added `ReleaseGroup`
18
+ - Added `Recording`
19
+
11
20
  ## [0.1.0] - 2025-01-31
12
21
 
13
22
  - Initial release
data/README.md CHANGED
@@ -94,6 +94,66 @@ listen.submit(mode: :playing_now)
94
94
  ListenBrainz::Listen.sumbit([listen])
95
95
  ```
96
96
 
97
+ ### Retrieving artists
98
+
99
+ ```ruby
100
+ # Retrieve top artists for the current user
101
+ ListenBrainz::Artist.get
102
+ ListenBrainz::Artist.get(count: 5, offset: 10, range: :this_month)
103
+
104
+ # Retrieve top artists for a different user
105
+ ListenBrainz::Artist.get('Bobby')
106
+ ListenBrainz::Artist.get('Bobby', count: 5, offset: 10, range: :this_month)
107
+
108
+ # Retrieve site-wide top artists
109
+ ListenBrainz::Artist.sitewide
110
+ ListenBrainz::Artist.sitewide(count: 5, offset: 10, range: :this_month)
111
+
112
+ # Retrieve artist map for the current user
113
+ ListenBrainz::ArtistMap.get
114
+ ListenBrainz::ArtistMap.get(range: :this_week)
115
+
116
+ # Retrieve artist map for a different user
117
+ ListenBrainz::ArtistMap.get('Bobby')
118
+ ListenBrainz::ArtistMap.get('Bobby', range: :this_week)
119
+
120
+ # Retrieve site-wide artist map
121
+ ListenBrainz::ArtistMap.sitewide
122
+ ListenBrainz::ArtistMap.sitewide(range: :all_time)
123
+ ```
124
+
125
+ ### Retrieving release groups
126
+
127
+ ```ruby
128
+ # Retrieve top release groups for the current user
129
+ ListenBrainz::ReleaseGroup.get
130
+ ListenBrainz::ReleaseGroup.get(count: 5, offset: 10, range: :this_month)
131
+
132
+ # Retrieve top release groups for a different user
133
+ ListenBrainz::ReleaseGroup.get('Bobby')
134
+ ListenBrainz::ReleaseGroup.get('Bobby', count: 5, offset: 10, range: :this_month)
135
+
136
+ # Retrieve site-wide top release groups
137
+ ListenBrainz::ReleaseGroup.sitewide
138
+ ListenBrainz::ReleaseGroup.sitewide(count: 5, offset: 10, range: :this_year)
139
+ ```
140
+
141
+ ### Retrieving recordings
142
+
143
+ ```ruby
144
+ # Retrieve top recordings for the current user
145
+ ListenBrainz::Recording.get
146
+ ListenBrainz::Recording.get(count: 5, offset: 10, range: :all_time)
147
+
148
+ # Retrieve top recordings for a different user
149
+ ListenBrainz::Recording.get('Bobby')
150
+ ListenBrainz::Recording.get('Bobby', count: 5, offset: 10, range: :all_time)
151
+
152
+ # Retrieve site-wide top recordings
153
+ ListenBrainz::Recording.sitewide
154
+ ListenBrainz::Recording.sitewide(count: 5, offset: 10, range: :all_time)
155
+ ```
156
+
97
157
  ## Documentation
98
158
 
99
159
  A complete YARD documentation is available below.
data/Rakefile CHANGED
@@ -11,6 +11,8 @@ RuboCop::RakeTask.new
11
11
 
12
12
  require 'yard'
13
13
 
14
- YARD::Rake::YardocTask.new
14
+ YARD::Rake::YardocTask.new do |yard|
15
+ yard.files = ['-', 'CHANGELOG.md']
16
+ end
15
17
 
16
18
  task default: %i[spec rubocop yard]
@@ -0,0 +1,88 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ListenBrainz
4
+ ##
5
+ # Model class for artists.
6
+ #
7
+ # @see https://rain0r.github.io/listenbrainz-openapi/index.html#/lbStats/topArtistsForUser
8
+ class Artist < Base
9
+ ##
10
+ # Retrieves the top artists for a given user.
11
+ #
12
+ # @param [String] username
13
+ # @param [Integer, nil] count Number of artists to retrieve
14
+ # @param [Integer, nil] offset Number of artists to skip
15
+ # @param [Symbol, nil] range +all_time+, +month+, +week+, +year+, +quarter+,
16
+ # +half_yearly+, +this_week+, +this_month+ or +this_year+
17
+ #
18
+ # @return [Payload]
19
+ def self.get(
20
+ username = ListenBrainz.client.username, count: nil, offset: nil,
21
+ range: nil
22
+ )
23
+ params = { count:, offset:, range: }.compact
24
+ ListenBrainz.client.query(
25
+ :get, "1/stats/user/#{username}/artists", params:
26
+ ).fetch(:payload).then { Payload.new(_1) }
27
+ end
28
+
29
+ ##
30
+ # Retrieves site-wide top artists.
31
+ #
32
+ # @param [Integer, nil] count Number of artists to retrieve
33
+ # @param [Integer, nil] offset Number of artists to skip
34
+ # @param [Symbol, nil] range +all_time+, +month+, +week+, +year+, +quarter+,
35
+ # +half_yearly+, +this_week+, +this_month+ or +this_year+
36
+ #
37
+ # @return [Payload]
38
+ def self.sitewide(count: nil, offset: nil, range: nil)
39
+ params = { count:, offset:, range: }.compact
40
+ payload = ListenBrainz.client.query(
41
+ :get, '1/stats/sitewide/artists', params:
42
+ ).fetch(:payload)
43
+
44
+ # HACK: API is not consistent between site-wide and user schema.
45
+ payload[:total_artist_count] = payload[:count]
46
+ Payload.new(payload)
47
+ end
48
+
49
+ ##
50
+ # Model class for artist payloads.
51
+ #
52
+ # Contains the actual artists as well as additional metadata.
53
+ class Payload < Base
54
+ ##
55
+ # @!attribute [r] from_ts
56
+ # @return [Time]
57
+ attribute :from_ts, Types::Timestamp
58
+ ##
59
+ # @!attribute [r] to_ts
60
+ # @return [Time]
61
+ attribute :to_ts, Types::Timestamp
62
+ ##
63
+ # @!attribute [r] total_artist_count
64
+ # @return [Integer]
65
+ attribute :total_artist_count, Types::Integer
66
+
67
+ ##
68
+ # @!attribute [r] artists
69
+ # @return [Array<Artist>]
70
+ attribute :artists, Types::Array.of(Artist)
71
+ end
72
+
73
+ ##
74
+ # @!attribute [r] artist_mbid
75
+ # @return [String, nil]
76
+ attribute? :artist_mbid, Types::String.optional
77
+ alias mbid artist_mbid
78
+ ##
79
+ # @!attribute [r] artist_name
80
+ # @return [String]
81
+ attribute :artist_name, Types::String
82
+ alias name artist_name
83
+ ##
84
+ # @!attribute [r] listen_count
85
+ # @return [Integer]
86
+ attribute :listen_count, Types::Integer
87
+ end
88
+ end
@@ -0,0 +1,81 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ListenBrainz
4
+ ##
5
+ # Model class for artist maps.
6
+ class ArtistMap < Base
7
+ ##
8
+ # Retrieves the artist map for the given user.
9
+ #
10
+ # @param [String] username
11
+ # @param [Symbol, nil] range
12
+ #
13
+ # @return [Payload]
14
+ #
15
+ # @see https://rain0r.github.io/listenbrainz-openapi/index.html#/lbStats/artistMapForUser
16
+ def self.get(username = ListenBrainz.client.username, range: nil)
17
+ params = { range: }.compact
18
+
19
+ ListenBrainz.client.query(
20
+ :get, "1/stats/user/#{username}/artist-map", params:
21
+ ).fetch(:payload).then { Payload.new(_1) }
22
+ end
23
+
24
+ ##
25
+ # Retrieves the site-wide artist map.
26
+ #
27
+ # @param [Symbol, nil] range
28
+ #
29
+ # @return [Payload]
30
+ #
31
+ # @see https://rain0r.github.io/listenbrainz-openapi/index.html#/lbStats/sitewideArtistMap
32
+ def self.sitewide(range: nil)
33
+ params = { range: }.compact
34
+ ListenBrainz.client.query(
35
+ :get, '1/stats/sitewide/artist-map', params:
36
+ ).fetch(:payload).then { Payload.new(_1) }
37
+ end
38
+
39
+ ##
40
+ # Model class for artist map payloads.
41
+ class Payload < Base
42
+ ##
43
+ # @!attribute [r] from_ts
44
+ # @return [Time]
45
+ attribute :from_ts, Types::Timestamp
46
+ ##
47
+ # @!attribute [r] last_updated
48
+ # @return [Time]
49
+ attribute :last_updated, Types::Timestamp
50
+ ##
51
+ # @!attribute [r] to_ts
52
+ # @return [Time]
53
+ attribute :to_ts, Types::Timestamp
54
+
55
+ ##
56
+ # @!attribute [r] artist_map
57
+ # @return [Array<ArtistMap>]
58
+ attribute :artist_map, Types::Array.of(ArtistMap)
59
+ end
60
+
61
+ ##
62
+ # @!attribute [r] artist_count
63
+ # @return [Integer]
64
+ attribute :artist_count, Types::Integer
65
+ ##
66
+ # @!attribute [r] country
67
+ # ISO-3166-1 alpha-3 code of the country
68
+ # @return [String]
69
+ # @see https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3
70
+ attribute :country, Types::String
71
+ ##
72
+ # @!attribute [r] listen_count
73
+ # @return [Integer]
74
+ attribute :listen_count, Types::Integer
75
+
76
+ ##
77
+ # @!attribute [r] artists
78
+ # @return [Array<Artist>]
79
+ attribute :artists, Types::Array.of(Artist)
80
+ end
81
+ end
@@ -0,0 +1,101 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ListenBrainz
4
+ ##
5
+ # Model class for recordings.
6
+ class Recording < Base
7
+ ##
8
+ # Retrieves the top recordings for the given user.
9
+ #
10
+ # @param [String, nil] username
11
+ # @param [Integer, nil] count
12
+ # @param [Integer, nil] offset
13
+ # @param [Symbol, nil] range
14
+ #
15
+ # @return [Payload]
16
+ #
17
+ # @see https://rain0r.github.io/listenbrainz-openapi/index.html#/lbStats/topRecordingsForUser
18
+ def self.get(
19
+ username = ListenBrainz.client.username, count: nil, offset: nil,
20
+ range: nil
21
+ )
22
+ params = { count:, offset:, range: }.compact
23
+ ListenBrainz.client.query(
24
+ :get, "1/stats/user/#{username}/recordings", params:
25
+ ).fetch(:payload).then { Payload.new(_1) }
26
+ end
27
+
28
+ ##
29
+ # Retrieves the site-wide top recordings.
30
+ #
31
+ # @param [Integer, nil] count
32
+ # @param [Integer, nil] offset
33
+ # @param [Symbol, nil] range
34
+ #
35
+ # @return [Payload]
36
+ #
37
+ # @see https://rain0r.github.io/listenbrainz-openapi/index.html#/lbStats/sitewideTopRecordings
38
+ def self.sitewide(count: nil, offset: nil, range: nil)
39
+ params = { count:, offset:, range: }.compact
40
+ ListenBrainz.client.query(:get, '1/stats/sitewide/recordings', params:)
41
+ .fetch(:payload).then { Payload.new(_1) }
42
+ end
43
+
44
+ ##
45
+ # Model class for recording payloads.
46
+ class Payload < Base
47
+ ##
48
+ # @!attribute [r] from_ts
49
+ # @return [Time]
50
+ attribute :from_ts, Types::Timestamp
51
+ ##
52
+ # @!attribute [r] last_updated
53
+ # @return [Time]
54
+ attribute :last_updated, Types::Timestamp
55
+ ##
56
+ # @!attribute [r] to_ts
57
+ # @return [Time]
58
+ attribute :to_ts, Types::Timestamp
59
+ ##
60
+ # @!attribute [r] total_recording_count
61
+ # @return [Integer, nil]
62
+ attribute? :total_recording_count, Types::Integer
63
+
64
+ ##
65
+ # @!attribute [r] recordings
66
+ # @return [Array<Recording>]
67
+ attribute :recordings, Types::Array.of(Recording)
68
+ end
69
+
70
+ ##
71
+ # @!attribute [r] artist_mbids
72
+ # @return [Array<String>]
73
+ attribute :artist_mbids, Types::Array.of(Types::String)
74
+ ##
75
+ # @!attribute [r] artist_name
76
+ # @return [String]
77
+ attribute :artist_name, Types::String
78
+ ##
79
+ # @!attribute [r] listen_count
80
+ # @return [Integer]
81
+ attribute :listen_count, Types::Integer
82
+ ##
83
+ # @!attribute [r] recording_mbid
84
+ # @return [String, nil]
85
+ attribute? :recording_mbid, Types::String.optional
86
+ alias mbid recording_mbid
87
+ ##
88
+ # @!attribute [r] release_mbid
89
+ # @return [String]
90
+ attribute? :release_mbid, Types::String.optional
91
+ ##
92
+ # @!attribute [r] release_name
93
+ # @return [String]
94
+ attribute :release_name, Types::String
95
+ ##
96
+ # @!attribute [r] track_name
97
+ # @return [String]
98
+ attribute :track_name, Types::String
99
+ alias name track_name
100
+ end
101
+ end
@@ -0,0 +1,90 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ListenBrainz
4
+ ##
5
+ # Model class for release groups.
6
+ class ReleaseGroup < Base
7
+ ##
8
+ # Retrieves the top release groups for the given user.
9
+ #
10
+ # @param [String, nil] username
11
+ # @param [Integer, nil] count
12
+ # @param [Integer, nil] offset
13
+ # @param [Symbol, nil] range
14
+ #
15
+ # @return [Payload]
16
+ #
17
+ # @see https://rain0r.github.io/listenbrainz-openapi/index.html#/lbStats/topReleaseGroupsForUser
18
+ def self.get(
19
+ username = ListenBrainz.client.username, count: nil, offset: nil,
20
+ range: nil
21
+ )
22
+ params = { count:, offset:, range: }.compact
23
+ ListenBrainz.client.query(
24
+ :get, "1/stats/user/#{username}/release-groups", params:
25
+ ).fetch(:payload).then { Payload.new(_1) }
26
+ end
27
+
28
+ ##
29
+ # Retrieves site-wide top release groups.
30
+ #
31
+ # @param [Integer, nil] count
32
+ # @param [Integer, nil] offset
33
+ # @param [Symbol, nil] range
34
+ #
35
+ # @return [Payload]
36
+ #
37
+ # @see https://rain0r.github.io/listenbrainz-openapi/index.html#/lbStats/sitewideTopReleaseGroups
38
+ def self.sitewide(count: nil, offset: nil, range: nil)
39
+ params = { count:, offset:, range: }.compact
40
+ ListenBrainz.client.query(
41
+ :get, '1/stats/sitewide/release-groups', params:
42
+ ).fetch(:payload).then { Payload.new(_1) }
43
+ end
44
+
45
+ ##
46
+ # Model class for release group payloads.
47
+ class Payload < Base
48
+ ##
49
+ # @!attribute [r] from_ts
50
+ # @return [Time]
51
+ attribute :from_ts, Types::Timestamp
52
+ ##
53
+ # @!attribute [r] last_updated
54
+ # @return [Time]
55
+ attribute :last_updated, Types::Timestamp
56
+ ##
57
+ # @!attribute [r] to_ts
58
+ # @return [Time]
59
+ attribute :to_ts, Types::Timestamp
60
+
61
+ ##
62
+ # @!attribute [r] release_groups
63
+ # @return [Array<ReleaseGroup>]
64
+ attribute :release_groups, Types::Array.of(ReleaseGroup)
65
+ end
66
+
67
+ ##
68
+ # @!attribute [r] artist_mbids
69
+ # @return [Array<String>]
70
+ attribute :artist_mbids, Types::Array.of(Types::String)
71
+ ##
72
+ # @!attribute [r] artist_name
73
+ # @return [String]
74
+ attribute :artist_name, Types::String
75
+ ##
76
+ # @!attribute [r] listen_count
77
+ # @return [Integer]
78
+ attribute :listen_count, Types::Integer
79
+ ##
80
+ # @!attribute [r] release_group_mbid
81
+ # @return [String, nil]
82
+ attribute? :release_group_mbid, Types::String.optional
83
+ alias mbid release_group_mbid
84
+ ##
85
+ # @!attribute [r] release_group_name
86
+ # @return [String, nil]
87
+ attribute? :release_group_name, Types::String.optional
88
+ alias name release_group_name
89
+ end
90
+ end
@@ -5,4 +5,9 @@ module ListenBrainz; end # :nodoc:
5
5
  require_relative 'models/base'
6
6
  require_relative 'models/types'
7
7
 
8
+ require_relative 'models/artist'
8
9
  require_relative 'models/listen'
10
+ require_relative 'models/recording'
11
+ require_relative 'models/release_group'
12
+
13
+ require_relative 'models/artist_map'
@@ -3,5 +3,5 @@
3
3
  module ListenBrainz
4
4
  ##
5
5
  # Current version of the gem.
6
- VERSION = '0.1.0'
6
+ VERSION = '0.2.0'
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: listenbrainz
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Richard Degenne
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2025-02-01 00:00:00.000000000 Z
11
+ date: 2025-02-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: dry-struct
@@ -47,6 +47,8 @@ extra_rdoc_files: []
47
47
  files:
48
48
  - ".gitignore"
49
49
  - ".gitlab-ci.yml"
50
+ - ".gitlab/issue_templates/Bug Report.md"
51
+ - ".gitlab/issue_templates/User Story.md"
50
52
  - ".rspec"
51
53
  - ".rubocop.yml"
52
54
  - ".ruby-version"
@@ -61,8 +63,12 @@ files:
61
63
  - lib/listenbrainz/client.rb
62
64
  - lib/listenbrainz/configuration.rb
63
65
  - lib/listenbrainz/models.rb
66
+ - lib/listenbrainz/models/artist.rb
67
+ - lib/listenbrainz/models/artist_map.rb
64
68
  - lib/listenbrainz/models/base.rb
65
69
  - lib/listenbrainz/models/listen.rb
70
+ - lib/listenbrainz/models/recording.rb
71
+ - lib/listenbrainz/models/release_group.rb
66
72
  - lib/listenbrainz/models/types.rb
67
73
  - lib/listenbrainz/version.rb
68
74
  - listenbrainz.code-workspace