Added url parser class to find out which type of url is entered

This commit is contained in:
2026-06-14 17:16:32 -04:00
parent a24d2d6443
commit 685f75b208
4 changed files with 150 additions and 0 deletions

View File

@@ -9,6 +9,7 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
add_executable(spotify-downloader add_executable(spotify-downloader
src/main.cpp src/main.cpp
src/url_parser.cpp
) )
add_subdirectory(external/CLI11) add_subdirectory(external/CLI11)

View File

@@ -1,4 +1,5 @@
#include "url_parser.hpp"
#include <CLI/CLI.hpp> #include <CLI/CLI.hpp>
#include <iostream> #include <iostream>
#include <string> #include <string>
@@ -25,6 +26,15 @@ int main(int argc, char **argv) {
if (cmd_download->parsed()) { if (cmd_download->parsed()) {
std::cout << "Target URL: " << url << "\n"; std::cout << "Target URL: " << url << "\n";
auto parsed = UrlParser::parse(url);
if (!parsed) {
std::cerr << "Unsupported URL\n";
return 1;
}
std::cout << "Type: " << parsed->type << '\n';
std::cout << "ID: " << parsed->id << '\n';
} }
return 0; return 0;

111
src/url_parser.cpp Normal file
View File

@@ -0,0 +1,111 @@
#include "url_parser.hpp"
#include <regex>
#include <ostream>
std::ostream &operator<<(std::ostream &os, UrlType type) {
switch (type) {
case UrlType::SpotifyTrack:
return os << "Spotify Track";
case UrlType::SpotifyPlaylist:
return os << "Spotify Playlist";
case UrlType::SpotifyAlbum:
return os << "Spotify Album";
case UrlType::SpotifyArtist:
return os << "Spotify Artist";
case UrlType::YoutubeVideo:
return os << "YouTube Video";
case UrlType::YoutubePlaylist:
return os << "YouTube Playlist";
default:
return os << "Unknown";
}
}
std::optional<ParsedUrl> UrlParser::parse(const std::string &url) {
std::smatch match;
// Spotify
{
static const std::regex spotify(
R"(https?://open\.spotify\.com/(track|playlist|album|artist)/([A-Za-zA-Z0-9]+))");
if (std::regex_search(url, match, spotify)) {
const auto resource = match[1].str();
const auto id = match[2].str();
if (resource == "track")
return ParsedUrl{UrlType::SpotifyTrack, id};
if (resource == "playlist")
return ParsedUrl{UrlType::SpotifyPlaylist, id};
if (resource == "album")
return ParsedUrl{UrlType::SpotifyAlbum, id};
if (resource == "artist")
return ParsedUrl{UrlType::SpotifyArtist, id};
}
}
// Spotify URI
{
static const std::regex spotify_uri(
R"(spotify:(track|playlist|album|artist):([A-Za-z0-9]+))");
if (std::regex_search(url, match, spotify_uri)) {
const auto resource = match[1].str();
const auto id = match[2].str();
if (resource == "track")
return ParsedUrl{UrlType::SpotifyTrack, id};
if (resource == "playlist")
return ParsedUrl{UrlType::SpotifyPlaylist, id};
if (resource == "album")
return ParsedUrl{UrlType::SpotifyAlbum, id};
if (resource == "artist")
return ParsedUrl{UrlType::SpotifyArtist, id};
}
}
// YouTube Playlist
{
static const std::regex yt_playlist(
R"(https?://(?:www\.)?youtube\.com/playlist\?list=([^&]+))");
if (std::regex_search(url, match, yt_playlist))
return ParsedUrl{UrlType::YoutubePlaylist, match[1].str()};
}
// YouTube Video
{
static const std::regex yt_video(
R"(https?://(?:www\.)?youtube\.com/watch\?.*v=([^&]+))");
if (std::regex_search(url, match, yt_video))
return ParsedUrl{UrlType::YoutubeVideo, match[1].str()};
}
// youtu.be
{
static const std::regex yt_short(R"(https?://youtu\.be/([^?&]+))");
if (std::regex_search(url, match, yt_short))
return ParsedUrl{UrlType::YoutubeVideo, match[1].str()};
}
return std::nullopt;
}

28
src/url_parser.hpp Normal file
View File

@@ -0,0 +1,28 @@
#pragma once
#include <optional>
#include <string>
enum class UrlType {
SpotifyTrack,
SpotifyPlaylist,
SpotifyAlbum,
SpotifyArtist,
YoutubeVideo,
YoutubePlaylist,
Unknown
};
struct ParsedUrl {
UrlType type;
std::string id;
};
std::ostream &operator<<(std::ostream &os, UrlType type);
class UrlParser {
public:
static std::optional<ParsedUrl> parse(const std::string &url);
};