A decentralized music tracking and discovery platform built on AT Protocol 馃幍
at fff48ea3213bb11efcfcb7db85be1dfcd2bebc5e 113 lines 3.0 kB view raw
1import chalk from "chalk"; 2import { consola } from "consola"; 3import { ctx } from "context"; 4import type * as FeedGenerator from "lexicon/types/app/rocksky/feed/generator"; 5import { createAgent } from "lib/agent"; 6import prompts from "prompts"; 7 8const args = process.argv.slice(2); 9 10if (args.length === 0) { 11 consola.error("Please provide user author identifier (handle or DID)."); 12 console.log(`Usage: ${chalk.cyan("npm run feed -- <handle|did>")}`); 13 process.exit(1); 14} 15 16const name = await prompts({ 17 type: "text", 18 name: "value", 19 message: "What is the feed name?", 20}); 21 22if (name.value.length < 3 || name.value.length > 240) { 23 consola.error("Feed name must be between 3 and 240 characters."); 24 process.exit(1); 25} 26 27const description = await prompts({ 28 type: "text", 29 name: "value", 30 message: "Please provide a short description of the feed", 31}); 32 33if (description.value.length > 3000) { 34 consola.error("Description is too long. Maximum length is 3000 characters."); 35 process.exit(1); 36} 37 38const did = await prompts({ 39 type: "text", 40 name: "value", 41 message: "What is the feed DID?", 42}); 43 44if (!/^did:web:[a-zA-Z0-9_.-]{3,30}$/.test(did.value)) { 45 consola.error( 46 "Invalid DID format. It should start with 'did:web:' followed by 3 to 30 alphanumeric characters, underscores, hyphens, or periods.", 47 ); 48 process.exit(1); 49} 50 51const rkey = await prompts({ 52 type: "text", 53 name: "value", 54 message: "What is the record key (rkey) for the feed?", 55}); 56 57if (!/^[a-zA-Z0-9_-]{3,30}$/.test(rkey.value)) { 58 consola.error( 59 "Invalid record key. Only alphanumeric characters, underscores, and hyphens are allowed. Length must be between 3 and 30 characters.", 60 ); 61 process.exit(1); 62} 63 64consola.info("Creating feed with the following details:"); 65consola.info("---"); 66consola.info("Feed name:", name.value); 67consola.info("Description:", description.value); 68consola.info("DID:", did.value); 69consola.info("Record key (rkey):", rkey.value); 70 71const confirm = await prompts({ 72 type: "confirm", 73 name: "value", 74 message: "Do you want to proceed?", 75 initial: true, 76}); 77 78if (!confirm.value) { 79 consola.info("Feed creation cancelled."); 80 process.exit(0); 81} 82 83let userDid = args[0]; 84 85if (!userDid.startsWith("did:plc:")) { 86 userDid = await ctx.baseIdResolver.handle.resolve(userDid); 87} 88 89const agent = await createAgent(ctx.oauthClient, userDid); 90 91consola.info( 92 `Writing ${chalk.greenBright("app.rocksky.feed.generator")} record...`, 93); 94 95const record: FeedGenerator.Record = { 96 $type: "app.rocksky.feed.generator", 97 displayName: name.value, 98 description: description.value, 99 did: did.value, 100 createdAt: new Date().toISOString(), 101}; 102 103const res = await agent.com.atproto.repo.createRecord({ 104 repo: agent.assertDid, 105 collection: "app.rocksky.feed.generator", 106 record, 107 rkey: rkey.value, 108}); 109 110consola.info(chalk.greenBright("Feed created successfully!")); 111consola.info(`Record created at: ${chalk.cyan(res.data.uri)}`); 112 113process.exit(0);