aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCara Salter <cara@devcara.com>2023-04-15 15:09:01 -0400
committerCara Salter <cara@devcara.com>2023-04-15 15:09:01 -0400
commita03540d61ed913b78f7c02f8b695fd69eea3e217 (patch)
tree7029841cee6b649b5ca192cd549b316dacfa24a9
parentac4a926685c754f4af5adb20edf6eb23e2a0f18a (diff)
download142bot-spotify.tar.gz
142bot-spotify.zip
Finish spotifyspotify
for now Change-Id: I77c7d319ddf37c7259f4de89567f9a6719f88796
-rw-r--r--.vscode/launch.json4
-rw-r--r--include/142bot/db.hpp6
-rw-r--r--modules/spotify/spotify.cpp86
-rw-r--r--src/db.cpp4
4 files changed, 89 insertions, 11 deletions
diff --git a/.vscode/launch.json b/.vscode/launch.json
index 89efb96..c72eb2c 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -5,13 +5,13 @@
"version": "0.2.0",
"configurations": [
{
- "name": "C++ Launch",
+ "name": "C++ Debug",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/build/142bot",
"args": [],
"environment": [],
"cwd": "${workspaceFolder}"
- }
+ },
]
} \ No newline at end of file
diff --git a/include/142bot/db.hpp b/include/142bot/db.hpp
index 0a82b84..505d6db 100644
--- a/include/142bot/db.hpp
+++ b/include/142bot/db.hpp
@@ -78,7 +78,7 @@ namespace pqxx
static asdf::timestamp from_string( std::string_view &text )
{
asdf::timestamp ts;
- if( !asdf::from_iso8601_str( std::string{ text } + "00", ts ) )
+ if( !asdf::from_iso8601_str( std::string{ text }, ts ) )
throw argument_error{
"Failed conversion to "
+ static_cast< std::string >( name() )
@@ -96,7 +96,7 @@ namespace pqxx
}
static char* into_buf(char* begin, char* end, asdf::timestamp const &value) {
- return pqxx::internal::generic_into_buf(begin, end, value);
+ return pqxx::string_traits<std::string>::into_buf(begin, end, asdf::to_iso8601_str(value));
}
static zview to_buf(char* begin, char* end, asdf::timestamp const &value) {
@@ -104,7 +104,7 @@ namespace pqxx
}
static std::size_t size_buffer(asdf::timestamp const &value) noexcept {
- return pqxx::string_traits<std::string>::size_buffer(asdf::to_iso8601_str(value)) + 1;
+ return pqxx::string_traits<std::string>::size_buffer(asdf::to_iso8601_str(value));
}
};
diff --git a/modules/spotify/spotify.cpp b/modules/spotify/spotify.cpp
index 8df83a4..e00a83b 100644
--- a/modules/spotify/spotify.cpp
+++ b/modules/spotify/spotify.cpp
@@ -32,6 +32,7 @@ class SpotifyModule: public Module {
std::string spotifyRegex;
std::string defaultSpotifyAccount;
std::string spotifyBaseUrl;
+ std::string spotifyDefaultDevice;
public:
SpotifyModule(Bot* creator, ModuleLoader* ml) : Module(creator, ml) {
ml->attach({I_OnMessage, I_OnCommand}, this);
@@ -39,6 +40,7 @@ public:
this->spotifyRegex = "^https:\/\/open.spotify.com\/track\/([a-zA-Z0-9]+)(.*)$";
this->defaultSpotifyAccount = "1";
this->spotifyBaseUrl = "https://api.spotify.com/v1";
+ this->spotifyDefaultDevice = "";
}
virtual std::string version() {
@@ -120,7 +122,7 @@ public:
* Performs a GET request to the Spotify API
*/
json spotify_get(const std::string route) {
- bot->core->log(dpp::ll_debug, fmt::format("Making GET request to {}", route));
+ bot->core->log(dpp::ll_debug, fmt::format("Making GET request to {}/{}", this->spotifyBaseUrl, route));
std::string token = get_spotify_token();
bot->core->log(dpp::ll_trace, "Obtained token.");
@@ -138,6 +140,31 @@ public:
return json::parse(r.text);
}
+ void spotify_post(const std::string route) {
+ return spotify_post(route, 200);
+ }
+
+ /**
+ * Performs a POST request to the Spotify API
+ */
+ void spotify_post(const std::string route, int expected_code) {
+ bot->core->log(dpp::ll_debug, fmt::format("Making spotify POST to {}", route));
+ std::string token = get_spotify_token();
+ bot->core->log(dpp::ll_trace, "Obtained Token.");
+
+ cpr::Response r = cpr::Post(cpr::Url{fmt::format("{}/{}", this->spotifyBaseUrl, route).c_str()},
+ cpr::Bearer{token});
+ bot->core->log(dpp::ll_trace, fmt::format("Made request. Code: {}", r.status_code));
+
+ if (r.status_code != expected_code) {
+ bot->core->log(dpp::ll_error, fmt::format("Spotify API Error: {}", r.text));
+ throw std::exception();
+ }
+
+ return;
+ }
+
+
virtual bool OnMessage(const dpp::message_create_t &message, const std::string& clean_message, bool mentioned, const std::vector<std::string> & mentions) {
sentry_set_tag("module", "spotify");
bot->core->log(dpp::ll_debug, "Got message event");
@@ -150,10 +177,15 @@ public:
try {
json res = spotify_get("tracks/" + match.str(1));
+ std::string post_rt = fmt::format("me/player/queue?uri=spotify:track:{}{}", match.str(1), this->spotifyDefaultDevice != "" ? "&device_id=" + this->spotifyDefaultDevice : "");
+
+ spotify_post(post_rt, 204);
+
dpp::embed embed = dpp::embed()
.set_title(res["name"])
- .set_author(res["artists"][0]["name"], "", "")
- .set_image(res["album"]["images"][0]["url"]);
+ .set_author(res["artists"][0]["name"], res["artists"][0]["external_urls"]["spotify"], "")
+ .set_thumbnail(res["album"]["images"][0]["url"])
+ .set_description("Added to the queue!");
bot->core->message_create(dpp::message(message.msg.channel_id, embed).set_reference(message.msg.id));
return true;
@@ -194,7 +226,7 @@ public:
bot->core->message_create(dpp::message(message.msg.channel_id, embed).set_reference(message.msg.id));
return true;
- } else if (subcommand == "default") {
+ } else if (subcommand == "account") {
pqxx::work tx(bot->conn);
try {
@@ -216,6 +248,52 @@ public:
}
EmbedSuccess("Updated default account.", message.msg.channel_id);
+ }else if (subcommand == "devices") {
+ json res = spotify_get("me/player/devices");
+
+ auto devices = res["devices"];
+ dpp::embed embed = dpp::embed().
+ set_color(dpp::colors::green)
+ .set_title("Spotify Devices")
+ .set_description("List of Spotify devices. Username is field ID and ID is field content.\n\nCurrent default account ID: " + this->defaultSpotifyAccount);
+
+
+ for (int i = 0; i < devices.size(); i++) {
+ std::string name = fmt::format("{} ({})", devices[i]["name"], devices[i]["id"].get<std::string>());
+ std::string content = fmt::format("{} {}", devices[i]["type"].get<std::string>(), devices[i]["id"].get<std::string>() == this->spotifyDefaultDevice ? "(Default)" : "");
+ embed.add_field(name, content, true);
+ }
+ bot->core->message_create(dpp::message(message.msg.channel_id, embed).set_reference(message.msg.id));
+
+ } else if (subcommand == "device") {
+ json res = spotify_get("me/player/devices");
+
+ auto devices = res["devices"];
+
+ for (int i = 0; i < devices.size(); i++) {
+ if (devices[i]["id"] == params[2]) {
+ this->spotifyDefaultDevice = params[2];
+ EmbedSuccess("Changed default spotify device", message.msg.channel_id);
+ return true;
+ }
+ }
+
+ EmbedError("Invalid ID", message.msg.channel_id);
+ } else if (subcommand == "status") {
+ auto res = spotify_get("me/player");
+
+ auto item = res["item"];
+ auto device = res["device"];
+ auto album = item["album"];
+
+ dpp::embed embed = dpp::embed()
+ .set_author(item["artists"][0]["name"], item["artists"][0]["external_urls"]["spotify"], "")
+ .set_title(fmt::format("\"{}\" on {} by {}", item["name"], album["name"], album["artists"][0]["name"]))
+ .set_thumbnail(album["images"][0]["url"])
+ .add_field("Status", res["is_playing"].get<bool>() ? "Playing" : "Paused", true)
+ .add_field("Repeating?", res["repeat_state"], true);
+
+ bot->core->message_create(dpp::message(message.msg.channel_id, embed).set_reference(message.msg.id));
} else {
EmbedError("Unknown Command", message.msg.channel_id);
}
diff --git a/src/db.cpp b/src/db.cpp
index 73a7f02..120c9d4 100644
--- a/src/db.cpp
+++ b/src/db.cpp
@@ -106,13 +106,13 @@ namespace asdf
bool from_iso8601_str( const std::string& s, timestamp& ts )
{
std::istringstream stream{ s };
- stream >> date::parse( "%F %T%z", ts );
+ stream >> date::parse( "%F %T", ts );
return !stream.fail();
}
std::string to_iso8601_str( const timestamp& ts )
{
- return date::format( "%F %T%z", ts );
+ return date::format( "%F %T", ts );
}
std::string to_http_ts_str( const timestamp& ts )