aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoreta <hi@theta.eu.org>2019-11-08 20:06:24 +0000
committereta <hi@theta.eu.org>2019-11-08 20:06:24 +0000
commit7e12390c66ac84694858d214fea327caeb7ce90f (patch)
tree514fa286f48320ba186125501507468517dd3987
parentae81c18da1b3fc73c3c8103e85efff68fcde7c3c (diff)
downloadsms-irc-7e12390c66ac84694858d214fea327caeb7ce90f.tar.gz
sms-irc-7e12390c66ac84694858d214fea327caeb7ce90f.tar.bz2
sms-irc-7e12390c66ac84694858d214fea327caeb7ce90f.zip
Less crappy message stub handling
- Message stubs are now actually handled instead of being dropped on the floor, and are either converted into a warning or an actual message. - As a side-effect of this work, missed calls are now properly announced! Yay! - More work probably needs doing around notifying the user about ciphertext messages (in a non-spammy fashion)
-rw-r--r--Cargo.lock2
-rw-r--r--src/whatsapp.rs33
-rw-r--r--src/whatsapp_msg.rs47
3 files changed, 60 insertions, 22 deletions
diff --git a/Cargo.lock b/Cargo.lock
index d487d5c..339f8a1 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2545,7 +2545,7 @@ dependencies = [
[[package]]
name = "whatsappweb-eta"
version = "0.5.0-pre1"
-source = "git+https://git.theta.eu.org/whatsappweb-rs.git/#1769795e6853de519bb8e2923890b1cf69d12636"
+source = "git+https://git.theta.eu.org/whatsappweb-rs.git/#7fb5c1de9e9a300400362e1e255451124651f677"
dependencies = [
"base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
"bincode 1.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
diff --git a/src/whatsapp.rs b/src/whatsapp.rs
index 542742d..eb43a03 100644
--- a/src/whatsapp.rs
+++ b/src/whatsapp.rs
@@ -5,7 +5,7 @@ use whatsappweb::Contact as WaContact;
use whatsappweb::Chat as WaChat;
use whatsappweb::GroupMetadata;
use whatsappweb::message::ChatMessage as WaMessage;
-use whatsappweb::message::{ChatMessageContent, Peer, MessageId};
+use whatsappweb::message::{ChatMessageContent, Peer, MessageId, MessageStubType};
use whatsappweb::session::PersistentSession as WaPersistentSession;
use whatsappweb::event::WaEvent;
use whatsappweb::req::WaRequest;
@@ -327,7 +327,7 @@ impl WhatsappManager {
use whatsappweb::message::{Direction};
trace!("processing WA message (new {}): {:?}", is_new, msg);
- let WaMessage { direction, content, id, quoted, .. } = msg;
+ let WaMessage { direction, content, id, quoted, stub_type, .. } = msg;
debug!("got message from dir {:?}", direction);
// If we don't mark things as read, we have to check every 'new' message,
// because they might not actually be new.
@@ -403,6 +403,7 @@ impl WhatsappManager {
id: id.clone(),
peer: peer.clone(),
ts: msg.time,
+ stub_type: stub_type.clone(),
from, group, content, quoted
};
let (msgs, is_media) = self.msgproc.process_wa_incoming(inc)?;
@@ -410,16 +411,26 @@ impl WhatsappManager {
for msg in msgs {
self.store_message(&msg.from, &msg.text, msg.group, msg.ts)?;
}
- // The > 0 check is here to avoid us storing a message ID when we actually never
- // got the message, because it was sent as a missing-ciphertext stub earlier or
- // something.
- //
- // Either way, we want to ensure that we send *something* for each message we're
- // marking as seen! Otherwise things get dropped on the floor.
- //
- // (FIXME: actually expose this stub type in ww-rs and send it as an alert)
+ // If no messages are generated from the processor, say something about it.
if num_msgs == 0 {
- warn!("Message {} is empty (for now).", id.0);
+ if let Some(st) = stub_type {
+ warn!("Message {} has stub type {:?}", id.0, st);
+ // CIPHERTEXT stubs mean "I'm about to send you the real message, but I can't
+ // just now because rekeying or something". The real message contents get
+ // sent with the same message ID, so storing it in the database now is a
+ // Bad Idea.
+ //
+ // All other stubs *should* (!) be fine though, and we store them here (after
+ // generating a loud warning in case it's _not_ fine), to avoid generating
+ // said loud warning every time we reconnect and load in backlog.
+ if st != MessageStubType::CIPHERTEXT {
+ self.store.store_wa_msgid(id.0.clone())?;
+ }
+ }
+ else {
+ // This is an interesting case, and shouldn't really happen...
+ warn!("Message {} is empty, and isn't even a stub!", id.0);
+ }
}
else if !is_media {
self.store.store_wa_msgid(id.0.clone())?;
diff --git a/src/whatsapp_msg.rs b/src/whatsapp_msg.rs
index de5aded..7f8fab9 100644
--- a/src/whatsapp_msg.rs
+++ b/src/whatsapp_msg.rs
@@ -3,7 +3,7 @@
use whatsappweb::{Jid, MediaType};
use chrono::prelude::*;
use futures::sync::mpsc::UnboundedSender;
-use whatsappweb::message::{ChatMessageContent, QuotedChatMessage, MessageId, Peer};
+use whatsappweb::message::{ChatMessageContent, QuotedChatMessage, MessageId, Peer, MessageStubType};
use regex::{Regex, Captures};
use huawei_modem::pdu::PduAddress;
use std::sync::Arc;
@@ -21,6 +21,7 @@ pub struct IncomingMessage {
pub group: Option<i32>,
pub content: ChatMessageContent,
pub quoted: Option<QuotedChatMessage>,
+ pub stub_type: Option<MessageStubType>,
pub ts: NaiveDateTime
}
pub struct ProcessedIncomingMessage {
@@ -88,24 +89,50 @@ impl WaMessageProcessor {
}
Ok(None)
}
+ fn stub_to_text(st: MessageStubType) -> Option<&'static str> {
+ use self::MessageStubType::*;
+ let ret = match st {
+ CALL_MISSED_VOICE => "\x01ACTION tried to voice call you\x01",
+ CALL_MISSED_VIDEO => "\x01ACTION tried to video call you\x01",
+ CALL_MISSED_GROUP_VOICE => "\x01ACTION tried to group voice call\x01",
+ CALL_MISSED_GROUP_VIDEO => "\x01ACTION tried to group video call\x01",
+ E2E_IDENTITY_CHANGED => "\x01ACTION is now using a different device (!)\x01",
+ E2E_ENCRYPTED => "\x01ACTION is now using end-to-end encryption\x01",
+ // FIXME: this probably needs Special Handling (how do we get the number?!).
+ INDIVIDUAL_CHANGE_NUMBER => "\x01ACTION changed their phone number (to something?)\x01",
+ GROUP_PARTICIPANT_CHANGE_NUMBER => "\x01ACTION changed their phone number (to something?)\x01",
+ // CIPHERTEXT stubs should never ever ever return any message text,
+ // because they'll be replaced with the real message text once it arrives!
+ CIPHERTEXT => return None,
+ _ => return None
+ };
+ Some(ret)
+ }
pub fn process_wa_incoming(&mut self, inc: IncomingMessage) -> Result<(Vec<ProcessedIncomingMessage>, bool)> {
- let IncomingMessage { id, peer, from, group, content, ts, quoted } = inc;
+ let IncomingMessage { id, peer, from, group, content, ts, quoted, stub_type } = inc;
let mut ret = Vec::with_capacity(2);
let mut is_media = false;
let text = match content {
ChatMessageContent::Text(s) => self.process_wa_text_message(&s),
ChatMessageContent::Unimplemented(mut det) => {
if det.trim() == "" {
- debug!("Discarding empty unimplemented message.");
- return Ok((ret, is_media));
+ if let Some(st) = stub_type.and_then(|x| Self::stub_to_text(x)) {
+ st.to_owned()
+ }
+ else {
+ debug!("Discarding empty unimplemented message.");
+ return Ok((ret, is_media));
+ }
}
- if det.len() > 128 {
- det = det.graphemes(true)
- .take(128)
- .chain(std::iter::once("…"))
- .collect();
+ else {
+ if det.len() > 128 {
+ det = det.graphemes(true)
+ .take(128)
+ .chain(std::iter::once("…"))
+ .collect();
+ }
+ format!("[\x02\x0304unimplemented\x0f] {}", det)
}
- format!("[\x02\x0304unimplemented\x0f] {}", det)
},
ChatMessageContent::LiveLocation { lat, long, speed, .. } => {
// FIXME: use write!() maybe