A decentralized music tracking and discovery platform built on AT Protocol 馃幍
rocksky.app
spotify
atproto
lastfm
musicbrainz
scrobbling
listenbrainz
1import chalk from "chalk";
2import { RockskyClient } from "client";
3import fs from "fs/promises";
4import md5 from "md5";
5import os from "os";
6import path from "path";
7
8export async function scrobble(track, artist, { timestamp }) {
9 const tokenPath = path.join(os.homedir(), ".rocksky", "token.json");
10 try {
11 await fs.access(tokenPath);
12 } catch (err) {
13 console.error(
14 `You are not logged in. Please run ${chalk.greenBright(
15 "`rocksky login <username>.bsky.social`"
16 )} first.`
17 );
18 return;
19 }
20
21 const tokenData = await fs.readFile(tokenPath, "utf-8");
22 const { token } = JSON.parse(tokenData);
23 if (!token) {
24 console.error(
25 `You are not logged in. Please run ${chalk.greenBright(
26 "`rocksky login <username>.bsky.social`"
27 )} first.`
28 );
29 return;
30 }
31
32 const client = new RockskyClient(token);
33 const apikeys = await client.getApiKeys();
34
35 if (!apikeys || apikeys.length === 0 || !apikeys[0].enabled) {
36 console.error(
37 `You don't have any API keys. Please create one using ${chalk.greenBright(
38 "`rocksky create apikey`"
39 )} command.`
40 );
41 return;
42 }
43
44 const signature = md5(
45 `api_key${
46 apikeys[0].apiKey
47 }artist[0]${artist}methodtrack.scrobblesk${token}timestamp[0]${
48 timestamp || Math.floor(Date.now() / 1000)
49 }track[0]${track}${apikeys[0].sharedSecret}`
50 );
51
52 const response = await client.scrobble(
53 apikeys[0].apiKey,
54 signature,
55 track,
56 artist,
57 timestamp
58 );
59
60 console.log(
61 `Scrobbled ${chalk.greenBright(track)} by ${chalk.greenBright(
62 artist
63 )} at ${chalk.greenBright(
64 new Date(
65 (timestamp || Math.floor(Date.now() / 1000)) * 1000
66 ).toLocaleString()
67 )}`
68 );
69}