forked from
rocksky.app/rocksky
A decentralized music tracking and discovery platform built on AT Protocol 馃幍
1import chalk from "chalk";
2import { consola } from "consola";
3import { ctx } from "context";
4import { eq } from "drizzle-orm";
5import { createAgent } from "lib/agent";
6import tables from "schema";
7
8const args = process.argv.slice(2);
9
10if (args.length === 0) {
11 consola.error("Please provide user author identifier (handle or DID).");
12 consola.info(`Usage: ${chalk.cyan("npm run feed -- <handle|did>")}`);
13 process.exit(1);
14}
15
16let did = args[0];
17
18if (!did.startsWith("did:plc:")) {
19 did = await ctx.baseIdResolver.handle.resolve(did);
20}
21
22const agent = await createAgent(ctx.oauthClient, did);
23let cursor: string | undefined;
24const BATCH_SIZE = 100;
25let i = 1;
26do {
27 const records = await agent.com.atproto.repo.listRecords({
28 repo: agent.assertDid,
29 collection: "app.rocksky.scrobble",
30 limit: BATCH_SIZE,
31 });
32
33 for (const record of records.data.records) {
34 const result = await ctx.db
35 .select()
36 .from(tables.scrobbles)
37 .where(eq(tables.scrobbles.uri, record.uri))
38 .limit(1);
39 if (result.length === 0) {
40 consola.info(`${i} Deleting record:`);
41 consola.info(record);
42 const rkey = record.uri.split("/").pop();
43 await agent.com.atproto.repo.deleteRecord({
44 repo: agent.assertDid,
45 collection: "app.rocksky.scrobble",
46 rkey,
47 });
48 await new Promise((resolve) => setTimeout(resolve, 1000)); // rate limit
49 } else {
50 consola.info(chalk.greenBright(`${i} Keeping record:`));
51 consola.info(record);
52 }
53 i += 1;
54 }
55 cursor = records.data.cursor;
56} while (cursor);
57
58consola.info(chalk.greenBright("Deduplication complete."));
59
60process.exit(0);