monitor webpage with applescript - applescript

So I'm trying to watch a webpage, and when an input form appears I need to input my name. I came up with this, but clearly not correct.
tell application "Google Chrome"
set textToType to "Peter"
repeat
if execute javascript "document.getElementById('Account_UserName') then
execute javascript "document.getElementById('Account_UserName').focus();"
keystroke textToType
keystroke return
end if
end repeat
end tell

I used this page for testing:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>My Test Page</title>
<style>
body {
margin: 10em;
padding: 2em;
border: solid .2em green;
}
h1 {
text-align: center;
}
</style>
</head>
<body>
<h1>Test Page</h1>
<form action="http://www.example.com/">
<input type="text" name="Account_UserName" id="Account_UserName">
</form>
</body>
</html>
The first issue is that in order to focus, Chrome appears to need the tab/window combination specified. So, instead of “execute javascript”, it is “execute tabSpecifier javascript”.
The second issue is that the AppleScript needs a boolean to check on; it doesn’t seem to handle the return value of “execute javascript” very well.
The third issue is that without a delay in the loop, AppleScript will lock up the app.
And finally, “keystroke” needs to be wrapped in a “tell application” for “System Events”.
Here’s an example that should get you started:
set textToType to "Peter"
set fieldName to "Account_UserName"
tell application "Google Chrome"
repeat
try
--Chrome needs to have a tab to execute JavaScript in
set myTab to tab 1 of window 1
set fieldNameCheck to execute myTab javascript "nameField=document.getElementById('" & fieldName & "');nameField.name"
if fieldNameCheck is equal to fieldName then
execute myTab javascript "document.getElementById('" & fieldName & "').focus();"
--activate the window so that System Events can type into it
activate myTab
tell application "System Events"
keystroke textToType
keystroke return
end tell
end if
end try
--sleep a second between loop, or AppleScript will eventually lock up the app
delay 1
end repeat
end tell
I opened Chrome, started browsing the web, and started running this script; when I navigated to the test page, it immediately detected that I was there, filled out the form, and submitted it to example.com.
Note that in real life, you might find it easier to perform the entire script in JavaScript using “javascript execute”, since you should be able to set the value and submit the form there.

Related

Applescript: Truncated feed URL

I'm running into errors with this simple script. It's a validator to validate RSS feed with multiple validation sites using Safari. Everything works fine as long as the feed does not contain special characters or anything after the = sign.
The script should validate the feed that was copied to the clipboard.
For example, this feed works fine: http://thefirst.libsyn.com/rss
This feed gets truncated after ?id: https://www.npr.org/rss/podcast.php?id=510298
This is only happening on the Podbase validator site.
If I could get the script to click the Validate and Go buttons, that would be amazing, but this is pretty basic…just stuck as to why the feed is getting truncated.
set feed_url to the clipboard as string
set the podbaseurl to "http://podba.se/validate/?url=" & feed_url
set the feedvalidatorurl to "http://feedvalidator.org/check.cgi?url=" & feed_url
set the castfeedurl to "http://castfeedvalidator.com/?url=" & feed_url
tell application "Safari"
make new document
open location podbaseurl
open location feedvalidatorurl
open location castfeedurl
end tell
The problem is that https://podba.se/validate only makes it look like a single GET request is enough, whereas clicking the Go button interactively performs many individual GET requests behind the scenes whose results are pieced together on the current page (and the URL is then modified to include the submitted feed URL).
In other words: even solving the (odd) truncation problem wouldn't be enough.
Therefore, your best bet is indeed to simulate an interactive submission of a feed URL, which requires filling an input box with the feed URL and pressing the submission button.
Interactive submission must be simulated for the http://castfeedvalidator.com site as well, where pressing the submission button is sufficient, however.
(As you report, even though inspecting the request sent by the submission button shows that a variation of your URL - which only prepares the feed URL for submission - can be used to instantly submit it, doing so doesn't render the results correctly (missing styles)).
The following code implements both suggestions (the simulated-interaction approach was adapted from this answer of mine):
# Sample value
set the clipboard to "https://www.npr.org/rss/podcast.php?id=510298"
set feed_url to the clipboard as string
# Base URL only; the feed URL will be submitted by simulated interaction below.
set the podbaseurl to "http://podba.se/validate/"
set the feedvalidatorurl to "http://feedvalidator.org/check.cgi?url=" & feed_url
set the castfeedurl to "http://castfeedvalidator.com/?url=" & feed_url
tell application "Safari"
activate
set newDoc to make new document
set newWin to front window
# Simulate interactive submission of feed_url at podbaseurl.
set URL of newDoc to podbaseurl
my submitUrl(newDoc, podbaseurl, feed_url)
# The feedvalidateorurl can be opened normally.
open location feedvalidatorurl
# Simulate interactive submission of feed_url at castfeedurl.
set newTab to make new tab in newWin
set URL of newTab to castfeedurl
my submitUrl(newTab, castfeedurl, feed_url)
end tell
on submitUrl(doc, target_url, feed_url)
# Synthesize the JavaScript command.
set jsCode to "
(function () { // Use a closure to avoid polluting the global namespace.
function doIt(t) { // Helper function
if (doIt.done) return; // Already successfully called? Ignore.
try {
// Perform the desired action - may fail if invoked too early.
if (/^http:\\/\\/podba.se/.test('" & target_url & "')) {
document.querySelector('#url-input').value = '" & feed_url & "';
document.querySelector('#url-input').dispatchEvent(new Event('input'));
setTimeout(function() { document.querySelector('#go-button').click(); }, 0);
} else { // http://feedvalidator.org
document.querySelector('.btn-subscribe').click()
}
} catch(e) {
return; // Return without setting the success 'flag'.
}
doIt.done=true; // Set success 'flag' as a property on this function object.
};
// Attach a listener to the window's load event for invoking the helper function then.
window.addEventListener('load', doIt);
// If the document signals readiness -- which may still be too early, we can't know --
// also try to invoke the helper function *directly*.
if (document.readyState === 'complete') { doIt(); }
})();
"
# Execute the JavaScript command in the target page.
tell application "Safari"
tell doc to do JavaScript jsCode
end tell
end submitUrl

Is it possible to add a hourglass to the cursor?

I want a vbscript.vbs that will add a hourglass to the cursor or completely changes the cursor into hourglass and cursor changes to standard mode at the end of script.
I searched Google a lot but didn't find anything.I haven't even tried a single line of code.
VBS doesn't include this functionality.
By default .vbs files are executed by the Windows Script Host, which doesn't provide a method for updating the cursor either. If you are using another host this may provide a method.
Assuming you are looking for a way to track the progress of your script there are some workarounds.
Method 1
Executing your script via the command line provides a UI, which you output progress to.
Method 2
Wrap your VBScript inside a HTA. This will provide a one page HTML UI. You could include some sort of progress indicator here.
As he said "destination-data" ==> VBS doesn't include this functionality.
But if you wrap your VBScript inside a HTA, you can found a workaround for this
Here is an example in HTA found here
<HTML>
<HEAD>
<STYLE>
.clsAccKey:first-letter {text-decoration: underline}
BUTTON {width: 15ex}
</STYLE>
<SCRIPT language=VBScript>
Option Explicit
Sub btnClick_onclick()
btnClick.disabled = True
document.body.style.cursor = "wait"
btnClick.style.cursor = "wait"
'Long delay here just to simulate a long
'running process visually for this demo.
setTimeout "HiThere", 2000, "VBScript"
End Sub
Sub HiThere()
document.body.style.cursor = "default"
btnClick.style.cursor = "default"
MsgBox "Hi There!"
btnClick.disabled = False
End Sub
</SCRIPT>
</HEAD>
<BODY>
<BUTTON id=btnClick accessKey=C class=clsAccKey>Click Me</BUTTON>
</BODY>
</HTML>
And i used it in this example : Execution a powershell file with HTA
<html>
<head>
<title>Execution a powershell file with HTA by Hackoo</title>
<HTA:APPLICATION
APPLICATIONNAME="Execution a powershell file with HTA by Hackoo"
SCROLL="yes"
SINGLEINSTANCE="yes"
WINDOWSTATE="maximize"
ICON="Winver.exe"
SCROLL="no"
/>
<script language="VBScript">
Option Explicit
Sub Run_PS_Script()
ExampleOutput.value = ""
btnClick.disabled = True
document.body.style.cursor = "wait"
btnClick.style.cursor = "wait"
Dim WshShell,Command,PSFile,return,fso,file,text,Temp
Set WshShell = CreateObject("WScript.Shell")
Temp = WshShell.ExpandEnvironmentStrings("%Temp%")
Command = "cmd /c echo Get-WmiObject Win32_Process ^| select ProcessID,ProcessName,Handle,commandline,ExecutablePath ^| Out-File %temp%\output.txt -Encoding ascii > %temp%\process.ps1"
PSFile = WshShell.Run(Command,0,True)
return = WshShell.Run("powershell.exe -ExecutionPolicy Unrestricted -File %temp%\process.ps1", 0, true)
Set fso = CreateObject("Scripting.FileSystemObject")
Set file = fso.OpenTextFile(Temp &"\output.txt", 1)
text = file.ReadAll
ExampleOutput.Value=text
file.Close
document.body.style.cursor = "default"
btnClick.style.cursor = "default"
btnClick.disabled = False
End Sub
</script>
</head>
<body bgcolor="123456">
<textarea id="ExampleOutput" style="width:100%" rows="37"></textarea>
<br>
<center><input type="button" name="btnClick" value="Run powershell script file " onclick="Run_PS_Script()"></center>
</body>
</html>

SetTimeout() won't execute the function

So this is my code snippet:
'in VBScript
Sub Main()
Dim timeoutTimer
'more scripts here
'more scripts here
'more scripts here
timeoutTimer = window.setTimeout("alert()", 2000)
Call WaitForAnEvent() 'This function waits for an event to happen
'if there is no event then code execution stop's
'and wait
'more scripts here
'more scripts here
'more scripts here
End Sub
Sub alert()
MsgBox "Help!"
End Sub
What happens is, there are times when alert() is not triggered, and I don't have any idea why. I conducted some research about setTimeout() and they said that setTimeout will be triggered if the timer expires and as soon as there is an available opportunity to execute it. I believe after WaitForAnEvent() is invoked there will be an available opportunity for setTimeout to be executed but
sometimes it is and sometimes it is not.
Update -------------------------------------------------------------------------------
I had been reading a lot of articles about setTimeout and they all say(in short) that it cannot be triggered if the browser is busy doing something.
Now:
Is it correct to assume that the browser is doing something(infinite), and
setTimeout cannot find an available moment to trigger the function?
Is there a way in VBScript/Javascript to check if IE(browser) is currently doing somthing like rendering text or executing some scripts?
I think you should change your function name from alert to something that does not collide with elements exposed by the browser (there is a window.alert() function). Maybe this will work as is (not tested), but it is better to avoid confusion
The proper syntax to bind the event to the handler is to retrieve a reference to the function (here renamed)
window.setTimeout(GetRef("showAlert"), 2000)
Probably because I don't have enough information, but I don't see the need for your WaitForAnEvent() function. Events happen. You bind the function to execute on event and leave to the browser the work to call the event handler when needed
edited Just for a sample (adapted from a previous answer)
In this HTA, there are five events being handled: Start button press, Stop button press, Exit button press, Clock interval and File existence check
The basic idea is NOT to have code running all the time. The browser has the control and when an event happens (button pressed or interval reached) the code to handle the event is called and ends.
<html>
<head>
<title>ClockwithAlerts</title>
<HTA:APPLICATION
ID="ClockHTA"
APPLICATIONNAME="ClockHTA"
MINIMIZEBUTTON="no"
MAXIMIZEBUTTON="no"
SINGLEINSTANCE="no"
SysMenu="no"
BORDER="thin"
/>
<SCRIPT LANGUAGE="VBScript">
Const TemporaryFolder = 2
Dim timerID, timerFile
Sub Window_onLoad
window.resizeTo 600,280
SetClockTimer True
timerFile = window.setInterval(GetRef("CheckFilePresence"), 1500)
End Sub
Sub CheckFilePresence
Dim myFile
With CreateObject("Scripting.FileSystemObject")
myFile = .BuildPath(.GetSpecialFolder( TemporaryFolder ), "test.txt")
If .FileExists(myFile) Then
fileStatus.innerText = "FILE ["& myFile &"] FOUND"
Else
fileStatus.innerText = "File ["& myFile &"] is not present"
End If
End With
End Sub
Sub SetClockTimer( Enabled )
If Enabled Then
timerID = window.setInterval(GetRef("RefreshTime"), 1000)
RefreshTime
Else
window.clearInterval(timerID)
timerID = Empty
End If
StartButton.disabled = Enabled
StopButton.disabled = Not Enabled
End Sub
Sub RefreshTime
CurrentTime.InnerHTML = FormatDateTime(Now, vbLongTime)
End Sub
Sub ExitProgram
If Not IsEmpty(timerID) Then window.clearInterval(timerID)
If Not IsEmpty(timerFile) Then window.clearInterval(timerFile)
window.close()
End Sub
</SCRIPT>
</head>
<body>
<input id="checkButton" type="button" value="EXIT" name="run_button" onClick="ExitProgram" align="right">
<br><br>
<span id="CurrentTime"></span>
<br><br>
<input id="Stopbutton" type="button" value="Stop" name="StopButton" onclick="SetClockTimer(False)">
<input id="StartButton" type="button" value="Start" name="StartButton" onclick="SetClockTimer(True)">
<hr>
<span id="fileStatus"></span>
</body>
</html>
try remove quotes around your function name:
timeoutTimer = window.setTimeout(alert, 2000)

Applescript to click on search results/other web page buttons and links?

How would I use Applescript to click on a web link in a google search. Can I identify them by name or number or anything?
Safari:
tell application "Safari"
open location "http://google.com/search?q=example"
do JavaScript "window.addEventListener('load', function() {
document.querySelectorAll('.r a')[0].click()
})" in document 1
end tell
Chrome:
tell application "Google Chrome"
open location "http://google.com/search?q=example"
tell active tab of window 1
execute javascript "window.addEventListener('load', function() {
document.querySelectorAll('.r a')[0].click()
})"
end tell
end tell
Edit: try something like this to match a YouTube result by title:
document.querySelector('.yt-uix-tile-link').click()
Edit 2: changed window.onload=function(){} to window.addEventListener('load',function(){}).
Building on #Lauri Ranta's great answer, here is convenience function clickOn(), which:
accepts a target document, a CSS selector string plus a zero-based index to select among what the selector string matches, and simulates a click on the element thus identified.
works irrespective of whether the target document is still being loaded or has already fully loaded - this turned out to be non-trivial. (Lauri's code relies on the window object's load event not to have fired yet).
works with both Safari and Google Chrome (if you don't have Chrome installed, you'll have to comment out a few lines)
Examples that use a delay to demonstrate that the click works even after the document has fully loaded:
# SAFARI
# Click on the *2nd* result returned from googling 'example' with Safari:
tell application "Safari"
open location "http://google.com/search?q=example"
delay 5 # sample delay - NOT needed
my clickOn(document 1, ".r a", 1)
end tell
# CHROME
tell application "Google Chrome"
open location "http://google.com/search?q=example"
delay 5 # sample delay - NOT needed
my clickOn(active tab of window 1, ".r a", 1)
end tell
clickOn source code:
on clickOn(doc, cssSelector, ndx)
# If no explicit index (into the matches returned by the CSS selector)
# is specified, default to 0.
if ndx is missing value or ndx = "" then set ndx to 0
# Synthesize the JavaScript command.
set jsCode to "
(function () { // Use a closure to avoid polluting the global namespace.
function doIt(t) { // Helper function
if (doIt.done) return; // Already successfully called? Ignore.
try {
// Perform the desired action - may fail if invoked too early.
document.querySelectorAll('" & cssSelector & "')[" & ndx & "].click();
} catch(e) {
return; // Return without setting the success 'flag'.
}
doIt.done=true; // Set success 'flag' as a property on this function object.
};
// Attach a listener to the window's load event for invoking the helper function then.
window.addEventListener('load', doIt);
// If the document signals readiness -- which may still be too early, we can't know --
// also try to invoke the helper function *directly*.
if (document.readyState === 'complete') { doIt(); }
})();
"
# Execute the JavaScript command in the target page.
if class of doc as text is "document" then # Safari: a «document» instance was passed
using terms from application "Safari"
tell doc to do JavaScript jsCode
end using terms from
else # Google Chrome: a «tab» instance was passed
# !! IF CHROME IS NOT INSTALLED, SIMPLY DEACTIVATE THIS `using terms from` BLOCK.
using terms from application "Google Chrome"
tell doc to execute javascript jsCode
end using terms from
end if
end clickOn

A Game Exit Menu

I need some help with a quick question.I have a HTA Application that is the menu for a game I am making, here is the problem, I have a exit button, but when you click it, it just closes the program, but what I want is to make it so when you click the exit button, a VBS dialog box pops up and asks, "Are you sure you want to exit the game?", with yes or no buttons, can anyone help me?
Thanks :D
Make the procedure called by your exit button look like this:
Sub ExitHTA
answer = MsgBox("Are you sure?", vbYesNo)
If answer = vbYes Then self.close()
End Sub
If you want you can put the application name as the message box title like this:
<html>
<title>My Game</title>
<HTA:APPLICATION ID="oHTA"
APPLICATIONNAME="My Game"
...
>
<script language="VBScript">
...
Sub ExitHTA
answer = MsgBox("Are you sure?", vbYesNo, oHTA.ApplicationName)
If answer = vbYes Then self.close()
End Sub
</script>
<body>
...
<input type="button" id="exitbtn" onClick="vbscript:ExitHTA" value="Exit">
...
</body>

Resources