#include <iostream>
#include <functional>
#include <unordered_map>
#include "crow.h"
#include "AnnotationTypes.hpp"
#define NULL_STRING std::string("null")
#define EMPTY_STRING std::string("")
#define NO_SUCH_COMMAND std::string("no_such_command")
typedef crow::json::wvalue json;
typedef std::function<json(std::string const &arguments, std::string const &session, void *payload)> handler_func;
struct CommandHandler {
[[nodiscard]] json exec(std::string const &arguments, std::string const &session) const {
return func(arguments, session, payload);
}
handler_func func;
void *payload{nullptr};
};
/* ------------------------------------------------------------------------------------------------------------------ */
json stopHandler(std::string const &arguments, std::string const &session, void *payload);
json wikiHandler(std::string const &arguments, std::string const &session, void *payload);
json klingerHandler(std::string const &arguments, std::string const &session, void *payload);
/* ------------------------------------------------------------------------------------------------------------------ */
json simple_response(std::string const &text, std::string const &session = NULL_STRING, bool success = true);
json create_annotation(Reply::AnnotationType annotation = Reply::AnnotationType::none,
std::string const &extra = EMPTY_STRING);
json create_text(std::string const &text);
json create_text(std::string const &text, std::vector<json> &&annotations);
json create_response(std::vector<json> &&reply, std::string const &session = NULL_STRING, bool success = true);
/* ------------------------------------------------------------------------------------------------------------------ */
int main() {
crow::SimpleApp app;
// command --> handler
static std::unordered_map<std::string, CommandHandler> const commands{
{"stop", {stopHandler, &app}},
{"wiki", {wikiHandler}},
{"klinger", {klingerHandler}},
};
CROW_ROUTE(app, "/")
.methods("POST"_method)
([&app](crow::request const &request) {
auto data = crow::json::load(request.body);
if (!data)
return crow::response(400);
if (!data.count("command"))
return crow::response(400, "malformed request: missing `command` field\n");
std::string command = (data.count("command") ? data["command"].s() : NO_SUCH_COMMAND);
std::string arguments = (data.count("arguments") ? data["arguments"].s() : EMPTY_STRING);
std::string session = (data.count("session") ? data["session"].s() : NULL_STRING);
if (auto itor = commands.find(command); itor != commands.end()) {
auto handler = itor->second;
return crow::response{handler.exec(arguments, session)};
}
return crow::response{simple_response("No such command!", NULL_STRING, false)};
});
app.port(18080).multithreaded().run();
std::cout << "Stopped successfully" << std::endl;
}
/* ------------------------------------------------------------------------------------------------------------------ */
json klingerHandler(std::string const &arguments, std::string const &session, void *payload) {
(void) payload;
return simple_response("Bonjour!");
}
json wikiHandler(std::string const &arguments, std::string const &session, void *payload) {
(void) payload;
std::vector<json> linkAnnotations;
linkAnnotations.push_back(std::move(create_annotation(Reply::AnnotationType::link, "Wikipedia")));
linkAnnotations.push_back(std::move(create_annotation(Reply::AnnotationType::underline)));
std::vector<json> reply_vec;
reply_vec.push_back(std::move(create_text("Visit ")));
reply_vec.push_back(std::move(create_text("https://eo.wikipedia.org/", std::move(linkAnnotations))));
reply_vec.push_back(std::move(create_text(" today!")));
return create_response(std::move(reply_vec), session, true);
}
json stopHandler(std::string const &arguments, std::string const &session, void *payload) {
auto app = (crow::SimpleApp *) payload;
app->stop();
std::vector<json> annotations;
annotations.push_back(std::move(create_annotation(Reply::AnnotationType::bold)));
std::vector<json> reply_vec;
reply_vec.push_back(std::move(create_text("stopped", std::move(annotations))));
return create_response(std::move(reply_vec), session, true);
}
/* ------------------------------------------------------------------------------------------------------------------ */
json simple_response(std::string const &text, std::string const &session, bool success) {
std::vector<json> reply_vec;
reply_vec.push_back(std::move(create_text(text)));
return create_response(std::move(reply_vec), session, success);
}
json create_annotation(Reply::AnnotationType annotationType, std::string const &extra) {
json annotation(crow::json::type::Object);
annotation["type"] = Reply::GetStringAnnotationType(annotationType);
annotation["extra"] = extra;
return annotation;
}
json create_text(std::string const &text) {
std::vector<json> annotations;
annotations.push_back(std::move(create_annotation()));
return create_text(text, std::move(annotations));
}
json create_text(std::string const &text, std::vector<json> &&annotations) {
json reply(crow::json::type::Object);
reply["text"] = text;
reply["annotations"] = std::move(annotations);
return reply;
}
json create_response(std::vector<json> &&reply, std::string const &session, bool success) {
json response(crow::json::type::Object);
response["success"] = success;
response["session"] = session;
response["reply"] = std::move(reply);
return response;
}
// curl -d '{"command":"klinger", "b":"12"}' -H "Content-Type: application/json" -X POST http://localhost:18080/