A decentralized music tracking and discovery platform built on AT Protocol 馃幍
at feat/like-scrobble 105 lines 2.7 kB view raw
1import { TID } from "@atproto/common"; 2import chalk from "chalk"; 3import type { Context } from "context"; 4import { eq } from "drizzle-orm"; 5import * as Playlist from "lexicon/types/app/rocksky/playlist"; 6import { createAgent } from "lib/agent"; 7import { StringCodec } from "nats"; 8import tables from "schema"; 9 10export function onNewPlaylist(ctx: Context) { 11 const sc = StringCodec(); 12 const sub = ctx.nc.subscribe("rocksky.playlist"); 13 (async () => { 14 for await (const m of sub) { 15 const payload: { 16 id: string; 17 did: string; 18 } = JSON.parse(sc.decode(m.data)); 19 console.log( 20 `New playlist: ${chalk.cyan(payload.did)} - ${chalk.greenBright(payload.id)}`, 21 ); 22 await putPlaylistRecord(ctx, payload); 23 } 24 })(); 25} 26 27async function putPlaylistRecord( 28 ctx: Context, 29 payload: { id: string; did: string }, 30) { 31 const agent = await createAgent(ctx.oauthClient, payload.did); 32 33 if (!agent) { 34 console.error( 35 `Failed to create agent, skipping playlist: ${chalk.cyan(payload.id)} for ${chalk.greenBright(payload.did)}`, 36 ); 37 return; 38 } 39 40 const [playlist] = await ctx.db 41 .select() 42 .from(tables.playlists) 43 .where(eq(tables.playlists.id, payload.id)) 44 .execute(); 45 46 let rkey = TID.nextStr(); 47 48 if (playlist.uri) { 49 rkey = playlist.uri.split("/").pop(); 50 } 51 52 const record: { 53 $type: string; 54 name: string; 55 description?: string; 56 createdAt: string; 57 pictureUrl?: string; 58 spotifyLink?: string; 59 tidalLink?: string; 60 appleMusicLink?: string; 61 youtubeLink?: string; 62 } = { 63 $type: "app.rocksky.playlist", 64 name: playlist.name, 65 description: playlist.description, 66 createdAt: new Date().toISOString(), 67 pictureUrl: playlist.picture, 68 spotifyLink: playlist.spotifyLink, 69 }; 70 71 if (!Playlist.validateRecord(record)) { 72 console.error(`Invalid record: ${chalk.redBright(JSON.stringify(record))}`); 73 return; 74 } 75 76 try { 77 const res = await agent.com.atproto.repo.putRecord({ 78 repo: agent.assertDid, 79 collection: "app.rocksky.playlist", 80 rkey, 81 record, 82 validate: false, 83 }); 84 const uri = res.data.uri; 85 console.log(`Playlist record created: ${chalk.greenBright(uri)}`); 86 await ctx.db 87 .update(tables.playlists) 88 .set({ uri }) 89 .where(eq(tables.playlists.id, payload.id)) 90 .execute(); 91 } catch (e) { 92 console.error(`Failed to put record: ${chalk.redBright(e.message)}`); 93 } 94 95 const [updatedPlaylist] = await ctx.db 96 .select() 97 .from(tables.playlists) 98 .where(eq(tables.playlists.id, payload.id)) 99 .execute(); 100 101 await ctx.meilisearch.post( 102 `indexes/playlists/documents?primaryKey=id`, 103 updatedPlaylist, 104 ); 105}