aboutsummaryrefslogblamecommitdiffstats
path: root/src/main.cpp
blob: c704f39a6a1634da3f5cc5e7d7beb9ac0a0b497e (plain) (tree)
1
2
3
4
5
6
7
8
                   

                        
 

                 

                              



                                                      

                                                                                                                  

                       
                                                                                             






                                                 










                                                                                                                        
 








                                                                                                                        
 
            

                        

                                                                          


                                             


                        
                                   
                                                           
                                                                   
 

                                                       
 


                                                                                                       








                                                                                                                 
                                                                                                       



                                          


                                                     
                                                                                                                        
 



                                                                                              
 

                                                                                           
 


                                                                                                      
 



                                                                                                         
 
                                                                

 

                                                                                           
                
 

                                                                                     
 

                                                                                   
 

                                                                
 
                                                                                                                        
 


                                                                                         
 

                                                                   
 





                                                                                        
 











                                                                            
 




                                                                                           
                    

 
                                                                                                                
#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/