CodeNewbie Community 🌱

stockbull11
stockbull11

Posted on

Creating a Spotify Song Downloader: Unveiling the Harmony of spotdl, React, and Express 🎵💃🚀

Gentle Heads-Up:
As we set sail on this melodic coding expedition, a friendly nudge! Our purpose here is purely educational. While the temptation to groove to those beats is strong, grabbing copyrighted content without the right permissions is a strict no-no. Let's always dance gracefully within the bounds of the law!

Check My Live Spotify Downloader: https://spotisaver.org/

Fine-Tuning the Frontend Symphony with React 🎸

Prerequisites:

  • Your coding groove on!
  • Node.js and npm installed.

Striking the React Notes:
Our frontend is like the face of our band - it's what the crowd sees! Let's dive into the React part and understand each chord:

// ----- Imports -----
import React, { useState } from 'react';
import styled from 'styled-components';
import Swal from 'sweetalert2';
import 'bootstrap/dist/css/bootstrap.min.css';

// ----- Styled Components -----

// Container components
const ScrollContainer = styled.div`
  scroll-snap-type: y mandatory;
  overflow-y: scroll;
  height: 100vh;
`;
const SectionsContainer = styled.div`
  max-height: 40vh;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 10px;
`;

// Layout and positioning components
const Section = styled.div`
  min-height: 100vh;
  scroll-snap-align: start;
  display: flex;
  flex-direction: column;
  justify-content: center;
  // align-items: center;
`;
const TableContainer = styled.div`
  width: 100%;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  padding: 20px;
  margin: 20px;
`;
const InputGroupContainer = styled.div`
  display: flex;
  justify-content: center;
`;

// List and item components
const ListContainer = styled.div`
  height: 20vh; 
  overflow-y: scroll;
`;

// ----- App Component -----
export default function App() {
  // State hooks
  const [sections, setSections] = useState([{ songUrl: '', audioFormat: 'mp3', urlList: [] }]);

  // Handle adding song URL and downloading
  const handleAddUrl = async (index) => {
    const newSections = [...sections];
    const section = newSections[index];

    try {
      const response = await fetch('http://localhost:3001/api/download', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ url: section.songUrl, format: section.audioFormat }),
      });

      if (response.ok) {
        const data = await response.json();
        section.urlList = [section.songUrl, ...section.urlList];
        newSections[index] = section;
        setSections(newSections);
        Swal.fire({ icon: 'success', title: 'OK', showConfirmButton: false, timer: 1000 });
      } else {
        Swal.fire({ icon: 'error', title: 'Song not found', showConfirmButton: false, timer: 1000 });
      }
    } catch (error) {
      Swal.fire({ icon: 'error', title: 'Song not found', showConfirmButton: false, timer: 1000 });
    }

    // Clear the input
    section.songUrl = '';
    newSections[index] = section;
    setSections(newSections);
  };

  const addSection = () => {
    setSections([...sections, { songUrl: '', audioFormat: 'mp3', urlList: [] }]);
  };

  // Main render
  return (
    <ScrollContainer>
      {/* Intro Section */}
      <Section className="container-fluid text-center">
        <h1 className="display-3">Download Spotify Songs with <code>spotdl</code></h1>
        <h1 className="display-5 text-center my-4">How to Download Music with SpotDL</h1>
        <p className="text-center mb-4">
          SpotDL is a utility that allows you to download music from Spotify directly to your computer. Here's a simple guide on how to use it with terminal commands.
        </p>
      </Section>

      {/* Command Table Section */}
      <Section className="container-fluid text-center">
        <TableContainer>
          <table className="table table-bordered">
            <thead>
              <tr>
                <th className="text-center">Command</th>
                <th className="text-center">Description</th>
              </tr>
            </thead>
            <tbody>
              {/* Commands */}
              <tr>
                <td className="text-center"><code>spotdl [trackUrl]</code></td>
                <td className="text-center">Download a track by its Spotify URL</td>
              </tr>
              {/* ... other commands ... */}
            </tbody>
          </table>
        </TableContainer>
        {/* Command Examples */}
        {/* ... */}
      </Section>

      {/* Download Section */}
      <Section className="container-fluid text-center">
        <div style={{ display: 'flex', justifyContent: 'center', marginBottom: '1rem' }}>
          <button className="btn btn-success w-25" style={{ width: 'auto' }} onClick={addSection}>New Section</button>
        </div>
        <SectionsContainer>
          {/* Iterating through sections for download */}
          {/* ... */}
        </SectionsContainer>
      </Section>
    </ScrollContainer>
  );
}
Enter fullscreen mode Exit fullscreen mode

*Decoding the Chords:
*

Styled Components:
We're using styled-components to strike a fashion statement with our app. Just like a rockstar needs an outfit, our components need styles!
Swal Alerts:
These pop-up alerts are like the light effects on stage. They inform the user whether their download was a hit or a miss.
React Hooks:
Just like how a song has multiple verses, our app keeps track of song URLs and formats using the useState hook.
Fetch API:
When the user wants to download a song, we send a request to our backstage (backend) crew using the Fetch API.

*Strumming the Backend with Express 🎤
*

Prerequisites:

  • Your coding rhythm!
  • Node.js and npm.

Hitting the Express High Notes:
Our backend is the unseen hero, doing all the heavy lifting. It's like the bassist, setting the foundation:

// ----- Imports -----
const express = require('express');
const cors = require('cors');
const { exec } = require('child_process');

// ----- Express App Configuration -----
const app = express();

// Middleware setup
app.use(cors());           // Enable CORS for all routes
app.use(express.json());   // For parsing application/json

// ----- Routes -----

// POST endpoint for song download
app.post('/api/download', (req, res) => {
    // Destructuring to get URL and format from the request body
    const { url, format } = req.body;

    // IMPORTANT: Always be cautious when running shell commands from user input.
    // Sanitize and validate the input to prevent malicious code execution.
    exec(`spotdl ${url}`, (error, stdout, stderr) => {
        if (error) {
            // Handle command execution errors
            return res.status(500).json({ error: 'Download failed' });
        }

        // Ideally, you'd return something more substantial here.
        // For example, you might return a download link or save the song info.
        res.status(200).json({ success: true, message: 'Downloaded successfully!' });
    });
});

// ----- Start the server -----
const PORT = 3001;
app.listen(PORT, () => {
    console.log(`Server running on http://localhost:${PORT}`);

**Navigating the Express Crescendo:
**
Express and CORS Harmony: Picture Express as our grand stage, and CORS as the harmony that ensures no unwanted interruptions, much like maintaining the security of our musical performance.

Child Process Drumroll: Introducing the Child Process – the backbone of our app, enabling it to play terminal commands like a skilled drummer hitting the beats in perfect rhythm.

API Endpoint Spotlight: The spotlight steals the show with our /api/download endpoint. This is the star of our performance, engaging with spotdl to download songs and gracefully waltzing with the frontend, creating a seamless and melodious user experience.

**Tuning In with httpie 🎧
**
Once the stage is set, it's time for a soundcheck – a crucial step to ensure everything is in perfect harmony. Conducting a soundcheck for our API using httpie is as straightforward as a melody:
Enter fullscreen mode Exit fullscreen mode


bash
http POST http://localhost:3001/api/download url= format=mp3



Simply replace `<Spotify_URL>` with the URL of your desired Spotify song, and let the enchantment unfold!

**The Grand Finale: Continued Learning 🌟
**Still craving more knowledge? Here's your backstage pass to take this coding party to the next level:
Dive Deeper into React: 
Uncover the mysteries of React by exploring its official documentation. For an extra thrill, venture into React Native and explore the world of mobile magic.
Express Middleware:
 Elevate your backend band by learning about Express middleware. It's like adding more instruments to your repertoire, enhancing your server's capabilities.
Web Security: 
Just like a band needs security at their concert, your web app deserves protection. Delve into the realm of web security practices to ensure a safe and sound experience for your users.
Wrapping Up & Final Notes:
And that's a wrap for our exhilarating journey through React, Express, and spotdl! I hope you've enjoyed this musical coding jam as much as I enjoyed creating it for you. Remember to groove responsibly and always respect the art and the artist!
But wait, there's more! If this guide struck a chord with you, join me on various platforms to keep the tech melodies flowing:
💻 Websites:
For in-depth guides, articles, and tutorials, visit spotisaver.org. It's a treasure trove designed to enhance your coding voyage.
Looking for AI tools? Discover, an AI finding platform built with Flutter and Dart, designed to pool the best AI resources for enthusiasts like you.
💌 Email: 
For feedback, questions, or just a good old chat about the wonders of tech and coding, drop a note at stockbull786@gmail.com. Engaging with fellow tech enthusiasts always brightens my day!
Before I take my final bow, let me reiterate: the world of coding is vast and magnificent, and collaboration and shared learning are its pillars. Whether you have queries, need help, or wish to share your own insights, I'm always here, eager to listen and assist.
Stay curious, stay passionate, and let's continue fostering a community where every coder finds their rhythm. Happy coding! 🎵🚀



Enter fullscreen mode Exit fullscreen mode

Top comments (0)