mirror of
https://github.com/chatmail/core.git
synced 2026-04-27 02:16:29 +03:00
attach selfavatar
This commit is contained in:
committed by
holger krekel
parent
3cf39dace0
commit
7f723ef2bf
55
src/chat.rs
55
src/chat.rs
@@ -1597,6 +1597,46 @@ pub fn set_gossiped_timestamp(context: &Context, chat_id: u32, timestamp: i64) {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn shall_attach_selfavatar(context: &Context, chat_id: u32) -> Result<bool, Error> {
|
||||
let resend_every_days = 14;
|
||||
let timestamp_some_days_ago = time() - resend_every_days * 24 * 60 * 60;
|
||||
let needs_attach = context.sql.query_map(
|
||||
"SELECT c.selfavatar_sent
|
||||
FROM chats_contacts cc
|
||||
LEFT JOIN contacts c ON c.id=cc.contact_id
|
||||
WHERE cc.chat_id=? AND cc.contact_id!=?;",
|
||||
params![chat_id, DC_CONTACT_ID_SELF],
|
||||
|row| Ok(row.get::<_, i64>(0)),
|
||||
|rows| {
|
||||
let mut needs_attach = false;
|
||||
for row in rows {
|
||||
if let Ok(selfavatar_sent) = row {
|
||||
let selfavatar_sent = selfavatar_sent?;
|
||||
if selfavatar_sent < timestamp_some_days_ago {
|
||||
needs_attach = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(needs_attach)
|
||||
},
|
||||
)?;
|
||||
Ok(needs_attach)
|
||||
}
|
||||
|
||||
pub fn set_selfavatar_timestamp(
|
||||
context: &Context,
|
||||
chat_id: u32,
|
||||
timestamp: i64,
|
||||
) -> Result<(), Error> {
|
||||
context.sql.execute(
|
||||
"UPDATE contacts
|
||||
SET selfavatar_sent=?
|
||||
WHERE id IN(SELECT contact_id FROM chats_contacts WHERE chat_id=?);",
|
||||
params![timestamp, chat_id],
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn remove_contact_from_chat(
|
||||
context: &Context,
|
||||
chat_id: u32,
|
||||
@@ -2435,4 +2475,19 @@ mod tests {
|
||||
|
||||
assert_eq!(chat2.name, chat.name);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_shall_attach_selfavatar() {
|
||||
let t = dummy_context();
|
||||
let chat_id = create_group_chat(&t.ctx, VerifiedStatus::Unverified, "foo").unwrap();
|
||||
assert!(!shall_attach_selfavatar(&t.ctx, chat_id).unwrap());
|
||||
|
||||
let (contact_id, _) =
|
||||
Contact::add_or_lookup(&t.ctx, "", "foo@bar.org", Origin::IncomingUnknownTo).unwrap();
|
||||
add_contact_to_chat(&t.ctx, chat_id, contact_id);
|
||||
assert!(shall_attach_selfavatar(&t.ctx, chat_id).unwrap());
|
||||
|
||||
assert!(set_selfavatar_timestamp(&t.ctx, chat_id, time()).is_ok());
|
||||
assert!(!shall_attach_selfavatar(&t.ctx, chat_id).unwrap());
|
||||
}
|
||||
}
|
||||
|
||||
18
src/job.rs
18
src/job.rs
@@ -633,7 +633,15 @@ pub fn job_send_msg(context: &Context, msg_id: MsgId) -> Result<(), Error> {
|
||||
/* create message */
|
||||
let needs_encryption = msg.param.get_int(Param::GuaranteeE2ee).unwrap_or_default();
|
||||
|
||||
let mimefactory = MimeFactory::from_msg(context, &msg)?;
|
||||
let attach_selfavatar = match chat::shall_attach_selfavatar(context, msg.chat_id) {
|
||||
Ok(attach_selfavatar) => attach_selfavatar,
|
||||
Err(err) => {
|
||||
warn!(context, "job: cannot get selfavatar-state: {}", err);
|
||||
false
|
||||
}
|
||||
};
|
||||
|
||||
let mimefactory = MimeFactory::from_msg(context, &msg, attach_selfavatar)?;
|
||||
let mut rendered_msg = mimefactory.render().map_err(|err| {
|
||||
message::set_msg_failed(context, msg_id, Some(err.to_string()));
|
||||
err
|
||||
@@ -672,6 +680,7 @@ pub fn job_send_msg(context: &Context, msg_id: MsgId) -> Result<(), Error> {
|
||||
if rendered_msg.is_gossiped {
|
||||
chat::set_gossiped_timestamp(context, msg.chat_id, time());
|
||||
}
|
||||
|
||||
if 0 != rendered_msg.last_added_location_id {
|
||||
if let Err(err) = location::set_kml_sent_timestamp(context, msg.chat_id, time()) {
|
||||
error!(context, "Failed to set kml sent_timestamp: {:?}", err);
|
||||
@@ -684,6 +693,13 @@ pub fn job_send_msg(context: &Context, msg_id: MsgId) -> Result<(), Error> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if attach_selfavatar {
|
||||
if let Err(err) = chat::set_selfavatar_timestamp(context, msg.chat_id, time()) {
|
||||
error!(context, "Failed to set selfavatar timestamp: {:?}", err);
|
||||
}
|
||||
}
|
||||
|
||||
if rendered_msg.is_encrypted && needs_encryption == 0 {
|
||||
msg.param.set_int(Param::GuaranteeE2ee, 1);
|
||||
msg.save_param_to_disk(context);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
use chrono::TimeZone;
|
||||
use lettre_email::{mime, Address, Header, MimeMultipartType, PartBuilder};
|
||||
|
||||
use crate::blob::BlobObject;
|
||||
use crate::chat::{self, Chat};
|
||||
use crate::config::Config;
|
||||
use crate::constants::*;
|
||||
@@ -41,6 +42,7 @@ pub struct MimeFactory<'a, 'b> {
|
||||
pub req_mdn: bool,
|
||||
pub context: &'a Context,
|
||||
last_added_location_id: u32,
|
||||
attach_selfavatar: bool,
|
||||
}
|
||||
|
||||
/// Result of rendering a message, ready to be submitted to a send job.
|
||||
@@ -62,7 +64,11 @@ pub struct RenderedEmail {
|
||||
}
|
||||
|
||||
impl<'a, 'b> MimeFactory<'a, 'b> {
|
||||
pub fn from_msg(context: &'a Context, msg: &'b Message) -> Result<MimeFactory<'a, 'b>, Error> {
|
||||
pub fn from_msg(
|
||||
context: &'a Context,
|
||||
msg: &'b Message,
|
||||
add_selfavatar: bool,
|
||||
) -> Result<MimeFactory<'a, 'b>, Error> {
|
||||
let chat = Chat::load_from_db(context, msg.chat_id)?;
|
||||
|
||||
let mut factory = MimeFactory {
|
||||
@@ -84,6 +90,7 @@ impl<'a, 'b> MimeFactory<'a, 'b> {
|
||||
references: String::default(),
|
||||
req_mdn: false,
|
||||
last_added_location_id: 0,
|
||||
attach_selfavatar: add_selfavatar,
|
||||
context,
|
||||
};
|
||||
|
||||
@@ -210,6 +217,7 @@ impl<'a, 'b> MimeFactory<'a, 'b> {
|
||||
references: String::default(),
|
||||
req_mdn: false,
|
||||
last_added_location_id: 0,
|
||||
attach_selfavatar: false,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -873,6 +881,21 @@ impl<'a, 'b> MimeFactory<'a, 'b> {
|
||||
}
|
||||
}
|
||||
|
||||
if self.attach_selfavatar {
|
||||
match context.get_config(Config::Selfavatar) {
|
||||
Some(path) => match build_selfavatar_file(context, path) {
|
||||
Ok((part, filename)) => {
|
||||
parts.push(part);
|
||||
protected_headers.push(Header::new("Chat-Profile-Image".into(), filename))
|
||||
}
|
||||
Err(err) => warn!(context, "mimefactory: cannot attach selfavatar: {}", err),
|
||||
},
|
||||
None => {
|
||||
protected_headers.push(Header::new("Chat-Profile-Image".into(), "0".into()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Single part, render as regular message.
|
||||
if parts.len() == 1 {
|
||||
return Ok(parts.pop().unwrap());
|
||||
@@ -1024,6 +1047,31 @@ fn build_body_file(
|
||||
Ok((mail, filename_to_send))
|
||||
}
|
||||
|
||||
fn build_selfavatar_file(context: &Context, path: String) -> Result<(PartBuilder, String), Error> {
|
||||
let blob = BlobObject::from_path(context, path)?;
|
||||
let filename_to_send = match blob.suffix() {
|
||||
Some(suffix) => format!("avatar.{}", suffix),
|
||||
None => "avatar".to_string(),
|
||||
};
|
||||
let mimetype = match message::guess_msgtype_from_suffix(blob.as_rel_path()) {
|
||||
Some(res) => res.1.parse()?,
|
||||
None => mime::APPLICATION_OCTET_STREAM,
|
||||
};
|
||||
let body = std::fs::read(blob.to_abs_path())?;
|
||||
let encoded_body = base64::encode(&body);
|
||||
|
||||
let part = PartBuilder::new()
|
||||
.content_type(&mimetype)
|
||||
.header((
|
||||
"Content-Disposition",
|
||||
format!("attachment; filename=\"{}\"", &filename_to_send),
|
||||
))
|
||||
.header(("Content-Transfer-Encoding", "base64"))
|
||||
.body(encoded_body);
|
||||
|
||||
Ok((part, filename_to_send))
|
||||
}
|
||||
|
||||
pub(crate) fn vec_contains_lowercase(vec: &[String], part: &str) -> bool {
|
||||
let partlc = part.to_lowercase();
|
||||
for cur in vec.iter() {
|
||||
|
||||
Reference in New Issue
Block a user