Module: Rocksky

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

Defined Under Namespace

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

Constant Summary collapse

VERSION =
"0.9.1"

Class Method Summary collapse

Class Method Details

.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.



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

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



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

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)


299
300
301
# File 'lib/rocksky.rb', line 299

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

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

Resolve full canonical metadata for a bare title + artist (matchSong).



166
167
168
# File 'lib/rocksky.rb', line 166

def self.match_song(title, artist, mb_id: nil, isrc: nil, base: nil)
  unwrap(C.rocksky_match_song(base.to_s, title, artist, 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? }.



152
153
154
155
156
157
# File 'lib/rocksky.rb', line 152

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

.profile(actor, base: nil) ⇒ Object

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



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

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

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



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

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.



202
203
204
# File 'lib/rocksky.rb', line 202

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).



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

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.



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

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).



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

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



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

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])


175
176
177
178
# File 'lib/rocksky.rb', line 175

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 }.



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

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:



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

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 }.



161
162
163
# File 'lib/rocksky.rb', line 161

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