pub struct Message {Show 34 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 filter_action: Option<i32>,
pub filter_sub_action: Option<i32>,
pub components: Vec<BubbleComponent>,
pub edited_parts: Option<EditedMessage>,
}Expand description
Row from the message table, with body and edit metadata parsed during row decoding.
Fields§
§rowid: i32Message row ID.
guid: StringMessage GUID.
text: Option<String>Plain body text, decoded from attributedBody when available.
service: Option<String>Raw service name.
handle_id: Option<i32>Sender handle row ID.
destination_caller_id: Option<String>Address that received the message.
subject: Option<String>Subject field.
date: i64Raw timestamp for when the message was written to the database.
date_read: i64Raw timestamp for when the message was read.
date_delivered: i64Raw timestamp for when the message was delivered.
is_from_me: booltrue when the database owner sent the message.
is_read: booltrue when the message was read by the recipient.
item_type: i32Message item type used by variant.
other_handle: Option<i32>Additional handle used by shared-location and group-action messages.
Shared-location active/inactive flag.
Shared-location direction flag.
group_title: Option<String>Group title carried by group-name-change messages.
group_action_type: i32Group action code.
associated_message_guid: Option<String>GUID of the message this row references.
associated_message_type: Option<i32>Type code for the associated message, used by variant.
balloon_bundle_id: Option<String>The bundle ID of the app that generated the AppMessage
expressive_send_style_id: Option<String>Expressive-send identifier used by get_expressive.
thread_originator_guid: Option<String>Indicates the first message in a thread of replies in get_replies()
thread_originator_part: Option<String>Body part index targeted by a reply.
date_edited: i64Raw timestamp for the most recent edit.
associated_message_emoji: Option<String>Emoji associated with a custom emoji tapback.
chat_id: Option<i32>The rowid of the chat this message belongs to.
None for a recovered deleted message; most callers should prefer
chat_rowid().
num_attachments: i32Number of attached files included in the message.
deleted_from: Option<i32>The rowid of the chat the message was deleted from.
Most callers should prefer chat_rowid().
num_replies: i32Number of replies to the message.
filter_action: Option<i32>Raw message filter category code, read by filter_action.
filter_sub_action: Option<i32>Raw message filter subcategory code. This field has no parsed representation.
components: Vec<BubbleComponent>The components of the message body, parsed by a TypedStreamDeserializer or streamtyped::parse()
edited_parts: Option<EditedMessage>Parsed edit/unsent metadata from message_summary_info.
Implementations§
Source§impl Message
impl Message
Sourcepub fn rows<'stmt, P: Params>(
stmt: &'stmt mut Statement<'_>,
params: P,
) -> Result<impl Iterator<Item = Result<Self, TableError>> + 'stmt, TableError>where
Self: 'stmt,
pub fn rows<'stmt, P: Params>(
stmt: &'stmt mut Statement<'_>,
params: P,
) -> Result<impl Iterator<Item = Result<Self, TableError>> + 'stmt, TableError>where
Self: 'stmt,
Resolve the column layout after the first step, then deserialize every
row by ordinal. Pass either a rusqlite::Statement or a
rusqlite::CachedStatement (via deref coercion).
If a required column is absent, return TableError::QueryError for
every row. Failed layout resolutions are not cached: retry resolution
after each step.
Resolve through the first Row to use metadata after
sqlite3_step: if the schema changed after preparation, the statement
may be recompiled during that step.
Sourcepub fn row<P: Params>(
stmt: &mut Statement<'_>,
params: P,
) -> Result<Self, TableError>
pub fn row<P: Params>( stmt: &mut Statement<'_>, params: P, ) -> Result<Self, TableError>
Resolve the stepped row’s column layout, then deserialize by ordinal.
Return TableError::QueryError if no row is found, a required column
is absent, or deserialization fails.
Source§impl Message
impl Message
Sourcepub fn run_diagnostic(db: &Connection) -> Result<MessageDiagnostic, TableError>
pub fn run_diagnostic(db: &Connection) -> Result<MessageDiagnostic, TableError>
Compute diagnostic data for the message table.
§Example
use imessage_database::util::dirs::default_db_path;
use imessage_database::tables::table::get_connection;
use imessage_database::tables::messages::Message;
let db_path = default_db_path().unwrap();
let conn = get_connection(&db_path).unwrap();
Message::run_diagnostic(&conn);Source§impl Message
impl Message
Sourcepub fn tapbacks_by_target(
db: &Connection,
capabilities: &Capabilities,
) -> Result<HashMap<String, HashMap<usize, Vec<Message>>>, TableError>
pub fn tapbacks_by_target( db: &Connection, capabilities: &Capabilities, ) -> Result<HashMap<String, HashMap<usize, Vec<Message>>>, TableError>
Cache tapback messages by target message GUID and body component index.
Builds a map like:
{
"message_guid": {
0: [Message, Message],
1: [Message]
}
}The 0 and 1 keys are component indexes in the target message body.
Return an empty map without querying if associated_message_guid is
absent from the schema.
Source§impl Message
impl Message
Sourcepub fn date(&self) -> Result<DateTime<Utc>, MessageError>
pub fn date(&self) -> Result<DateTime<Utc>, MessageError>
Decode date to an instant.
Stored as nanoseconds (seconds in older rows) since the Messages epoch,
2001-01-01 00:00:00 UTC. Call with_timezone() to render in another zone.
Sourcepub fn date_delivered(&self) -> Result<DateTime<Utc>, MessageError>
pub fn date_delivered(&self) -> Result<DateTime<Utc>, MessageError>
Decode date_delivered to an instant.
Stored as nanoseconds (seconds in older rows) since the Messages epoch,
2001-01-01 00:00:00 UTC. Call with_timezone() to render in another zone.
Sourcepub fn date_read(&self) -> Result<DateTime<Utc>, MessageError>
pub fn date_read(&self) -> Result<DateTime<Utc>, MessageError>
Decode date_read to an instant.
Stored as nanoseconds (seconds in older rows) since the Messages epoch,
2001-01-01 00:00:00 UTC. Call with_timezone() to render in another zone.
Sourcepub fn date_edited(&self) -> Result<DateTime<Utc>, MessageError>
pub fn date_edited(&self) -> Result<DateTime<Utc>, MessageError>
Decode date_edited to an instant.
Stored as nanoseconds (seconds in older rows) since the Messages epoch,
2001-01-01 00:00:00 UTC. Call with_timezone() to render in another zone.
Sourcepub fn time_until_read<Tz: TimeZone>(&self, zone: &Tz) -> Option<String>
pub fn time_until_read<Tz: TimeZone>(&self, zone: &Tz) -> Option<String>
Calculate the elapsed time until the message was read or delivered.
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 computes the difference from the date received (date) to the date read (date_read).
In the latter case, this computes the difference from the date sent (date) to the date delivered (date_delivered).
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.
Use the calendar in zone to count whole years; see
readable_diff.
Sourcepub fn is_announcement(&self) -> bool
pub fn is_announcement(&self) -> bool
true when the message is an Announcement.
Sourcepub fn is_tapback(&self) -> bool
pub fn is_tapback(&self) -> bool
true when the message is a Tapback to another message.
Sourcepub fn is_expressive(&self) -> bool
pub fn is_expressive(&self) -> bool
true when the message has an Expressive send effect.
Sourcepub fn is_url(&self) -> bool
pub fn is_url(&self) -> bool
true when the message has a URL preview.
Sourcepub fn is_handwriting(&self) -> bool
pub fn is_handwriting(&self) -> bool
true when the message is a HandwrittenMessage.
Sourcepub fn is_digital_touch(&self) -> bool
pub fn is_digital_touch(&self) -> bool
true when the message is a Digital Touch message.
Sourcepub fn is_poll_vote(&self) -> bool
pub fn is_poll_vote(&self) -> bool
true when the message is a PollVote.
Sourcepub fn is_poll_update(&self) -> bool
pub fn is_poll_update(&self) -> bool
true when the message adds or updates poll options.
Sourcepub fn is_part_edited(&self, index: usize) -> bool
pub fn is_part_edited(&self, index: usize) -> bool
true when the specified message component was edited.
Sourcepub fn is_fully_unsent(&self) -> bool
pub fn is_fully_unsent(&self) -> bool
true when all message components were unsent.
Sourcepub fn has_attachments(&self) -> bool
pub fn has_attachments(&self) -> bool
true when the message contains Attachments.
Attachments can be queried with Attachment::from_message().
Sourcepub fn has_replies(&self) -> bool
pub fn has_replies(&self) -> bool
true when the message begins a thread.
Sourcepub fn is_kept_audio_message(&self) -> bool
pub fn is_kept_audio_message(&self) -> bool
true when the message indicates a sent audio message was kept.
true when the message is a SharePlay/FaceTime message.
Sourcepub fn is_from_me(&self) -> bool
pub fn is_from_me(&self) -> bool
true when the message was sent by the database owner.
Returns the SharedLocation when the message is a legacy
shared-location event.
Sourcepub fn is_deleted(&self) -> bool
pub fn is_deleted(&self) -> bool
true when the message is present in the recoverable deleted-message table.
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 chat_rowid(&self) -> Option<i32>
pub fn chat_rowid(&self) -> Option<i32>
The rowid of the chat this message belongs to.
A recovered deleted message has no chat_message_join row, so its
chat_id is None and deleted_from
is the only reference to its chat. Resolve a message’s chat through this
method so its transcript and attachments land in the same conversation.
Sourcepub fn has_translation(&self, db: &Connection) -> bool
pub fn has_translation(&self, db: &Connection) -> bool
true when the message summary includes translation metadata.
Sourcepub fn get_translation(
&self,
db: &Connection,
) -> Result<Option<Translation>, MessageError>
pub fn get_translation( &self, db: &Connection, ) -> Result<Option<Translation>, MessageError>
Parse translation metadata for the message.
Sourcepub fn cache_translations(
db: &Connection,
) -> Result<HashSet<String>, TableError>
pub fn cache_translations( db: &Connection, ) -> Result<HashSet<String>, TableError>
Cache message GUIDs whose summaries include translation metadata.
Sourcepub fn group_action(&self) -> Option<GroupAction<'_>>
pub fn group_action(&self) -> Option<GroupAction<'_>>
Parse the group action encoded by the message.
Sourcepub fn get_count(
db: &Connection,
capabilities: &Capabilities,
context: &QueryContext,
) -> Result<i64, TableError>
pub fn get_count( db: &Connection, capabilities: &Capabilities, context: &QueryContext, ) -> Result<i64, TableError>
Count messages matching the provided query context.
§Example
use imessage_database::tables::{
capabilities::Capabilities,
messages::Message,
table::get_connection,
};
use imessage_database::util::dirs::default_db_path;
use imessage_database::util::query_context::QueryContext;
let db_path = default_db_path().unwrap();
let conn = get_connection(&db_path).unwrap();
let capabilities = Capabilities::determine(&conn).unwrap();
let context = QueryContext::default();
Message::get_count(&conn, &capabilities, &context);Sourcepub fn stream_rows<'a>(
db: &'a Connection,
capabilities: &Capabilities,
context: &'a QueryContext,
) -> Result<CachedStatement<'a>, TableError>
pub fn stream_rows<'a>( db: &'a Connection, capabilities: &Capabilities, context: &'a QueryContext, ) -> Result<CachedStatement<'a>, TableError>
Stream messages from the database with optional filters.
§Example
use imessage_database::tables::{
capabilities::Capabilities,
messages::Message,
table::get_connection,
};
use imessage_database::util::dirs::default_db_path;
use imessage_database::util::query_context::QueryContext;
let db_path = default_db_path().unwrap();
let conn = get_connection(&db_path).unwrap();
let capabilities = Capabilities::determine(&conn).unwrap();
let context = QueryContext::default();
let mut statement = Message::stream_rows(&conn, &capabilities, &context).unwrap();
for message in Message::rows(&mut statement, []).unwrap() {
println!("{:#?}", message);
}Sourcepub fn clean_associated_guid(&self) -> Option<(usize, &str)>
pub fn clean_associated_guid(&self) -> Option<(usize, &str)>
Parse the target body component index and GUID from associated_message_guid.
Returns a tuple of (component index, message GUID) if present.
Sourcepub fn get_replies(
&self,
db: &Connection,
capabilities: &Capabilities,
) -> Result<HashMap<usize, Vec<Self>>, TableError>
pub fn get_replies( &self, db: &Connection, capabilities: &Capabilities, ) -> Result<HashMap<usize, Vec<Self>>, TableError>
Group replies by target body component index.
Sourcepub fn get_votes(
&self,
db: &Connection,
capabilities: &Capabilities,
) -> Result<Vec<Self>, TableError>
pub fn get_votes( &self, db: &Connection, capabilities: &Capabilities, ) -> Result<Vec<Self>, TableError>
Load messages that vote on or update the parent poll.
Sourcepub fn as_poll(
&self,
db: &Connection,
capabilities: &Capabilities,
) -> Result<Option<Poll>, MessageError>
pub fn as_poll( &self, db: &Connection, capabilities: &Capabilities, ) -> Result<Option<Poll>, MessageError>
Parse this message as a poll, including vote counts and option updates.
Sourcepub fn variant(&self) -> Variant<'_>
pub fn variant(&self) -> Variant<'_>
Classify the message using its associated-message fields and app balloon bundle ID.
Sourcepub fn get_announcement(&self) -> Option<Announcement<'_>>
pub fn get_announcement(&self) -> Option<Announcement<'_>>
Parse the announcement represented by this message.
Sourcepub fn filter_action(&self) -> Option<FilterAction>
pub fn filter_action(&self) -> Option<FilterAction>
Parse the message’s raw filter category.
A raw 0 maps to FilterAction::Unfiltered; an absent or NULL value
maps to None.
Sourcepub fn payload_data(&self, db: &Connection) -> Option<Value>
pub fn payload_data(&self, db: &Connection) -> Option<Value>
Parse the MESSAGE_PAYLOAD BLOB column as a property list.
Calling this reads a BLOB from the database.
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>>
Read the raw MESSAGE_PAYLOAD BLOB bytes.
Calling this reads a BLOB from the database.
This column contains data used by HandwrittenMessages.
Sourcepub fn message_summary_info(&self, db: &Connection) -> Option<Value>
pub fn message_summary_info(&self, db: &Connection) -> Option<Value>
Parse the MESSAGE_SUMMARY_INFO BLOB column as a property list.
Calling this reads a BLOB from the database.
This column contains data used by edited iMessages.
Sourcepub fn get_expressive(&self) -> Expressive<'_>
pub fn get_expressive(&self) -> Expressive<'_>
Parse the expressive send effect.
Sourcepub fn from_guid(
guid: &str,
db: &Connection,
capabilities: &Capabilities,
) -> Result<Self, TableError>
pub fn from_guid( guid: &str, db: &Connection, capabilities: &Capabilities, ) -> Result<Self, TableError>
Query a single message by GUID.
The returned message includes parsed components
and edited_parts when available. Body parsing
failures preserve the row’s metadata.
§Example
use imessage_database::{
tables::{
capabilities::Capabilities,
messages::Message,
table::get_connection,
},
util::dirs::default_db_path,
};
let db_path = default_db_path().unwrap();
let conn = get_connection(&db_path).unwrap();
let capabilities = Capabilities::determine(&conn).unwrap();
if let Ok(message) = Message::from_guid("example-guid", &conn, &capabilities) {
println!("Text: {:?}", message.text);
println!("Body components: {:#?}", message.components);
println!("Edit history: {:#?}", message.edited_parts);
}