~nicohman/signal-rs

ad7bba6ed316afe281e38a8327baf7c1bbf824da — nicohman 3 months ago 32c5e84
Basic attachments
5 files changed, 59 insertions(+), 7 deletions(-)

M Cargo.lock
M Cargo.toml
M README.md
M src/main.rs
M src/presage_manager.rs
M Cargo.lock => Cargo.lock +1 -1
@@ 2668,7 2668,6 @@ checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
[[package]]
name = "presage"
version = "0.1.0"
source = "git+https://github.com/whisperfish/presage#1ede250d04ccc700ee89e3c0632bf96c62452e03"
dependencies = [
 "anyhow",
 "base64 0.12.3",


@@ 2676,6 2675,7 @@ dependencies = [
 "env_logger",
 "futures",
 "hex",
 "hyper 0.14.5",
 "image",
 "libsignal-protocol",
 "libsignal-service",

M Cargo.toml => Cargo.toml +1 -1
@@ 23,7 23,7 @@ phonenumber = "0.3.1"
chrono = "0.4.6"
crossbeam-channel = "0.4.4"
once_cell = "^0"
presage = { git = "https://github.com/whisperfish/presage" }
presage = { path = "../nicohman-presage" }
lazy_static = "1.4.0"
regex = "1.4.1"
reqwest = "0.10.8"

M README.md => README.md +1 -1
@@ 18,5 18,5 @@ A Rust-based signal app with a QML/Kirigami frontend. Uses presage as a backend.
- Re-add attachment support
- Reaction sending
- Group editing/creation
- Profiles
- Avatars
- And much more
\ No newline at end of file

M src/main.rs => src/main.rs +2 -0
@@ 30,6 30,7 @@ use std::collections::*;
mod config;
mod util;
use config::*;
use futures::io::AsyncWrite;
use notify_rust::Notification;
use serde_json::json;
use std::cell::*;


@@ 385,6 386,7 @@ impl SignalUI {
                    .unwrap(),
                res_sender,
                req_receiver,
                config,
            )
            .await;
        });

M src/presage_manager.rs => src/presage_manager.rs +54 -4
@@ 1,6 1,7 @@
use crate::util::*;
use crate::*;
use anyhow::{Context, Result};
use futures::io::AsyncReadExt;
use futures_util::StreamExt;
use pallet::Document;
use pallet::Store;


@@ 22,7 23,11 @@ impl Presage {
        config_store: SledConfigStore,
        res_sender: UnboundedSender<SignalResponse>,
        mut req_receiver: UnboundedReceiver<SignalRequest>,
        config: Config,
    ) {
        let data_dir = config
            .data_dir
            .replace("~", home::home_dir().unwrap().to_str().unwrap());
        let mut manager = Manager::with_config_store(config_store, ProtocolContext::default())
            .expect("Couldn't create Manager");
        let whoami = manager


@@ 79,6 84,8 @@ impl Presage {
                                    }

                                }


                                if let Some(react) = dm.reaction {
                                    if react.target_author_uuid.is_some() && react.emoji.is_some() && react.target_sent_timestamp.is_some() {
                                        if let Some(remove) = react.remove {


@@ 96,7 103,8 @@ impl Presage {
                                        }
                                    }
                                }
                                if let Some(body) = dm.body {
                                if dm.body.is_some() || dm.attachments.len() > 0{
                                    let body = dm.body.unwrap_or_default();
                                    let mut chat_id = response
                                        .metadata
                                        .sender


@@ 110,6 118,26 @@ impl Presage {
                                            master_key: None
                                        };
                                        res_sender.send(SignalResponse::SGroup(g)).expect("Couldn't send SGroup");
                                        }
                                    let mut attachments : Vec<Attachment> = vec![];
                                    // TODO: This blocks the select loop until attachment has been downloaded. It shouldn't do that. Fix this.
                                    for attachment in dm.attachments.iter() {
                                        let path = Path::new(&data_dir).join("attachments").join(attachment.file_name());
                                        if !path.exists() {
                                            let mut key : [u8; 64] = [0; 64];
                                            let mut down = manager.fetch_attachment(attachment).await.unwrap();
                                            key.copy_from_slice(attachment.key.as_ref().unwrap().as_slice());
                                            let mut ciphertext : Vec<u8> = vec![];
                                            down.read_to_end(&mut ciphertext).await.unwrap();
                                            libsignal_service::attachment_cipher::decrypt_in_place(key, &mut ciphertext).unwrap();
                                            let mut f = fs::OpenOptions::new().write(true).create(true).open(&path).unwrap();
                                            f.write_all(&ciphertext).expect("Couldn't write to attachment file");
                                            attachments.push(Attachment {
                                                file: path.into_os_string().into_string().unwrap(),
                                                file_name: attachment.file_name().to_string(),
                                                c_type: AttachmentType::from_mime(attachment.content_type())
                                            });
                                        }
                                    }
                                    if let Some(gc2) = dm.group_v2 {
                                        let gid = get_gid_v2(gc2.master_key.clone().unwrap());


@@ 126,7 154,7 @@ impl Presage {
                                        ID: 0,
                                        message: body,
                                        reactions: vec![],
                                        attachment: Some(vec![]),
                                        attachment: Some(attachments),
                                        outgoing: response.metadata.sender.identifier().to_uppercase() == whoami,
                                    };
                                    res_sender.send(SignalResponse::IDLessMessage(msg)).expect("Couldn't send IDLessMessage");


@@ 153,7 181,8 @@ impl Presage {
                                                }
                                            }
                                        }
                                        if let Some(body) = dm.body {
                                        if dm.body.is_some() || dm.attachments.len() > 0 {
                                            let body = dm.body.unwrap_or_default();
                                            let mut chat_id = sent
                                                .destination_uuid.
                                                unwrap_or(sent.destination_e164.unwrap_or_default()).to_uppercase();


@@ 167,6 196,26 @@ impl Presage {
                                                };
                                                res_sender.send(SignalResponse::SGroup(g)).expect("Couldn't send SGroup");
                                            }
                                            let mut attachments : Vec<Attachment> = vec![];
                                            // TODO: This blocks the select loop until attachment has been downloaded. It shouldn't do that. Fix this.
                                            for attachment in dm.attachments.iter() {
                                                let path = Path::new(&data_dir).join("attachments").join(attachment.file_name());
                                                if !path.exists() {
                                                    let mut key : [u8; 64] = [0; 64];
                                                    let mut down = manager.fetch_attachment(attachment).await.unwrap();
                                                    key.copy_from_slice(attachment.key.as_ref().unwrap().as_slice());
                                                    let mut ciphertext : Vec<u8> = vec![];
                                                    down.read_to_end(&mut ciphertext).await.unwrap();
                                                    libsignal_service::attachment_cipher::decrypt_in_place(key, &mut ciphertext).unwrap();
                                                    let mut f = fs::OpenOptions::new().write(true).create(true).open(&path).unwrap();
                                                    f.write_all(&ciphertext).expect("Couldn't write to attachment file");
                                                    attachments.push(Attachment {
                                                        file: path.into_os_string().into_string().unwrap(),
                                                        file_name: attachment.file_name().to_string(),
                                                        c_type: AttachmentType::from_mime(attachment.content_type())
                                                    });
                                                }
                                            }
                                            if let Some(gc2) = dm.group_v2 {
                                                let gid = get_gid_v2(gc2.master_key.clone().unwrap());
                                                chat_id = gid;


@@ 181,7 230,7 @@ impl Presage {
                                                ID: 0,
                                                message: body,
                                                reactions: vec![],
                                                attachment: Some(vec![]),
                                                attachment: Some(attachments),
                                                outgoing: response.metadata.sender.identifier().to_uppercase() == whoami,
                                            };
                                            res_sender.send(SignalResponse::IDLessMessage(msg)).expect("Couldn't send IDLessMessage");


@@ 283,6 332,7 @@ impl Presage {
            .replace("~", home::home_dir().unwrap().to_str().unwrap());
        // Open, index and setup stores for messages/contacts/groups/avatars
        fs::create_dir_all(Path::new(&data_dir).join("avatars"))?;
        fs::create_dir_all(Path::new(&data_dir).join("attachments"))?;
        let m_db =
            pallet::ext::sled::open(Path::new(&data_dir).join("messages").to_str().unwrap())?;
        let c_db =