Add image receipt to the text channel
This is disturbingly useless with Empathy because it doesn't know how to display text/html parts, or plain image/png parts either :/ Time to start playing with KDE Spacebar? How does it handle them?
This commit is contained in:
@@ -43,6 +43,7 @@ impl telepathy::ChannelInterfaceMessages for Channel {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let ctx = self.ctx.read().unwrap();
|
let ctx = self.ctx.read().unwrap();
|
||||||
|
let blobdir = ctx.get_blobdir();
|
||||||
|
|
||||||
let msg_id = match dc::chat::send_msg(&ctx, self.chat_id, &mut delta_msg) {
|
let msg_id = match dc::chat::send_msg(&ctx, self.chat_id, &mut delta_msg) {
|
||||||
Ok(msg_id) => msg_id,
|
Ok(msg_id) => msg_id,
|
||||||
@@ -53,7 +54,7 @@ impl telepathy::ChannelInterfaceMessages for Channel {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let token = format!("{}", msg_id.to_u32());
|
let token = format!("{}", msg_id.to_u32());
|
||||||
let dbus_parts = convert_msg(&delta_msg);
|
let dbus_parts = convert_msg(blobdir, &delta_msg).map_err(|_| MethodErr::no_arg())?;
|
||||||
|
|
||||||
let messages_sig = telepathy::ChannelInterfaceMessagesMessageSent {
|
let messages_sig = telepathy::ChannelInterfaceMessagesMessageSent {
|
||||||
content: dbus_parts,
|
content: dbus_parts,
|
||||||
@@ -90,7 +91,7 @@ impl telepathy::ChannelInterfaceMessages for Channel {
|
|||||||
fn supported_content_types(&self) -> Result<Vec<String>> {
|
fn supported_content_types(&self) -> Result<Vec<String>> {
|
||||||
println!("Channel::supported_content_types()");
|
println!("Channel::supported_content_types()");
|
||||||
|
|
||||||
Ok(vec!["text/plain".to_string()]) // TODO: image support
|
Ok(vec!["*/*".to_string()])
|
||||||
}
|
}
|
||||||
|
|
||||||
fn message_types(&self) -> Result<Vec<u32>> {
|
fn message_types(&self) -> Result<Vec<u32>> {
|
||||||
@@ -111,13 +112,15 @@ impl telepathy::ChannelInterfaceMessages for Channel {
|
|||||||
|
|
||||||
let mut out = Vec::<Vec<HashMap<String, VarArg>>>::new();
|
let mut out = Vec::<Vec<HashMap<String, VarArg>>>::new();
|
||||||
let ctx = self.ctx.read().unwrap();
|
let ctx = self.ctx.read().unwrap();
|
||||||
|
let blobdir = ctx.get_blobdir();
|
||||||
|
|
||||||
for msg_id in dc::chat::get_chat_msgs(&ctx, self.chat_id, 0, None) {
|
for msg_id in dc::chat::get_chat_msgs(&ctx, self.chat_id, 0, None) {
|
||||||
if let Ok(msg) = dc::message::Message::load_from_db(&ctx, msg_id) {
|
if let Ok(msg) = dc::message::Message::load_from_db(&ctx, msg_id) {
|
||||||
match msg.get_state() {
|
match msg.get_state() {
|
||||||
MessageState::InFresh | MessageState::InNoticed => {
|
MessageState::InFresh | MessageState::InNoticed => {
|
||||||
println!(" A message: {:?}", msg);
|
println!(" A message: {:?}", msg);
|
||||||
out.push(convert_msg(&msg))
|
let parts = convert_msg(blobdir, &msg).map_err(|_| MethodErr::no_arg())?;
|
||||||
|
out.push(parts);
|
||||||
}
|
}
|
||||||
_ => continue,
|
_ => continue,
|
||||||
}
|
}
|
||||||
|
@@ -401,6 +401,7 @@ impl Connection {
|
|||||||
let chans = c2.read().unwrap();
|
let chans = c2.read().unwrap();
|
||||||
let u_ctx = ctx.clone();
|
let u_ctx = ctx.clone();
|
||||||
let ctx = u_ctx.read().unwrap();
|
let ctx = u_ctx.read().unwrap();
|
||||||
|
let blobdir = ctx.get_blobdir();
|
||||||
|
|
||||||
// Autocreate channel if it doesn't already exist
|
// Autocreate channel if it doesn't already exist
|
||||||
// FIXME: unknown contacts need more care than this
|
// FIXME: unknown contacts need more care than this
|
||||||
@@ -453,11 +454,16 @@ impl Connection {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let parts = convert_msg(&msg);
|
let parts = convert_msg(blobdir, &msg);
|
||||||
|
if parts.is_err() {
|
||||||
|
println!("can't convert, skipping: {}", parts.unwrap_err());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
let sig =
|
let sig = telepathy::ChannelInterfaceMessagesMessageReceived {
|
||||||
telepathy::ChannelInterfaceMessagesMessageReceived { message: parts }
|
message: parts.unwrap(),
|
||||||
.to_emit_message(&chan_path);
|
}
|
||||||
|
.to_emit_message(&chan_path);
|
||||||
|
|
||||||
actq.send(DbusAction::Signal(sig)).unwrap();
|
actq.send(DbusAction::Signal(sig)).unwrap();
|
||||||
|
|
||||||
|
@@ -1,35 +1,47 @@
|
|||||||
use crate::padfoot::{var_i64, var_str, var_u32, VarArg};
|
use crate::padfoot::{var_bytearray, var_i64, var_str, var_u32, VarArg};
|
||||||
|
|
||||||
use deltachat::message::Message;
|
use dc::constants::Viewtype as Vt;
|
||||||
|
use dc::message::Message;
|
||||||
|
use deltachat as dc;
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
type Part = HashMap<String, VarArg>;
|
||||||
|
type Result<T> = std::result::Result<T, Box<dyn std::error::Error>>;
|
||||||
|
|
||||||
// Turns a deltachat::message::Message into a Telepathy Message_Part_List
|
// Turns a deltachat::message::Message into a Telepathy Message_Part_List
|
||||||
pub fn convert_msg(msg: &Message) -> Vec<HashMap<String, VarArg>> {
|
pub fn convert_msg(blobdir: &std::path::Path, msg: &Message) -> Result<Vec<Part>> {
|
||||||
if msg.is_setupmessage() {
|
if msg.is_setupmessage() {
|
||||||
return convert_setupmessage(msg);
|
return Ok(convert_setupmessage(msg));
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut parts = vec![build_props(msg)];
|
let mut parts = vec![make_props(msg)];
|
||||||
|
|
||||||
if let Some(text) = msg.get_text() {
|
// TODO: Check. Can a deltachat message have multiple parts? Can an image
|
||||||
parts.push(build_plain(&text));
|
// viewtype have text as well?
|
||||||
}
|
let result = match msg.get_viewtype() {
|
||||||
|
Vt::Text => build_txt(msg),
|
||||||
|
Vt::Unknown => build_unknown(msg),
|
||||||
|
Vt::Audio | Vt::Voice => build_snd(msg),
|
||||||
|
Vt::Video => build_vid(msg),
|
||||||
|
_ => build_attachment(blobdir, msg),
|
||||||
|
};
|
||||||
|
|
||||||
// TODO: other parts. Can a deltachat message have multiple parts?
|
result.map(|mut more| {
|
||||||
|
parts.append(&mut more);
|
||||||
parts
|
parts
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn convert_setupmessage(msg: &Message) -> Vec<HashMap<String, VarArg>> {
|
fn convert_setupmessage(msg: &Message) -> Vec<Part> {
|
||||||
let msg_id = msg.get_id();
|
let msg_id = msg.get_id();
|
||||||
vec![
|
vec![
|
||||||
build_props(msg),
|
make_props(msg),
|
||||||
build_plain(&format!("Setup message received. To apply it, reply with:\nIMEX: {} nnnn-nnnn-nnnn-nnnn-nnnn-nnnn-nnnn-nnnn-nnnn\nNo whitespace in the setup-code!", msg_id.to_u32())),
|
make_plain(&format!("Setup message received. To apply it, reply with:\nIMEX: {} nnnn-nnnn-nnnn-nnnn-nnnn-nnnn-nnnn-nnnn-nnnn\nNo whitespace in the setup-code!", msg_id.to_u32())),
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_props(msg: &Message) -> HashMap<String, VarArg> {
|
fn make_props(msg: &Message) -> Part {
|
||||||
let msg_id = msg.get_id();
|
let msg_id = msg.get_id();
|
||||||
let mut out = HashMap::new();
|
let mut out = HashMap::new();
|
||||||
|
|
||||||
@@ -63,14 +75,65 @@ fn build_props(msg: &Message) -> HashMap<String, VarArg> {
|
|||||||
out
|
out
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_plain(text: &str) -> HashMap<String, VarArg> {
|
fn make_plain(text: &str) -> Part {
|
||||||
|
make_content("text/plain", None, var_str(text.to_string()))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn make_content(type_: &str, id: Option<&str>, content: VarArg) -> Part {
|
||||||
let mut out = HashMap::new();
|
let mut out = HashMap::new();
|
||||||
|
|
||||||
out.insert(
|
out.insert("content-type".to_string(), var_str(type_.to_string()));
|
||||||
"content-type".to_string(),
|
out.insert("content".to_string(), content);
|
||||||
var_str("text/plain".to_string()),
|
|
||||||
);
|
id.map(|txt| out.insert("identifier".to_string(), var_str(txt.to_string())));
|
||||||
out.insert("content".to_string(), var_str(text.to_string()));
|
|
||||||
|
|
||||||
out
|
out
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn build_snd(_msg: &Message) -> Result<Vec<Part>> {
|
||||||
|
Ok(vec![make_plain("(a sound file was received)")])
|
||||||
|
}
|
||||||
|
|
||||||
|
fn build_txt(msg: &Message) -> Result<Vec<Part>> {
|
||||||
|
Ok(vec![make_plain(
|
||||||
|
&msg.get_text().unwrap_or_else(|| "".to_string()),
|
||||||
|
)])
|
||||||
|
}
|
||||||
|
|
||||||
|
fn build_unknown(_msg: &Message) -> Result<Vec<Part>> {
|
||||||
|
Ok(vec![make_plain("(a message of unknown type was received)")])
|
||||||
|
}
|
||||||
|
|
||||||
|
fn build_vid(_msg: &Message) -> Result<Vec<Part>> {
|
||||||
|
Ok(vec![make_plain("(a video was received)")])
|
||||||
|
}
|
||||||
|
|
||||||
|
// The message contains a file. Detect the content-type and construct a part
|
||||||
|
// containing the data in full.
|
||||||
|
fn build_attachment(blobdir: &std::path::Path, msg: &Message) -> Result<Vec<Part>> {
|
||||||
|
let mime = msg
|
||||||
|
.get_filemime()
|
||||||
|
.unwrap_or_else(|| "application/octet-stream".to_string());
|
||||||
|
let filename = msg.get_filename().ok_or("Failed to get filename")?;
|
||||||
|
|
||||||
|
let path: std::path::PathBuf = [blobdir, &std::path::Path::new(&filename)].iter().collect();
|
||||||
|
// let mut path = std::path::PathBuf::from(blobdir);
|
||||||
|
// path.push(filename);
|
||||||
|
|
||||||
|
let data =
|
||||||
|
std::fs::read(&path).map_err(|e| format!("Failed to read file {:?}: {}", path, e))?;
|
||||||
|
|
||||||
|
println!("MIME type for attachment: {}", mime);
|
||||||
|
|
||||||
|
let html = make_content(
|
||||||
|
"text/html",
|
||||||
|
None,
|
||||||
|
var_str("<img src=\"cid:picture\" />".to_string()),
|
||||||
|
);
|
||||||
|
|
||||||
|
let txt = make_plain("(an image was sent but cannot be displayed)");
|
||||||
|
|
||||||
|
let blob = make_content(&mime, Some("picture"), var_bytearray(data));
|
||||||
|
|
||||||
|
Ok(vec![html, txt, blob])
|
||||||
|
}
|
||||||
|
@@ -20,6 +20,10 @@ pub fn var_bool(item: bool) -> VarArg {
|
|||||||
var_arg(Box::new(item))
|
var_arg(Box::new(item))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn var_bytearray(item: std::vec::Vec<u8>) -> VarArg {
|
||||||
|
var_arg(Box::new(item))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn var_u32(item: u32) -> VarArg {
|
pub fn var_u32(item: u32) -> VarArg {
|
||||||
var_arg(Box::new(item))
|
var_arg(Box::new(item))
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user