137 lines
4.6 KiB
Rust
137 lines
4.6 KiB
Rust
use crate::padfoot::{get_var_str, get_var_u32, requestables, Channel, DbusAction, VarArg};
|
|
use crate::telepathy;
|
|
|
|
use async_std::task::block_on;
|
|
use dbus::tree::MethodErr;
|
|
use dc::contact::Contact;
|
|
use deltachat as dc;
|
|
|
|
use std::collections::HashMap;
|
|
|
|
use super::Connection;
|
|
|
|
type ChannelSpec = (
|
|
dbus::Path<'static>, // Object path on this connection
|
|
HashMap<String, VarArg>, // Map of channel property -> value
|
|
);
|
|
|
|
type RequestableChannelSpec = (HashMap<String, VarArg>, Vec<String>);
|
|
|
|
type Result<T> = std::result::Result<T, MethodErr>;
|
|
|
|
impl AsRef<dyn telepathy::ConnectionInterfaceRequests + 'static> for std::rc::Rc<Connection> {
|
|
fn as_ref(&self) -> &(dyn telepathy::ConnectionInterfaceRequests + 'static) {
|
|
&**self
|
|
}
|
|
}
|
|
|
|
impl telepathy::ConnectionInterfaceRequests for Connection {
|
|
fn create_channel(
|
|
&self,
|
|
request: HashMap<&str, VarArg>,
|
|
) -> Result<(dbus::Path<'static>, HashMap<String, VarArg>)> {
|
|
println!("Connection<{}>::create_channel({:?})", self.id(), request);
|
|
|
|
Err(MethodErr::no_arg()) // FIXME: should be NotImplemented?
|
|
}
|
|
|
|
fn ensure_channel(
|
|
&self,
|
|
request: HashMap<&str, VarArg>,
|
|
) -> Result<(bool, dbus::Path<'static>, HashMap<String, VarArg>)> {
|
|
let path = self.path().clone();
|
|
println!("Connection<{}>::ensure_channel({:?})", self.id(), request);
|
|
|
|
// Empathy sends this for the request:
|
|
//
|
|
// {
|
|
// "org.freedesktop.Telepathy.Channel.TargetID": Variant("me@example.com"),
|
|
// "org.freedesktop.Telepathy.Channel.TargetHandleType": Variant(1),
|
|
// "org.freedesktop.Telepathy.Channel.ChannelType": Variant("org.freedesktop.Telepathy.Channel.Type.Text")
|
|
// }
|
|
|
|
// FIXME: life would be easier with TargetHandle
|
|
let target_id = request
|
|
.get("org.freedesktop.Telepathy.Channel.TargetID")
|
|
.map(|va| get_var_str(va))
|
|
.unwrap();
|
|
|
|
let target_handle_type = request
|
|
.get("org.freedesktop.Telepathy.Channel.TargetHandleType")
|
|
.map(|va| get_var_u32(va))
|
|
.unwrap();
|
|
|
|
let channel_type = request
|
|
.get("org.freedesktop.Telepathy.Channel.ChannelType")
|
|
.map(|va| get_var_str(va))
|
|
.unwrap();
|
|
|
|
// Text only
|
|
if channel_type != "org.freedesktop.Telepathy.Channel.Type.Text" {
|
|
println!(" Wrong channel type: {:?}", channel_type);
|
|
return Err(MethodErr::no_arg());
|
|
};
|
|
|
|
// IMs only
|
|
if target_handle_type != 1 {
|
|
println!(" Wrong target handle type: {:?}", target_handle_type);
|
|
return Err(MethodErr::no_arg());
|
|
};
|
|
|
|
let ctx = self.ctx.read().unwrap();
|
|
|
|
let target_handle =
|
|
block_on(Contact::lookup_id_by_addr(&ctx, target_id.clone(), dc::contact::Origin::Unknown));
|
|
if target_handle == 0 {
|
|
println!("Couldn't find target handle for {}", target_id);
|
|
return Err(MethodErr::no_arg());
|
|
};
|
|
|
|
let chat_id = dc::chat::ChatId::new(target_handle);
|
|
let channel_path = Connection::build_channel_path(path, chat_id);
|
|
|
|
// Return an existing channel if it already exists
|
|
let chans = self.channels.read().unwrap();
|
|
if let Some(channel) = chans.get(&channel_path) {
|
|
return Ok((false, channel_path, channel.chan_props()));
|
|
}
|
|
|
|
// Now we need to discover or create a chat id for the contact
|
|
let chat_id = block_on(dc::chat::create_by_contact_id(&ctx, target_handle)).unwrap();
|
|
let channel = Channel::new(
|
|
self.actq.clone(),
|
|
chat_id,
|
|
self.ctx.clone(),
|
|
dc::constants::DC_CONTACT_ID_SELF, // initiator is self in this case
|
|
channel_path.clone(),
|
|
true, // requested
|
|
target_handle,
|
|
);
|
|
let response = channel.chan_props(); // FIXME: fill with data about the channel
|
|
|
|
// Send signal
|
|
self.actq.send(DbusAction::NewChannel(channel)).unwrap();
|
|
|
|
Ok((true, channel_path, response))
|
|
}
|
|
|
|
fn channels(&self) -> Result<Vec<ChannelSpec>> {
|
|
println!("Connection<{}>::channels()", self.id());
|
|
|
|
let mut out = Vec::<ChannelSpec>::new();
|
|
for channel in self.channels.read().unwrap().values() {
|
|
out.push((
|
|
channel.path(),
|
|
HashMap::<String, VarArg>::new(), // FIXME: work out what props should be shown
|
|
));
|
|
}
|
|
|
|
Ok(out)
|
|
}
|
|
|
|
fn requestable_channel_classes(&self) -> Result<Vec<RequestableChannelSpec>> {
|
|
println!("Connection<{}>::requestable_channel_classes()", self.id());
|
|
Ok(requestables())
|
|
}
|
|
}
|