Skip to content

Commit 8ac4a32

Browse files
committed
Polls
1 parent bd08b8a commit 8ac4a32

File tree

3 files changed

+48
-31
lines changed

3 files changed

+48
-31
lines changed

src/imessage/aps_client.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ pub const MADRID_SERVICE: IDSService = IDSService {
6969
("supports-certified-delivery-v1", Value::Boolean(true)),
7070
("supports-transcript-backgrounds", Value::Boolean(true)),
7171
("supports-gti", Value::Boolean(true)),
72+
("supports-polls", Value::Boolean(true)),
7273
],
7374
flags: 17,
7475
capabilities_name: "Messenger"

src/imessage/messages.rs

Lines changed: 30 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -675,11 +675,11 @@ pub enum BalloonLayout {
675675
pub struct Balloon {
676676
pub url: String,
677677
pub session: Option<String>, // UUID
678-
pub layout: BalloonLayout,
678+
pub layout: Option<BalloonLayout>,
679679
pub ld_text: Option<String>,
680680
pub is_live: bool,
681681

682-
pub icon: Vec<u8>,
682+
pub icon: Option<Vec<u8>>,
683683
}
684684

685685
impl Balloon {
@@ -701,7 +701,7 @@ impl Balloon {
701701
layout: unpacked.layout,
702702
ld_text: unpacked.ldtext,
703703
is_live: unpacked.live_layout_info.is_some(),
704-
icon: ungzip(&*unpacked.app_icon)?,
704+
icon: unpacked.app_icon.map(|a| ungzip(&a).unwrap()),
705705
})
706706
}
707707

@@ -710,10 +710,10 @@ impl Balloon {
710710
item: RawBalloonData {
711711
ldtext: self.ld_text.clone(),
712712
layout: self.layout.clone(),
713-
app_icon: NSData {
714-
data: gzip(&self.icon)?.into(),
713+
app_icon: self.icon.as_ref().map(|icon| NSData {
714+
data: gzip(&icon).unwrap().into(),
715715
class: NSDataClass::NSMutableData
716-
},
716+
}),
717717
app_name: app.name.clone(),
718718
session_identifier: self.session.as_ref().map(|session| Uuid::from_str(&session).unwrap().into()),
719719
live_layout_info: if self.is_live {
@@ -912,7 +912,8 @@ pub enum ReactMessageType {
912912
},
913913
Extension {
914914
spec: ExtensionApp,
915-
body: MessageParts
915+
body: MessageParts,
916+
is_meta: bool,
916917
},
917918
}
918919

@@ -950,11 +951,11 @@ impl ReactMessageType {
950951
)
951952
}
952953
},
953-
Self::Extension { spec: ExtensionApp { balloon: None, .. }, body } => {
954+
Self::Extension { spec: ExtensionApp { balloon: None, .. }, body, .. } => {
954955
body.raw_text()
955956
}
956957
,
957-
Self::Extension { spec: ExtensionApp { balloon: Some(_), .. }, body } => {
958+
Self::Extension { spec: ExtensionApp { balloon: Some(_), .. }, body, .. } => {
958959
"\u{fffd}".to_string() // replacement character
959960
}
960961
}
@@ -967,8 +968,9 @@ impl ReactMessageType {
967968
} else {
968969
reaction.get_idx() + 3000
969970
},
970-
Self::Extension { spec: ExtensionApp { balloon: None, .. }, body: _ } => 1000,
971-
Self::Extension { spec: ExtensionApp { balloon: Some(_), .. }, body: _ } => 2,
971+
Self::Extension { spec: ExtensionApp { balloon: None, .. }, body: _, .. } => 1000,
972+
Self::Extension { spec: ExtensionApp { balloon: Some(_), .. }, body: _, is_meta: false } => 2,
973+
Self::Extension { spec: ExtensionApp { balloon: Some(_), .. }, body: _, is_meta: true } => 4000,
972974
}
973975
}
974976

@@ -979,29 +981,29 @@ impl ReactMessageType {
979981

980982
fn notification(&self) -> bool {
981983
match self {
982-
Self::React { reaction: _, enable: _ } => true,
983-
Self::Extension { spec: _, body: _ } => false,
984+
Self::React { .. } => true,
985+
Self::Extension { is_meta, .. } => *is_meta,
984986
}
985987
}
986988

987989
fn prid(&self) -> Option<String> {
988990
match self {
989-
Self::Extension { spec: ExtensionApp { balloon: None, .. }, body: _ } => Some("3cN".to_string()),
991+
Self::Extension { spec: ExtensionApp { balloon: None, .. }, body: _, .. } => Some("3cN".to_string()),
990992
_ => None,
991993
}
992994
}
993995

994996
fn get_xml(&self) -> Option<String> {
995997
match self {
996998
Self::React { reaction: _, enable: _ } => None,
997-
Self::Extension { spec: _, body } => {
999+
Self::Extension { spec: _, body, .. } => {
9981000
Some(body.to_xml(None))
9991001
},
10001002
}
10011003
}
10021004

10031005
fn is_balloon(&self) -> bool {
1004-
matches!(self, Self::Extension { spec: ExtensionApp { balloon: Some(_), .. }, body: _ })
1006+
matches!(self, Self::Extension { spec: ExtensionApp { balloon: Some(_), .. }, body: _, .. })
10051007
}
10061008
}
10071009

@@ -2157,13 +2159,15 @@ impl MessageInst {
21572159
let text = react.get_text();
21582160

21592161
let mut balloon_id: Option<String> = None;
2162+
let mut balloon_name: Option<String> = None;
21602163
let mut balloon_part: Option<Vec<u8>> = None;
21612164
let mut app_info: Option<Data> = None;
2162-
if let ReactMessageType::Extension { spec: app_obj, body: _ } = &react.reaction {
2165+
if let ReactMessageType::Extension { spec: app_obj, body: _, .. } = &react.reaction {
21632166
let (app, balloon) = app_obj.to_raw()?;
21642167
app_info = if balloon.is_none() { Some(app.into()) } else { None };
21652168
balloon_part = balloon;
21662169
balloon_id = Some(app_obj.bundle_id.clone());
2170+
balloon_name = Some(app_obj.name.clone());
21672171
}
21682172

21692173
let (balloon_part, balloon_part_mmcs) = if let Some(balloon_part) = balloon_part {
@@ -2187,7 +2191,9 @@ impl MessageInst {
21872191
cv_name: conversation.cv_name.clone(),
21882192
notification: if react.reaction.notification() { Some(plist_to_bin(&NotificationData {
21892193
ams: react.to_text.clone(),
2190-
amc: 1
2194+
amc: if balloon_name.is_some() { 9 } else { 1 },
2195+
amd: balloon_name,
2196+
amb: balloon_id.clone(),
21912197
}).unwrap().into()) } else { None },
21922198
amk: if let Some(part) = react.to_part { format!("p:{}/{}", part, react.to_uuid) } else { react.to_uuid.clone() },
21932199
type_spec: app_info,
@@ -2637,7 +2643,7 @@ impl MessageInst {
26372643
}), Message::RenameMessage(RenameMessage { new_name: loaded.new_name.clone() }));
26382644
}
26392645
if let Ok(loaded) = plist::from_value::<RawReactMessage>(&value) {
2640-
let (to_uuid, to_part) = if loaded.amt == 2 {
2646+
let (to_uuid, to_part) = if loaded.amt == 2 || loaded.amt == 4000 {
26412647
(loaded.amk, None)
26422648
} else {
26432649
let target_msg_data = Regex::new(r"p:([0-9]+)/([0-9A-F\-]+)").unwrap()
@@ -2646,16 +2652,17 @@ impl MessageInst {
26462652
};
26472653

26482654
let msg = match loaded.amt {
2649-
2 => {
2655+
2 | 4000 => {
26502656
let balloon_part = Self::get_balloon(loaded.balloon_part, loaded.balloon_part_mmcs, apns).await;
2651-
let (Some(xml), Some(balloon), Some(balloon_id)) = (&loaded.xml, &balloon_part, &loaded.balloon_id) else {
2657+
let (Some(balloon), Some(balloon_id)) = (&balloon_part, &loaded.balloon_id) else {
26522658
return Err(PushError::BadMsg)
26532659
};
26542660

26552661
let data = ExtensionApp::from_bp(balloon, balloon_id)?;
26562662
ReactMessageType::Extension {
26572663
spec: data,
2658-
body: MessageParts::parse_parts(xml, None),
2664+
body: loaded.xml.as_ref().map(|xml| MessageParts::parse_parts(xml, None)).unwrap_or(MessageParts(vec![])),
2665+
is_meta: loaded.amt == 4000,
26592666
}
26602667
},
26612668
1000 => {
@@ -2666,6 +2673,7 @@ impl MessageInst {
26662673
ReactMessageType::Extension {
26672674
spec: data,
26682675
body: MessageParts::parse_parts(xml, None),
2676+
is_meta: false,
26692677
}
26702678
},
26712679
2007 | 3007 => {

src/imessage/rawmessages.rs

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ use crate::util::{NSData, NSUUID, NSURL};
99
struct NotificationData {
1010
pub ams: String,
1111
pub amc: u64,
12+
pub amd: Option<String>,
13+
pub amb: Option<String>,
1214
}
1315

1416
#[derive(Serialize, Deserialize)]
@@ -446,11 +448,11 @@ struct RawIMessage {
446448
struct RawBalloonData {
447449
ldtext: Option<String>,
448450
#[serde(flatten)]
449-
layout: BalloonLayout,
451+
layout: Option<BalloonLayout>,
450452
#[serde(rename = "an")]
451453
app_name: String,
452454
#[serde(rename = "ai")]
453-
app_icon: NSData,
455+
app_icon: Option<NSData>,
454456
session_identifier: Option<NSUUID>,
455457
live_layout_info: Option<NSData>,
456458
#[serde(rename = "URL")]
@@ -462,14 +464,20 @@ impl Serialize for RawBalloonData {
462464
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
463465
where
464466
S: Serializer {
465-
let mut serialized = plist::to_value(&self.layout).map_err(serde::ser::Error::custom)?;
466-
let Some(dict) = serialized.as_dictionary_mut() else { panic!("not a dictionary!") };
467-
468-
dict.extend([
467+
let mut dict = Dictionary::from_iter([
469468
("an".to_string(), self.app_name.clone().into()),
470-
("ai".to_string(), plist::to_value(&self.app_icon).map_err(serde::ser::Error::custom)?),
471469
("URL".to_string(), plist::to_value(&self.url).map_err(serde::ser::Error::custom)?)
472-
].into_iter());
470+
]);
471+
472+
if let Some(layout) = &self.layout {
473+
let serialized = plist::to_value(&layout).map_err(serde::ser::Error::custom)?;
474+
let Some(d) = serialized.into_dictionary() else { panic!("not a dictionary!") };
475+
dict.extend(d)
476+
}
477+
478+
if let Some(app_icon) = &self.app_icon {
479+
dict.insert("ai".to_string(), plist::to_value(&app_icon).map_err(serde::ser::Error::custom)?);
480+
}
473481

474482
if let Some(appid) = &self.appid {
475483
dict.insert("appid".to_string(), appid.into());
@@ -487,7 +495,7 @@ impl Serialize for RawBalloonData {
487495
dict.insert("liveLayoutInfo".to_string(), plist::to_value(&live_layout_info).map_err(serde::ser::Error::custom)?);
488496
}
489497

490-
serialized.serialize(serializer)
498+
dict.serialize(serializer)
491499
}
492500
}
493501

0 commit comments

Comments
 (0)