AppleScript realizes automatic forwarding of SMS

Keywords: OS X Mac Google SQL crontab

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
"message_sqlite_date.png"
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

Posted by randydg on Thu, 25 Jun 2020 01:51:38 -0700