45 .
bridge = std::move(bridge),
46 .display_queue = std::move(display_queue),
47 .transport_queue = std::move(transport_queue),
48 .session_queue = std::move(session_queue),
49 .connection_monitor_queue = std::move(connection_monitor_queue),
55 "Interactive Commands:\n"
56 " /broadcast <message> Send to all local peers\n"
57 " /chat <contact> Enter chat mode with contact\n"
58 " /connect <relay> Add Nostr relay\n"
59 " /disconnect Disconnect from Nostr relay\n"
60 " /identities List discovered identities\n"
61 " /leave Exit chat mode\n"
62 " /mode <internet|mesh|hybrid> Switch transport mode\n"
63 " /peers List discovered peers\n"
64 " /publish Publish identity to network\n"
65 " /scan Force peer discovery\n"
66 " /send <peer> <message> Send encrypted message to peer\n"
67 " /sessions Show encrypted sessions\n"
68 " /status Show network status\n"
69 " /trust <peer> [alias] Establish session with peer\n"
70 " /verify <peer> Show safety numbers\n"
71 " /version Show version information\n"
72 " /quit Exit interactive mode\n");
77 "Connected Peers: (transport layer not implemented)\n"
78 " No peers discovered yet\n");
83 std::string node_fingerprint = ctx->bridge->get_node_fingerprint();
84 ctx->emit(
"\nCrypto Status:\n Node Fingerprint: {}\n", node_fingerprint);
88 auto contacts = ctx->bridge->list_contacts();
90 if (contacts.empty()) {
91 ctx->emit(
"No active sessions\n");
95 ctx->emit(
"Active Sessions ({}):\n", contacts.size());
96 for (
const auto &contact : contacts) {
97 if (contact.user_alias.empty()) {
98 ctx->emit(
" {}\n", contact.rdx_fingerprint);
100 ctx->emit(
" {} ({})\n", contact.user_alias, contact.rdx_fingerprint);
109 ctx->emit(
"Publishing identity to network...\n");
114 ctx->emit(
"Unpublishing identity from network...\n");
119 "Scanning for BLE peers... (BLE transport not implemented)\n"
120 " No peers found\n");
123 [ctx](
const events::version &) { ctx->emit(
"Radix Relay v{}\n", radix_relay::cmake::project_version); },
126 if (command.new_mode ==
"internet" or command.new_mode ==
"mesh" or command.new_mode ==
"hybrid") {
127 ctx->emit(
"Switched to {} mode\n", command.new_mode);
129 ctx->emit(
"Invalid mode. Use: internet, mesh, or hybrid\n");
134 if (not command.peer.empty() and not command.message.empty()) {
135 ctx->session_queue->push(command);
136 ctx->emit(
"Sending '{}' to '{}'...\n", command.message, command.peer);
138 ctx->emit(
"Usage: send <peer> <message>\n");
143 if (not command.message.empty()) {
144 ctx->emit(
"Broadcasting '{}' to all local peers (not implemented)\n", command.message);
146 ctx->emit(
"Usage: broadcast <message>\n");
151 if (not command.relay.empty()) {
152 ctx->session_queue->push(command);
153 ctx->emit(
"Connecting to Nostr relay {}\n", command.relay);
155 ctx->emit(
"Usage: connect <relay>\n");
161 ctx->emit(
"Disconnecting from Nostr relay\n");
165 if (not command.peer.empty()) {
166 ctx->session_queue->push(command);
167 ctx->emit(
"Establishing session with {}...\n", command.peer);
169 ctx->emit(
"Usage: trust <peer> [alias]\n");
174 if (not command.peer.empty()) {
175 ctx->emit(
"Safety numbers for {} (Signal Protocol not implemented)\n", command.peer);
177 ctx->emit(
"Usage: verify <peer>\n");
182 if (command.contact.empty()) {
183 ctx->emit(
"Usage: /chat <contact>\n");
188 const auto contact = ctx->bridge->lookup_contact(command.contact);
189 const auto display_name = contact.user_alias.empty() ? contact.rdx_fingerprint : contact.user_alias;
191 ctx->display_queue->push(
194 constexpr std::uint32_t history_limit = 5;
195 const auto messages = ctx->bridge->get_conversation_messages(contact.rdx_fingerprint, history_limit, 0);
197 if (not messages.empty()) {
199 .
message = fmt::format(
"--- Conversation History ({} messages) ---", messages.size()),
200 .contact_rdx = contact.rdx_fingerprint,
204 for (
auto it = messages.rbegin(); it != messages.rend(); ++it) {
205 const auto &msg = *it;
207 const auto direction_indicator = (msg.direction == signal::MessageDirection::Incoming) ?
"← " :
"→ ";
208 const auto sender_name = (msg.direction == signal::MessageDirection::Incoming) ? display_name :
"You";
210 const auto formatted_message = fmt::format(
"{}{}: {}", direction_indicator, sender_name, msg.content);
212 const auto source_type = (msg.direction == signal::MessageDirection::Incoming)
217 .contact_rdx = contact.rdx_fingerprint,
218 .timestamp = msg.timestamp,
219 .source_type = source_type });
223 .contact_rdx = contact.rdx_fingerprint,
227 const auto newest_timestamp = messages.front().timestamp;
228 ctx->bridge->mark_conversation_read_up_to(contact.rdx_fingerprint, newest_timestamp);
230 ctx->bridge->mark_conversation_read(contact.rdx_fingerprint);
233 ctx->emit(
"Entering chat with {}\n", display_name);
234 }
catch (
const std::exception &) {
235 ctx->emit(
"Contact not found: {}\n", command.contact);
241 ctx->emit(
"Exiting chat mode\n");