imessage-exporter icon indicating copy to clipboard operation
imessage-exporter copied to clipboard

Support Mentions

Open ReagentX opened this issue 2 years ago • 8 comments

iMessage has a feature where you can mention chat participants:

image

There is only one column in the database that seems related to mentions: has_unseen_mention. It is just a boolean column, though, so it contains no data on what or who was mentioned. The binary blob columns also do not seem to have any information out of the ordinary. Thus, I am not sure how to proceed with this feature.

ReagentX avatar Jul 16 '22 03:07 ReagentX

The attributedBody data contains no delimiters in the body text:

image

There is an additional field called __kIMMentionConfirmedMention, but it only contains the handle's number/email, not the location of the mention within the message body.

ReagentX avatar Jan 09 '23 07:01 ReagentX

Just a quick thought, but cross-referencing the number/email with the user's contacts and then searching for the contact's name in the message seems to be the only way to find the mention in the message - albeit with quite a lot of effort required to make it work.

goldkehlchen avatar Jan 17 '23 20:01 goldkehlchen

See #62, this software will not target features outside of the iMessage database.

Also, you can type contact names without transforming them into mentions; a string search doesn't have enough context to handle that case.

ReagentX avatar Jan 17 '23 20:01 ReagentX

The attributedBody does contain the range of text that should be annotated with the mention. If parsing the attributedBody, you should see a list of message parts, and this will contain a part for the mention as well with a corrseponding range. For example, if the text is:

Hi ReagentX, here's an example for issue 18!

The attributedBody will have three parts inside it:

1st part: Hi 2nd part: ReagentX 3rd part: , here's an example for issue 18!

And these three will have NSRanges. This also works with multi-part messages.

tneotia avatar Jan 23 '23 16:01 tneotia

And these three will have NSRanges

Where? I don't see any delimiters in the attributedBody. I'm also not sure how much of the streamtyped data I can parse without reaching into NSUnarchiver, which I am not sure I can even do in Rust.

ReagentX avatar Jan 23 '23 16:01 ReagentX

"attributedBody": [{
            "string": "Heya  every part of this message that you can still see was sent from macOS Ventura Tanay mandatory mention",
            "runs": [{
                "range": [0, 4],
                "attributes": {
                    "__kIMBaseWritingDirectionAttributeName": -1,
                    "__kIMMessagePartAttributeName": 0
                }
            }, {
                "range": [4, 1],
                "attributes": {
                    "__kIMFileTransferGUIDAttributeName": "624F228F-8EE7-4FBD-9AD8-CA87FEDC0D9F",
                    "__kIMBaseWritingDirectionAttributeName": -1,
                    "__kIMMessagePartAttributeName": 1
                }
            }, {
                "range": [5, 1],
                "attributes": {
                    "__kIMFileTransferGUIDAttributeName": "29B4410B-10EC-42B4-8AD6-83BF7E94599F",
                    "__kIMBaseWritingDirectionAttributeName": -1,
                    "__kIMMessagePartAttributeName": 3
                }
            }, {
                "range": [6, 77],
                "attributes": {
                    "__kIMBaseWritingDirectionAttributeName": -1,
                    "__kIMMessagePartAttributeName": 4
                }
            }, {
                "range": [83, 1],
                "attributes": {
                    "__kIMFileTransferGUIDAttributeName": "C4D638E6-76C0-4BAE-B637-AD9E96F44489",
                    "__kIMBaseWritingDirectionAttributeName": -1,
                    "__kIMMessagePartAttributeName": 5
                }
            }, {
                "range": [84, 5],
                "attributes": {
                    "__kIMBaseWritingDirectionAttributeName": -1,
                    "__kIMMessagePartAttributeName": 6,
                    "__kIMMentionConfirmedMention": "<address>"
                }
            }, {
                "range": [89, 18],
                "attributes": {
                    "__kIMBaseWritingDirectionAttributeName": -1,
                    "__kIMMessagePartAttributeName": 6
                }
            }]
        }],

Here is an example of an actual deserialized attributedBody, notice that the second to last part is the mention and has NSRange(84,5)

tneotia avatar Jan 23 '23 16:01 tneotia

I'm part of the bluebubbles team (https://github.com/BlueBubblesApp). Our server uses node and one of our users / contributors made a node package to deserialize these with NSKeyedUnarchiver - https://www.npmjs.com/package/node-typedstream

Works great for attributedBody, messageSummaryInfo, and payloadData

tneotia avatar Jan 23 '23 16:01 tneotia

Got it, thanks, this is extremely helpful.

ReagentX avatar Jan 23 '23 16:01 ReagentX

Tracking support for this and a custom attributedBody parser in Rust in the feat/cs/attributedBody-parse branch, which will also be required for #273. The existing Python/Node libs were helpful, but not what I wanted, so I ended up writing my own parser.

ReagentX avatar Jun 13 '24 19:06 ReagentX

An attributedBody like:

image

Gets parsed as:

image

ReagentX avatar Jun 19 '24 05:06 ReagentX

At long last, we have come full circle:

image

ReagentX avatar Jul 27 '24 05:07 ReagentX