comparison irccdctl/cli.cpp @ 773:8c44bbcbbab9

Misc: style, cleanup and update
author David Demelier <markand@malikania.fr>
date Fri, 26 Oct 2018 13:01:00 +0200
parents 445c071e8efb
children 7145a3df4cb7
comparison
equal deleted inserted replaced
772:f5ccf65ae929 773:8c44bbcbbab9
26 26
27 #include <irccd/daemon/rule_service.hpp> 27 #include <irccd/daemon/rule_service.hpp>
28 28
29 #include "cli.hpp" 29 #include "cli.hpp"
30 30
31 using irccd::json_util::deserializer;
32
31 namespace irccd::ctl { 33 namespace irccd::ctl {
32 34
33 // {{{ helpers 35 // {{{ helpers
34 36
35 namespace { 37 namespace {
36 38
37 template <typename T> 39 template <typename T>
38 auto bind() noexcept -> cli::constructor 40 auto bind() noexcept -> cli::constructor
39 { 41 {
40 return [] () noexcept { 42 return [] () noexcept {
41 return std::make_unique<T>(); 43 return std::make_unique<T>();
42 }; 44 };
43 } 45 }
44 46
45 auto format(std::vector<std::string> args) -> std::string 47 auto format(std::vector<std::string> args) -> std::string
46 { 48 {
47 auto result = option::read(args, { 49 auto result = option::read(args, {
48 { "-f", true }, 50 { "-f", true },
49 { "--format", true } 51 { "--format", true }
50 }); 52 });
51 53
52 if (result.count("-f") > 0) 54 if (result.count("-f") > 0)
53 return result.find("-f")->second; 55 return result.find("-f")->second;
54 if (result.count("--format") > 0) 56 if (result.count("--format") > 0)
55 return result.find("--format")->second; 57 return result.find("--format")->second;
56 58
57 return "native"; 59 return "native";
58 } 60 }
59 61
60 void onConnect(const nlohmann::json &v) 62 void onConnect(const nlohmann::json &v)
61 { 63 {
62 std::cout << "event: onConnect\n"; 64 std::cout << "event: onConnect\n";
63 std::cout << "server: " << json_util::pretty(v.value("server", "(unknown)")) << "\n"; 65 std::cout << "server: " << json_util::pretty(v.value("server", "(unknown)")) << "\n";
64 } 66 }
65 67
66 void onInvite(const nlohmann::json &v) 68 void onInvite(const nlohmann::json &v)
67 { 69 {
68 std::cout << "event: onInvite\n"; 70 std::cout << "event: onInvite\n";
69 std::cout << "server: " << json_util::pretty(v.value("server", "(unknown)")) << "\n"; 71 std::cout << "server: " << json_util::pretty(v.value("server", "(unknown)")) << "\n";
70 std::cout << "origin: " << json_util::pretty(v.value("origin", "(unknown)")) << "\n"; 72 std::cout << "origin: " << json_util::pretty(v.value("origin", "(unknown)")) << "\n";
71 std::cout << "channel: " << json_util::pretty(v.value("channel", "(unknown)")) << "\n"; 73 std::cout << "channel: " << json_util::pretty(v.value("channel", "(unknown)")) << "\n";
72 } 74 }
73 75
74 void onJoin(const nlohmann::json &v) 76 void onJoin(const nlohmann::json &v)
75 { 77 {
76 std::cout << "event: onJoin\n"; 78 std::cout << "event: onJoin\n";
77 std::cout << "server: " << json_util::pretty(v.value("server", "(unknown)")) << "\n"; 79 std::cout << "server: " << json_util::pretty(v.value("server", "(unknown)")) << "\n";
78 std::cout << "origin: " << json_util::pretty(v.value("origin", "(unknown)")) << "\n"; 80 std::cout << "origin: " << json_util::pretty(v.value("origin", "(unknown)")) << "\n";
79 std::cout << "channel: " << json_util::pretty(v.value("channel", "(unknown)")) << "\n"; 81 std::cout << "channel: " << json_util::pretty(v.value("channel", "(unknown)")) << "\n";
80 } 82 }
81 83
82 void onKick(const nlohmann::json &v) 84 void onKick(const nlohmann::json &v)
83 { 85 {
84 std::cout << "event: onKick\n"; 86 std::cout << "event: onKick\n";
85 std::cout << "server: " << json_util::pretty(v.value("server", "(unknown)")) << "\n"; 87 std::cout << "server: " << json_util::pretty(v.value("server", "(unknown)")) << "\n";
86 std::cout << "origin: " << json_util::pretty(v.value("origin", "(unknown)")) << "\n"; 88 std::cout << "origin: " << json_util::pretty(v.value("origin", "(unknown)")) << "\n";
87 std::cout << "channel: " << json_util::pretty(v.value("channel", "(unknown)")) << "\n"; 89 std::cout << "channel: " << json_util::pretty(v.value("channel", "(unknown)")) << "\n";
88 std::cout << "target: " << json_util::pretty(v.value("target", "(unknown)")) << "\n"; 90 std::cout << "target: " << json_util::pretty(v.value("target", "(unknown)")) << "\n";
89 std::cout << "reason: " << json_util::pretty(v.value("reason", "(unknown)")) << "\n"; 91 std::cout << "reason: " << json_util::pretty(v.value("reason", "(unknown)")) << "\n";
90 } 92 }
91 93
92 void onMessage(const nlohmann::json &v) 94 void onMessage(const nlohmann::json &v)
93 { 95 {
94 std::cout << "event: onMessage\n"; 96 std::cout << "event: onMessage\n";
95 std::cout << "server: " << json_util::pretty(v.value("server", "(unknown)")) << "\n"; 97 std::cout << "server: " << json_util::pretty(v.value("server", "(unknown)")) << "\n";
96 std::cout << "origin: " << json_util::pretty(v.value("origin", "(unknown)")) << "\n"; 98 std::cout << "origin: " << json_util::pretty(v.value("origin", "(unknown)")) << "\n";
97 std::cout << "channel: " << json_util::pretty(v.value("channel", "(unknown)")) << "\n"; 99 std::cout << "channel: " << json_util::pretty(v.value("channel", "(unknown)")) << "\n";
98 std::cout << "message: " << json_util::pretty(v.value("message", "(unknown)")) << "\n"; 100 std::cout << "message: " << json_util::pretty(v.value("message", "(unknown)")) << "\n";
99 } 101 }
100 102
101 void onMe(const nlohmann::json &v) 103 void onMe(const nlohmann::json &v)
102 { 104 {
103 std::cout << "event: onMe\n"; 105 std::cout << "event: onMe\n";
104 std::cout << "server: " << json_util::pretty(v.value("server", "(unknown)")) << "\n"; 106 std::cout << "server: " << json_util::pretty(v.value("server", "(unknown)")) << "\n";
105 std::cout << "origin: " << json_util::pretty(v.value("origin", "(unknown)")) << "\n"; 107 std::cout << "origin: " << json_util::pretty(v.value("origin", "(unknown)")) << "\n";
106 std::cout << "target: " << json_util::pretty(v.value("target", "(unknown)")) << "\n"; 108 std::cout << "target: " << json_util::pretty(v.value("target", "(unknown)")) << "\n";
107 std::cout << "message: " << json_util::pretty(v.value("message", "(unknown)")) << "\n"; 109 std::cout << "message: " << json_util::pretty(v.value("message", "(unknown)")) << "\n";
108 } 110 }
109 111
110 void onMode(const nlohmann::json &v) 112 void onMode(const nlohmann::json &v)
111 { 113 {
112 std::cout << "event: onMode\n"; 114 std::cout << "event: onMode\n";
113 std::cout << "server: " << json_util::pretty(v.value("server", "(unknown)")) << "\n"; 115 std::cout << "server: " << json_util::pretty(v.value("server", "(unknown)")) << "\n";
114 std::cout << "origin: " << json_util::pretty(v.value("origin", "(unknown)")) << "\n"; 116 std::cout << "origin: " << json_util::pretty(v.value("origin", "(unknown)")) << "\n";
115 std::cout << "mode: " << json_util::pretty(v.value("mode", "(unknown)")) << "\n"; 117 std::cout << "mode: " << json_util::pretty(v.value("mode", "(unknown)")) << "\n";
116 } 118 }
117 119
118 void onNames(const nlohmann::json &v) 120 void onNames(const nlohmann::json &v)
119 { 121 {
120 std::cout << "event: onNames\n"; 122 std::cout << "event: onNames\n";
121 std::cout << "server: " << json_util::pretty(v.value("server", "(unknown)")) << "\n"; 123 std::cout << "server: " << json_util::pretty(v.value("server", "(unknown)")) << "\n";
122 std::cout << "channel: " << json_util::pretty(v.value("channel", "(unknown)")) << "\n"; 124 std::cout << "channel: " << json_util::pretty(v.value("channel", "(unknown)")) << "\n";
123 std::cout << "names: " << json_util::pretty(v.value("names", "(unknown)")) << "\n"; 125 std::cout << "names: " << json_util::pretty(v.value("names", "(unknown)")) << "\n";
124 } 126 }
125 127
126 void onNick(const nlohmann::json &v) 128 void onNick(const nlohmann::json &v)
127 { 129 {
128 std::cout << "event: onNick\n"; 130 std::cout << "event: onNick\n";
129 std::cout << "server: " << json_util::pretty(v.value("server", "(unknown)")) << "\n"; 131 std::cout << "server: " << json_util::pretty(v.value("server", "(unknown)")) << "\n";
130 std::cout << "origin: " << json_util::pretty(v.value("origin", "(unknown)")) << "\n"; 132 std::cout << "origin: " << json_util::pretty(v.value("origin", "(unknown)")) << "\n";
131 std::cout << "nickname: " << json_util::pretty(v.value("nickname", "(unknown)")) << "\n"; 133 std::cout << "nickname: " << json_util::pretty(v.value("nickname", "(unknown)")) << "\n";
132 } 134 }
133 135
134 void onNotice(const nlohmann::json &v) 136 void onNotice(const nlohmann::json &v)
135 { 137 {
136 std::cout << "event: onNotice\n"; 138 std::cout << "event: onNotice\n";
137 std::cout << "server: " << json_util::pretty(v.value("server", "(unknown)")) << "\n"; 139 std::cout << "server: " << json_util::pretty(v.value("server", "(unknown)")) << "\n";
138 std::cout << "origin: " << json_util::pretty(v.value("origin", "(unknown)")) << "\n"; 140 std::cout << "origin: " << json_util::pretty(v.value("origin", "(unknown)")) << "\n";
139 std::cout << "message: " << json_util::pretty(v.value("message", "(unknown)")) << "\n"; 141 std::cout << "message: " << json_util::pretty(v.value("message", "(unknown)")) << "\n";
140 } 142 }
141 143
142 void onPart(const nlohmann::json &v) 144 void onPart(const nlohmann::json &v)
143 { 145 {
144 std::cout << "event: onPart\n"; 146 std::cout << "event: onPart\n";
145 std::cout << "server: " << json_util::pretty(v.value("server", "(unknown)")) << "\n"; 147 std::cout << "server: " << json_util::pretty(v.value("server", "(unknown)")) << "\n";
146 std::cout << "origin: " << json_util::pretty(v.value("origin", "(unknown)")) << "\n"; 148 std::cout << "origin: " << json_util::pretty(v.value("origin", "(unknown)")) << "\n";
147 std::cout << "channel: " << json_util::pretty(v.value("channel", "(unknown)")) << "\n"; 149 std::cout << "channel: " << json_util::pretty(v.value("channel", "(unknown)")) << "\n";
148 std::cout << "reason: " << json_util::pretty(v.value("reason", "(unknown)")) << "\n"; 150 std::cout << "reason: " << json_util::pretty(v.value("reason", "(unknown)")) << "\n";
149 } 151 }
150 152
151 void onTopic(const nlohmann::json &v) 153 void onTopic(const nlohmann::json &v)
152 { 154 {
153 std::cout << "event: onTopic\n"; 155 std::cout << "event: onTopic\n";
154 std::cout << "server: " << json_util::pretty(v.value("server", "(unknown)")) << "\n"; 156 std::cout << "server: " << json_util::pretty(v.value("server", "(unknown)")) << "\n";
155 std::cout << "origin: " << json_util::pretty(v.value("origin", "(unknown)")) << "\n"; 157 std::cout << "origin: " << json_util::pretty(v.value("origin", "(unknown)")) << "\n";
156 std::cout << "channel: " << json_util::pretty(v.value("channel", "(unknown)")) << "\n"; 158 std::cout << "channel: " << json_util::pretty(v.value("channel", "(unknown)")) << "\n";
157 std::cout << "topic: " << json_util::pretty(v.value("topic", "(unknown)")) << "\n"; 159 std::cout << "topic: " << json_util::pretty(v.value("topic", "(unknown)")) << "\n";
158 } 160 }
159 161
160 void onWhois(const nlohmann::json &v) 162 void onWhois(const nlohmann::json &v)
161 { 163 {
162 std::cout << "event: onWhois\n"; 164 std::cout << "event: onWhois\n";
163 std::cout << "server: " << json_util::pretty(v.value("server", "(unknown)")) << "\n"; 165 std::cout << "server: " << json_util::pretty(v.value("server", "(unknown)")) << "\n";
164 std::cout << "nickname: " << json_util::pretty(v.value("nickname", "(unknown)")) << "\n"; 166 std::cout << "nickname: " << json_util::pretty(v.value("nickname", "(unknown)")) << "\n";
165 std::cout << "username: " << json_util::pretty(v.value("username", "(unknown)")) << "\n"; 167 std::cout << "username: " << json_util::pretty(v.value("username", "(unknown)")) << "\n";
166 std::cout << "host: " << json_util::pretty(v.value("host", "(unknown)")) << "\n"; 168 std::cout << "host: " << json_util::pretty(v.value("host", "(unknown)")) << "\n";
167 std::cout << "realname: " << json_util::pretty(v.value("realname", "(unknown)")) << "\n"; 169 std::cout << "realname: " << json_util::pretty(v.value("realname", "(unknown)")) << "\n";
168 } 170 }
169 171
170 const std::unordered_map<std::string_view, std::function<void (const nlohmann::json&)>> events{ 172 const std::unordered_map<std::string_view, std::function<void (const nlohmann::json&)>> events{
171 { "onConnect", onConnect }, 173 { "onConnect", onConnect },
172 { "onInvite", onInvite }, 174 { "onInvite", onInvite },
173 { "onJoin", onJoin }, 175 { "onJoin", onJoin },
174 { "onKick", onKick }, 176 { "onKick", onKick },
175 { "onMessage", onMessage }, 177 { "onMessage", onMessage },
176 { "onMe", onMe }, 178 { "onMe", onMe },
177 { "onMode", onMode }, 179 { "onMode", onMode },
178 { "onNames", onNames }, 180 { "onNames", onNames },
179 { "onNick", onNick }, 181 { "onNick", onNick },
180 { "onNotice", onNotice }, 182 { "onNotice", onNotice },
181 { "onPart", onPart }, 183 { "onPart", onPart },
182 { "onTopic", onTopic }, 184 { "onTopic", onTopic },
183 { "onWhois", onWhois } 185 { "onWhois", onWhois }
184 }; 186 };
185 187
186 void get_event(ctl::controller& ctl, std::string fmt) 188 void get_event(ctl::controller& ctl, std::string fmt)
187 { 189 {
188 ctl.read([&ctl, fmt] (auto code, auto message) { 190 ctl.read([&ctl, fmt] (auto code, auto message) {
189 if (code) 191 if (code)
190 throw std::system_error(code); 192 throw std::system_error(code);
191 193
192 const auto event = json_util::document(message).get<std::string>("event"); 194 const auto event = deserializer(message).get<std::string>("event");
193 const auto it = events.find(event ? *event : ""); 195 const auto it = events.find(event ? *event : "");
194 196
195 if (it != events.end()) { 197 if (it != events.end()) {
196 if (fmt == "json") 198 if (fmt == "json")
197 std::cout << message.dump(4) << std::endl; 199 std::cout << message.dump(4) << std::endl;
198 else { 200 else {
199 it->second(message); 201 it->second(message);
200 std::cout << std::endl; 202 std::cout << std::endl;
201 } 203 }
202 } 204 }
203 205
204 get_event(ctl, std::move(fmt)); 206 get_event(ctl, std::move(fmt));
205 }); 207 });
206 } 208 }
207 209
208 auto parse(std::vector<std::string> &args) -> option::result 210 auto parse(std::vector<std::string> &args) -> option::result
209 { 211 {
210 option::options options{ 212 option::options options{
211 { "-c", true }, 213 { "-c", true },
212 { "--command", true }, 214 { "--command", true },
213 { "-n", true }, 215 { "-n", true },
214 { "--nickname", true }, 216 { "--nickname", true },
215 { "-r", true }, 217 { "-r", true },
216 { "--realname", true }, 218 { "--realname", true },
217 { "-S", false }, 219 { "-S", false },
218 { "--ssl-verify", false }, 220 { "--ssl-verify", false },
219 { "-s", false }, 221 { "-s", false },
220 { "--ssl", false }, 222 { "--ssl", false },
221 { "-u", true }, 223 { "-u", true },
222 { "--username", true } 224 { "--username", true }
223 }; 225 };
224 226
225 return option::read(args, options); 227 return option::read(args, options);
226 } 228 }
227 229
228 } // !namespace 230 } // !namespace
229 231
230 // }}} 232 // }}}
231 233
232 // {{{ cli 234 // {{{ cli
233 235
234 const std::vector<cli::constructor> cli::registry{ 236 const std::vector<cli::constructor> cli::registry{
235 bind<plugin_config_cli>(), 237 bind<plugin_config_cli>(),
236 bind<plugin_info_cli>(), 238 bind<plugin_info_cli>(),
237 bind<plugin_list_cli>(), 239 bind<plugin_list_cli>(),
238 bind<plugin_load_cli>(), 240 bind<plugin_load_cli>(),
239 bind<plugin_reload_cli>(), 241 bind<plugin_reload_cli>(),
240 bind<plugin_unload_cli>(), 242 bind<plugin_unload_cli>(),
241 bind<rule_add_cli>(), 243 bind<rule_add_cli>(),
242 bind<rule_edit_cli>(), 244 bind<rule_edit_cli>(),
243 bind<rule_info_cli>(), 245 bind<rule_info_cli>(),
244 bind<rule_info_cli>(), 246 bind<rule_list_cli>(),
245 bind<rule_list_cli>(), 247 bind<rule_move_cli>(),
246 bind<rule_move_cli>(), 248 bind<rule_remove_cli>(),
247 bind<rule_remove_cli>(), 249 bind<server_connect_cli>(),
248 bind<server_connect_cli>(), 250 bind<server_disconnect_cli>(),
249 bind<server_disconnect_cli>(), 251 bind<server_info_cli>(),
250 bind<server_info_cli>(), 252 bind<server_invite_cli>(),
251 bind<server_invite_cli>(), 253 bind<server_join_cli>(),
252 bind<server_join_cli>(), 254 bind<server_kick_cli>(),
253 bind<server_kick_cli>(), 255 bind<server_list_cli>(),
254 bind<server_list_cli>(), 256 bind<server_me_cli>(),
255 bind<server_me_cli>(), 257 bind<server_message_cli>(),
256 bind<server_message_cli>(), 258 bind<server_mode_cli>(),
257 bind<server_mode_cli>(), 259 bind<server_nick_cli>(),
258 bind<server_nick_cli>(), 260 bind<server_notice_cli>(),
259 bind<server_notice_cli>(), 261 bind<server_part_cli>(),
260 bind<server_part_cli>(), 262 bind<server_reconnect_cli>(),
261 bind<server_reconnect_cli>(), 263 bind<server_topic_cli>(),
262 bind<server_topic_cli>(), 264 bind<watch_cli>()
263 bind<watch_cli>()
264 }; 265 };
265 266
266 void cli::recv_response(ctl::controller& ctl, nlohmann::json req, handler_t handler) 267 void cli::recv_response(ctl::controller& ctl, nlohmann::json req, handler_t handler)
267 { 268 {
268 ctl.read([&ctl, req, handler, this] (auto code, auto message) { 269 ctl.read([&ctl, req, handler, this] (auto code, auto message) {
269 if (code) 270 if (code)
270 throw std::system_error(code); 271 throw std::system_error(code);
271 272
272 const auto c = json_util::document(message).get<std::string>("command"); 273 const auto c = deserializer(message).get<std::string>("command");
273 274
274 if (!c) { 275 if (!c) {
275 recv_response(ctl, std::move(req), std::move(handler)); 276 recv_response(ctl, std::move(req), std::move(handler));
276 return; 277 return;
277 } 278 }
278 279
279 if (handler) 280 if (handler)
280 handler(std::move(message)); 281 handler(std::move(message));
281 }); 282 });
282 } 283 }
283 284
284 void cli::request(ctl::controller& ctl, nlohmann::json req, handler_t handler) 285 void cli::request(ctl::controller& ctl, nlohmann::json req, handler_t handler)
285 { 286 {
286 ctl.write(req, [&ctl, req, handler, this] (auto code) { 287 ctl.write(req, [&ctl, req, handler, this] (auto code) {
287 if (code) 288 if (code)
288 throw std::system_error(code); 289 throw std::system_error(code);
289 290
290 recv_response(ctl, std::move(req), std::move(handler)); 291 recv_response(ctl, std::move(req), std::move(handler));
291 }); 292 });
292 } 293 }
293 294
294 // }}} 295 // }}}
295 296
296 // {{{ plugin_config_cli 297 // {{{ plugin_config_cli
297 298
298 void plugin_config_cli::set(ctl::controller& ctl, const std::vector<std::string>&args) 299 void plugin_config_cli::set(ctl::controller& ctl, const std::vector<std::string>&args)
299 { 300 {
300 request(ctl, { 301 request(ctl, {
301 { "command", "plugin-config" }, 302 { "command", "plugin-config" },
302 { "plugin", args[0] }, 303 { "plugin", args[0] },
303 { "variable", args[1] }, 304 { "variable", args[1] },
304 { "value", args[2] } 305 { "value", args[2] }
305 }); 306 });
306 } 307 }
307 308
308 void plugin_config_cli::get(ctl::controller& ctl, const std::vector<std::string>& args) 309 void plugin_config_cli::get(ctl::controller& ctl, const std::vector<std::string>& args)
309 { 310 {
310 auto json = nlohmann::json::object({ 311 auto json = nlohmann::json::object({
311 { "command", "plugin-config" }, 312 { "command", "plugin-config" },
312 { "plugin", args[0] }, 313 { "plugin", args[0] },
313 { "variable", args[1] } 314 { "variable", args[1] }
314 }); 315 });
315 316
316 request(ctl, std::move(json), [args] (auto result) { 317 request(ctl, std::move(json), [args] (auto result) {
317 if (result["variables"].is_object()) 318 if (result["variables"].is_object())
318 std::cout << json_util::pretty(result["variables"][args[1]]) << std::endl; 319 std::cout << json_util::pretty(result["variables"][args[1]]) << std::endl;
319 }); 320 });
320 } 321 }
321 322
322 void plugin_config_cli::getall(ctl::controller& ctl, const std::vector<std::string> &args) 323 void plugin_config_cli::getall(ctl::controller& ctl, const std::vector<std::string> &args)
323 { 324 {
324 const auto json = nlohmann::json::object({ 325 const auto json = nlohmann::json::object({
325 { "command", "plugin-config" }, 326 { "command", "plugin-config" },
326 { "plugin", args[0] } 327 { "plugin", args[0] }
327 }); 328 });
328 329
329 request(ctl, json, [] (auto result) { 330 request(ctl, json, [] (auto result) {
330 const auto variables = result["variables"]; 331 const auto variables = result["variables"];
331 332
332 for (auto v = variables.begin(); v != variables.end(); ++v) 333 for (auto v = variables.begin(); v != variables.end(); ++v)
333 std::cout << std::setw(16) << std::left << v.key() << " : " << json_util::pretty(v.value()) << std::endl; 334 std::cout << std::setw(16) << std::left << v.key() << " : " << json_util::pretty(v.value()) << std::endl;
334 }); 335 });
335 } 336 }
336 337
337 auto plugin_config_cli::get_name() const noexcept -> std::string_view 338 auto plugin_config_cli::get_name() const noexcept -> std::string_view
338 { 339 {
339 return "plugin-config"; 340 return "plugin-config";
340 } 341 }
341 342
342 void plugin_config_cli::exec(ctl::controller& ctl, const std::vector<std::string> &args) 343 void plugin_config_cli::exec(ctl::controller& ctl, const std::vector<std::string> &args)
343 { 344 {
344 switch (args.size()) { 345 switch (args.size()) {
345 case 3: 346 case 3:
346 set(ctl, args); 347 set(ctl, args);
347 break; 348 break;
348 case 2: 349 case 2:
349 get(ctl, args); 350 get(ctl, args);
350 break; 351 break;
351 case 1: 352 case 1:
352 getall(ctl, args); 353 getall(ctl, args);
353 break; 354 break;
354 default: 355 default:
355 throw std::invalid_argument("plugin-config requires at least 1 argument"); 356 throw std::invalid_argument("plugin-config requires at least 1 argument");
356 } 357 }
357 } 358 }
358 359
359 // }}} 360 // }}}
360 361
361 // {{{ plugin_info_cli 362 // {{{ plugin_info_cli
362 363
363 auto plugin_info_cli::get_name() const noexcept -> std::string_view 364 auto plugin_info_cli::get_name() const noexcept -> std::string_view
364 { 365 {
365 return "plugin-info"; 366 return "plugin-info";
366 } 367 }
367 368
368 void plugin_info_cli::exec(ctl::controller& ctl, const std::vector<std::string>& args) 369 void plugin_info_cli::exec(ctl::controller& ctl, const std::vector<std::string>& args)
369 { 370 {
370 if (args.size() < 1) 371 if (args.size() < 1)
371 throw std::invalid_argument("plugin-info requires 1 argument"); 372 throw std::invalid_argument("plugin-info requires 1 argument");
372 373
373 const auto json = nlohmann::json::object({ 374 const auto json = nlohmann::json::object({
374 { "command", "plugin-info" }, 375 { "command", "plugin-info" },
375 { "plugin", args[0] } 376 { "plugin", args[0] }
376 }); 377 });
377 378
378 request(ctl, json, [] (auto result) { 379 request(ctl, json, [] (auto result) {
379 const json_util::document doc(result); 380 const deserializer doc(result);
380 381
381 std::cout << std::boolalpha; 382 std::cout << std::boolalpha;
382 std::cout << "Author : " << 383 std::cout << "Author : "
383 doc.get<std::string>("author").value_or("(unknown)") << std::endl; 384 << doc.get<std::string>("author").value_or("(unknown)") << std::endl;
384 std::cout << "License : " << 385 std::cout << "License : "
385 doc.get<std::string>("license").value_or("(unknown)") << std::endl; 386 << doc.get<std::string>("license").value_or("(unknown)") << std::endl;
386 std::cout << "Summary : " << 387 std::cout << "Summary : "
387 doc.get<std::string>("summary").value_or("(unknown)") << std::endl; 388 << doc.get<std::string>("summary").value_or("(unknown)") << std::endl;
388 std::cout << "Version : " << 389 std::cout << "Version : "
389 doc.get<std::string>("version").value_or("(unknown)") << std::endl; 390 << doc.get<std::string>("version").value_or("(unknown)") << std::endl;
390 }); 391 });
391 } 392 }
392 393
393 // }}} 394 // }}}
394 395
395 // {{{ plugin_list_cli 396 // {{{ plugin_list_cli
396 397
397 auto plugin_list_cli::get_name() const noexcept -> std::string_view 398 auto plugin_list_cli::get_name() const noexcept -> std::string_view
398 { 399 {
399 return "plugin-list"; 400 return "plugin-list";
400 } 401 }
401 402
402 void plugin_list_cli::exec(ctl::controller& ctl, const std::vector<std::string>&) 403 void plugin_list_cli::exec(ctl::controller& ctl, const std::vector<std::string>&)
403 { 404 {
404 request(ctl, {{ "command", "plugin-list" }}, [] (auto result) { 405 request(ctl, {{ "command", "plugin-list" }}, [] (auto result) {
405 for (const auto& value : result["list"]) 406 for (const auto& value : result["list"])
406 if (value.is_string()) 407 if (value.is_string())
407 std::cout << value.template get<std::string>() << std::endl; 408 std::cout << value.template get<std::string>() << std::endl;
408 }); 409 });
409 } 410 }
410 411
411 // }}} 412 // }}}
412 413
413 // {{{ plugin_load_cli 414 // {{{ plugin_load_cli
414 415
415 auto plugin_load_cli::get_name() const noexcept -> std::string_view 416 auto plugin_load_cli::get_name() const noexcept -> std::string_view
416 { 417 {
417 return "plugin-load"; 418 return "plugin-load";
418 } 419 }
419 420
420 void plugin_load_cli::exec(ctl::controller& ctl, const std::vector<std::string> &args) 421 void plugin_load_cli::exec(ctl::controller& ctl, const std::vector<std::string> &args)
421 { 422 {
422 if (args.size() < 1) 423 if (args.size() < 1)
423 throw std::invalid_argument("plugin-load requires 1 argument"); 424 throw std::invalid_argument("plugin-load requires 1 argument");
424 425
425 request(ctl, { 426 request(ctl, {
426 { "command", "plugin-load" }, 427 { "command", "plugin-load" },
427 { "plugin", args[0] } 428 { "plugin", args[0] }
428 }); 429 });
429 } 430 }
430 431
431 // }}} 432 // }}}
432 433
433 // {{{ plugin_reload_cli 434 // {{{ plugin_reload_cli
434 435
435 auto plugin_reload_cli::get_name() const noexcept -> std::string_view 436 auto plugin_reload_cli::get_name() const noexcept -> std::string_view
436 { 437 {
437 return "plugin-reload"; 438 return "plugin-reload";
438 } 439 }
439 440
440 void plugin_reload_cli::exec(ctl::controller& ctl, const std::vector<std::string>& args) 441 void plugin_reload_cli::exec(ctl::controller& ctl, const std::vector<std::string>& args)
441 { 442 {
442 if (args.size() < 1) 443 if (args.size() < 1)
443 throw std::invalid_argument("plugin-reload requires 1 argument"); 444 throw std::invalid_argument("plugin-reload requires 1 argument");
444 445
445 request(ctl, { 446 request(ctl, {
446 { "command", "plugin-reload" }, 447 { "command", "plugin-reload" },
447 { "plugin", args[0] } 448 { "plugin", args[0] }
448 }); 449 });
449 } 450 }
450 451
451 // }}} 452 // }}}
452 453
453 // {{{ plugin_unload_cli 454 // {{{ plugin_unload_cli
454 455
455 auto plugin_unload_cli::get_name() const noexcept -> std::string_view 456 auto plugin_unload_cli::get_name() const noexcept -> std::string_view
456 { 457 {
457 return "plugin-unload"; 458 return "plugin-unload";
458 } 459 }
459 460
460 void plugin_unload_cli::exec(ctl::controller& ctl, const std::vector<std::string>& args) 461 void plugin_unload_cli::exec(ctl::controller& ctl, const std::vector<std::string>& args)
461 { 462 {
462 if (args.size() < 1) 463 if (args.size() < 1)
463 throw std::invalid_argument("plugin-unload requires 1 argument"); 464 throw std::invalid_argument("plugin-unload requires 1 argument");
464 465
465 request(ctl, { 466 request(ctl, {
466 { "command", "plugin-unload" }, 467 { "command", "plugin-unload" },
467 { "plugin", args[0] } 468 { "plugin", args[0] }
468 }); 469 });
469 } 470 }
470 471
471 // }}} 472 // }}}
472 473
473 // {{{ rule_add_cli 474 // {{{ rule_add_cli
474 475
475 auto rule_add_cli::get_name() const noexcept -> std::string_view 476 auto rule_add_cli::get_name() const noexcept -> std::string_view
476 { 477 {
477 return "rule-add"; 478 return "rule-add";
478 } 479 }
479 480
480 void rule_add_cli::exec(ctl::controller& ctl, const std::vector<std::string>& args) 481 void rule_add_cli::exec(ctl::controller& ctl, const std::vector<std::string>& args)
481 { 482 {
482 static const option::options options{ 483 static const option::options options{
483 { "-c", true }, 484 { "-c", true },
484 { "--add-channel", true }, 485 { "--add-channel", true },
485 { "-e", true }, 486 { "-e", true },
486 { "--add-event", true }, 487 { "--add-event", true },
487 { "-i", true }, 488 { "-i", true },
488 { "--index", true }, 489 { "--index", true },
489 { "-p", true }, 490 { "-p", true },
490 { "--add-plugin", true }, 491 { "--add-plugin", true },
491 { "-s", true }, 492 { "-s", true },
492 { "--add-server", true } 493 { "--add-server", true }
493 }; 494 };
494 495
495 auto copy = args; 496 auto copy = args;
496 auto result = option::read(copy, options); 497 auto result = option::read(copy, options);
497 498
498 if (copy.size() < 1) 499 if (copy.size() < 1)
499 throw std::invalid_argument("rule-add requires at least 1 argument"); 500 throw std::invalid_argument("rule-add requires at least 1 argument");
500 501
501 auto json = nlohmann::json::object({ 502 auto json = nlohmann::json::object({
502 { "command", "rule-add" }, 503 { "command", "rule-add" },
503 { "channels", nlohmann::json::array() }, 504 { "channels", nlohmann::json::array() },
504 { "events", nlohmann::json::array() }, 505 { "events", nlohmann::json::array() },
505 { "plugins", nlohmann::json::array() }, 506 { "plugins", nlohmann::json::array() },
506 { "servers", nlohmann::json::array() } 507 { "servers", nlohmann::json::array() }
507 }); 508 });
508 509
509 // All sets. 510 // All sets.
510 for (const auto& pair : result) { 511 for (const auto& pair : result) {
511 if (pair.first == "-c" || pair.first == "--add-channel") 512 if (pair.first == "-c" || pair.first == "--add-channel")
512 json["channels"].push_back(pair.second); 513 json["channels"].push_back(pair.second);
513 if (pair.first == "-e" || pair.first == "--add-event") 514 if (pair.first == "-e" || pair.first == "--add-event")
514 json["events"].push_back(pair.second); 515 json["events"].push_back(pair.second);
515 if (pair.first == "-p" || pair.first == "--add-plugin") 516 if (pair.first == "-p" || pair.first == "--add-plugin")
516 json["plugins"].push_back(pair.second); 517 json["plugins"].push_back(pair.second);
517 if (pair.first == "-s" || pair.first == "--add-server") 518 if (pair.first == "-s" || pair.first == "--add-server")
518 json["servers"].push_back(pair.second); 519 json["servers"].push_back(pair.second);
519 } 520 }
520 521
521 // Index. 522 // Index.
522 std::optional<unsigned> index; 523 std::optional<unsigned> index;
523 524
524 if (result.count("-i") > 0 && !(index = string_util::to_uint(result.find("-i")->second))) 525 if (result.count("-i") > 0 && !(index = string_util::to_uint(result.find("-i")->second)))
525 throw std::invalid_argument("invalid index argument"); 526 throw std::invalid_argument("invalid index argument");
526 if (result.count("--index") > 0 && !(index = string_util::to_uint(result.find("--index")->second))) 527 if (result.count("--index") > 0 && !(index = string_util::to_uint(result.find("--index")->second)))
527 throw std::invalid_argument("invalid index argument"); 528 throw std::invalid_argument("invalid index argument");
528 529
529 if (index) 530 if (index)
530 json["index"] = *index; 531 json["index"] = *index;
531 532
532 json["action"] = copy[0]; 533 json["action"] = copy[0];
533 534
534 request(ctl, json); 535 request(ctl, json);
535 } 536 }
536 537
537 // }}} 538 // }}}
538 539
539 // {{{ rule_edit_cli 540 // {{{ rule_edit_cli
540 541
541 auto rule_edit_cli::get_name() const noexcept -> std::string_view 542 auto rule_edit_cli::get_name() const noexcept -> std::string_view
542 { 543 {
543 return "rule-edit"; 544 return "rule-edit";
544 } 545 }
545 546
546 void rule_edit_cli::exec(ctl::controller& ctl, const std::vector<std::string>& args) 547 void rule_edit_cli::exec(ctl::controller& ctl, const std::vector<std::string>& args)
547 { 548 {
548 static const option::options options{ 549 static const option::options options{
549 { "-a", true }, 550 { "-a", true },
550 { "--action", true }, 551 { "--action", true },
551 { "-c", true }, 552 { "-c", true },
552 { "--add-channel", true }, 553 { "--add-channel", true },
553 { "-C", true }, 554 { "-C", true },
554 { "--remove-channel", true }, 555 { "--remove-channel", true },
555 { "-e", true }, 556 { "-e", true },
556 { "--add-event", true }, 557 { "--add-event", true },
557 { "-E", true }, 558 { "-E", true },
558 { "--remove-event", true }, 559 { "--remove-event", true },
559 { "-p", true }, 560 { "-p", true },
560 { "--add-plugin", true }, 561 { "--add-plugin", true },
561 { "-P", true }, 562 { "-P", true },
562 { "--remove-plugin", true }, 563 { "--remove-plugin", true },
563 { "-s", true }, 564 { "-s", true },
564 { "--add-server", true }, 565 { "--add-server", true },
565 { "-S", true }, 566 { "-S", true },
566 { "--remove-server", true }, 567 { "--remove-server", true },
567 }; 568 };
568 569
569 auto copy = args; 570 auto copy = args;
570 auto result = option::read(copy, options); 571 auto result = option::read(copy, options);
571 572
572 if (copy.size() < 1) 573 if (copy.size() < 1)
573 throw std::invalid_argument("rule-edit requires at least 1 argument"); 574 throw std::invalid_argument("rule-edit requires at least 1 argument");
574 575
575 auto json = nlohmann::json::object({ 576 auto json = nlohmann::json::object({
576 { "command", "rule-edit" }, 577 { "command", "rule-edit" },
577 { "channels", nlohmann::json::array() }, 578 { "channels", nlohmann::json::array() },
578 { "events", nlohmann::json::array() }, 579 { "events", nlohmann::json::array() },
579 { "plugins", nlohmann::json::array() }, 580 { "plugins", nlohmann::json::array() },
580 { "servers", nlohmann::json::array() } 581 { "servers", nlohmann::json::array() }
581 }); 582 });
582 583
583 for (const auto& pair : result) { 584 for (const auto& pair : result) {
584 // Action. 585 // Action.
585 if (pair.first == "-a" || pair.first == "--action") 586 if (pair.first == "-a" || pair.first == "--action")
586 json["action"] = pair.second; 587 json["action"] = pair.second;
587 588
588 // Additions. 589 // Additions.
589 if (pair.first == "-c" || pair.first == "--add-channel") 590 if (pair.first == "-c" || pair.first == "--add-channel")
590 json["add-channels"].push_back(pair.second); 591 json["add-channels"].push_back(pair.second);
591 if (pair.first == "-e" || pair.first == "--add-event") 592 if (pair.first == "-e" || pair.first == "--add-event")
592 json["add-events"].push_back(pair.second); 593 json["add-events"].push_back(pair.second);
593 if (pair.first == "-p" || pair.first == "--add-plugin") 594 if (pair.first == "-p" || pair.first == "--add-plugin")
594 json["add-plugins"].push_back(pair.second); 595 json["add-plugins"].push_back(pair.second);
595 if (pair.first == "-s" || pair.first == "--add-server") 596 if (pair.first == "-s" || pair.first == "--add-server")
596 json["add-servers"].push_back(pair.second); 597 json["add-servers"].push_back(pair.second);
597 598
598 // Removals. 599 // Removals.
599 if (pair.first == "-C" || pair.first == "--remove-channel") 600 if (pair.first == "-C" || pair.first == "--remove-channel")
600 json["remove-channels"].push_back(pair.second); 601 json["remove-channels"].push_back(pair.second);
601 if (pair.first == "-E" || pair.first == "--remove-event") 602 if (pair.first == "-E" || pair.first == "--remove-event")
602 json["remove-events"].push_back(pair.second); 603 json["remove-events"].push_back(pair.second);
603 if (pair.first == "-P" || pair.first == "--remove-plugin") 604 if (pair.first == "-P" || pair.first == "--remove-plugin")
604 json["remove-plugins"].push_back(pair.second); 605 json["remove-plugins"].push_back(pair.second);
605 if (pair.first == "-S" || pair.first == "--remove-server") 606 if (pair.first == "-S" || pair.first == "--remove-server")
606 json["remove-servers"].push_back(pair.second); 607 json["remove-servers"].push_back(pair.second);
607 } 608 }
608 609
609 // Index. 610 // Index.
610 const auto index = string_util::to_uint(copy[0]); 611 const auto index = string_util::to_uint(copy[0]);
611 612
612 if (!index) 613 if (!index)
613 throw rule_error(rule_error::invalid_index); 614 throw rule_error(rule_error::invalid_index);
614 615
615 json["index"] = *index; 616 json["index"] = *index;
616 617
617 request(ctl, json); 618 request(ctl, json);
618 } 619 }
619 620
620 // }}} 621 // }}}
621 622
622 // {{{ rule_info_cli 623 // {{{ rule_info_cli
623 624
624 void rule_info_cli::print(const nlohmann::json& json, int index) 625 void rule_info_cli::print(const nlohmann::json& json, int index)
625 { 626 {
626 assert(json.is_object()); 627 assert(json.is_object());
627 628
628 const auto unjoin = [] (auto array) { 629 const auto unjoin = [] (auto array) {
629 std::ostringstream oss; 630 std::ostringstream oss;
630 631
631 for (auto it = array.begin(); it != array.end(); ++it) { 632 for (auto it = array.begin(); it != array.end(); ++it) {
632 if (!it->is_string()) 633 if (!it->is_string())
633 continue; 634 continue;
634 635
635 oss << it->template get<std::string>() << " "; 636 oss << it->template get<std::string>() << " ";
636 } 637 }
637 638
638 return oss.str(); 639 return oss.str();
639 }; 640 };
640 const auto unstr = [] (auto action) { 641 const auto unstr = [] (auto action) {
641 if (action.is_string() && action == "accept") 642 if (action.is_string() && action == "accept")
642 return "accept"; 643 return "accept";
643 else 644 else
644 return "drop"; 645 return "drop";
645 }; 646 };
646 647
647 std::cout << "rule: " << index << std::endl; 648 std::cout << "rule: " << index << std::endl;
648 std::cout << "servers: " << unjoin(json["servers"]) << std::endl; 649 std::cout << "servers: " << unjoin(json["servers"]) << std::endl;
649 std::cout << "channels: " << unjoin(json["channels"]) << std::endl; 650 std::cout << "channels: " << unjoin(json["channels"]) << std::endl;
650 std::cout << "plugins: " << unjoin(json["plugins"]) << std::endl; 651 std::cout << "plugins: " << unjoin(json["plugins"]) << std::endl;
651 std::cout << "events: " << unjoin(json["events"]) << std::endl; 652 std::cout << "events: " << unjoin(json["events"]) << std::endl;
652 std::cout << "action: " << unstr(json["action"]) << std::endl; 653 std::cout << "action: " << unstr(json["action"]) << std::endl;
653 std::cout << std::endl; 654 std::cout << std::endl;
654 } 655 }
655 656
656 auto rule_info_cli::get_name() const noexcept -> std::string_view 657 auto rule_info_cli::get_name() const noexcept -> std::string_view
657 { 658 {
658 return "rule-info"; 659 return "rule-info";
659 } 660 }
660 661
661 void rule_info_cli::exec(ctl::controller& ctl, const std::vector<std::string>& args) 662 void rule_info_cli::exec(ctl::controller& ctl, const std::vector<std::string>& args)
662 { 663 {
663 if (args.size() < 1) 664 if (args.size() < 1)
664 throw std::invalid_argument("rule-info requires 1 argument"); 665 throw std::invalid_argument("rule-info requires 1 argument");
665 666
666 const auto index = string_util::to_int(args[0]); 667 const auto index = string_util::to_int(args[0]);
667 668
668 if (!index) 669 if (!index)
669 throw rule_error(rule_error::invalid_index); 670 throw rule_error(rule_error::invalid_index);
670 671
671 const auto json = nlohmann::json::object({ 672 const auto json = nlohmann::json::object({
672 { "command", "rule-info" }, 673 { "command", "rule-info" },
673 { "index", *index } 674 { "index", *index }
674 }); 675 });
675 676
676 request(ctl, json, [index] (auto result) { 677 request(ctl, json, [index] (auto result) {
677 print(result, *index); 678 print(result, *index);
678 }); 679 });
679 } 680 }
680 681
681 // }}} 682 // }}}
682 683
683 // {{{ rule_list_cli 684 // {{{ rule_list_cli
684 685
685 auto rule_list_cli::get_name() const noexcept -> std::string_view 686 auto rule_list_cli::get_name() const noexcept -> std::string_view
686 { 687 {
687 return "rule-list"; 688 return "rule-list";
688 } 689 }
689 690
690 void rule_list_cli::exec(ctl::controller& ctl, const std::vector<std::string>&) 691 void rule_list_cli::exec(ctl::controller& ctl, const std::vector<std::string>&)
691 { 692 {
692 request(ctl, {{ "command", "rule-list" }}, [] (auto result) { 693 request(ctl, {{ "command", "rule-list" }}, [] (auto result) {
693 auto pos = 0; 694 auto pos = 0;
694 695
695 for (const auto& obj : result["list"]) { 696 for (const auto& obj : result["list"])
696 if (obj.is_object()) 697 if (obj.is_object())
697 rule_info_cli::print(obj, pos++); 698 rule_info_cli::print(obj, pos++);
698 } 699 });
699 });
700 } 700 }
701 701
702 // }}} 702 // }}}
703 703
704 // {{{ rule_move_cli 704 // {{{ rule_move_cli
705 705
706 auto rule_move_cli::get_name() const noexcept -> std::string_view 706 auto rule_move_cli::get_name() const noexcept -> std::string_view
707 { 707 {
708 return "rule-move"; 708 return "rule-move";
709 } 709 }
710 710
711 void rule_move_cli::exec(ctl::controller& ctl, const std::vector<std::string>& args) 711 void rule_move_cli::exec(ctl::controller& ctl, const std::vector<std::string>& args)
712 { 712 {
713 if (args.size() < 2) 713 if (args.size() < 2)
714 throw std::invalid_argument("rule-move requires 2 arguments"); 714 throw std::invalid_argument("rule-move requires 2 arguments");
715 715
716 const auto from = string_util::to_int<int>(args[0]); 716 const auto from = string_util::to_int<int>(args[0]);
717 const auto to = string_util::to_int<int>(args[1]); 717 const auto to = string_util::to_int<int>(args[1]);
718 718
719 if (!from) 719 if (!from)
720 throw rule_error(rule_error::invalid_index); 720 throw rule_error(rule_error::invalid_index);
721 if (!to) 721 if (!to)
722 throw rule_error(rule_error::invalid_index); 722 throw rule_error(rule_error::invalid_index);
723 723
724 request(ctl, { 724 request(ctl, {
725 { "command", "rule-move" }, 725 { "command", "rule-move" },
726 { "from", *from }, 726 { "from", *from },
727 { "to", *to } 727 { "to", *to }
728 }); 728 });
729 } 729 }
730 730
731 // }}} 731 // }}}
732 732
733 // {{{ rule_remove_cli 733 // {{{ rule_remove_cli
734 734
735 auto rule_remove_cli::get_name() const noexcept -> std::string_view 735 auto rule_remove_cli::get_name() const noexcept -> std::string_view
736 { 736 {
737 return "rule-remove"; 737 return "rule-remove";
738 } 738 }
739 739
740 void rule_remove_cli::exec(ctl::controller& ctl, const std::vector<std::string>& args) 740 void rule_remove_cli::exec(ctl::controller& ctl, const std::vector<std::string>& args)
741 { 741 {
742 if (args.size() < 1) 742 if (args.size() < 1)
743 throw std::invalid_argument("rule-remove requires 1 argument"); 743 throw std::invalid_argument("rule-remove requires 1 argument");
744 744
745 const auto index = string_util::to_int(args[0]); 745 const auto index = string_util::to_int(args[0]);
746 746
747 if (!index) 747 if (!index)
748 throw rule_error(rule_error::invalid_index); 748 throw rule_error(rule_error::invalid_index);
749 749
750 request(ctl, { 750 request(ctl, {
751 { "command", "rule-remove" }, 751 { "command", "rule-remove" },
752 { "index", *index } 752 { "index", *index }
753 }); 753 });
754 } 754 }
755 755
756 // }}} 756 // }}}
757 757
758 // {{{ server_connect_cli 758 // {{{ server_connect_cli
759 759
760 auto server_connect_cli::get_name() const noexcept -> std::string_view 760 auto server_connect_cli::get_name() const noexcept -> std::string_view
761 { 761 {
762 return "server-connect"; 762 return "server-connect";
763 } 763 }
764 764
765 void server_connect_cli::exec(ctl::controller& ctl, const std::vector<std::string>& args) 765 void server_connect_cli::exec(ctl::controller& ctl, const std::vector<std::string>& args)
766 { 766 {
767 std::vector<std::string> copy(args); 767 std::vector<std::string> copy(args);
768 768
769 option::result result = parse(copy); 769 option::result result = parse(copy);
770 option::result::const_iterator it; 770 option::result::const_iterator it;
771 771
772 if (copy.size() < 2) 772 if (copy.size() < 2)
773 throw std::invalid_argument("server-connect requires at least 2 arguments"); 773 throw std::invalid_argument("server-connect requires at least 2 arguments");
774 774
775 auto object = nlohmann::json::object({ 775 auto object = nlohmann::json::object({
776 { "command", "server-connect" }, 776 { "command", "server-connect" },
777 { "name", copy[0] }, 777 { "name", copy[0] },
778 { "host", copy[1] } 778 { "host", copy[1] }
779 }); 779 });
780 780
781 if (copy.size() == 3) { 781 if (copy.size() == 3) {
782 const auto port = string_util::to_int(copy[2]); 782 const auto port = string_util::to_int(copy[2]);
783 783
784 if (!port) 784 if (!port)
785 throw std::invalid_argument("invalid port given"); 785 throw std::invalid_argument("invalid port given");
786 786
787 object["port"] = *port; 787 object["port"] = *port;
788 } 788 }
789 789
790 if (result.count("-S") > 0 || result.count("--ssl-verify") > 0) 790 if (result.count("-S") > 0 || result.count("--ssl-verify") > 0)
791 object["sslVerify"] = true; 791 object["sslVerify"] = true;
792 if (result.count("-s") > 0 || result.count("--ssl") > 0) 792 if (result.count("-s") > 0 || result.count("--ssl") > 0)
793 object["ssl"] = true; 793 object["ssl"] = true;
794 if ((it = result.find("-n")) != result.end() || (it = result.find("--nickname")) != result.end()) 794 if ((it = result.find("-n")) != result.end() || (it = result.find("--nickname")) != result.end())
795 object["nickname"] = it->second; 795 object["nickname"] = it->second;
796 if ((it = result.find("-r")) != result.end() || (it = result.find("--realname")) != result.end()) 796 if ((it = result.find("-r")) != result.end() || (it = result.find("--realname")) != result.end())
797 object["realname"] = it->second; 797 object["realname"] = it->second;
798 if ((it = result.find("-u")) != result.end() || (it = result.find("--username")) != result.end()) 798 if ((it = result.find("-u")) != result.end() || (it = result.find("--username")) != result.end())
799 object["username"] = it->second; 799 object["username"] = it->second;
800 800
801 request(ctl, object); 801 request(ctl, object);
802 } 802 }
803 803
804 // }}} 804 // }}}
805 805
806 // {{{ server_disconnect_cli 806 // {{{ server_disconnect_cli
807 807
808 auto server_disconnect_cli::get_name() const noexcept -> std::string_view 808 auto server_disconnect_cli::get_name() const noexcept -> std::string_view
809 { 809 {
810 return "server-disconnect"; 810 return "server-disconnect";
811 } 811 }
812 812
813 void server_disconnect_cli::exec(ctl::controller& ctl, const std::vector<std::string>& args) 813 void server_disconnect_cli::exec(ctl::controller& ctl, const std::vector<std::string>& args)
814 { 814 {
815 auto object = nlohmann::json::object({ 815 auto object = nlohmann::json::object({
816 { "command", "server-disconnect" } 816 { "command", "server-disconnect" }
817 }); 817 });
818 818
819 if (args.size() > 0) 819 if (args.size() > 0)
820 object["server"] = args[0]; 820 object["server"] = args[0];
821 821
822 request(ctl, object); 822 request(ctl, object);
823 } 823 }
824 824
825 // }}} 825 // }}}
826 826
827 // {{{ server_info_cli 827 // {{{ server_info_cli
828 828
829 auto server_info_cli::get_name() const noexcept -> std::string_view 829 auto server_info_cli::get_name() const noexcept -> std::string_view
830 { 830 {
831 return "server-info"; 831 return "server-info";
832 } 832 }
833 833
834 void server_info_cli::exec(ctl::controller& ctl, const std::vector<std::string>& args) 834 void server_info_cli::exec(ctl::controller& ctl, const std::vector<std::string>& args)
835 { 835 {
836 if (args.size() < 1) 836 if (args.size() < 1)
837 throw std::invalid_argument("server-info requires 1 argument"); 837 throw std::invalid_argument("server-info requires 1 argument");
838 838
839 auto json = nlohmann::json::object({ 839 auto json = nlohmann::json::object({
840 { "command", "server-info" }, 840 { "command", "server-info" },
841 { "server", args[0] } 841 { "server", args[0] }
842 }); 842 });
843 843
844 request(ctl, std::move(json), [] (auto result) { 844 request(ctl, std::move(json), [] (auto result) {
845 std::cout << std::boolalpha; 845 std::cout << std::boolalpha;
846 std::cout << "Name : " << json_util::pretty(result["name"]) << std::endl; 846 std::cout << "Name : " << json_util::pretty(result["name"]) << std::endl;
847 std::cout << "Host : " << json_util::pretty(result["host"]) << std::endl; 847 std::cout << "Host : " << json_util::pretty(result["host"]) << std::endl;
848 std::cout << "Port : " << json_util::pretty(result["port"]) << std::endl; 848 std::cout << "Port : " << json_util::pretty(result["port"]) << std::endl;
849 std::cout << "Ipv6 : " << json_util::pretty(result["ipv6"]) << std::endl; 849 std::cout << "Ipv6 : " << json_util::pretty(result["ipv6"]) << std::endl;
850 std::cout << "SSL : " << json_util::pretty(result["ssl"]) << std::endl; 850 std::cout << "SSL : " << json_util::pretty(result["ssl"]) << std::endl;
851 std::cout << "SSL verified : " << json_util::pretty(result["sslVerify"]) << std::endl; 851 std::cout << "SSL verified : " << json_util::pretty(result["sslVerify"]) << std::endl;
852 std::cout << "Channels : "; 852 std::cout << "Channels : ";
853 853
854 for (const auto& v : result["channels"]) 854 for (const auto& v : result["channels"])
855 if (v.is_string()) 855 if (v.is_string())
856 std::cout << v.template get<std::string>() << " "; 856 std::cout << v.template get<std::string>() << " ";
857 857
858 std::cout << std::endl; 858 std::cout << std::endl;
859 859
860 std::cout << "Nickname : " << json_util::pretty(result["nickname"]) << std::endl; 860 std::cout << "Nickname : " << json_util::pretty(result["nickname"]) << std::endl;
861 std::cout << "User name : " << json_util::pretty(result["username"]) << std::endl; 861 std::cout << "User name : " << json_util::pretty(result["username"]) << std::endl;
862 std::cout << "Real name : " << json_util::pretty(result["realname"]) << std::endl; 862 std::cout << "Real name : " << json_util::pretty(result["realname"]) << std::endl;
863 }); 863 });
864 } 864 }
865 865
866 // }}} 866 // }}}
867 867
868 // {{{ server_invite_cli 868 // {{{ server_invite_cli
869 869
870 auto server_invite_cli::get_name() const noexcept -> std::string_view 870 auto server_invite_cli::get_name() const noexcept -> std::string_view
871 { 871 {
872 return "server-invite"; 872 return "server-invite";
873 } 873 }
874 874
875 void server_invite_cli::exec(ctl::controller& ctl, const std::vector<std::string>& args) 875 void server_invite_cli::exec(ctl::controller& ctl, const std::vector<std::string>& args)
876 { 876 {
877 if (args.size() < 3) 877 if (args.size() < 3)
878 throw std::invalid_argument("server-invite requires 3 arguments"); 878 throw std::invalid_argument("server-invite requires 3 arguments");
879 879
880 request(ctl, { 880 request(ctl, {
881 { "command", "server-invite" }, 881 { "command", "server-invite" },
882 { "server", args[0] }, 882 { "server", args[0] },
883 { "target", args[1] }, 883 { "target", args[1] },
884 { "channel", args[2] } 884 { "channel", args[2] }
885 }); 885 });
886 } 886 }
887 887
888 // }}} 888 // }}}
889 889
890 // {{{ server_join_cli 890 // {{{ server_join_cli
891 891
892 auto server_join_cli::get_name() const noexcept -> std::string_view 892 auto server_join_cli::get_name() const noexcept -> std::string_view
893 { 893 {
894 return "server-join"; 894 return "server-join";
895 } 895 }
896 896
897 void server_join_cli::exec(ctl::controller& ctl, const std::vector<std::string>& args) 897 void server_join_cli::exec(ctl::controller& ctl, const std::vector<std::string>& args)
898 { 898 {
899 if (args.size() < 2) 899 if (args.size() < 2)
900 throw std::invalid_argument("server-join requires at least 2 arguments"); 900 throw std::invalid_argument("server-join requires at least 2 arguments");
901 901
902 auto object = nlohmann::json::object({ 902 auto object = nlohmann::json::object({
903 { "command", "server-join" }, 903 { "command", "server-join" },
904 { "server", args[0] }, 904 { "server", args[0] },
905 { "channel", args[1] } 905 { "channel", args[1] }
906 }); 906 });
907 907
908 if (args.size() == 3) 908 if (args.size() == 3)
909 object["password"] = args[2]; 909 object["password"] = args[2];
910 910
911 request(ctl, object); 911 request(ctl, object);
912 } 912 }
913 913
914 // }}} 914 // }}}
915 915
916 // {{{ server_kick_cli 916 // {{{ server_kick_cli
917 917
918 auto server_kick_cli::get_name() const noexcept -> std::string_view 918 auto server_kick_cli::get_name() const noexcept -> std::string_view
919 { 919 {
920 return "server-kick"; 920 return "server-kick";
921 } 921 }
922 922
923 void server_kick_cli::exec(ctl::controller& ctl, const std::vector<std::string>& args) 923 void server_kick_cli::exec(ctl::controller& ctl, const std::vector<std::string>& args)
924 { 924 {
925 if (args.size() < 3) 925 if (args.size() < 3)
926 throw std::invalid_argument("server-kick requires at least 3 arguments "); 926 throw std::invalid_argument("server-kick requires at least 3 arguments ");
927 927
928 auto object = nlohmann::json::object({ 928 auto object = nlohmann::json::object({
929 { "command", "server-kick" }, 929 { "command", "server-kick" },
930 { "server", args[0] }, 930 { "server", args[0] },
931 { "target", args[1] }, 931 { "target", args[1] },
932 { "channel", args[2] } 932 { "channel", args[2] }
933 }); 933 });
934 934
935 if (args.size() == 4) 935 if (args.size() == 4)
936 object["reason"] = args[3]; 936 object["reason"] = args[3];
937 937
938 request(ctl, object); 938 request(ctl, object);
939 } 939 }
940 940
941 // }}} 941 // }}}
942 942
943 // {{{ server_list_cli 943 // {{{ server_list_cli
944 944
945 auto server_list_cli::get_name() const noexcept -> std::string_view 945 auto server_list_cli::get_name() const noexcept -> std::string_view
946 { 946 {
947 return "server-list"; 947 return "server-list";
948 } 948 }
949 949
950 void server_list_cli::exec(ctl::controller& ctl, const std::vector<std::string>&) 950 void server_list_cli::exec(ctl::controller& ctl, const std::vector<std::string>&)
951 { 951 {
952 request(ctl, {{ "command", "server-list" }}, [] (auto result) { 952 request(ctl, {{ "command", "server-list" }}, [] (auto result) {
953 for (const auto& n : result["list"]) 953 for (const auto& n : result["list"])
954 if (n.is_string()) 954 if (n.is_string())
955 std::cout << n.template get<std::string>() << std::endl; 955 std::cout << n.template get<std::string>() << std::endl;
956 }); 956 });
957 } 957 }
958 958
959 // }}} 959 // }}}
960 960
961 // {{{ server_me_cli 961 // {{{ server_me_cli
962 962
963 auto server_me_cli::get_name() const noexcept -> std::string_view 963 auto server_me_cli::get_name() const noexcept -> std::string_view
964 { 964 {
965 return "server-me"; 965 return "server-me";
966 } 966 }
967 967
968 void server_me_cli::exec(ctl::controller& ctl, const std::vector<std::string>& args) 968 void server_me_cli::exec(ctl::controller& ctl, const std::vector<std::string>& args)
969 { 969 {
970 if (args.size() < 3) 970 if (args.size() < 3)
971 throw std::runtime_error("server-me requires 3 arguments"); 971 throw std::runtime_error("server-me requires 3 arguments");
972 972
973 request(ctl, { 973 request(ctl, {
974 { "command", "server-me" }, 974 { "command", "server-me" },
975 { "server", args[0] }, 975 { "server", args[0] },
976 { "target", args[1] }, 976 { "target", args[1] },
977 { "message", args[2] } 977 { "message", args[2] }
978 }); 978 });
979 } 979 }
980 980
981 // }}} 981 // }}}
982 982
983 // {{{ server_message_cli 983 // {{{ server_message_cli
984 984
985 auto server_message_cli::get_name() const noexcept -> std::string_view 985 auto server_message_cli::get_name() const noexcept -> std::string_view
986 { 986 {
987 return "server-message"; 987 return "server-message";
988 } 988 }
989 989
990 void server_message_cli::exec(ctl::controller& ctl, const std::vector<std::string>& args) 990 void server_message_cli::exec(ctl::controller& ctl, const std::vector<std::string>& args)
991 { 991 {
992 if (args.size() < 3) 992 if (args.size() < 3)
993 throw std::invalid_argument("server-message requires 3 arguments"); 993 throw std::invalid_argument("server-message requires 3 arguments");
994 994
995 request(ctl, { 995 request(ctl, {
996 { "command", "server-message" }, 996 { "command", "server-message" },
997 { "server", args[0] }, 997 { "server", args[0] },
998 { "target", args[1] }, 998 { "target", args[1] },
999 { "message", args[2] } 999 { "message", args[2] }
1000 }); 1000 });
1001 } 1001 }
1002 1002
1003 // }}} 1003 // }}}
1004 1004
1005 // {{{ server_mode_cli 1005 // {{{ server_mode_cli
1006 1006
1007 auto server_mode_cli::get_name() const noexcept -> std::string_view 1007 auto server_mode_cli::get_name() const noexcept -> std::string_view
1008 { 1008 {
1009 return "server-mode"; 1009 return "server-mode";
1010 } 1010 }
1011 1011
1012 void server_mode_cli::exec(ctl::controller& ctl, const std::vector<std::string>& args) 1012 void server_mode_cli::exec(ctl::controller& ctl, const std::vector<std::string>& args)
1013 { 1013 {
1014 if (args.size() < 2) 1014 if (args.size() < 2)
1015 throw std::invalid_argument("server-mode requires at least 3 arguments"); 1015 throw std::invalid_argument("server-mode requires at least 3 arguments");
1016 1016
1017 auto json = nlohmann::json({ 1017 auto json = nlohmann::json({
1018 { "command", "server-mode" }, 1018 { "command", "server-mode" },
1019 { "server", args[0] }, 1019 { "server", args[0] },
1020 { "channel", args[1] }, 1020 { "channel", args[1] },
1021 { "mode", args[2] } 1021 { "mode", args[2] }
1022 }); 1022 });
1023 1023
1024 if (args.size() >= 4) 1024 if (args.size() >= 4)
1025 json["limit"] = args[3]; 1025 json["limit"] = args[3];
1026 if (args.size() >= 5) 1026 if (args.size() >= 5)
1027 json["user"] = args[4]; 1027 json["user"] = args[4];
1028 if (args.size() >= 6) 1028 if (args.size() >= 6)
1029 json["mask"] = args[5]; 1029 json["mask"] = args[5];
1030 1030
1031 request(ctl, std::move(json)); 1031 request(ctl, std::move(json));
1032 } 1032 }
1033 1033
1034 // }}} 1034 // }}}
1035 1035
1036 // {{{ server_nick_cli 1036 // {{{ server_nick_cli
1037 1037
1038 auto server_nick_cli::get_name() const noexcept -> std::string_view 1038 auto server_nick_cli::get_name() const noexcept -> std::string_view
1039 { 1039 {
1040 return "server-nick"; 1040 return "server-nick";
1041 } 1041 }
1042 1042
1043 void server_nick_cli::exec(ctl::controller& ctl, const std::vector<std::string>& args) 1043 void server_nick_cli::exec(ctl::controller& ctl, const std::vector<std::string>& args)
1044 { 1044 {
1045 if (args.size() < 2) 1045 if (args.size() < 2)
1046 throw std::invalid_argument("server-nick requires 2 arguments"); 1046 throw std::invalid_argument("server-nick requires 2 arguments");
1047 1047
1048 request(ctl, { 1048 request(ctl, {
1049 { "command", "server-nick" }, 1049 { "command", "server-nick" },
1050 { "server", args[0] }, 1050 { "server", args[0] },
1051 { "nickname", args[1] } 1051 { "nickname", args[1] }
1052 }); 1052 });
1053 } 1053 }
1054 1054
1055 // }}} 1055 // }}}
1056 1056
1057 // {{{ server_notice_cli 1057 // {{{ server_notice_cli
1058 1058
1059 auto server_notice_cli::get_name() const noexcept -> std::string_view 1059 auto server_notice_cli::get_name() const noexcept -> std::string_view
1060 { 1060 {
1061 return "server-notice"; 1061 return "server-notice";
1062 } 1062 }
1063 1063
1064 void server_notice_cli::exec(ctl::controller& ctl, const std::vector<std::string>& args) 1064 void server_notice_cli::exec(ctl::controller& ctl, const std::vector<std::string>& args)
1065 { 1065 {
1066 if (args.size() < 3) 1066 if (args.size() < 3)
1067 throw std::invalid_argument("server-notice requires 3 arguments"); 1067 throw std::invalid_argument("server-notice requires 3 arguments");
1068 1068
1069 request(ctl, { 1069 request(ctl, {
1070 { "command", "server-notice" }, 1070 { "command", "server-notice" },
1071 { "server", args[0] }, 1071 { "server", args[0] },
1072 { "target", args[1] }, 1072 { "target", args[1] },
1073 { "message", args[2] } 1073 { "message", args[2] }
1074 }); 1074 });
1075 } 1075 }
1076 1076
1077 // }}} 1077 // }}}
1078 1078
1079 // {{{ server_part_cli 1079 // {{{ server_part_cli
1080 1080
1081 auto server_part_cli::get_name() const noexcept -> std::string_view 1081 auto server_part_cli::get_name() const noexcept -> std::string_view
1082 { 1082 {
1083 return "server-part"; 1083 return "server-part";
1084 } 1084 }
1085 1085
1086 void server_part_cli::exec(ctl::controller& ctl, const std::vector<std::string>& args) 1086 void server_part_cli::exec(ctl::controller& ctl, const std::vector<std::string>& args)
1087 { 1087 {
1088 if (args.size() < 2) 1088 if (args.size() < 2)
1089 throw std::invalid_argument("server-part requires at least 2 arguments"); 1089 throw std::invalid_argument("server-part requires at least 2 arguments");
1090 1090
1091 auto object = nlohmann::json::object({ 1091 auto object = nlohmann::json::object({
1092 { "command", "server-part" }, 1092 { "command", "server-part" },
1093 { "server", args[0] }, 1093 { "server", args[0] },
1094 { "channel", args[1] } 1094 { "channel", args[1] }
1095 }); 1095 });
1096 1096
1097 if (args.size() >= 3) 1097 if (args.size() >= 3)
1098 object["reason"] = args[2]; 1098 object["reason"] = args[2];
1099 1099
1100 request(ctl, object); 1100 request(ctl, object);
1101 } 1101 }
1102 1102
1103 // }}} 1103 // }}}
1104 1104
1105 // {{{ server_reconnect_cli 1105 // {{{ server_reconnect_cli
1106 1106
1107 auto server_reconnect_cli::get_name() const noexcept -> std::string_view 1107 auto server_reconnect_cli::get_name() const noexcept -> std::string_view
1108 { 1108 {
1109 return "server-reconnect"; 1109 return "server-reconnect";
1110 } 1110 }
1111 1111
1112 void server_reconnect_cli::exec(ctl::controller& ctl, const std::vector<std::string>& args) 1112 void server_reconnect_cli::exec(ctl::controller& ctl, const std::vector<std::string>& args)
1113 { 1113 {
1114 auto object = nlohmann::json::object({ 1114 auto object = nlohmann::json::object({
1115 { "command", "server-reconnect" } 1115 { "command", "server-reconnect" }
1116 }); 1116 });
1117 1117
1118 if (args.size() >= 1) 1118 if (args.size() >= 1)
1119 object["server"] = args[0]; 1119 object["server"] = args[0];
1120 1120
1121 request(ctl, object); 1121 request(ctl, object);
1122 } 1122 }
1123 1123
1124 // }}} 1124 // }}}
1125 1125
1126 // {{{ server_topic_cli 1126 // {{{ server_topic_cli
1127 1127
1128 auto server_topic_cli::get_name() const noexcept -> std::string_view 1128 auto server_topic_cli::get_name() const noexcept -> std::string_view
1129 { 1129 {
1130 return "server-topic"; 1130 return "server-topic";
1131 } 1131 }
1132 1132
1133 void server_topic_cli::exec(ctl::controller& ctl, const std::vector<std::string>& args) 1133 void server_topic_cli::exec(ctl::controller& ctl, const std::vector<std::string>& args)
1134 { 1134 {
1135 if (args.size() < 3) 1135 if (args.size() < 3)
1136 throw std::invalid_argument("server-topic requires 3 arguments"); 1136 throw std::invalid_argument("server-topic requires 3 arguments");
1137 1137
1138 request(ctl, { 1138 request(ctl, {
1139 { "command", "server-topic" }, 1139 { "command", "server-topic" },
1140 { "server", args[0] }, 1140 { "server", args[0] },
1141 { "channel", args[1] }, 1141 { "channel", args[1] },
1142 { "topic", args[2] } 1142 { "topic", args[2] }
1143 }); 1143 });
1144 } 1144 }
1145 1145
1146 // }}} 1146 // }}}
1147 1147
1148 // {{{ watch_cli 1148 // {{{ watch_cli
1149 1149
1150 auto watch_cli::get_name() const noexcept -> std::string_view 1150 auto watch_cli::get_name() const noexcept -> std::string_view
1151 { 1151 {
1152 return "watch"; 1152 return "watch";
1153 } 1153 }
1154 1154
1155 void watch_cli::exec(ctl::controller& ctl, const std::vector<std::string>& args) 1155 void watch_cli::exec(ctl::controller& ctl, const std::vector<std::string>& args)
1156 { 1156 {
1157 auto fmt = format(args); 1157 const auto fmt = format(args);
1158 1158
1159 if (fmt != "native" && fmt != "json") 1159 if (fmt != "native" && fmt != "json")
1160 throw std::invalid_argument("invalid format given: " + fmt); 1160 throw std::invalid_argument("invalid format given: " + fmt);
1161 1161
1162 get_event(ctl, fmt); 1162 get_event(ctl, fmt);
1163 } 1163 }
1164 1164
1165 // }}} 1165 // }}}
1166 1166
1167 } // !irccd::ctl 1167 } // !irccd::ctl