Browse Source

update bot

master
alistair 3 years ago
parent
commit
7028fd7991
  1. 6
      CMakeLists.txt
  2. 7
      compile_commands.json
  3. BIN
      telegram_bot
  4. 221
      telegram_bot.cpp

6
CMakeLists.txt

@ -3,6 +3,12 @@ set(CMAKE_CXX_STANDARD 17) @@ -3,6 +3,12 @@ set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_BUILD_TYPE "Debug")
set (CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -g -fno-omit-frame-pointer -fsanitize=address")
set (CMAKE_LINKER_FLAGS_DEBUG "${CMAKE_LINKER_FLAGS_DEBUG} -fno-omit-frame-pointer -fsanitize=address")
include(FetchContent)
FetchContent_Declare(json
GIT_REPOSITORY https://github.com/nlohmann/json.git

7
compile_commands.json

@ -4,6 +4,12 @@ @@ -4,6 +4,12 @@
"/usr/bin/c++",
"-c",
"-DCURL_STATICLIB",
"-DFMT_LOCALE",
"-DFMT_SHARED",
"-DSPDLOG_COMPILED_LIB",
"-DSPDLOG_FMT_EXTERNAL",
"-DSPDLOG_SHARED_LIB",
"-I/home/alistair/Documents/programming/bog/bog/spdlog/include",
"-I/home/alistair/Documents/programming/bog/bog/tgbot-cpp/include",
"-I/home/alistair/Documents/programming/bog/bog/build/_deps/json-src/single_include",
"-I/home/alistair/Documents/programming/bog/bog/build/_deps/cpr-src/include",
@ -11,6 +17,7 @@ @@ -11,6 +17,7 @@
"-I/home/alistair/Documents/programming/bog/bog/build/_deps/curl-build/include/curl",
"-std=c++11",
"-Wall",
"-std=c++17",
"-o",
"CMakeFiles/telegram_bog.dir/telegram_bot.cpp.o",
"../telegram_bot.cpp"

BIN
telegram_bot

Binary file not shown.

221
telegram_bot.cpp

@ -9,6 +9,7 @@ @@ -9,6 +9,7 @@
#include <cstdlib>
#include <exception>
#include <istream>
#include <sstream>
#include <string>
#include <nlohmann/json.hpp>
#include <memory>
@ -198,6 +199,7 @@ class songdb { @@ -198,6 +199,7 @@ class songdb {
for (int i = 0; i < argc; i++) {
values->insert({azColName[i], argv[i]});
}
return 0;
}
bool
@ -229,7 +231,9 @@ class songdb { @@ -229,7 +231,9 @@ class songdb {
"user INT NOT NULL, "
"rating NOT NULL, "
" FOREIGN KEY (song) REFERENCES tracks (id),"
" FOREIGN KEY (list) REFERENCES songlists (id));";
" FOREIGN KEY (list) REFERENCES songlists (id),"
" PRIMARY KEY (song, list, user)"
");";
std::string create_tracks_table =
"CREATE TABLE IF NOT EXISTS tracks ("
@ -295,11 +299,15 @@ class songdb { @@ -295,11 +299,15 @@ class songdb {
check_error(err);
}
sqlite3_reset(statement);
sqlite3_finalize(statement);
}
int get_song_list_id(int64_t group_id) {
/* Retrieve or create the song list id for a group.
*
* As is, song lists are unique to telegram groups
*/
int64_t 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 = ?;";
@ -308,6 +316,7 @@ class songdb { @@ -308,6 +316,7 @@ class songdb {
*/
int err;
sqlite3_stmt *statement;
sqlite3_prepare_v2(db, list_query.c_str(), list_query.length(), &statement, NULL);
err = sqlite3_bind_int64(statement, 1, group_id);
@ -330,40 +339,85 @@ class songdb { @@ -330,40 +339,85 @@ class songdb {
} else if (err == SQLITE_DONE) {
// create the list
sqlite3_reset(statement);
sqlite3_finalize(statement);
create_new_list(group_id);
sqlite3_prepare_v2(db, list_query.c_str(), list_query.length(), &statement, NULL);
err = sqlite3_bind_int64(statement, 0, group_id);
err = sqlite3_prepare_v2(db, list_query.c_str(), list_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_ROW){
list_id = sqlite3_column_int64(statement, 0);
}
else {
else if (err != SQLITE_DONE) {
check_error(err);
}
} else {
check_error(err);
}
return list_id;
}
bool insert_song(std::string name, std::string artist, std::optional<std::string> spotify_id) {
struct track_entry {
int64_t id;
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_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);
std::optional<track_entry> get_song(int64_t id) {
std::string check_exist = "SELECT * FROM tracks WHERE id = ?;";
int err;
sqlite3_stmt *statement;
err = sqlite3_prepare_v2(db, check_exist.c_str(), check_exist.length(), &statement, NULL);
check_error(err);
err = sqlite3_bind_int64(statement, 1, id);
check_error(err);
err = sqlite3_step(statement);
if (err == SQLITE_ROW) {
int64_t id = sqlite3_column_int64(statement, 0);
std::string name {(char *)sqlite3_column_text(statement, 1)};
std::string artist {(char *)sqlite3_column_text(statement, 2)};
char * spotid = (char *)sqlite3_column_text(statement, 3);
if (spotid) {
track_entry e {id, name, artist, std::string(spotid)};
sqlite3_finalize(statement);
return e;
}
track_entry e {id, name, artist};
sqlite3_finalize(statement);
return e;
}
sqlite3_finalize(statement);
return {};
}
std::optional<track_entry> get_song(std::string name, std::string artist) {
return get_song(name, artist, {});
}
std::optional<track_entry> get_song(std::string name, std::string artist, std::optional<std::string> spotify_id) {
spdlog::debug("get_song");
std::string check_exist_spot = "SELECT * FROM tracks WHERE spotifyid = ?;";
std::string check_exist_nospot = "SELECT * FROM tracks WHERE name = ? AND artist = ?;";
int err;
sqlite3_stmt *statement;
/* check whether the song exists */
if (spotify_id) {
@ -383,16 +437,49 @@ class songdb { @@ -383,16 +437,49 @@ class songdb {
check_error(err);
}
err = sqlite3_step(statement);
if (err == SQLITE_ROW) {
int64_t id = sqlite3_column_int64(statement, 0);
std::string name {(char *)sqlite3_column_text(statement, 1)};
std::string artist {(char *)sqlite3_column_text(statement, 2)};
char * spotid = (char *)sqlite3_column_text(statement, 3);
if (spotid) {
track_entry e {id, name, artist, std::string(spotid)};
sqlite3_finalize(statement);
return e;
}
track_entry e {id, name, artist};
sqlite3_finalize(statement);
return e;
spdlog::info("Entry exists.");
return true;
} else if (err != SQLITE_DONE) {
check_error(err);
return true;
sqlite3_finalize(statement);
return {};
}
sqlite3_finalize(statement);
return {};
}
std::optional<track_entry> insert_song(std::string name, std::string artist, std::optional<std::string> spotify_id) {
spdlog::debug("insert_song");
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);
sqlite3_stmt *statement;
int err;
auto e = get_song(name, artist, spotify_id);
if (e) {
return e;
}
if (spotify_id) {
err = sqlite3_prepare_v2(db, ins_query_spot.c_str(), ins_query_spot.length(), &statement, NULL);
@ -413,12 +500,57 @@ class songdb { @@ -413,12 +500,57 @@ class songdb {
err = sqlite3_step(statement);
if (err != SQLITE_DONE) {
sqlite3_reset(statement);
sqlite3_finalize(statement);
spdlog::warn("Failed insertion Sqlite: {}", sqlite3_errstr(err));
spdlog::dump_backtrace();
sqlite3_finalize(statement);
return {};
}
sqlite3_finalize(statement);
return get_song(name, artist, spotify_id);
}
bool
insert_vote(int64_t user, int64_t group, int value, int64_t songid)
{
spdlog::debug("insert_vote");
auto song = get_song(songid);
if (!song) {
spdlog::error("Failed to add vote, couldnt find song id: {}", songid);
return true;
}
int64_t list = get_song_list_id(group);
/* find existing vote */
std::string ins_query = "INSERT OR REPLACE INTO votes (song, list, user, rating) "
"VALUES (?, ?, ?, ?);";
sqlite3_stmt *statement;
int err;
err = sqlite3_prepare_v2(db, ins_query.c_str(), ins_query.length(), &statement, NULL);
check_error(err);
err = sqlite3_bind_int64(statement, 1, song->id);
check_error(err);
err = sqlite3_bind_int64(statement, 2, list);
check_error(err);
err = sqlite3_bind_int64(statement, 3, user);
check_error(err);
err= sqlite3_bind_int64(statement, 4, value);
check_error(err);
err = sqlite3_step(statement);
if (err != SQLITE_DONE) {
check_error(err);
sqlite3_finalize(statement);
return true;
}
sqlite3_finalize(statement);
return false;
}
@ -488,8 +620,6 @@ int main() { @@ -488,8 +620,6 @@ int main() {
Bot bot(teletoken);
InlineKeyboardMarkup::Ptr keyboard(new InlineKeyboardMarkup);
std::vector<InlineKeyboardButton::Ptr> row0;
@ -518,14 +648,42 @@ int main() { @@ -518,14 +648,42 @@ int main() {
button5->callbackData= "5";
row0.push_back(button5);
keyboard->inlineKeyboard.push_back(row0);
bot.getEvents().onCallbackQuery([&bot, &keyboard, &data](CallbackQuery::Ptr query) {
spdlog::info("Query: {}, mesg {}", query->data, query->message->text);
if ((query->data == "1") || (query->data == "2") || (query->data == "3") || (query->data == "4") || (query->data == "5")) {
std::istringstream is {query->data};
int value;
is >> value;
std::string songidflag = "songid:";
auto a = query->message->text.find(songidflag);
auto b = query->message->text.find("\n", a);
if (a==std::string::npos || b==std::string::npos) {
spdlog::error("Parse songid");
spdlog::dump_backtrace();
return;
}
a += songidflag.length();
std::istringstream is2 {query->message->text.substr(a, b - a)};
int64_t songid;
is2 >> songid;
auto song = data.get_song(songid);
if (!song) {
spdlog::error ("bad song id");
}
spdlog::info("Adding vote for {}: {}",song->name, value);
data.insert_vote(query->from->id, query->message->chat->id, value, songid);
bot.getEvents().onCallbackQuery([&bot, &keyboard](CallbackQuery::Ptr query) {
if (StringTools::startsWith(query->data, "check")) {
std::string response = "ok";
bot.getApi().sendMessage(query->message->chat->id, response, false, 0, keyboard, "Markdown");
}
});
@ -551,14 +709,21 @@ int main() { @@ -551,14 +709,21 @@ int main() {
std::string title = track_data["name"];
std::string artist = track_data["artists"][0]["name"];
auto song = data.insert_song(title, artist, *resp);
std::string response = "Added song: " + title + ", by " + artist;
response += "\n\r\n\r";
std::ostringstream os;
os << song->id;
response += "\n\rsongid:" + os.str() + "\n\r\n\r";
response += "Everyone, please rate how well you know this song /5";
data.insert_song(title, artist, {});
bot.getApi().sendMessage(message->chat->id, response, false, 0, keyboard, "Markdown");
});
bot.getEvents().onCommand("vote", [&bot](Message::Ptr message) {
bot.getApi().sendMessage(message->chat->id, "Hi!");
});
bot.getEvents().onCommand("start", [&bot](Message::Ptr message) {
bot.getApi().sendMessage(message->chat->id, "Hi!");

Loading…
Cancel
Save