Private
Public Access
1
0

cargo fmt

This commit is contained in:
2025-08-24 11:04:41 -07:00
parent da813806bb
commit 06b27c041a
2 changed files with 312 additions and 106 deletions

View File

@@ -1,7 +1,7 @@
use crate::xpc::interface::SERVICE_NAME; use crate::xpc::interface::SERVICE_NAME;
use futures_util::StreamExt; use futures_util::StreamExt;
use kordophoned::daemon::{events::Event, signals::Signal, DaemonResult};
use kordophoned::daemon::settings::Settings; use kordophoned::daemon::settings::Settings;
use kordophoned::daemon::{events::Event, signals::Signal, DaemonResult};
use std::collections::HashMap; use std::collections::HashMap;
use std::ffi::CString; use std::ffi::CString;
use std::sync::Arc; use std::sync::Arc;
@@ -252,47 +252,62 @@ async fn dispatch(agent: &XpcAgent, root: &HashMap<CString, Message>) -> Message
} }
} }
"SyncConversationList" => { "SyncConversationList" => match agent.send_event(Event::SyncConversationList).await {
match agent.send_event(Event::SyncConversationList).await {
Ok(()) => make_ok_reply(), Ok(()) => make_ok_reply(),
Err(e) => make_error_reply("DaemonError", &format!("{}", e)), Err(e) => make_error_reply("DaemonError", &format!("{}", e)),
} },
}
"SyncAllConversations" => { "SyncAllConversations" => match agent.send_event(Event::SyncAllConversations).await {
match agent.send_event(Event::SyncAllConversations).await {
Ok(()) => make_ok_reply(), Ok(()) => make_ok_reply(),
Err(e) => make_error_reply("DaemonError", &format!("{}", e)), Err(e) => make_error_reply("DaemonError", &format!("{}", e)),
} },
}
"SyncConversation" => { "SyncConversation" => {
let conversation_id = match get_dictionary_field(root, "arguments").and_then(|m| dict_get_str(m, "conversation_id")) { let conversation_id = match get_dictionary_field(root, "arguments")
.and_then(|m| dict_get_str(m, "conversation_id"))
{
Some(id) => id, Some(id) => id,
None => return make_error_reply("InvalidRequest", "Missing conversation_id"), None => return make_error_reply("InvalidRequest", "Missing conversation_id"),
}; };
match agent.send_event(|r| Event::SyncConversation(conversation_id, r)).await { match agent
.send_event(|r| Event::SyncConversation(conversation_id, r))
.await
{
Ok(()) => make_ok_reply(), Ok(()) => make_ok_reply(),
Err(e) => make_error_reply("DaemonError", &format!("{}", e)), Err(e) => make_error_reply("DaemonError", &format!("{}", e)),
} }
} }
"MarkConversationAsRead" => { "MarkConversationAsRead" => {
let conversation_id = match get_dictionary_field(root, "arguments").and_then(|m| dict_get_str(m, "conversation_id")) { let conversation_id = match get_dictionary_field(root, "arguments")
.and_then(|m| dict_get_str(m, "conversation_id"))
{
Some(id) => id, Some(id) => id,
None => return make_error_reply("InvalidRequest", "Missing conversation_id"), None => return make_error_reply("InvalidRequest", "Missing conversation_id"),
}; };
match agent.send_event(|r| Event::MarkConversationAsRead(conversation_id, r)).await { match agent
.send_event(|r| Event::MarkConversationAsRead(conversation_id, r))
.await
{
Ok(()) => make_ok_reply(), Ok(()) => make_ok_reply(),
Err(e) => make_error_reply("DaemonError", &format!("{}", e)), Err(e) => make_error_reply("DaemonError", &format!("{}", e)),
} }
} }
"GetMessages" => { "GetMessages" => {
let args = match get_dictionary_field(root, "arguments") { Some(a) => a, None => return make_error_reply("InvalidRequest", "Missing arguments") }; let args = match get_dictionary_field(root, "arguments") {
let conversation_id = match dict_get_str(args, "conversation_id") { Some(id) => id, None => return make_error_reply("InvalidRequest", "Missing conversation_id") }; Some(a) => a,
None => return make_error_reply("InvalidRequest", "Missing arguments"),
};
let conversation_id = match dict_get_str(args, "conversation_id") {
Some(id) => id,
None => return make_error_reply("InvalidRequest", "Missing conversation_id"),
};
let last_message_id = dict_get_str(args, "last_message_id"); let last_message_id = dict_get_str(args, "last_message_id");
match agent.send_event(|r| Event::GetMessages(conversation_id, last_message_id, r)).await { match agent
.send_event(|r| Event::GetMessages(conversation_id, last_message_id, r))
.await
{
Ok(messages) => { Ok(messages) => {
let mut items: Vec<Message> = Vec::with_capacity(messages.len()); let mut items: Vec<Message> = Vec::with_capacity(messages.len());
for msg in messages { for msg in messages {
@@ -312,22 +327,35 @@ async fn dispatch(agent: &XpcAgent, root: &HashMap<CString, Message>) -> Message
} }
} }
"DeleteAllConversations" => { "DeleteAllConversations" => match agent.send_event(Event::DeleteAllConversations).await {
match agent.send_event(Event::DeleteAllConversations).await {
Ok(()) => make_ok_reply(), Ok(()) => make_ok_reply(),
Err(e) => make_error_reply("DaemonError", &format!("{}", e)), Err(e) => make_error_reply("DaemonError", &format!("{}", e)),
} },
}
"SendMessage" => { "SendMessage" => {
let args = match get_dictionary_field(root, "arguments") { Some(a) => a, None => return make_error_reply("InvalidRequest", "Missing arguments") }; let args = match get_dictionary_field(root, "arguments") {
let conversation_id = match dict_get_str(args, "conversation_id") { Some(v) => v, None => return make_error_reply("InvalidRequest", "Missing conversation_id") }; Some(a) => a,
None => return make_error_reply("InvalidRequest", "Missing arguments"),
};
let conversation_id = match dict_get_str(args, "conversation_id") {
Some(v) => v,
None => return make_error_reply("InvalidRequest", "Missing conversation_id"),
};
let text = dict_get_str(args, "text").unwrap_or_default(); let text = dict_get_str(args, "text").unwrap_or_default();
let attachment_guids: Vec<String> = match args.get(&cstr("attachment_guids")) { let attachment_guids: Vec<String> = match args.get(&cstr("attachment_guids")) {
Some(Message::Array(arr)) => arr.iter().filter_map(|m| match m { Message::String(s) => Some(s.to_string_lossy().into_owned()), _ => None }).collect(), Some(Message::Array(arr)) => arr
.iter()
.filter_map(|m| match m {
Message::String(s) => Some(s.to_string_lossy().into_owned()),
_ => None,
})
.collect(),
_ => Vec::new(), _ => Vec::new(),
}; };
match agent.send_event(|r| Event::SendMessage(conversation_id, text, attachment_guids, r)).await { match agent
.send_event(|r| Event::SendMessage(conversation_id, text, attachment_guids, r))
.await
{
Ok(uuid) => { Ok(uuid) => {
let mut reply: XpcMap = HashMap::new(); let mut reply: XpcMap = HashMap::new();
dict_put_str(&mut reply, "type", "SendMessageResponse"); dict_put_str(&mut reply, "type", "SendMessageResponse");
@@ -339,16 +367,41 @@ async fn dispatch(agent: &XpcAgent, root: &HashMap<CString, Message>) -> Message
} }
"GetAttachmentInfo" => { "GetAttachmentInfo" => {
let args = match get_dictionary_field(root, "arguments") { Some(a) => a, None => return make_error_reply("InvalidRequest", "Missing arguments") }; let args = match get_dictionary_field(root, "arguments") {
let attachment_id = match dict_get_str(args, "attachment_id") { Some(v) => v, None => return make_error_reply("InvalidRequest", "Missing attachment_id") }; Some(a) => a,
match agent.send_event(|r| Event::GetAttachment(attachment_id, r)).await { None => return make_error_reply("InvalidRequest", "Missing arguments"),
};
let attachment_id = match dict_get_str(args, "attachment_id") {
Some(v) => v,
None => return make_error_reply("InvalidRequest", "Missing attachment_id"),
};
match agent
.send_event(|r| Event::GetAttachment(attachment_id, r))
.await
{
Ok(attachment) => { Ok(attachment) => {
let mut reply: XpcMap = HashMap::new(); let mut reply: XpcMap = HashMap::new();
dict_put_str(&mut reply, "type", "GetAttachmentInfoResponse"); dict_put_str(&mut reply, "type", "GetAttachmentInfoResponse");
dict_put_str(&mut reply, "path", &attachment.get_path_for_preview(false).to_string_lossy()); dict_put_str(
dict_put_str(&mut reply, "preview_path", &attachment.get_path_for_preview(true).to_string_lossy()); &mut reply,
dict_put_str(&mut reply, "downloaded", &attachment.is_downloaded(false).to_string()); "path",
dict_put_str(&mut reply, "preview_downloaded", &attachment.is_downloaded(true).to_string()); &attachment.get_path_for_preview(false).to_string_lossy(),
);
dict_put_str(
&mut reply,
"preview_path",
&attachment.get_path_for_preview(true).to_string_lossy(),
);
dict_put_str(
&mut reply,
"downloaded",
&attachment.is_downloaded(false).to_string(),
);
dict_put_str(
&mut reply,
"preview_downloaded",
&attachment.is_downloaded(true).to_string(),
);
Message::Dictionary(reply) Message::Dictionary(reply)
} }
Err(e) => make_error_reply("DaemonError", &format!("{}", e)), Err(e) => make_error_reply("DaemonError", &format!("{}", e)),
@@ -356,10 +409,21 @@ async fn dispatch(agent: &XpcAgent, root: &HashMap<CString, Message>) -> Message
} }
"DownloadAttachment" => { "DownloadAttachment" => {
let args = match get_dictionary_field(root, "arguments") { Some(a) => a, None => return make_error_reply("InvalidRequest", "Missing arguments") }; let args = match get_dictionary_field(root, "arguments") {
let attachment_id = match dict_get_str(args, "attachment_id") { Some(v) => v, None => return make_error_reply("InvalidRequest", "Missing attachment_id") }; Some(a) => a,
let preview = dict_get_str(args, "preview").map(|s| s == "true").unwrap_or(false); None => return make_error_reply("InvalidRequest", "Missing arguments"),
match agent.send_event(|r| Event::DownloadAttachment(attachment_id, preview, r)).await { };
let attachment_id = match dict_get_str(args, "attachment_id") {
Some(v) => v,
None => return make_error_reply("InvalidRequest", "Missing attachment_id"),
};
let preview = dict_get_str(args, "preview")
.map(|s| s == "true")
.unwrap_or(false);
match agent
.send_event(|r| Event::DownloadAttachment(attachment_id, preview, r))
.await
{
Ok(()) => make_ok_reply(), Ok(()) => make_ok_reply(),
Err(e) => make_error_reply("DaemonError", &format!("{}", e)), Err(e) => make_error_reply("DaemonError", &format!("{}", e)),
} }
@@ -367,9 +431,18 @@ async fn dispatch(agent: &XpcAgent, root: &HashMap<CString, Message>) -> Message
"UploadAttachment" => { "UploadAttachment" => {
use std::path::PathBuf; use std::path::PathBuf;
let args = match get_dictionary_field(root, "arguments") { Some(a) => a, None => return make_error_reply("InvalidRequest", "Missing arguments") }; let args = match get_dictionary_field(root, "arguments") {
let path = match dict_get_str(args, "path") { Some(v) => v, None => return make_error_reply("InvalidRequest", "Missing path") }; Some(a) => a,
match agent.send_event(|r| Event::UploadAttachment(PathBuf::from(path), r)).await { None => return make_error_reply("InvalidRequest", "Missing arguments"),
};
let path = match dict_get_str(args, "path") {
Some(v) => v,
None => return make_error_reply("InvalidRequest", "Missing path"),
};
match agent
.send_event(|r| Event::UploadAttachment(PathBuf::from(path), r))
.await
{
Ok(upload_guid) => { Ok(upload_guid) => {
let mut reply: XpcMap = HashMap::new(); let mut reply: XpcMap = HashMap::new();
dict_put_str(&mut reply, "type", "UploadAttachmentResponse"); dict_put_str(&mut reply, "type", "UploadAttachmentResponse");
@@ -380,34 +453,48 @@ async fn dispatch(agent: &XpcAgent, root: &HashMap<CString, Message>) -> Message
} }
} }
"GetAllSettings" => { "GetAllSettings" => match agent.send_event(Event::GetAllSettings).await {
match agent.send_event(Event::GetAllSettings).await {
Ok(settings) => { Ok(settings) => {
let mut reply: XpcMap = HashMap::new(); let mut reply: XpcMap = HashMap::new();
dict_put_str(&mut reply, "type", "GetAllSettingsResponse"); dict_put_str(&mut reply, "type", "GetAllSettingsResponse");
dict_put_str(&mut reply, "server_url", &settings.server_url.unwrap_or_default()); dict_put_str(
dict_put_str(&mut reply, "username", &settings.username.unwrap_or_default()); &mut reply,
"server_url",
&settings.server_url.unwrap_or_default(),
);
dict_put_str(
&mut reply,
"username",
&settings.username.unwrap_or_default(),
);
Message::Dictionary(reply) Message::Dictionary(reply)
} }
Err(e) => make_error_reply("DaemonError", &format!("{}", e)), Err(e) => make_error_reply("DaemonError", &format!("{}", e)),
} },
}
"UpdateSettings" => { "UpdateSettings" => {
let args = match get_dictionary_field(root, "arguments") { Some(a) => a, None => return make_error_reply("InvalidRequest", "Missing arguments") }; let args = match get_dictionary_field(root, "arguments") {
Some(a) => a,
None => return make_error_reply("InvalidRequest", "Missing arguments"),
};
let server_url = dict_get_str(args, "server_url"); let server_url = dict_get_str(args, "server_url");
let username = dict_get_str(args, "username"); let username = dict_get_str(args, "username");
let settings = Settings { server_url, username, token: None }; let settings = Settings {
match agent.send_event(|r| Event::UpdateSettings(settings, r)).await { server_url,
username,
token: None,
};
match agent
.send_event(|r| Event::UpdateSettings(settings, r))
.await
{
Ok(()) => make_ok_reply(), Ok(()) => make_ok_reply(),
Err(e) => make_error_reply("DaemonError", &format!("{}", e)), Err(e) => make_error_reply("DaemonError", &format!("{}", e)),
} }
} }
// No-op used by clients to ensure the connection is established and subscribed // No-op used by clients to ensure the connection is established and subscribed
"SubscribeSignals" => { "SubscribeSignals" => make_ok_reply(),
make_ok_reply()
}
// Unknown method fallback // Unknown method fallback
other => make_error_reply("UnknownMethod", other), other => make_error_reply("UnknownMethod", other),
@@ -438,11 +525,17 @@ fn signal_to_message(signal: Signal) -> Message {
dict_put_str(&mut root, "name", "UpdateStreamReconnected"); dict_put_str(&mut root, "name", "UpdateStreamReconnected");
} }
} }
if !args.is_empty() { root.insert(cstr("arguments"), Message::Dictionary(args)); } if !args.is_empty() {
root.insert(cstr("arguments"), Message::Dictionary(args));
}
Message::Dictionary(root) Message::Dictionary(root)
} }
async fn handle_client(agent: XpcAgent, mut client: XpcClient, mut signal_rx: broadcast::Receiver<Signal>) { async fn handle_client(
agent: XpcAgent,
mut client: XpcClient,
mut signal_rx: broadcast::Receiver<Signal>,
) {
log::info!(target: LOG_TARGET, "New XPC connection"); log::info!(target: LOG_TARGET, "New XPC connection");
loop { loop {

View File

@@ -278,18 +278,27 @@ impl DaemonInterface for XpcDaemonInterface {
if let Some(id) = _conversation_id { if let Some(id) = _conversation_id {
let mut args = HashMap::new(); let mut args = HashMap::new();
args.insert(Self::key("conversation_id"), Message::String(CString::new(id).unwrap())); args.insert(
let _ = self.call_method(&mut client, "SyncConversation", Some(args)).await?; Self::key("conversation_id"),
Message::String(CString::new(id).unwrap()),
);
let _ = self
.call_method(&mut client, "SyncConversation", Some(args))
.await?;
return Ok(()); return Ok(());
} }
let _ = self.call_method(&mut client, "SyncAllConversations", None).await?; let _ = self
.call_method(&mut client, "SyncAllConversations", None)
.await?;
Ok(()) Ok(())
} }
async fn sync_conversations_list(&mut self) -> Result<()> { async fn sync_conversations_list(&mut self) -> Result<()> {
let mach_port_name = Self::build_service_name()?; let mach_port_name = Self::build_service_name()?;
let mut client = XPCClient::connect(&mach_port_name); let mut client = XPCClient::connect(&mach_port_name);
let _ = self.call_method(&mut client, "SyncConversationList", None).await?; let _ = self
.call_method(&mut client, "SyncConversationList", None)
.await?;
Ok(()) Ok(())
} }
async fn print_messages( async fn print_messages(
@@ -301,24 +310,39 @@ impl DaemonInterface for XpcDaemonInterface {
let mut client = XPCClient::connect(&mach_port_name); let mut client = XPCClient::connect(&mach_port_name);
let mut args = HashMap::new(); let mut args = HashMap::new();
args.insert(Self::key("conversation_id"), Message::String(CString::new(_conversation_id).unwrap())); args.insert(
Self::key("conversation_id"),
Message::String(CString::new(_conversation_id).unwrap()),
);
if let Some(last) = _last_message_id { if let Some(last) = _last_message_id {
args.insert(Self::key("last_message_id"), Message::String(CString::new(last).unwrap())); args.insert(
Self::key("last_message_id"),
Message::String(CString::new(last).unwrap()),
);
} }
let reply = self.call_method(&mut client, "GetMessages", Some(args)).await?; let reply = self
.call_method(&mut client, "GetMessages", Some(args))
.await?;
match reply.get(&Self::key("messages")) { match reply.get(&Self::key("messages")) {
Some(Message::Array(items)) => { Some(Message::Array(items)) => {
println!("Number of messages: {}", items.len()); println!("Number of messages: {}", items.len());
for item in items { for item in items {
if let Message::Dictionary(map) = item { if let Message::Dictionary(map) = item {
let guid = Self::get_string(map, "id").map(|s| s.to_string_lossy().into_owned()).unwrap_or_default(); let guid = Self::get_string(map, "id")
let sender = Self::get_string(map, "sender").map(|s| s.to_string_lossy().into_owned()).unwrap_or_default(); .map(|s| s.to_string_lossy().into_owned())
let text = Self::get_string(map, "text").map(|s| s.to_string_lossy().into_owned()).unwrap_or_default(); .unwrap_or_default();
let sender = Self::get_string(map, "sender")
.map(|s| s.to_string_lossy().into_owned())
.unwrap_or_default();
let text = Self::get_string(map, "text")
.map(|s| s.to_string_lossy().into_owned())
.unwrap_or_default();
let date_ts = Self::get_i64_from_str(map, "date").unwrap_or(0); let date_ts = Self::get_i64_from_str(map, "date").unwrap_or(0);
let msg = crate::printers::PrintableMessage { let msg = crate::printers::PrintableMessage {
guid, guid,
date: time::OffsetDateTime::from_unix_timestamp(date_ts).unwrap_or_else(|_| time::OffsetDateTime::UNIX_EPOCH), date: time::OffsetDateTime::from_unix_timestamp(date_ts)
.unwrap_or_else(|_| time::OffsetDateTime::UNIX_EPOCH),
sender, sender,
text, text,
file_transfer_guids: vec![], file_transfer_guids: vec![],
@@ -340,10 +364,20 @@ impl DaemonInterface for XpcDaemonInterface {
let mach_port_name = Self::build_service_name()?; let mach_port_name = Self::build_service_name()?;
let mut client = XPCClient::connect(&mach_port_name); let mut client = XPCClient::connect(&mach_port_name);
let mut args = HashMap::new(); let mut args = HashMap::new();
args.insert(Self::key("conversation_id"), Message::String(CString::new(_conversation_id).unwrap())); args.insert(
args.insert(Self::key("text"), Message::String(CString::new(_text).unwrap())); Self::key("conversation_id"),
let reply = self.call_method(&mut client, "SendMessage", Some(args)).await?; Message::String(CString::new(_conversation_id).unwrap()),
if let Some(uuid) = Self::get_string(&reply, "uuid") { println!("Outgoing message ID: {}", uuid.to_string_lossy()); } );
args.insert(
Self::key("text"),
Message::String(CString::new(_text).unwrap()),
);
let reply = self
.call_method(&mut client, "SendMessage", Some(args))
.await?;
if let Some(uuid) = Self::get_string(&reply, "uuid") {
println!("Outgoing message ID: {}", uuid.to_string_lossy());
}
Ok(()) Ok(())
} }
async fn wait_for_signals(&mut self) -> Result<()> { async fn wait_for_signals(&mut self) -> Result<()> {
@@ -351,7 +385,10 @@ impl DaemonInterface for XpcDaemonInterface {
let mut client = XPCClient::connect(&mach_port_name); let mut client = XPCClient::connect(&mach_port_name);
// Send a subscription/warm-up message so the server loop starts selecting for this client // Send a subscription/warm-up message so the server loop starts selecting for this client
client.send_message(Message::Dictionary(Self::build_request("SubscribeSignals", None))); client.send_message(Message::Dictionary(Self::build_request(
"SubscribeSignals",
None,
)));
println!("Waiting for XPC signals..."); println!("Waiting for XPC signals...");
while let Some(msg) = client.next().await { while let Some(msg) = client.next().await {
@@ -359,7 +396,10 @@ impl DaemonInterface for XpcDaemonInterface {
Message::Dictionary(map) => { Message::Dictionary(map) => {
let name_key = Self::key("name"); let name_key = Self::key("name");
let args_key = Self::key("arguments"); let args_key = Self::key("arguments");
let name = match map.get(&name_key) { Some(Message::String(s)) => s.to_string_lossy().into_owned(), _ => continue }; let name = match map.get(&name_key) {
Some(Message::String(s)) => s.to_string_lossy().into_owned(),
_ => continue,
};
match name.as_str() { match name.as_str() {
"ConversationsUpdated" => { "ConversationsUpdated" => {
@@ -367,8 +407,13 @@ impl DaemonInterface for XpcDaemonInterface {
} }
"MessagesUpdated" => { "MessagesUpdated" => {
if let Some(Message::Dictionary(args)) = map.get(&args_key) { if let Some(Message::Dictionary(args)) = map.get(&args_key) {
if let Some(Message::String(cid)) = args.get(&Self::key("conversation_id")) { if let Some(Message::String(cid)) =
println!("Signal: Messages updated for conversation {}", cid.to_string_lossy()); args.get(&Self::key("conversation_id"))
{
println!(
"Signal: Messages updated for conversation {}",
cid.to_string_lossy()
);
} }
} }
} }
@@ -377,23 +422,52 @@ impl DaemonInterface for XpcDaemonInterface {
} }
"AttachmentDownloadCompleted" => { "AttachmentDownloadCompleted" => {
if let Some(Message::Dictionary(args)) = map.get(&args_key) { if let Some(Message::Dictionary(args)) = map.get(&args_key) {
if let Some(Message::String(aid)) = args.get(&Self::key("attachment_id")) { if let Some(Message::String(aid)) =
println!("Signal: Attachment downloaded: {}", aid.to_string_lossy()); args.get(&Self::key("attachment_id"))
{
println!(
"Signal: Attachment downloaded: {}",
aid.to_string_lossy()
);
} }
} }
} }
"AttachmentDownloadFailed" => { "AttachmentDownloadFailed" => {
if let Some(Message::Dictionary(args)) = map.get(&args_key) { if let Some(Message::Dictionary(args)) = map.get(&args_key) {
if let Some(Message::String(aid)) = args.get(&Self::key("attachment_id")) { if let Some(Message::String(aid)) =
eprintln!("Signal: Attachment download failed: {}", aid.to_string_lossy()); args.get(&Self::key("attachment_id"))
{
eprintln!(
"Signal: Attachment download failed: {}",
aid.to_string_lossy()
);
} }
} }
} }
"AttachmentUploadCompleted" => { "AttachmentUploadCompleted" => {
if let Some(Message::Dictionary(args)) = map.get(&args_key) { if let Some(Message::Dictionary(args)) = map.get(&args_key) {
let upload = args.get(&Self::key("upload_guid")).and_then(|v| match v { Message::String(s) => Some(s.to_string_lossy().into_owned()), _ => None }).unwrap_or_default(); let upload = args
let attachment = args.get(&Self::key("attachment_guid")).and_then(|v| match v { Message::String(s) => Some(s.to_string_lossy().into_owned()), _ => None }).unwrap_or_default(); .get(&Self::key("upload_guid"))
println!("Signal: Attachment uploaded: upload={}, attachment={}", upload, attachment); .and_then(|v| match v {
Message::String(s) => {
Some(s.to_string_lossy().into_owned())
}
_ => None,
})
.unwrap_or_default();
let attachment = args
.get(&Self::key("attachment_guid"))
.and_then(|v| match v {
Message::String(s) => {
Some(s.to_string_lossy().into_owned())
}
_ => None,
})
.unwrap_or_default();
println!(
"Signal: Attachment uploaded: upload={}, attachment={}",
upload, attachment
);
} }
} }
"ConfigChanged" => { "ConfigChanged" => {
@@ -413,23 +487,40 @@ impl DaemonInterface for XpcDaemonInterface {
let mut client = XPCClient::connect(&mach_port_name); let mut client = XPCClient::connect(&mach_port_name);
match _cmd { match _cmd {
ConfigCommands::Print => { ConfigCommands::Print => {
let reply = self.call_method(&mut client, "GetAllSettings", None).await?; let reply = self
let server_url = Self::get_string(&reply, "server_url").map(|s| s.to_string_lossy().into_owned()).unwrap_or_default(); .call_method(&mut client, "GetAllSettings", None)
let username = Self::get_string(&reply, "username").map(|s| s.to_string_lossy().into_owned()).unwrap_or_default(); .await?;
let table = prettytable::table!([b->"Server URL", &server_url], [b->"Username", &username]); let server_url = Self::get_string(&reply, "server_url")
.map(|s| s.to_string_lossy().into_owned())
.unwrap_or_default();
let username = Self::get_string(&reply, "username")
.map(|s| s.to_string_lossy().into_owned())
.unwrap_or_default();
let table =
prettytable::table!([b->"Server URL", &server_url], [b->"Username", &username]);
table.printstd(); table.printstd();
Ok(()) Ok(())
} }
ConfigCommands::SetServerUrl { url } => { ConfigCommands::SetServerUrl { url } => {
let mut args = HashMap::new(); let mut args = HashMap::new();
args.insert(Self::key("server_url"), Message::String(CString::new(url).unwrap())); args.insert(
let _ = self.call_method(&mut client, "UpdateSettings", Some(args)).await?; Self::key("server_url"),
Message::String(CString::new(url).unwrap()),
);
let _ = self
.call_method(&mut client, "UpdateSettings", Some(args))
.await?;
Ok(()) Ok(())
} }
ConfigCommands::SetUsername { username } => { ConfigCommands::SetUsername { username } => {
let mut args = HashMap::new(); let mut args = HashMap::new();
args.insert(Self::key("username"), Message::String(CString::new(username).unwrap())); args.insert(
let _ = self.call_method(&mut client, "UpdateSettings", Some(args)).await?; Self::key("username"),
Message::String(CString::new(username).unwrap()),
);
let _ = self
.call_method(&mut client, "UpdateSettings", Some(args))
.await?;
Ok(()) Ok(())
} }
} }
@@ -437,33 +528,55 @@ impl DaemonInterface for XpcDaemonInterface {
async fn delete_all_conversations(&mut self) -> Result<()> { async fn delete_all_conversations(&mut self) -> Result<()> {
let mach_port_name = Self::build_service_name()?; let mach_port_name = Self::build_service_name()?;
let mut client = XPCClient::connect(&mach_port_name); let mut client = XPCClient::connect(&mach_port_name);
let _ = self.call_method(&mut client, "DeleteAllConversations", None).await?; let _ = self
.call_method(&mut client, "DeleteAllConversations", None)
.await?;
Ok(()) Ok(())
} }
async fn download_attachment(&mut self, _attachment_id: String) -> Result<()> { async fn download_attachment(&mut self, _attachment_id: String) -> Result<()> {
let mach_port_name = Self::build_service_name()?; let mach_port_name = Self::build_service_name()?;
let mut client = XPCClient::connect(&mach_port_name); let mut client = XPCClient::connect(&mach_port_name);
let mut args = HashMap::new(); let mut args = HashMap::new();
args.insert(Self::key("attachment_id"), Message::String(CString::new(_attachment_id).unwrap())); args.insert(
args.insert(Self::key("preview"), Message::String(CString::new("false").unwrap())); Self::key("attachment_id"),
let _ = self.call_method(&mut client, "DownloadAttachment", Some(args)).await?; Message::String(CString::new(_attachment_id).unwrap()),
);
args.insert(
Self::key("preview"),
Message::String(CString::new("false").unwrap()),
);
let _ = self
.call_method(&mut client, "DownloadAttachment", Some(args))
.await?;
Ok(()) Ok(())
} }
async fn upload_attachment(&mut self, _path: String) -> Result<()> { async fn upload_attachment(&mut self, _path: String) -> Result<()> {
let mach_port_name = Self::build_service_name()?; let mach_port_name = Self::build_service_name()?;
let mut client = XPCClient::connect(&mach_port_name); let mut client = XPCClient::connect(&mach_port_name);
let mut args = HashMap::new(); let mut args = HashMap::new();
args.insert(Self::key("path"), Message::String(CString::new(_path).unwrap())); args.insert(
let reply = self.call_method(&mut client, "UploadAttachment", Some(args)).await?; Self::key("path"),
if let Some(guid) = Self::get_string(&reply, "upload_guid") { println!("Upload GUID: {}", guid.to_string_lossy()); } Message::String(CString::new(_path).unwrap()),
);
let reply = self
.call_method(&mut client, "UploadAttachment", Some(args))
.await?;
if let Some(guid) = Self::get_string(&reply, "upload_guid") {
println!("Upload GUID: {}", guid.to_string_lossy());
}
Ok(()) Ok(())
} }
async fn mark_conversation_as_read(&mut self, _conversation_id: String) -> Result<()> { async fn mark_conversation_as_read(&mut self, _conversation_id: String) -> Result<()> {
let mach_port_name = Self::build_service_name()?; let mach_port_name = Self::build_service_name()?;
let mut client = XPCClient::connect(&mach_port_name); let mut client = XPCClient::connect(&mach_port_name);
let mut args = HashMap::new(); let mut args = HashMap::new();
args.insert(Self::key("conversation_id"), Message::String(CString::new(_conversation_id).unwrap())); args.insert(
let _ = self.call_method(&mut client, "MarkConversationAsRead", Some(args)).await?; Self::key("conversation_id"),
Message::String(CString::new(_conversation_id).unwrap()),
);
let _ = self
.call_method(&mut client, "MarkConversationAsRead", Some(args))
.await?;
Ok(()) Ok(())
} }
} }