diff --git a/VIEW_TRANSITIONS_GUIDE.md b/VIEW_TRANSITIONS_GUIDE.md deleted file mode 100644 index a16d097..0000000 --- a/VIEW_TRANSITIONS_GUIDE.md +++ /dev/null @@ -1,100 +0,0 @@ -# View Transitions Implementation Guide - -## Overview - -This project now uses the native **View Transitions API** to create smooth animations between pages, including browser back/forward navigation. The implementation is based on best practices from the [nmn.sh](https://github.com/nmn/nmn.sh) repository. - -## What Changed - -### 1. CSS Configuration (`src/index.css`) - -Added comprehensive view transition CSS rules: - -```css -/* Enable smooth cross-document view transitions (browser navigation) */ -@view-transition { - navigation: auto; -} - -/* Default transition for all elements */ -::view-transition-old(root), -::view-transition-new(root) { - animation-duration: 0.3s; - animation-timing-function: ease-in-out; -} -``` - -**Key Feature**: `@view-transition { navigation: auto; }` enables transitions to work with native browser navigation (back/forward buttons, URL changes), not just client-side routing. - -### 2. Component Updates - -**AlbumCard.tsx** and **album/[albumId]/page.tsx**: - -Changed from React `ViewTransition` component wrapper: -```tsx -// ❌ Old approach (only works with client-side routing) - - {label} - -``` - -To native CSS `viewTransitionName` property: -```tsx -// ✅ New approach (works with all navigation) -{label} -``` - -### 3. TypeScript Support - -Added type definitions in `src/types/view-transitions.d.ts` to extend React's `CSSProperties` interface with `viewTransitionName` support. - -## How It Works - -### Client-Side Routing -- Uses `next-view-transitions` package -- `` component from the package automatically triggers view transitions -- Smooth animations between pages when clicking links - -### Browser Navigation (Back/Forward) -- Native `@view-transition { navigation: auto; }` CSS rule -- Browser automatically captures before/after states -- Smooth transitions even with browser buttons or URL changes -- **No JavaScript required** for basic transitions - -### Named Transitions -Elements with matching `viewTransitionName` values will morph smoothly between pages: -- Album images: `album-card-image-{id}` -- Album titles: `album-card-title-{id}` -- Release dates: `album-card-release-date-{id}` - -## Browser Support - -- **Chrome/Edge**: Full support (v111+) -- **Safari**: Support in v18+ (macOS Sonoma, iOS 17) -- **Firefox**: In development -- **Fallback**: Graceful degradation to instant navigation - -## Testing - -1. **Client-side navigation**: Click any album card → smooth transition -2. **Browser back button**: Press back → smooth transition -3. **Direct URL change**: Type URL directly → smooth transition on supported browsers - -## Benefits Over Previous Implementation - -1. ✅ **Works with browser navigation** (back/forward buttons) -2. ✅ **Works with direct URL changes** -3. ✅ **Better performance** (native browser API) -4. ✅ **More reliable** (less JavaScript, more standards-based) -5. ✅ **Progressive enhancement** (works without JS) - -## References - -- [View Transitions API (MDN)](https://developer.mozilla.org/en-US/docs/Web/API/View_Transitions_API) -- [nmn.sh repository](https://github.com/nmn/nmn.sh) -- [Chrome View Transitions Guide](https://developer.chrome.com/docs/web-platform/view-transitions/) - diff --git a/data/.gitkeep b/data/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/data/fetched-songs.json b/data/fetched-songs.json new file mode 100644 index 0000000..839f824 --- /dev/null +++ b/data/fetched-songs.json @@ -0,0 +1,27 @@ +{ + "hybrid-theory-1": true, + "hybrid-theory-2": true, + "hybrid-theory-3": true, + "hybrid-theory-4": true, + "hybrid-theory-5": true, + "hybrid-theory-6": true, + "hybrid-theory-7": true, + "hybrid-theory-8": true, + "hybrid-theory-9": true, + "hybrid-theory-10": true, + "hybrid-theory-11": true, + "hybrid-theory-12": true, + "meteora-1": true, + "meteora-2": true, + "meteora-3": true, + "meteora-4": true, + "meteora-5": true, + "meteora-6": true, + "meteora-7": true, + "meteora-8": true, + "meteora-9": true, + "meteora-10": true, + "meteora-11": true, + "meteora-12": true, + "meteora-13": true +} diff --git a/data/song-links.json b/data/song-links.json new file mode 100644 index 0000000..c6b1b55 --- /dev/null +++ b/data/song-links.json @@ -0,0 +1,152 @@ +{ + "hybrid-theory-1": { + "spotify": "https://open.spotify.com/track/4HvcbAR8LisalXKt7cpqE1", + "youtube": "https://www.youtube.com/watch?v=vjVkXlxsO8Q", + "youtubeMusic": "https://music.youtube.com/watch?v=vjVkXlxsO8Q", + "appleMusic": "https://geo.music.apple.com/de/album/_/528436018?i=528436568&mt=1&app=music&ls=1&at=1000lHKX&ct=api_http&itscg=30200&itsct=odsl_m" + }, + "hybrid-theory-2": { + "spotify": "https://open.spotify.com/track/4bYLTrlcqctyHck3fjhMgW", + "youtube": "https://www.youtube.com/watch?v=4qlCC1GOwFw", + "youtubeMusic": "https://music.youtube.com/watch?v=4qlCC1GOwFw", + "appleMusic": "https://geo.music.apple.com/de/album/_/590431776?i=590431778&mt=1&app=music&ls=1&at=1000lHKX&ct=api_http&itscg=30200&itsct=odsl_m" + }, + "hybrid-theory-3": { + "spotify": "https://open.spotify.com/track/1Q9QN6dHEDeUegsySY012f", + "youtube": "https://www.youtube.com/watch?v=M8UTS2iFXOo", + "youtubeMusic": "https://music.youtube.com/watch?v=M8UTS2iFXOo", + "appleMusic": "https://geo.music.apple.com/de/album/_/528436018?i=528437421&mt=1&app=music&ls=1&at=1000lHKX&ct=api_http&itscg=30200&itsct=odsl_m" + }, + "hybrid-theory-4": { + "spotify": "https://open.spotify.com/track/214LJVTqrkUOGemWDGHJpr", + "youtube": "https://www.youtube.com/watch?v=jZSPAp8kCl4", + "youtubeMusic": "https://music.youtube.com/watch?v=jZSPAp8kCl4", + "appleMusic": "https://geo.music.apple.com/de/album/_/590431776?i=590431781&mt=1&app=music&ls=1&at=1000lHKX&ct=api_http&itscg=30200&itsct=odsl_m" + }, + "hybrid-theory-5": { + "spotify": "https://open.spotify.com/track/0X576XiCW9uEtko6f6VkcU", + "youtube": "https://www.youtube.com/watch?v=Gd9OhYroLN0", + "youtubeMusic": "https://music.youtube.com/watch?v=Gd9OhYroLN0", + "appleMusic": "https://geo.music.apple.com/de/album/_/591534774?i=591534780&mt=1&app=music&ls=1&at=1000lHKX&ct=api_http&itscg=30200&itsct=odsl_m" + }, + "hybrid-theory-6": { + "spotify": "https://open.spotify.com/track/5tkHje8FGSF258gi869GcV", + "youtube": "https://www.youtube.com/watch?v=ig-fyQqf510", + "youtubeMusic": "https://music.youtube.com/watch?v=ig-fyQqf510", + "appleMusic": "https://geo.music.apple.com/de/album/_/528436018?i=528437609&mt=1&app=music&ls=1&at=1000lHKX&ct=api_http&itscg=30200&itsct=odsl_m" + }, + "hybrid-theory-7": { + "spotify": "https://open.spotify.com/track/4SJoEhpI6C61wtUfxSHMGc", + "youtube": "https://www.youtube.com/watch?v=wWBp-nlGX1o", + "youtubeMusic": "https://music.youtube.com/watch?v=wWBp-nlGX1o", + "appleMusic": "https://geo.music.apple.com/de/album/_/528436018?i=528437611&mt=1&app=music&ls=1&at=1000lHKX&ct=api_http&itscg=30200&itsct=odsl_m" + }, + "hybrid-theory-8": { + "spotify": "https://open.spotify.com/track/7q115ia4fQn9zonjpexWsY", + "youtube": "https://www.youtube.com/watch?v=eVTXPUF4Oz4", + "youtubeMusic": "https://music.youtube.com/watch?v=eVTXPUF4Oz4", + "appleMusic": "https://geo.music.apple.com/de/album/_/528436018?i=528437613&mt=1&app=music&ls=1&at=1000lHKX&ct=api_http&itscg=30200&itsct=odsl_m" + }, + "hybrid-theory-9": { + "spotify": "https://open.spotify.com/track/1B8WdDScvobpFsZLfdmIE1", + "youtube": "https://www.youtube.com/watch?v=3t2WkCudwfY", + "youtubeMusic": "https://music.youtube.com/watch?v=3t2WkCudwfY", + "appleMusic": "https://geo.music.apple.com/de/album/_/528436018?i=528437708&mt=1&app=music&ls=1&at=1000lHKX&ct=api_http&itscg=30200&itsct=odsl_m" + }, + "hybrid-theory-10": { + "spotify": "https://open.spotify.com/track/3JAu2BH8sSI46rJGzQerb6", + "youtube": "https://www.youtube.com/watch?v=HNCgBuI2eJc", + "youtubeMusic": "https://music.youtube.com/watch?v=HNCgBuI2eJc", + "appleMusic": "https://geo.music.apple.com/de/album/_/528436018?i=528437709&mt=1&app=music&ls=1&at=1000lHKX&ct=api_http&itscg=30200&itsct=odsl_m" + }, + "hybrid-theory-11": { + "spotify": "https://open.spotify.com/track/15voDM9pGkwEvHBUecpcmo", + "youtube": "https://www.youtube.com/watch?v=qqC5sdsHLq8", + "youtubeMusic": "https://music.youtube.com/watch?v=qqC5sdsHLq8", + "appleMusic": "https://geo.music.apple.com/de/album/_/528436018?i=528437710&mt=1&app=music&ls=1&at=1000lHKX&ct=api_http&itscg=30200&itsct=odsl_m" + }, + "hybrid-theory-12": { + "spotify": "https://open.spotify.com/track/4HlMOXxwF9SYG1RoJxEjio", + "youtube": "https://www.youtube.com/watch?v=Ve1LNJEIKUE", + "youtubeMusic": "https://music.youtube.com/watch?v=Ve1LNJEIKUE", + "appleMusic": "https://geo.music.apple.com/de/album/_/590431776?i=590431790&mt=1&app=music&ls=1&at=1000lHKX&ct=api_http&itscg=30200&itsct=odsl_m" + }, + "meteora-1": { + "spotify": "https://open.spotify.com/track/4hbpxoMCp62bd1sdy7XehS", + "youtube": "https://www.youtube.com/watch?v=U6R-twDkrcI", + "youtubeMusic": "https://music.youtube.com/watch?v=U6R-twDkrcI", + "appleMusic": "https://geo.music.apple.com/de/album/_/590423275?i=590423280&mt=1&app=music&ls=1&at=1000lHKX&ct=api_http&itscg=30200&itsct=odsl_m" + }, + "meteora-2": { + "spotify": "https://open.spotify.com/track/6HZdbb05lEXLvcmee3ZXO2", + "youtube": "https://www.youtube.com/watch?v=oWfGOVWrueo", + "youtubeMusic": "https://music.youtube.com/watch?v=oWfGOVWrueo", + "appleMusic": "https://geo.music.apple.com/de/album/_/1668484895?i=1668485277&mt=1&app=music&ls=1&at=1000lHKX&ct=api_http&itscg=30200&itsct=odsl_m" + }, + "meteora-3": { + "spotify": "https://open.spotify.com/track/3agtg0x11wPvLIWkYR39nZ", + "youtube": "https://www.youtube.com/watch?v=zsCD5XCu6CM", + "youtubeMusic": "https://music.youtube.com/watch?v=zsCD5XCu6CM", + "appleMusic": "https://geo.music.apple.com/de/album/_/528435845?i=528437020&mt=1&app=music&ls=1&at=1000lHKX&ct=api_http&itscg=30200&itsct=odsl_m" + }, + "meteora-4": { + "spotify": "https://open.spotify.com/track/4zP2e2aIzOZGEFTq1MDJmm", + "youtube": "https://www.youtube.com/watch?v=NjdgcHdzvac", + "youtubeMusic": "https://music.youtube.com/watch?v=NjdgcHdzvac", + "appleMusic": "https://geo.music.apple.com/de/album/_/590423275?i=590423283&mt=1&app=music&ls=1&at=1000lHKX&ct=api_http&itscg=30200&itsct=odsl_m" + }, + "meteora-5": { + "spotify": "https://open.spotify.com/track/3R9NKZ4jmxNjOFihSF5s7f", + "youtube": "https://www.youtube.com/watch?v=oMals9XXQY8", + "youtubeMusic": "https://music.youtube.com/watch?v=oMals9XXQY8", + "appleMusic": "https://geo.music.apple.com/de/album/_/590423275?i=590423284&mt=1&app=music&ls=1&at=1000lHKX&ct=api_http&itscg=30200&itsct=odsl_m" + }, + "meteora-6": { + "spotify": "https://open.spotify.com/track/17bgialGAwoiGj1STY4cnR", + "youtube": "https://www.youtube.com/watch?v=U5zdmjVeQzE", + "youtubeMusic": "https://music.youtube.com/watch?v=U5zdmjVeQzE", + "appleMusic": "https://geo.music.apple.com/de/album/_/590423275?i=590423285&mt=1&app=music&ls=1&at=1000lHKX&ct=api_http&itscg=30200&itsct=odsl_m" + }, + "meteora-7": { + "spotify": "https://open.spotify.com/track/4Yf5bqU3NK4kNOypcrLYwU", + "youtube": "https://www.youtube.com/watch?v=LYU-8IFcDPw", + "youtubeMusic": "https://music.youtube.com/watch?v=LYU-8IFcDPw", + "appleMusic": "https://geo.music.apple.com/de/album/_/528435845?i=528437024&mt=1&app=music&ls=1&at=1000lHKX&ct=api_http&itscg=30200&itsct=odsl_m" + }, + "meteora-8": { + "spotify": "https://open.spotify.com/track/2DrMcGNKEY0FZqjMovGaCm", + "youtube": "https://www.youtube.com/watch?v=6dEAeCHQrBs", + "youtubeMusic": "https://music.youtube.com/watch?v=6dEAeCHQrBs", + "appleMusic": "https://geo.music.apple.com/de/album/_/528435845?i=528437025&mt=1&app=music&ls=1&at=1000lHKX&ct=api_http&itscg=30200&itsct=odsl_m" + }, + "meteora-9": { + "spotify": "https://open.spotify.com/track/6n8TMVyFKoUmDc4apxceRD", + "youtube": "https://www.youtube.com/watch?v=v2H4l9RpkwM", + "youtubeMusic": "https://music.youtube.com/watch?v=v2H4l9RpkwM", + "appleMusic": "https://geo.music.apple.com/de/album/_/528435845?i=528437026&mt=1&app=music&ls=1&at=1000lHKX&ct=api_http&itscg=30200&itsct=odsl_m" + }, + "meteora-10": { + "spotify": "https://open.spotify.com/track/60IkVf7UfQXmt5CwkpcX8a", + "youtube": "https://www.youtube.com/watch?v=YLHpvjrFpe0", + "youtubeMusic": "https://music.youtube.com/watch?v=YLHpvjrFpe0", + "appleMusic": "https://geo.music.apple.com/de/album/_/528435845?i=528437027&mt=1&app=music&ls=1&at=1000lHKX&ct=api_http&itscg=30200&itsct=odsl_m" + }, + "meteora-11": { + "spotify": "https://open.spotify.com/track/4m1P1BSg9nLxaWbvPhNdhw", + "youtube": "https://www.youtube.com/watch?v=QJ87793QXes", + "youtubeMusic": "https://music.youtube.com/watch?v=QJ87793QXes", + "appleMusic": "https://geo.music.apple.com/de/album/_/590423275?i=590423550&mt=1&app=music&ls=1&at=1000lHKX&ct=api_http&itscg=30200&itsct=odsl_m" + }, + "meteora-12": { + "spotify": "https://open.spotify.com/track/3sbezh9MMCQrr4KY7zw13j", + "youtube": "https://www.youtube.com/watch?v=J1KqQYsUYIk", + "youtubeMusic": "https://music.youtube.com/watch?v=J1KqQYsUYIk", + "appleMusic": "https://geo.music.apple.com/de/album/_/528435845?i=528437513&mt=1&app=music&ls=1&at=1000lHKX&ct=api_http&itscg=30200&itsct=odsl_m" + }, + "meteora-13": { + "spotify": "https://open.spotify.com/track/2nLtzopw4rPReszdYBJU6h", + "youtube": "https://www.youtube.com/watch?v=kXYiU_JCYtU", + "youtubeMusic": "https://music.youtube.com/watch?v=kXYiU_JCYtU", + "appleMusic": "https://geo.music.apple.com/de/album/_/528435845?i=528437514&mt=1&app=music&ls=1&at=1000lHKX&ct=api_http&itscg=30200&itsct=odsl_m" + } +} diff --git a/package.json b/package.json index bac7171..401b543 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,8 @@ "dev": "next dev", "build": "next build", "start": "next start", - "lint": "eslint ." + "lint": "eslint .", + "fetch-links": "bun run scripts/fetch-song-links.ts" }, "dependencies": { "@mantine/carousel": "^8.3.5", @@ -23,6 +24,7 @@ }, "devDependencies": { "@eslint/js": "^9.36.0", + "@types/bun": "^1.3.1", "@types/node": "^24.6.0", "@types/react": "^19.2.2", "@types/react-dom": "^19.2.2", diff --git a/scripts/README.md b/scripts/README.md new file mode 100644 index 0000000..94b9102 --- /dev/null +++ b/scripts/README.md @@ -0,0 +1,74 @@ +# Song Links Fetcher + +This script fetches streaming links (Spotify, YouTube, YouTube Music, Apple Music) for all Linkin Park songs in the project using the SongLink API. + +## Features + +- 🎵 Fetches links for all songs from the `list.ts` file using their Spotify URLs +- ⏱️ Respects API rate limit (10 requests per minute) +- 💾 Caches already-fetched songs to avoid redundant API calls +- 📁 Outputs both TypeScript and JSON files +- 📊 Shows progress and summary statistics +- ⏭️ Automatically skips songs without Spotify URLs +- 🎨 Automatically formats all generated files with Prettier + +## Usage + +Run the script with: + +```bash +bun run fetch-links +``` + +## Output Files + +1. **`src/lib/songLinks.ts`** - TypeScript file with exported `songLinks` object +2. **`data/song-links.json`** - JSON file with all song links +3. **`data/fetched-songs.json`** - Cache file tracking which songs have been fetched + +## Data Structure + +The generated TypeScript file exports a `songLinks` object with this structure: + +```typescript +{ + "hybrid-theory-1": { + "spotify": "https://open.spotify.com/track/...", + "youtube": "https://www.youtube.com/watch?v=...", + "youtubeMusic": "https://music.youtube.com/watch?v=...", + "appleMusic": "https://music.apple.com/..." + }, + // ... more songs +} +``` + +## API Information + +- **API**: [SongLink/Odesli API](https://linktree.notion.site/API-d0ebe08a5e304a55928405eb682f6741) +- **Endpoint**: `https://api.song.link/v1-alpha.1/links` +- **Parameters**: + - `url`: Spotify track URL (encoded) + - `userCountry`: DE (Germany) + - `songIfSingle`: true (for better matching) +- **Rate Limit**: 10 requests per minute +- **Delay between requests**: 6 seconds + +## Requirements + +Each track in `list.ts` must have a `__SPOTIFY_URL__` field with a valid Spotify track URL. Tracks without this field will be automatically skipped. + +## Resumable + +If the script is interrupted or fails for any song, you can simply run it again. It will: +- Skip already-fetched songs (based on the cache file) +- Continue fetching remaining songs +- Preserve all previously fetched data + +## Clearing Cache + +To re-fetch all songs from scratch, delete the cache file: + +```bash +rm data/fetched-songs.json +``` + diff --git a/scripts/fetch-song-links.ts b/scripts/fetch-song-links.ts new file mode 100644 index 0000000..49d0544 --- /dev/null +++ b/scripts/fetch-song-links.ts @@ -0,0 +1,243 @@ +#!/usr/bin/env bun + +import { join } from "path"; +import { $ } from "bun"; +import { albums } from "../src/lib/list"; + +// Configuration +const API_BASE = "https://api.song.link/v1-alpha.1/links"; +const RATE_LIMIT_DELAY = 6000; // 6 seconds (10 requests per minute) +const USER_COUNTRY = "DE"; // Germany +const DATA_DIR = join(import.meta.dir, "../data"); +const CACHE_FILE = join(DATA_DIR, "fetched-songs.json"); +const OUTPUT_TS_FILE = join(import.meta.dir, "../src/lib/songLinks.ts"); +const OUTPUT_JSON_FILE = join(DATA_DIR, "song-links.json"); + +interface SongLinks { + spotify?: string; + youtube?: string; + youtubeMusic?: string; + appleMusic?: string; +} + +interface SongLinksData { + [songId: string]: SongLinks; +} + +interface CachedSongs { + [songId: string]: boolean; +} + +// Delay function for rate limiting +const delay = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms)); + +// Load cached songs +async function loadCache(): Promise { + const file = Bun.file(CACHE_FILE); + const exists = await file.exists(); + + if (!exists) { + console.log("No cache file found, starting fresh..."); + return {}; + } + + try { + return await file.json(); + } catch { + console.log("Invalid cache file, starting fresh..."); + return {}; + } +} + +// Load existing song links +async function loadExistingSongLinks(): Promise { + const file = Bun.file(OUTPUT_JSON_FILE); + const exists = await file.exists(); + + if (!exists) { + console.log("No existing song links found, starting fresh..."); + return {}; + } + + try { + return await file.json(); + } catch { + console.log("Invalid song links file, starting fresh..."); + return {}; + } +} + +// Ensure data directory exists +async function ensureDataDir(): Promise { + await Bun.write(join(DATA_DIR, ".gitkeep"), ""); +} + +// Save cache +async function saveCache(cache: CachedSongs): Promise { + await ensureDataDir(); + await Bun.write(CACHE_FILE, JSON.stringify(cache, null, 2)); +} + +// Save song links to JSON +async function saveSongLinksJSON(songLinks: SongLinksData): Promise { + await ensureDataDir(); + await Bun.write(OUTPUT_JSON_FILE, JSON.stringify(songLinks, null, 2)); +} + +// Save song links to TypeScript file +async function saveSongLinksTS(songLinks: SongLinksData): Promise { + const tsContent = `// This file is auto-generated by scripts/fetch-song-links.ts +// Do not edit manually +// Last updated: ${new Date().toISOString()} +// Run: bun run fetch-links + +export interface SongLinks { + spotify?: string; + youtube?: string; + youtubeMusic?: string; + appleMusic?: string; +} + +export interface SongLinksData { + [songId: string]: SongLinks; +} + +export const songLinks: SongLinksData = ${JSON.stringify(songLinks, null, 2)}; +`; + + await Bun.write(OUTPUT_TS_FILE, tsContent); +} + +// Fetch song links from API +async function fetchSongLinks(spotifyUrl: string, songName: string): Promise { + try { + // Encode the Spotify URL + const encodedUrl = encodeURIComponent(spotifyUrl); + + // Use the url parameter with songIfSingle for better matching + const url = `${API_BASE}?url=${encodedUrl}&userCountry=${USER_COUNTRY}&songIfSingle=true`; + + console.log(` Fetching: ${songName}`); + console.log(` Spotify URL: ${spotifyUrl}`); + + const response = await fetch(url); + + if (!response.ok) { + const errorText = await response.text(); + console.error(` ❌ Failed to fetch (${response.status}): ${errorText}`); + return null; + } + + const data = await response.json(); + + // Extract links from the response + const links: SongLinks = { + spotify: data.linksByPlatform?.spotify?.url || undefined, + youtube: data.linksByPlatform?.youtube?.url || undefined, + youtubeMusic: data.linksByPlatform?.youtubeMusic?.url || undefined, + appleMusic: data.linksByPlatform?.appleMusic?.url || undefined, + }; + + console.log(` ✓ Success!`); + return links; + } catch (error) { + console.error(` ❌ Error:`, error); + return null; + } +} + +// Main function +async function main() { + console.log("🎵 Starting song link fetcher...\n"); + + // Load existing data + const cache = await loadCache(); + const songLinks = await loadExistingSongLinks(); + + let requestCount = 0; + let successCount = 0; + let skipCount = 0; + let failCount = 0; + + // Process all albums and tracks + for (const album of albums) { + console.log(`\n📀 Album: ${album.label}`); + + for (const track of album.tracks) { + const songId = track.id; + const songName = track.label; + const spotifyUrl = track.__SPOTIFY_URL__; + + // Skip if already fetched + if (cache[songId]) { + console.log(` ⏭️ Skipping: ${songName} (already fetched)`); + skipCount++; + continue; + } + + // Skip if no Spotify URL + if (!spotifyUrl) { + console.log(` ⏭️ Skipping: ${songName} (no Spotify URL)`); + skipCount++; + continue; + } + + // Add delay before request (except for first request) + if (requestCount > 0) { + console.log(` ⏳ Waiting ${RATE_LIMIT_DELAY / 1000}s (rate limit)...`); + await delay(RATE_LIMIT_DELAY); + } + + // Fetch links + const links = await fetchSongLinks(spotifyUrl, songName); + + if (links) { + songLinks[songId] = links; + cache[songId] = true; + successCount++; + + // Save progress after each successful fetch + await saveSongLinksJSON(songLinks); + await saveCache(cache); + } else { + failCount++; + } + + requestCount++; + } + } + + // Save final TypeScript file + console.log("\n💾 Generating TypeScript file..."); + await saveSongLinksTS(songLinks); + + // Summary + console.log("\n" + "=".repeat(50)); + console.log("📊 Summary:"); + console.log(` Total requests: ${requestCount}`); + console.log(` Successful: ${successCount}`); + console.log(` Skipped: ${skipCount}`); + console.log(` Failed: ${failCount}`); + console.log("=".repeat(50)); + + // Format files with prettier + console.log("\n🎨 Formatting files with Prettier..."); + try { + await $`bunx prettier --write ${OUTPUT_TS_FILE} ${OUTPUT_JSON_FILE} ${CACHE_FILE}`; + console.log(` ✓ Formatted all files`); + } catch (error) { + console.error(" ⚠️ Prettier formatting failed:", error); + } + + console.log("\n✨ Done!"); + console.log(`\n📁 Output files:`); + console.log(` - ${OUTPUT_TS_FILE}`); + console.log(` - ${OUTPUT_JSON_FILE}`); + console.log(` - ${CACHE_FILE}`); +} + +// Run the script +main().catch((error) => { + console.error("❌ Fatal error:", error); + process.exit(1); +}); diff --git a/src/app/album/[albumId]/page.tsx b/src/app/album/[albumId]/page.tsx index de8d918..f67fc61 100644 --- a/src/app/album/[albumId]/page.tsx +++ b/src/app/album/[albumId]/page.tsx @@ -39,7 +39,7 @@ export default async function AlbumDetail({ params }: { params: Promise<{ albumI const theme = getThemeColors(albumId); return ( - + {/* Back Button */} @@ -76,69 +76,6 @@ export default async function AlbumDetail({ params }: { params: Promise<{ albumI - {/* Album Header */} - {/* - {/* Album Cover */} - {/* - - {album.label} - - */} - - {/* Album Info */} - {/* - - - {album.label} - - - - Released:{" "} - {new Date(album.releaseDate).toLocaleDateString("en-US", { - year: "numeric", - month: "long", - day: "numeric", - })} - - - - - {album.tracks.length} Songs - - - Linkin Park - - - - - - - - {album.description} - - */} - {/* */} - {/* Track List */} {album.tracks.length > 0 && ( diff --git a/src/lib/ListTypes.ts b/src/lib/ListTypes.ts index 832ed8a..3efc8d7 100644 --- a/src/lib/ListTypes.ts +++ b/src/lib/ListTypes.ts @@ -5,6 +5,9 @@ export type Track = { studioUrl: string | null; emilyLiveUrl: string | null; lpLiveUrl: string | null; + + // this is the spotify url for the album + __SPOTIFY_URL__: string; }; export type Album = { diff --git a/src/lib/list.ts b/src/lib/list.ts index a7cb81f..26fc94a 100644 --- a/src/lib/list.ts +++ b/src/lib/list.ts @@ -11,100 +11,124 @@ export const albums: Album[] = [ "Hybrid Theory is the debut studio album by American rock band Linkin Park, released on October 24, 2000, by Warner Bros. Records. It was recorded at The Plant Studios in Sausalito, California, and produced by Don Gilmore. The album was a commercial success, reaching number one on the Billboard 200 chart and selling over 10 million copies in the United States alone.", tracks: [ { - id: "1", + id: "hybrid-theory-1", label: "Papercut", duration: "03:04", studioUrl: null, emilyLiveUrl: null, lpLiveUrl: null, + + __SPOTIFY_URL__: "https://open.spotify.com/track/4HvcbAR8LisalXKt7cpqE1?si=a736ed41b9e84ff9", }, { - id: "2", + id: "hybrid-theory-2", label: "One Step Closer", duration: "02:35", studioUrl: null, emilyLiveUrl: null, lpLiveUrl: null, + + __SPOTIFY_URL__: "https://open.spotify.com/track/4bYLTrlcqctyHck3fjhMgW?si=dd2c47138fed4c4c", }, { - id: "3", + id: "hybrid-theory-3", label: "With You", duration: "03:23", studioUrl: null, emilyLiveUrl: null, lpLiveUrl: null, + + __SPOTIFY_URL__: "https://open.spotify.com/track/1Q9QN6dHEDeUegsySY012f?si=d4a1aca393954caa", }, { - id: "4", + id: "hybrid-theory-4", label: "Points of Authority", duration: "03:20", studioUrl: null, emilyLiveUrl: null, lpLiveUrl: null, + + __SPOTIFY_URL__: "https://open.spotify.com/track/214LJVTqrkUOGemWDGHJpr?si=749f11d7cd9a4f56", }, { - id: "5", + id: "hybrid-theory-5", label: "Crawling", duration: "03:29", studioUrl: null, emilyLiveUrl: null, lpLiveUrl: null, + + __SPOTIFY_URL__: "https://open.spotify.com/track/0X576XiCW9uEtko6f6VkcU?si=0a47dc1d660b4c71", }, { - id: "6", + id: "hybrid-theory-6", label: "Runaway", duration: "03:03", studioUrl: null, emilyLiveUrl: null, lpLiveUrl: null, + + __SPOTIFY_URL__: "https://open.spotify.com/track/5tkHje8FGSF258gi869GcV?si=f69a7e1ebf0f4f31", }, { - id: "7", + id: "hybrid-theory-7", label: "By Myself", duration: "03:09", studioUrl: null, emilyLiveUrl: null, lpLiveUrl: null, + + __SPOTIFY_URL__: "https://open.spotify.com/track/4SJoEhpI6C61wtUfxSHMGc?si=4ca78fd74ae74d6f", }, { - id: "8", + id: "hybrid-theory-8", label: "In the End", duration: "03:36", studioUrl: null, emilyLiveUrl: null, lpLiveUrl: null, + + __SPOTIFY_URL__: "https://open.spotify.com/track/7q115ia4fQn9zonjpexWsY?si=1e4cb0fe76244b11", }, { - id: "9", + id: "hybrid-theory-9", label: "A Place for My Head", duration: "03:04", studioUrl: null, emilyLiveUrl: null, lpLiveUrl: null, + + __SPOTIFY_URL__: "https://open.spotify.com/track/1B8WdDScvobpFsZLfdmIE1?si=f1b5b6fe0abb4e23", }, { - id: "10", + id: "hybrid-theory-10", label: "Forgotten", duration: "03:04", studioUrl: null, emilyLiveUrl: null, lpLiveUrl: null, + + __SPOTIFY_URL__: "https://open.spotify.com/track/3JAu2BH8sSI46rJGzQerb6?si=92186e546f0049b9", }, { - id: "11", + id: "hybrid-theory-11", label: "Cure for the Itch", duration: "02:37", studioUrl: null, emilyLiveUrl: null, lpLiveUrl: null, + + __SPOTIFY_URL__: "https://open.spotify.com/track/15voDM9pGkwEvHBUecpcmo?si=0b50fb655a2e4649", }, { - id: "12", + id: "hybrid-theory-12", label: "Pushing Me Away", duration: "03:11", studioUrl: null, emilyLiveUrl: null, lpLiveUrl: null, + + __SPOTIFY_URL__: "https://open.spotify.com/track/4HlMOXxwF9SYG1RoJxEjio?si=1b9286e4d2c947d3", }, ], }, @@ -118,216 +142,242 @@ export const albums: Album[] = [ "Meteora is the second studio album by American rock band Linkin Park, released on March 24, 2003, by Warner Bros. Records. It was recorded at The Plant Studios in Sausalito, California, and produced by Don Gilmore. The album was a commercial success, reaching number one on the Billboard 200 chart and selling over 10 million copies in the United States alone.", tracks: [ { - id: "1", + id: "meteora-1", label: "Foreword", duration: "00:13", studioUrl: null, emilyLiveUrl: null, lpLiveUrl: null, + + __SPOTIFY_URL__: "https://open.spotify.com/track/4hbpxoMCp62bd1sdy7XehS?si=0c4b2f93b36e43e7", }, { - id: "2", + id: "meteora-2", label: "Don't Stay", duration: "03:07", studioUrl: null, emilyLiveUrl: null, lpLiveUrl: null, + + __SPOTIFY_URL__: "https://open.spotify.com/track/6HZdbb05lEXLvcmee3ZXO2?si=b1f8362c72694a1b", }, { - id: "3", + id: "meteora-3", label: "Somewhere I Belong", duration: "03:33", studioUrl: null, emilyLiveUrl: null, lpLiveUrl: null, + + __SPOTIFY_URL__: "https://open.spotify.com/track/3agtg0x11wPvLIWkYR39nZ?si=e79dfe0143374cd9", }, { - id: "4", + id: "meteora-4", label: "Lying from You", duration: "02:55", studioUrl: null, emilyLiveUrl: null, lpLiveUrl: null, + + __SPOTIFY_URL__: "https://open.spotify.com/track/4zP2e2aIzOZGEFTq1MDJmm?si=a7951a3a01e740ac", }, { - id: "5", + id: "meteora-5", label: "Hit the Floor", duration: "02:44", studioUrl: null, emilyLiveUrl: null, lpLiveUrl: null, + + __SPOTIFY_URL__: "https://open.spotify.com/track/3R9NKZ4jmxNjOFihSF5s7f?si=3f07863add1e4e0f", }, { - id: "6", + id: "meteora-6", label: "Easier to Run", duration: "03:24", studioUrl: null, emilyLiveUrl: null, lpLiveUrl: null, + + __SPOTIFY_URL__: "https://open.spotify.com/track/17bgialGAwoiGj1STY4cnR?si=679a5b245d1d4610", }, { - id: "7", + id: "meteora-7", label: "Faint", duration: "02:42", studioUrl: null, emilyLiveUrl: null, lpLiveUrl: null, + + __SPOTIFY_URL__: "https://open.spotify.com/track/4Yf5bqU3NK4kNOypcrLYwU?si=cf2f7362cff04704", }, { - id: "8", + id: "meteora-8", label: "Figure.09", duration: "03:17", studioUrl: null, emilyLiveUrl: null, lpLiveUrl: null, + + __SPOTIFY_URL__: "https://open.spotify.com/track/2DrMcGNKEY0FZqjMovGaCm?si=583eb32931e84c48", }, { - id: "9", + id: "meteora-9", label: "Breaking the Habit", duration: "03:16", studioUrl: null, emilyLiveUrl: null, lpLiveUrl: null, + + __SPOTIFY_URL__: "https://open.spotify.com/track/6n8TMVyFKoUmDc4apxceRD?si=2b17f6b1906f46ec", }, { - id: "10", + id: "meteora-10", label: "From the Inside", duration: "02:55", studioUrl: null, emilyLiveUrl: null, lpLiveUrl: null, + + __SPOTIFY_URL__: "https://open.spotify.com/track/60IkVf7UfQXmt5CwkpcX8a?si=56ad75e64c174188", }, { - id: "11", + id: "meteora-11", label: "Nobody's Listening", duration: "02:58", studioUrl: null, emilyLiveUrl: null, lpLiveUrl: null, + + __SPOTIFY_URL__: "https://open.spotify.com/track/4m1P1BSg9nLxaWbvPhNdhw?si=9671f8d0299f429f", }, { - id: "12", + id: "meteora-12", label: "Session", duration: "02:24", studioUrl: null, emilyLiveUrl: null, lpLiveUrl: null, + + __SPOTIFY_URL__: "https://open.spotify.com/track/3sbezh9MMCQrr4KY7zw13j?si=62626db46f734d63", }, { - id: "13", + id: "meteora-13", label: "Numb", duration: "03:05", studioUrl: null, emilyLiveUrl: null, lpLiveUrl: null, + + __SPOTIFY_URL__: "https://open.spotify.com/track/2nLtzopw4rPReszdYBJU6h?si=8023141252ac4fec", }, ], }, - { - id: "minutes-to-midnight", - label: "Minutes to Midnight", - releaseDate: "2007-05-14", - image: "/minutes_to_midnight.jpg", - url: "/minutes-to-midnight", - description: - "Minutes to Midnight is the third studio album by American rock band Linkin Park, released on May 14, 2007, by Warner Bros. Records. The album marked a departure from the band's previous nu-metal sound, incorporating more alternative rock and experimental elements.", - tracks: [ - { - id: "1", - label: "Wake", - duration: "01:40", - studioUrl: null, - emilyLiveUrl: null, - lpLiveUrl: null, - }, - { - id: "2", - label: "Given Up", - duration: "03:09", - studioUrl: null, - emilyLiveUrl: null, - lpLiveUrl: null, - }, - { - id: "3", - label: "Leave Out All the Rest", - duration: "03:29", - studioUrl: null, - emilyLiveUrl: null, - lpLiveUrl: null, - }, - { - id: "4", - label: "Bleed It Out", - duration: "02:44", - studioUrl: null, - emilyLiveUrl: null, - lpLiveUrl: null, - }, - { - id: "5", - label: "Shadow of the Day", - duration: "04:49", - studioUrl: null, - emilyLiveUrl: null, - lpLiveUrl: null, - }, - { - id: "6", - label: "What I've Done", - duration: "03:25", - studioUrl: null, - emilyLiveUrl: null, - lpLiveUrl: null, - }, - { - id: "7", - label: "Hands Held High", - duration: "03:53", - studioUrl: null, - emilyLiveUrl: null, - lpLiveUrl: null, - }, - { - id: "8", - label: "No More Sorrow", - duration: "03:41", - studioUrl: null, - emilyLiveUrl: null, - lpLiveUrl: null, - }, - { - id: "9", - label: "Valentine's Day", - duration: "03:16", - studioUrl: null, - emilyLiveUrl: null, - lpLiveUrl: null, - }, - { - id: "10", - label: "In Between", - duration: "03:16", - studioUrl: null, - emilyLiveUrl: null, - lpLiveUrl: null, - }, - { - id: "11", - label: "In Pieces", - duration: "03:38", - studioUrl: null, - emilyLiveUrl: null, - lpLiveUrl: null, - }, - { - id: "12", - label: "The Little Things Give You Away", - duration: "06:23", - studioUrl: null, - emilyLiveUrl: null, - lpLiveUrl: null, - }, - ], - }, + // { + // id: "minutes-to-midnight", + // label: "Minutes to Midnight", + // releaseDate: "2007-05-14", + // image: "/minutes_to_midnight.jpg", + // url: "/minutes-to-midnight", + // description: + // "Minutes to Midnight is the third studio album by American rock band Linkin Park, released on May 14, 2007, by Warner Bros. Records. The album marked a departure from the band's previous nu-metal sound, incorporating more alternative rock and experimental elements.", + // tracks: [ + // { + // id: "minutes-to-midnight-1", + // label: "Wake", + // duration: "01:40", + // studioUrl: null, + // emilyLiveUrl: null, + // lpLiveUrl: null, + // }, + // { + // id: "minutes-to-midnight-2", + // label: "Given Up", + // duration: "03:09", + // studioUrl: null, + // emilyLiveUrl: null, + // lpLiveUrl: null, + // }, + // { + // id: "minutes-to-midnight-3", + // label: "Leave Out All the Rest", + // duration: "03:29", + // studioUrl: null, + // emilyLiveUrl: null, + // lpLiveUrl: null, + // }, + // { + // id: "minutes-to-midnight-4", + // label: "Bleed It Out", + // duration: "02:44", + // studioUrl: null, + // emilyLiveUrl: null, + // lpLiveUrl: null, + // }, + // { + // id: "minutes-to-midnight-5", + // label: "Shadow of the Day", + // duration: "04:49", + // studioUrl: null, + // emilyLiveUrl: null, + // lpLiveUrl: null, + // }, + // { + // id: "minutes-to-midnight-6", + // label: "What I've Done", + // duration: "03:25", + // studioUrl: null, + // emilyLiveUrl: null, + // lpLiveUrl: null, + // }, + // { + // id: "minutes-to-midnight-7", + // label: "Hands Held High", + // duration: "03:53", + // studioUrl: null, + // emilyLiveUrl: null, + // lpLiveUrl: null, + // }, + // { + // id: "minutes-to-midnight-8", + // label: "No More Sorrow", + // duration: "03:41", + // studioUrl: null, + // emilyLiveUrl: null, + // lpLiveUrl: null, + // }, + // { + // id: "minutes-to-midnight-9", + // label: "Valentine's Day", + // duration: "03:16", + // studioUrl: null, + // emilyLiveUrl: null, + // lpLiveUrl: null, + // }, + // { + // id: "minutes-to-midnight-10", + // label: "In Between", + // duration: "03:16", + // studioUrl: null, + // emilyLiveUrl: null, + // lpLiveUrl: null, + // }, + // { + // id: "minutes-to-midnight-11", + // label: "In Pieces", + // duration: "03:38", + // studioUrl: null, + // emilyLiveUrl: null, + // lpLiveUrl: null, + // }, + // { + // id: "minutes-to-midnight-12", + // label: "The Little Things Give You Away", + // duration: "06:23", + // studioUrl: null, + // emilyLiveUrl: null, + // lpLiveUrl: null, + // }, + // ], + // }, ]; diff --git a/src/lib/songLinks.ts b/src/lib/songLinks.ts new file mode 100644 index 0000000..093efa4 --- /dev/null +++ b/src/lib/songLinks.ts @@ -0,0 +1,193 @@ +// This file is auto-generated by scripts/fetch-song-links.ts +// Do not edit manually +// Last updated: 2025-10-24T22:59:54.578Z +// Run: bun run fetch-links + +export interface SongLinks { + spotify?: string; + youtube?: string; + youtubeMusic?: string; + appleMusic?: string; +} + +export interface SongLinksData { + [songId: string]: SongLinks; +} + +export const songLinks: SongLinksData = { + "hybrid-theory-1": { + spotify: "https://open.spotify.com/track/4HvcbAR8LisalXKt7cpqE1", + youtube: "https://www.youtube.com/watch?v=vjVkXlxsO8Q", + youtubeMusic: "https://music.youtube.com/watch?v=vjVkXlxsO8Q", + appleMusic: + "https://geo.music.apple.com/de/album/_/528436018?i=528436568&mt=1&app=music&ls=1&at=1000lHKX&ct=api_http&itscg=30200&itsct=odsl_m", + }, + "hybrid-theory-2": { + spotify: "https://open.spotify.com/track/4bYLTrlcqctyHck3fjhMgW", + youtube: "https://www.youtube.com/watch?v=4qlCC1GOwFw", + youtubeMusic: "https://music.youtube.com/watch?v=4qlCC1GOwFw", + appleMusic: + "https://geo.music.apple.com/de/album/_/590431776?i=590431778&mt=1&app=music&ls=1&at=1000lHKX&ct=api_http&itscg=30200&itsct=odsl_m", + }, + "hybrid-theory-3": { + spotify: "https://open.spotify.com/track/1Q9QN6dHEDeUegsySY012f", + youtube: "https://www.youtube.com/watch?v=M8UTS2iFXOo", + youtubeMusic: "https://music.youtube.com/watch?v=M8UTS2iFXOo", + appleMusic: + "https://geo.music.apple.com/de/album/_/528436018?i=528437421&mt=1&app=music&ls=1&at=1000lHKX&ct=api_http&itscg=30200&itsct=odsl_m", + }, + "hybrid-theory-4": { + spotify: "https://open.spotify.com/track/214LJVTqrkUOGemWDGHJpr", + youtube: "https://www.youtube.com/watch?v=jZSPAp8kCl4", + youtubeMusic: "https://music.youtube.com/watch?v=jZSPAp8kCl4", + appleMusic: + "https://geo.music.apple.com/de/album/_/590431776?i=590431781&mt=1&app=music&ls=1&at=1000lHKX&ct=api_http&itscg=30200&itsct=odsl_m", + }, + "hybrid-theory-5": { + spotify: "https://open.spotify.com/track/0X576XiCW9uEtko6f6VkcU", + youtube: "https://www.youtube.com/watch?v=Gd9OhYroLN0", + youtubeMusic: "https://music.youtube.com/watch?v=Gd9OhYroLN0", + appleMusic: + "https://geo.music.apple.com/de/album/_/591534774?i=591534780&mt=1&app=music&ls=1&at=1000lHKX&ct=api_http&itscg=30200&itsct=odsl_m", + }, + "hybrid-theory-6": { + spotify: "https://open.spotify.com/track/5tkHje8FGSF258gi869GcV", + youtube: "https://www.youtube.com/watch?v=ig-fyQqf510", + youtubeMusic: "https://music.youtube.com/watch?v=ig-fyQqf510", + appleMusic: + "https://geo.music.apple.com/de/album/_/528436018?i=528437609&mt=1&app=music&ls=1&at=1000lHKX&ct=api_http&itscg=30200&itsct=odsl_m", + }, + "hybrid-theory-7": { + spotify: "https://open.spotify.com/track/4SJoEhpI6C61wtUfxSHMGc", + youtube: "https://www.youtube.com/watch?v=wWBp-nlGX1o", + youtubeMusic: "https://music.youtube.com/watch?v=wWBp-nlGX1o", + appleMusic: + "https://geo.music.apple.com/de/album/_/528436018?i=528437611&mt=1&app=music&ls=1&at=1000lHKX&ct=api_http&itscg=30200&itsct=odsl_m", + }, + "hybrid-theory-8": { + spotify: "https://open.spotify.com/track/7q115ia4fQn9zonjpexWsY", + youtube: "https://www.youtube.com/watch?v=eVTXPUF4Oz4", + youtubeMusic: "https://music.youtube.com/watch?v=eVTXPUF4Oz4", + appleMusic: + "https://geo.music.apple.com/de/album/_/528436018?i=528437613&mt=1&app=music&ls=1&at=1000lHKX&ct=api_http&itscg=30200&itsct=odsl_m", + }, + "hybrid-theory-9": { + spotify: "https://open.spotify.com/track/1B8WdDScvobpFsZLfdmIE1", + youtube: "https://www.youtube.com/watch?v=3t2WkCudwfY", + youtubeMusic: "https://music.youtube.com/watch?v=3t2WkCudwfY", + appleMusic: + "https://geo.music.apple.com/de/album/_/528436018?i=528437708&mt=1&app=music&ls=1&at=1000lHKX&ct=api_http&itscg=30200&itsct=odsl_m", + }, + "hybrid-theory-10": { + spotify: "https://open.spotify.com/track/3JAu2BH8sSI46rJGzQerb6", + youtube: "https://www.youtube.com/watch?v=HNCgBuI2eJc", + youtubeMusic: "https://music.youtube.com/watch?v=HNCgBuI2eJc", + appleMusic: + "https://geo.music.apple.com/de/album/_/528436018?i=528437709&mt=1&app=music&ls=1&at=1000lHKX&ct=api_http&itscg=30200&itsct=odsl_m", + }, + "hybrid-theory-11": { + spotify: "https://open.spotify.com/track/15voDM9pGkwEvHBUecpcmo", + youtube: "https://www.youtube.com/watch?v=qqC5sdsHLq8", + youtubeMusic: "https://music.youtube.com/watch?v=qqC5sdsHLq8", + appleMusic: + "https://geo.music.apple.com/de/album/_/528436018?i=528437710&mt=1&app=music&ls=1&at=1000lHKX&ct=api_http&itscg=30200&itsct=odsl_m", + }, + "hybrid-theory-12": { + spotify: "https://open.spotify.com/track/4HlMOXxwF9SYG1RoJxEjio", + youtube: "https://www.youtube.com/watch?v=Ve1LNJEIKUE", + youtubeMusic: "https://music.youtube.com/watch?v=Ve1LNJEIKUE", + appleMusic: + "https://geo.music.apple.com/de/album/_/590431776?i=590431790&mt=1&app=music&ls=1&at=1000lHKX&ct=api_http&itscg=30200&itsct=odsl_m", + }, + "meteora-1": { + spotify: "https://open.spotify.com/track/4hbpxoMCp62bd1sdy7XehS", + youtube: "https://www.youtube.com/watch?v=U6R-twDkrcI", + youtubeMusic: "https://music.youtube.com/watch?v=U6R-twDkrcI", + appleMusic: + "https://geo.music.apple.com/de/album/_/590423275?i=590423280&mt=1&app=music&ls=1&at=1000lHKX&ct=api_http&itscg=30200&itsct=odsl_m", + }, + "meteora-2": { + spotify: "https://open.spotify.com/track/6HZdbb05lEXLvcmee3ZXO2", + youtube: "https://www.youtube.com/watch?v=oWfGOVWrueo", + youtubeMusic: "https://music.youtube.com/watch?v=oWfGOVWrueo", + appleMusic: + "https://geo.music.apple.com/de/album/_/1668484895?i=1668485277&mt=1&app=music&ls=1&at=1000lHKX&ct=api_http&itscg=30200&itsct=odsl_m", + }, + "meteora-3": { + spotify: "https://open.spotify.com/track/3agtg0x11wPvLIWkYR39nZ", + youtube: "https://www.youtube.com/watch?v=zsCD5XCu6CM", + youtubeMusic: "https://music.youtube.com/watch?v=zsCD5XCu6CM", + appleMusic: + "https://geo.music.apple.com/de/album/_/528435845?i=528437020&mt=1&app=music&ls=1&at=1000lHKX&ct=api_http&itscg=30200&itsct=odsl_m", + }, + "meteora-4": { + spotify: "https://open.spotify.com/track/4zP2e2aIzOZGEFTq1MDJmm", + youtube: "https://www.youtube.com/watch?v=NjdgcHdzvac", + youtubeMusic: "https://music.youtube.com/watch?v=NjdgcHdzvac", + appleMusic: + "https://geo.music.apple.com/de/album/_/590423275?i=590423283&mt=1&app=music&ls=1&at=1000lHKX&ct=api_http&itscg=30200&itsct=odsl_m", + }, + "meteora-5": { + spotify: "https://open.spotify.com/track/3R9NKZ4jmxNjOFihSF5s7f", + youtube: "https://www.youtube.com/watch?v=oMals9XXQY8", + youtubeMusic: "https://music.youtube.com/watch?v=oMals9XXQY8", + appleMusic: + "https://geo.music.apple.com/de/album/_/590423275?i=590423284&mt=1&app=music&ls=1&at=1000lHKX&ct=api_http&itscg=30200&itsct=odsl_m", + }, + "meteora-6": { + spotify: "https://open.spotify.com/track/17bgialGAwoiGj1STY4cnR", + youtube: "https://www.youtube.com/watch?v=U5zdmjVeQzE", + youtubeMusic: "https://music.youtube.com/watch?v=U5zdmjVeQzE", + appleMusic: + "https://geo.music.apple.com/de/album/_/590423275?i=590423285&mt=1&app=music&ls=1&at=1000lHKX&ct=api_http&itscg=30200&itsct=odsl_m", + }, + "meteora-7": { + spotify: "https://open.spotify.com/track/4Yf5bqU3NK4kNOypcrLYwU", + youtube: "https://www.youtube.com/watch?v=LYU-8IFcDPw", + youtubeMusic: "https://music.youtube.com/watch?v=LYU-8IFcDPw", + appleMusic: + "https://geo.music.apple.com/de/album/_/528435845?i=528437024&mt=1&app=music&ls=1&at=1000lHKX&ct=api_http&itscg=30200&itsct=odsl_m", + }, + "meteora-8": { + spotify: "https://open.spotify.com/track/2DrMcGNKEY0FZqjMovGaCm", + youtube: "https://www.youtube.com/watch?v=6dEAeCHQrBs", + youtubeMusic: "https://music.youtube.com/watch?v=6dEAeCHQrBs", + appleMusic: + "https://geo.music.apple.com/de/album/_/528435845?i=528437025&mt=1&app=music&ls=1&at=1000lHKX&ct=api_http&itscg=30200&itsct=odsl_m", + }, + "meteora-9": { + spotify: "https://open.spotify.com/track/6n8TMVyFKoUmDc4apxceRD", + youtube: "https://www.youtube.com/watch?v=v2H4l9RpkwM", + youtubeMusic: "https://music.youtube.com/watch?v=v2H4l9RpkwM", + appleMusic: + "https://geo.music.apple.com/de/album/_/528435845?i=528437026&mt=1&app=music&ls=1&at=1000lHKX&ct=api_http&itscg=30200&itsct=odsl_m", + }, + "meteora-10": { + spotify: "https://open.spotify.com/track/60IkVf7UfQXmt5CwkpcX8a", + youtube: "https://www.youtube.com/watch?v=YLHpvjrFpe0", + youtubeMusic: "https://music.youtube.com/watch?v=YLHpvjrFpe0", + appleMusic: + "https://geo.music.apple.com/de/album/_/528435845?i=528437027&mt=1&app=music&ls=1&at=1000lHKX&ct=api_http&itscg=30200&itsct=odsl_m", + }, + "meteora-11": { + spotify: "https://open.spotify.com/track/4m1P1BSg9nLxaWbvPhNdhw", + youtube: "https://www.youtube.com/watch?v=QJ87793QXes", + youtubeMusic: "https://music.youtube.com/watch?v=QJ87793QXes", + appleMusic: + "https://geo.music.apple.com/de/album/_/590423275?i=590423550&mt=1&app=music&ls=1&at=1000lHKX&ct=api_http&itscg=30200&itsct=odsl_m", + }, + "meteora-12": { + spotify: "https://open.spotify.com/track/3sbezh9MMCQrr4KY7zw13j", + youtube: "https://www.youtube.com/watch?v=J1KqQYsUYIk", + youtubeMusic: "https://music.youtube.com/watch?v=J1KqQYsUYIk", + appleMusic: + "https://geo.music.apple.com/de/album/_/528435845?i=528437513&mt=1&app=music&ls=1&at=1000lHKX&ct=api_http&itscg=30200&itsct=odsl_m", + }, + "meteora-13": { + spotify: "https://open.spotify.com/track/2nLtzopw4rPReszdYBJU6h", + youtube: "https://www.youtube.com/watch?v=kXYiU_JCYtU", + youtubeMusic: "https://music.youtube.com/watch?v=kXYiU_JCYtU", + appleMusic: + "https://geo.music.apple.com/de/album/_/528435845?i=528437514&mt=1&app=music&ls=1&at=1000lHKX&ct=api_http&itscg=30200&itsct=odsl_m", + }, +}; diff --git a/tsconfig.json b/tsconfig.json index 584ed54..c0f6404 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -2,6 +2,7 @@ "compilerOptions": { "target": "ES2020", "lib": ["ES2020", "DOM", "DOM.Iterable"], + "types": ["bun-types"], "module": "ESNext", "skipLibCheck": true, "moduleResolution": "bundler",