Skip to main content

Message

Struct Message 

Source
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

Row from the message table, plus body/edit metadata populated by parse_body.

Fields§

§rowid: i32

Message row ID.

§guid: String

Message GUID.

§text: Option<String>

Plain body text. parse_body may populate this from attributedBody.

§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: i64

Raw timestamp for when the message was written to the database.

§date_read: i64

Raw timestamp for when the message was read.

§date_delivered: i64

Raw timestamp for when the message was delivered.

§is_from_me: bool

true when the database owner sent the message.

§is_read: bool

true when the message was read by the recipient.

§item_type: i32

Message item type used by variant.

§other_handle: Option<i32>

Additional handle used by shared-location and group-action messages.

§share_status: bool

Shared-location active/inactive flag.

§share_direction: Option<bool>

Shared-location direction flag.

§group_title: Option<String>

Group title carried by group-name-change messages.

§group_action_type: i32

Group 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: i64

Raw timestamp for the most recent edit.

§associated_message_emoji: Option<String>

Emoji associated with a custom emoji tapback.

§chat_id: Option<i32>

Chat row ID this message belongs to.

§num_attachments: i32

Number of attached files included in the message.

§deleted_from: Option<i32>

The rowid of the chat the message was deleted from

§num_replies: i32

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>

Parsed edit/unsent metadata from message_summary_info.

Implementations§

Source§

impl Message

Source

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();
let conn = get_connection(&db_path).unwrap();
Message::run_diagnostic(&conn);
Source§

impl Message

Source

pub fn parse_body(&self, db: &Connection) -> Result<ParsedBody, MessageError>

Parse the body of a message, deserializing it as typedstream (and falling back to streamtyped) data if necessary.

This method performs pure parsing without mutating the message. Use Self::apply_body() to apply the result back to the message.

§Example
if let Ok(body) = message.parse_body(&conn) {
    message.apply_body(body);
}
Source

pub fn apply_body(&mut self, body: ParsedBody)

Apply a ParsedBody to this message, setting its text, components, edited parts, and balloon bundle ID.

Source

pub fn generate_text_legacy<'a>( &'a mut self, db: &'a Connection, ) -> Result<&'a str, MessageError>

Parse text with the legacy parser only.

This ignores typedstream attributes and does not preserve every modern message type.

Source

pub fn date(&self, offset: i64) -> Result<DateTime<Local>, MessageError>

Convert date to local time.

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.

Source

pub fn date_delivered( &self, offset: i64, ) -> Result<DateTime<Local>, MessageError>

Convert date_delivered to local time.

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.

Source

pub fn date_read(&self, offset: i64) -> Result<DateTime<Local>, MessageError>

Convert date_read to local time.

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.

Source

pub fn date_edited(&self, offset: i64) -> Result<DateTime<Local>, MessageError>

Convert date_edited to local time.

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.

Source

pub fn time_until_read(&self, offset: i64) -> 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.

offset can be provided by get_offset or manually.

Source

pub fn is_reply(&self) -> bool

true when the message is a thread reply.

Source

pub fn is_announcement(&self) -> bool

true when the message is an Announcement.

Source

pub fn is_tapback(&self) -> bool

true when the message is a Tapback to another message.

Source

pub fn is_expressive(&self) -> bool

true when the message has an Expressive send effect.

Source

pub fn is_url(&self) -> bool

true when the message has a URL preview.

Source

pub fn is_handwriting(&self) -> bool

true when the message is a HandwrittenMessage.

Source

pub fn is_digital_touch(&self) -> bool

true when the message is a Digital Touch message.

Source

pub fn is_poll(&self) -> bool

true when the message is a Poll.

Source

pub fn is_poll_vote(&self) -> bool

true when the message is a PollVote.

Source

pub fn is_poll_update(&self) -> bool

true when the message adds or updates poll options.

Source

pub fn is_edited(&self) -> bool

true when the message was edited.

Source

pub fn is_part_edited(&self, index: usize) -> bool

true when the specified message component was edited.

Source

pub fn is_fully_unsent(&self) -> bool

true when all message components were unsent.

Source

pub fn has_attachments(&self) -> bool

true when the message contains Attachments.

Attachments can be queried with Attachment::from_message().

Source

pub fn has_replies(&self) -> bool

true when the message begins a thread.

Source

pub fn is_kept_audio_message(&self) -> bool

true when the message indicates a sent audio message was kept.

Source

pub fn is_shareplay(&self) -> bool

true when the message is a SharePlay/FaceTime message.

Source

pub fn is_from_me(&self) -> bool

true when the message was sent by the database owner.

Source

pub fn shared_location_kind(&self) -> Option<SharedLocation>

Returns the SharedLocation when the message is a legacy shared-location event.

Source

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.

Source

pub fn has_translation(&self, db: &Connection) -> bool

true when the message summary includes translation metadata.

Source

pub fn get_translation( &self, db: &Connection, ) -> Result<Option<Translation>, MessageError>

Parse translation metadata for the message.

Source

pub fn cache_translations( db: &Connection, ) -> Result<HashSet<String>, TableError>

Cache message GUIDs whose summaries include translation metadata.

Source

pub fn group_action(&self) -> Option<GroupAction<'_>>

Parse the group action encoded by the message.

Source

pub fn get_count( db: &Connection, context: &QueryContext, ) -> Result<i64, TableError>

Count messages matching the provided query context.

§Example
use imessage_database::util::dirs::default_db_path;
use imessage_database::tables::table::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);
Source

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::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();

for message in Message::rows(&mut statement, []).unwrap() {
    println!("{:#?}", message);
}
Source

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.

Source

pub fn get_replies( &self, db: &Connection, ) -> Result<HashMap<usize, Vec<Self>>, TableError>

Group replies by target body component index.

Source

pub fn get_votes(&self, db: &Connection) -> Result<Vec<Self>, TableError>

Load messages that vote on or update the parent poll.

Source

pub fn as_poll(&self, db: &Connection) -> Result<Option<Poll>, MessageError>

Parse this message as a poll, including vote counts and option updates.

Source

pub fn variant(&self) -> Variant<'_>

Classify the message using its associated-message fields and app balloon bundle ID.

Source

pub fn get_announcement(&self) -> Option<Announcement<'_>>

Parse the announcement represented by this message.

Source

pub fn service(&self) -> Service<'_>

Parse the message service.

Source

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().

Source

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.

Source

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.

Source

pub fn attributed_body(&self, db: &Connection) -> Option<Vec<u8>>

Get a message’s typedstream from the ATTRIBUTED_BODY BLOB column

Calling this reads a BLOB from the database.

This column contains the message’s body text with any other attributes.

Source

pub fn get_expressive(&self) -> Expressive<'_>

Parse the expressive send effect.

Source

pub fn from_guid(guid: &str, db: &Connection) -> Result<Self, TableError>

Query a single message by GUID.

§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) {
    if let Ok(body) = message.parse_body(&conn) {
        message.apply_body(body);
    }
    println!("{:#?}", message)
}

Trait Implementations§

Source§

impl Cacheable for Message

Source§

fn cache(db: &Connection) -> Result<HashMap<Self::K, Self::V>, 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.

Source§

type K = String

Key type for the cache map.
Source§

type V = HashMap<usize, Vec<Message>>

Value type for the cache map.
Source§

impl Debug for Message

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Table for Message

Source§

fn get(db: &Connection) -> Result<CachedStatement<'_>, TableError>

Prepare the newest compatible message query, falling back through older schemas.

Source§

fn from_row(row: &Row<'_>) -> Result<Message>

Deserialize a single row into Self. Returns rusqlite::Result for direct use inside rusqlite::query_map / query_row callbacks. For high-level iteration, prefer Table::rows or Table::row.
Source§

fn rows<'stmt, P: Params>( stmt: &'stmt mut Statement<'_>, params: P, ) -> Result<impl Iterator<Item = Result<Self, TableError>> + 'stmt, TableError>
where Self: 'stmt,

Iterate over rows produced by stmt, deserializing each via from_row. Errors at row-fetch or row-deserialize time are surfaced uniformly as TableError. Accepts both rusqlite::Statement and rusqlite::CachedStatement (the latter via deref coercion). Read more
Source§

fn row<P: Params>( stmt: &mut Statement<'_>, params: P, ) -> Result<Self, TableError>

Fetch exactly one row from stmt. Returns TableError::QueryError if the row is missing or fails to deserialize. Accepts both rusqlite::Statement and rusqlite::CachedStatement (the latter via deref coercion).
Source§

fn stream<F, E>(db: &Connection, callback: F) -> Result<(), E>
where E: From<TableError>, F: FnMut(Result<Self, TableError>) -> Result<(), E>,

Process every row from the table’s default SELECT * query using a callback. Builds and discards the prepared statement internally, so the caller never sees it. Read more
Source§

fn get_blob<'a>( &self, db: &'a Connection, table: &str, column: &str, rowid: i64, ) -> Option<Blob<'a>>

Open a BLOB column for the supplied rowid.
Source§

fn has_blob( &self, db: &Connection, table: &str, column: &str, rowid: i64, ) -> bool

Return whether a BLOB column is non-null for the supplied rowid.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.