Skip to content

Commit bd08b8a

Browse files
committed
Group typing indicators
1 parent 228b8c8 commit bd08b8a

File tree

4 files changed

+44
-26
lines changed

4 files changed

+44
-26
lines changed

src/imessage/aps_client.rs

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ pub const MADRID_SERVICE: IDSService = IDSService {
6868
("supports-send-later-messages", Value::Boolean(true)),
6969
("supports-certified-delivery-v1", Value::Boolean(true)),
7070
("supports-transcript-backgrounds", Value::Boolean(true)),
71+
("supports-gti", Value::Boolean(true)),
7172
],
7273
flags: 17,
7374
capabilities_name: "Messenger"
@@ -222,24 +223,19 @@ impl IMClient {
222223
}).ok())
223224
}
224225

225-
// typing
226226
if let IDSRecvMessage {
227227
sender: Some(sender),
228228
target: Some(target),
229229
is_typing: Some(0),
230-
message,
230+
message: None,
231231
..
232232
} = &payload {
233233
return Ok(payload.to_message(Some(ConversationData {
234234
participants: vec![sender.clone(), target.clone()],
235235
cv_name: None,
236236
sender_guid: None,
237237
after_guid: None,
238-
}), if message.is_some() {
239-
Message::StopTyping
240-
} else {
241-
Message::Typing
242-
}).ok())
238+
}), Message::Typing(true)).ok())
243239
}
244240

245241
// errors

src/imessage/messages.rs

Lines changed: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1596,11 +1596,10 @@ pub enum Message {
15961596
React(ReactMessage),
15971597
Delivered,
15981598
Read,
1599-
Typing,
1599+
Typing(bool),
16001600
Unsend(UnsendMessage),
16011601
Edit(EditMessage),
16021602
IconChange(IconChangeMessage),
1603-
StopTyping,
16041603
EnableSmsActivation(bool),
16051604
MessageReadOnDevice,
16061605
SmsConfirmSent(bool /* status */),
@@ -1651,11 +1650,10 @@ impl Message {
16511650
Self::ChangeParticipants(_) => 190,
16521651
Self::Delivered => 101,
16531652
Self::Read => 102,
1654-
Self::Typing => 100,
1653+
Self::Typing(_) => 100,
16551654
Self::Edit(_) => 118,
16561655
Self::Unsend(_) => 118,
16571656
Self::IconChange(_) => 190,
1658-
Self::StopTyping => 100,
16591657
Self::EnableSmsActivation(_) => 145,
16601658
Self::MessageReadOnDevice => 147,
16611659
Self::SmsConfirmSent(status) => if *status { 146 } else { 149 },
@@ -1730,7 +1728,7 @@ impl Message {
17301728
return Some(true)
17311729
}
17321730
match self {
1733-
Self::Typing => Some(true),
1731+
Self::Typing(_) => Some(true),
17341732
Self::Delivered => Some(true),
17351733
Self::Edit(_) => Some(true),
17361734
Self::Unsend(_) => Some(true),
@@ -1772,8 +1770,8 @@ impl fmt::Display for Message {
17721770
Message::Delivered => {
17731771
write!(f, "delivered")
17741772
},
1775-
Message::Typing => {
1776-
write!(f, "typing")
1773+
Message::Typing(typing) => {
1774+
write!(f, "{}", if *typing { "typing" } else { "stopped typing" })
17771775
},
17781776
Message::Edit(e) => {
17791777
write!(f, "Edited {}", e.new_parts.raw_text())
@@ -1784,9 +1782,6 @@ impl fmt::Display for Message {
17841782
Message::IconChange(_e) => {
17851783
write!(f, "changed the group icon")
17861784
},
1787-
Message::StopTyping => {
1788-
write!(f, "stopped typing")
1789-
},
17901785
Message::EnableSmsActivation(enabled) => {
17911786
write!(f, "{} sms activation", if *enabled { "enabled" } else { "disabled" })
17921787
},
@@ -1935,7 +1930,7 @@ impl MessageInst {
19351930
match &self.message {
19361931
Message::Read => false,
19371932
Message::Delivered => false,
1938-
Message::Typing => false,
1933+
Message::Typing(typing) => self.conversation.as_ref().is_some_and(|a| a.participants.len() > 2) || !*typing,
19391934
Message::MessageReadOnDevice => false,
19401935
Message::PeerCacheInvalidate => false,
19411936
Message::Unschedule => false,
@@ -1946,8 +1941,7 @@ impl MessageInst {
19461941

19471942
pub fn get_ex(&self) -> Option<u32> {
19481943
match &self.message {
1949-
Message::Typing => Some(0),
1950-
Message::StopTyping => Some(0),
1944+
Message::Typing(_) => Some(0),
19511945
_ => None
19521946
}
19531947
}
@@ -1968,7 +1962,7 @@ impl MessageInst {
19681962

19691963
pub fn get_send_participants(&self, my_handles: &[String]) -> Vec<String> {
19701964
let mut target_participants = self.conversation.as_ref().unwrap().participants.clone();
1971-
if let Message::Delivered | Message::Typing | Message::StopTyping = self.message {
1965+
if let Message::Delivered | Message::Typing(_) = self.message {
19721966
// do not send delivery reciepts to other devices on same acct
19731967
target_participants.retain(|p| {
19741968
!my_handles.contains(p)
@@ -2131,14 +2125,16 @@ impl MessageInst {
21312125
};
21322126
plist_to_bin(&raw).unwrap()
21332127
},
2134-
Message::StopTyping => {
2135-
let raw = RawIMessage {
2128+
Message::Typing(typing) => {
2129+
let raw = RawEncryptedTyping {
21362130
participants: conversation.participants.clone(),
21372131
sender_guid: conversation.sender_guid.clone(),
21382132
pv: 0,
21392133
gv: "8".to_string(),
2140-
v: "1".to_string(),
2134+
v: if !*typing { Some("1".to_string()) } else { None },
21412135
cv_name: conversation.cv_name.clone(),
2136+
gt: if conversation.participants.len() > 2 { Some(true) } else { None },
2137+
u: if *typing { Some(true) } else { None },
21422138
..Default::default()
21432139
};
21442140

@@ -2369,7 +2365,6 @@ impl MessageInst {
23692365
},
23702366
Message::Delivered => panic!("no enc body!"),
23712367
Message::Read => panic!("no enc body!"),
2372-
Message::Typing => panic!("no enc body!"),
23732368
Message::MessageReadOnDevice => panic!("no enc body!"),
23742369
Message::PeerCacheInvalidate => panic!("no enc body!"),
23752370
Message::Error(_) => panic!("no enc body!"),
@@ -2505,6 +2500,16 @@ impl MessageInst {
25052500
return wrapper.to_message(None, Message::EnableSmsActivation(true));
25062501
}
25072502
}
2503+
if wrapper.is_typing == Some(0) {
2504+
if let Ok(loaded) = plist::from_value::<RawEncryptedTyping>(&value) {
2505+
return wrapper.to_message(Some(ConversationData {
2506+
participants: loaded.participants.clone(),
2507+
cv_name: loaded.cv_name.clone(),
2508+
sender_guid: loaded.sender_guid.clone(),
2509+
after_guid: None,
2510+
}), Message::Typing(loaded.u == Some(true)));
2511+
}
2512+
}
25082513
if let Ok(loaded) = plist::from_value::<RawSmsDeactivateMessage>(&value) {
25092514
if loaded.ue {
25102515
return wrapper.to_message(None, Message::EnableSmsActivation(false));

src/imessage/rawmessages.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,21 @@ struct RawMMCSBalloon {
364364
size: usize,
365365
}
366366

367+
#[derive(Serialize, Deserialize, Default)]
368+
struct RawEncryptedTyping {
369+
pv: u32,
370+
#[serde(rename = "p")]
371+
participants: Vec<String>,
372+
u: Option<bool>,
373+
gt: Option<bool>,
374+
#[serde(rename = "gid")]
375+
sender_guid: Option<String>,
376+
gv: String,
377+
v: Option<String>,
378+
#[serde(rename = "n")]
379+
cv_name: Option<String>,
380+
}
381+
367382
#[derive(Serialize, Deserialize, Default)]
368383
struct RawIMessage {
369384
#[serde(rename = "t")]

src/macos.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,15 @@
22
use std::{collections::HashMap, time::{Duration, SystemTime}};
33

44
use async_trait::async_trait;
5-
use open_absinthe::nac::{HardwareConfig, ValidationCtx};
5+
use open_absinthe::nac::ValidationCtx;
66
use plist::{Data, Dictionary, Value};
77
use serde::{Deserialize, Serialize};
88
use uuid::Uuid;
99

1010
use crate::{activation::ActivationInfo, util::{encode_hex, get_bag, REQWEST, plist_to_buf, IDS_BAG}, DebugMeta, OSConfig, PushError, RegisterMeta};
1111

12+
pub use open_absinthe::nac::HardwareConfig;
13+
1214
#[derive(Serialize, Deserialize, Clone)]
1315
pub struct MacOSConfig {
1416
pub inner: HardwareConfig,

0 commit comments

Comments
 (0)