50 explicit command_parser(std::shared_ptr<Bridge> bridge) : bridge_(std::move(bridge)) { build_handler_chain(); }
63 auto effective_input = input;
65 if (active_chat_rdx_.has_value() and not input.starts_with(
"/")) {
66 effective_input =
"/send " + active_chat_rdx_.value() +
" " + input;
69 for (
const auto &handler : handlers_) {
71 if (
auto result = handler(effective_input)) {
return *result; }
82 auto enter_chat_mode(
const std::string &rdx_fingerprint)
const ->
void { active_chat_rdx_ = rdx_fingerprint; }
94 [[nodiscard]]
auto in_chat_mode() const ->
bool {
return active_chat_rdx_.has_value(); }
97 std::shared_ptr<Bridge> bridge_;
98 mutable std::optional<std::string> active_chat_rdx_;
99 std::vector<handler_t> handlers_;
104 template<
typename Event>
static auto exact_match(std::string_view command) ->
handler_t
106 return [cmd = std::string(command)](
const std::string &input) ->
parse_result_t {
107 if (input == cmd) {
return Event{}; }
115 template<
typename Event,
typename Extractor>
116 static auto prefix_match(std::string_view prefix, Extractor extractor) ->
handler_t
118 return [p = std::string(prefix), ext = std::move(extractor)](
const std::string &input) ->
parse_result_t {
119 if (input.starts_with(p)) {
return ext(input.substr(p.length())); }
124 auto build_handler_chain() ->
void
129 handlers_.push_back(prefix_match<events::send>(
"/send ", [](
const std::string &args) {
130 const auto first_space = args.find(
' ');
131 if (first_space != std::string::npos and not args.empty()) {
132 return events::send{ .peer = args.substr(0, first_space), .message = args.substr(first_space + 1) };
134 return events::send{ .peer =
"", .message =
"" };
138 handlers_.push_back([
this](
const std::string &input) ->
parse_result_t {
139 constexpr auto chat_cmd =
"/chat ";
140 if (not input.starts_with(chat_cmd)) {
return std::nullopt; }
142 const auto contact_name = input.substr(std::string_view(chat_cmd).length());
143 if (not contact_name.empty()) {
145 const auto contact = bridge_->lookup_contact(contact_name);
146 active_chat_rdx_ = contact.rdx_fingerprint;
147 }
catch (
const std::exception & ) {
151 return events::chat{ .contact = contact_name };
155 handlers_.push_back([
this](
const std::string &input) ->
parse_result_t {
156 if (input ==
"/leave") {
157 active_chat_rdx_.reset();
158 return events::leave{};
164 handlers_.push_back(exact_match<events::help>(
"/help"));
165 handlers_.push_back(exact_match<events::status>(
"/status"));
166 handlers_.push_back(exact_match<events::peers>(
"/peers"));
167 handlers_.push_back(exact_match<events::sessions>(
"/sessions"));
170 handlers_.push_back(prefix_match<events::connect>(
171 "/connect ", [](
const std::string &args) {
return events::connect{ .relay = args }; }));
172 handlers_.push_back(exact_match<events::disconnect>(
"/disconnect"));
175 handlers_.push_back(exact_match<events::identities>(
"/identities"));
176 handlers_.push_back(prefix_match<events::trust>(
"/trust ", [](
const std::string &args) {
177 const auto first_space = args.find(
' ');
178 if (first_space != std::string::npos and not args.empty()) {
179 return events::trust{ .peer = args.substr(0, first_space), .alias = args.substr(first_space + 1) };
181 return events::trust{ .peer = args, .alias =
"" };
184 prefix_match<events::verify>(
"/verify ", [](
const std::string &args) {
return events::verify{ .peer = args }; }));
187 handlers_.push_back(prefix_match<events::broadcast>(
188 "/broadcast ", [](
const std::string &args) {
return events::broadcast{ .message = args }; }));
190 prefix_match<events::mode>(
"/mode ", [](
const std::string &args) {
return events::mode{ .new_mode = args }; }));
191 handlers_.push_back(exact_match<events::scan>(
"/scan"));
192 handlers_.push_back(exact_match<events::version>(
"/version"));
193 handlers_.push_back(exact_match<events::publish_identity>(
"/publish"));
194 handlers_.push_back(exact_match<events::unpublish_identity>(
"/unpublish"));
std::variant< events::help, events::peers, events::status, events::sessions, events::identities, events::scan, events::version, events::mode, events::send, events::broadcast, events::connect, events::disconnect, events::publish_identity, events::unpublish_identity, events::trust, events::verify, events::chat, events::leave, events::unknown_command > command_variant_t