Get Source of Current Tab in Google Chrome via Applescript - macos

It's child's play to do this in Safari, which has good Applescript support. Google Chrome's AS support has just arrived so I'm giving them the benefit of the doubt. I am basically trying to grab the current HTML via the clipboard so I can get information out. We have some nifty commands like this:
tell application "Google Chrome"
view source of active tab of window 1
save active tab of window 1
print active tab of window 1
reload active tab of window 1
go back active tab of window 1
go forward active tab of window 1
copy selection of active tab of window 1
paste selection active tab of window 1
end tell
but alas you can't say "set X to source of active tab of window 1". Anyone have any suggestions for me? My current ideas are to load the code I need in the background in Safari (pretty ugly) or try to display source and grab it with UI script, but that's also ugly. Also I keep encountering scripting bugs that keep it from working.
Any help would be appreciated.

Since google chrome supports Javascript
--Applescript code
tell active tab of window 1
set sourcehtml to execute javascript
document.getElementsByTagName('html')[0].innerHTML
end tell

Chrome's AppleScript library can execute JavaScript.
This will assign the full source of the page to source and return it
tell application "Google Chrome"
set source to execute front window's active tab javascript "document.documentElement.outerHTML"
end tell

I'm very excited to learn that Chrome has AppleScript support now. It's unfortunate that it's minimal as yet, but I'm sure (I hope!) it'll get better. Since there's no way to get the source directly, I'd choose the following hackish route:
tell application "Google Chrome"
view source of active tab of window 1 -- Or whichever tab you want
delay 3
repeat while loading of active tab of window 1
delay 3
end repeat
select all of active tab of window 1 -- Must *always* be the active tab
copy selection of active tab of window 1
delete tab (active tab index of window 1) of window 1
end tell
delay 1
return the clipboard
Yes, it's hackish, but that's unavoidable, given the current state of the scripting dictionary. The script should be straightforward: open a source tab, wait for it to load, select the contents, copy it, and close the tab. You can play with the delay 3s to see what works best. Note that the first active tab of window 1 is arbitrary, the rest explicitly refer to the source tab. Also, apparently there's no way to close a tab from within Chrome's scripting dictionary (oy vey), so I had to use JavaScript instead. Also, the last delay 1 shouldn't be necessary, but if it wasn't there, my tests would sometimes return the wrong thing, even though the clipboard contents were correct when I pasted them in. I think it's because there was enough text that it took a noticeable amount of time to update the clipboard.
Edit 1: I replaced execute the active tab of window 1 javascript "window.close()" with the delete tab line, as was suggested to me. Unfortunately, delete tab active tab of window 1 doesn't work, so you need this slightly more convoluted construction.

-- This script copies the HTML of a tab to a TextEdit document.
tell application "Chromium"
tell tab 1 of window 1 to view source
repeat while (loading of tab 2 of window 1)
end repeat
tell tab 2 of window 1 to select all
tell tab 2 of window 1 to copy selection
end tell
tell application "TextEdit"
set text of document 1 to the clipboard
end tell
Explanation: The script is put in a tight loop waiting for the tab to load, Then just copies the HTML to clipboard.
tell application "Google Chrome"
set t to active tab index of window 1
tell active tab of window 1 to view source
set t to t + 1
repeat while (loading of tab t of window 1)
end repeat
tell tab t of window 1 to select all
tell tab t of window 1 to copy selection
delete tab t of window 1
end tell
EDIT1: the above script should do exaclt what you want

The simple answer is:
set sourcehtml to execute javascript "document.getElementsByTagName('html')[0].innerHTML"
Seems, other posts are really close but still no clear/working solution. The code working to me:
tell application "Google Chrome"
activate
tell active tab of window 1
set sourcehtml to execute javascript "document.getElementsByTagName('html')[0].innerHTML"
return sourcehtml
end tell
end tell

Seeing as how Chrome's AS support has "just arrived" it is bound to be "exciting" to use. In trying some of the commands they have available in their dictionary, it looks as though they still have some kinks to work out. Until Google exposes a way in the API to get the source code more easily (and/or works out the related kinks), you'll have to use one of the alternatives you mention in your post.

Related

Need script to click button on website that downloads a file

I am new to this so this is probably a dumb question but....
I am trying to get a download to happen off a website by clicking on a link but I don't think I have my code right for AppleScript.
The script opens the right website, but when I try to get it to download the file I need by clicking "export data" the code below doesnt seem to do anything, and am not sure what I am missing/did wrong. No error code. Just doesnt do anything.
Website Here
to clickId(LeaderBoard1_cmdCSV)
tell application "Safari"
do JavaScript "document.getElementById('" & LeaderBoard1_cmdCSV & "').click();" in document 1
end tell
end clickId
Thanks for the help.
The following example AppleScript code will open a new Safari window to the designated URL, wait for the page to finish loading, then click the Export Data link to download the FanGraphs Leaderboard.csv file.
Note: This was tested on macOS High Sierra, however for macOS Mojave and later there is a note in the waitForPageToFinishLoadingInSafari() handler to modify its code. Don't forget to do it if applicable.
To use JavaScript with AppleScript and Safari the Allow JavaScript from Apple Events on the Safari > Develop menu, which is hidden by default, must be checked. It can be shown by checking [√] Show Develop menu in menu bar in: Safari > Preferences… > Advanced
set theURL to "https://www.fangraphs.com/leaders.aspx?pos=all&stats=bat&lg=all&qual=50&type=c%2c6%2c11%2c12%2c13%2c21%2c23%2c39%2c35%2c34%2c41%2c42%2c43%2c104%2c107%2c110%2c206%2c209%2c211%2c50%2c61&season=2019&month=0&season1=2019&ind=0&team=0&rost=0&age=0&filter=&players=0"
tell application "Safari" to ¬
make new document with properties {URL:theURL}
my waitForPageToFinishLoadingInSafari()
my clickId("LeaderBoard1_cmdCSV")
-- # Handlers:
to clickId(ElementID)
tell application "Safari"
do JavaScript "document.getElementById('" & ElementID & "').click();" in document 1
end tell
end clickId
on waitForPageToFinishLoadingInSafari()
-- # NOTE: For macOS Mojave and later, change 'UI element 1' to 'UI element 2` in the code below.
tell application "System Events"
repeat until (accessibility description of ¬
button 1 of UI element 1 of every group of toolbar 1 of window 1 of ¬
process "Safari" whose name = "Reload this page") contains "Reload this page"
delay 0.5
end repeat
end tell
end waitForPageToFinishLoadingInSafari
Note: The example AppleScript code is just that and does not contain any error handling as may be appropriate. The onus is upon the user to add any error handling as may be appropriate, needed or wanted. Have a look at the try statement and error statement in the AppleScript Language Guide. See also, Working with Errors. Additionally, the use of the delay command may be necessary between events where appropriate, e.g. delay 0.5, with the value of the delay set appropriately.

Why does Script editor not like this edit?

I got his script:
set vURL to URL of current tab of window 1
end tell
tell application "Google Chrome"
if windows ≠ {} then
make new tab at the end of window 1 with properties {URL:vURL}
else
make new window
set URL of (active tab of window 1) to vURL
end if
activate
end tell
I'd really like to be able to just quickly open the tab I'm using in Safari in Firefox beause...
I'm told have to add more text here so, Skip this paragraph. ... a site I use a lot has some great features in Firefox but it can be slow to load so I like to switch backwards and forwards between the two.
Why won't it work if I change "Google Chrome" to "Firefox":
tell application "Safari"
set vURL to URL of current tab of window 1
end tell
tell application "Firefox"
if windows ≠ {} then
make new tab at the end of window 1 with properties {URL:vURL}
else
make new window
set URL of (active tab of window 1) to vURL
end if
activate
end tell
Thanks
You can't mix and match scripting terms - the scripting terminology (if any) for a given application is entirely up to the developer and is unique to that application. There also isn't a standard or common practice for term names, so any similarity between scripting terms of different applications would be purely coincidental and wouldn't necessarily provide the same functionality.
Looking at the scripting dictionaries for Google Chrome vs Safari and Firefox:
Firefox doesn't really have a scripting dictionary, only a default suite is available. Specifically, a window does not have either
tab, active tab, or URL elements (URL here would also be
assumed to be from StandardAdditions)
Safari windows do not have an active tab property.
You will need to target each application with its own tell statement, using the terminology specific to that application. Also note that trying to do something like using a variable to hold the application name will not work, since the scripting terminology for each application is looked up when the script is compiled.
(Edit from comments)
To open the URL of the current Safari tab with Firefox (version 69.0.1 in Mojave), you can do something like:
tell application "Safari" to set theURL to (get URL of current tab of front window)
tell application "Firefox"
activate
open location theURL
end tell

xcode: application runs properly from Debug folder, but not if copied to any other folder

I have a weirdness with my applescript application created in xcode.
When building for run, it runs properly. When copying the app from the Debug folder to another place, it does not run properly.
The application starts Photoshop, and then uses System Events UI scripting to open the Open File dialog. When not running from the Debug folder, it gets to start Photoshop, also activates System events, it seems to find the Photoshop process, but does not start with the UI scripting.
Being a noob, it baffles me, and I am stuck.
If further information is needed, please bear with me, and let me know what is needed.
Additional information: Another very similar application, which in particular uses exactly the same code, does work without issues.
Also, as asked in a comment, the application is given control to the machine in the Accessibility settings.
Edit: code as requested in comment
set myps to "com.adobe.Photoshop"
set applName to (get name of application id myps)
delay 1
tell application id myps
-- activate
using terms from application "Adobe Photoshop CC 2018"
activate
tell application "System Events"
set ProcessList to name of every process
if (applName is in ProcessList) then
tell process applName
delay 0.8
display alert "here I am"
click menu item 2 of menu 1 of menu bar item 3 of menu bar 1
delay 0.8
tell window 1
-- and so on
"click menu item 2 of menu 1 of menu bar item 3 of menu bar 1" opens the Open File dialog.
When running automatically after building or form the Debug (or Build) folder, that dialog opens; when running from elsewhere, the last thing I get is the "I am here" alert.
Also note that there is another block of code omitted, which uses a plist file to pass some parameters at runtime, but these parameters are needed only later in the script.
Thanks in advance
This is most likely because you need to build for release instead of debug. To do this go to Product -> Scheme -> Edit Scheme. Then click the Run tab on the side and change the Build Configuration to Release.
This will build an executable that should be completely self contained.

Error getting the number of tabs in "Terminal" window via Applescript on OSX El Capitan

Basically, I want to change the theme of bash when I open new windows, not new tabs, and then have tabs of a window share the same theme; while themes of separate windows are determined randomly.
After some digging, I found out an applescript which sets the theme of the current tab of Terminal window. I created a
/usr/local/terminal-color.scpt as:
on run argv
tell application "Terminal" to set current settings of selected tab of front window to some settings set
end run
And I have added the following statement to my bash profile:
osascript /usr/local/terminal-color.scpt
Now this script, of course, runs with every new instance of the bash. I cannot do anything about that from bash_profile. However, I should be able to differentiate a new window or a new tab from the applescript itself. Therefore, I am looking for an if statement, which would let the script run only when new windows are created. Something like:
on run argv
if index of selected tab is 0
tell application "Terminal" ....
end if
end run
But I cannot figure out how to achieve this looking at the applescript documentation and scripting dictionary of the terminal application. Help please
Update
I try editing the script as follows:
set tabNum to number of tabs of front window
if tabNum = 1 then
tell app ...
this won't work either giving an error tabs of window 1 doesn’t understand the “count” message
My approach was correct but I had a simple mistake of trying to get tab or window data before choosing an application scope. To put in simple words, first tell the application, then ask about its properties. Here's the code that worked:
on run argv
tell application "Terminal"
if number of tabs of front window = 1 then
set current settings of selected tab of front window to some settings set
end if
end tell
end run
Even Better
Improving the previous script; this one not randomly chooses a theme, it iterates through your available terminal themes according to the windows you have already open. You can also set your default theme that will be set on your first launch of the terminal. In my case, it was the 5th one in the settings set. Here goes the code:
tell application "Terminal"
if number of tabs in front window = 1 then
set defaultThemeOffset to 5
set allThemes to number of settings set
set allWindows to number of windows
set themeIndex to (defaultThemeOffset + allWindows) mod allThemes
set current settings of selected tab of front window to settings set themeIndex
end if
end tell

How can I use AppleScript to address dialog box in Ableton Live?

I have a collection of Ableton Live files (extension ".als") that I need to cycle through while playing a show. I'd like to dedicate a keyboard shortcut to launch each one, and had intended to use AppleScript for this.
The issue is that each file gets changed as I go through the process of playing the associated song, so that when I press the keyboard shortcut to launch the .als associated with the next song in my set, Ableton opens the "Save changes before closing?" dialog box (at which point what I want to do is select "Don't Save").
Simply pressing command + D at this point will do the trick, but I'd really like to automate this keypress. I can't seem to figure out how to get applescript to do this. I'm an applescript noob, and clicking the "Open Dictionary" option in AS seems to show that Ableton is not officially a scriptable app.
Any thoughts on this? Here's an example of an AppleScript I've been trying. This starts the process of opening the next .als in my set list, but won't click the "Don't Save" button.
tell application "Finder"
activate
open document file "Song 1.als" of folder "Desktop" of folder "User" of folder "Users" of startup disk
end tell
tell application "System Events"
keystroke "d" using command down
end tell
Interesting!
Finally came across tips that made it work:
Add both the Script Editor and Ableton Live to the Accessibility API:
System Preferences > Security & Privacy > Privacy...
Ignore application responses to continue the script during dialog.
LiveLoader.scpt:
-- open file
ignoring application responses -- don't wait for user input
tell application "Ableton Live 9 Suite" to open "Users:username:Desktop:LiveSet Project:LiveSet.als"
end ignoring
-- use delay if needed
-- delay 0.5
-- skip saving file
tell application "System Events"
set frontmost of process "Live" to true
key code 123 -- left
key code 123 -- left
keystroke return -- enter
end tell
Note:
Consider possible security impact.
Perhaps simply disable apps in Privacy List after use. (Could be scripted ;)
Can now also send mouse clicks, for more creativeness. :)
I know this is old. but in the interest of helping others who might find themselves here... heres what i have done.
use a program call Qlab. the free version will be fine.
make an applescript Cue. go to the 'trigger' tab. select midi trigger. hit the midi key you would like to assign the command too. this cue will now launch when it receives this midi note - even when running in the background.
go to the 'script' tab. copy and paste the script below.
you can make the relevant adjustments for each song. Basically each key will close all current ableton files without saving - as requested. and then launch a specific live set. which ever one you have assigned. in this case, the song 'Less Than Nothing'
the code...
tell application "System Events"
set frontmost of process "Live" to true
keystroke "q" using command down
tell application "System Events" to keystroke (ASCII character 28) --left arrow
tell application "System Events" to keystroke (ASCII character 28) --left arrow
keystroke return
end tell
delay 2.0
do shell script "open '/Users/CamMac/Desktop/Less Than Nothing 2 .als' "

Resources