-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathWebLib.scpt
More file actions
456 lines (378 loc) · 14.4 KB
/
WebLib.scpt
File metadata and controls
456 lines (378 loc) · 14.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
#@osa-lang:AppleScript
use framework "AppKit"
use framework "Foundation"
use framework "PDFKit"
use framework "WebKit"
use framework "CoreWLAN"
use scripting additions
property NSURL : class "NSURL"
property NSImage : class "NSImage"
property NSURLComponents : class "NSURLComponents"
property NSString : class "NSString"
property NSMutableString : class "NSMutableString"
property NSRegularExpression : class "NSRegularExpression"
property NSDataDetector : class "NSDataDetector"
property NSSet : class "NSSet"
property monthNames : {January, February, March, April, May, June, July, August, September, October, November, December}
-- Filetypes
property PNG : "PNG"
property JPG : "JPG"
property HTML : "HTML"
property TXT : "TXT"
property PDF : "PDF"
script WiFiManager
use framework "CoreWLAN"
(*
Disconnects from the current WiFi network.
*)
on disconnect()
set interface to current application's CWWiFiClient's sharedWiFiClient()'s interface()
interface's disassociate()
end disconnect
(*
Disables the WiFi interface.
*)
on disable()
set interface to current application's CWWiFiClient's sharedWiFiClient()'s interface()
my (interface's setPower:false |error|:(missing value))
end disable
(*
Enables the WiFi interface.
*)
on enable()
set interface to current application's CWWiFiClient's sharedWiFiClient()'s interface()
my (interface's setPower:true |error|:(missing value))
end enable
(*
Gets the MAC address of the WiFi interface.
*)
on getMACAddress()
return current application's CWWiFiClient's sharedWiFiClient()'s interface()'s hardwareAddress() as text
end getMACAddress
(*
Gets the current aggregate RSSI measurement for the WiFi interface.
*)
on getRSSI()
return current application's CWWiFiClient's sharedWiFiClient()'s interface()'s rssiValue()
end getRSSI
(*
Gets the SSID of the current WiFi network.
*)
on getSSID()
return current application's CWWiFiClient's sharedWiFiClient()'s interface()'s ssid() as text
end getSSID
(*
Attempts to connect to the network with the given name, using the provided password.
Params:
networkName (String) - The name of the WiFi network to connect to.
thePassword (String) - The password to authenticate the connection with.
Returns:
(Boolean) - True if the network was connected to successfully, false otherwise.
*)
on connectToNetwork:networkName usingPassword:thePassword
set theWiFiInterface to current application's CWWiFiClient's sharedWiFiClient()'s interface()
set theNetworks to (theWiFiInterface's scanForNetworksWithSSID:(missing value) |error|:(missing value))'s allObjects()
repeat with theNetwork in theNetworks
if theNetwork's ssid() as text is networkName then
log "hi"
(theWiFiInterface's associateToNetwork:theNetwork |password|:thePassword |error|:(missing value))
return true
end if
end repeat
return false
end connectToNetwork:usingPassword:
(*
Scans for available WiFi networks and returns the list of network SSIDs.
*)
on getAvailableNetworks()
set theWiFiInterface to current application's CWWiFiClient's sharedWiFiClient()'s interface()
set theNetworks to (theWiFiInterface's scanForNetworksWithSSID:(missing value) |error|:(missing value))'s allObjects()
set theSSIDs to {}
repeat with theNetwork in theNetworks
copy theNetwork's ssid() as text to end of theSSIDs
end repeat
return theSSIDs
end getAvailableNetworks
end script
(*
Initializes a new Website instance.
Returns:
(Website) - The newly created website instance.
Example:
set mySite to WebLib's WLWebsite()
set mySite's URLString to "https://apple.com"
return mySite
*)
on WLWebsite()
script Website
use framework "Foundation"
property title : missing value
property «class dscr» : missing value
property URLString : missing value
property HTML : missing value
property visibleText : missing value
property favicon : missing value
property host : missing value
property scheme : missing value
property pathString : missing value
property query : missing value
property queryItems : missing value
property port : missing value
(*
Pings the site's host the speciifed number of times, returning the average.
Params:
numAttempts (Number) - The number of times to ping the website host.
Returns:
(Number) - The average ms per ping.
*)
on ping over numAttempts : 1
set hostname to my host
set pingCommand to "/sbin/ping -c " & numAttempts & " " & quoted form of hostname & " | tail -1| awk '{print $4}' | cut -d '/' -f 2"
set pingOutput to do shell script pingCommand
return pingOutput as number
end ping
(*
Saves the website as a text file, HTML file, PDF, PNG, or JPG.
Params:
filePath (String) - The path to save the site to.
fileType (String) - The filetype to save the site as; TXT, HTML, PDF, PNG, or JPG.
Returns:
(Boolean) - True if the file was saved successfully false otherwise.
*)
on save in filePath as filetype : "txt"
set _NSURL to current application's NSClassFromString("NSURL")
set theURL to NSURL's URLWithString:(my URLString)
set theData to current application's NSData's dataWithContentsOfURL:theURL
try
ignoring case
if filetype is TXT or filetype is HTML then
tell application "System Events"
set homedir to current user's home directory as text
set theFile to open for access filePath with write permission
write my HTML to theFile
close access theFile
end tell
else if filetype is PDF then
try
do shell script "/usr/local/bin/wkhtmltopdf \"" & (my URLString) & "\" \"" & filePath & "\"" user name "steven"
on error err
log err
display alert "Install wkhtmltopdf from wkhtmltopdf.org."
end try
else if filetype is PNG then
try
do shell script "/usr/local/bin/wkhtmltoimage --format \"PNG\" \"" & (my URLString) & "\" \"" & filePath & "\"" user name "steven"
on error err
log err
display alert "Install wkhtmltoimage from wkhtmltopdf.org."
end try
else if filetype is JPG then
try
do shell script "/usr/local/bin/wkhtmltoimage --format \"JPG\" \"" & (my URLString) & "\" \"" & filePath & "\"" user name "steven"
on error err
log err
display alert "Install wkhtmltoimage from wkhtmltopdf.org."
end try
end if
end ignoring
on error
return false
end try
return true
end save
(*
Opens the website in the default browser.
*)
on open
open location URLString
end open
end script
end WLWebsite
(*
Gets the average ping to a website over the specified number of attempts.
Params:
site (Website or String) - The Website script object or URL string to get the ping to.
numAttempts (Number) - The total number of times to ping the site.
Returns:
(Number) - The average ping time.
Example:
set mySite to WebLib's websiteWithURLString:"https://apple.com"
return WebLib's (ping for mySite over 3)
*)
on ping for site over numAttempts : 1
if class of site is script then
return site's (ping over numAttempts)
else if class of site is text then
set theURL to NSURL's URLWithString:site
set hostname to theURL's |host|() as text
set pingCommand to "/sbin/ping -c " & numAttempts & " " & quoted form of hostname & " | tail -1| awk '{print $4}' | cut -d '/' -f 2"
set pingOutput to do shell script pingCommand
return pingOutput as number
end if
end ping
(*
Creates a new Website script object for the given URL.
Params:
URLString (String) - The URL of the target website.
Returns:
(Website) - A new Website script object configured for the target URL.
Example:
set mySite to WebLib's websiteWithURLString:"https://apple.com"
*)
on websiteWithURLString:URLString
set newWebsite to WLWebsite()
set newWebsite's URLString to URLString
set theURL to NSURL's URLWithString:URLString
set newWebsite's host to (theURL's |host|()) as text
set newWebsite's scheme to (theURL's |scheme|()) as text
set newWebsite's pathString to (theURL's |path|()) as text
set newWebsite's query to (theURL's query()) as text
set newWebsite's port to (theURL's |port|()) as text
set faviconURL to NSURL's URLWithString:("http://" & newWebsite's host & "/favicon.ico")
try
set faviconImg to NSImage's alloc()'s initWithContentsOfURL:faviconURL
set newWebsite's favicon to faviconImg
on error err
log err
end try
set URLComponents to NSURLComponents's componentsWithString:URLString
set theQueryItems to {} as record
if URLComponents's queryItems() is not missing value then
repeat with theComponent in URLComponents's queryItems()
set theQueryItems to theQueryItems & {name:theComponent's |name|() as text, value:theComponent's value() as text}
end repeat
end if
set newWebsite's queryItems to theQueryItems
set theHTML to NSString's alloc()'s initWithContentsOfURL:theURL
if theHTML is missing value then
return newWebsite
end if
set newWebsite's HTML to theHTML as text
-- Extract the website's title
set titleRegex to NSRegularExpression's regularExpressionWithPattern:"<title>(.*?)</title>" options:0 |error|:(missing value)
set titleMatch to titleRegex's firstMatchInString:theHTML options:0 range:{0, theHTML's |length|()}
if titleMatch is not (missing value) then
set titleRange to titleMatch's rangeAtIndex:1
set newWebsite's title to (theHTML's substringWithRange:titleRange) as text
end if
-- Extract the website's visible text
set theVisibleText to NSMutableString's stringWithCapacity:(theHTML's |length|())
theVisibleText's setString:theHTML
set htmlTagsRegex to NSRegularExpression's regularExpressionWithPattern:"(<head>[\\S\\s\\n\\r]*?<\\/head>|<script[\\s\\S\\n\\r]+?<\\/script>|<style[\\s\\S\\n\\r]+?<\\/style>|<a [\\s\\S\\n\\r]+?<\\/a>|<nav[\\s\\S\\n\\r]+?<\\/nav>|<link[\\s\\S\\n\\r]+?<\\/link>|<form[\\s\\S\\n\\r]+?<\\/form>|<button[\\s\\S\\n\\r]+?<\\/button>|<!--[\\s\\S\\n\\r]+?-->|<select[\\s\\S\\n\\r]+?<\\/select>|<[\\s\\n\\r\\S]+?>|&.*?;)" options:0 |error|:(missing value)
htmlTagsRegex's replaceMatchesInString:theVisibleText options:0 range:{0, theHTML's |length|()} withTemplate:""
set excessSpaceRefex to NSRegularExpression's regularExpressionWithPattern:"[\\s\\n\\r]+" options:0 |error|:(missing value)
excessSpaceRefex's replaceMatchesInString:theVisibleText options:0 range:{0, length of (theVisibleText as text)} withTemplate:" "
set newWebsite's visibleText to (theVisibleText as text)
return newWebsite
end websiteWithURLString:
(*
Creates a new Website script object for the given URL.
Params:
URLString (String) - The URL of the target website.
Returns:
(Website) - A new Website script object configured for the target URL.
Example:
set mySite to WebLib's (website for "https://apple.com")
*)
on Website for URLString
return my websiteWithURLString:URLString
end Website
(*
Initializes a new WebScraper instance.
Returns:
(WebScraper) - The newly created web scraper.
Example:
set newScraper to WebLib's WLWebScraper()
set newScraper's target to "https://apple.com"
return newScraper
*)
to WLWebScraper()
script WebScraper
use framework "Foundation"
property target : missing value
on itemsWithTypes:theTypes forKeyPath:theKeyPath
if target is missing value then
error "Must set target"
end if
set theURL to NSURL's alloc()'s initWithString:target
set theHTML to NSString's stringWithContentsOfURL:theURL encoding:(current application's NSUTF8StringEncoding) |error|:(missing value)
set theDetector to NSDataDetector's dataDetectorWithTypes:theTypes |error|:(missing value)
set linkArray to theDetector's matchesInString:theHTML options:0 range:{location:0, |length|:theHTML's |length|()}
set linkArray to (linkArray's valueForKeyPath:theKeyPath)
set linkArray to NSSet's setWithArray:linkArray
return linkArray's allObjects() as list
end itemsWithTypes:forKeyPath:
on extractLinks()
return my itemsWithTypes:32 forKeyPath:"URL.absoluteString"
end extractLinks
on extractPhoneNumbers()
return my itemsWithTypes:(current application's NSTextCheckingTypeLink) forKeyPath:"URL.absoluteString"
end extractPhoneNumbers
on extractTransitInfo()
return my itemsWithTypes:(current application's NSTextCheckingTypeTransitInformation) forKeyPath:"transitComponents"
end extractTransitInfo
on extractDates()
return my itemsWithTypes:(current application's NSTextCheckingTypeDate) forKeyPath:"date"
end extractDates
on extractAddresses()
return my itemsWithTypes:(current application's NSTextCheckingTypeAddress) forKeyPath:"addressComponents"
end extractAddresses
end script
end WLWebScraper
(*
Creates a new web scraper for a URL.
Params:
URLString (String) - The URL of a website to scrape.
Returns:
(WebScraper) - A new WebScraper script object configured for the target URL.
Example:
set mySite to "https://apple.com"
set scraper to WebLib's webScraperForURLWithString: mySite
*)
on webScraperForURLWithString:URLString
set newScraper to WLWebScraper()
set newScraper's target to URLString
return newScraper
end webScraperForURLWithString:
(*
Creates a new web scraper for a website.
Params:
theWebsite (Website) - The website to scrape.
Returns:
(WebScraper) - A new WebScraper script object configured for the target website.
Example:
set mySite to WebLib's (website for "https://apple.com")
set scraper to WebLib's (WebScraper for mySite)
*)
on WebScraper for theWebsite
return my webScraperForURLWithString:(theWebsite's URLString)
end WebScraper
(*
Percent-encodes a text string.
Params:
theString (String) - The string to encode.
Returns:
(String) - The percent-encoded string.
Example:
set urlComponent to WebLib's (percentEncoding for "Tim Cook & Friends")
--> "Tim%20Cook%20%26%20Friends"
*)
on percentEncoding for theString
set the theNSString to current application's NSString's stringWithString:theString
set allowedCharacterSet to current application's NSCharacterSet's alphanumericCharacterSet
return (theNSString's stringByAddingPercentEncodingWithAllowedCharacters:allowedCharacterSet) as text
end percentEncoding
(*
Decodes a percent-encoded text string.
Params:
theString (String) - The string to decode.
Returns:
(String) - The percent-decoded string.
Example:
set urlComponent to WebLib's (percentDecoding for "Tim%20Cook%20%26%20Friends")
--> "Tim Cook & Friends"
*)
on percentDecoding for theString
set theNSString to current application's NSString's stringWithString:theString
return (theNSString's stringByRemovingPercentEncoding()) as text
end percentDecoding