|
|
|
@ -16,22 +16,81 @@
@@ -16,22 +16,81 @@
|
|
|
|
|
#include <sys/types.h> |
|
|
|
|
#include <tgbot/tgbot.h> |
|
|
|
|
#include <cpr/cpr.h> |
|
|
|
|
#include <optional> |
|
|
|
|
|
|
|
|
|
using namespace TgBot; |
|
|
|
|
using json = nlohmann::json; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
namespace util { |
|
|
|
|
|
|
|
|
|
std::string trim_whitespace(std::string s) { |
|
|
|
|
int ff = s.find_first_not_of(" \n\t"); |
|
|
|
|
int ll = s.find_last_not_of(" \n\t"); |
|
|
|
|
return s.substr(ff, ll - ff + 1); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::string read_file(std::string const &fpath) { |
|
|
|
|
std::ostringstream sstr; |
|
|
|
|
std::ifstream in (fpath); |
|
|
|
|
sstr << in.rdbuf(); |
|
|
|
|
return sstr.str(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void write_file(std::string const &fpath, std::string const &content) { |
|
|
|
|
std::fstream s; |
|
|
|
|
s.open(fpath, std::ios_base::out); |
|
|
|
|
if (!s.is_open()) { |
|
|
|
|
std::cerr << "Error: failed to open file "<< fpath; |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
s << content; |
|
|
|
|
s.close(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
namespace kare { |
|
|
|
|
|
|
|
|
|
class spotify { |
|
|
|
|
|
|
|
|
|
const std::string API_NAME_BASE = "https://api.spotify.com/v1/"; |
|
|
|
|
const std::string client_id; |
|
|
|
|
const std::string client_secret; |
|
|
|
|
const std::string API_NAME_BASE = "https://api.spotify.com/"; |
|
|
|
|
std::string access_token; |
|
|
|
|
cpr::Header auth_header; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public: |
|
|
|
|
spotify(std::string id, std::string secret) : client_id(id),client_secret(secret) { |
|
|
|
|
|
|
|
|
|
void 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(std::string access_token) : access_token(access_token) { |
|
|
|
|
auth_header = cpr::Header{{"Authorization", "Bearer " + access_token}}; |
|
|
|
|
verify_logged_in(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
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()); |
|
|
|
@ -48,12 +107,33 @@ class spotify {
@@ -48,12 +107,33 @@ class spotify {
|
|
|
|
|
isj >> auth_response; |
|
|
|
|
|
|
|
|
|
if (auth_response.count("access_token")) { |
|
|
|
|
std::cout << "Successfully logged into spotify" << std::endl << "Access token: " << 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> 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 { |
|
|
|
|
return {}; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
}; |
|
|
|
@ -88,25 +168,36 @@ class db {
@@ -88,25 +168,36 @@ class db {
|
|
|
|
|
int main() { |
|
|
|
|
char *teletok = getenv("TELEGRAM_TOKEN"); |
|
|
|
|
|
|
|
|
|
char *spotid = getenv("SPOTIFY_SECRET"); |
|
|
|
|
char *spotsecret = getenv("SPOTIFY_ID"); |
|
|
|
|
// needed if file not exist
|
|
|
|
|
char *spotid = getenv("SPOTIFY_ID"); |
|
|
|
|
char *spotsecret = getenv("SPOTIFY_SECRET"); |
|
|
|
|
char *spotaccess_token = getenv("SPOTIFY_TOKEN"); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!teletok) { |
|
|
|
|
std::cout << "Need to set environment variable TELEGRAM_TOKEN" << std::endl; |
|
|
|
|
exit(1); |
|
|
|
|
} |
|
|
|
|
if (!spotid) { |
|
|
|
|
std::cout << "Need to set environment variable SPOTIFY_ID" << std::endl; |
|
|
|
|
exit(1); |
|
|
|
|
} |
|
|
|
|
if (!spotsecret) { |
|
|
|
|
std::cout << "Need to set environment variable SPOTIFY_SECRET" << std::endl; |
|
|
|
|
exit(1); |
|
|
|
|
|
|
|
|
|
if (!spotaccess_token) { |
|
|
|
|
if (!spotid) { |
|
|
|
|
std::cout << "Need to set environment variable SPOTIFY_ID or SPOTIFY_TOKEN" << std::endl; |
|
|
|
|
exit(1); |
|
|
|
|
} |
|
|
|
|
if (!spotsecret) { |
|
|
|
|
std::cout << "Need to set environment variable SPOTIFY_SECRET of SPOTIFY_TOKEN" << std::endl; |
|
|
|
|
exit(1); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
std::string teletoken {teletok}; |
|
|
|
|
|
|
|
|
|
auto s = kare::spotify(spotid, spotsecret); |
|
|
|
|
kare::spotify *s; |
|
|
|
|
if (spotaccess_token)
|
|
|
|
|
s = new kare::spotify(spotaccess_token); |
|
|
|
|
else
|
|
|
|
|
s = new kare::spotify(spotid, spotsecret); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Bot bot(teletoken); |
|
|
|
|
bot.getEvents().onCommand("start", [&bot](Message::Ptr message) { |
|
|
|
|