Skip to content

Commit

Permalink
Merge pull request #57 from ReagentX/feat/cs/shareplay-messages
Browse files Browse the repository at this point in the history
Feat/cs/shareplay messages
  • Loading branch information
ReagentX authored Jan 13, 2023
2 parents 800d54f + 9c95932 commit e0c4be2
Show file tree
Hide file tree
Showing 5 changed files with 98 additions and 52 deletions.
2 changes: 2 additions & 0 deletions imessage-database/src/message_types/variants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,8 @@ pub enum Variant<'a> {
Normal,
/// A message that has been edited or unsent
Edited,
/// A SharePlay message
SharePlay,
}

/// Defines behavior for different types of messages that have custom balloons
Expand Down
19 changes: 18 additions & 1 deletion imessage-database/src/tables/messages.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ pub struct Message {
pub date_delivered: i64,
pub is_from_me: bool,
pub is_read: bool,
pub item_type: i32,
pub group_title: Option<String>,
pub associated_message_guid: Option<String>,
pub associated_message_type: Option<i32>,
Expand Down Expand Up @@ -110,6 +111,7 @@ impl Table for Message {
date_delivered: row.get("date_delivered").unwrap_or(0),
is_from_me: row.get("is_from_me")?,
is_read: row.get("is_read")?,
item_type: row.get("item_type").unwrap_or_default(),
group_title: row.get("group_title").unwrap_or(None),
associated_message_guid: row.get("associated_message_guid").unwrap_or(None),
associated_message_type: row.get("associated_message_type").unwrap_or(None),
Expand Down Expand Up @@ -439,10 +441,15 @@ impl Message {
}

/// `true` if the message begins a thread, else `false`
fn has_replies(&self) -> bool {
pub fn has_replies(&self) -> bool {
self.num_replies > 0
}

/// `true` if the message is a SharePlay/FaceTime message, else `false`
pub fn is_shareplay(&self) -> bool {
self.item_type == 6
}

/// Get the index of the part of a message a reply is pointing to
pub fn get_reply_index(&self) -> usize {
if let Some(parts) = &self.thread_originator_part {
Expand Down Expand Up @@ -609,9 +616,12 @@ impl Message {

/// Get the variant of a message, see [crate::message_types::variants] for detail.
pub fn variant(&self) -> Variant {
// Check if a message was edited first as those have special properties
if self.is_edited() {
return Variant::Edited;
}

// Handle different types of bundle IDs next, as those are most common
if let Some(associated_message_type) = self.associated_message_type {
return match associated_message_type {
// Standard iMessages with either text or a message payload
Expand Down Expand Up @@ -657,6 +667,12 @@ impl Message {
x => Variant::Unknown(x),
};
}

// Any other rarer cases belong here
if self.is_shareplay() {
return Variant::SharePlay;
}

Variant::Normal
}

Expand Down Expand Up @@ -788,6 +804,7 @@ mod tests {
date_delivered: i64::default(),
is_from_me: false,
is_read: false,
item_type: 0,
group_title: None,
associated_message_guid: None,
associated_message_type: Some(i32::default()),
Expand Down
2 changes: 2 additions & 0 deletions imessage-exporter/src/exporters/exporter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ pub(super) trait Writer<'a> {
fn format_expressive(&self, msg: &'a Message) -> &'a str;
/// Format an announcement message
fn format_announcement(&self, msg: &'a Message) -> String;
/// Format a SharePlay message
fn format_shareplay(&self) -> &str;
/// Format an edited message
fn format_edited(&self, msg: &'a Message, indent: &str) -> Result<String, MessageError>;
fn write_to_file(file: &Path, text: &str);
Expand Down
67 changes: 41 additions & 26 deletions imessage-exporter/src/exporters/html.rs
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,16 @@ impl<'a> Writer<'a> for HTML<'a> {
);
}

// Handle SharePlay
if message.is_shareplay() {
self.add_line(
&mut formatted_message,
self.format_shareplay(),
"<span class=\"shareplay\">",
"</span>",
);
}

// Generate the message body from it's components
for (idx, message_part) in message_parts.iter().enumerate() {
// Write the part div start
Expand Down Expand Up @@ -597,6 +607,10 @@ impl<'a> Writer<'a> for HTML<'a> {
msg.group_title.as_deref().unwrap_or(UNKNOWN)
)
}
fn format_shareplay(&self) -> &str {
"SharePlay Message Ended"
}

fn format_edited(&self, msg: &'a Message, _: &str) -> Result<String, MessageError> {
if let Some(payload) = msg.message_summary_info(&self.config.db) {
let edited_message =
Expand Down Expand Up @@ -777,32 +791,6 @@ impl<'a> BalloonFormatter for HTML<'a> {
out_s
}

fn format_handwriting(&self, _: &AppMessage, _: &str) -> String {
String::from("Handwritten messages are not yet supported!")
}

fn format_apple_pay(&self, balloon: &AppMessage, _: &str) -> String {
self.balloon_to_html(balloon, "Apple Pay", &mut [])
}

fn format_fitness(&self, balloon: &AppMessage, _: &str) -> String {
self.balloon_to_html(balloon, "Fitness", &mut [])
}

fn format_slideshow(&self, balloon: &AppMessage, _: &str) -> String {
self.balloon_to_html(balloon, "Slideshow", &mut [])
}

fn format_generic_app(
&self,
balloon: &AppMessage,
bundle_id: &str,
attachments: &mut Vec<Attachment>,
_: &str,
) -> String {
self.balloon_to_html(balloon, bundle_id, attachments)
}

fn format_collaboration(&self, balloon: &CollaborationMessage, _: &str) -> String {
let mut out_s = String::new();

Expand Down Expand Up @@ -859,6 +847,32 @@ impl<'a> BalloonFormatter for HTML<'a> {

out_s
}

fn format_handwriting(&self, _: &AppMessage, _: &str) -> String {
String::from("Handwritten messages are not yet supported!")
}

fn format_apple_pay(&self, balloon: &AppMessage, _: &str) -> String {
self.balloon_to_html(balloon, "Apple Pay", &mut [])
}

fn format_fitness(&self, balloon: &AppMessage, _: &str) -> String {
self.balloon_to_html(balloon, "Fitness", &mut [])
}

fn format_slideshow(&self, balloon: &AppMessage, _: &str) -> String {
self.balloon_to_html(balloon, "Slideshow", &mut [])
}

fn format_generic_app(
&self,
balloon: &AppMessage,
bundle_id: &str,
attachments: &mut Vec<Attachment>,
_: &str,
) -> String {
self.balloon_to_html(balloon, bundle_id, attachments)
}
}

impl<'a> HTML<'a> {
Expand Down Expand Up @@ -1016,6 +1030,7 @@ mod tests {
date_delivered: i64::default(),
is_from_me: false,
is_read: false,
item_type: 0,
group_title: None,
associated_message_guid: None,
associated_message_type: Some(i32::default()),
Expand Down
60 changes: 35 additions & 25 deletions imessage-exporter/src/exporters/txt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,11 @@ impl<'a> Writer<'a> for TXT<'a> {
self.add_line(&mut formatted_message, &edited, &indent);
}

// Handle SharePlay
if message.is_shareplay() {
self.add_line(&mut formatted_message, self.format_shareplay(), &indent);
}

// Generate the message body from it's components
for (idx, message_part) in message_parts.iter().enumerate() {
match message_part {
Expand Down Expand Up @@ -383,6 +388,10 @@ impl<'a> Writer<'a> for TXT<'a> {
)
}

fn format_shareplay(&self) -> &str {
"SharePlay Message\nEnded"
}

fn format_edited(&self, msg: &'a Message, indent: &str) -> Result<String, MessageError> {
if let Some(payload) = msg.message_summary_info(&self.config.db) {
// Parse the edited message
Expand Down Expand Up @@ -487,6 +496,31 @@ impl<'a> BalloonFormatter for TXT<'a> {
out_s
}

fn format_collaboration(&self, balloon: &CollaborationMessage, indent: &str) -> String {
let mut out_s = String::from(indent);

if let Some(name) = balloon.app_name {
out_s.push_str(name);
} else if let Some(bundle_id) = balloon.bundle_id {
out_s.push_str(bundle_id);
}

if !out_s.is_empty() {
out_s.push_str(" message:\n");
}

if let Some(title) = balloon.title {
self.add_line(&mut out_s, title, indent);
}

if let Some(url) = balloon.get_url() {
self.add_line(&mut out_s, url, indent);
}

// We want to keep the newlines between blocks, but the last one should be removed
out_s.strip_suffix('\n').unwrap_or(&out_s).to_string()
}

fn format_handwriting(&self, _: &AppMessage, indent: &str) -> String {
format!("{indent}Handwritten messages are not yet supported!")
}
Expand Down Expand Up @@ -582,31 +616,6 @@ impl<'a> BalloonFormatter for TXT<'a> {
// We want to keep the newlines between blocks, but the last one should be removed
out_s.strip_suffix('\n').unwrap_or(&out_s).to_string()
}

fn format_collaboration(&self, balloon: &CollaborationMessage, indent: &str) -> String {
let mut out_s = String::from(indent);

if let Some(name) = balloon.app_name {
out_s.push_str(name);
} else if let Some(bundle_id) = balloon.bundle_id {
out_s.push_str(bundle_id);
}

if !out_s.is_empty() {
out_s.push_str(" message:\n");
}

if let Some(title) = balloon.title {
self.add_line(&mut out_s, title, indent);
}

if let Some(url) = balloon.get_url() {
self.add_line(&mut out_s, url, indent);
}

// We want to keep the newlines between blocks, but the last one should be removed
out_s.strip_suffix('\n').unwrap_or(&out_s).to_string()
}
}

impl<'a> TXT<'a> {
Expand Down Expand Up @@ -649,6 +658,7 @@ mod tests {
date_delivered: i64::default(),
is_from_me: false,
is_read: false,
item_type: 0,
group_title: None,
associated_message_guid: None,
associated_message_type: Some(i32::default()),
Expand Down

0 comments on commit e0c4be2

Please # to comment.