const Soundcloud = require('soundcloud.ts').default; const fs = require('fs'); const path = require('path'); const slugify = require('slugify'); // Configuration const PLAYLIST_URL = 'https://soundcloud.com/snxraven/sets/raven-scott-rap'; // Metal playlist URL const CACHE_FILE = path.join(__dirname, 'cache_rap.json'); // Cache file for metal playlist // Helper function to create a slug from track title function generateSlug(title) { try { const slug = slugify(title, { lower: true, strict: true, remove: /[*+~.()'"!:@]/g }); if (!slug || slug.trim() === '') { console.warn(`Empty slug for title: "${title}". Using fallback.`); return 'track-' + Date.now(); } console.log(`Generated slug for "${title}": "${slug}"`); return slug; } catch (err) { console.error(`Error generating slug for title: "${title}"`, err); return 'track-' + Date.now(); } } // Helper function to sanitize track data function sanitizeTrackData(track) { return { title: typeof track.title === 'string' ? track.title : 'Unknown Title', description: typeof track.description === 'string' ? track.description : 'No description available', url: typeof track.permalink_url === 'string' ? track.permalink_url : '', playCount: Number.isFinite(track.playback_count) ? track.playback_count : 0, publishedAt: typeof track.created_at === 'string' ? track.created_at : new Date().toISOString(), slug: generateSlug(track.title || 'Unknown') }; } // Helper function to save cache function saveCache(cacheFile, data) { try { // Filter out invalid tracks const validTracks = data.tracks.filter(track => { try { JSON.stringify(track); return true; } catch (err) { console.error(`Invalid track data for "${track.title}":`, err); return false; } }); const cacheData = { tracks: validTracks, timestamp: data.timestamp }; console.log(`Saving cache with ${validTracks.length} tracks to ${cacheFile}`); console.log('Cached track titles:', validTracks.map(t => t.title)); const jsonString = JSON.stringify(cacheData, null, 2); fs.writeFileSync(cacheFile, jsonString, { encoding: 'utf8' }); console.log(`Cache saved to ${cacheFile}`); } catch (err) { console.error(`Error saving cache to ${cacheFile}:`, err); console.error('Problematic cache data:', data); } } // Fetch all tracks from a SoundCloud playlist async function fetchPlaylist(playlistUrl) { try { const soundcloud = new Soundcloud(); // No client ID or OAuth token const playlist = await soundcloud.playlists.getAlt(playlistUrl); console.log(`Fetched playlist with ${playlist.tracks.length} tracks:`, playlist.tracks.map(t => t.title)); const tracks = []; for (const track of playlist.tracks) { try { console.log(`Processing track: "${track.title || 'Unknown'}"`); const trackData = sanitizeTrackData(track); tracks.push(trackData); console.log(`Successfully processed track: "${track.title || 'Unknown'}"`); } catch (err) { console.error(`Error processing track "${track.title || 'Unknown'}":`, err); continue; } } console.log(`Total fetched tracks: ${tracks.length}`); if (tracks.length < 56) { console.warn(`Expected ~56 tracks, but only ${tracks.length} were fetched. Verify playlist URL or check for private tracks.`); } return tracks; } catch (err) { console.error(`Error fetching playlist ${playlistUrl}:`, err); return []; } } // Main function to generate cache async function generateCache() { const tracks = await fetchPlaylist(PLAYLIST_URL); saveCache(CACHE_FILE, { tracks, timestamp: Date.now() }); } // Run the cache generation generateCache().catch(err => { console.error('Error generating cache:', err); process.exit(1); });