-
Notifications
You must be signed in to change notification settings - Fork 1
parse sticker reactions #57
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -59,7 +59,10 @@ const removeObjReplacementChar = (text: string): string => { | |
| return text.replaceAll(OBJ_REPLACEMENT_CHAR, ' ').trim() | ||
| } | ||
|
|
||
| function assignReactions(currentUserID: string, message: BeeperMessage, _reactionRows: MappedReactionMessageRow[] = [], filterIndex?: number) { | ||
| const reactionStickerAssetURL = (accountID: string, rowID: MappedReactionMessageRow['ROWID']) => | ||
| `asset://${accountID}/reaction-sticker/${rowID}.heic` | ||
|
|
||
| function assignReactions(currentUserID: string, accountID: string, message: BeeperMessage, _reactionRows: MappedReactionMessageRow[] = [], filterIndex?: number) { | ||
| const reactions: MessageReaction[] = [] | ||
| const reactionRows = filterIndex != null | ||
| ? _reactionRows.filter(r => r.associated_message_guid.startsWith(`p:${filterIndex}/`)) | ||
|
|
@@ -75,6 +78,7 @@ function assignReactions(currentUserID: string, message: BeeperMessage, _reactio | |
| id: participantID, | ||
| reactionKey: actionKey === 'emoji' ? reaction.associated_message_emoji : actionKey, | ||
| participantID, | ||
| imgURL: actionKey === 'sticker' ? reactionStickerAssetURL(accountID, reaction.ROWID) : undefined, | ||
| }) | ||
| } else if (actionType === 'unreacted') { | ||
| const index = reactions.findIndex(r => r.id === participantID) | ||
|
|
@@ -241,7 +245,7 @@ const UUID_START = 11 | |
| const UUID_LENGTH = 36 | ||
| const UUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[0-9a-f]{4}-[0-9a-f]{12}$/i | ||
| // eslint-disable-next-line @typescript-eslint/default-param-last -- FIXME(skip) | ||
| export function mapMessage(msgRow: MappedMessageRow, attachmentRows: MappedAttachmentRow[] = [], reactionRows: MappedReactionMessageRow[], currentUserID: string): BeeperMessage[] { | ||
| export function mapMessage(msgRow: MappedMessageRow, attachmentRows: MappedAttachmentRow[] = [], reactionRows: MappedReactionMessageRow[], currentUserID: string, accountID: string): BeeperMessage[] { | ||
| const attachments = attachmentRows.map(a => mapAttachment(a, msgRow)).filter(attachment => attachment != null) | ||
|
Comment on lines
247
to
249
|
||
| const isSMS = msgRow.service === 'SMS' || msgRow.service === 'RCS' | ||
| const isGroup = !!msgRow.room_name | ||
|
|
@@ -615,9 +619,10 @@ export function mapMessage(msgRow: MappedMessageRow, attachmentRows: MappedAttac | |
| type: reactionType, | ||
| messageID: m.linkedMessageID, | ||
| participantID: m.senderID, | ||
| imgURL: assocMsgType === 'reacted_sticker' ? reactionStickerAssetURL(accountID, msgRow.ROWID) : undefined, | ||
| reactionKey: actionKey === 'emoji' ? msgRow.associated_message_emoji : actionKey, | ||
| } | ||
| if (actionKey === 'emoji' || actionKey in supportedReactions) { | ||
| if (actionKey === 'emoji' || actionKey === 'sticker' || actionKey in supportedReactions) { | ||
| m.parseTemplate = true | ||
| m.text = `${msgRow.is_from_me ? 'You' : '{{sender}}'} ${REACTION_VERB_MAP[assocMsgType]} ${msi?.ams ? `"${msi?.ams}"` : 'a message'}` | ||
| m.isHidden = true | ||
|
|
@@ -629,7 +634,7 @@ export function mapMessage(msgRow: MappedMessageRow, attachmentRows: MappedAttac | |
|
|
||
| return messages.map(msg => { | ||
| // texts.log('assigning reactions', msg.id, msg.index, reactionRows) | ||
| assignReactions(currentUserID, msg, reactionRows, messages.length === 1 ? undefined : msg.extra?.part) | ||
| assignReactions(currentUserID, accountID, msg, reactionRows, messages.length === 1 ? undefined : msg.extra?.part) | ||
| return msg | ||
| }) | ||
| } | ||
|
|
@@ -672,6 +677,7 @@ function mapParticipant({ participantID: id, uncanonicalized_id }: MappedHandleR | |
| export const mapAccountLogin = (al: string) => al?.replace(/^(E|P):/, '') | ||
|
|
||
| type Context = { | ||
| accountID: string | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
# Verify every mapThread/mapMessages callsite threads accountID.
rg -n -C3 '\bmapThread\s*\(|\bmapMessages\s*\(' --type tsRepository: beeper/platform-imessage Length of output: 4617 🏁 Script executed: # First, check what Context is being passed at the mapThread calls
cat -n src/api.ts | sed -n '220,240p'Repository: beeper/platform-imessage Length of output: 1200 🏁 Script executed: # Also check the second mapThread call
cat -n src/api.ts | sed -n '250,270p'Repository: beeper/platform-imessage Length of output: 983 🏁 Script executed: # Check the Context type definition
fd -t f -e ts | xargs rg -l 'type Context|interface Context' | head -5Repository: beeper/platform-imessage Length of output: 82 🏁 Script executed: # Search for Context type/interface definition
rg -n 'type Context|interface Context' src/mappers.ts -A 15Repository: beeper/platform-imessage Length of output: 848 🏁 Script executed: # Also check the mapThread function signature more completely
sed -n '705,720p' src/mappers.tsRepository: beeper/platform-imessage Length of output: 1145 🏁 Script executed: # Check mapThreads function and its callers
rg -n 'mapThreads' src/ -B 2 -A 5Repository: beeper/platform-imessage Length of output: 2258 🏁 Script executed: # Also verify TypeScript compilation would catch this type error
# by checking how accountID is passed in the correct calls
rg -n 'accountID:' src/ -B 2 -A 2 | head -40Repository: beeper/platform-imessage Length of output: 2518 Add
🤖 Prompt for AI Agents |
||
| currentUserID: string | ||
| handleRowsMap: { [threadID: string]: MappedHandleRow[] } | ||
| mapMessageArgsMap: { [threadID: string]: [MappedMessageRow[], MappedAttachmentRow[], MappedReactionMessageRow[]] } | ||
|
|
@@ -688,16 +694,16 @@ type Context = { | |
|
|
||
| // @ts-expect-error FIXME(skip): argument ordering | ||
| // eslint-disable-next-line @typescript-eslint/default-param-last | ||
| export function mapMessages(messages: MappedMessageRow[], attachmentRows?: MappedAttachmentRow[], reactionRows?: MappedReactionMessageRow[], currentUserID: string): BeeperMessage[] { | ||
| export function mapMessages(messages: MappedMessageRow[], attachmentRows?: MappedAttachmentRow[], reactionRows?: MappedReactionMessageRow[], currentUserID: string, accountID: string): BeeperMessage[] { | ||
| const groupedAttachmentRows = groupBy(attachmentRows, 'msgRowID') | ||
| const groupedReactionRows = groupBy(reactionRows, r => r.associated_message_guid.replace(assocMsgGuidPrefix, '')) | ||
| return messages | ||
| .flatMap(message => mapMessage(message, groupedAttachmentRows[message.ROWID], groupedReactionRows[message.guid], currentUserID)) | ||
| .flatMap(message => mapMessage(message, groupedAttachmentRows[message.ROWID], groupedReactionRows[message.guid], currentUserID, accountID)) | ||
| .filter(Boolean) | ||
| } | ||
|
|
||
| export function mapThread(chat: MappedChatRow, context: Context): BeeperThread { | ||
| const { currentUserID } = context | ||
| const { currentUserID, accountID } = context | ||
| const handleRows = context.handleRowsMap[chat.guid] | ||
| const mapMessageArgs = context.mapMessageArgsMap?.[chat.guid] | ||
| const selfID = chat.last_addressed_handle || mapAccountLogin(chat.account_login) || currentUserID | ||
|
|
@@ -707,7 +713,7 @@ export function mapThread(chat: MappedChatRow, context: Context): BeeperThread { | |
| const participants = [...handleRows.map(h => mapParticipant(h, chat.display_name)), selfParticipant].filter(participant => participant != null) | ||
| const isGroup = !!chat.room_name | ||
| const isReadOnly = chat.state === 0 && chat.properties != null | ||
| const messages = mapMessageArgs ? mapMessages(...mapMessageArgs, currentUserID) : [] | ||
| const messages = mapMessageArgs ? mapMessages(...mapMessageArgs, currentUserID, accountID) : [] | ||
| /* | ||
| props = { | ||
| "com.apple.iChat.LastArchivedMessageID": [ 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX', 101010 ], | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -104,5 +104,6 @@ | |
| } | ||
| ], | ||
| [], | ||
| "tinyslices@gmail.com" | ||
| "tinyslices@gmail.com", | ||
| "imessage-test-account" | ||
| ] | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -104,5 +104,6 @@ | |
| } | ||
| ], | ||
| [], | ||
| "tinyslices@gmail.com" | ||
| "tinyslices@gmail.com", | ||
| "imessage-test-account" | ||
| ] | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -104,5 +104,6 @@ | |
| } | ||
| ], | ||
| [], | ||
| "tinyslices@gmail.com" | ||
| "tinyslices@gmail.com", | ||
| "imessage-test-account" | ||
| ] | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The new
reaction-stickerbranch returnsfile://...directly and skips the existingconvertCGBIfallback used by the default asset path. If the sticker attachment is an Apple CGBI PNG (a format this codebase already special-cases), the reaction image can be unreadable/corrupted when rendered.Useful? React with 👍 / 👎.