Skip to main content

Message

Struct Message 

Source
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: i32

Message row ID.

§guid: String

Message 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: 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>

The rowid of the chat this message belongs to.

None for a recovered deleted message; most callers should prefer chat_rowid().

§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.

Most callers should prefer chat_rowid().

§num_replies: i32

Number 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

Source

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.

Source

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

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

impl Message

Source

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

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

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

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, 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);
Source

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);
}
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, capabilities: &Capabilities, ) -> Result<HashMap<usize, Vec<Self>>, TableError>

Group replies by target body component index.

Source

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

Load messages that vote on or update the parent poll.

Source

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.

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

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 get_expressive(&self) -> Expressive<'_>

Parse the expressive send effect.

Source

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);
}

Trait Implementations§

Source§

impl Debug for Message

Source§

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

Formats the value using the given formatter. Read more

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 = !

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

fn try_from(value: U) -> Result<T, !>

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.