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, // Map of channel property -> value ); type RequestableChannelSpec = (HashMap, Vec); type Result = std::result::Result; impl AsRef for std::rc::Rc { 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)> { 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)> { 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> { println!("Connection<{}>::channels()", self.id()); let mut out = Vec::::new(); for channel in self.channels.read().unwrap().values() { out.push(( channel.path(), HashMap::::new(), // FIXME: work out what props should be shown )); } Ok(out) } fn requestable_channel_classes(&self) -> Result> { println!("Connection<{}>::requestable_channel_classes()", self.id()); Ok(requestables()) } }