A decentralized music tracking and discovery platform built on AT Protocol 🎵 rocksky.app
spotify atproto lastfm musicbrainz scrobbling listenbrainz
0

Configure Feed

Select the types of activity you want to include in your feed.

rocksky / docs / sdks / ruby.mdx
7.4 kB 156 lines
1--- 2title: "Ruby" 3description: "Idiomatic Ruby client for the Rocksky XRPC API." 4icon: "gem" 5--- 6 7`rocksky` is a stdlib-only Ruby client for the Rocksky API. 8 9```ruby 10client = Rocksky.new(token: ENV["ROCKSKY_TOKEN"]) 11 12client.actor.get_profile(did: "tsiry-sandratraina.com") 13client.charts.get_top_artists(limit: 10, start_date: "2025-01-01") 14client.scrobble.create_scrobble(title: "In Bloom", artist: "Nirvana") 15``` 16 17Every XRPC NSID maps to a method on a resource object. 18`app.rocksky.actor.getProfile` becomes `client.actor.get_profile(...)`. 19`app.rocksky.scrobble.createScrobble` becomes 20`client.scrobble.create_scrobble(...)`. Kwargs in, parsed JSON out. 21 22## Install 23 24```ruby 25# Gemfile 26gem "rocksky" 27``` 28 29```bash 30gem install rocksky 31``` 32 33Requires Ruby 3.0+. Depends only on Ruby's stdlib (`net/http`, `json`, `uri`). 34 35## Quick start 36 37```ruby 38require "rocksky" 39 40# Reads ROCKSKY_BASE_URL and ROCKSKY_TOKEN from the env when omitted. 41client = Rocksky.new 42 43profile = client.actor.get_profile(did: "tsiry-sandratraina.com") 44puts profile["displayName"] 45``` 46 47For authenticated calls, pass a bearer token: 48 49```ruby 50client = Rocksky.new(token: "eyJ...") 51client.scrobble.create_scrobble(title: "In Bloom", artist: "Nirvana") 52``` 53 54`with_token` derives a new client without mutating the original — handy when a 55single base client is shared across users in a web app: 56 57```ruby 58base = Rocksky.new 59def for_user(base, token) = base.with_token(token) 60``` 61 62## Resources 63 64| Resource | Methods | 65| ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- | 66| `client.actor` | `get_profile`, `get_actor_albums/artists/songs/scrobbles/playlists/loved_songs`, `get_actor_neighbours`, `get_actor_compatibility` | 67| `client.album` | `get_album`, `get_albums`, `get_album_tracks` | 68| `client.apikey` | `get_apikeys`, `create_apikey`, `update_apikey`, `remove_apikey` *(auth)* | 69| `client.artist` | `get_artist`, `get_artists`, `get_artist_albums/tracks/listeners/recent_listeners` | 70| `client.charts` | `get_scrobbles_chart`, `get_top_artists`, `get_top_tracks` | 71| `client.feed` | `search`, `get_feed_generators/generator/feed`, `get_stories`, `get_recommendations`, `get_artist_recommendations`, `get_album_recommendations` | 72| `client.graph` | `follow_account`, `unfollow_account`, `get_followers`, `get_follows`, `get_known_followers` *(auth)* | 73| `client.like` | `like_song`, `dislike_song`, `like_shout`, `dislike_shout` *(auth)* | 74| `client.mirror` | `get_mirror_sources`, `put_mirror_source` *(auth)* | 75| `client.player` | `play`, `pause`, `next`, `previous`, `seek`, `play_file`, `play_directory`, `add_items_to_queue`, `get_currently_playing`, `get_playback_queue` | 76| `client.playlist` | `get_playlist`, `get_playlists`, `create_playlist`, `remove_playlist`, `start_playlist`, `insert_files`, `insert_directory` | 77| `client.scrobble` | `create_scrobble`, `get_scrobble`, `get_scrobbles` | 78| `client.shout` | `create_shout`, `reply_shout`, `remove_shout`, `report_shout`, `get_*_shouts`, `get_shout_replies` | 79| `client.song` | `get_song`, `get_songs`, `get_song_recent_listeners`, `match_song`, `create_song` | 80| `client.spotify` | `play`, `pause`, `next`, `previous`, `seek`, `get_currently_playing` *(auth)* | 81| `client.stats` | `get_stats`, `get_wrapped` | 82 83For anything not covered: 84 85```ruby 86client.query("app.rocksky.actor.getProfile", did: "did:plc:7vdlgi2bflelz7mmuxoqjfcr") 87client.procedure("app.rocksky.like.likeSong", body: { uri: "at://..." }) 88``` 89 90## Conventions 91 92- **Keyword args** for every parameter. Ruby `snake_case` maps to the 93 lexicon's `camelCase` (`start_date:` `startDate`). 94- **`nil` is dropped.** Pass `nil` for any optional param and it won't be sent. 95- **Arrays are CSV-joined.** Lexicon list params accept Ruby arrays. 96- **Hashes in, hashes out.** Responses come back as plain `Hash` (string 97 keys), mirroring the lexicon JSON 1:1. 98 99## Errors 100 101```ruby 102begin 103 client.song.get_song(uri: "at://does-not-exist") 104rescue Rocksky::NotFound => e 105 puts "missing: #{e.message} (status=#{e.status}, nsid=#{e.nsid})" 106rescue Rocksky::RateLimited 107 sleep 5; retry 108rescue Rocksky::Error => e 109 warn "rocksky failure: #{e.class}: #{e.message}" 110end 111``` 112 113| Class | Status | 114| ------------------------- | ------------------- | 115| `Rocksky::BadRequest` | 400 | 116| `Rocksky::Unauthorized` | 401 | 117| `Rocksky::Forbidden` | 403 | 118| `Rocksky::NotFound` | 404 | 119| `Rocksky::RateLimited` | 429 | 120| `Rocksky::ServerError` | 5xx | 121| `Rocksky::HTTPError` | any other non-2xx | 122| `Rocksky::TransportError` | DNS/TCP/timeouts | 123 124## Configuration 125 126| Option | Default | Env var | 127| -------------- | ----------------------------- | --------------------- | 128| `base_url` | `https://api.rocksky.app` | `ROCKSKY_BASE_URL` | 129| `token` | `nil` | `ROCKSKY_TOKEN` | 130| `headers` | `{}` | — | 131| `user_agent` | `rocksky-ruby/<version>` | — | 132| `open_timeout` | `10` seconds | — | 133| `read_timeout` | `30` seconds | — | 134 135## IRB console 136 137```bash 138$ gem install rocksky 139$ ROCKSKY_TOKEN=eyJ... rocksky-console 140Rocksky 0.1.0 — interactive console 141 base_url : https://api.rocksky.app 142 token : present (set via ROCKSKY_TOKEN) 143 144irb> client.actor.get_profile(did: "did:plc:7vdlgi2bflelz7mmuxoqjfcr") 145=> {"did"=>"did:plc:...", "handle"=>"tsiry-sandratraina.com", ...} 146``` 147 148## Types 149 150Lexicon-derived `Struct` types are available under `Rocksky::Generated::*`, mirroring every lex `*View*` / `*Record` / `*Input` / `*Output` / `*Params` shape from [the Rocksky lexicons](https://tangled.org/rocksky.app/rocksky/tree/main/apps/api/lexicons). Regenerate with `bun run lexgen:types` at the repo root. 151 152 153## License 154 155MIT © Tsiry Sandratraina. Source: 156[`sdk/ruby`](https://tangled.org/@rocksky.app/rocksky/blob/main/sdk/ruby).