A decentralized music tracking and discovery platform built on AT Protocol 🎵

fix: add missing commas in type definitions and function parameters for consistency

+73 -73
+3 -3
apps/api/src/index.ts
··· 46 46 rateLimiter({ 47 47 limit: 1000, 48 48 window: 30, // 👈 30 seconds 49 - }) 49 + }), 50 50 ); 51 51 52 52 app.use("*", async (c, next) => { ··· 161 161 ctx.redis.get(`nowplaying:${user.did}:status`), 162 162 ]); 163 163 return c.json( 164 - nowPlaying ? { ...JSON.parse(nowPlaying), is_playing: status === "1" } : {} 164 + nowPlaying ? { ...JSON.parse(nowPlaying), is_playing: status === "1" } : {}, 165 165 ); 166 166 }); 167 167 ··· 313 313 listeners: 1, 314 314 sha256: item.track.sha256, 315 315 id: item.scrobble.id, 316 - })) 316 + })), 317 317 ); 318 318 }); 319 319
+1 -1
apps/api/src/lexicon/types/app/rocksky/apikey/createApikey.ts
··· 9 9 import type { HandlerAuth, HandlerPipeThrough } from "@atproto/xrpc-server"; 10 10 import type * as AppRockskyApikeyDefs from "./defs"; 11 11 12 - export type QueryParams = {} 12 + export type QueryParams = {}; 13 13 14 14 export interface InputSchema { 15 15 /** The name of the API key. */
+1 -1
apps/api/src/lexicon/types/app/rocksky/apikey/updateApikey.ts
··· 9 9 import type { HandlerAuth, HandlerPipeThrough } from "@atproto/xrpc-server"; 10 10 import type * as AppRockskyApikeyDefs from "./defs"; 11 11 12 - export type QueryParams = {} 12 + export type QueryParams = {}; 13 13 14 14 export interface InputSchema { 15 15 /** The ID of the API key to update. */
+1 -1
apps/api/src/lexicon/types/app/rocksky/like/dislikeShout.ts
··· 9 9 import type { HandlerAuth, HandlerPipeThrough } from "@atproto/xrpc-server"; 10 10 import type * as AppRockskyShoutDefs from "../shout/defs"; 11 11 12 - export type QueryParams = {} 12 + export type QueryParams = {}; 13 13 14 14 export interface InputSchema { 15 15 /** The unique identifier of the shout to dislike */
+1 -1
apps/api/src/lexicon/types/app/rocksky/like/dislikeSong.ts
··· 9 9 import type { HandlerAuth, HandlerPipeThrough } from "@atproto/xrpc-server"; 10 10 import type * as AppRockskySongDefs from "../song/defs"; 11 11 12 - export type QueryParams = {} 12 + export type QueryParams = {}; 13 13 14 14 export interface InputSchema { 15 15 /** The unique identifier of the song to dislike */
+1 -1
apps/api/src/lexicon/types/app/rocksky/like/likeShout.ts
··· 9 9 import type { HandlerAuth, HandlerPipeThrough } from "@atproto/xrpc-server"; 10 10 import type * as AppRockskyShoutDefs from "../shout/defs"; 11 11 12 - export type QueryParams = {} 12 + export type QueryParams = {}; 13 13 14 14 export interface InputSchema { 15 15 /** The unique identifier of the shout to like */
+1 -1
apps/api/src/lexicon/types/app/rocksky/like/likeSong.ts
··· 9 9 import type { HandlerAuth, HandlerPipeThrough } from "@atproto/xrpc-server"; 10 10 import type * as AppRockskySongDefs from "../song/defs"; 11 11 12 - export type QueryParams = {} 12 + export type QueryParams = {}; 13 13 14 14 export interface InputSchema { 15 15 /** The unique identifier of the song to like */
+1 -1
apps/api/src/lexicon/types/app/rocksky/scrobble/createScrobble.ts
··· 9 9 import type { HandlerAuth, HandlerPipeThrough } from "@atproto/xrpc-server"; 10 10 import type * as AppRockskyScrobbleDefs from "./defs"; 11 11 12 - export type QueryParams = {} 12 + export type QueryParams = {}; 13 13 14 14 export interface InputSchema { 15 15 /** The title of the track being scrobbled */
+1 -1
apps/api/src/lexicon/types/app/rocksky/shout/createShout.ts
··· 9 9 import type { HandlerAuth, HandlerPipeThrough } from "@atproto/xrpc-server"; 10 10 import type * as AppRockskyShoutDefs from "./defs"; 11 11 12 - export type QueryParams = {} 12 + export type QueryParams = {}; 13 13 14 14 export interface InputSchema { 15 15 /** The content of the shout */
+1 -1
apps/api/src/lexicon/types/app/rocksky/shout/replyShout.ts
··· 9 9 import type { HandlerAuth, HandlerPipeThrough } from "@atproto/xrpc-server"; 10 10 import type * as AppRockskyShoutDefs from "./defs"; 11 11 12 - export type QueryParams = {} 12 + export type QueryParams = {}; 13 13 14 14 export interface InputSchema { 15 15 /** The unique identifier of the shout to reply to */
+1 -1
apps/api/src/lexicon/types/app/rocksky/shout/reportShout.ts
··· 9 9 import type { HandlerAuth, HandlerPipeThrough } from "@atproto/xrpc-server"; 10 10 import type * as AppRockskyShoutDefs from "./defs"; 11 11 12 - export type QueryParams = {} 12 + export type QueryParams = {}; 13 13 14 14 export interface InputSchema { 15 15 /** The unique identifier of the shout to report */
+1 -1
apps/api/src/lexicon/types/app/rocksky/song/createSong.ts
··· 9 9 import type { HandlerAuth, HandlerPipeThrough } from "@atproto/xrpc-server"; 10 10 import type * as AppRockskySongDefs from "./defs"; 11 11 12 - export type QueryParams = {} 12 + export type QueryParams = {}; 13 13 14 14 export interface InputSchema { 15 15 /** The title of the song */
+1 -1
apps/api/src/lexicon/types/app/rocksky/spotify/next.ts
··· 8 8 import { CID } from "multiformats/cid"; 9 9 import { type HandlerAuth, HandlerPipeThrough } from "@atproto/xrpc-server"; 10 10 11 - export type QueryParams = {} 11 + export type QueryParams = {}; 12 12 13 13 export type InputSchema = undefined; 14 14 export type HandlerInput = undefined;
+1 -1
apps/api/src/lexicon/types/app/rocksky/spotify/pause.ts
··· 8 8 import { CID } from "multiformats/cid"; 9 9 import { type HandlerAuth, HandlerPipeThrough } from "@atproto/xrpc-server"; 10 10 11 - export type QueryParams = {} 11 + export type QueryParams = {}; 12 12 13 13 export type InputSchema = undefined; 14 14 export type HandlerInput = undefined;
+1 -1
apps/api/src/lexicon/types/app/rocksky/spotify/play.ts
··· 8 8 import { CID } from "multiformats/cid"; 9 9 import { type HandlerAuth, HandlerPipeThrough } from "@atproto/xrpc-server"; 10 10 11 - export type QueryParams = {} 11 + export type QueryParams = {}; 12 12 13 13 export type InputSchema = undefined; 14 14 export type HandlerInput = undefined;
+1 -1
apps/api/src/lexicon/types/app/rocksky/spotify/previous.ts
··· 8 8 import { CID } from "multiformats/cid"; 9 9 import { type HandlerAuth, HandlerPipeThrough } from "@atproto/xrpc-server"; 10 10 11 - export type QueryParams = {} 11 + export type QueryParams = {}; 12 12 13 13 export type InputSchema = undefined; 14 14 export type HandlerInput = undefined;
+46 -46
apps/api/src/nowplaying/nowplaying.service.ts
··· 26 26 27 27 export async function putArtistRecord( 28 28 track: Track, 29 - agent: Agent 29 + agent: Agent, 30 30 ): Promise<string | null> { 31 31 const rkey = TID.nextStr(); 32 32 const record: Artist.Record = { ··· 62 62 63 63 export async function putAlbumRecord( 64 64 track: Track, 65 - agent: Agent 65 + agent: Agent, 66 66 ): Promise<string | null> { 67 67 const rkey = TID.nextStr(); 68 68 ··· 103 103 104 104 export async function putSongRecord( 105 105 track: Track, 106 - agent: Agent 106 + agent: Agent, 107 107 ): Promise<string | null> { 108 108 const rkey = TID.nextStr(); 109 109 ··· 158 158 159 159 async function putScrobbleRecord( 160 160 track: Track, 161 - agent: Agent 161 + agent: Agent, 162 162 ): Promise<string | null> { 163 163 const rkey = TID.nextStr(); 164 164 ··· 276 276 .where( 277 277 and( 278 278 eq(artistAlbums.albumId, scrobble.album.id), 279 - eq(artistAlbums.artistId, scrobble.artist.id) 280 - ) 279 + eq(artistAlbums.artistId, scrobble.artist.id), 280 + ), 281 281 ) 282 282 .limit(1) 283 283 .then((rows) => rows[0]), ··· 440 440 }, 441 441 }), 442 442 null, 443 - 2 443 + 2, 444 444 ); 445 445 446 446 ctx.nc.publish( 447 447 "rocksky.scrobble", 448 - Buffer.from(message.replaceAll("sha_256", "sha256")) 448 + Buffer.from(message.replaceAll("sha_256", "sha256")), 449 449 ); 450 450 451 451 const trackMessage = JSON.stringify( ··· 492 492 xata_createdat: artist_album.createdAt.toISOString(), 493 493 xata_updatedat: artist_album.updatedAt.toISOString(), 494 494 }, 495 - }) 495 + }), 496 496 ); 497 497 498 498 ctx.nc.publish( 499 499 "rocksky.track", 500 - Buffer.from(trackMessage.replaceAll("sha_256", "sha256")) 500 + Buffer.from(trackMessage.replaceAll("sha_256", "sha256")), 501 501 ); 502 502 } 503 503 ··· 505 505 ctx: Context, 506 506 track: Track, 507 507 agent: Agent, 508 - userDid: string 508 + userDid: string, 509 509 ): Promise<void> { 510 510 // check if scrobble already exists (user did + timestamp) 511 511 const scrobbleTime = dayjs.unix(track.timestamp || dayjs().unix()); ··· 524 524 eq(tracks.title, track.title), 525 525 eq(tracks.artist, track.artist), 526 526 gte(scrobbles.timestamp, scrobbleTime.subtract(60, "seconds").toDate()), 527 - lte(scrobbles.timestamp, scrobbleTime.add(60, "seconds").toDate()) 528 - ) 527 + lte(scrobbles.timestamp, scrobbleTime.add(60, "seconds").toDate()), 528 + ), 529 529 ) 530 530 .limit(1) 531 531 .then((rows) => rows[0]); ··· 533 533 if (existingScrobble) { 534 534 console.log( 535 535 `Scrobble already exists for ${chalk.cyan(track.title)} at ${chalk.cyan( 536 - scrobbleTime.format("YYYY-MM-DD HH:mm:ss") 537 - )}` 536 + scrobbleTime.format("YYYY-MM-DD HH:mm:ss"), 537 + )}`, 538 538 ); 539 539 return; 540 540 } ··· 547 547 tracks.sha256, 548 548 createHash("sha256") 549 549 .update( 550 - `${track.title} - ${track.artist} - ${track.album}`.toLowerCase() 550 + `${track.title} - ${track.artist} - ${track.album}`.toLowerCase(), 551 551 ) 552 - .digest("hex") 553 - ) 552 + .digest("hex"), 553 + ), 554 554 ) 555 555 .limit(1) 556 556 .then((rows) => rows[0]); ··· 564 564 albums.sha256, 565 565 createHash("sha256") 566 566 .update(`${track.album} - ${track.albumArtist}`.toLowerCase()) 567 - .digest("hex") 568 - ) 567 + .digest("hex"), 568 + ), 569 569 ) 570 570 .limit(1) 571 571 .then((rows) => rows[0]); ··· 586 586 artists.sha256, 587 587 createHash("sha256") 588 588 .update(track.albumArtist.toLowerCase()) 589 - .digest("hex") 590 - ) 589 + .digest("hex"), 590 + ), 591 591 ) 592 592 .limit(1) 593 593 .then((rows) => rows[0]); ··· 618 618 artist: track.artist.split(",").map((a) => ({ name: a.trim() })), 619 619 name: track.title, 620 620 album: track.album, 621 - } 621 + }, 622 622 ); 623 623 624 624 if (!mbTrack?.trackMBID) { ··· 647 647 albums.sha256, 648 648 createHash("sha256") 649 649 .update(`${track.album} - ${track.albumArtist}`.toLowerCase()) 650 - .digest("hex") 651 - ) 650 + .digest("hex"), 651 + ), 652 652 ) 653 653 .limit(1) 654 654 .then((rows) => rows[0]); ··· 664 664 tracks.sha256, 665 665 createHash("sha256") 666 666 .update( 667 - `${track.title} - ${track.artist} - ${track.album}`.toLowerCase() 667 + `${track.title} - ${track.artist} - ${track.album}`.toLowerCase(), 668 668 ) 669 - .digest("hex") 670 - ) 669 + .digest("hex"), 670 + ), 671 671 ) 672 672 .limit(1) 673 673 .then((rows) => rows[0]); ··· 681 681 682 682 if (existingTrack) { 683 683 console.log( 684 - `Song found: ${chalk.cyan(existingTrack.id)} - ${track.title}, after ${chalk.magenta(tries)} tries` 684 + `Song found: ${chalk.cyan(existingTrack.id)} - ${track.title}, after ${chalk.magenta(tries)} tries`, 685 685 ); 686 686 } 687 687 ··· 694 694 artists.sha256, 695 695 createHash("sha256") 696 696 .update(track.albumArtist.toLowerCase()) 697 - .digest("hex") 697 + .digest("hex"), 698 698 ), 699 699 eq( 700 700 artists.sha256, 701 - createHash("sha256").update(track.artist.toLowerCase()).digest("hex") 702 - ) 703 - ) 701 + createHash("sha256").update(track.artist.toLowerCase()).digest("hex"), 702 + ), 703 + ), 704 704 ) 705 705 .limit(1) 706 706 .then((rows) => rows[0]); ··· 715 715 .innerJoin(artists, eq(userArtists.artistId, artists.id)) 716 716 .innerJoin(users, eq(userArtists.userId, users.id)) 717 717 .where( 718 - and(eq(artists.id, existingArtist?.id || ""), eq(users.did, userDid)) 718 + and(eq(artists.id, existingArtist?.id || ""), eq(users.did, userDid)), 719 719 ) 720 720 .limit(1) 721 721 .then((rows) => rows[0]); ··· 750 750 tracks.sha256, 751 751 createHash("sha256") 752 752 .update( 753 - `${track.title} - ${track.artist} - ${track.album}`.toLowerCase() 753 + `${track.title} - ${track.artist} - ${track.album}`.toLowerCase(), 754 754 ) 755 - .digest("hex") 756 - ) 755 + .digest("hex"), 756 + ), 757 757 ) 758 758 .limit(1) 759 759 .then((rows) => rows[0]); 760 760 761 761 while (!existingTrack?.artistUri && !existingTrack?.albumUri && tries < 30) { 762 762 console.log( 763 - `Artist uri not ready, trying again: ${chalk.magenta(tries + 1)}` 763 + `Artist uri not ready, trying again: ${chalk.magenta(tries + 1)}`, 764 764 ); 765 765 existingTrack = await ctx.db 766 766 .select() ··· 770 770 tracks.sha256, 771 771 createHash("sha256") 772 772 .update( 773 - `${track.title} - ${track.artist} - ${track.album}`.toLowerCase() 773 + `${track.title} - ${track.artist} - ${track.album}`.toLowerCase(), 774 774 ) 775 - .digest("hex") 776 - ) 775 + .digest("hex"), 776 + ), 777 777 ) 778 778 .limit(1) 779 779 .then((rows) => rows[0]); ··· 788 788 artists.sha256, 789 789 createHash("sha256") 790 790 .update(track.albumArtist.toLowerCase()) 791 - .digest("hex") 792 - ) 791 + .digest("hex"), 792 + ), 793 793 ) 794 794 .limit(1) 795 795 .then((rows) => rows[0]); ··· 812 812 albums.sha256, 813 813 createHash("sha256") 814 814 .update(`${track.album} - ${track.albumArtist}`.toLowerCase()) 815 - .digest("hex") 816 - ) 815 + .digest("hex"), 816 + ), 817 817 ) 818 818 .limit(1) 819 819 .then((rows) => rows[0]); ··· 843 843 844 844 if (existingTrack?.artistUri) { 845 845 console.log( 846 - `Artist uri ready: ${chalk.cyan(existingTrack.id)} - ${track.title}, after ${chalk.magenta(tries)} tries` 846 + `Artist uri ready: ${chalk.cyan(existingTrack.id)} - ${track.title}, after ${chalk.magenta(tries)} tries`, 847 847 ); 848 848 } 849 849
+4 -4
apps/api/src/sqliteKv.ts
··· 101 101 oc.column("id").doUpdateSet({ 102 102 value, 103 103 updated_at: now, 104 - }) 104 + }), 105 105 ) 106 106 .execute(); 107 107 }, ··· 126 126 oc.column("id").doUpdateSet({ 127 127 value, 128 128 updated_at: now, 129 - }) 129 + }), 130 130 ) 131 131 .execute(); 132 - }) 132 + }), 133 133 ); 134 134 }); 135 135 }, ··· 170 170 await getDb().destroy(); 171 171 }, 172 172 }; 173 - } 173 + }, 174 174 );
+5 -5
apps/api/src/tealfm/index.ts
··· 20 20 async function publishPlayingNow( 21 21 agent: Agent, 22 22 track: MusicbrainzTrack, 23 - duration: number 23 + duration: number, 24 24 ) { 25 25 try { 26 26 // wait 60 seconds to ensure the track is actually being played ··· 34 34 // diff in seconds less than 60 35 35 Math.abs( 36 36 new Date(record.playedTime).getTime() - 37 - new Date(track.timestamp).getTime() 37 + new Date(track.timestamp).getTime(), 38 38 ) < 60000 39 39 ); 40 40 }); 41 41 if (alreadyPlayed) { 42 42 console.log( 43 43 `Track ${chalk.cyan(track.name)} by ${chalk.cyan( 44 - track.artist.map((a) => a.name).join(", ") 45 - )} already played recently. Skipping...` 44 + track.artist.map((a) => a.name).join(", "), 45 + )} already played recently. Skipping...`, 46 46 ); 47 47 return; 48 48 } ··· 88 88 async function publishStatus( 89 89 agent: Agent, 90 90 track: MusicbrainzTrack, 91 - duration: number 91 + duration: number, 92 92 ) { 93 93 const item: PlayView = { 94 94 trackName: track.name,