changeset 344:4665fffff6f2

Irccdctl: new cli interface
author David Demelier <markand@malikania.fr>
date Sat, 12 Nov 2016 22:58:48 +0100
parents 3d927ba4af75
children 006452e4a997
files CMakeLists.txt irccd/main.cpp irccdctl/cli.cpp irccdctl/cli.hpp irccdctl/main.cpp plugins/debugnative/main.cpp
diffstat 6 files changed, 192 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- a/CMakeLists.txt	Sat Nov 12 22:57:47 2016 +0100
+++ b/CMakeLists.txt	Sat Nov 12 22:58:48 2016 +0100
@@ -91,7 +91,7 @@
 add_subdirectory(contrib)
 
 if (WITH_JS)
-#add_subdirectory(plugins)
+    add_subdirectory(plugins)
 endif ()
 
 # Platform specific.
--- a/irccd/main.cpp	Sat Nov 12 22:57:47 2016 +0100
+++ b/irccd/main.cpp	Sat Nov 12 22:58:48 2016 +0100
@@ -35,6 +35,7 @@
 
 #include <format.h>
 
+#include "cmd-plugin-config.hpp"
 #include "cmd-plugin-reload.hpp"
 #include "cmd-plugin-unload.hpp"
 #include "cmd-server-cmode.hpp"
@@ -297,6 +298,7 @@
     option::Result options = parse(argc, argv);
 
     instance = std::make_unique<Irccd>();
+    instance->commands().add(std::make_unique<command::PluginConfigCommand>());
     instance->commands().add(std::make_unique<command::PluginReloadCommand>());
     instance->commands().add(std::make_unique<command::PluginUnloadCommand>());
     instance->commands().add(std::make_unique<command::ServerChannelModeCommand>());
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/irccdctl/cli.cpp	Sat Nov 12 22:58:48 2016 +0100
@@ -0,0 +1,83 @@
+/*
+ * cli.cpp -- command line for irccdctl
+ *
+ * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <json.hpp>
+
+#include "cli.hpp"
+#include "irccdctl.hpp"
+#include "util.hpp"
+#include "elapsed-timer.hpp"
+
+namespace irccd {
+
+void Cli::check(const nlohmann::json &response)
+{
+    if (!util::json::getBool(response, "status", false)) {
+        auto error = util::json::getString(response, "error");
+
+        if (error.empty())
+            throw std::runtime_error("command failed with an unknown error");
+
+        throw std::runtime_error(error);
+    }
+}
+
+nlohmann::json Cli::request(Irccdctl &irccdctl, nlohmann::json args)
+{
+    auto msg = nlohmann::json();
+
+    if (!args.is_object())
+        args = nlohmann::json::object();
+
+    args.push_back({"command", m_name});
+    irccdctl.client().request(args);
+
+    auto id = irccdctl.client().onMessage.connect([&] (auto input) {
+        msg = std::move(input);
+    });
+
+    try {
+        ElapsedTimer timer;
+
+        while (!msg.is_object() && timer.elapsed() < 3000)
+            util::poller::poll(3000 - timer.elapsed(), irccdctl);
+    } catch (const std::exception &) {
+        irccdctl.client().onMessage.disconnect(id);
+        throw;
+    }
+
+    irccdctl.client().onMessage.disconnect(id);
+
+    std::cout << msg << std::endl;
+
+    if (!msg.is_object())
+        throw std::runtime_error("no response received");
+    if (util::json::getString(msg, "command") != m_name)
+        throw std::runtime_error("unexpected command result received");
+
+    check(msg);
+
+    return msg;
+}
+
+void Cli::call(Irccdctl &irccdctl, nlohmann::json args)
+{
+    check(request(irccdctl, args));
+}
+
+} // !irccd
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/irccdctl/cli.hpp	Sat Nov 12 22:58:48 2016 +0100
@@ -0,0 +1,98 @@
+/*
+ * cli.hpp -- command line for irccdctl
+ *
+ * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef IRCCD_CLI_HPP
+#define IRCCD_CLI_HPP
+
+#include <string>
+#include <vector>
+
+#include <json.hpp>
+
+namespace irccd {
+
+class Irccdctl;
+
+class Cli {
+protected:
+    std::string m_name;
+    std::string m_summary;
+    std::string m_usage;
+    std::string m_help;
+
+    /**
+     * Check the message result and print an error if any.
+     *
+     * \param result the result
+     * \throw an error if any
+     */
+    void check(const nlohmann::json &result);
+
+    /**
+     * Send a request and wait for the response.
+     *
+     * \param irccdctl the client
+     * \param args the optional arguments
+     */
+    nlohmann::json request(Irccdctl &irccdctl, nlohmann::json args = nullptr);
+
+    /**
+     * Call a command and wait for success/error response.
+     *
+     * \param irccdctl the client
+     * \param args the extra arguments (may be null)
+     */
+    void call(Irccdctl &irccdctl, nlohmann::json args);
+
+public:
+    inline Cli(std::string name, std::string summary, std::string usage, std::string help) noexcept
+        : m_name(std::move(name))
+        , m_summary(std::move(summary))
+        , m_usage(std::move(usage))
+        , m_help(std::move(help))
+    {
+    }
+
+    virtual ~Cli() = default;
+
+    inline const std::string &name() const noexcept
+    {
+        return m_name;
+    }
+
+    inline const std::string &summary() const noexcept
+    {
+        return m_summary;
+    }
+
+    inline const std::string &usage() const noexcept
+    {
+        return m_usage;
+    }
+
+    inline const std::string &help() const noexcept
+    {
+        return m_help;
+    }
+
+    virtual void exec(Irccdctl &client, const std::vector<std::string> &args) = 0;
+};
+
+} // !irccd
+
+#endif // !IRCCD_CLI_HPP
--- a/irccdctl/main.cpp	Sat Nov 12 22:57:47 2016 +0100
+++ b/irccdctl/main.cpp	Sat Nov 12 22:58:48 2016 +0100
@@ -19,6 +19,7 @@
 #include "client.hpp"
 #include "irccdctl.hpp"
 
+#include "cli-plugin-config.hpp"
 #include "cli-plugin-reload.hpp"
 #include "cli-plugin-unload.hpp"
 #include "cli-server-cmode.hpp"
@@ -46,8 +47,8 @@
         Irccdctl ctl(std::make_unique<Client>());
         ctl.client().connect(net::local::create("/tmp/irccd.sock"));
 
-        cli::ServerReconnectCli command;
-        command.exec(ctl, {"local"});
+        cli::PluginConfigCli command;
+        command.exec(ctl, {"ask", "disable_if", "ok"});
     } catch (const std::exception &ex) {
         std::cerr << ex.what() << std::endl;
     }
--- a/plugins/debugnative/main.cpp	Sat Nov 12 22:57:47 2016 +0100
+++ b/plugins/debugnative/main.cpp	Sat Nov 12 22:58:48 2016 +0100
@@ -18,11 +18,11 @@
 
 #include <iostream>
 
-#include <irccd/irccd.hpp>
-#include <irccd/logger.hpp>
-#include <irccd/plugin-dynlib.hpp>
-#include <irccd/server.hpp>
-#include <irccd/util.hpp>
+#include <irccd.hpp>
+#include <logger.hpp>
+#include <plugin-dynlib.hpp>
+#include <server.hpp>
+#include <util.hpp>
 
 using namespace irccd;