(*
The script automatically creats folder "MacScripter Topics" and numerated subfolder in it,
adds to name of topic its MacScripter index,
saves the (10, or more) topics as webarchive.
Made some improvments to stabilize the script,
display dialog is replaced with display notification to not interrupt the process
Written by KniazidisR
I used here the ideas and snippets from Fredrik71 and
Shane Stanley <sstanley@myriad-com.com.au>
*)
use AppleScript version "2.4" -- Yosemite (10.10) or later
use scripting additions
use framework "Foundation"
use framework "AppKit"
use framework "WebKit"
property loadingWaitMaximumSeconds : 10
property thePath : missing value
property indexOfNewestTopic : 32247 -- indicate here the Topic you consider as newest
set indexofLastTopics to 1 -- indexOfNewestTopic - 9
set homeFolderHFS to (path to home folder from user domain) as text
tell application "Finder" to if not (exists (homeFolderHFS & "MacScripter Topics:")) then make new folder at documentsFolderHFS with properties {name:"MacScripter Topics"}
set macscripterFolder to alias (homeFolderHFS & "MacScripter Topics:")
set destinationFolderHFS to (macscripterFolder as text) & indexofLastTopics & "-" & indexOfNewestTopic
tell application "Finder" to if not (exists destinationFolderHFS) then make new folder at (macscripterFolder as text) with properties {name:("" & indexofLastTopics & "-" & indexOfNewestTopic)}
set destinationFolderPath to POSIX path of (alias destinationFolderHFS)
tell application "Safari" to activate
repeat with i from indexOfNewestTopic to indexofLastTopics by -1
-- open location
tell application "Safari" to make new document with properties ¬
{URL:("https://www.macscripter.net/viewtopic.php?id=" & i)}
-- check page full loading
set isLoaded to my waitSafariWebPageLoading(loadingWaitMaximumSeconds)
if isLoaded then
if document "Info / MacScripter" of application "Safari" exists then
-- badTopic URL : "The link you followed is incorrect or outdated."
close document "Info / MacScripter" of application "Safari" saving no
else
-- Tell Safari to get the name and URL of document 1
tell application "Safari" to tell document 1 to set {theName, theURL} to {name, URL}
-- Correct the name string.
set theName to (my stringOffsetBeginOrEnd:theName withOffset:"/" withOption:"end")
-- Output path of the file.
set thePath to destinationFolderPath & i & ". " & theName & " .webarchive"
-- Run the handler.
(my archivePage:theURL toPath:thePath)
-- Following 2 lines is optional. Remove them to speed up the process
display notification "Webpage saved"
delay 7 -- this is to to allow switching notification
end if
-- close current document
tell application "Safari" to close documents saving no
end if
end repeat
on waitSafariWebPageLoading(loadingWaitMaximumSeconds as integer)
set lineChangingChars to {linefeed, return, character id 11, character id 12, character id 133, character id 8232, character id 8233}
set {ATID, htmlEnding} to {AppleScript's text item delimiters, ""}
tell application "Safari"
repeat 100 * loadingWaitMaximumSeconds times
delay 0.1
set AppleScript's text item delimiters to {"<", ">"}
try
copy text item -2 of (get source of front document) to htmlEnding
end try
set AppleScript's text item delimiters to lineChangingChars
set htmlEnding to text items of htmlEnding
set AppleScript's text item delimiters to ""
set htmlEnding to "<" & htmlEnding & ">"
if htmlEnding is "</html>" then exit repeat
end repeat
end tell
set AppleScript's text item delimiters to ATID
if htmlEnding is "</html>" then return true
display notification "The webpage loading failed"
return false
end waitSafariWebPageLoading
on archivePage:thePageURL toPath:aPath
set my thePath to aPath -- store path for use later
my performSelectorOnMainThread:"setUpWebViewForPage:" withObject:thePageURL waitUntilDone:true
end archivePage:toPath:
on setUpWebViewForPage:thePageURL
-- needs to be done on the main thread
-- make a WebView
set theView to current application's WebView's alloc()'s initWithFrame:{origin:{x:0, y:0}, |size|:{width:100, height:100}}
-- tell it to call delegate methods on me
theView's setFrameLoadDelegate:me
-- load the page
theView's setMainFrameURL:thePageURL
end setUpWebViewForPage:
-- called when the WebView loads a frame
on WebView:aWebView didFinishLoadForFrame:webFrame
-- the main frame is our interest
if webFrame = aWebView's mainFrame() then
-- get the data and write it to file
set theArchiveData to webFrame's dataSource()'s webArchive()'s |data|()
theArchiveData's writeToFile:thePath atomically:true
-- display notification "The webarchive was saved"
end if
end WebView:didFinishLoadForFrame:
on WebView:WebView didFailLoadWithError:theError forFrame:webFrame
-- got an error, bail
WebView's stopLoading:me
display notification "The webarchive was not saved"
end WebView:didFailLoadWithError:forFrame:
on stringOffsetBeginOrEnd:theString withOffset:theChar withOption:theOption
set aString to theString
set x to the offset of theChar in aString
if (theOption = "begin") then
return (text from x to 1 of aString)
else if (theOption = "end") then
return (text from (x + 2) to -1 of aString)
else
error number -128
end if
end stringOffsetBeginOrEnd:withOffset:withOption:
Interesting and useful, thanks!