Browse Source

insert songs

master
alistair 3 years ago
parent
commit
470e8b6df3
  1. 4
      CMakeLists.txt
  2. 160
      telegram_bot.cpp

4
CMakeLists.txt

@ -29,12 +29,15 @@ project(echobot-submodule) @@ -29,12 +29,15 @@ project(echobot-submodule)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall")
set(Boost_USE_MULTITHREADED ON)
find_package(spdlog REQUIRED)
find_package(SQLite3 REQUIRED)
find_package(Threads REQUIRED)
find_package(OpenSSL REQUIRED)
find_package(Boost COMPONENTS system REQUIRED)
include_directories(/usr/local/include ${OPENSSL_INCLUDE_DIR} ${Boost_INCLUDE_DIR})
include_directories(spdlog/include/)
add_subdirectory(tgbot-cpp)
add_executable(telegram_bog telegram_bot.cpp)
@ -44,4 +47,5 @@ target_link_libraries(telegram_bog PRIVATE TgBot ${CMAKE_THREAD_LIBS_INIT} @@ -44,4 +47,5 @@ target_link_libraries(telegram_bog PRIVATE TgBot ${CMAKE_THREAD_LIBS_INIT}
nlohmann_json::nlohmann_json)
target_link_libraries(telegram_bog PRIVATE cpr::cpr)
target_link_libraries(telegram_bog sqlite3)
target_link_libraries(telegram_bog PRIVATE spdlog::spdlog)

160
telegram_bot.cpp

@ -21,6 +21,7 @@ @@ -21,6 +21,7 @@
#include <sqlite3.h>
#include <cstdlib>
#include <map>
#include <spdlog/spdlog.h>
using namespace TgBot;
using json = nlohmann::json;
@ -146,6 +147,7 @@ class spotify { @@ -146,6 +147,7 @@ class spotify {
}
return info;
} else {
std::cout << r.text << std::endl;
return {};
}
@ -179,15 +181,6 @@ class songdb { @@ -179,15 +181,6 @@ class songdb {
/* need one table for every chat: keep it all in memory? */
/*
*
* song lists: [list id (autoincrement int), (int64) telegram group id, (string) list name ]
* - these are tied to telegram groups
*
* songs : [Song spotify ID (string), list id (foreign key)], votes tally (int), number of votes (int)
* - these are tied to song lists
*
*/
std::string filepath;
sqlite3 *db;
@ -213,6 +206,15 @@ class songdb { @@ -213,6 +206,15 @@ class songdb {
char *errmsg;
int err;
/*
* songlists: [list id (autoincrement int), (int64) telegram group id, (string) list name ]
*
* songs : [songid int autoincrement, song name NOT NULL, song artist NULL, Song spotify ID (string) ]
*
* votes: [song id foreign key, list id foreign key, telegram user id, int rating ]
*
*/
std::string create_songlist_table =
"CREATE TABLE IF NOT EXISTS songlists ("
"id INTEGER PRIMARY KEY AUTOINCREMENT, "
@ -220,17 +222,23 @@ class songdb { @@ -220,17 +222,23 @@ class songdb {
"name VARCHAR(200) NOT NULL "
");";
std::string create_votes_table =
"CREATE TABLE IF NOT EXISTS votes ("
"song INT NOT NULL, "
"list INT NOT NULL, "
"user INT NOT NULL, "
"rating NOT NULL, "
" FOREIGN KEY (song) REFERENCES tracks (id),"
" FOREIGN KEY (list) REFERENCES songlists (id));";
std::string create_tracks_table =
"CREATE TABLE IF NOT EXISTS tracks ("
"spotifyid VARCHAR(200) PRIMARY KEY, "
"list INT NOT NULL, "
"vote_total INT NOT NULL,"
"vote_count INT NOT NULL,"
"FOREIGN KEY (list)"
" REFERENCES songlists (id)"
"id INTEGER PRIMARY KEY AUTOINCREMENT, "
"name VARCHAR(200) NOT NULL, "
"artist VARCHAR(200), "
"spotifyid VARCHAR(200) "
");";
err = sqlite3_exec(db, create_songlist_table.c_str(), NULL, 0, &errmsg);
if (err != SQLITE_OK) {
@ -238,7 +246,6 @@ class songdb { @@ -238,7 +246,6 @@ class songdb {
exit (1);
}
err = sqlite3_exec(db, create_tracks_table.c_str(), NULL, 0, &errmsg);
if (err != SQLITE_OK) {
@ -246,16 +253,23 @@ class songdb { @@ -246,16 +253,23 @@ class songdb {
exit (1);
}
err = sqlite3_exec(db, create_votes_table.c_str(), NULL, 0, &errmsg);
if (err != SQLITE_OK) {
std::cout << "SQLite Error: " << create_votes_table << "\n" << errmsg << std::endl;
exit (1);
}
if (errmsg)
free(errmsg);
sqlite3_free(errmsg);
return false;
}
int check_error(int rc) {
if (rc != SQLITE_OK) {
std::cout << "SQL Error: " << sqlite3_errmsg(db) << std::endl;
spdlog::error("SQLite: {}", sqlite3_errmsg(db));
spdlog::dump_backtrace();
exit(1);
}
return 0;
@ -266,18 +280,28 @@ class songdb { @@ -266,18 +280,28 @@ class songdb {
public:
void create_new_list(int64_t group_id) {
spdlog::debug("create_new_list {}", group_id);
sqlite3_stmt *statement;
std::string insert_query = "INSERT INTO songlists (groupid, name) VALUES (? , default);";
sqlite3_prepare_v2(db, insert_query.c_str(), insert_query.length(), &statement, NULL);
sqlite3_bind_int64(statement, 0, group_id);
int err = sqlite3_step(statement);
int err;
std::string insert_query = "INSERT INTO songlists (groupid, name) VALUES (? , \"default\");";
err = sqlite3_prepare_v2(db, insert_query.c_str(), insert_query.length(), &statement, NULL);
check_error(err);
err = sqlite3_bind_int64(statement, 1, group_id);
check_error(err);
err = sqlite3_step(statement);
if (err != SQLITE_DONE) {
check_error(err);
}
sqlite3_reset(statement);
}
int get_song_list_id(int64_t group_id) {
spdlog::debug("get_song_list_id {}", group_id);
std::string list_query = "SELECT * FROM songlists WHERE groupid = ?;";
/* A constraint of this implementation is that every group can only have
* one list
@ -286,18 +310,20 @@ class songdb { @@ -286,18 +310,20 @@ class songdb {
sqlite3_stmt *statement;
sqlite3_prepare_v2(db, list_query.c_str(), list_query.length(), &statement, NULL);
err = sqlite3_bind_int64(statement, 0, group_id);
err = sqlite3_bind_int64(statement, 1, group_id);
check_error(err);
err = sqlite3_step(statement);
int list_id;
if (err == SQLITE_ROW) {
list_id = sqlite3_column_int64(statement, 0);
if (err == SQLITE_ROW && sqlite3_column_count(statement)) {
list_id = sqlite3_column_int(statement, 0);
err = sqlite3_step(statement);
if (err != SQLITE_DONE) {
// should only ever be 1 entry
std::cout << "bad\n";
spdlog::error("Should only be one list per group?");
spdlog::dump_backtrace();
exit(1);
}
@ -325,25 +351,74 @@ class songdb { @@ -325,25 +351,74 @@ class songdb {
}
bool insert_song(std::string spotify_id, int64_t group_id) {
bool insert_song(std::string name, std::string artist, std::optional<std::string> spotify_id) {
spdlog::debug("insert_song");
std::string check_exist_spot = "SELECT * FROM tracks WHERE spotifyid = ?;";
std::string check_exist_nospot = "SELECT * FROM tracks WHERE name = ? AND artist = ?;";
std::string ins_query = "INSERT INTO tracks (spotifyid, list, vote_total, vote_count) VALUES(?, ?, 0, 0);";
std::string ins_query_spot = "INSERT INTO tracks (name, artist, spotifyid) VALUES(?, ?, ?);";
std::string ins_query_nospot = "INSERT INTO tracks (name, artist) VALUES(?, ?);";
int list_id = get_song_list_id(group_id);
// int list_id = get_song_list_id(group_id);
sqlite3_stmt *statement;
sqlite3_prepare_v2(db, ins_query.c_str(), ins_query.length(), &statement, NULL);
sqlite3_bind_text(statement, 0, spotify_id.c_str(), spotify_id.length(), NULL);
sqlite3_bind_int(statement, 1, list_id);
int err = sqlite3_step(statement);
int err;
/* check whether the song exists */
if (spotify_id) {
err = sqlite3_prepare_v2(db, check_exist_spot.c_str(), check_exist_spot.length(), &statement, NULL);
check_error(err);
err = sqlite3_bind_text(statement, 1, spotify_id->c_str(), spotify_id->length(), NULL);
check_error(err);
} else {
err = sqlite3_prepare_v2(db, check_exist_nospot.c_str(), check_exist_nospot.length(), &statement, NULL);
check_error(err);
err = sqlite3_bind_text(statement, 1, name.c_str(), name.length(), NULL);
check_error(err);
err = sqlite3_bind_text(statement, 2, artist.c_str(), artist.length(), NULL);
check_error(err);
}
err = sqlite3_step(statement);
if (err == SQLITE_ROW) {
spdlog::info("Entry exists.");
return true;
} else if (err != SQLITE_DONE) {
check_error(err);
return true;
}
if (spotify_id) {
err = sqlite3_prepare_v2(db, ins_query_spot.c_str(), ins_query_spot.length(), &statement, NULL);
} else {
err = sqlite3_prepare_v2(db, ins_query_nospot.c_str(), ins_query_nospot.length(), &statement, NULL);
}
check_error(err);
err = sqlite3_bind_text(statement, 1, name.c_str(), name.length(), NULL);
check_error(err);
err = sqlite3_bind_text(statement, 2, artist.c_str(), artist.length(), NULL);
check_error(err);
if (spotify_id) {
err = sqlite3_bind_text(statement, 3, spotify_id->c_str(), spotify_id->length(), NULL);
check_error(err);
}
err = sqlite3_step(statement);
if (err != SQLITE_DONE) {
sqlite3_reset(statement);
spdlog::warn("Failed insertion Sqlite: {}", sqlite3_errstr(err));
spdlog::dump_backtrace();
return true;
}
return false;
}
@ -372,6 +447,10 @@ class songdb { @@ -372,6 +447,10 @@ class songdb {
};
int main() {
spdlog::set_level(spdlog::level::info); // Set global log level to debug
spdlog::enable_backtrace(32);
char *teletok = getenv("TELEGRAM_TOKEN");
// needed if file not exist
@ -474,11 +553,10 @@ int main() { @@ -474,11 +553,10 @@ int main() {
std::string response = "Added song: " + title + ", by " + artist;
response += "\n\r\n\r";
response += "Everyone, please rate this suggestion /5";
response += "Everyone, please rate how well you know this song /5";
data.insert_song(*resp, message->chat->id);
data.insert_song(title, artist, {});
bot.getApi().sendMessage(message->chat->id, response, false, 0, keyboard, "Markdown");
});

Loading…
Cancel
Save