You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
114 lines
3.5 KiB
114 lines
3.5 KiB
#include "spotify.h" |
|
#include "cpr/cprtypes.h" |
|
#include "cpr/parameters.h" |
|
#include <nlohmann/json.hpp> |
|
#include <cpr/cpr.h> |
|
#include <istream> |
|
#include <sstream> |
|
#include <string> |
|
#include <spdlog/spdlog.h> |
|
#include <iostream> |
|
#include <cstdio> |
|
#include "Base64.hpp" |
|
#include <optional> |
|
|
|
using json = nlohmann::json; |
|
|
|
void spotify::verify_logged_in() { |
|
/* |
|
* |
|
* Would be a good idea to just requrst a page to chek. but the /me |
|
* endpoint is for logged in users i guess? and this iis jut an app. |
|
* |
|
cpr::Response r = cpr::Get(cpr::Url{API_NAME_BASE + "v1/me"},cpr::Header{{"Authorization", "Bearer " + access_token}}); |
|
std::istringstream isj {r.text}; |
|
json auth_response; |
|
try { |
|
isj >> auth_response; |
|
} catch (json::exception & e) { |
|
std::cout << e.id << r.text; |
|
} |
|
|
|
if (auth_response.count("display_name")) { |
|
std::cout << "Logged in as " << auth_response["display_name"] << std::endl << auth_response["href"] << std::endl; |
|
} else { |
|
std::cout << "Failed to log in" << std::endl << auth_response.dump(4) << std::endl; |
|
} |
|
*/ |
|
} |
|
|
|
spotify::spotify(std::string access_token) : access_token(access_token) { |
|
auth_header = cpr::Header{{"Authorization", "Bearer " + access_token}}; |
|
verify_logged_in(); |
|
} |
|
|
|
spotify::spotify(std::string client_id, std::string client_secret) { |
|
auto ascii_token = client_id + ":" + client_secret; |
|
|
|
size_t buf_length = base64::get_encoded_length(ascii_token.length()); |
|
auto buf = std::make_unique<uint8_t[]>(buf_length); |
|
std::string auth_token; |
|
|
|
base64::encode((uint8_t *)(ascii_token.c_str()), ascii_token.length(), buf.get(), buf_length); |
|
auth_token = std::string {(char *)buf.get(), buf_length}; |
|
|
|
cpr::Response r = cpr::Post(cpr::Url{"https://accounts.spotify.com/api/token"},cpr::Header{{"Authorization", "Basic " + auth_token}}, cpr::Parameters{{"grant_type", "client_credentials"}}); |
|
|
|
std::istringstream isj {r.text}; |
|
|
|
json auth_response; |
|
if (r.status_code == 200) { |
|
isj >> auth_response; |
|
} else { |
|
spdlog::error("Login error {} {}",r.status_code, r.status_line); |
|
} |
|
|
|
|
|
if (auth_response.count("access_token")) { |
|
access_token = auth_response["access_token"]; |
|
std::cout << "Successfully logged into spotify" << std::endl << "Access token: " << access_token << std::endl; |
|
} else { |
|
std::cout << "Unable to log into spotify:" << std::endl << auth_response.dump(4) << std::endl; |
|
exit (1); |
|
} |
|
|
|
auth_header = cpr::Header{{"Authorization", "Bearer " + access_token}}; |
|
verify_logged_in(); |
|
} |
|
|
|
std::optional<json> spotify::get_track(std::string track_id) { |
|
|
|
auto r = cpr::Get(cpr::Url{API_NAME_BASE + "v1/tracks/" + track_id}, auth_header); |
|
if (r.status_code == 200) { |
|
std::istringstream isj {r.text}; |
|
json info ; |
|
try { |
|
isj >> info; |
|
} catch (json::exception & e) { |
|
std::cout << "Json error" << std::endl; |
|
} |
|
return info; |
|
} else { |
|
std::cout << r.text << std::endl; |
|
return {}; |
|
} |
|
} |
|
|
|
/* |
|
* Parse track link from a spotify url like: |
|
* |
|
* https://open.spotify.com/track/4UO1pfxi5fDbxshrwwznJ2?si=BtN9Yn_JQXSHGUa4CEZKvQ&utm_source=copy-link |
|
* |
|
* |
|
*/ |
|
std::optional<std::string> spotify::track_id_from_link(std::string link) { |
|
const std::string start = "spotify.com/track/"; |
|
auto f = link.find(start); |
|
if (f == std::string::npos) { |
|
return {}; |
|
} |
|
|
|
auto end = link.find("?", f); |
|
auto begin = f + start.length(); |
|
return link.substr(begin, end - begin); |
|
}
|
|
|