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