Formatting changes

This commit is contained in:
kdeng00
2020-11-28 18:38:29 -05:00
parent 5f22129462
commit 9ecb23ade3
6 changed files with 281 additions and 281 deletions
+4 -4
View File
@@ -14,16 +14,16 @@ find_path (CPPCODEC_INCLUDE_DIRS "cppcodec/base32_crockford.hpp")
set (SOURCES set (SOURCES
"${CMAKE_CURRENT_SOURCE_DIR}/src/SpotifyDemo.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/src/SpotifyDemo.cpp"
) )
set (SD_INCLUDE_DIR set (SD_INCLUDE_DIR
"${CMAKE_CURRENT_SOURCE_DIR}/include" "${CMAKE_CURRENT_SOURCE_DIR}/include"
) )
set (HEADERS set (HEADERS
"${SD_INCLUDE_DIR}/Models.h" "${SD_INCLUDE_DIR}/Models.h"
) )
include_directories ("${SD_INCLUDE_DIR}") include_directories ("${SD_INCLUDE_DIR}")
+1 -1
View File
@@ -1,4 +1,4 @@
{ {
"client_id": "id", "client_id": "id",
"client_secret": "secret" "client_secret": "secret"
} }
+58 -58
View File
@@ -6,71 +6,71 @@
namespace Models namespace Models
{ {
template<typename Str = std::string, template<typename Str = std::string,
typename Num = int, typename Num = int,
typename Dur = long> typename Dur = long>
class Song class Song
{ {
public: public:
Song() = default; Song() = default;
Str title; Str title;
Str artist; Str artist;
Str album; Str album;
Str released; Str released;
Dur duration; Dur duration;
}; };
template<typename Str = std::string, template<typename Str = std::string,
typename Num = int> typename Num = int>
class Album class Album
{ {
public: public:
Album() = default; Album() = default;
Str title; Str title;
Str released; Str released;
std::vector<Song<>> songs; std::vector<Song<>> songs;
}; };
template<typename Str = std::string> template<typename Str = std::string>
class ClientInformation class ClientInformation
{ {
public: public:
ClientInformation() = default; ClientInformation() = default;
ClientInformation(Str& id, Str& secret) : ClientInformation(Str& id, Str& secret) :
client_id(std::move(id)), client_secret(std::move(secret)) client_id(std::move(id)), client_secret(std::move(secret))
{ {
} }
ClientInformation(Str&& id, Str&& secret) : ClientInformation(Str&& id, Str&& secret) :
client_id(id), client_secret(secret) client_id(id), client_secret(secret)
{ {
} }
auto is_empty() auto is_empty()
{ {
return (client_id.empty() && client_secret.empty()) ? true : false; return (client_id.empty() && client_secret.empty()) ? true : false;
} }
Str client_id; Str client_id;
Str client_secret; Str client_secret;
}; };
template<typename Str = std::string, template<typename Str = std::string,
typename Num = int> typename Num = int>
class TokenResp class TokenResp
{ {
public: public:
auto is_empty() auto is_empty()
{ {
return this->access_token.empty(); return this->access_token.empty();
} }
Str access_token; Str access_token;
Str token_type; Str token_type;
Num expires_in; Num expires_in;
Str scope; Str scope;
}; };
} }
#endif #endif
+122 -122
View File
@@ -13,163 +13,163 @@
namespace Spotify namespace Spotify
{ {
template<typename Tok = Models::TokenResp<std::string>> template<typename Tok = Models::TokenResp<std::string>>
class SpotifyCall class SpotifyCall
{ {
public: public:
SpotifyCall() = default; SpotifyCall() = default;
SpotifyCall(Tok& tok) : token(tok) SpotifyCall(Tok& tok) : token(tok)
{ {
} }
SpotifyCall(Tok&& tok) : token(std::move(tok)) SpotifyCall(Tok&& tok) : token(std::move(tok))
{ {
} }
template<typename Str = std::string> template<typename Str = std::string>
auto search_songs(Str&& title) auto search_songs(Str&& title)
{ {
constexpr auto limit = 49; constexpr auto limit = 49;
std::vector<Models::Album<>> albums; std::vector<Models::Album<>> albums;
albums.reserve(limit); albums.reserve(limit);
std::string search_query("name:"); std::string search_query("name:");
search_query.append(delimit_search_query(title)); search_query.append(delimit_search_query(title));
const auto uri = search_uri(); const auto uri = search_uri();
const auto authorization = bearer_authorization(); const auto authorization = bearer_authorization();
Str limit_str(std::to_string(limit)); Str limit_str(std::to_string(limit));
auto resp = cpr::Get(cpr::Url{ uri }, auto resp = cpr::Get(cpr::Url{ uri },
cpr::Parameters{ {"type", "track"}, cpr::Parameters{ {"type", "track"},
{"limit", limit_str}, {"limit", limit_str},
{"q", search_query} }, {"q", search_query} },
cpr::Header{ {"Authorization", authorization.c_str()} }); cpr::Header{ {"Authorization", authorization.c_str()} });
if (resp.status_code == 200) { if (resp.status_code == 200) {
parse_albums(albums, std::move(resp.text)); parse_albums(albums, std::move(resp.text));
} }
return albums; return albums;
} }
template<typename Cont = std::vector<Models::Album<std::string>>> template<typename Cont = std::vector<Models::Album<std::string>>>
void print_songs_to_console(Cont &albums) void print_songs_to_console(Cont &albums)
{ {
std::cout << "Printing songs to the console\n"; std::cout << "Printing songs to the console\n";
std::for_each(albums.begin(), albums.end(), [](auto album) { std::for_each(albums.begin(), albums.end(), [](auto album) {
auto song = album.songs.at(0); auto song = album.songs.at(0);
std::cout << "Title: " << song.title << "\n"; std::cout << "Title: " << song.title << "\n";
std::cout << "Artist: " << song.artist << "\n"; std::cout << "Artist: " << song.artist << "\n";
std::cout << "Album: " << album.title << "\n"; std::cout << "Album: " << album.title << "\n";
std::cout << "Released Date: " << song.released << "\n"; std::cout << "Released Date: " << song.released << "\n";
std::cout << "Duration (ms): " << song.duration << "\n"; std::cout << "Duration (ms): " << song.duration << "\n";
std::cout << "\n"; std::cout << "\n";
}); });
std::cout << "\n"; std::cout << "\n";
} }
private: private:
template<typename Str = std::string> template<typename Str = std::string>
auto delimit_search_query(Str &&title) auto delimit_search_query(Str &&title)
{ {
return std::regex_replace(title, std::regex(" "), "%20"); return std::regex_replace(title, std::regex(" "), "%20");
} }
auto bearer_authorization() auto bearer_authorization()
{ {
std::string authorization("Bearer "); std::string authorization("Bearer ");
authorization.append(this->token.access_token); authorization.append(this->token.access_token);
return authorization; return authorization;
} }
template<typename Alb = Models::Album<>, typename Vec = std::vector<Alb>, template<typename Alb = Models::Album<>, typename Vec = std::vector<Alb>,
typename Str = std::string> typename Str = std::string>
void parse_albums(Vec &alb, Str &&resp) void parse_albums(Vec &alb, Str &&resp)
{ {
auto obj = nlohmann::json::parse(resp); auto obj = nlohmann::json::parse(resp);
for (auto& item : obj["tracks"]["items"]) { for (auto& item : obj["tracks"]["items"]) {
auto album_json = item["album"]; auto album_json = item["album"];
auto artists_json = item["artists"]; auto artists_json = item["artists"];
Alb album; Alb album;
album.title = album_json["name"].get<std::string>(); album.title = album_json["name"].get<std::string>();
album.released = album_json["release_date"].get<std::string>(); album.released = album_json["release_date"].get<std::string>();
Models::Song<> song; Models::Song<> song;
song.title = item["name"].get<std::string>(); song.title = item["name"].get<std::string>();
song.duration = item["duration_ms"].get<long>(); song.duration = item["duration_ms"].get<long>();
song.artist = artists_json[0]["name"].get<std::string>(); song.artist = artists_json[0]["name"].get<std::string>();
song.released = album.released; song.released = album.released;
song.album = album.title; song.album = album.title;
std::vector<Models::Song<>> songs; std::vector<Models::Song<>> songs;
songs.push_back(song); songs.push_back(song);
album.songs = songs; album.songs = songs;
alb.push_back(album); alb.push_back(album);
} }
} }
auto saved_albums_response_body() auto saved_albums_response_body()
{ {
nlohmann::json obj; nlohmann::json obj;
std::string uri(base_uri()); std::string uri(base_uri());
uri.append("/"); uri.append("/");
uri.append(album_saved()); uri.append(album_saved());
std::string auth_header("Bearer "); std::string auth_header("Bearer ");
auth_header.append(this->token.access_token); auth_header.append(this->token.access_token);
auto resp = cpr::Get(cpr::Url(uri), auto resp = cpr::Get(cpr::Url(uri),
cpr::Header{{"Authorization", auth_header.c_str()}} cpr::Header{{"Authorization", auth_header.c_str()}}
); );
if (resp.status_code == 200) { if (resp.status_code == 200) {
obj = nlohmann::json::parse(resp.text); obj = nlohmann::json::parse(resp.text);
} }
return obj; return obj;
} }
template<typename Str = std::string> template<typename Str = std::string>
auto search_uri() auto search_uri()
{ {
Str uri(base_uri()); Str uri(base_uri());
uri.append("/"); uri.append("/");
uri.append(search_item_endpoint()); uri.append(search_item_endpoint());
return uri; return uri;
} }
constexpr auto base_uri() noexcept constexpr auto base_uri() noexcept
{ {
return "https://api.spotify.com/v1"; return "https://api.spotify.com/v1";
} }
constexpr auto album_saved() noexcept constexpr auto album_saved() noexcept
{ {
return "me/albums"; return "me/albums";
} }
constexpr auto search_item_endpoint() noexcept constexpr auto search_item_endpoint() noexcept
{ {
return "search"; return "search";
} }
Tok token; Tok token;
}; };
} }
#endif #endif
+72 -72
View File
@@ -14,100 +14,100 @@
namespace Manager namespace Manager
{ {
template<typename Str = std::string> template<typename Str = std::string>
class TokenRetrieval class TokenRetrieval
{ {
public: public:
TokenRetrieval() = default; TokenRetrieval() = default;
TokenRetrieval(Models::ClientInformation<Str> &info) : TokenRetrieval(Models::ClientInformation<Str> &info) :
client_information(std::move(info)) client_information(std::move(info))
{ {
} }
TokenRetrieval(Models::ClientInformation<Str> &&info) : TokenRetrieval(Models::ClientInformation<Str> &&info) :
client_information(info) client_information(info)
{ {
} }
template<typename TokResp> template<typename TokResp>
auto retrieve_token() auto retrieve_token()
{ {
if (this->client_information.is_empty()) { if (this->client_information.is_empty()) {
return TokResp(); return TokResp();
} }
auto token = make_call<TokResp>(); auto token = make_call<TokResp>();
return (token.is_empty()) ? TokResp() : token; return (token.is_empty()) ? TokResp() : token;
} }
private: private:
template<typename TokResp> template<typename TokResp>
auto make_call() auto make_call()
{ {
TokResp resp; TokResp resp;
Str authorization("Basic "); Str authorization("Basic ");
authorization.append(encoded_authorization()); authorization.append(encoded_authorization());
const auto uri = construct_uri(spotify_uri(), spotify_token_endpoint()); const auto uri = construct_uri(spotify_uri(), spotify_token_endpoint());
auto r = cpr::Post(cpr::Url{ uri }, auto r = cpr::Post(cpr::Url{ uri },
cpr::Parameters{ {"grant_type", "client_credentials" }}, cpr::Parameters{ {"grant_type", "client_credentials" }},
cpr::Header{ {"Authorization", authorization.c_str()} } cpr::Header{ {"Authorization", authorization.c_str()} }
); );
if (r.status_code == 200) { if (r.status_code == 200) {
auto token = nlohmann::json::parse(r.text); auto token = nlohmann::json::parse(r.text);
resp.access_token = token["access_token"].get<Str>(); resp.access_token = token["access_token"].get<Str>();
resp.token_type = token["token_type"].get<Str>(); resp.token_type = token["token_type"].get<Str>();
resp.expires_in = token["expires_in"].get<int>(); resp.expires_in = token["expires_in"].get<int>();
resp.scope = token["scope"].get<Str>(); resp.scope = token["scope"].get<Str>();
} }
return resp; return resp;
} }
auto encoded_authorization() auto encoded_authorization()
{ {
Str unencoded(client_information.client_id); Str unencoded(client_information.client_id);
unencoded.append(":"); unencoded.append(":");
unencoded.append(client_information.client_secret); unencoded.append(client_information.client_secret);
std::vector<char> v(unencoded.begin(), unencoded.end()); std::vector<char> v(unencoded.begin(), unencoded.end());
return cppcodec::base64_rfc4648::encode(v); return cppcodec::base64_rfc4648::encode(v);
} }
template<typename Ch = char> template<typename Ch = char>
auto construct_uri(Ch *base, Ch *endpoint) auto construct_uri(Ch *base, Ch *endpoint)
{ {
Str uri(base); Str uri(base);
if (uri.at(uri.size() - 1) != '/') { if (uri.at(uri.size() - 1) != '/') {
uri.append("/"); uri.append("/");
} }
uri.append(endpoint); uri.append(endpoint);
return uri; return uri;
} }
auto constexpr spotify_uri() noexcept auto constexpr spotify_uri() noexcept
{ {
return "https://accounts.spotify.com"; return "https://accounts.spotify.com";
} }
auto constexpr spotify_token_endpoint() noexcept auto constexpr spotify_token_endpoint() noexcept
{ {
return "api/token"; return "api/token";
} }
Models::ClientInformation<Str> client_information; Models::ClientInformation<Str> client_information;
}; };
} }
#endif #endif
+24 -24
View File
@@ -19,47 +19,47 @@ using namespace Models;
template<typename Conf, typename Str> template<typename Conf, typename Str>
auto retrieve_client_information(Str &&path) auto retrieve_client_information(Str &&path)
{ {
std::fstream config_file(path, std::ios::in); std::fstream config_file(path, std::ios::in);
std::stringstream buffer; std::stringstream buffer;
buffer << config_file.rdbuf(); buffer << config_file.rdbuf();
config_file.close(); config_file.close();
auto client_json = nlohmann::json::parse(buffer.str()); auto client_json = nlohmann::json::parse(buffer.str());
std::string id(client_json["client_id"].get<std::string>()); std::string id(client_json["client_id"].get<std::string>());
std::string secret(client_json["client_secret"].get<std::string>()); std::string secret(client_json["client_secret"].get<std::string>());
Conf client_information(std::move(id), std::move(secret)); Conf client_information(std::move(id), std::move(secret));
return client_information; return client_information;
} }
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
std::cout << "Starting SpotfyDemo\n"; std::cout << "Starting SpotfyDemo\n";
if (argc < 2) { if (argc < 2) {
std::cout << "Provide path to the client information json file\n"; std::cout << "Provide path to the client information json file\n";
return -1; return -1;
} }
std::string path(std::move(argv[1])); std::string path(std::move(argv[1]));
auto client_info = retrieve_client_information<ClientInformation<std::string>, auto client_info = retrieve_client_information<ClientInformation<std::string>,
std::string>(std::move(path)); std::string>(std::move(path));
Manager::TokenRetrieval<> tok_mgr(std::move(client_info)); Manager::TokenRetrieval<> tok_mgr(std::move(client_info));
auto resp = tok_mgr.retrieve_token<Models::TokenResp<std::string>>(); auto resp = tok_mgr.retrieve_token<Models::TokenResp<std::string>>();
Spotify::SpotifyCall<> spotify(std::move(resp)); Spotify::SpotifyCall<> spotify(std::move(resp));
std::string song_title("Heave"); std::string song_title("Heave");
auto albums = spotify.search_songs(song_title); auto albums = spotify.search_songs(song_title);
spotify.print_songs_to_console(albums); spotify.print_songs_to_console(albums);
return 0; return 0;
} }