Make bot token an argument, add trivia commands
This commit is contained in:
parent
54de981fc6
commit
c189265435
@ -4,7 +4,10 @@
|
|||||||
|
|
||||||
#include "APIHelper.hpp"
|
#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();
|
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());
|
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);
|
void send_message(std::string channel_id, std::string message);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const std::string BASE_URL = "https://discordapp.com/api";
|
const std::string BASE_URL;
|
||||||
const std::string CHANNELS_URL = BASE_URL + "/channels";
|
const std::string CHANNELS_URL;
|
||||||
const std::string TOKEN = "MTk5NjU3MDk1MjU4MTc3NTM5.ClyBNQ.15qTa-XBKRtGNMMYeXCrU50GhWE";
|
const std::string TOKEN;
|
||||||
const std::string TOKEN_PARAM = "token=" + TOKEN;
|
const std::string TOKEN_PARAM;
|
||||||
const std::string JSON_CTYPE = "application/json";
|
const std::string JSON_CTYPE;
|
||||||
|
|
||||||
HTTPHelper *http;
|
HTTPHelper *http;
|
||||||
};
|
};
|
||||||
|
@ -5,6 +5,8 @@
|
|||||||
#include "APIHelper.hpp"
|
#include "APIHelper.hpp"
|
||||||
#include "data_structures/User.hpp"
|
#include "data_structures/User.hpp"
|
||||||
|
|
||||||
|
extern std::string bot_token;
|
||||||
|
|
||||||
GatewayHandler::GatewayHandler() {
|
GatewayHandler::GatewayHandler() {
|
||||||
last_seq = 0;
|
last_seq = 0;
|
||||||
|
|
||||||
@ -26,8 +28,6 @@ void GatewayHandler::handle_data(std::string data, client &c, websocketpp::conne
|
|||||||
case 11:
|
case 11:
|
||||||
c.get_alog().write(websocketpp::log::alevel::app, "Heartbeat acknowledged.");
|
c.get_alog().write(websocketpp::log::alevel::app, "Heartbeat acknowledged.");
|
||||||
break;
|
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) {
|
void GatewayHandler::on_hello(json decoded, client &c, websocketpp::connection_hdl &hdl) {
|
||||||
heartbeat_interval = decoded["d"]["heartbeat_interval"];
|
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(
|
c.set_timer(heartbeat_interval, websocketpp::lib::bind(
|
||||||
&GatewayHandler::heartbeat,
|
&GatewayHandler::heartbeat,
|
||||||
@ -71,14 +71,10 @@ void GatewayHandler::on_dispatch(json decoded, client &c, websocketpp::connectio
|
|||||||
std::string event_name = decoded["t"];
|
std::string event_name = decoded["t"];
|
||||||
json data = decoded["d"];
|
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") {
|
if (event_name == "READY") {
|
||||||
user_object.load_from_json(data["user"]);
|
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, "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") {
|
else if (event_name == "GUILD_CREATE") {
|
||||||
std::string guild_id = data["id"];
|
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
|
// 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]));
|
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 == "TYPING_START") {}
|
||||||
else if (event_name == "MESSAGE_CREATE") {
|
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"]);
|
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;
|
std::vector<std::string> words;
|
||||||
boost::split(words, message, boost::is_any_of(" "));
|
boost::split(words, message, boost::is_any_of(" "));
|
||||||
if (games.find(channel->id) != games.end()) { // message received in channel with ongoing game
|
if (words[0] == "`trivia" || words[0] == "`t") {
|
||||||
games[channel->id]->handle_answer(message, sender);
|
|
||||||
} else if (words[0] == "`trivia" || words[0] == "`t") {
|
|
||||||
int questions = 10;
|
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 {
|
try {
|
||||||
questions = std::stoi(words[1]);
|
questions = std::stoi(words[1]);
|
||||||
} catch (std::invalid_argument e) {
|
if (words.size() == 3) {
|
||||||
ah->send_message(channel->id, ":exclamation: Invalid arguments!");
|
delay = std::stoi(words[2]);
|
||||||
}
|
}
|
||||||
} else if (words.size() > 2) {
|
}
|
||||||
|
catch (std::invalid_argument e) {
|
||||||
ah->send_message(channel->id, ":exclamation: Invalid arguments!");
|
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();
|
games[channel->id]->start();
|
||||||
}
|
}
|
||||||
else if (words[0] == "`channels") {
|
else if (words[0] == "`channels") {
|
||||||
@ -130,23 +146,25 @@ void GatewayHandler::on_dispatch(json decoded, client &c, websocketpp::connectio
|
|||||||
+ guilds[ch.second->guild_id]->name + " (" + ch.second->guild_id + ")\n";
|
+ guilds[ch.second->guild_id]->name + " (" + ch.second->guild_id + ")\n";
|
||||||
}
|
}
|
||||||
ah->send_message(channel->id, m);
|
ah->send_message(channel->id, m);
|
||||||
} else if (words[0] == "`guilds") {
|
}
|
||||||
|
else if (words[0] == "`guilds") {
|
||||||
std::string m = "Guild List:\n";
|
std::string m = "Guild List:\n";
|
||||||
for (auto &gu : guilds) {
|
for (auto &gu : guilds) {
|
||||||
m += "> " + gu.second->name + " (" + gu.second->id + ") Channels: " + std::to_string(gu.second->channels.size()) + "\n";
|
m += "> " + gu.second->name + " (" + gu.second->id + ") Channels: " + std::to_string(gu.second->channels.size()) + "\n";
|
||||||
}
|
}
|
||||||
ah->send_message(channel->id, m);
|
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) {
|
void GatewayHandler::identify(client &c, websocketpp::connection_hdl &hdl) {
|
||||||
json identify = {
|
json identify = {
|
||||||
{ "op", 2 },
|
{ "op", 2 },
|
||||||
{ "d", {
|
{ "d", {
|
||||||
{ "token", TOKEN },
|
{ "token", bot_token },
|
||||||
{ "properties", {
|
{ "properties", {
|
||||||
{ "$browser", "Microsoft Windows 10" },
|
{ "$browser", "Microsoft Windows 10" },
|
||||||
{ "$device", "TriviaBot-0.0" },
|
{ "$device", "TriviaBot-0.0" },
|
||||||
@ -160,13 +178,14 @@ void GatewayHandler::identify(client &c, websocketpp::connection_hdl &hdl) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
c.send(hdl, identify.dump(), websocketpp::frame::opcode::text);
|
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) {
|
void GatewayHandler::delete_game(std::string channel_id) {
|
||||||
auto it = games.find(channel_id);
|
auto it = games.find(channel_id);
|
||||||
|
|
||||||
if (it != games.end()) {
|
if (it != games.end()) {
|
||||||
|
it->second->interrupt();
|
||||||
// remove from map
|
// remove from map
|
||||||
games.erase(it);
|
games.erase(it);
|
||||||
} else {
|
} else {
|
||||||
|
@ -57,7 +57,6 @@ private:
|
|||||||
int heartbeat_interval;
|
int heartbeat_interval;
|
||||||
|
|
||||||
const int protocol_version = 5;
|
const int protocol_version = 5;
|
||||||
const std::string TOKEN = "MTk5NjU3MDk1MjU4MTc3NTM5.ClyBNQ.15qTa-XBKRtGNMMYeXCrU50GhWE";
|
|
||||||
|
|
||||||
// bot's user obj
|
// bot's user obj
|
||||||
DiscordObjects::User user_object;
|
DiscordObjects::User user_object;
|
||||||
|
@ -2,23 +2,34 @@
|
|||||||
|
|
||||||
#include "ClientConnection.hpp"
|
#include "ClientConnection.hpp"
|
||||||
|
|
||||||
int main() {
|
std::string bot_token;
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
curl_global_init(CURL_GLOBAL_DEFAULT);
|
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";
|
std::string uri = "wss://gateway.discord.gg/?v=5&encoding=json";
|
||||||
|
|
||||||
try {
|
try {
|
||||||
ClientConnection endpoint;
|
ClientConnection conn;
|
||||||
endpoint.start(uri);
|
conn.start(uri);
|
||||||
}
|
}
|
||||||
catch (const std::exception & e) {
|
catch (const std::exception & e) {
|
||||||
std::cout << e.what() << std::endl;
|
std::cerr << e.what() << std::endl;
|
||||||
}
|
}
|
||||||
catch (websocketpp::lib::error_code e) {
|
catch (websocketpp::lib::error_code e) {
|
||||||
std::cout << e.message() << std::endl;
|
std::cerr << e.message() << std::endl;
|
||||||
}
|
}
|
||||||
catch (...) {
|
catch (...) {
|
||||||
std::cout << "other exception" << std::endl;
|
std::cerr << "other exception" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::getchar();
|
std::getchar();
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
#include "APIHelper.hpp"
|
#include "APIHelper.hpp"
|
||||||
#include "data_structures/User.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->gh = gh;
|
||||||
this->ah = ah;
|
this->ah = ah;
|
||||||
this->channel_id = channel_id;
|
this->channel_id = channel_id;
|
||||||
@ -23,6 +23,11 @@ TriviaGame::TriviaGame(GatewayHandler *gh, APIHelper *ah, std::string channel_id
|
|||||||
}
|
}
|
||||||
|
|
||||||
TriviaGame::~TriviaGame() {
|
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) +
|
std::string message = ":red_circle: **(" + std::to_string(questions_asked) + "/" + std::to_string(total_questions) +
|
||||||
")** Game over! **Scores:**\n";
|
")** Game over! **Scores:**\n";
|
||||||
|
|
||||||
@ -131,7 +136,6 @@ TriviaGame::~TriviaGame() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (update_sql != "") {
|
if (update_sql != "") {
|
||||||
std::cout << update_sql << std::endl;
|
|
||||||
rc = sqlite3_prepare_v2(db, update_sql.c_str(), -1, &stmt, 0);
|
rc = sqlite3_prepare_v2(db, update_sql.c_str(), -1, &stmt, 0);
|
||||||
if (rc != SQLITE_OK) {
|
if (rc != SQLITE_OK) {
|
||||||
std::cerr << "SQL error." << std::endl;
|
std::cerr << "SQL error." << std::endl;
|
||||||
@ -159,14 +163,14 @@ TriviaGame::~TriviaGame() {
|
|||||||
sqlite3_close(db);
|
sqlite3_close(db);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TriviaGame::end_game() {
|
|
||||||
gh->delete_game(channel_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
void TriviaGame::start() {
|
void TriviaGame::start() {
|
||||||
question();
|
question();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TriviaGame::interrupt() {
|
||||||
|
current_thread->interrupt();
|
||||||
|
}
|
||||||
|
|
||||||
void TriviaGame::question() {
|
void TriviaGame::question() {
|
||||||
sqlite3 *db; int rc; char *sql;
|
sqlite3 *db; int rc; char *sql;
|
||||||
|
|
||||||
@ -212,7 +216,7 @@ void TriviaGame::question() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void TriviaGame::give_hint(int hints_given, std::string hint) {
|
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();
|
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));
|
hint = boost::regex_replace(hint, regexp, std::string(1, hide_char));
|
||||||
|
|
||||||
print = true;
|
print = true;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
std::stringstream hint_stream(hint);
|
std::stringstream hint_stream(hint);
|
||||||
|
|
||||||
std::random_device rd;
|
std::random_device rd;
|
||||||
@ -281,13 +284,13 @@ void TriviaGame::give_hint(int hints_given, std::string hint) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void TriviaGame::question_failed() {
|
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() + "` **");
|
ah->send_message(channel_id, ":exclamation: Question failed. Answer: ** `" + *current_answers.begin() + "` **");
|
||||||
|
|
||||||
if (questions_asked < 10) {
|
if (questions_asked < total_questions) {
|
||||||
question();
|
question();
|
||||||
} else {
|
} 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);
|
increase_score(sender.id);
|
||||||
update_average_time(sender.id, diff.total_milliseconds());
|
update_average_time(sender.id, diff.total_milliseconds());
|
||||||
|
|
||||||
if (questions_asked < 10) {
|
if (questions_asked < total_questions) {
|
||||||
question();
|
question();
|
||||||
} else {
|
} 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 {
|
class TriviaGame {
|
||||||
public:
|
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();
|
~TriviaGame();
|
||||||
|
|
||||||
void start();
|
void start();
|
||||||
|
void interrupt();
|
||||||
void handle_answer(std::string answer, DiscordObjects::User sender);
|
void handle_answer(std::string answer, DiscordObjects::User sender);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int questions_asked;
|
int questions_asked;
|
||||||
int total_questions;
|
int total_questions;
|
||||||
|
boost::posix_time::seconds interval;
|
||||||
|
|
||||||
void end_game();
|
|
||||||
void question();
|
void question();
|
||||||
void give_hint(int hints_given, std::string hint);
|
void give_hint(int hints_given, std::string hint);
|
||||||
void question_failed();
|
void question_failed();
|
||||||
|
@ -83,8 +83,6 @@ namespace DiscordObjects {
|
|||||||
|
|
||||||
inline void Guild::load_from_json(json data) {
|
inline void Guild::load_from_json(json data) {
|
||||||
Guild();
|
Guild();
|
||||||
std::cout << data.dump(4) << std::endl;
|
|
||||||
|
|
||||||
|
|
||||||
id = data.value("id", "null");
|
id = data.value("id", "null");
|
||||||
name = data.value("name", "null");
|
name = data.value("name", "null");
|
||||||
|
Loading…
Reference in New Issue
Block a user