Something went wrong. Try again.
A decentralized music tracking and discovery platform built on AT Protocol ๐ต rocksky.app
spotify atproto lastfm musicbrainz scrobbling listenbrainz
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139import { ctx } from "context";import { eq, or } from "drizzle-orm";import { Hono } from "hono";import albums, { type SelectAlbum } from "schema/albums";import artists, { type SelectArtist } from "schema/artists";import scrobbles from "schema/scrobbles";import tracks, { type SelectTrack } from "schema/tracks";import users from "schema/users";
const app = new Hono();
app.get("/", async (c) => { const path = c.req.query("path");
if (!path) { return c.text("OG Service: please provide a path query parameter.", 400); }
let m = path.match(/^\/profile\/([^/]+)$/); if (m) { const handle = decodeURIComponent(m[1]); const user = await ctx.readDb .select() .from(users) .where(or(eq(users.handle, handle), eq(users.did, handle))) .limit(1) .execute() .then(([row]) => row); if (!user) { return c.text("OG Service: user not found.", 404); } return c.json({ title: `@${user.handle} on Rocksky`, description: "Rocksky user profile โ recent scrobbles, top artists, albums, and tracks.", image: user.avatar.endsWith("/@jpeg") ? undefined : user.avatar, url: `https://rocksky.app/profile/${user.handle}`, type: "website", twitterCard: "summary_large_image", }); }
m = path.match(/^\/(did:plc:[^/]+)\/(scrobble|album|artist|song)\/([^/]+)$/); if (m) { const did = decodeURIComponent(m[1]); const kind = m[2] as "scrobble" | "album" | "artist" | "song"; const rkey = decodeURIComponent(m[3]); const uri = `at://${did}/app.rocksky.${kind}/${rkey}`;
const tableMap = { scrobble: scrobbles, album: albums, artist: artists, song: tracks, };
const table = tableMap[kind]; if (kind === "scrobble") { const record = await ctx.readDb .select({ scrobbles: scrobbles, users: users, tracks: tracks, artists: artists, albums: albums, }) .from(table) .where(eq(table.uri, uri)) .leftJoin(users, eq(scrobbles.userId, users.id)) .leftJoin(tracks, eq(scrobbles.trackId, tracks.id)) .leftJoin(artists, eq(scrobbles.artistId, artists.id)) .leftJoin(albums, eq(scrobbles.albumId, albums.id)) .limit(1) .execute() .then(([row]) => row);
if (!record) { return c.text("OG Service: record not found.", 404); }
return c.json({ title: `Scrobble: ${record.tracks.title} by ${record.artists.name}`, description: `A listening activity (scrobble) - ${record.tracks.title} - ${record.artists.name} by @${record.users.handle} on Rocksky.`, image: record.albums.albumArt, url: `https://rocksky.app/${did}/scrobble/${rkey}`, type: "website", twitterCard: "summary_large_image", }); }
const record = await ctx.readDb .select() .from(table) .where(eq(table.uri, uri)) .limit(1) .execute() .then(([row]) => row); if (!record) { return c.text("OG Service: record not found.", 404); }
let title; let description; let image; const url = `https://rocksky.app/${did}/${kind}/${rkey}`;
if (kind === "album") { title = `Album: ${(record as SelectAlbum).title} by ${(record as SelectAlbum).artist}`; description = `See listening stats and favorites for ${(record as SelectAlbum).title} by ${(record as SelectAlbum).artist} on Rocksky.`; image = (record as SelectAlbum).albumArt; }
if (kind === "artist") { title = `Artist: ${(record as SelectArtist).name}`; description = `See listening stats and favorites for ${(record as SelectArtist).name} on Rocksky.`; image = (record as SelectArtist).picture; }
if (kind === "song") { title = `Track: ${(record as SelectTrack).title} by ${(record as SelectTrack).artist}`; description = `See listening stats and favorites for ${(record as SelectTrack).title} by ${(record as SelectTrack).artist} on Rocksky.`; image = (record as SelectTrack).albumArt; }
return c.json({ title, description, image, url, type: "website", twitterCard: "summary_large_image", }); }
return c.text("OG Service: unsupported path format.", 400);});
export default app;