Mercurial > irccd
diff irccdctl/cli.cpp @ 345:006452e4a997
Irccdctl: unify cli commands
author | David Demelier <markand@malikania.fr> |
---|---|
date | Sun, 13 Nov 2016 09:45:54 +0100 |
parents | 4665fffff6f2 |
children | 24b1709093e7 |
line wrap: on
line diff
--- a/irccdctl/cli.cpp Sat Nov 12 22:58:48 2016 +0100 +++ b/irccdctl/cli.cpp Sun Nov 13 09:45:54 2016 +0100 @@ -16,15 +16,23 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include <iostream> + #include <json.hpp> #include "cli.hpp" +#include "elapsed-timer.hpp" #include "irccdctl.hpp" +#include "options.hpp" #include "util.hpp" -#include "elapsed-timer.hpp" namespace irccd { +/* + * Cli. + * ------------------------------------------------------------------ + */ + void Cli::check(const nlohmann::json &response) { if (!util::json::getBool(response, "status", false)) { @@ -80,4 +88,723 @@ check(request(irccdctl, args)); } +namespace cli { + +/* + * PluginConfigCli. + * ------------------------------------------------------------------ + */ + +void PluginConfigCli::set(Irccdctl &irccdctl, const std::vector<std::string> &args) +{ + check(request(irccdctl, nlohmann::json::object({ + { "plugin", args[0] }, + { "variable", args[1] }, + { "value", args[2] } + }))); +} + +void PluginConfigCli::get(Irccdctl &irccdctl, const std::vector<std::string> &args) +{ + auto result = request(irccdctl, nlohmann::json::object({ + { "plugin", args[0] }, + { "variable", args[1] } + })); + + check(result); + + if (result["variables"].is_object()) + std::cout << util::json::pretty(result["variables"][args[1]]) << std::endl; +} + +void PluginConfigCli::getall(Irccdctl &irccdctl, const std::vector<std::string> &args) +{ + auto result = request(irccdctl, nlohmann::json::object({{ "plugin", args[0] }})); + + check(result); + + auto variables = result["variables"]; + + for (auto v = variables.begin(); v != variables.end(); ++v) + std::cout << std::setw(16) << std::left << v.key() << " : " << util::json::pretty(v.value()) << std::endl; +} + +PluginConfigCli::PluginConfigCli() + : Cli("plugin-config", + "configure a plugin", + "plugin-config plugin [variable] [value]", + "Get or set plugin configuration.\n\n" + "Examples:\n" + "\tirccdctl plugin-config ask") +{ +} + +void PluginConfigCli::exec(Irccdctl &irccdctl, const std::vector<std::string> &args) +{ + switch (args.size()) { + case 3: + set(irccdctl, args); + break; + case 2: + get(irccdctl, args); + break; + case 1: + getall(irccdctl, args); + break; + default: + throw std::invalid_argument("plugin-config requires at least 1 argument"); + } +} + +/* + * PluginInfoCli. + * ------------------------------------------------------------------ + */ + +PluginInfoCli::PluginInfoCli() + : Cli("plugin-info", + "get plugin information", + "plugin-info plugin", + "Get plugin information\n\n" + "Example:\n" + "\tirccdctl plugin-info ask" + ) +{ +} + +void PluginInfoCli::exec(Irccdctl &irccdctl, const std::vector<std::string> &args) +{ + if (args.size() < 1) + throw std::invalid_argument("plugin-info requires 1 argument"); + + auto result = request(irccdctl, {{ "plugin", args[0] }}); + + std::cout << std::boolalpha; + std::cout << "Author : " << util::json::getString(result, "author") << std::endl; + std::cout << "License : " << util::json::getString(result, "license") << std::endl; + std::cout << "Summary : " << util::json::getString(result, "summary") << std::endl; + std::cout << "Version : " << util::json::getString(result, "version") << std::endl; +} + +/* + * PluginListCli. + * ------------------------------------------------------------------ + */ + +PluginListCli::PluginListCli() + : Cli("plugin-list", + "list loaded plugins", + "plugin-list", + "Get the list of all loaded plugins.\n\n" + "Example:\n" + "\tirccdctl plugin-list") +{ +} + +void PluginListCli::exec(Irccdctl &irccdctl, const std::vector<std::string> &) +{ + auto result = request(irccdctl); + + for (const auto &value : result["list"]) + if (value.is_string()) + std::cout << value.get<std::string>() << std::endl; +} + +/* + * PluginLoadCli. + * ------------------------------------------------------------------ + */ + +PluginLoadCli::PluginLoadCli() + : Cli("plugin-load", + "load a plugin", + "plugin-load logger", + "Load a plugin into the irccd instance.\n\n" + "Example:\n" + "\tirccdctl plugin-load logger") +{ +} + +void PluginLoadCli::exec(Irccdctl &irccdctl, const std::vector<std::string> &args) +{ + if (args.size() < 1) + throw std::invalid_argument("plugin-load requires 1 argument"); + + check(request(irccdctl, {{"plugin", args[0]}})); +} + +/* + * PluginReloadCli. + * ------------------------------------------------------------------ + */ + +PluginReloadCli::PluginReloadCli() + : Cli("plugin-reload", + "reload a plugin", + "plugin-reload plugin", + "Call the onReload event on the specified plugin.") +{ +} + +void PluginReloadCli::exec(Irccdctl &irccdctl, const std::vector<std::string> &args) +{ + if (args.size() < 1) + throw std::invalid_argument("plugin-reload requires 1 argument"); + + check(request(irccdctl, {{ "plugin", args[0] }})); +} + +/* + * PluginUnloadCli. + * ------------------------------------------------------------------ + */ + +PluginUnloadCli::PluginUnloadCli() + : Cli("plugin-unload", + "unload a plugin", + "plugin-unload plugin", + "Unload a loaded plugin from the irccd instance.\n\n" + "Example:\n" + "tirccdctl plugin-unload logger") +{ +} + +void PluginUnloadCli::exec(Irccdctl &irccdctl, const std::vector<std::string> &args) +{ + if (args.size() < 1) + throw std::invalid_argument("plugin-unload requires 1 argument"); + + check(request(irccdctl, {{ "plugin", args[0] }})); +} + +/* + * ServerChannelCli. + * ------------------------------------------------------------------ + */ + +ServerChannelMode::ServerChannelMode() + : Cli("server-cmode", + "change channel mode", + "server-cmode server channel mode", + "Change the mode of the specified channel.\n\n" + "Example:\n" + "\tirccdctl server-cmode freenode #staff +t") +{ +} + +void ServerChannelMode::exec(Irccdctl &irccdctl, const std::vector<std::string> &args) +{ + if (args.size() < 3) + throw std::invalid_argument("server-cmode requires 3 arguments"); + + check(request(irccdctl, { + { "command", "server-cmode" }, + { "server", args[0] }, + { "channel", args[1] }, + { "mode", args[2] } + })); +} + +/* + * ServerChannelNoticeCli. + * ------------------------------------------------------------------ + */ + +ServerChannelNoticeCli::ServerChannelNoticeCli() + : Cli("server-cnotice", + "send a channel notice", + "server-cnotice server channel message", + "Send a message notice on a channel.\n\n" + "Example:\n" + "\tirccdctl server-cnotice freenode #staff \"Don't flood!\"") +{ +} + +void ServerChannelNoticeCli::exec(Irccdctl &irccdctl, const std::vector<std::string> &args) +{ + if (args.size() < 3) + throw std::invalid_argument("server-cnotice requires 3 arguments"); + + check(request(irccdctl, { + { "command", "server-cnotice" }, + { "server", args[0] }, + { "channel", args[1] }, + { "message", args[2] } + })); +} + +/* + * ServerConnectCli. + * ------------------------------------------------------------------ + */ + +namespace { + +option::Result parse(std::vector<std::string> &args) +{ + option::Options options{ + { "-c", true }, + { "--command", true }, + { "-n", true }, + { "--nickname", true }, + { "-r", true }, + { "--realname", true }, + { "-S", false }, + { "--ssl-verify", false }, + { "-s", false }, + { "--ssl", false }, + { "-u", true }, + { "--username", true } + }; + + return option::read(args, options); +} + +} // !namespace + +ServerConnectCli::ServerConnectCli() + : Cli("server-connect", + "add a server", + "server-connect [options] id host [port]", + "Connect to a server.\n\n" + "Available options:\n" + " -c, --command\t\tspecify the command char\n" + " -n, --nickname\tspecify a nickname\n" + " -r, --realname\tspecify a real name\n" + " -S, --ssl-verify\tverify SSL\n" + " -s, --ssl\t\tconnect using SSL\n" + " -u, --username\tspecify a user name\n\n" + "Example:\n" + "\tirccdctl server-connect -n jean example irc.example.org\n" + "\tirccdctl server-connect --ssl example irc.example.org 6697") +{ +} + +void ServerConnectCli::exec(Irccdctl &irccdctl, const std::vector<std::string> &args) +{ + std::vector<std::string> copy(args); + + option::Result result = parse(copy); + option::Result::const_iterator it; + + if (copy.size() < 2) + throw std::invalid_argument("server-connect requires at least 2 arguments"); + + auto object = nlohmann::json::object({ + { "name", copy[0] }, + { "host", copy[1] } + }); + + if (copy.size() == 3) { + if (!util::isNumber(copy[2])) + throw std::invalid_argument("invalid port number"); + + object["port"] = std::stoi(copy[2]); + } + + if (result.count("-S") > 0 || result.count("--ssl-verify") > 0) + object["sslVerify"] = true; + if (result.count("-s") > 0 || result.count("--ssl") > 0) + object["ssl"] = true; + if ((it = result.find("-n")) != result.end() || (it = result.find("--nickname")) != result.end()) + object["nickname"] = it->second; + if ((it = result.find("-r")) != result.end() || (it = result.find("--realname")) != result.end()) + object["realname"] = it->second; + if ((it = result.find("-u")) != result.end() || (it = result.find("--username")) != result.end()) + object["username"] = it->second; + + check(request(irccdctl, object)); +} + +/* + * ServerDisconnectCli. + * ------------------------------------------------------------------ + */ + +ServerDisconnectCli::ServerDisconnectCli() + : Cli("server-disconnect", + "disconnect server", + "server-disconnect [server]", + "Disconnect from a server.\n\n" + "If server is not specified, irccd disconnects all servers.\n\n" + "Example:\n" + "\tirccdctl server-disconnect localhost") +{ +} + +void ServerDisconnectCli::exec(Irccdctl &irccdctl, const std::vector<std::string> &args) +{ + auto object = nlohmann::json::object({ + { "command", "server-disconnect" } + }); + + if (args.size() > 0) + object["server"] = args[0]; + + check(request(irccdctl, object)); +} + +/* + * ServerInfoCli. + * ------------------------------------------------------------------ + */ + +ServerInfoCli::ServerInfoCli() + : Cli("server-info", + "get server information", + "server-info server", + "Get information about a server.\n\n" + "Example:\n" + "\tirccdctl server-info freenode") +{ +} + +void ServerInfoCli::exec(Irccdctl &irccdctl, const std::vector<std::string> &args) +{ + if (args.size() < 1) + throw std::invalid_argument("server-info requires 1 argument"); + + auto result = request(irccdctl, { + { "command", "server-info" }, + { "server", args[0] } + }); + + check(result); + + std::cout << std::boolalpha; + std::cout << "Name : " << util::json::pretty(result["name"]) << std::endl; + std::cout << "Host : " << util::json::pretty(result["host"]) << std::endl; + std::cout << "Port : " << util::json::pretty(result["port"]) << std::endl; + std::cout << "Ipv6 : " << util::json::pretty(result["ipv6"]) << std::endl; + std::cout << "SSL : " << util::json::pretty(result["ssl"]) << std::endl; + std::cout << "SSL verified : " << util::json::pretty(result["sslVerify"]) << std::endl; + std::cout << "Channels : "; + + for (const auto &v : result["channels"]) + if (v.is_string()) + std::cout << v.get<std::string>() << " "; + + std::cout << std::endl; + + std::cout << "Nickname : " << util::json::pretty(result["nickname"]) << std::endl; + std::cout << "User name : " << util::json::pretty(result["username"]) << std::endl; + std::cout << "Real name : " << util::json::pretty(result["realname"]) << std::endl; +} + +/* + * ServerInviteCli. + * ------------------------------------------------------------------ + */ + +ServerInviteCli::ServerInviteCli() + : Cli("server-invite", + "invite someone", + "server-invite server nickname channel", + "Invite the specified target on the channel.\n\n" + "Example:\n" + "\tirccdctl server-invite freenode xorg62 #staff") +{ +} + +void ServerInviteCli::exec(Irccdctl &irccdctl, const std::vector<std::string> &args) +{ + if (args.size() < 3) + throw std::invalid_argument("server-invite requires 3 arguments"); + + check(request(irccdctl, { + { "command", "server-invite" }, + { "server", args[0] }, + { "target", args[1] }, + { "channel", args[2] } + })); +} + +/* + * ServerJoinCli. + * ------------------------------------------------------------------ + */ + +ServerJoinCli::ServerJoinCli() + : Cli("server-join", + "join a channel", + "server-join server channel [password]", + "Join the specified channel, the password is optional.\n\n" + "Example:\n" + "\tirccdctl server-join freenode #test\n" + "\tirccdctl server-join freenode #private-club secret") +{ +} + +void ServerJoinCli::exec(Irccdctl &irccdctl, const std::vector<std::string> &args) +{ + if (args.size() < 2) + throw std::invalid_argument("server-join requires at least 2 arguments"); + + auto object = nlohmann::json::object({ + { "server", args[0] }, + { "channel", args[1] } + }); + + if (args.size() == 3) + object["password"] = args[2]; + + check(request(irccdctl, object)); +} + +/* + * ServerKickCli. + * ------------------------------------------------------------------ + */ + +ServerKickCli::ServerKickCli() + : Cli("server-kick", + "kick someone from a channel", + "server-kick server target channel [reason]", + "Kick the specified target from the channel, the reason is optional.\n\n" + "Example:\n" + "\tirccdctl server-kick freenode jean #staff \"Stop flooding\"") +{ +} + +void ServerKickCli::exec(Irccdctl &irccdctl, const std::vector<std::string> &args) +{ + if (args.size() < 3) + throw std::invalid_argument("server-kick requires at least 3 arguments "); + + auto object = nlohmann::json::object({ + { "server", args[0] }, + { "target", args[1] }, + { "channel", args[2] } + }); + + if (args.size() == 4) + object["reason"] = args[3]; + + check(request(irccdctl, object)); +} + +/* + * ServerListCli. + * ------------------------------------------------------------------ + */ + +ServerListCli::ServerListCli() + : Cli("server-list", + "get list of servers", + "server-list\n\n", + "Get the list of all connected servers.\n\n" + "Example:\n" + "\tirccdctl server-list") +{ +} + +void ServerListCli::exec(Irccdctl &irccdctl, const std::vector<std::string> &) +{ + auto response = request(irccdctl); + + check(response); + + for (const auto &n : response["list"]) + if (n.is_string()) + std::cout << n.get<std::string>() << std::endl; +} + +/* + * ServerMeCli. + * ------------------------------------------------------------------ + */ + +ServerMeCli::ServerMeCli() + : Cli("server-me", + "send an action emote", + "server-me server target message", + "Send an action emote.\n\n" + "Example:\n" + "\tirccdctl server-me freenode #staff \"going back soon\"") +{ +} + +void ServerMeCli::exec(Irccdctl &irccdctl, const std::vector<std::string> &args) +{ + if (args.size() < 3) + throw std::runtime_error("server-me requires 3 arguments"); + + check(request(irccdctl, { + { "server", args[0] }, + { "target", args[1] }, + { "message", args[2] } + })); +} + +/* + * ServerMessageCli. + * ------------------------------------------------------------------ + */ + +ServerMessageCli::ServerMessageCli() + : Cli("server-message", + "send a message", + "server-message server target message", + "Send a message to the specified target or channel.\n\n" + "Example:\n" + "\tirccdctl server-message freenode #staff \"Hello from irccd\"") +{ +} + +void ServerMessageCli::exec(Irccdctl &irccdctl, const std::vector<std::string> &args) +{ + if (args.size() < 3) + throw std::invalid_argument("server-message requires 3 arguments"); + + check(request(irccdctl, { + { "server", args[0] }, + { "target", args[1] }, + { "message", args[2] } + })); +} + +/* + * ServerModeCli. + * ------------------------------------------------------------------ + */ + +ServerModeCli::ServerModeCli() + : Cli("server-mode", + "the the user mode", + "server-mode server mode", + "Set the irccd's user mode.\n\n" + "Example:\n" + "\tirccdctl server-mode +i") +{ +} + +void ServerModeCli::exec(Irccdctl &irccdctl, const std::vector<std::string> &args) +{ + if (args.size() < 2) + throw std::invalid_argument("server-mode requires 2 arguments"); + + check(request(irccdctl, { + { "server", args[0] }, + { "mode", args[1] } + })); +} + +/* + * ServerNickCli. + * ------------------------------------------------------------------ + */ + +ServerNickCli::ServerNickCli() + : Cli("server-nick", + "change your nickname", + "server-nick server nickname", + "Change irccd's nickname.\n\n" + "Example:\n" + "\tirccdctl server-nick freenode david") +{ +} + +void ServerNickCli::exec(Irccdctl &irccdctl, const std::vector<std::string> &args) +{ + if (args.size() < 2) + throw std::invalid_argument("server-nick requires 2 arguments"); + + check(request(irccdctl, { + { "server", args[0] }, + { "nickname", args[1] } + })); +} + +/* + * ServerNoticeCli. + * ------------------------------------------------------------------ + */ + +ServerNoticeCli::ServerNoticeCli() + : Cli("server-notice", + "send a private notice", + "server-notice server target message", + "Send a private notice to the specified target.\n\n" + "Example:\n" + "\tirccdctl server-notice freenode jean \"I know you are here.\"") +{ +} + +void ServerNoticeCli::exec(Irccdctl &irccdctl, const std::vector<std::string> &args) +{ + if (args.size() < 3) + throw std::invalid_argument("server-notice requires 3 arguments"); + + check(request(irccdctl, { + { "server", args[0] }, + { "target", args[1] }, + { "message", args[2] } + })); +} + +/* + * ServerPartCli. + * ------------------------------------------------------------------ + */ + +ServerPartCli::ServerPartCli() + : Cli("server-part", + "leave a channel", + "server-part server channel [reason]", + "Leave the specified channel, the reason is optional.\n\n" + "Not all IRC servers support giving a reason to leave a channel, do not " + "specify it if this is a concern.\n\n" + "Example:\n" + "\tirccdctl server-part freenode #staff" + "\tirccdctl server-part freenode #botwar \"too noisy\"") +{ +} + +void ServerPartCli::exec(Irccdctl &irccdctl, const std::vector<std::string> &args) +{ + if (args.size() < 2) + throw std::invalid_argument("server-part requires at least 2 arguments"); + + auto object = nlohmann::json::object({ + { "server", args[0] }, + { "channel", args[1] } + }); + + if (args.size() >= 3) + object["reason"] = args[2]; + + check(request(irccdctl, object)); +} + +/* + * ServerReconnectCli. + * ------------------------------------------------------------------ + */ + +ServerReconnectCli::ServerReconnectCli() + : Cli("server-reconnect", + "force reconnection of a server", + "server-reconnect [server]", + "Force reconnection of one or all servers.\n\n" + "If server is not specified, all servers will try to reconnect.\n\n" + "Example:\n" + "\tirccdctl server-reconnect\n" + "\tirccdctl server-reconnect wanadoo") +{ +} + +void ServerReconnectCli::exec(Irccdctl &irccdctl, const std::vector<std::string> &args) +{ + auto object = nlohmann::json::object({ + { "command", "server-reconnect" } + }); + + if (args.size() >= 1) + object["server"] = args[0]; + + check(request(irccdctl, object)); +} + +} // !cli + } // !irccd