rocksky 0.4.1 → 0.5.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e128365c7e45c3e9853b61446d4f62b3c117aa7a2b523d627b3e28bf37890862
4
- data.tar.gz: fce5a199e7b72de73c407ce3015d856ac8c31150e8d1352f5c2573eab8ffdb8c
3
+ metadata.gz: f5ff00fa4d526c5436fb713d32c4f49f85609263ccf950ea51a2091bec6d8951
4
+ data.tar.gz: 161fb86cda0ae97b7044a10c9d5a249971143d00d6cf27560500199ebfdcfbfa
5
5
  SHA512:
6
- metadata.gz: 8e743abeb46fd38a8238166c907064645766e34b1f3e0e40f63b875fbc1e1cb2fe8d1d8cf90960ec52d0078a535b7b7c14baba7a3c90420a1dbda8b0b3a4b919
7
- data.tar.gz: d787a2289995372310020770b4849543ec4edd2f0114bafce19c99afde63abb10d9bed5a90e11a76135023a05895adf6438bf05dfcb9cbb53c7311ea7746d586
6
+ metadata.gz: 4c279685557ce908beb4d7e763a6b4d3a6fd6e55d51158aa518bdeb70189ecec3b22b2367bd0cdcb61e72439a22f73745159b21d64326a02d49f2f6cec608a26
7
+ data.tar.gz: 8c09668a64234fc5064e50b53e039cbc9ae2d077290cac0dbeb0769f175ae6f24a65f11a7ae039af34d38793dbbb2897283ff23e7978a87e1ce9453d558c5275
data/README.md CHANGED
@@ -11,6 +11,12 @@ every Rocksky SDK.
11
11
  gem install rocksky
12
12
  ```
13
13
 
14
+ Or in a Gemfile:
15
+
16
+ ```ruby
17
+ gem "rocksky", "~> 0.5"
18
+ ```
19
+
14
20
  The gem is pure-Ruby; the native library is fetched from the GitHub release on
15
21
  first load and cached (checksum-verified). For a local checkout, build it once:
16
22
 
@@ -46,16 +52,63 @@ camelCase keys.
46
52
 
47
53
  ### Reads — `Rocksky`
48
54
 
49
- `profile(actor, base:)`, `scrobbles(actor, limit:, offset:, base:)`,
55
+ Named reads: `profile(actor, base:)`, `scrobbles(actor, limit:, offset:, base:)`,
50
56
  `top_tracks(limit:, offset:, base:)`, `global_stats(base:)`. Every read takes an
51
57
  optional `base:` to target a custom AppView.
52
58
 
59
+ **Universal escape hatch** — `Rocksky.get(nsid, params, base: nil, token: nil)`
60
+ reaches the *whole* `app.rocksky.*` read catalog and returns the parsed
61
+ Hash/Array. Pass `token:` to send an `Authorization: Bearer` header for
62
+ auth-gated queries.
63
+
64
+ ```ruby
65
+ Rocksky.get("app.rocksky.album.getAlbums", limit: 10)
66
+ Rocksky.get("app.rocksky.album.getAlbumTracks", uri: album_uri)
67
+ Rocksky.get("app.rocksky.graph.getFollows", actor: "alice.bsky.social")
68
+ Rocksky.get("app.rocksky.actor.getActorLovedSongs", actor: "alice.bsky.social")
69
+ Rocksky.get("app.rocksky.stats.getStats")
70
+ Rocksky.get("app.rocksky.charts.getScrobblesChart", token: "…")
71
+ ```
72
+
73
+ **Typed date-window charts** — `top_tracks_interval(limit:, offset:, interval:)`
74
+ and `top_artists_interval(...)`. `interval:` is `:all` or one of
75
+ `[:days, n]` / `[:weeks, n]` / `[:months, n]` / `[:years, n]` /
76
+ `[:range, start, end]`.
77
+
78
+ ```ruby
79
+ Rocksky.top_tracks_interval(limit: 5, interval: [:days, 7])
80
+ Rocksky.top_artists_interval(limit: 5, interval: :all)
81
+ ```
82
+
83
+ **Match** — `Rocksky.match_song(title, artist, mb_id: nil, isrc: nil)` resolves a
84
+ bare title + artist into full canonical metadata.
85
+
53
86
  ### Writes — `Rocksky::Agent`
54
87
 
55
- `Agent.login(session_path, identifier, password, appview:)` → an agent. Then
56
- `scrobble(track)` (fans out to artist/album/song/scrobble), `like(uri, cid)`,
57
- `follow(did)`, `shout(subject_uri, subject_cid, message)`, `refresh_session`, and
58
- `close` (release the native handle).
88
+ `Agent.login(session_path, identifier, password, appview:, dedup_path:)` → an
89
+ agent. Pass `dedup_path:` to enable scrobble dedup + realtime hydration (see
90
+ below). Then `scrobble(track)` (fans out to artist/album/song/scrobble),
91
+ `like(uri, cid)`, `follow(did)`, `shout(subject_uri, subject_cid, message)`,
92
+ `refresh_session`, and `close` (release the native handle).
93
+
94
+ **Two scrobble paths** — `scrobble(track)` takes full metadata, while
95
+ `scrobble_match(title, artist, album: nil, mb_id: nil, isrc: nil)` matches a bare
96
+ title + artist first, then writes.
97
+
98
+ ```ruby
99
+ agent.scrobble_match("Chaser", "Calibro 35", album: "Jazzploitation")
100
+ ```
101
+
102
+ **Dedup + realtime** — with `dedup_path:` set at login, `agent.sync_repo`
103
+ backfills from the PDS repo and `agent.hydrate_from_jetstream` streams live
104
+ updates, both deduped against the on-disk store.
105
+
106
+ ```ruby
107
+ agent = Rocksky::Agent.login("session.json", "alice.bsky.social", "app-password",
108
+ dedup_path: "./dedup")
109
+ agent.sync_repo
110
+ agent.hydrate_from_jetstream
111
+ ```
59
112
 
60
113
  ### Identity hashes
61
114
 
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "repo": "tsirysndr/rocksky",
3
- "tag": "bindings-v0.1.0",
3
+ "tag": "bindings-v0.2.0",
4
4
  "checksums": {
5
- "aarch64-apple-darwin": "219b7b12367377f13afba32516102e2f7993f32de5a73bbb8a0194aa88dc343a",
6
- "aarch64-linux-gnu": "5da500cd45bdd8cb3d1caa5cbf59c48c7fccbd8ea6fbb2c3f86d069ffc1e163d",
7
- "x86_64-apple-darwin": "1c73239d7f8124d53643df68067a82ba88ae3f9ef8a2f692ab59e70f60c58a1a",
8
- "x86_64-linux-gnu": "9e651b38e5a1cc1766d4ab14cb0e337c6dc0a3fd0b70a6a6dfe5aee064d806df",
9
- "x86_64-unknown-freebsd": "f52e23181f1d8143f067b1b6d9f7318db5dce3a34f22701f94c2857235cacd45",
10
- "x86_64-unknown-netbsd": "98ad3408c4c59a8a98a30e5a8531542e3e8479e1fb210761a07c24710b67bb98"
5
+ "aarch64-apple-darwin": "3fc61d1194d66f58eaea8b82643bbdcd705ab80a626e38975a3c0d66ea14047d",
6
+ "aarch64-linux-gnu": "4e6f003fb0c45eba7a675b81cc76b084dc770333b2d8c676b2123d19e78f89a0",
7
+ "x86_64-apple-darwin": "a90563838920ef3575b1af55062e5f1bddcd124ba0d4b9bd50b5639ab6c4ed4e",
8
+ "x86_64-linux-gnu": "98c2df9ff416fd3f2f0e50e0e48122751ea829f5208f11002ce9fdd85b0fbe5f",
9
+ "x86_64-unknown-freebsd": "5ad9efc806706ba51cb7f1fe0e678eb97e03e2dd218fec9fe7e7ab29e0efcb68",
10
+ "x86_64-unknown-netbsd": "f82db46965ea7872085920d37f4a854f7f882e0efa257df9a11dd3e2f7cebf48"
11
11
  }
12
12
  }
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Rocksky
4
- VERSION = "0.4.1"
4
+ VERSION = "0.5.0"
5
5
  end
data/lib/rocksky.rb CHANGED
@@ -26,12 +26,19 @@ module Rocksky
26
26
  "char* rocksky_scrobbles(const char*, const char*, unsigned int, unsigned int)",
27
27
  "char* rocksky_top_tracks(const char*, unsigned int, unsigned int)",
28
28
  "char* rocksky_global_stats(const char*)",
29
+ "char* rocksky_get(const char*, const char*, const char*, const char*)",
30
+ "char* rocksky_match_song(const char*, const char*, const char*, const char*, const char*)",
31
+ "char* rocksky_top_tracks_interval(const char*, unsigned int, unsigned int, const char*, unsigned int, const char*, const char*)",
32
+ "char* rocksky_top_artists_interval(const char*, unsigned int, unsigned int, const char*, unsigned int, const char*, const char*)",
29
33
  "char* rocksky_song_hash(const char*, const char*, const char*)",
30
34
  "void rocksky_string_free(void*)",
31
35
  "char* rocksky_last_error()",
32
- "void* rocksky_agent_login(const char*, const char*, const char*, const char*)",
36
+ "void* rocksky_agent_login(const char*, const char*, const char*, const char*, const char*)",
33
37
  "void rocksky_agent_free(void*)",
34
38
  "char* rocksky_agent_scrobble(void*, const char*)",
39
+ "char* rocksky_agent_scrobble_match(void*, const char*, const char*, const char*, const char*, const char*)",
40
+ "char* rocksky_agent_sync_repo(void*)",
41
+ "char* rocksky_agent_hydrate_from_jetstream(void*)",
35
42
  "char* rocksky_agent_like(void*, const char*, const char*)",
36
43
  "char* rocksky_agent_follow(void*, const char*)",
37
44
  "char* rocksky_agent_shout(void*, const char*, const char*, const char*)",
@@ -82,6 +89,53 @@ module Rocksky
82
89
  unwrap(C.rocksky_global_stats(base.to_s))
83
90
  end
84
91
 
92
+ # Universal read escape hatch — call any app.rocksky.* query by nsid. +params+
93
+ # is a hash of string params; the whole read-query catalog is reachable here.
94
+ #
95
+ # Rocksky.get("app.rocksky.album.getAlbum", { uri: uri })
96
+ # Rocksky.get("app.rocksky.charts.getScrobblesChart", { did: did })
97
+ # +token+, when given, is sent as an Authorization: Bearer header — needed for
98
+ # auth-gated queries.
99
+ def self.get(nsid, params = {}, base: nil, token: nil)
100
+ unwrap(C.rocksky_get(base.to_s, nsid, JSON.generate(params), token.to_s))
101
+ end
102
+
103
+ # Resolve full canonical metadata for a bare title + artist (matchSong).
104
+ def self.match_song(title, artist, mb_id: nil, isrc: nil, base: nil)
105
+ unwrap(C.rocksky_match_song(base.to_s, title, artist, mb_id.to_s, isrc.to_s))
106
+ end
107
+
108
+ # Top tracks chart over a typed date window. +interval+ is +:all+, or a pair
109
+ # like +[:days, 7]+ / +[:weeks, 4]+ / +[:months, 1]+ / +[:years, 1]+, or
110
+ # +[:range, start_rfc3339, end_rfc3339]+.
111
+ #
112
+ # Rocksky.top_tracks_interval(limit: 10, interval: [:days, 7])
113
+ def self.top_tracks_interval(limit: 50, offset: 0, interval: :all, base: nil)
114
+ unit, n, s, e = interval_parts(interval)
115
+ unwrap(C.rocksky_top_tracks_interval(base.to_s, limit, offset, unit, n, s, e))
116
+ end
117
+
118
+ # Top artists chart over a typed date window (see .top_tracks_interval).
119
+ def self.top_artists_interval(limit: 50, offset: 0, interval: :all, base: nil)
120
+ unit, n, s, e = interval_parts(interval)
121
+ unwrap(C.rocksky_top_artists_interval(base.to_s, limit, offset, unit, n, s, e))
122
+ end
123
+
124
+ # Normalize an interval into (unit, n, start, end) for the native call.
125
+ def self.interval_parts(interval)
126
+ case interval
127
+ when :all, nil then ["all", 0, "", ""]
128
+ when Array
129
+ kind, a, b = interval
130
+ return ["range", 0, a.to_s, b.to_s] if kind == :range
131
+
132
+ [kind.to_s, Integer(a), "", ""]
133
+ else
134
+ raise Error, "invalid interval: #{interval.inspect}"
135
+ end
136
+ end
137
+ private_class_method :interval_parts
138
+
85
139
  # Identity hash — identical across every Rocksky SDK.
86
140
  def self.song_hash(title, artist, album)
87
141
  take_string(C.rocksky_song_hash(title, artist, album))
@@ -92,8 +146,10 @@ module Rocksky
92
146
  # Records are passed as Hashes with camelCase keys (title, artist, album,
93
147
  # albumArtist, durationMs, …), matching the wire record shape.
94
148
  class Agent
95
- def self.login(session_path, identifier, password, appview: nil)
96
- ptr = C.rocksky_agent_login(session_path, identifier, password, appview.to_s)
149
+ # +dedup_path+ enables the local dedup index (needed for #sync_repo /
150
+ # #hydrate_from_jetstream).
151
+ def self.login(session_path, identifier, password, appview: nil, dedup_path: nil)
152
+ ptr = C.rocksky_agent_login(session_path, identifier, password, appview.to_s, dedup_path.to_s)
97
153
  raise Error, (Rocksky.take_string(C.rocksky_last_error()) || "login failed") if ptr.null?
98
154
 
99
155
  new(ptr)
@@ -108,6 +164,23 @@ module Rocksky
108
164
  Rocksky.unwrap(C.rocksky_agent_scrobble(@ptr, JSON.generate(track)))
109
165
  end
110
166
 
167
+ # Scrobble from just a title + artist (album optional, plus optional mb_id /
168
+ # isrc anchors): resolve full metadata via matchSong, then fan out.
169
+ def scrobble_match(title, artist, album: nil, mb_id: nil, isrc: nil)
170
+ Rocksky.unwrap(C.rocksky_agent_scrobble_match(@ptr, title, artist, album.to_s, mb_id.to_s, isrc.to_s))
171
+ end
172
+
173
+ # Download the caller's repo and (re)build the local dedup index (needs a
174
+ # dedup_path at login). Returns the per-collection counts.
175
+ def sync_repo
176
+ Rocksky.unwrap(C.rocksky_agent_sync_repo(@ptr))
177
+ end
178
+
179
+ # Keep the local dedup index hydrated from Jetstream in the background.
180
+ def hydrate_from_jetstream
181
+ Rocksky.unwrap(C.rocksky_agent_hydrate_from_jetstream(@ptr))
182
+ end
183
+
111
184
  def like(uri, cid)
112
185
  Rocksky.unwrap(C.rocksky_agent_like(@ptr, uri, cid))
113
186
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rocksky
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.1
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rocksky