forked from
rocksky.app/rocksky
A decentralized music tracking and discovery platform built on AT Protocol 馃幍
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}