Module: Rocksky

Defined in:
lib/rocksky/filter.rb,
lib/rocksky.rb,
lib/rocksky/native.rb,
lib/rocksky/remote.rb,
lib/rocksky/library.rb,
lib/rocksky/version.rb,
lib/rocksky/playlist.rb

Overview

Standalone — no native core involved. Loads on its own via require "rocksky/filter".

Defined Under Namespace

Modules: Native, Playlist Classes: Agent, Error, Filter, Library, RemoteController, RemotePlayer

Constant Summary collapse

VERSION =
"0.11.1"

Class Method Summary collapse

Class Method Details

.catalog_albums(limit: 50, offset: 0, genre: nil, filter: nil, base: nil) ⇒ Object

The album catalog (app.rocksky.album.getAlbums). Returns { "albums" => [...] }.



150
151
152
# File 'lib/rocksky.rb', line 150

def self.catalog_albums(limit: 50, offset: 0, genre: nil, filter: nil, base: nil)
  get("app.rocksky.album.getAlbums", catalog_params(limit, offset, genre, filter), base: base)
end

.catalog_artists(limit: 50, offset: 0, genre: nil, filter: nil, base: nil) ⇒ Object

The artist catalog (app.rocksky.artist.getArtists). Returns { "artists" => [...] }.



144
145
146
# File 'lib/rocksky.rb', line 144

def self.catalog_artists(limit: 50, offset: 0, genre: nil, filter: nil, base: nil)
  get("app.rocksky.artist.getArtists", catalog_params(limit, offset, genre, filter), base: base)
end

.catalog_songs(limit: 50, offset: 0, genre: nil, filter: nil, base: nil) ⇒ Object

The song catalog (app.rocksky.song.getSongs), optionally narrowed by genre: and/or an RSQL filter:. Returns { "tracks" => [...] }.



138
139
140
# File 'lib/rocksky.rb', line 138

def self.catalog_songs(limit: 50, offset: 0, genre: nil, filter: nil, base: nil)
  get("app.rocksky.song.getSongs", catalog_params(limit, offset, genre, filter), base: base)
end

.get(nsid, params = {}, base: nil, token: nil) ⇒ Object

Universal read escape hatch — call any app.rocksky.* query by nsid. params is a hash of string params; the whole read-query catalog is reachable here.

Rocksky.get("app.rocksky.album.getAlbum", { uri: uri })
Rocksky.get("app.rocksky.charts.getScrobblesChart", { did: did })

token, when given, is sent as an Authorization: Bearer header — needed for auth-gated queries.



183
184
185
# File 'lib/rocksky.rb', line 183

def self.get(nsid, params = {}, base: nil, token: nil)
  unwrap(C.rocksky_get(base.to_s, nsid, JSON.generate(params), token.to_s))
end

.global_stats(base: nil) ⇒ Object



127
128
129
# File 'lib/rocksky.rb', line 127

def self.global_stats(base: nil)
  unwrap(C.rocksky_global_stats(base.to_s))
end

.library(token, base: nil) ⇒ Object

Build an authenticated app.rocksky.library.* (uploaded-music) client. The token is required — every library method is auth-gated.

lib = Rocksky.library(token)
lib.get_song(song_id)


355
356
357
# File 'lib/rocksky.rb', line 355

def self.library(token, base: nil)
  Library.new(token, base: base)
end

.match_song(title, artist, album: nil, mb_id: nil, isrc: nil, base: nil) ⇒ Object

Resolve full canonical metadata for a bare title + artist (matchSong). album steers the match toward that release (case-insensitive) so a remaster/live/single edition doesn't shadow the intended album.



222
223
224
# File 'lib/rocksky.rb', line 222

def self.match_song(title, artist, album: nil, mb_id: nil, isrc: nil, base: nil)
  unwrap(C.rocksky_match_song(base.to_s, title, artist, album.to_s, mb_id.to_s, isrc.to_s))
end

.notifications(token:, limit: nil, cursor: nil, base: nil) ⇒ Object

The authenticated viewer's notifications, most recent first. limit defaults to 30 server-side; cursor paginates. Returns { "notifications" => [...], "unreadCount" => Integer, "cursor" => String? }.



206
207
208
209
210
211
# File 'lib/rocksky.rb', line 206

def self.notifications(token:, limit: nil, cursor: nil, base: nil)
  params = {}
  params[:limit] = limit unless limit.nil?
  params[:cursor] = cursor unless cursor.nil?
  get("app.rocksky.notification.listNotifications", params, base: base, token: token)
end

.post(nsid, params = {}, base: nil, token: nil) ⇒ Object

Universal write escape hatch — call any app.rocksky.* procedure whose arguments ride the query string. Most are auth-gated, so pass token.

Rocksky.post("app.rocksky.playlist.removePlaylist", { uri: uri }, token: tok)


191
192
193
# File 'lib/rocksky.rb', line 191

def self.post(nsid, params = {}, base: nil, token: nil)
  unwrap(C.rocksky_post(base.to_s, nsid, JSON.generate(params), token.to_s))
end

.profile(actor, base: nil) ⇒ Object

---- reads (unauthenticated; base: overrides the AppView URL) ----



115
116
117
# File 'lib/rocksky.rb', line 115

def self.profile(actor, base: nil)
  unwrap(C.rocksky_profile(base.to_s, actor))
end

.scrobble_feed(did: nil, following: false, limit: 50, offset: 0, filter: nil, base: nil) ⇒ Object

A social/global scrobbles feed (app.rocksky.scrobble.getScrobbles). Pass did: to scope to an actor and following: true for their follow graph. filter: reaches the joined track/user/artist via dotted fields, e.g. Rocksky::Filter.eq(:"track.artist", "Daft Punk"). Returns { "scrobbles" => [...] }.



159
160
161
162
163
164
165
# File 'lib/rocksky.rb', line 159

def self.scrobble_feed(did: nil, following: false, limit: 50, offset: 0, filter: nil, base: nil)
  params = { limit: limit, offset: offset }
  params[:did] = did unless did.nil?
  params[:following] = following if following
  params[:filter] = filter.to_s unless filter.nil?
  get("app.rocksky.scrobble.getScrobbles", params, base: base)
end

.scrobbles(actor, limit: 50, offset: 0, base: nil) ⇒ Object



119
120
121
# File 'lib/rocksky.rb', line 119

def self.scrobbles(actor, limit: 50, offset: 0, base: nil)
  unwrap(C.rocksky_scrobbles(base.to_s, actor, limit, offset))
end

.song_hash(title, artist, album) ⇒ Object

Identity hash — identical across every Rocksky SDK.



258
259
260
# File 'lib/rocksky.rb', line 258

def self.song_hash(title, artist, album)
  take_string(C.rocksky_song_hash(title, artist, album))
end

.symbolize(obj) ⇒ Object

Recursively convert Hash string keys to symbols (Arrays walked too). Used by the remote-control glue so commands/events reach handlers as symbol-keyed hashes (e.g. cmd, event).



102
103
104
105
106
107
108
109
110
111
# File 'lib/rocksky.rb', line 102

def self.symbolize(obj)
  case obj
  when Hash
    obj.each_with_object({}) { |(k, v), acc| acc[k.to_sym] = symbolize(v) }
  when Array
    obj.map { |e| symbolize(e) }
  else
    obj
  end
end

.take_string(ptr) ⇒ Object

Copy an owned C string into a Ruby string and free the original.



82
83
84
85
86
87
88
89
# File 'lib/rocksky.rb', line 82

def self.take_string(ptr)
  return nil if ptr.nil? || ptr.null?

  len = STRLEN.call(ptr)
  str = ptr[0, len].force_encoding("UTF-8")
  C.rocksky_string_free(ptr)
  str
end

.top_artists_interval(limit: 50, offset: 0, interval: :all, base: nil) ⇒ Object

Top artists chart over a typed date window (see .top_tracks_interval).



237
238
239
240
# File 'lib/rocksky.rb', line 237

def self.top_artists_interval(limit: 50, offset: 0, interval: :all, base: nil)
  unit, n, s, e = interval_parts(interval)
  unwrap(C.rocksky_top_artists_interval(base.to_s, limit, offset, unit, n, s, e))
end

.top_tracks(limit: 50, offset: 0, base: nil) ⇒ Object



123
124
125
# File 'lib/rocksky.rb', line 123

def self.top_tracks(limit: 50, offset: 0, base: nil)
  unwrap(C.rocksky_top_tracks(base.to_s, limit, offset))
end

.top_tracks_interval(limit: 50, offset: 0, interval: :all, base: nil) ⇒ Object

Top tracks chart over a typed date window. interval is :all, or a pair like [:days, 7] / [:weeks, 4] / [:months, 1] / [:years, 1], or [:range, start_rfc3339, end_rfc3339].

Rocksky.top_tracks_interval(limit: 10, interval: [:days, 7])


231
232
233
234
# File 'lib/rocksky.rb', line 231

def self.top_tracks_interval(limit: 50, offset: 0, interval: :all, base: nil)
  unit, n, s, e = interval_parts(interval)
  unwrap(C.rocksky_top_tracks_interval(base.to_s, limit, offset, unit, n, s, e))
end

.unread_count(token:, base: nil) ⇒ Object

The authenticated viewer's unread-notification count. Returns { "count" => Integer }.



199
200
201
# File 'lib/rocksky.rb', line 199

def self.unread_count(token:, base: nil)
  get("app.rocksky.notification.getUnreadCount", {}, base: base, token: token)
end

.unwrap(ptr) ⇒ Object

Parse a {"ok"|"error"} envelope, raising Error on failure.

Raises:



92
93
94
95
96
97
# File 'lib/rocksky.rb', line 92

def self.unwrap(ptr)
  parsed = JSON.parse(take_string(ptr))
  raise Error, parsed["error"] if parsed.key?("error")

  parsed["ok"]
end

.update_seen(token:, ids: [], base: nil) ⇒ Object

Mark notifications as viewed. ids is an array of notification ids, or an empty array to mark all as viewed. Returns { "unreadCount" => Integer }.



215
216
217
# File 'lib/rocksky.rb', line 215

def self.update_seen(token:, ids: [], base: nil)
  unwrap(C.rocksky_update_seen(base.to_s, token.to_s, JSON.generate(ids)))
end