const fs = require("fs"); const path = require("path"); const csv = require("csv-parser"); const React = require("react"); const dotenv = require("dotenv"); const ReactDOMServer = require("react-dom/server"); const TemplatePageModule = require("./build/components/jamtracks/JKJamTracksLandingTemplatePage"); const ArtistTemplatePageModule = require("./build/components/jamtracks/JKJamTracksArtistLandingTemplatePage"); var csvFilePath = `jamtracks-for-env/jam_tracks_for_jam_ui.${process.env.USER}.csv` var artistCsvFilePath = `jamtracks-for-env/jam_tracks_for_jam_ui_artists.${process.env.USER}.csv` var sitemapPath = path.join(__dirname, "..", "public", "sitemap.xml"); const clear_sitemap = () => { fs.writeFileSync(sitemapPath, ""); // Add the root element fs.writeFileSync(sitemapPath, `\n`, { flag: 'a' }); // Add the root url fs.writeFileSync(sitemapPath, `${process.env.REACT_APP_BASE_URL}\n`, { flag: 'a' }); // Add standard URLs specific to this site, such as: // All prefix with /public fs.writeFileSync(sitemapPath, `${process.env.REACT_APP_BASE_URL}/\n`, { flag: 'a' }); fs.writeFileSync(sitemapPath, `${process.env.REACT_APP_BASE_URL}/public/privacy\n`, { flag: 'a' } ); fs.writeFileSync(sitemapPath, `${process.env.REACT_APP_BASE_URL}/public/help\n`, { flag: 'a' } ); fs.writeFileSync(sitemapPath, `${process.env.REACT_APP_BASE_URL}/public/knowledge-base\n`, { flag: 'a' } ); fs.writeFileSync(sitemapPath, `${process.env.REACT_APP_BASE_URL}/public/help-desk\n`, { flag: 'a' } ); fs.writeFileSync(sitemapPath, `${process.env.REACT_APP_BASE_URL}/public/forum\n`, { flag: 'a' } ); fs.writeFileSync(sitemapPath, `${process.env.REACT_APP_BASE_URL}/public/unsubscribe\n`, { flag: 'a' } ); fs.writeFileSync(sitemapPath, `${process.env.REACT_APP_BASE_URL}/public/downloads\n`, { flag: 'a' } ); fs.writeFileSync(sitemapPath, `${process.env.REACT_APP_BASE_URL}/public/downloads-legacy\n`, { flag: 'a' } ); fs.writeFileSync(sitemapPath, `${process.env.REACT_APP_BASE_URL}/auth/login\n`, { flag: 'a' }); fs.writeFileSync(sitemapPath, `${process.env.REACT_APP_BASE_URL}/auth/signup\n`, { flag: 'a' } ); fs.writeFileSync(sitemapPath, `${process.env.REACT_APP_BASE_URL}/auth/forget-password\n`, { flag: 'a' } ); // Add the closing root element } const add_song_to_sitemap = (artistSlug, songSlug) => { fs.writeFileSync(sitemapPath, `${process.env.REACT_APP_BASE_URL}/backing-tracks/${artistSlug}/${songSlug}\n`, { flag: 'a' }); } const add_artist_to_sitemap = (artistSlug) => { fs.writeFileSync(sitemapPath, `${process.env.REACT_APP_BASE_URL}/backing-tracks/${artistSlug}\n`, { flag: 'a' }); } const close_sitemap = () => { fs.writeFileSync(sitemapPath, "", { flag: 'a' } ); } /** * Loads a CSV file into an array of objects. * @param {string} csvPath - The path to the CSV file. * @returns {Promise>} - A promise that resolves with the parsed CSV data. */ const load_csv = (csvPath) => { return new Promise((resolve, reject) => { const results = []; fs.createReadStream(csvPath) .pipe(csv()) .on('data', (data) => results.push(data)) .on('end', () => resolve(results)) .on('error', (error) => reject(error)); }); }; /** * Finds all songs for a given artist based on the original_artist_slug * and sorts them alphabetically by the `slug` field. * @param {string} artistSlug - The original_artist_slug to match. * @param {Array} songsCsv - The songs CSV data. * @returns {Array} - A sorted array of matching song objects. */ const collect_songs_for_artist = (artistSlug, songsCsv) => { return songsCsv .filter((song) => song.original_artist_slug === artistSlug) .sort((a, b) => a.slug.localeCompare(b.slug)); // Sort alphabetically by slug }; const init = () => { const node_env = process.env.NODE_ENV || 'development'; const environment = process.env.ENVIRONMENT || 'development'; console.log(`environment=${environment} node_env=${node_env}`); console.log(dotenv.config({ path: `../.env.${environment}` })); if (environment === "production" || environment === "staging") { csvFilePath = `jamtracks-for-env/jam_tracks_for_jam_ui.${environment}.csv`; artistCsvFilePath = `jamtracks-for-env/jam_tracks_for_jam_ui_artists.${environment}.csv`; } console.log("Song csv file", csvFilePath); console.log("Artist csv file", artistCsvFilePath); if (!process.env.PUBLIC_URL) { console.log("setting public url", process.env.REACT_APP_BASE_URL); process.env.PUBLIC_URL = process.env.REACT_APP_BASE_URL; } clear_sitemap(); //const __dirname = path.resolve(path.dirname('')); console.log("init done successfully") } const generateSongPages = async (render) => { const rows = []; const OUTPUT_DIR = path.join(__dirname, "..", "public", "backing-tracks"); if (!fs.existsSync(OUTPUT_DIR)) { fs.mkdirSync(OUTPUT_DIR, { recursive: true }); } console.log("generatPages starting") const TemplatePage = TemplatePageModule.default; fs.createReadStream(csvFilePath) .pipe(csv()) .on("data", (row) => rows.push(row)) .on("end", async () => { console.log(`Processing ${rows.length} rows...`); for (const row of rows) { // id, original_artist, name, original_artist_slug, name_slug, plan_code, slug, URL, licensor, vendor_id const { id, original_artist, name, original_artist_slug, name_slug, plan_code, slug, allow_free } = row; const artist = original_artist; const song = name; const location = `/backing-tracks/${original_artist_slug}/${name_slug}`; const fullPath = process.env.REACT_APP_BASE_URL + location; const logoPath = process.env.REACT_APP_BASE_URL + "/favicon.svg"; add_song_to_sitemap(original_artist_slug, name_slug); console.log(`Generating ${artist} - ${song}`); const html = render ? ReactDOMServer.renderToStaticMarkup( React.createElement(TemplatePage, { id, plan_code, slug, artist, song, location }) ) : ""; const fullHtml = ` ${artist} - ${song} - Free Backing Track
${html}
`; const ARTIST_DIR = path.join(OUTPUT_DIR, original_artist_slug); if (!fs.existsSync(ARTIST_DIR)) { fs.mkdirSync(ARTIST_DIR, { recursive: false }); } const finalOutputPath = process.env.NODE_ENV === "development" ? `${name_slug}.html` : `${name_slug}.html`; const outputFilePath = path.join(ARTIST_DIR, finalOutputPath); fs.writeFileSync(outputFilePath, fullHtml); console.log(`Generated: ${outputFilePath}`); } console.log("All pages generated!"); }); }; const generateArtistPages = async (render) => { const rows = []; const OUTPUT_DIR = path.join(__dirname, "..", "public", "backing-tracks"); if (!fs.existsSync(OUTPUT_DIR)) { fs.mkdirSync(OUTPUT_DIR, { recursive: true }); } console.log("generatPages starting") const TemplatePage = TemplatePageModule.default; const songs_csv = await load_csv(csvFilePath); fs.createReadStream(artistCsvFilePath) .pipe(csv()) .on("data", (row) => rows.push(row)) .on("end", async () => { console.log(`Processing ${rows.length} rows...`); for (const row of rows) { const { original_artist, original_artist_slug, url } = row; const artist = original_artist; const matchingSongs = collect_songs_for_artist(original_artist_slug, songs_csv); console.log(`Found ${matchingSongs.length} songs for ${artist}`); const location = `/backing-tracks/${original_artist_slug}`; const fullPath = process.env.REACT_APP_BASE_URL + location; const logoPath = process.env.REACT_APP_BASE_URL + "/favicon.svg"; add_artist_to_sitemap(original_artist_slug); console.log(`Generating ${artist}`); const songs = matchingSongs.map((song) => { return { name: song.name, plan_code: song.plan_code, url: process.env.REACT_APP_BASE_URL + "/backing-tracks/" + song.original_artist_slug + "/" + song.name_slug } }); const html = render ? ReactDOMServer.renderToStaticMarkup( React.createElement(ArtistTemplatePage, { artist, original_artist_slug, location }) ) : ""; const fullHtml = ` ${artist} - Free Backing Track
${html}
`; const finalOutputPath = process.env.NODE_ENV === "development" ? `${original_artist_slug}.html` : `${original_artist_slug}.html`; const outputFilePath = path.join(OUTPUT_DIR, finalOutputPath); fs.writeFileSync(outputFilePath, fullHtml); console.log(`Generated: ${outputFilePath}`); } close_sitemap(); console.log("All pages generated!"); }); }; let render = false; if (process.argv.length > 2) { render = process.argv[2] === "true" || process.argv[2] === "yes" || process.argv[2] === "1"; } init() generateSongPages(render); generateArtistPages(render);