Make bot token an argument, add trivia commands
This commit is contained in:
parent
54de981fc6
commit
c189265435
@ -4,7 +4,10 @@
|
||||
|
||||
#include "APIHelper.hpp"
|
||||
|
||||
APIHelper::APIHelper() {
|
||||
extern std::string bot_token;
|
||||
|
||||
APIHelper::APIHelper() : BASE_URL("https://discordapp.com/api"), CHANNELS_URL(BASE_URL + "/channels"),
|
||||
TOKEN_PARAM("token=" + bot_token), JSON_CTYPE("application/json") {
|
||||
http = new HTTPHelper();
|
||||
}
|
||||
|
||||
@ -15,5 +18,5 @@ void APIHelper::send_message(std::string channel_id, std::string message) {
|
||||
};
|
||||
|
||||
const std::string response = http->post_request(url, JSON_CTYPE, data.dump());
|
||||
std::cout << response << std::endl;
|
||||
// TODO: verify success
|
||||
}
|
@ -16,11 +16,11 @@ public:
|
||||
void send_message(std::string channel_id, std::string message);
|
||||
|
||||
private:
|
||||
const std::string BASE_URL = "https://discordapp.com/api";
|
||||
const std::string CHANNELS_URL = BASE_URL + "/channels";
|
||||
const std::string TOKEN = "MTk5NjU3MDk1MjU4MTc3NTM5.ClyBNQ.15qTa-XBKRtGNMMYeXCrU50GhWE";
|
||||
const std::string TOKEN_PARAM = "token=" + TOKEN;
|
||||
const std::string JSON_CTYPE = "application/json";
|
||||
const std::string BASE_URL;
|
||||
const std::string CHANNELS_URL;
|
||||
const std::string TOKEN;
|
||||
const std::string TOKEN_PARAM;
|
||||
const std::string JSON_CTYPE;
|
||||
|
||||
HTTPHelper *http;
|
||||
};
|
||||
|
@ -5,6 +5,8 @@
|
||||
#include "APIHelper.hpp"
|
||||
#include "data_structures/User.hpp"
|
||||
|
||||
extern std::string bot_token;
|
||||
|
||||
GatewayHandler::GatewayHandler() {
|
||||
last_seq = 0;
|
||||
|
||||
@ -26,8 +28,6 @@ void GatewayHandler::handle_data(std::string data, client &c, websocketpp::conne
|
||||
case 11:
|
||||
c.get_alog().write(websocketpp::log::alevel::app, "Heartbeat acknowledged.");
|
||||
break;
|
||||
default:
|
||||
std::cout << data << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
@ -53,7 +53,7 @@ void GatewayHandler::heartbeat(websocketpp::lib::error_code const & ec, client *
|
||||
void GatewayHandler::on_hello(json decoded, client &c, websocketpp::connection_hdl &hdl) {
|
||||
heartbeat_interval = decoded["d"]["heartbeat_interval"];
|
||||
|
||||
c.get_alog().write(websocketpp::log::alevel::app, "Heartbeat interval: " + std::to_string((float)heartbeat_interval / 1000) + " seconds");
|
||||
c.get_alog().write(websocketpp::log::alevel::app, "Heartbeat interval: " + std::to_string(heartbeat_interval / 1000.0f) + " seconds");
|
||||
|
||||
c.set_timer(heartbeat_interval, websocketpp::lib::bind(
|
||||
&GatewayHandler::heartbeat,
|
||||
@ -71,14 +71,10 @@ void GatewayHandler::on_dispatch(json decoded, client &c, websocketpp::connectio
|
||||
std::string event_name = decoded["t"];
|
||||
json data = decoded["d"];
|
||||
|
||||
c.get_alog().write(websocketpp::log::alevel::app, "Received event: " + event_name + " (new seq value: " + std::to_string(last_seq) + ")");
|
||||
|
||||
if (event_name == "READY") {
|
||||
user_object.load_from_json(data["user"]);
|
||||
|
||||
c.get_alog().write(websocketpp::log::alevel::app, "Sign-on confirmed. (@" + user_object.username + "#" + user_object.discriminator + ")");
|
||||
|
||||
c.get_alog().write(websocketpp::log::alevel::app, data.dump(4));
|
||||
}
|
||||
else if (event_name == "GUILD_CREATE") {
|
||||
std::string guild_id = data["id"];
|
||||
@ -92,8 +88,6 @@ void GatewayHandler::on_dispatch(json decoded, client &c, websocketpp::connectio
|
||||
// add ptr to said channel list to guild's channel list
|
||||
guilds[guild_id]->channels.push_back(std::shared_ptr<DiscordObjects::Channel>(channels[channel_id]));
|
||||
}
|
||||
|
||||
c.get_alog().write(websocketpp::log::alevel::app, data.dump(4));
|
||||
}
|
||||
else if (event_name == "TYPING_START") {}
|
||||
else if (event_name == "MESSAGE_CREATE") {
|
||||
@ -102,25 +96,47 @@ void GatewayHandler::on_dispatch(json decoded, client &c, websocketpp::connectio
|
||||
|
||||
DiscordObjects::User sender(data["author"]);
|
||||
|
||||
c.get_alog().write(websocketpp::log::alevel::app, "Message received: " + message + " $" + channel->name + " ^" + channel->id);
|
||||
|
||||
std::vector<std::string> words;
|
||||
boost::split(words, message, boost::is_any_of(" "));
|
||||
if (games.find(channel->id) != games.end()) { // message received in channel with ongoing game
|
||||
games[channel->id]->handle_answer(message, sender);
|
||||
} else if (words[0] == "`trivia" || words[0] == "`t") {
|
||||
if (words[0] == "`trivia" || words[0] == "`t") {
|
||||
int questions = 10;
|
||||
if (words.size() == 2) {
|
||||
int delay = 8;
|
||||
|
||||
if (words.size() > 3) {
|
||||
ah->send_message(channel->id, ":exclamation: Invalid arguments!");
|
||||
return;
|
||||
}
|
||||
else if(words.size() > 1) {
|
||||
if (words[1] == "help" || words[1] == "h") {
|
||||
std::string help = "**Base command \\`t[rivia]**. Arguments:\n";
|
||||
help += "\\`trivia **{x}** **{y}**: Makes the game last **x** number of questions, optionally sets the time interval between hints to **y** seconds\n";
|
||||
help += "\\`trivia **stop**: stops the ongoing game.\n";
|
||||
help += "\\`trivia **help**: prints this message\n";
|
||||
|
||||
ah->send_message(channel->id, help);
|
||||
return;
|
||||
}
|
||||
else if (words[1] == "stop" || words[1] == "s") {
|
||||
if (games.find(channel->id) != games.end()) {
|
||||
delete_game(channel->id);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
try {
|
||||
questions = std::stoi(words[1]);
|
||||
} catch (std::invalid_argument e) {
|
||||
ah->send_message(channel->id, ":exclamation: Invalid arguments!");
|
||||
if (words.size() == 3) {
|
||||
delay = std::stoi(words[2]);
|
||||
}
|
||||
} else if (words.size() > 2) {
|
||||
}
|
||||
catch (std::invalid_argument e) {
|
||||
ah->send_message(channel->id, ":exclamation: Invalid arguments!");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
games[channel->id] = std::make_unique<TriviaGame>(this, ah, channel->id, questions);
|
||||
games[channel->id] = std::make_unique<TriviaGame>(this, ah, channel->id, questions, delay);
|
||||
games[channel->id]->start();
|
||||
}
|
||||
else if (words[0] == "`channels") {
|
||||
@ -130,24 +146,26 @@ void GatewayHandler::on_dispatch(json decoded, client &c, websocketpp::connectio
|
||||
+ guilds[ch.second->guild_id]->name + " (" + ch.second->guild_id + ")\n";
|
||||
}
|
||||
ah->send_message(channel->id, m);
|
||||
} else if (words[0] == "`guilds") {
|
||||
}
|
||||
else if (words[0] == "`guilds") {
|
||||
std::string m = "Guild List:\n";
|
||||
for (auto &gu : guilds) {
|
||||
m += "> " + gu.second->name + " (" + gu.second->id + ") Channels: " + std::to_string(gu.second->channels.size()) + "\n";
|
||||
}
|
||||
ah->send_message(channel->id, m);
|
||||
}
|
||||
c.get_alog().write(websocketpp::log::alevel::app, data.dump(2));
|
||||
else if (games.find(channel->id) != games.end()) { // message received in channel with ongoing game
|
||||
games[channel->id]->handle_answer(message, sender);
|
||||
}
|
||||
}
|
||||
//c.get_alog().write(websocketpp::log::alevel::app, decoded.dump(2));
|
||||
}
|
||||
|
||||
void GatewayHandler::identify(client &c, websocketpp::connection_hdl &hdl) {
|
||||
json identify = {
|
||||
{ "op", 2 },
|
||||
{ "d",{
|
||||
{ "token", TOKEN },
|
||||
{ "properties",{
|
||||
{ "d", {
|
||||
{ "token", bot_token },
|
||||
{ "properties", {
|
||||
{ "$browser", "Microsoft Windows 10" },
|
||||
{ "$device", "TriviaBot-0.0" },
|
||||
{ "$referrer", "" },
|
||||
@ -155,18 +173,19 @@ void GatewayHandler::identify(client &c, websocketpp::connection_hdl &hdl) {
|
||||
} },
|
||||
{ "compress", false },
|
||||
{ "large_threshold", 250 },
|
||||
{ "shard",{ 0, 1 } }
|
||||
{ "shard", { 0, 1 } }
|
||||
} }
|
||||
};
|
||||
|
||||
c.send(hdl, identify.dump(), websocketpp::frame::opcode::text);
|
||||
c.get_alog().write(websocketpp::log::alevel::app, "Sent identify payload.");
|
||||
c.get_alog().write(websocketpp::log::alevel::app, "Sent identify payload. Token: " + bot_token);
|
||||
}
|
||||
|
||||
void GatewayHandler::delete_game(std::string channel_id) {
|
||||
auto it = games.find(channel_id);
|
||||
|
||||
if (it != games.end()) {
|
||||
it->second->interrupt();
|
||||
// remove from map
|
||||
games.erase(it);
|
||||
} else {
|
||||
|
@ -57,7 +57,6 @@ private:
|
||||
int heartbeat_interval;
|
||||
|
||||
const int protocol_version = 5;
|
||||
const std::string TOKEN = "MTk5NjU3MDk1MjU4MTc3NTM5.ClyBNQ.15qTa-XBKRtGNMMYeXCrU50GhWE";
|
||||
|
||||
// bot's user obj
|
||||
DiscordObjects::User user_object;
|
||||
|
@ -2,23 +2,34 @@
|
||||
|
||||
#include "ClientConnection.hpp"
|
||||
|
||||
int main() {
|
||||
std::string bot_token;
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
curl_global_init(CURL_GLOBAL_DEFAULT);
|
||||
|
||||
if (argc == 2) {
|
||||
bot_token = argv[1];
|
||||
}
|
||||
else {
|
||||
std::cout << "Please enter your bot token: " << std::endl;
|
||||
std::cin >> bot_token;
|
||||
}
|
||||
|
||||
// todo: get this using API
|
||||
std::string uri = "wss://gateway.discord.gg/?v=5&encoding=json";
|
||||
|
||||
try {
|
||||
ClientConnection endpoint;
|
||||
endpoint.start(uri);
|
||||
ClientConnection conn;
|
||||
conn.start(uri);
|
||||
}
|
||||
catch (const std::exception & e) {
|
||||
std::cout << e.what() << std::endl;
|
||||
std::cerr << e.what() << std::endl;
|
||||
}
|
||||
catch (websocketpp::lib::error_code e) {
|
||||
std::cout << e.message() << std::endl;
|
||||
std::cerr << e.message() << std::endl;
|
||||
}
|
||||
catch (...) {
|
||||
std::cout << "other exception" << std::endl;
|
||||
std::cerr << "other exception" << std::endl;
|
||||
}
|
||||
|
||||
std::getchar();
|
||||
|
@ -13,7 +13,7 @@
|
||||
#include "APIHelper.hpp"
|
||||
#include "data_structures/User.hpp"
|
||||
|
||||
TriviaGame::TriviaGame(GatewayHandler *gh, APIHelper *ah, std::string channel_id, int total_questions) {
|
||||
TriviaGame::TriviaGame(GatewayHandler *gh, APIHelper *ah, std::string channel_id, int total_questions, int delay) : interval(delay) {
|
||||
this->gh = gh;
|
||||
this->ah = ah;
|
||||
this->channel_id = channel_id;
|
||||
@ -23,6 +23,11 @@ TriviaGame::TriviaGame(GatewayHandler *gh, APIHelper *ah, std::string channel_id
|
||||
}
|
||||
|
||||
TriviaGame::~TriviaGame() {
|
||||
if (scores.size() == 0) {
|
||||
ah->send_message(channel_id, ":red_circle: Game cancelled!");
|
||||
return;
|
||||
}
|
||||
|
||||
std::string message = ":red_circle: **(" + std::to_string(questions_asked) + "/" + std::to_string(total_questions) +
|
||||
")** Game over! **Scores:**\n";
|
||||
|
||||
@ -33,7 +38,7 @@ TriviaGame::~TriviaGame() {
|
||||
}
|
||||
|
||||
// sort by score, highest->lowest
|
||||
std::sort(pairs.begin(), pairs.end(), [=](std::pair<std::string, int>& a, std::pair<std::string, int>& b) {
|
||||
std::sort(pairs.begin(), pairs.end(), [=](std::pair<std::string, int> &a, std::pair<std::string, int> &b) {
|
||||
return a.second > b.second;
|
||||
});
|
||||
|
||||
@ -83,7 +88,7 @@ TriviaGame::~TriviaGame() {
|
||||
rc = sqlite3_step(stmt);
|
||||
|
||||
if (rc == SQLITE_ROW) {
|
||||
std::string id = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 0));
|
||||
std::string id = reinterpret_cast<const char *>(sqlite3_column_text(stmt, 0));
|
||||
int total_score = sqlite3_column_int(stmt, 1);
|
||||
int average_time = sqlite3_column_int(stmt, 2);
|
||||
|
||||
@ -131,7 +136,6 @@ TriviaGame::~TriviaGame() {
|
||||
}
|
||||
|
||||
if (update_sql != "") {
|
||||
std::cout << update_sql << std::endl;
|
||||
rc = sqlite3_prepare_v2(db, update_sql.c_str(), -1, &stmt, 0);
|
||||
if (rc != SQLITE_OK) {
|
||||
std::cerr << "SQL error." << std::endl;
|
||||
@ -159,14 +163,14 @@ TriviaGame::~TriviaGame() {
|
||||
sqlite3_close(db);
|
||||
}
|
||||
|
||||
void TriviaGame::end_game() {
|
||||
gh->delete_game(channel_id);
|
||||
}
|
||||
|
||||
void TriviaGame::start() {
|
||||
question();
|
||||
}
|
||||
|
||||
void TriviaGame::interrupt() {
|
||||
current_thread->interrupt();
|
||||
}
|
||||
|
||||
void TriviaGame::question() {
|
||||
sqlite3 *db; int rc; char *sql;
|
||||
|
||||
@ -188,10 +192,10 @@ void TriviaGame::question() {
|
||||
rc = sqlite3_step(stmt);
|
||||
if (rc == SQLITE_ROW) {
|
||||
// result received
|
||||
std::string id = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 0)); // converts id to string for us
|
||||
std::string category = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 1));
|
||||
std::string question = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 2));
|
||||
std::string answer = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 3));
|
||||
std::string id = reinterpret_cast<const char *>(sqlite3_column_text(stmt, 0)); // converts id to string for us
|
||||
std::string category = reinterpret_cast<const char *>(sqlite3_column_text(stmt, 1));
|
||||
std::string question = reinterpret_cast<const char *>(sqlite3_column_text(stmt, 2));
|
||||
std::string answer = reinterpret_cast<const char *>(sqlite3_column_text(stmt, 3));
|
||||
|
||||
current_question = "#" + id + " [" + category + "] **" + question + "**";
|
||||
boost::split(current_answers, boost::algorithm::to_lower_copy(answer), boost::is_any_of("*"));
|
||||
@ -212,7 +216,7 @@ void TriviaGame::question() {
|
||||
}
|
||||
|
||||
void TriviaGame::give_hint(int hints_given, std::string hint) {
|
||||
boost::this_thread::sleep(boost::posix_time::seconds(10));
|
||||
boost::this_thread::sleep(interval);
|
||||
|
||||
std::string answer = *current_answers.begin();
|
||||
|
||||
@ -225,8 +229,7 @@ void TriviaGame::give_hint(int hints_given, std::string hint) {
|
||||
hint = boost::regex_replace(hint, regexp, std::string(1, hide_char));
|
||||
|
||||
print = true;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
std::stringstream hint_stream(hint);
|
||||
|
||||
std::random_device rd;
|
||||
@ -281,13 +284,13 @@ void TriviaGame::give_hint(int hints_given, std::string hint) {
|
||||
}
|
||||
|
||||
void TriviaGame::question_failed() {
|
||||
boost::this_thread::sleep(boost::posix_time::seconds(10));
|
||||
boost::this_thread::sleep(interval);
|
||||
ah->send_message(channel_id, ":exclamation: Question failed. Answer: ** `" + *current_answers.begin() + "` **");
|
||||
|
||||
if (questions_asked < 10) {
|
||||
if (questions_asked < total_questions) {
|
||||
question();
|
||||
} else {
|
||||
end_game();
|
||||
gh->delete_game(channel_id);
|
||||
}
|
||||
}
|
||||
|
||||
@ -307,15 +310,11 @@ void TriviaGame::handle_answer(std::string answer, DiscordObjects::User sender)
|
||||
increase_score(sender.id);
|
||||
update_average_time(sender.id, diff.total_milliseconds());
|
||||
|
||||
if (questions_asked < 10) {
|
||||
if (questions_asked < total_questions) {
|
||||
question();
|
||||
} else {
|
||||
end_game();
|
||||
gh->delete_game(channel_id);
|
||||
}
|
||||
} else if (answer == "`s" || answer == "`stop") {
|
||||
current_thread->interrupt();
|
||||
|
||||
end_game();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -19,17 +19,18 @@ namespace DiscordObjects {
|
||||
|
||||
class TriviaGame {
|
||||
public:
|
||||
TriviaGame(GatewayHandler *gh, APIHelper *ah, std::string channel_id, int total_questions);
|
||||
TriviaGame(GatewayHandler *gh, APIHelper *ah, std::string channel_id, int total_questions, int delay);
|
||||
~TriviaGame();
|
||||
|
||||
void start();
|
||||
void interrupt();
|
||||
void handle_answer(std::string answer, DiscordObjects::User sender);
|
||||
|
||||
private:
|
||||
int questions_asked;
|
||||
int total_questions;
|
||||
boost::posix_time::seconds interval;
|
||||
|
||||
void end_game();
|
||||
void question();
|
||||
void give_hint(int hints_given, std::string hint);
|
||||
void question_failed();
|
||||
|
@ -83,8 +83,6 @@ namespace DiscordObjects {
|
||||
|
||||
inline void Guild::load_from_json(json data) {
|
||||
Guild();
|
||||
std::cout << data.dump(4) << std::endl;
|
||||
|
||||
|
||||
id = data.value("id", "null");
|
||||
name = data.value("name", "null");
|
||||
|
Loading…
Reference in New Issue
Block a user