rocksky 0.3.0 → 0.4.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 +4 -4
- data/README.md +43 -199
- data/lib/rocksky/manifest.json +5 -0
- data/lib/rocksky/native.rb +114 -0
- data/lib/rocksky/version.rb +3 -1
- data/lib/rocksky.rb +130 -28
- data/rocksky.gemspec +7 -3
- metadata +7 -25
- data/lib/rocksky/client.rb +0 -84
- data/lib/rocksky/error.rb +0 -58
- data/lib/rocksky/generated/types.rb +0 -219
- data/lib/rocksky/http.rb +0 -123
- data/lib/rocksky/resources/actor.rb +0 -60
- data/lib/rocksky/resources/album.rb +0 -22
- data/lib/rocksky/resources/apikey.rb +0 -28
- data/lib/rocksky/resources/artist.rb +0 -40
- data/lib/rocksky/resources/base.rb +0 -24
- data/lib/rocksky/resources/charts.rb +0 -33
- data/lib/rocksky/resources/feed.rb +0 -53
- data/lib/rocksky/resources/graph.rb +0 -34
- data/lib/rocksky/resources/like.rb +0 -26
- data/lib/rocksky/resources/mirror.rb +0 -22
- data/lib/rocksky/resources/player.rb +0 -73
- data/lib/rocksky/resources/playlist.rb +0 -45
- data/lib/rocksky/resources/scrobble.rb +0 -36
- data/lib/rocksky/resources/shout.rb +0 -58
- data/lib/rocksky/resources/song.rb +0 -38
- data/lib/rocksky/resources/spotify.rb +0 -37
- data/lib/rocksky/resources/stats.rb +0 -16
data/lib/rocksky/client.rb
DELETED
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
module Rocksky
|
|
2
|
-
# Top-level client for the Rocksky XRPC API.
|
|
3
|
-
#
|
|
4
|
-
# client = Rocksky.new(token: ENV["ROCKSKY_TOKEN"])
|
|
5
|
-
# client.actor.get_profile(did: "alice.bsky.social")
|
|
6
|
-
#
|
|
7
|
-
# Resources are lazily instantiated and memoised: `client.actor`, `client.album`,
|
|
8
|
-
# `client.artist`, `client.scrobble`, etc.
|
|
9
|
-
class Client
|
|
10
|
-
DEFAULT_BASE_URL = "https://api.rocksky.app".freeze
|
|
11
|
-
|
|
12
|
-
attr_reader :base_url, :token, :headers, :user_agent,
|
|
13
|
-
:open_timeout, :read_timeout
|
|
14
|
-
|
|
15
|
-
def initialize(
|
|
16
|
-
base_url: nil,
|
|
17
|
-
token: nil,
|
|
18
|
-
headers: {},
|
|
19
|
-
user_agent: "rocksky-ruby/#{Rocksky::VERSION}",
|
|
20
|
-
open_timeout: HTTP::DEFAULT_OPEN_TIMEOUT,
|
|
21
|
-
read_timeout: HTTP::DEFAULT_READ_TIMEOUT
|
|
22
|
-
)
|
|
23
|
-
@base_url = normalize_base_url(base_url || ENV["ROCKSKY_BASE_URL"] || DEFAULT_BASE_URL)
|
|
24
|
-
@token = token || ENV["ROCKSKY_TOKEN"]
|
|
25
|
-
@headers = headers.dup
|
|
26
|
-
@user_agent = user_agent
|
|
27
|
-
@open_timeout = open_timeout
|
|
28
|
-
@read_timeout = read_timeout
|
|
29
|
-
@http = HTTP.new(self)
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
# Return a derived client that uses the given token (everything else copied).
|
|
33
|
-
# Handy for sharing one client across users in a request-scoped server.
|
|
34
|
-
def with_token(new_token)
|
|
35
|
-
self.class.new(
|
|
36
|
-
base_url: base_url,
|
|
37
|
-
token: new_token,
|
|
38
|
-
headers: headers,
|
|
39
|
-
user_agent: user_agent,
|
|
40
|
-
open_timeout: open_timeout,
|
|
41
|
-
read_timeout: read_timeout
|
|
42
|
-
)
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
# ---- Raw XRPC access ---------------------------------------------------
|
|
46
|
-
|
|
47
|
-
def query(nsid, **params)
|
|
48
|
-
@http.query(nsid, params)
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
def procedure(nsid, params: {}, body: nil)
|
|
52
|
-
@http.procedure(nsid, params, body)
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
# ---- Resource accessors ------------------------------------------------
|
|
56
|
-
|
|
57
|
-
def actor; @actor ||= Resources::Actor.new(@http); end
|
|
58
|
-
def album; @album ||= Resources::Album.new(@http); end
|
|
59
|
-
def apikey; @apikey ||= Resources::Apikey.new(@http); end
|
|
60
|
-
def artist; @artist ||= Resources::Artist.new(@http); end
|
|
61
|
-
def charts; @charts ||= Resources::Charts.new(@http); end
|
|
62
|
-
def feed; @feed ||= Resources::Feed.new(@http); end
|
|
63
|
-
def graph; @graph ||= Resources::Graph.new(@http); end
|
|
64
|
-
def like; @like ||= Resources::Like.new(@http); end
|
|
65
|
-
def mirror; @mirror ||= Resources::Mirror.new(@http); end
|
|
66
|
-
def player; @player ||= Resources::Player.new(@http); end
|
|
67
|
-
def playlist; @playlist ||= Resources::Playlist.new(@http); end
|
|
68
|
-
def scrobble; @scrobble ||= Resources::Scrobble.new(@http); end
|
|
69
|
-
def shout; @shout ||= Resources::Shout.new(@http); end
|
|
70
|
-
def song; @song ||= Resources::Song.new(@http); end
|
|
71
|
-
def spotify; @spotify ||= Resources::Spotify.new(@http); end
|
|
72
|
-
def stats; @stats ||= Resources::Stats.new(@http); end
|
|
73
|
-
|
|
74
|
-
def inspect
|
|
75
|
-
"#<Rocksky::Client base_url=#{base_url.inspect} token=#{token ? "[FILTERED]" : nil.inspect}>"
|
|
76
|
-
end
|
|
77
|
-
|
|
78
|
-
private
|
|
79
|
-
|
|
80
|
-
def normalize_base_url(url)
|
|
81
|
-
url.to_s.sub(%r{/+\z}, "")
|
|
82
|
-
end
|
|
83
|
-
end
|
|
84
|
-
end
|
data/lib/rocksky/error.rb
DELETED
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
module Rocksky
|
|
2
|
-
class Error < StandardError
|
|
3
|
-
attr_reader :status, :body, :nsid
|
|
4
|
-
|
|
5
|
-
def initialize(message, status: nil, body: nil, nsid: nil)
|
|
6
|
-
super(message)
|
|
7
|
-
@status = status
|
|
8
|
-
@body = body
|
|
9
|
-
@nsid = nsid
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
def self.from_response(status, body, nsid: nil)
|
|
13
|
-
message = extract_message(body) || "request failed"
|
|
14
|
-
klass = klass_for(status)
|
|
15
|
-
klass.new(message, status: status, body: body, nsid: nsid)
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
def self.from_transport(cause, nsid: nil)
|
|
19
|
-
TransportError.new(
|
|
20
|
-
"transport error: #{cause.class}: #{cause.message}",
|
|
21
|
-
body: nil,
|
|
22
|
-
nsid: nsid
|
|
23
|
-
)
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
def self.klass_for(status)
|
|
27
|
-
case status
|
|
28
|
-
when 400 then BadRequest
|
|
29
|
-
when 401 then Unauthorized
|
|
30
|
-
when 403 then Forbidden
|
|
31
|
-
when 404 then NotFound
|
|
32
|
-
when 429 then RateLimited
|
|
33
|
-
when 500..599 then ServerError
|
|
34
|
-
else HTTPError
|
|
35
|
-
end
|
|
36
|
-
end
|
|
37
|
-
private_class_method :klass_for
|
|
38
|
-
|
|
39
|
-
def self.extract_message(body)
|
|
40
|
-
case body
|
|
41
|
-
when Hash
|
|
42
|
-
body["message"] || body["error"] || body[:message] || body[:error]
|
|
43
|
-
when String
|
|
44
|
-
body unless body.empty?
|
|
45
|
-
end
|
|
46
|
-
end
|
|
47
|
-
private_class_method :extract_message
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
class HTTPError < Error; end
|
|
51
|
-
class BadRequest < HTTPError; end
|
|
52
|
-
class Unauthorized < HTTPError; end
|
|
53
|
-
class Forbidden < HTTPError; end
|
|
54
|
-
class NotFound < HTTPError; end
|
|
55
|
-
class RateLimited < HTTPError; end
|
|
56
|
-
class ServerError < HTTPError; end
|
|
57
|
-
class TransportError < Error; end
|
|
58
|
-
end
|
|
@@ -1,219 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
# AUTO-GENERATED FILE -- DO NOT EDIT.
|
|
3
|
-
# Source: apps/api/lexicons/**/*.json
|
|
4
|
-
# Regenerate via: bun run lexgen:types
|
|
5
|
-
|
|
6
|
-
module Rocksky
|
|
7
|
-
module Generated
|
|
8
|
-
BlobRef = Struct.new(:type, :ref, :mimeType, :size, keyword_init: true)
|
|
9
|
-
|
|
10
|
-
ActorArtistViewBasic = Struct.new(:id, :name, :picture, :uri, :user1Rank, :user2Rank, :weight, keyword_init: true)
|
|
11
|
-
ActorCompatibilityViewBasic = Struct.new(:compatibilityLevel, :compatibilityPercentage, :sharedArtists, :topSharedArtistNames, :topSharedDetailedArtists, :user1ArtistCount, :user2ArtistCount, keyword_init: true)
|
|
12
|
-
ActorNeighbourViewBasic = Struct.new(:userId, :did, :handle, :displayName, :avatar, :sharedArtistsCount, :similarityScore, :topSharedArtistNames, :topSharedArtistsDetails, keyword_init: true)
|
|
13
|
-
ActorProfileViewBasic = Struct.new(:id, :did, :handle, :displayName, :avatar, :createdAt, :updatedAt, keyword_init: true)
|
|
14
|
-
ActorProfileViewDetailed = Struct.new(:id, :did, :handle, :displayName, :avatar, :createdAt, :updatedAt, keyword_init: true)
|
|
15
|
-
ActorTrackView = Struct.new(:name, :artist, :album, :albumCoverUrl, :durationMs, :source, :recordingMbId, keyword_init: true)
|
|
16
|
-
AddDirectoryToQueueParams = Struct.new(:playerId, :directory, :position, :shuffle, keyword_init: true)
|
|
17
|
-
AddItemsToQueueParams = Struct.new(:playerId, :items, :position, :shuffle, keyword_init: true)
|
|
18
|
-
AlbumRecord = Struct.new(:title, :artist, :duration, :releaseDate, :year, :genre, :albumArt, :albumArtUrl, :tags, :youtubeLink, :spotifyLink, :tidalLink, :appleMusicLink, :createdAt, keyword_init: true)
|
|
19
|
-
AlbumViewBasic = Struct.new(:id, :uri, :title, :artist, :artistUri, :year, :albumArt, :releaseDate, :sha256, :playCount, :uniqueListeners, keyword_init: true)
|
|
20
|
-
AlbumViewDetailed = Struct.new(:id, :uri, :title, :artist, :artistUri, :year, :albumArt, :releaseDate, :sha256, :playCount, :uniqueListeners, :tags, :tracks, keyword_init: true)
|
|
21
|
-
ApiKeyView = Struct.new(:id, :name, :description, :createdAt, keyword_init: true)
|
|
22
|
-
ArtistListenerViewBasic = Struct.new(:id, :did, :handle, :displayName, :avatar, :mostListenedSong, :totalPlays, :rank, keyword_init: true)
|
|
23
|
-
ArtistMbid = Struct.new(:mbid, :name, keyword_init: true)
|
|
24
|
-
ArtistRecentListenerView = Struct.new(:id, :did, :handle, :displayName, :avatar, :timestamp, :scrobbleUri, keyword_init: true)
|
|
25
|
-
ArtistRecord = Struct.new(:name, :bio, :picture, :pictureUrl, :tags, :born, :died, :bornIn, :createdAt, keyword_init: true)
|
|
26
|
-
ArtistSongViewBasic = Struct.new(:uri, :title, :playCount, keyword_init: true)
|
|
27
|
-
ArtistViewBasic = Struct.new(:id, :uri, :name, :picture, :sha256, :playCount, :uniqueListeners, :tags, keyword_init: true)
|
|
28
|
-
ArtistViewDetailed = Struct.new(:id, :uri, :name, :picture, :sha256, :playCount, :uniqueListeners, :tags, keyword_init: true)
|
|
29
|
-
ChartsScrobbleViewBasic = Struct.new(:date, :count, keyword_init: true)
|
|
30
|
-
ChartsView = Struct.new(:scrobbles, keyword_init: true)
|
|
31
|
-
CreateApikeyInput = Struct.new(:name, :description, keyword_init: true)
|
|
32
|
-
CreatePlaylistParams = Struct.new(:name, :description, keyword_init: true)
|
|
33
|
-
CreateScrobbleInput = Struct.new(:title, :artist, :album, :duration, :mbId, :isrc, :albumArt, :trackNumber, :releaseDate, :year, :discNumber, :lyrics, :composer, :copyrightMessage, :label, :artistPicture, :spotifyLink, :lastfmLink, :tidalLink, :appleMusicLink, :youtubeLink, :deezerLink, :timestamp, keyword_init: true)
|
|
34
|
-
CreateShoutInput = Struct.new(:message, keyword_init: true)
|
|
35
|
-
CreateSongInput = Struct.new(:title, :artist, :albumArtist, :album, :duration, :mbId, :isrc, :albumArt, :trackNumber, :releaseDate, :year, :discNumber, :lyrics, keyword_init: true)
|
|
36
|
-
DescribeFeedGeneratorOutput = Struct.new(:did, :feeds, keyword_init: true)
|
|
37
|
-
DescribeFeedGeneratorParams = Struct.new(keyword_init: true)
|
|
38
|
-
DislikeShoutInput = Struct.new(:uri, keyword_init: true)
|
|
39
|
-
DislikeSongInput = Struct.new(:uri, keyword_init: true)
|
|
40
|
-
DownloadFileParams = Struct.new(:fileId, keyword_init: true)
|
|
41
|
-
DropboxFileListView = Struct.new(:files, keyword_init: true)
|
|
42
|
-
DropboxFileView = Struct.new(:id, :name, :pathLower, :pathDisplay, :clientModified, :serverModified, keyword_init: true)
|
|
43
|
-
DropboxTemporaryLinkView = Struct.new(:link, keyword_init: true)
|
|
44
|
-
FeedGeneratorsView = Struct.new(:feeds, keyword_init: true)
|
|
45
|
-
FeedGeneratorView = Struct.new(:id, :name, :description, :uri, :avatar, :creator, keyword_init: true)
|
|
46
|
-
FeedItemView = Struct.new(:scrobble, keyword_init: true)
|
|
47
|
-
FeedRecommendationsView = Struct.new(:recommendations, :cursor, keyword_init: true)
|
|
48
|
-
FeedRecommendationView = Struct.new(:title, :artist, :album, :albumArt, :trackUri, :artistUri, :albumUri, :genres, :recommendationScore, :source, :likesCount, keyword_init: true)
|
|
49
|
-
FeedRecommendedAlbumsView = Struct.new(:albums, :cursor, keyword_init: true)
|
|
50
|
-
FeedRecommendedAlbumView = Struct.new(:id, :uri, :title, :artist, :artistUri, :year, :albumArt, :recommendationScore, :source, keyword_init: true)
|
|
51
|
-
FeedRecommendedArtistsView = Struct.new(:artists, :cursor, keyword_init: true)
|
|
52
|
-
FeedRecommendedArtistView = Struct.new(:id, :uri, :name, :picture, :genres, :recommendationScore, :source, keyword_init: true)
|
|
53
|
-
FeedSearchResultsView = Struct.new(:hits, :processingTimeMs, :limit, :offset, :estimatedTotalHits, keyword_init: true)
|
|
54
|
-
FeedStoriesView = Struct.new(:stories, keyword_init: true)
|
|
55
|
-
FeedStoryView = Struct.new(:album, :albumArt, :albumArtist, :albumUri, :artist, :artistUri, :avatar, :createdAt, :did, :handle, :id, :title, :trackId, :trackUri, :uri, keyword_init: true)
|
|
56
|
-
FeedUriView = Struct.new(:uri, keyword_init: true)
|
|
57
|
-
FeedView = Struct.new(:feed, :cursor, keyword_init: true)
|
|
58
|
-
FollowAccountOutput = Struct.new(:subject, :followers, :cursor, keyword_init: true)
|
|
59
|
-
FollowAccountParams = Struct.new(:account, keyword_init: true)
|
|
60
|
-
FollowRecord = Struct.new(:createdAt, :subject, :via, keyword_init: true)
|
|
61
|
-
GeneratorRecord = Struct.new(:did, :avatar, :displayName, :description, :createdAt, keyword_init: true)
|
|
62
|
-
GetActorAlbumsOutput = Struct.new(:albums, keyword_init: true)
|
|
63
|
-
GetActorAlbumsParams = Struct.new(:did, :limit, :offset, :startDate, :endDate, keyword_init: true)
|
|
64
|
-
GetActorArtistsOutput = Struct.new(:artists, keyword_init: true)
|
|
65
|
-
GetActorArtistsParams = Struct.new(:did, :limit, :offset, :startDate, :endDate, keyword_init: true)
|
|
66
|
-
GetActorCompatibilityOutput = Struct.new(:compatibility, keyword_init: true)
|
|
67
|
-
GetActorCompatibilityParams = Struct.new(:did, keyword_init: true)
|
|
68
|
-
GetActorLovedSongsOutput = Struct.new(:tracks, keyword_init: true)
|
|
69
|
-
GetActorLovedSongsParams = Struct.new(:did, :limit, :offset, keyword_init: true)
|
|
70
|
-
GetActorNeighboursOutput = Struct.new(:neighbours, keyword_init: true)
|
|
71
|
-
GetActorNeighboursParams = Struct.new(:did, keyword_init: true)
|
|
72
|
-
GetActorPlaylistsOutput = Struct.new(:playlists, keyword_init: true)
|
|
73
|
-
GetActorPlaylistsParams = Struct.new(:did, :limit, :offset, keyword_init: true)
|
|
74
|
-
GetActorScrobblesOutput = Struct.new(:scrobbles, keyword_init: true)
|
|
75
|
-
GetActorScrobblesParams = Struct.new(:did, :limit, :offset, keyword_init: true)
|
|
76
|
-
GetActorSongsOutput = Struct.new(:songs, keyword_init: true)
|
|
77
|
-
GetActorSongsParams = Struct.new(:did, :limit, :offset, :startDate, :endDate, keyword_init: true)
|
|
78
|
-
GetAlbumParams = Struct.new(:uri, keyword_init: true)
|
|
79
|
-
GetAlbumRecommendationsParams = Struct.new(:did, :limit, keyword_init: true)
|
|
80
|
-
GetAlbumShoutsOutput = Struct.new(:shouts, keyword_init: true)
|
|
81
|
-
GetAlbumShoutsParams = Struct.new(:uri, :limit, :offset, keyword_init: true)
|
|
82
|
-
GetAlbumsOutput = Struct.new(:albums, keyword_init: true)
|
|
83
|
-
GetAlbumsParams = Struct.new(:limit, :offset, :genre, keyword_init: true)
|
|
84
|
-
GetAlbumTracksOutput = Struct.new(:tracks, keyword_init: true)
|
|
85
|
-
GetAlbumTracksParams = Struct.new(:uri, keyword_init: true)
|
|
86
|
-
GetApikeysOutput = Struct.new(:apiKeys, keyword_init: true)
|
|
87
|
-
GetApikeysParams = Struct.new(:offset, :limit, keyword_init: true)
|
|
88
|
-
GetArtistAlbumsOutput = Struct.new(:albums, keyword_init: true)
|
|
89
|
-
GetArtistAlbumsParams = Struct.new(:uri, keyword_init: true)
|
|
90
|
-
GetArtistListenersOutput = Struct.new(:listeners, keyword_init: true)
|
|
91
|
-
GetArtistListenersParams = Struct.new(:uri, :offset, :limit, keyword_init: true)
|
|
92
|
-
GetArtistParams = Struct.new(:uri, keyword_init: true)
|
|
93
|
-
GetArtistRecentListenersOutput = Struct.new(:listeners, keyword_init: true)
|
|
94
|
-
GetArtistRecentListenersParams = Struct.new(:uri, :offset, :limit, keyword_init: true)
|
|
95
|
-
GetArtistRecommendationsParams = Struct.new(:did, :limit, keyword_init: true)
|
|
96
|
-
GetArtistShoutsOutput = Struct.new(:shouts, keyword_init: true)
|
|
97
|
-
GetArtistShoutsParams = Struct.new(:uri, :limit, :offset, keyword_init: true)
|
|
98
|
-
GetArtistsOutput = Struct.new(:artists, keyword_init: true)
|
|
99
|
-
GetArtistsParams = Struct.new(:limit, :offset, :names, :genre, keyword_init: true)
|
|
100
|
-
GetArtistTracksOutput = Struct.new(:tracks, keyword_init: true)
|
|
101
|
-
GetArtistTracksParams = Struct.new(:uri, :limit, :offset, keyword_init: true)
|
|
102
|
-
GetCurrentlyPlayingParams = Struct.new(:playerId, :actor, keyword_init: true)
|
|
103
|
-
GetFeedGeneratorOutput = Struct.new(:view, keyword_init: true)
|
|
104
|
-
GetFeedGeneratorParams = Struct.new(:feed, keyword_init: true)
|
|
105
|
-
GetFeedGeneratorsParams = Struct.new(:size, keyword_init: true)
|
|
106
|
-
GetFeedParams = Struct.new(:feed, :limit, :cursor, keyword_init: true)
|
|
107
|
-
GetFeedSkeletonOutput = Struct.new(:scrobbles, :cursor, keyword_init: true)
|
|
108
|
-
GetFeedSkeletonParams = Struct.new(:feed, :limit, :offset, :cursor, keyword_init: true)
|
|
109
|
-
GetFileParams = Struct.new(:fileId, keyword_init: true)
|
|
110
|
-
GetFilesParams = Struct.new(:at, keyword_init: true)
|
|
111
|
-
GetFollowersOutput = Struct.new(:subject, :followers, :cursor, :count, keyword_init: true)
|
|
112
|
-
GetFollowersParams = Struct.new(:actor, :limit, :dids, :cursor, keyword_init: true)
|
|
113
|
-
GetFollowsOutput = Struct.new(:subject, :follows, :cursor, :count, keyword_init: true)
|
|
114
|
-
GetFollowsParams = Struct.new(:actor, :limit, :dids, :cursor, keyword_init: true)
|
|
115
|
-
GetGlobalStatsParams = Struct.new(keyword_init: true)
|
|
116
|
-
GetKnownFollowersOutput = Struct.new(:subject, :followers, :cursor, keyword_init: true)
|
|
117
|
-
GetKnownFollowersParams = Struct.new(:actor, :limit, :cursor, keyword_init: true)
|
|
118
|
-
GetMetadataParams = Struct.new(:path, keyword_init: true)
|
|
119
|
-
GetMirrorSourcesOutput = Struct.new(:sources, keyword_init: true)
|
|
120
|
-
GetMirrorSourcesParams = Struct.new(keyword_init: true)
|
|
121
|
-
GetPlaybackQueueParams = Struct.new(:playerId, keyword_init: true)
|
|
122
|
-
GetPlaylistParams = Struct.new(:uri, keyword_init: true)
|
|
123
|
-
GetPlaylistsOutput = Struct.new(:playlists, keyword_init: true)
|
|
124
|
-
GetPlaylistsParams = Struct.new(:limit, :offset, keyword_init: true)
|
|
125
|
-
GetProfileParams = Struct.new(:did, keyword_init: true)
|
|
126
|
-
GetProfileShoutsOutput = Struct.new(:shouts, keyword_init: true)
|
|
127
|
-
GetProfileShoutsParams = Struct.new(:did, :offset, :limit, keyword_init: true)
|
|
128
|
-
GetRecommendationsParams = Struct.new(:did, :limit, keyword_init: true)
|
|
129
|
-
GetScrobbleParams = Struct.new(:uri, keyword_init: true)
|
|
130
|
-
GetScrobblesChartParams = Struct.new(:did, :artisturi, :albumuri, :songuri, :genre, :from, :to, keyword_init: true)
|
|
131
|
-
GetScrobblesOutput = Struct.new(:scrobbles, keyword_init: true)
|
|
132
|
-
GetScrobblesParams = Struct.new(:did, :following, :limit, :offset, keyword_init: true)
|
|
133
|
-
GetShoutRepliesOutput = Struct.new(:shouts, keyword_init: true)
|
|
134
|
-
GetShoutRepliesParams = Struct.new(:uri, :limit, :offset, keyword_init: true)
|
|
135
|
-
GetSongParams = Struct.new(:uri, :mbid, :isrc, :spotifyId, keyword_init: true)
|
|
136
|
-
GetSongRecentListenersOutput = Struct.new(:listeners, keyword_init: true)
|
|
137
|
-
GetSongRecentListenersParams = Struct.new(:uri, :offset, :limit, keyword_init: true)
|
|
138
|
-
GetSongsOutput = Struct.new(:songs, keyword_init: true)
|
|
139
|
-
GetSongsParams = Struct.new(:limit, :offset, :genre, :mbid, :isrc, :spotifyId, keyword_init: true)
|
|
140
|
-
GetStatsParams = Struct.new(:did, keyword_init: true)
|
|
141
|
-
GetStoriesParams = Struct.new(:size, :feed, :following, keyword_init: true)
|
|
142
|
-
GetTemporaryLinkParams = Struct.new(:path, keyword_init: true)
|
|
143
|
-
GetTopArtistsOutput = Struct.new(:artists, keyword_init: true)
|
|
144
|
-
GetTopArtistsParams = Struct.new(:limit, :offset, :startDate, :endDate, keyword_init: true)
|
|
145
|
-
GetTopTracksOutput = Struct.new(:tracks, keyword_init: true)
|
|
146
|
-
GetTopTracksParams = Struct.new(:limit, :offset, :startDate, :endDate, keyword_init: true)
|
|
147
|
-
GetTrackShoutsOutput = Struct.new(:shouts, keyword_init: true)
|
|
148
|
-
GetTrackShoutsParams = Struct.new(:uri, keyword_init: true)
|
|
149
|
-
GetWrappedParams = Struct.new(:did, :year, keyword_init: true)
|
|
150
|
-
GoogledriveFileListView = Struct.new(:files, keyword_init: true)
|
|
151
|
-
GoogledriveFileView = Struct.new(:id, keyword_init: true)
|
|
152
|
-
# indicates that a handle or DID could not be resolved
|
|
153
|
-
GraphNotFoundActor = Struct.new(:actor, :notFound, keyword_init: true)
|
|
154
|
-
GraphRelationship = Struct.new(:did, :following, :followedBy, keyword_init: true)
|
|
155
|
-
InsertDirectoryParams = Struct.new(:uri, :directory, :position, keyword_init: true)
|
|
156
|
-
InsertFilesParams = Struct.new(:uri, :files, :position, keyword_init: true)
|
|
157
|
-
LikeRecord = Struct.new(:createdAt, :subject, keyword_init: true)
|
|
158
|
-
LikeShoutInput = Struct.new(:uri, keyword_init: true)
|
|
159
|
-
LikeSongInput = Struct.new(:uri, keyword_init: true)
|
|
160
|
-
MatchSongParams = Struct.new(:title, :artist, :mbId, :isrc, keyword_init: true)
|
|
161
|
-
MirrorSourceView = Struct.new(:provider, :enabled, :externalUsername, :hasCredentials, :lastPolledAt, :lastScrobbleSeenAt, keyword_init: true)
|
|
162
|
-
NextParams = Struct.new(:playerId, keyword_init: true)
|
|
163
|
-
PauseParams = Struct.new(:playerId, keyword_init: true)
|
|
164
|
-
PlayDirectoryParams = Struct.new(:playerId, :directoryId, :shuffle, :recurse, :position, keyword_init: true)
|
|
165
|
-
PlayerCurrentlyPlayingViewDetailed = Struct.new(:title, keyword_init: true)
|
|
166
|
-
PlayerPlaybackQueueViewDetailed = Struct.new(:tracks, keyword_init: true)
|
|
167
|
-
PlayFileParams = Struct.new(:playerId, :fileId, keyword_init: true)
|
|
168
|
-
PlaylistItemRecord = Struct.new(:subject, :createdAt, :track, :order, keyword_init: true)
|
|
169
|
-
PlaylistRecord = Struct.new(:name, :description, :picture, :pictureUrl, :createdAt, :spotifyLink, :tidalLink, :youtubeLink, :appleMusicLink, keyword_init: true)
|
|
170
|
-
# Basic view of a playlist, including its metadata
|
|
171
|
-
PlaylistViewBasic = Struct.new(:id, :title, :uri, :curatorDid, :curatorHandle, :curatorName, :curatorAvatarUrl, :description, :coverImageUrl, :createdAt, :trackCount, keyword_init: true)
|
|
172
|
-
# Detailed view of a playlist, including its tracks and metadata
|
|
173
|
-
PlaylistViewDetailed = Struct.new(:id, :title, :uri, :curatorDid, :curatorHandle, :curatorName, :curatorAvatarUrl, :description, :coverImageUrl, :createdAt, :tracks, keyword_init: true)
|
|
174
|
-
PlayParams = Struct.new(:playerId, keyword_init: true)
|
|
175
|
-
PreviousParams = Struct.new(:playerId, keyword_init: true)
|
|
176
|
-
ProfileRecord = Struct.new(:displayName, :description, :avatar, :banner, :labels, :joinedViaStarterPack, :createdAt, keyword_init: true)
|
|
177
|
-
PutMirrorSourceInput = Struct.new(:provider, :enabled, :externalUsername, :apiKey, keyword_init: true)
|
|
178
|
-
RadioRecord = Struct.new(:name, :url, :description, :genre, :logo, :website, :createdAt, keyword_init: true)
|
|
179
|
-
RadioViewBasic = Struct.new(:id, :name, :description, :createdAt, keyword_init: true)
|
|
180
|
-
RadioViewDetailed = Struct.new(:id, :name, :description, :website, :url, :genre, :logo, :createdAt, keyword_init: true)
|
|
181
|
-
RemoveApikeyParams = Struct.new(:id, keyword_init: true)
|
|
182
|
-
RemovePlaylistParams = Struct.new(:uri, keyword_init: true)
|
|
183
|
-
RemoveShoutParams = Struct.new(:id, keyword_init: true)
|
|
184
|
-
RemoveTrackParams = Struct.new(:uri, :position, keyword_init: true)
|
|
185
|
-
ReplyShoutInput = Struct.new(:shoutId, :message, keyword_init: true)
|
|
186
|
-
ReportShoutInput = Struct.new(:shoutId, :reason, keyword_init: true)
|
|
187
|
-
ScrobbleFirstScrobbleView = Struct.new(:handle, :avatar, :timestamp, keyword_init: true)
|
|
188
|
-
ScrobbleRecord = Struct.new(:title, :artist, :artists, :albumArtist, :album, :duration, :trackNumber, :discNumber, :releaseDate, :year, :genre, :tags, :composer, :lyrics, :copyrightMessage, :wiki, :albumArt, :albumArtUrl, :youtubeLink, :spotifyLink, :tidalLink, :appleMusicLink, :createdAt, :mbid, :label, :isrc, keyword_init: true)
|
|
189
|
-
ScrobbleViewBasic = Struct.new(:id, :user, :userDisplayName, :userAvatar, :title, :artist, :artistUri, :album, :albumUri, :cover, :date, :uri, :sha256, :liked, :likesCount, keyword_init: true)
|
|
190
|
-
ScrobbleViewDetailed = Struct.new(:id, :user, :title, :artist, :artistUri, :album, :albumUri, :cover, :date, :uri, :sha256, :liked, :likesCount, :listeners, :scrobbles, :artists, :firstScrobble, keyword_init: true)
|
|
191
|
-
SearchParams = Struct.new(:query, keyword_init: true)
|
|
192
|
-
SeekParams = Struct.new(:playerId, :position, keyword_init: true)
|
|
193
|
-
ShoutAuthor = Struct.new(:id, :did, :handle, :displayName, :avatar, keyword_init: true)
|
|
194
|
-
ShoutRecord = Struct.new(:message, :createdAt, :parent, :subject, keyword_init: true)
|
|
195
|
-
ShoutView = Struct.new(:id, :message, :parent, :createdAt, :author, keyword_init: true)
|
|
196
|
-
SongFirstScrobbleView = Struct.new(:handle, :avatar, :timestamp, keyword_init: true)
|
|
197
|
-
SongRecentListenerView = Struct.new(:id, :did, :handle, :displayName, :avatar, :timestamp, :scrobbleUri, keyword_init: true)
|
|
198
|
-
SongRecord = Struct.new(:title, :artist, :artists, :albumArtist, :album, :duration, :trackNumber, :discNumber, :releaseDate, :year, :genre, :tags, :composer, :lyrics, :copyrightMessage, :wiki, :albumArt, :albumArtUrl, :youtubeLink, :spotifyLink, :tidalLink, :appleMusicLink, :createdAt, :mbid, :label, :isrc, keyword_init: true)
|
|
199
|
-
SongViewBasic = Struct.new(:id, :title, :artist, :albumArtist, :albumArt, :uri, :album, :duration, :trackNumber, :discNumber, :playCount, :uniqueListeners, :albumUri, :artistUri, :sha256, :mbid, :isrc, :tags, :createdAt, keyword_init: true)
|
|
200
|
-
SongViewDetailed = Struct.new(:id, :title, :artist, :albumArtist, :albumArt, :uri, :album, :duration, :trackNumber, :discNumber, :playCount, :uniqueListeners, :albumUri, :artistUri, :sha256, :mbid, :isrc, :tags, :createdAt, :artists, :firstScrobble, keyword_init: true)
|
|
201
|
-
SpotifyTrackView = Struct.new(:id, :name, :artist, :album, :duration, :previewUrl, keyword_init: true)
|
|
202
|
-
StartPlaylistParams = Struct.new(:uri, :shuffle, :position, keyword_init: true)
|
|
203
|
-
StatsGlobalStatsView = Struct.new(:scrobbles, :users, :artists, :albums, :tracks, keyword_init: true)
|
|
204
|
-
StatsView = Struct.new(:scrobbles, :artists, :lovedTracks, :albums, :tracks, keyword_init: true)
|
|
205
|
-
StatsWrappedAlbum = Struct.new(:id, :title, :artist, :albumArt, :uri, :playCount, keyword_init: true)
|
|
206
|
-
StatsWrappedArtist = Struct.new(:id, :name, :picture, :uri, :playCount, keyword_init: true)
|
|
207
|
-
StatsWrappedDayCount = Struct.new(:date, :count, keyword_init: true)
|
|
208
|
-
StatsWrappedGenreCount = Struct.new(:genre, :count, keyword_init: true)
|
|
209
|
-
StatsWrappedMilestone = Struct.new(:trackTitle, :artistName, :timestamp, :trackUri, keyword_init: true)
|
|
210
|
-
StatsWrappedMonthCount = Struct.new(:month, :count, keyword_init: true)
|
|
211
|
-
StatsWrappedTrack = Struct.new(:id, :title, :artist, :albumArt, :uri, :artistUri, :albumUri, :playCount, keyword_init: true)
|
|
212
|
-
StatsWrappedView = Struct.new(:year, :totalScrobbles, :totalListeningTimeMinutes, :topArtists, :topTracks, :topAlbums, :topGenres, :scrobblesPerMonth, :mostActiveDay, :mostActiveHour, :newArtistsCount, :longestStreak, :firstScrobble, :lastScrobble, keyword_init: true)
|
|
213
|
-
StatusRecord = Struct.new(:track, :startedAt, :expiresAt, keyword_init: true)
|
|
214
|
-
StrongRef = Struct.new(:uri, :cid, keyword_init: true)
|
|
215
|
-
UnfollowAccountOutput = Struct.new(:subject, :followers, :cursor, keyword_init: true)
|
|
216
|
-
UnfollowAccountParams = Struct.new(:account, keyword_init: true)
|
|
217
|
-
UpdateApikeyInput = Struct.new(:id, :name, :description, keyword_init: true)
|
|
218
|
-
end
|
|
219
|
-
end
|
data/lib/rocksky/http.rb
DELETED
|
@@ -1,123 +0,0 @@
|
|
|
1
|
-
require "json"
|
|
2
|
-
require "net/http"
|
|
3
|
-
require "uri"
|
|
4
|
-
|
|
5
|
-
module Rocksky
|
|
6
|
-
# Low-level XRPC transport. Most users should go through the resource
|
|
7
|
-
# accessors on {Rocksky::Client} (e.g. `client.actor.get_profile(...)`).
|
|
8
|
-
class HTTP
|
|
9
|
-
DEFAULT_OPEN_TIMEOUT = 10
|
|
10
|
-
DEFAULT_READ_TIMEOUT = 30
|
|
11
|
-
|
|
12
|
-
attr_reader :client
|
|
13
|
-
|
|
14
|
-
def initialize(client)
|
|
15
|
-
@client = client
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
# GET /xrpc/<nsid>?...
|
|
19
|
-
def query(nsid, params = {})
|
|
20
|
-
request(method: :get, nsid: nsid, params: params)
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
# POST /xrpc/<nsid>?... with optional JSON body.
|
|
24
|
-
def procedure(nsid, params = {}, body = nil)
|
|
25
|
-
request(method: :post, nsid: nsid, params: params, body: body)
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
private
|
|
29
|
-
|
|
30
|
-
def request(method:, nsid:, params: {}, body: nil)
|
|
31
|
-
uri = build_uri(nsid, params)
|
|
32
|
-
req = build_request(method, uri, body)
|
|
33
|
-
apply_headers(req)
|
|
34
|
-
|
|
35
|
-
response = perform(uri, req)
|
|
36
|
-
handle_response(response, nsid)
|
|
37
|
-
rescue Timeout::Error, Errno::ECONNREFUSED, SocketError, IOError,
|
|
38
|
-
Net::OpenTimeout, Net::ReadTimeout => e
|
|
39
|
-
raise Error.from_transport(e, nsid: nsid)
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
def build_uri(nsid, params)
|
|
43
|
-
url = "#{client.base_url}/xrpc/#{nsid}"
|
|
44
|
-
uri = URI.parse(url)
|
|
45
|
-
encoded = encode_params(params)
|
|
46
|
-
uri.query = URI.encode_www_form(encoded) unless encoded.empty?
|
|
47
|
-
uri
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
def build_request(method, uri, body)
|
|
51
|
-
req =
|
|
52
|
-
case method
|
|
53
|
-
when :get then Net::HTTP::Get.new(uri.request_uri)
|
|
54
|
-
when :post then Net::HTTP::Post.new(uri.request_uri)
|
|
55
|
-
else raise ArgumentError, "unsupported method: #{method}"
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
if body && !body.empty?
|
|
59
|
-
req["content-type"] = "application/json"
|
|
60
|
-
req.body = JSON.generate(body)
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
req
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
def apply_headers(req)
|
|
67
|
-
req["accept"] = "application/json"
|
|
68
|
-
req["user-agent"] = client.user_agent if client.user_agent
|
|
69
|
-
req["authorization"] = "Bearer #{client.token}" if client.token
|
|
70
|
-
client.headers.each { |name, value| req[name] = value }
|
|
71
|
-
end
|
|
72
|
-
|
|
73
|
-
def perform(uri, req)
|
|
74
|
-
http = Net::HTTP.new(uri.host, uri.port)
|
|
75
|
-
http.use_ssl = (uri.scheme == "https")
|
|
76
|
-
http.open_timeout = client.open_timeout
|
|
77
|
-
http.read_timeout = client.read_timeout
|
|
78
|
-
http.request(req)
|
|
79
|
-
end
|
|
80
|
-
|
|
81
|
-
def handle_response(response, nsid)
|
|
82
|
-
status = response.code.to_i
|
|
83
|
-
body = parse_body(response)
|
|
84
|
-
|
|
85
|
-
return body if status.between?(200, 299)
|
|
86
|
-
|
|
87
|
-
raise Error.from_response(status, body, nsid: nsid)
|
|
88
|
-
end
|
|
89
|
-
|
|
90
|
-
def parse_body(response)
|
|
91
|
-
return nil if response.body.nil? || response.body.empty?
|
|
92
|
-
|
|
93
|
-
content_type = response["content-type"].to_s
|
|
94
|
-
if content_type.include?("application/json")
|
|
95
|
-
JSON.parse(response.body)
|
|
96
|
-
else
|
|
97
|
-
response.body
|
|
98
|
-
end
|
|
99
|
-
rescue JSON::ParserError
|
|
100
|
-
response.body
|
|
101
|
-
end
|
|
102
|
-
|
|
103
|
-
# Drop nil values; convert symbol keys to strings; join arrays with commas
|
|
104
|
-
# (matches the lexicon-defined array encoding used by other SDKs).
|
|
105
|
-
def encode_params(params)
|
|
106
|
-
return {} if params.nil?
|
|
107
|
-
|
|
108
|
-
Hash(params).each_with_object({}) do |(key, value), out|
|
|
109
|
-
next if value.nil?
|
|
110
|
-
|
|
111
|
-
out[key.to_s] = encode_value(value)
|
|
112
|
-
end
|
|
113
|
-
end
|
|
114
|
-
|
|
115
|
-
def encode_value(value)
|
|
116
|
-
case value
|
|
117
|
-
when Array then value.join(",")
|
|
118
|
-
when true, false then value.to_s
|
|
119
|
-
else value
|
|
120
|
-
end
|
|
121
|
-
end
|
|
122
|
-
end
|
|
123
|
-
end
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
module Rocksky
|
|
2
|
-
module Resources
|
|
3
|
-
# `app.rocksky.actor.*` endpoints.
|
|
4
|
-
class Actor < Base
|
|
5
|
-
# Fetch a profile by DID or handle.
|
|
6
|
-
def get_profile(did:)
|
|
7
|
-
query("app.rocksky.actor.getProfile", did: did)
|
|
8
|
-
end
|
|
9
|
-
|
|
10
|
-
# Albums an actor has scrobbled.
|
|
11
|
-
def get_actor_albums(did:, limit: nil, offset: nil, start_date: nil, end_date: nil)
|
|
12
|
-
query("app.rocksky.actor.getActorAlbums",
|
|
13
|
-
did: did, limit: limit, offset: offset,
|
|
14
|
-
startDate: start_date, endDate: end_date)
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
# Artists an actor has scrobbled.
|
|
18
|
-
def get_actor_artists(did:, limit: nil, offset: nil, start_date: nil, end_date: nil)
|
|
19
|
-
query("app.rocksky.actor.getActorArtists",
|
|
20
|
-
did: did, limit: limit, offset: offset,
|
|
21
|
-
startDate: start_date, endDate: end_date)
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
# Songs an actor has scrobbled.
|
|
25
|
-
def get_actor_songs(did:, limit: nil, offset: nil, start_date: nil, end_date: nil)
|
|
26
|
-
query("app.rocksky.actor.getActorSongs",
|
|
27
|
-
did: did, limit: limit, offset: offset,
|
|
28
|
-
startDate: start_date, endDate: end_date)
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
# Songs an actor has loved.
|
|
32
|
-
def get_actor_loved_songs(did:, limit: nil, offset: nil)
|
|
33
|
-
query("app.rocksky.actor.getActorLovedSongs",
|
|
34
|
-
did: did, limit: limit, offset: offset)
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
# Scrobbles for an actor.
|
|
38
|
-
def get_actor_scrobbles(did:, limit: nil, offset: nil)
|
|
39
|
-
query("app.rocksky.actor.getActorScrobbles",
|
|
40
|
-
did: did, limit: limit, offset: offset)
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
# Playlists for an actor.
|
|
44
|
-
def get_actor_playlists(did:, limit: nil, offset: nil)
|
|
45
|
-
query("app.rocksky.actor.getActorPlaylists",
|
|
46
|
-
did: did, limit: limit, offset: offset)
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
# Musical neighbours of an actor.
|
|
50
|
-
def get_actor_neighbours(did:)
|
|
51
|
-
query("app.rocksky.actor.getActorNeighbours", did: did)
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
# Compatibility score between the authenticated user and another actor.
|
|
55
|
-
def get_actor_compatibility(did:)
|
|
56
|
-
query("app.rocksky.actor.getActorCompatibility", did: did)
|
|
57
|
-
end
|
|
58
|
-
end
|
|
59
|
-
end
|
|
60
|
-
end
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
module Rocksky
|
|
2
|
-
module Resources
|
|
3
|
-
# `app.rocksky.album.*` endpoints.
|
|
4
|
-
class Album < Base
|
|
5
|
-
# Fetch an album by AT-URI.
|
|
6
|
-
def get_album(uri:)
|
|
7
|
-
query("app.rocksky.album.getAlbum", uri: uri)
|
|
8
|
-
end
|
|
9
|
-
|
|
10
|
-
# List albums.
|
|
11
|
-
def get_albums(limit: nil, offset: nil, genre: nil)
|
|
12
|
-
query("app.rocksky.album.getAlbums",
|
|
13
|
-
limit: limit, offset: offset, genre: genre)
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
# Tracks belonging to an album.
|
|
17
|
-
def get_album_tracks(uri:)
|
|
18
|
-
query("app.rocksky.album.getAlbumTracks", uri: uri)
|
|
19
|
-
end
|
|
20
|
-
end
|
|
21
|
-
end
|
|
22
|
-
end
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
module Rocksky
|
|
2
|
-
module Resources
|
|
3
|
-
# `app.rocksky.apikey.*` endpoints. All require an authenticated client.
|
|
4
|
-
class Apikey < Base
|
|
5
|
-
# List your API keys.
|
|
6
|
-
def get_apikeys(limit: nil, offset: nil)
|
|
7
|
-
query("app.rocksky.apikey.getApikeys", limit: limit, offset: offset)
|
|
8
|
-
end
|
|
9
|
-
|
|
10
|
-
# Create a new API key.
|
|
11
|
-
def create_apikey(name:, description: nil)
|
|
12
|
-
body = { name: name, description: description }.compact
|
|
13
|
-
procedure("app.rocksky.apikey.createApikey", body: body)
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
# Update an API key.
|
|
17
|
-
def update_apikey(id:, name: nil, description: nil)
|
|
18
|
-
body = { id: id, name: name, description: description }.compact
|
|
19
|
-
procedure("app.rocksky.apikey.updateApikey", body: body)
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
# Remove an API key.
|
|
23
|
-
def remove_apikey(id:)
|
|
24
|
-
procedure("app.rocksky.apikey.removeApikey", params: { id: id })
|
|
25
|
-
end
|
|
26
|
-
end
|
|
27
|
-
end
|
|
28
|
-
end
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
module Rocksky
|
|
2
|
-
module Resources
|
|
3
|
-
# `app.rocksky.artist.*` endpoints.
|
|
4
|
-
class Artist < Base
|
|
5
|
-
# Fetch an artist by AT-URI.
|
|
6
|
-
def get_artist(uri:)
|
|
7
|
-
query("app.rocksky.artist.getArtist", uri: uri)
|
|
8
|
-
end
|
|
9
|
-
|
|
10
|
-
# List artists. `names` may be an Array of strings; it will be joined CSV-style.
|
|
11
|
-
def get_artists(limit: nil, offset: nil, names: nil, genre: nil)
|
|
12
|
-
query("app.rocksky.artist.getArtists",
|
|
13
|
-
limit: limit, offset: offset, names: names, genre: genre)
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
# Albums by an artist.
|
|
17
|
-
def get_artist_albums(uri:)
|
|
18
|
-
query("app.rocksky.artist.getArtistAlbums", uri: uri)
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
# Tracks by an artist.
|
|
22
|
-
def get_artist_tracks(uri:, limit: nil, offset: nil)
|
|
23
|
-
query("app.rocksky.artist.getArtistTracks",
|
|
24
|
-
uri: uri, limit: limit, offset: offset)
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
# All-time listeners for an artist.
|
|
28
|
-
def get_artist_listeners(uri:, limit: nil, offset: nil)
|
|
29
|
-
query("app.rocksky.artist.getArtistListeners",
|
|
30
|
-
uri: uri, limit: limit, offset: offset)
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
# Recent listeners for an artist.
|
|
34
|
-
def get_artist_recent_listeners(uri:, limit: nil, offset: nil)
|
|
35
|
-
query("app.rocksky.artist.getArtistRecentListeners",
|
|
36
|
-
uri: uri, limit: limit, offset: offset)
|
|
37
|
-
end
|
|
38
|
-
end
|
|
39
|
-
end
|
|
40
|
-
end
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
module Rocksky
|
|
2
|
-
module Resources
|
|
3
|
-
# Shared plumbing for resource classes. Each subclass calls {#query} or
|
|
4
|
-
# {#procedure} with the lexicon NSID; the {Rocksky::HTTP} instance does the
|
|
5
|
-
# actual transport work.
|
|
6
|
-
class Base
|
|
7
|
-
attr_reader :http
|
|
8
|
-
|
|
9
|
-
def initialize(http)
|
|
10
|
-
@http = http
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
protected
|
|
14
|
-
|
|
15
|
-
def query(nsid, **params)
|
|
16
|
-
@http.query(nsid, params)
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
def procedure(nsid, params: {}, body: nil)
|
|
20
|
-
@http.procedure(nsid, params, body)
|
|
21
|
-
end
|
|
22
|
-
end
|
|
23
|
-
end
|
|
24
|
-
end
|