使用 AppleScript 读取 iMessage

Ben*_*son 10 macos applescript imessage

我正在尝试编写一个脚本来遍历消息应用程序中的所有聊天 - 我的目标是找到我尚未回复的所有消息并向我发送提醒。

\n\n

但我被困在第一个方 - 我可以看到我有多少消息:

\n\n
tell application "Messages" to log (count of chats)\n
Run Code Online (Sandbox Code Playgroud)\n\n

但我无法从聊天中获得哪怕是简单的属性;例如:

\n\n
tell application "Messages" to set x to started of first chat\n
Run Code Online (Sandbox Code Playgroud)\n\n

给出错误:Can\xe2\x80\x99t 开始聊天 1。” 聊天 1 开始时的数字 -1728

\n\n

有什么想法我哪里出错了......?

\n

CJK*_*CJK 5

我对您的sqlite3代码进行了一些细微的调整,然后创建了这个 AppleScript,它会生成一个提醒列表(在“提醒”应用程序中)。唯一的缺点是发件人显示为电话号码或 iMessage 地址,并且不会使用地址簿“转换”为姓名。这可以通过对联系人tell执行一些命令并搜索电话号码来实现,但这目前超出了此特定工作的范围。

\n
    -- Run an SQL query on the messages database via shell script\n    do shell script (["sqlite3 -line ~/Library/Messages/chat.db ", \xc2\xac\n        "'SELECT MAX(date) lastMessageDate, h.id, text ", \xc2\xac\n        "FROM message m INNER JOIN handle h ON h.ROWID=m.handle_id ", \xc2\xac\n        "WHERE is_from_me = 0 GROUP BY h.ROWID' | egrep -io -e '\\\\w+ = .+'"] as text)\n    \n    set query_response to result\n        --> lastMessageDate = %timestamp%\n        --> id = %phone number or iMessage address%\n        --> text = %message content%\n        --> ...\n    \n    -- Groups all messages into a single item of an array\n    -- Each occurence of  "lastMessageDate = " indicates \n    -- a new message and, hence, a new array item.\n    set AppleScript's text item delimiters to "lastMessageDate = "\n    set query_response to rest of text items of query_response\n    \n    -- Loop through the array organise each message\n    repeat with message in query_response\n        \n        -- Split the array item up into its components\n        set [receivedOn, sentFrom, textContent] \xc2\xac\n            to [paragraph 1, \xc2\xac\n            text 6 thru -1 of paragraph 2, \xc2\xac\n            text 8 thru -1 of paragraph 3] of message\n        \n        -- Convert ReceivedOn to a value representing\n        -- the number of days since 01/01/2001\n        set receivedOn to receivedOn / (1.0E+9 * 86400)\n        \n        -- Convert ReceivedOn again to the date\n        -- corresponding to the number of days since\n        -- 01/01/2001, i.e. the date and time the message\n        -- was sent\n        set receivedOn to (date "Monday, 1 January 2001 at 00:00:00") + receivedOn * days\n        \n        -- Make a reminder\n        tell application "Reminders"\n            if not (exists (list named "Awaiting My Reply")) then \xc2\xac\n                make new list with properties {name:"Awaiting My Reply"}\n            \n            tell list named "Awaiting My Reply"\n                -- This creates a reminder with a past due date\n                -- meaning you can sort the reminder list by due\n                -- date to see who has been waiting longest\n                -- for you to reply\n                make new reminder with properties \xc2\xac\n                    {name:"Reply To " & sentFrom, body:\xc2\xac\n                        textContent, due date:\xc2\xac\n                        receivedOn} \xc2\xac\n                        \n            end tell\n        end tell\n    end repeat\n
Run Code Online (Sandbox Code Playgroud)\n

当然,如果您的任何短信碰巧包含短语“lastMessagedate =”,那么上面的脚本将无法正常工作。但是,有一些解决方法,我尝试了sqlite3包括listcolumncsv返回的各种格式,所有这些格式都有其优点和缺点。

\n

附录:从匹配的电话号码检索联系方式

\n

经过多次实验,已成功将上述脚本与地址簿搜索集成,以用联系人姓名替换电话号码:

\n
    -- Replace dbID with your address book's serial number\n    -- (look in ~/Library/Application Support/AddressBook/Sources)\n    property dbID : "377FDA5C-013A-430A-A964-9943C0B40137"\n    property db : {Messages:"/Users/CK/Library/Messages/chat.db", Addresses:"/Users/CK/Library/Application Support/AddressBook/Sources/" & dbID & "/AddressBook-v22.abcddb"}\n\n    -- Run an SQL query on the messages database via shell script\n    set Messages to do shell script (["sqlite3 -line ", \xc2\xac\n        quoted form of (Messages in db) as text, \xc2\xac\n        " 'SELECT MAX(date) lastMessageDate, h.id, text", \xc2\xac\n        " FROM message m INNER JOIN handle h ON h.ROWID=m.handle_id", \xc2\xac\n        " WHERE is_from_me = 0 GROUP BY h.ROWID'", \xc2\xac\n        " | egrep -io -e '\\\\w+ = .+'"] as text)\n    --> lastMessageDate = %timestamp%\n    --> id = %phone number or iMessage address%\n    --> text = %message content%\n    --> ...\n    \n    set PhoneNumbers to do shell script (["sqlite3 -list -separator : ", \xc2\xac\n        quoted form of (Addresses in db) as text, \xc2\xac\n        " 'select r.ZFIRSTNAME, r.ZLASTNAME, p.ZFULLNUMBER", \xc2\xac\n        " from ZABCDRECORD as r, ZABCDPHONENUMBER as p", \xc2\xac\n        " WHERE p.ZOWNER=r.Z_PK'", \xc2\xac\n        " | tr -c -d '[:alnum:]:[:cntrl:]:[:space:]:+#*'"] as text)\n    --> %first name%:%last name:%phone number%\n    --> ...\n    \n    set NamesAndNumbers to paragraphs of PhoneNumbers\n    set AppleScript's text item delimiters to ":"\n    tell NamesAndNumbers to \xc2\xac\n        repeat with n from 1 to count it\n            set its item n to \xc2\xac\n                {firstname:text item 1, lastname:text item 2, phone:text item 3} \xc2\xac\n                    of its item n\n        end repeat\n    \n    -- Groups all messages into a single item of an array\n    -- Each occurence of  "lastMessageDate = " indicates \n    -- a new message and, hence, a new array item.\n    set AppleScript's text item delimiters to "lastMessageDate = "\n    set Messages to rest of text items of Messages\n    \n    -- Loop through the array organise each message\n    repeat with message in Messages\n        \n        -- Split the array item up into its components\n        set [receivedOn, sentFrom, textContent] \xc2\xac\n            to [paragraph 1, \xc2\xac\n            text 6 thru -1 of paragraph 2, \xc2\xac\n            text 8 thru -1 of paragraph 3] of message\n        \n        -- Convert ReceivedOn to a value representing\n        -- the number of days since 01/01/2001\n        set receivedOn to receivedOn / (1.0E+9 * 86400)\n        \n        -- Convert ReceivedOn again to the date\n        -- corresponding to the number of days since\n        -- 01/01/2001, i.e. the date and time the message\n        -- was sent\n        set receivedOn to (date "Monday, 1 January 2001 at 00:00:00") + receivedOn * days\n        \n        -- Keep the "+" delimiter but replace the "+44" with\n        -- your own country's intl dialling code, e.g. {"+1", "+"}\n        -- as this may or may not prefix a phone number\n        set AppleScript's text item delimiters to {"+44", "+"}\n        set sentFrom to last text item of sentFrom\n        \n        -- Find the name to whom the phone number belongs\n        ignoring white space\n            set match to ""\n            repeat with person in NamesAndNumbers\n                if the person's phone contains sentFrom then\n                    set match to contents of the person\n                    exit repeat\n                end if\n            end repeat\n        end ignoring\n        \n        set AppleScript's text item delimiters to space\n        if match is not "" then set sentFrom to the contents of \xc2\xac\n            {firstname, lastname} of match as text\n        \n        -- Make a reminder\n        tell application "Reminders"\n            if not (exists (list named "Awaiting My Reply")) then \xc2\xac\n                make new list with properties {name:"Awaiting My Reply"}\n            \n            tell list named "Awaiting My Reply"\n                -- This creates a reminder with a past due date\n                -- meaning you can sort the reminder list by due\n                -- date to see who has been waiting longest\n                -- for you to reply\n                make new reminder with properties \xc2\xac\n                    {name:"Reply To " & sentFrom, body:\xc2\xac\n                        textContent, due date:\xc2\xac\n                        receivedOn} \xc2\xac\n                        \n            end tell\n        end tell\n    end repeat\n
Run Code Online (Sandbox Code Playgroud)\n