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 / sdk / gleam
1 folder 5 files
README.md

rocksky — Gleam SDK#

Package Version Hex Docs Gleam Erlang/OTP NIF License

Gleam bindings to the shared Rocksky Rust core (rocksky-sdk) via the rocksky_erl Rustler NIF: AppView reads, AT Protocol PDS writes (scrobble, like, follow, shout) and the identity hashes — the same engine behind every Rocksky SDK. Targets Erlang.

Installation#

gleam add rocksky   # rocksky = ">= 1.7.0 and < 2.0.0"

rocksky 1.7.0 depends on rocksky_erl 0.4.0, whose loader fetches the native library from the GitHub release on first use (checksum-verified). For monorepo dev, build it with ../erlang/build-core.sh and use the local path dep in gleam.toml.

Quick start#

import rocksky/client

pub fn main() {
  // Reads — use the default AppView (https://api.rocksky.app).
  // Envelope calls return Dynamic ({ok, value} | {error, message}); decode with
  // gleam/dynamic.
  echo client.global_stats()
  echo client.top_tracks(10, 0)

  // Writes — log in once (session persisted at the given path).
  let agent = client.login("session.json", "alice.bsky.social", "app-password")
  echo client.follow(agent, "did:plc:rlwgbwqdknilpxxep5gvzc3y")
}

API#

Reads#

Named reads: profile(actor), scrobbles(actor, limit, offset), top_tracks(limit, offset), global_stats() — each returns Dynamic. To target a custom AppView endpoint, use the *_at variant with a trailing endpoint URL (e.g. global_stats_at("https://…"), top_tracks_at(limit, offset, "https://…")).

Universal get — the escape hatch reaches the whole app.rocksky.* read catalog by NSID: get(nsid, params_json), get_authed(nsid, params_json, token) (bearer token for auth-gated queries), and get_at(nsid, params_json, endpoint), each returning Dynamic.

echo client.get("app.rocksky.album.getAlbums", "{\"limit\":20}")
echo client.get("app.rocksky.album.getAlbumTracks", "{\"uri\":\"...\"}")
echo client.get("app.rocksky.graph.getFollows", "{\"actor\":\"...\"}")
echo client.get("app.rocksky.stats.getStats", "{}")

Typed date-window chartstop_tracks_interval(limit, offset, interval) and top_artists_interval(limit, offset, interval), where Interval is AllTime | LastDays(Int) | LastWeeks(Int) | LastMonths(Int) | LastYears(Int) | Range(String, String).

echo client.top_tracks_interval(5, 0, client.LastDays(7))

Matchmatch_song(title, artist) resolves a bare title + artist into full canonical metadata.

Writes#

login(session_path, identifier, password) → an opaque Agent. Then scrobble(agent, track) (full metadata) or scrobble_match(agent, ScrobbleMatch(title, artist, album, mb_id, isrc, timestamp)) (match-then-write) — title/artist are String, the rest Option (album override, mb_id/isrc match anchors, timestamp scrobbled-at Unix seconds), e.g. scrobble_match(agent, ScrobbleMatch("Chaser", "Calibro 35", None, None, None, None)), like(agent, uri, cid), follow(agent, did), shout(agent, subject_uri, subject_cid, message), refresh_session(agent).

Dedup + realtime — once logged in with a dedup path, keep the store warm with sync_repo(agent) and hydrate_from_jetstream(agent).

Identity hashes#

song_hash(title, artist, album), artist_hash(album_artist) — lowercase-hex SHA-256, identical to the server and every other Rocksky SDK.

Example#

gleam run -m examples/native_core

License#

MIT.