pub struct Message {Show 32 fields
pub rowid: i32,
pub guid: String,
pub text: Option<String>,
pub service: Option<String>,
pub handle_id: Option<i32>,
pub destination_caller_id: Option<String>,
pub subject: Option<String>,
pub date: i64,
pub date_read: i64,
pub date_delivered: i64,
pub is_from_me: bool,
pub is_read: bool,
pub item_type: i32,
pub other_handle: Option<i32>,
pub share_status: bool,
pub share_direction: Option<bool>,
pub group_title: Option<String>,
pub group_action_type: i32,
pub associated_message_guid: Option<String>,
pub associated_message_type: Option<i32>,
pub balloon_bundle_id: Option<String>,
pub expressive_send_style_id: Option<String>,
pub thread_originator_guid: Option<String>,
pub thread_originator_part: Option<String>,
pub date_edited: i64,
pub associated_message_emoji: Option<String>,
pub chat_id: Option<i32>,
pub num_attachments: i32,
pub deleted_from: Option<i32>,
pub num_replies: i32,
pub components: Vec<BubbleComponent>,
pub edited_parts: Option<EditedMessage>,
}
Expand description
Represents a single row in the message
table.
Additional information is available in the parent module.
Fields§
§rowid: i32
The unique identifier for the message in the database
guid: String
The globally unique identifier for the message
text: Option<String>
The text of the message, which may require calling Self::generate_text()
to populate
service: Option<String>
The service the message was sent from
handle_id: Option<i32>
The ID of the person who sent the message
destination_caller_id: Option<String>
The address the database owner received the message at, i.e. a phone number or email
subject: Option<String>
The content of the Subject field
date: i64
The date the message was written to the database
date_read: i64
The date the message was read
date_delivered: i64
The date a message was delivered
is_from_me: bool
true
if the database owner sent the message, else false
is_read: bool
true
if the message was read by the recipient, else false
item_type: i32
Intermediate data for determining the Variant
of a message
other_handle: Option<i32>
Optional handle for the recipient of a message that includes shared content
Boolean determining whether some shared data is active or inactive, i.e. shared location being enabled or disabled
Boolean determining the direction shared data was sent; false
indicates it was sent from the database owner, true
indicates it was sent to the database owner
group_title: Option<String>
If the message updates the display_name
of the chat, this field will be populated
group_action_type: i32
If the message modified for a group, this will be nonzero
associated_message_guid: Option<String>
The message GUID of a message associated with this one
associated_message_type: Option<i32>
The numeric type code for the associated message, used to determine message variant
balloon_bundle_id: Option<String>
The bundle ID of the app that generated the AppMessage
expressive_send_style_id: Option<String>
Intermediate data for determining the expressive
of a message
thread_originator_guid: Option<String>
Indicates the first message in a thread of replies in get_replies()
thread_originator_part: Option<String>
Indicates the part of a message a reply is pointing to
date_edited: i64
The date the message was most recently edited
associated_message_emoji: Option<String>
If present, this is the emoji associated with a custom emoji tapback
chat_id: Option<i32>
The identifier
of the chat the message belongs to
num_attachments: i32
The number of attached files included in the message
deleted_from: Option<i32>
The identifier
of the chat the message was deleted from
num_replies: i32
The number of replies to the message
components: Vec<BubbleComponent>
The components of the message body, parsed by a TypedStreamDeserializer
or streamtyped::parse()
edited_parts: Option<EditedMessage>
The components of the message that may or may not have been edited or unsent
Implementations§
Source§impl Message
impl Message
Sourcepub fn generate_text<'a>(
&'a mut self,
db: &'a Connection,
) -> Result<&'a str, MessageError>
pub fn generate_text<'a>( &'a mut self, db: &'a Connection, ) -> Result<&'a str, MessageError>
Generate the text of a message, deserializing it as typedstream
(and falling back to streamtyped
) data if necessary.
Sourcepub fn generate_text_legacy<'a>(
&'a mut self,
db: &'a Connection,
) -> Result<&'a str, MessageError>
pub fn generate_text_legacy<'a>( &'a mut self, db: &'a Connection, ) -> Result<&'a str, MessageError>
Generates the text using the legacy parser only, ignoring any typedstream data. This is useful for messages that do not have typedstream data, such as those from older iOS versions.
Warning: This method does not handle typedstream data and will not parse all message types correctly.
Sourcepub fn date(&self, offset: &i64) -> Result<DateTime<Local>, MessageError>
pub fn date(&self, offset: &i64) -> Result<DateTime<Local>, MessageError>
Calculates the date a message was written to the database.
This field is stored as a unix timestamp with an epoch of 2001-01-01 00:00:00
in the local time zone
offset
can be provided by get_offset
or manually.
Sourcepub fn date_delivered(
&self,
offset: &i64,
) -> Result<DateTime<Local>, MessageError>
pub fn date_delivered( &self, offset: &i64, ) -> Result<DateTime<Local>, MessageError>
Calculates the date a message was marked as delivered.
This field is stored as a unix timestamp with an epoch of 2001-01-01 00:00:00
in the local time zone
offset
can be provided by get_offset
or manually.
Sourcepub fn date_read(&self, offset: &i64) -> Result<DateTime<Local>, MessageError>
pub fn date_read(&self, offset: &i64) -> Result<DateTime<Local>, MessageError>
Calculates the date a message was marked as read.
This field is stored as a unix timestamp with an epoch of 2001-01-01 00:00:00
in the local time zone
offset
can be provided by get_offset
or manually.
Sourcepub fn date_edited(&self, offset: &i64) -> Result<DateTime<Local>, MessageError>
pub fn date_edited(&self, offset: &i64) -> Result<DateTime<Local>, MessageError>
Calculates the date a message was most recently edited.
This field is stored as a unix timestamp with an epoch of 2001-01-01 00:00:00
in the local time zone
offset
can be provided by get_offset
or manually.
Sourcepub fn time_until_read(&self, offset: &i64) -> Option<String>
pub fn time_until_read(&self, offset: &i64) -> Option<String>
Gets the time until the message was read. This can happen in two ways:
- You received a message, then waited to read it
- You sent a message, and the recipient waited to read it
In the former case, this subtracts the date read column (date_read
) from the date received column (date
).
In the latter case, this subtracts the date delivered column (date_delivered
) from the date received column (date
).
Not all messages get tagged with the read properties. If more than one message has been sent in a thread before getting read, only the most recent message will get the tag.
offset
can be provided by get_offset
or manually.
Sourcepub fn is_announcement(&self) -> bool
pub fn is_announcement(&self) -> bool
true
if the message is an Announcement
, else false
Sourcepub fn is_tapback(&self) -> bool
pub fn is_tapback(&self) -> bool
true
if the message is a Tapback
to another message, else false
Sourcepub fn is_expressive(&self) -> bool
pub fn is_expressive(&self) -> bool
true
if the message has an Expressive
, else false
Sourcepub fn is_url(&self) -> bool
pub fn is_url(&self) -> bool
true
if the message has a URL preview, else false
Sourcepub fn is_handwriting(&self) -> bool
pub fn is_handwriting(&self) -> bool
true
if the message is a HandwrittenMessage
, else false
Sourcepub fn is_digital_touch(&self) -> bool
pub fn is_digital_touch(&self) -> bool
true
if the message is a Digital Touch
, else false
Sourcepub fn is_poll_vote(&self) -> bool
pub fn is_poll_vote(&self) -> bool
true
if the message is a Poll
vote, else false
Sourcepub fn is_poll_update(&self) -> bool
pub fn is_poll_update(&self) -> bool
true
if the message is a Poll
vote, else false
Sourcepub fn is_part_edited(&self, index: usize) -> bool
pub fn is_part_edited(&self, index: usize) -> bool
true
if the specified message component was edited, else false
Sourcepub fn is_fully_unsent(&self) -> bool
pub fn is_fully_unsent(&self) -> bool
true
if all message components were unsent, else false
Sourcepub fn has_attachments(&self) -> bool
pub fn has_attachments(&self) -> bool
true
if the message contains Attachment
s, else false
Attachments can be queried with Attachment::from_message()
.
Sourcepub fn has_replies(&self) -> bool
pub fn has_replies(&self) -> bool
true
if the message begins a thread, else false
Sourcepub fn is_kept_audio_message(&self) -> bool
pub fn is_kept_audio_message(&self) -> bool
true
if the message indicates a sent audio message was kept, else false
true
if the message is a SharePlay/FaceTime message, else false
Sourcepub fn is_from_me(&self) -> bool
pub fn is_from_me(&self) -> bool
true
if the message was sent by the database owner, else false
Sourcepub fn started_sharing_location(&self) -> bool
pub fn started_sharing_location(&self) -> bool
true
if the message indicates a sender started sharing their location, else false
Sourcepub fn stopped_sharing_location(&self) -> bool
pub fn stopped_sharing_location(&self) -> bool
true
if the message indicates a sender stopped sharing their location, else false
Sourcepub fn is_deleted(&self) -> bool
pub fn is_deleted(&self) -> bool
true
if the message was deleted and is recoverable, else false
Messages removed by deleting an entire conversation or by deleting a single message from a conversation are moved to a separate collection for up to 30 days. Messages present in this collection are restored to the conversations they belong to. Apple details this process here.
Messages that have expired from this restoration process are permanently deleted and cannot be recovered.
Note: This is not the same as an Unsent
message.
Sourcepub fn has_translation(&self, db: &Connection) -> bool
pub fn has_translation(&self, db: &Connection) -> bool
true
if the message was translated, else false
Sourcepub fn get_translation(
&self,
db: &Connection,
) -> Result<Option<Translation>, PlistParseError>
pub fn get_translation( &self, db: &Connection, ) -> Result<Option<Translation>, PlistParseError>
Generates the Translation
for the current message
Sourcepub fn cache_translations(
db: &Connection,
) -> Result<HashSet<String>, TableError>
pub fn cache_translations( db: &Connection, ) -> Result<HashSet<String>, TableError>
Cache all message GUIDs that contain translation data
Sourcepub fn group_action(&self) -> Option<GroupAction<'_>>
pub fn group_action(&self) -> Option<GroupAction<'_>>
Get the group action for the current message
Sourcepub fn get_count(
db: &Connection,
context: &QueryContext,
) -> Result<u64, TableError>
pub fn get_count( db: &Connection, context: &QueryContext, ) -> Result<u64, TableError>
Get the number of messages in the database
§Example
use imessage_database::util::dirs::default_db_path;
use imessage_database::tables::table::{Diagnostic, get_connection};
use imessage_database::tables::messages::Message;
use imessage_database::util::query_context::QueryContext;
let db_path = default_db_path();
let conn = get_connection(&db_path).unwrap();
let context = QueryContext::default();
Message::get_count(&conn, &context);
Sourcepub fn stream_rows<'a>(
db: &'a Connection,
context: &'a QueryContext,
) -> Result<CachedStatement<'a>, TableError>
pub fn stream_rows<'a>( db: &'a Connection, context: &'a QueryContext, ) -> Result<CachedStatement<'a>, TableError>
Stream messages from the database with optional filters.
§Example
use imessage_database::util::dirs::default_db_path;
use imessage_database::tables::table::{Diagnostic, get_connection};
use imessage_database::tables::{messages::Message, table::Table};
use imessage_database::util::query_context::QueryContext;
let db_path = default_db_path();
let conn = get_connection(&db_path).unwrap();
let context = QueryContext::default();
let mut statement = Message::stream_rows(&conn, &context).unwrap();
let messages = statement.query_map([], |row| Ok(Message::from_row(row))).unwrap();
messages.map(|msg| println!("{:#?}", Message::extract(msg)));
Sourcepub fn clean_associated_guid(&self) -> Option<(usize, &str)>
pub fn clean_associated_guid(&self) -> Option<(usize, &str)>
Clean and parse the associated message GUID for tapbacks and replies.
Returns a tuple of (component index, message GUID) if present.
Sourcepub fn get_replies(
&self,
db: &Connection,
) -> Result<HashMap<usize, Vec<Self>>, TableError>
pub fn get_replies( &self, db: &Connection, ) -> Result<HashMap<usize, Vec<Self>>, TableError>
Build a HashMap
of message component index to messages that reply to that component
Sourcepub fn get_votes(&self, db: &Connection) -> Result<Vec<Self>, TableError>
pub fn get_votes(&self, db: &Connection) -> Result<Vec<Self>, TableError>
Build a Vec
of messages that vote on the parent poll
Sourcepub fn as_poll(&self, db: &Connection) -> Result<Option<Poll>, PlistParseError>
pub fn as_poll(&self, db: &Connection) -> Result<Option<Poll>, PlistParseError>
If the message is a poll, attempt to parse and return it
Sourcepub fn get_announcement(&self) -> Option<Announcement<'_>>
pub fn get_announcement(&self) -> Option<Announcement<'_>>
Determine the type of announcement a message contains, if it contains one
Sourcepub fn service(&self) -> Service<'_>
pub fn service(&self) -> Service<'_>
Determine the service the message was sent from, i.e. iMessage, SMS, IRC, etc.
Sourcepub fn payload_data(&self, db: &Connection) -> Option<Value>
pub fn payload_data(&self, db: &Connection) -> Option<Value>
Get a message’s plist from the MESSAGE_PAYLOAD
BLOB column
Calling this hits the database, so it is expensive and should only get invoked when needed.
This column contains data used by iMessage app balloons and can be parsed with
parse_ns_keyed_archiver()
.
Sourcepub fn raw_payload_data(&self, db: &Connection) -> Option<Vec<u8>>
pub fn raw_payload_data(&self, db: &Connection) -> Option<Vec<u8>>
Get a message’s raw data from the MESSAGE_PAYLOAD
BLOB column
Calling this hits the database, so it is expensive and should only get invoked when needed.
This column contains data used by HandwrittenMessage
s.
Sourcepub fn message_summary_info(&self, db: &Connection) -> Option<Value>
pub fn message_summary_info(&self, db: &Connection) -> Option<Value>
Get a message’s plist from the MESSAGE_SUMMARY_INFO
BLOB column
Calling this hits the database, so it is expensive and should only get invoked when needed.
This column contains data used by edited
iMessages.
Sourcepub fn attributed_body(&self, db: &Connection) -> Option<Vec<u8>>
pub fn attributed_body(&self, db: &Connection) -> Option<Vec<u8>>
Get a message’s typedstream from the ATTRIBUTED_BODY
BLOB column
Calling this hits the database, so it is expensive and should only get invoked when needed.
This column contains the message’s body text with any other attributes.
Sourcepub fn get_expressive(&self) -> Expressive<'_>
pub fn get_expressive(&self) -> Expressive<'_>
Determine which Expressive
the message was sent with
Sourcepub fn from_guid(guid: &str, db: &Connection) -> Result<Self, TableError>
pub fn from_guid(guid: &str, db: &Connection) -> Result<Self, TableError>
Create a message from a given GUID; useful for debugging
§Example
use imessage_database::{
tables::{
messages::Message,
table::get_connection,
},
util::dirs::default_db_path,
};
let db_path = default_db_path();
let conn = get_connection(&db_path).unwrap();
if let Ok(mut message) = Message::from_guid("example-guid", &conn) {
let _ = message.generate_text(&conn);
println!("{:#?}", message)
}
Trait Implementations§
Source§impl Cacheable for Message
impl Cacheable for Message
Source§fn cache(db: &Connection) -> Result<HashMap<Self::K, Self::V>, TableError>
fn cache(db: &Connection) -> Result<HashMap<Self::K, Self::V>, TableError>
Used for tapbacks that do not exist in a foreign key table
Builds a map like:
{
"message_guid": {
0: [Message, Message],
1: [Message]
}
}
Where the 0
and 1
are the tapback indexes in the body of the message mapped by message_guid
Source§impl Diagnostic for Message
impl Diagnostic for Message
Source§fn run_diagnostic(db: &Connection) -> Result<(), TableError>
fn run_diagnostic(db: &Connection) -> Result<(), TableError>
Emit diagnostic data for the Messages table
§Example
use imessage_database::util::dirs::default_db_path;
use imessage_database::tables::table::{Diagnostic, get_connection};
use imessage_database::tables::messages::Message;
let db_path = default_db_path();
let conn = get_connection(&db_path).unwrap();
Message::run_diagnostic(&conn);
Source§impl Table for Message
impl Table for Message
Source§fn get(db: &Connection) -> Result<CachedStatement<'_>, TableError>
fn get(db: &Connection) -> Result<CachedStatement<'_>, TableError>
Convert data from the messages table to native Rust data structures, falling back to more compatible queries to ensure compatibility with older database schemas
Source§fn from_row(row: &Row<'_>) -> Result<Message>
fn from_row(row: &Row<'_>) -> Result<Message>
rusqlite::Result
Source§fn extract(
message: Result<Result<Self, Error>, Error>,
) -> Result<Self, TableError>
fn extract( message: Result<Result<Self, Error>, Error>, ) -> Result<Self, TableError>
rusqlite::Result<Self>
into our TableError