aboutsummaryrefslogtreecommitdiffstats
path: root/src/main.cpp
blob: c704f39a6a1634da3f5cc5e7d7beb9ac0a0b497e (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
#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/