tangled
alpha
login
or
join now
rocksky.app
/
rocksky
96
fork
atom
A decentralized music tracking and discovery platform built on AT Protocol 🎵
rocksky.app
spotify
atproto
lastfm
musicbrainz
scrobbling
listenbrainz
96
fork
atom
overview
issues
7
pulls
pipelines
chore: lint files
tsiry-sandratraina.com
6 months ago
aff62528
f90156f9
+27
-28
6 changed files
expand all
collapse all
unified
split
apps
api
src
xrpc
app
rocksky
spotify
getCurrentlyPlaying.ts
next.ts
pause.ts
play.ts
previous.ts
seek.ts
+14
-14
apps/api/src/xrpc/app/rocksky/spotify/getCurrentlyPlaying.ts
···
23
Effect.catchAll((err) => {
24
console.error(err);
25
return Effect.succeed({});
26
-
}),
27
);
28
server.app.rocksky.spotify.getCurrentlyPlaying({
29
auth: ctx.authVerifier,
···
54
.where(
55
or(
56
eq(tables.users.did, params.actor || did),
57
-
eq(tables.users.handle, params.actor || did),
58
-
),
59
)
60
.execute()
61
.then((users) => ({ user: users[0], ctx, params, did })),
···
90
.from(tables.spotifyAccounts)
91
.leftJoin(
92
tables.users,
93
-
eq(tables.users.id, tables.spotifyAccounts.userId),
94
)
95
.where(
96
or(
97
eq(tables.users.did, params.actor || did),
98
-
eq(tables.users.handle, params.actor || did),
99
-
),
100
)
101
.execute()
102
.then(([results]) => ({
···
129
Match.value(cached).pipe(
130
Match.when(null, () => ({})),
131
Match.when(undefined, () => ({})),
132
-
Match.orElse(() => JSON.parse(cached)),
133
-
),
134
)
135
.then((cached) => [cached, ctx, user]),
136
catch: (error) =>
···
143
try: async () => {
144
const sha256 = createHash("sha256")
145
.update(
146
-
`${track.item.name} - ${track.item.artists.map((x) => x.name).join(", ")} - ${track.item.album.name}`.toLowerCase(),
147
)
148
.digest("hex");
149
const [record] = await ctx.db
···
156
.from(tables.lovedTracks)
157
.leftJoin(
158
tables.tracks,
159
-
eq(tables.lovedTracks.trackId, tables.tracks.id),
160
)
161
.leftJoin(tables.users, eq(tables.lovedTracks.userId, tables.users.id))
162
.where(
163
-
and(eq(tables.tracks.sha256, sha256), eq(tables.users.did, user.did)),
164
)
165
.execute()
166
.then((results) =>
167
Match.value(track).pipe(
168
Match.when(
169
(t) => !Object.keys(t).length,
170
-
() => ({}),
171
),
172
Match.orElse(() => ({
173
...track,
···
175
artistUri: record?.artistUri,
176
albumUri: record?.albumUri,
177
liked: results.length > 0,
178
-
})),
179
-
),
180
);
181
},
182
catch: (error) => new Error(`Failed to retrieve URI and likes: ${error}`),
···
23
Effect.catchAll((err) => {
24
console.error(err);
25
return Effect.succeed({});
26
+
})
27
);
28
server.app.rocksky.spotify.getCurrentlyPlaying({
29
auth: ctx.authVerifier,
···
54
.where(
55
or(
56
eq(tables.users.did, params.actor || did),
57
+
eq(tables.users.handle, params.actor || did)
58
+
)
59
)
60
.execute()
61
.then((users) => ({ user: users[0], ctx, params, did })),
···
90
.from(tables.spotifyAccounts)
91
.leftJoin(
92
tables.users,
93
+
eq(tables.users.id, tables.spotifyAccounts.userId)
94
)
95
.where(
96
or(
97
eq(tables.users.did, params.actor || did),
98
+
eq(tables.users.handle, params.actor || did)
99
+
)
100
)
101
.execute()
102
.then(([results]) => ({
···
129
Match.value(cached).pipe(
130
Match.when(null, () => ({})),
131
Match.when(undefined, () => ({})),
132
+
Match.orElse(() => JSON.parse(cached))
133
+
)
134
)
135
.then((cached) => [cached, ctx, user]),
136
catch: (error) =>
···
143
try: async () => {
144
const sha256 = createHash("sha256")
145
.update(
146
+
`${track.item.name} - ${track.item.artists.map((x) => x.name).join(", ")} - ${track.item.album.name}`.toLowerCase()
147
)
148
.digest("hex");
149
const [record] = await ctx.db
···
156
.from(tables.lovedTracks)
157
.leftJoin(
158
tables.tracks,
159
+
eq(tables.lovedTracks.trackId, tables.tracks.id)
160
)
161
.leftJoin(tables.users, eq(tables.lovedTracks.userId, tables.users.id))
162
.where(
163
+
and(eq(tables.tracks.sha256, sha256), eq(tables.users.did, user.did))
164
)
165
.execute()
166
.then((results) =>
167
Match.value(track).pipe(
168
Match.when(
169
(t) => !Object.keys(t).length,
170
+
() => ({})
171
),
172
Match.orElse(() => ({
173
...track,
···
175
artistUri: record?.artistUri,
176
albumUri: record?.albumUri,
177
liked: results.length > 0,
178
+
}))
179
+
)
180
);
181
},
182
catch: (error) => new Error(`Failed to retrieve URI and likes: ${error}`),
+3
-3
apps/api/src/xrpc/app/rocksky/spotify/next.ts
···
23
Effect.catchAll((err) => {
24
console.error(err);
25
return Effect.succeed({});
26
-
}),
27
);
28
server.app.rocksky.spotify.next({
29
auth: ctx.authVerifier,
···
72
.where(eq(tables.spotifyTokens.userId, user.id))
73
.execute()
74
.then(([spotifyToken]) =>
75
-
decrypt(spotifyToken.refreshToken, env.SPOTIFY_ENCRYPTION_KEY),
76
)
77
.then((refreshToken) => ({
78
user,
···
105
client_secret: env.SPOTIFY_CLIENT_SECRET,
106
}),
107
})
108
-
.then((res) => res.json())
109
.then((data) => data.access_token),
110
catch: (error) => new Error(`Failed to retrieve Spotify token: ${error}`),
111
});
···
23
Effect.catchAll((err) => {
24
console.error(err);
25
return Effect.succeed({});
26
+
})
27
);
28
server.app.rocksky.spotify.next({
29
auth: ctx.authVerifier,
···
72
.where(eq(tables.spotifyTokens.userId, user.id))
73
.execute()
74
.then(([spotifyToken]) =>
75
+
decrypt(spotifyToken.refreshToken, env.SPOTIFY_ENCRYPTION_KEY)
76
)
77
.then((refreshToken) => ({
78
user,
···
105
client_secret: env.SPOTIFY_CLIENT_SECRET,
106
}),
107
})
108
+
.then((res) => res.json() as Promise<{ access_token: string }>)
109
.then((data) => data.access_token),
110
catch: (error) => new Error(`Failed to retrieve Spotify token: ${error}`),
111
});
+3
-4
apps/api/src/xrpc/app/rocksky/spotify/pause.ts
···
23
Effect.catchAll((err) => {
24
console.error(err);
25
return Effect.succeed({});
26
-
}),
27
);
28
server.app.rocksky.spotify.pause({
29
auth: ctx.authVerifier,
···
72
.where(eq(tables.spotifyTokens.userId, user.id))
73
.execute()
74
.then(([spotifyToken]) =>
75
-
decrypt(spotifyToken.refreshToken, env.SPOTIFY_ENCRYPTION_KEY),
76
)
77
.then((refreshToken) => ({
78
user,
···
86
87
const withSpotifyToken = ({
88
refreshToken,
89
-
ctx,
90
}: {
91
refreshToken: string;
92
ctx: Context;
···
105
client_secret: env.SPOTIFY_CLIENT_SECRET,
106
}),
107
})
108
-
.then((res) => res.json())
109
.then((data) => data.access_token),
110
catch: (error) => new Error(`Failed to retrieve Spotify token: ${error}`),
111
});
···
23
Effect.catchAll((err) => {
24
console.error(err);
25
return Effect.succeed({});
26
+
})
27
);
28
server.app.rocksky.spotify.pause({
29
auth: ctx.authVerifier,
···
72
.where(eq(tables.spotifyTokens.userId, user.id))
73
.execute()
74
.then(([spotifyToken]) =>
75
+
decrypt(spotifyToken.refreshToken, env.SPOTIFY_ENCRYPTION_KEY)
76
)
77
.then((refreshToken) => ({
78
user,
···
86
87
const withSpotifyToken = ({
88
refreshToken,
0
89
}: {
90
refreshToken: string;
91
ctx: Context;
···
104
client_secret: env.SPOTIFY_CLIENT_SECRET,
105
}),
106
})
107
+
.then((res) => res.json() as Promise<{ access_token: string }>)
108
.then((data) => data.access_token),
109
catch: (error) => new Error(`Failed to retrieve Spotify token: ${error}`),
110
});
+3
-3
apps/api/src/xrpc/app/rocksky/spotify/play.ts
···
23
Effect.catchAll((err) => {
24
console.error(err);
25
return Effect.succeed({});
26
-
}),
27
);
28
server.app.rocksky.spotify.play({
29
auth: ctx.authVerifier,
···
72
.where(eq(tables.spotifyTokens.userId, user.id))
73
.execute()
74
.then(([spotifyToken]) =>
75
-
decrypt(spotifyToken.refreshToken, env.SPOTIFY_ENCRYPTION_KEY),
76
)
77
.then((refreshToken) => ({
78
user,
···
105
client_secret: env.SPOTIFY_CLIENT_SECRET,
106
}),
107
})
108
-
.then((res) => res.json())
109
.then((data) => data.access_token),
110
catch: (error) => new Error(`Failed to retrieve Spotify token: ${error}`),
111
});
···
23
Effect.catchAll((err) => {
24
console.error(err);
25
return Effect.succeed({});
26
+
})
27
);
28
server.app.rocksky.spotify.play({
29
auth: ctx.authVerifier,
···
72
.where(eq(tables.spotifyTokens.userId, user.id))
73
.execute()
74
.then(([spotifyToken]) =>
75
+
decrypt(spotifyToken.refreshToken, env.SPOTIFY_ENCRYPTION_KEY)
76
)
77
.then((refreshToken) => ({
78
user,
···
105
client_secret: env.SPOTIFY_CLIENT_SECRET,
106
}),
107
})
108
+
.then((res) => res.json() as Promise<{ access_token: string }>)
109
.then((data) => data.access_token),
110
catch: (error) => new Error(`Failed to retrieve Spotify token: ${error}`),
111
});
+3
-3
apps/api/src/xrpc/app/rocksky/spotify/previous.ts
···
23
Effect.catchAll((err) => {
24
console.error(err);
25
return Effect.succeed({});
26
-
}),
27
);
28
server.app.rocksky.spotify.previous({
29
auth: ctx.authVerifier,
···
72
.where(eq(tables.spotifyTokens.userId, user.id))
73
.execute()
74
.then(([spotifyToken]) =>
75
-
decrypt(spotifyToken.refreshToken, env.SPOTIFY_ENCRYPTION_KEY),
76
)
77
.then((refreshToken) => ({
78
refreshToken,
···
97
client_secret: env.SPOTIFY_CLIENT_SECRET,
98
}),
99
})
100
-
.then((res) => res.json())
101
.then((data) => data.access_token),
102
catch: (error) => new Error(`Failed to retrieve Spotify token: ${error}`),
103
});
···
23
Effect.catchAll((err) => {
24
console.error(err);
25
return Effect.succeed({});
26
+
})
27
);
28
server.app.rocksky.spotify.previous({
29
auth: ctx.authVerifier,
···
72
.where(eq(tables.spotifyTokens.userId, user.id))
73
.execute()
74
.then(([spotifyToken]) =>
75
+
decrypt(spotifyToken.refreshToken, env.SPOTIFY_ENCRYPTION_KEY)
76
)
77
.then((refreshToken) => ({
78
refreshToken,
···
97
client_secret: env.SPOTIFY_CLIENT_SECRET,
98
}),
99
})
100
+
.then((res) => res.json() as Promise<{ access_token: string }>)
101
.then((data) => data.access_token),
102
catch: (error) => new Error(`Failed to retrieve Spotify token: ${error}`),
103
});
+1
-1
apps/api/src/xrpc/app/rocksky/spotify/seek.ts
···
107
client_secret: env.SPOTIFY_CLIENT_SECRET,
108
}),
109
})
110
-
.then((res) => res.json())
111
.then((data) => ({
112
accessToken: data.access_token,
113
position: params.position,
···
107
client_secret: env.SPOTIFY_CLIENT_SECRET,
108
}),
109
})
110
+
.then((res) => res.json() as Promise<{ access_token: string }>)
111
.then((data) => ({
112
accessToken: data.access_token,
113
position: params.position,