Background: during this period, a colleague needs to log in to my account frequently, and to verify the mobile phone verification code, I need to manually forward the verification code to him every time. I find it very troublesome, so I want to see if there is any way to free my hands, and then I find that AppleScript is such a very useful thing:)
Required configuration
- Mac: since AppleScript is used, a Mac computer is indispensable (MAC OS Catalina 10.15.5)
- iphone: if the message type is iMessage, you only need to log in to Apple account on Mac. If the message type is SMS, you need to take advantage of Apple's ecology, and messages on iphone can be automatically forwarded to MAC (supported after IOS 8).
AppleScript
What is AppleScript?
AppleScript is used to write scripts that run on MAC and can operate applications. Apple officials also require that the development of mac software needs to set aside methods that can be operated by AppleScript. With AppleScript, we can easily realize the scripting of repetitive work, improve work efficiency and avoid repetitive work.
Basic grammar
The syntax of AppleScript is very close to that of natural language, with almost no punctuation. The syntax is not as strict as that of other languages
Variable definition
-- Assign Baidu URL to variable url_str set url_str to "https://www.baidu.com"
notice
-- Assign Baidu URL to variable url_str set url_str to "https://www.baidu.com" -- notice display notification "url set success"
Operation application
-- Assign Baidu URL to variable url_str set url_str to "https://www.baidu.com" -- take bing URL assigned to variable url_str2 set url_str2 to "https://www.bing.com" -- notice display notification "url set success" -- Operation application tell application "Google Chrome" -- Create a new window set newWin to make new window -- Get new window tab set theTab to get active tab of newWin -- operation tab tell theTab -- set up tabURL set URL of theTab to url_str -- visit go forward -- Delay 3 seconds delay 3 --Reset tabURL set URL of theTab to url_str2 go forward end tell end tell
Dictionaries
Apple will ask the development of mac software to provide a way to operate the application software. You can query whether the software can be operated by AppleScript through a dictionary
Dictionary open mode
Script editor - > Open Dictionary - > select the software you want to operate
chrome dictionary.
AppleScript Language Guide
Learn about AppleScript's Basic grammar It is the first step to master the automation of AppleScript. After having a certain understanding of AppleScript, when you find that you have repeated operations in the future, you can first think about how to solve it through AppleScript
Problem solving
Back to the main point, because I have a certain understanding of AppleScript and have done simple tests, the first thing I think about is whether I can use automatic script to deal with repeated SMS forwarding work (I have never used AppleScript to solve practical problems before)
Send SMS
The first thing we need is to open the dictionary. Because Message itself is developed by apple, there must be a rich API for us to use
Through searching, we can basically locate the send method we need to send SMS. In the send method, we need to define a buddy and continue to check the buddy
Check our buddy. It is included in a service. Continue with service
The upper layer of service contains application, so we can write our script
tell application "Messages" send "test" to buddy "+86199xxxx" of service "SMS" end tell
A very simple piece of code that can be sent for testing. During the test, it is found that there must be a record of messages sent with the number (that is, a window needs to be opened)
event listeners
After successfully sending SMS, we are close to liberation hands. Next, we just need to call our sending script to forward the message we received when we receive the verification code message
Continue to check our dictionary. There is a message received event. It can meet our needs by reading the literal meaning. It's him
Very simply, we just need to get the message we need and the people who send it to us to judge (after all, we can't forward all the messages)
using terms from application "Messages" on message received theMessage from theBuddy -- Notification received message display notification "message" -- take Message App so set visible of window "Messages" to true -- take Message App Topping set frontmost of window "Message" to true end message received end using terms from
Is it over here? How can it be so simple? It's called "the way of heaven, it's not so easy for you to succeed"
After continuous testing, I found that the script didn't meet my expectations at all, there was no notice and no top. Where did I write the problem? Well, if you know something wrong, you should change it and study modestly. Baidu ~, well, can't find, harm, Google ~ (personal habits, Baidu first, Google only when it finds that it can't find the information you want or Baidu is full of the same article copied back and forth, after all, Google is not allowed, I'm a good kid)
Constantly changing key words and descriptions, finally found some solutions in my bulk English
I found that there was no problem with what I wrote in my script, just a few steps. for example
copy the script into a new AppleScript Editor document and save it in ~/Library/Application Scripts/com.apple.iChat/ Then activate it by selecting it in Messages -> Preferences -> General -> AppleScript Handler:
as well as
AppleScript file copied to ~/Library/Scripts/Messages by Messages, it started to work.
Different paths, but they all seem to need to be copied, so they are tested to the directory respectively, but message - > preference - > General has not been found all the time. Anyway, it is still not successful. Continue to google
Finally, it turns out Message.app Message received event handler was removed in Mac OS High Sierra version 10.13.4, and business chat emmmmmmm was opened......, so it is not allowed to
Analysis database
The way of the incident doesn't work. There's only another way. What other way can I use it? So I thought of a possibility. Even if I could find these messages in a long time, how did he store them.
OK, if you have ideas, you have directions. In the end, continuous search and discovery exist in the directory / Users/herbert/Library/Messages chat.db In file
Open it with sqlite
sqlite3 /Users/herbert/Library/Messages/chat.db
View table structure and some data in the table
.schema message select * from message order by ROWID desc limit 5;
Finally, sort out the SQL according to the sorted table structure relationship and the number I need to query
-- Query from specified number within one minute xxxxxx_number SMS for SELECT text, handle_id,date,datetime(date/1000000000 + strftime('%s','2001-01-01'), 'unixepoch', 'localtime') as date_utc FROM message T1 INNER JOIN chat_message_join T2 ON T1.ROWID=T2.message_id INNER JOIN chat T3 ON T2.chat_id=T3.ROWID AND T3.chat_identifier = 'xxxxxx_number' where datetime(date/1000000000 + strftime('%s','2001-01-01'), 'unixepoch', 'localtime') > datetime('now','localtime','-1 minute') ORDER BY T1.date;
When querying the data, I found an unusual date store (I haven't seen it before) with an 18 digit time number
Handling method:
datetime(date/1000000000 + 978307200,'unixepoch','localtime').
datetime(date/1000000000+ strftime('%s','2001-01-01'),'unixepoch','localtime')
Script
We have got the data we need. Next, we only need to get the data once a minute. If we can get the data, then it's OK to call the script that we sent the SMS
Script auto_forward.sh
#/bin/sh phone="+86xxxx" call_apple() { while read line do osascript /Users/herbert/Documents/AppleScript/ForwardMessage/SendMessage.scpt $line $phone done } export -f call_apple sqlite3 /Users/herbert/Library/Messages/chat.db '.read /Users/herbert/Documents/AppleScript/ForwardMessage/select.txt' | call_apple
Store our sql in a separate file for easy modification select.txt
SELECT text FROM message T1 INNER JOIN chat_message_join T2 ON T1.ROWID=T2.message_id INNER JOIN chat T3 ON T2.chat_id=T3.ROWID AND T3.chat_identifier = 'from_number' where datetime(date/1000000000 + strftime('%s','2001-01-01'), 'unixepoch', 'localtime') > datetime('now','localtime','-1 minute') ORDER BY T1.date;
SendMessage.scpt
on run argv set msgContent to item 1 of argv set phone to item 2 of argv sendMsg(msgContent, phone) end run on sendMsg(msgContent, phone) tell application "Messages" send msgContent to buddy phone of service "SMS" end tell end sendMsg
All you need to do is join crontab
crontab -e */1 * * * * sh /Users/herbert/Documents/AppleScript/ForwardMessage/auto_forward.sh
This test still failed to meet the expectations, but it was successful when the script was executed alone. It is speculated that the problem is cron, so check the log
vim /var/mail/herbert
I found the problem
sh: /Users/herbert/Documents/test/demo.sh: Operation not permitted
This problem will appear in Mojave 10.14, Catalina 10.15 and later versions
Solution: System Preferences - > Security and privacy - > Privacy - > full disk access - > Add cron