Gleam Library for the Rocksky API

implement get_track function

Changed files
+237 -4
src
rocksky
resources
test
+73
replay_mocks.json
··· 1934 1934 ], 1935 1935 "body": "{\"name\":\"Kiesza\",\"picture\":\"https://i.scdn.co/image/ab6761610000e5ebf8449085dadabebe939997a1\",\"sha256\":\"85291a57793af605e54f78cd6e1d37e28896711fb23001ec9e7caf8bf5254821\",\"uri\":\"at://did:plc:7vdlgi2bflelz7mmuxoqjfcr/app.rocksky.artist/3liorhapngk23\",\"xata_createdat\":\"2025-02-21T12:06:22.709Z\",\"xata_updatedat\":\"2025-04-22T18:16:09.245Z\",\"xata_version\":393,\"apple_music_link\":null,\"biography\":null,\"born\":null,\"born_in\":null,\"died\":null,\"spotify_link\":null,\"tidal_link\":null,\"youtube_link\":null,\"id\":\"rec_cus6ofnu3busimrou51g\",\"listeners\":1,\"scrobbles\":163,\"tags\":[]}" 1936 1936 } 1937 + }, 1938 + { 1939 + "request": { 1940 + "timestamp": 1746392351, 1941 + "method": "GET", 1942 + "path": "/users/did:plc:7vdlgi2bflelz7mmuxoqjfcr/app.rocksky.song/3lhtyr34rnk2h", 1943 + "query_params": null, 1944 + "headers": [ 1945 + [ 1946 + "content-length", 1947 + "0" 1948 + ], 1949 + [ 1950 + "user-agent", 1951 + "gleam_httpc/4.1.0" 1952 + ], 1953 + [ 1954 + "te", 1955 + "" 1956 + ], 1957 + [ 1958 + "host", 1959 + "localhost:6677" 1960 + ], 1961 + [ 1962 + "authorization", 1963 + "Bearer" 1964 + ], 1965 + [ 1966 + "connection", 1967 + "close" 1968 + ] 1969 + ], 1970 + "body": "" 1971 + }, 1972 + "response": { 1973 + "status": 200, 1974 + "headers": [ 1975 + [ 1976 + "access-control-allow-origin", 1977 + "*" 1978 + ], 1979 + [ 1980 + "alt-svc", 1981 + "h3=\":443\"; ma=2592000" 1982 + ], 1983 + [ 1984 + "content-length", 1985 + "2332" 1986 + ], 1987 + [ 1988 + "content-type", 1989 + "application/json" 1990 + ], 1991 + [ 1992 + "date", 1993 + "Sun, 04 May 2025 20:59:13 GMT" 1994 + ], 1995 + [ 1996 + "via", 1997 + "1.1 Caddy" 1998 + ], 1999 + [ 2000 + "x-ratelimit-limit", 2001 + "1000" 2002 + ], 2003 + [ 2004 + "x-ratelimit-remaining", 2005 + "992" 2006 + ] 2007 + ], 2008 + "body": "{\"album\":\"Bad Dream\",\"album_art\":\"https://cdn.rocksky.app/covers/cc969b71214e8e8fb65fbfd5892dabcb.jpg\",\"album_artist\":\"Cannons\",\"album_uri\":\"at://did:plc:7vdlgi2bflelz7mmuxoqjfcr/app.rocksky.album/3lhtyr5qjdk2h\",\"artist\":\"Cannons\",\"artist_uri\":\"at://did:plc:7vdlgi2bflelz7mmuxoqjfcr/app.rocksky.artist/3lhluehwa2c2k\",\"composer\":\"Michelle Lewis, Ryan Clapham, Paul Daniel Davis\",\"copyright_message\":\"(P) 2021 Cannons, under exclusive license to Columbia Records, a Division of Sony Music Entertainment\",\"disc_number\":1,\"duration\":202616,\"lyrics\":\"[00:00.28] I bought a ticket to your show\\n[00:04.36] Did you see me? Did you know?\\n[00:08.65] I was standing in the back row (back row, back row)\\n[00:12.83] With the lights down low\\n[00:16.84] I couldn't think of the right words\\n[00:21.00] Now it's just too late\\n[00:25.28] Now you're somebody's baby\\n[00:29.04] So I'll be on my way\\n[00:33.60] I been living in a bad dream\\n[00:38.78] \\n[00:42.03] I been living in a bad, bad dream\\n[00:50.08] I wish that somebody would wake me\\n[00:54.11] Don't like this feeling, won't you shake me?\\n[00:58.56] 'Cause anymore might break me (break me, break me)\\n[01:02.95] And you'll never know\\n[01:07.06] I couldn't think of the right words\\n[01:11.02] Now it's just too late\\n[01:15.45] Now you're somebody's baby\\n[01:19.13] So I'll be on my way\\n[01:23.62] I been living in a bad dream\\n[01:27.89] \\n[01:32.14] I been living in a bad, bad dream\\n[01:40.20] Sleepwalking through a sad scene\\n[01:45.78] \\n[01:48.60] I been living in a bad, bad dream\\n[01:55.62] \\n[02:30.51] I been living in a bad dream\\n[02:35.75] \\n[02:38.73] I been living in a bad, bad dream\\n[02:44.63] \\n[02:46.93] Sleepwalking through a sad scene\\n[02:51.74] \\n[02:55.49] I been living in a bad, bad dream\\n[03:01.78] \\n[03:03.88] I been living in a bad dream\\n[03:06.73] \",\"sha256\":\"721b08ec2ab67af85ef024ff5333b4fae9d7f2f258b2c399d32c2683243486b4\",\"title\":\"Bad Dream\",\"track_number\":1,\"uri\":\"at://did:plc:7vdlgi2bflelz7mmuxoqjfcr/app.rocksky.song/3lhtyr34rnk2h\",\"xata_createdat\":\"2025-02-10T20:11:36.377Z\",\"xata_updatedat\":\"2025-04-21T16:23:08.817Z\",\"xata_version\":73,\"apple_music_link\":null,\"genre\":null,\"label\":null,\"mb_id\":null,\"spotify_link\":null,\"tidal_link\":null,\"youtube_link\":null,\"id\":\"rec_cul5qu365asp6a7ql7gg\",\"tags\":[],\"listeners\":1,\"scrobbles\":35}" 2009 + } 1937 2010 } 1938 2011 ]
+6 -4
src/rocksky.gleam
··· 1 - import gleam/option.{None, Some} 1 + import gleam/option.{None} 2 2 import rocksky/client/base 3 - import rocksky/resources/scrobbles 3 + import rocksky/resources/tracks.{get_track} 4 4 5 5 pub fn main() { 6 6 let client = base.new(None, None) 7 7 8 - scrobbles.new(client) 9 - |> scrobbles.get_scrobbles(Some("tsiry-sandratraina.com")) 8 + get_track( 9 + tracks.new(client), 10 + "did:plc:7vdlgi2bflelz7mmuxoqjfcr/app.rocksky.song/3lhtyr34rnk2h", 11 + ) 10 12 |> echo 11 13 }
+142
src/rocksky/resources/tracks.gleam
··· 99 99 } 100 100 } 101 101 } 102 + 103 + pub fn get_track( 104 + resource: TrackResource, 105 + uri: String, 106 + ) -> Result(Track, errors.ApiError) { 107 + let path = 108 + resource.base_path |> string.replace("{did}/tracks", "") 109 + <> string.replace(uri, "at://", "") 110 + let client = resource.client 111 + 112 + case base_client.get(client, path, None) { 113 + Ok(res) -> { 114 + let track_decoder = { 115 + use album <- decode.field("album", decode.string) 116 + use album_art <- decode.field( 117 + "album_art", 118 + decode.optional(decode.string), 119 + ) 120 + use album_artist <- decode.field("album_artist", decode.string) 121 + use artist <- decode.field("artist", decode.string) 122 + use composer <- decode.optional_field( 123 + "composer", 124 + None, 125 + decode.optional(decode.string), 126 + ) 127 + use copyright_message <- decode.optional_field( 128 + "copyright_message", 129 + None, 130 + decode.optional(decode.string), 131 + ) 132 + use disc_number <- decode.field("disc_number", decode.int) 133 + use duration <- decode.field("duration", decode.int) 134 + use sha256 <- decode.field("sha256", decode.string) 135 + use title <- decode.field("title", decode.string) 136 + use track_number <- decode.field("track_number", decode.int) 137 + use xata_createdat <- decode.field("xata_createdat", decode.string) 138 + use id <- decode.field("id", decode.string) 139 + use xata_updatedat <- decode.field("xata_updatedat", decode.string) 140 + use xata_version <- decode.field("xata_version", decode.int) 141 + use album_uri <- decode.optional_field( 142 + "album_uri", 143 + None, 144 + decode.optional(decode.string), 145 + ) 146 + use apple_music_link <- decode.optional_field( 147 + "apple_music_link", 148 + None, 149 + decode.optional(decode.string), 150 + ) 151 + use artist_uri <- decode.optional_field( 152 + "artist_uri", 153 + None, 154 + decode.optional(decode.string), 155 + ) 156 + use genre <- decode.optional_field( 157 + "genre", 158 + None, 159 + decode.optional(decode.string), 160 + ) 161 + use label <- decode.optional_field( 162 + "label", 163 + None, 164 + decode.optional(decode.string), 165 + ) 166 + use lyrics <- decode.optional_field( 167 + "lyrics", 168 + None, 169 + decode.optional(decode.string), 170 + ) 171 + use mb_id <- decode.optional_field( 172 + "mb_id", 173 + None, 174 + decode.optional(decode.string), 175 + ) 176 + use spotify_link <- decode.optional_field( 177 + "spotify_link", 178 + None, 179 + decode.optional(decode.string), 180 + ) 181 + use tidal_link <- decode.optional_field( 182 + "tidal_link", 183 + None, 184 + decode.optional(decode.string), 185 + ) 186 + use uri <- decode.optional_field( 187 + "uri", 188 + None, 189 + decode.optional(decode.string), 190 + ) 191 + use youtube_link <- decode.optional_field( 192 + "youtube_link", 193 + None, 194 + decode.optional(decode.string), 195 + ) 196 + use listeners <- decode.field("listeners", decode.int) 197 + use scrobbles <- decode.field("scrobbles", decode.int) 198 + decode.success(track.TrackDetails( 199 + album:, 200 + album_art:, 201 + album_artist:, 202 + artist:, 203 + composer:, 204 + copyright_message:, 205 + disc_number:, 206 + duration:, 207 + sha256:, 208 + title:, 209 + track_number:, 210 + xata_createdat:, 211 + id:, 212 + xata_updatedat:, 213 + xata_version:, 214 + album_uri:, 215 + apple_music_link:, 216 + artist_uri:, 217 + genre:, 218 + label:, 219 + lyrics:, 220 + mb_id:, 221 + spotify_link:, 222 + tidal_link:, 223 + uri:, 224 + youtube_link:, 225 + listeners:, 226 + scrobbles:, 227 + )) 228 + } 229 + case json.parse(from: res.body, using: track_decoder) { 230 + Ok(track) -> { 231 + Ok(track) 232 + } 233 + Error(err) -> { 234 + echo err 235 + Error(errors.JsonParseError("Failed to decode track")) 236 + } 237 + } 238 + } 239 + Error(error) -> { 240 + Error(error) 241 + } 242 + } 243 + }
+16
test/rocksky_test.gleam
··· 162 162 ) 163 163 |> should.be_ok 164 164 } 165 + 166 + pub fn get_track_test() { 167 + let client = base.from_url(base_url, None, None) 168 + 169 + tracks.new(client) 170 + |> tracks.get_track( 171 + "did:plc:7vdlgi2bflelz7mmuxoqjfcr/app.rocksky.song/3lhtyr34rnk2h", 172 + ) 173 + |> should.be_ok 174 + 175 + tracks.new(client) 176 + |> tracks.get_track( 177 + "at://did:plc:7vdlgi2bflelz7mmuxoqjfcr/app.rocksky.song/3lhtyr34rnk2h", 178 + ) 179 + |> should.be_ok 180 + }