The dangerous SafariCam!

You may already know the amazing AppCam, but here comes its wicked companion, the dangerous SafariCam!

While AppCam creates an image containing the icons of your currently applications, SafariCam creates an image containing thumbnail screenshots of the websites currently open in your SafariBrowser:

A SafariCam image with horizontal orientation

Yes, now you can visual tell the world what you are currently surfing on the web!

As always, I invite you to download and inspect the AppleScript on your fine Mac:

The dangerous SafariCam (version 0.1, ca. 87.9 KB)

Requirements
AppCam requires
¢ Mac OS X 10.5 Leopard (the script makes use of the newly introduced Scripting Bridge)
and was successfully tested on Intel & PowerPC based Macs

Installation & Usage
Just download and extract the ZIP archive and then open the SafariCam script with a double click. After a short time you will see the created SafariCam files in the following folder on your Mac:

~/Library/Application Support/SafariCam/current/

Note
SafariCam is not a ready-to-use AppleScript, but rather a proof of concept that needs your personal ideas. You will have to add your own custom functions to the code to process the generated SafariCam files. I added an example function that simply opens all generated SafariCam files to get you started. Just imagine to upload the SafariCam images with curl to your FTP server and use them in the sidebar of your WordPress blog! Or as your signature image! A thousand possibilities! Yes, SafariCam puts YOU in the driver seat :smiley: But see the warning below:

Warning
Publishing SafariCam images can result in copyright and security conflicts. Moreover using SafariCam while viewing websites containing adult content can be problematic…
Therefor please use the blacklist property below to prevent embarrassing situations for you and your environment.

Known Problems
SafariCam currently relies on built-in internal properties and not on user-specific preferences that are imported at startup. Therefor please keep in mind that changes made to the internal properties below will affect all users using this AppleScript.

Settings
If you open the SafariCam script with the Script Editor, you will see a number of properties that can be easily edited to adjust SafariCam to your very own requirements.

You can:
¢ alter the update frequency (by default SafariCam creates a new image set every 5 minutes)
¢ choose between PNG or JPG output (JPEG does not offer transparency!)
¢ set the image orientation (horizontal, vertical or both [= 2 image files])
¢ set a border value in pixel used between the thumbnail screenshots
¢ choose to create a text file containing the corresponding URLs and the creation date/time of the current SafariCam image (by default SafariCam will create it)
¢ define a blacklist that can be used to prevent URLs from being processed by SafariCam

Note: After you edited the properties and saved the SafariCam script, please make sure that the two Python scripts named «combimgs.py» and «webkit2png.py» are still located in the Application bundle:
SafariCam.app/Contents/Resources/combimgs.py
SafariCam.app/Contents/Resources/webkit2png.py

Image Creation
The creation of the SafariCam images is done by a Python script (located inside the Script bundle) which uses the newly introduced Scripting Bridge and the NSImage class.
This way SafariCam does not need to rely on external libraries or tools like PIL, ImageMagick or iMagine Photo. Just built-in Mac OS X technologies are used.

How It Works
Once started, SafariCam will stay open and execute the following process in predefined time intervals:

  1. Create a list of all URLs currently open in Safari
  2. Process this list to create thumbnail screenshots of the websites using webkit2png
  3. Create one or more SafariCam images containing all generated thumbnail screenshots
    (4.) Create a text file containing the creation date/time of the current SafariCam images and the corresponding URLs
  4. Now it’s your turn: Write your own custom functions to further process the created SafariCam files!

All SafariCam files are saved in its Application Support folder:
~/Library/Application Support/SafariCam/current/

Special thanks to Joe Hewitt for the NSImage sample code!

More special thanks to Paul Hammond for creating webkit2png!

Important: Opening and saving the below script code in Script Editor won’t result in a usable AppleScript! That is because SafariCam internally relies on two Python scripts, which are located inside its Application bundle. Therefor please download the complete script here.


-- created: 10.05.2008
-- modified: -/-
-- current version: 0.1
-- history:
-- ¢ v0.1:
--   + first public release
-- requires:
-- ¢ Mac OS X 10.5 Leopard
-- (the script makes use of the newly introduced Scripting Bridge)
-- ¢ a fast Apple Macintosh computer is recommended
--
-- special thanks to:
-- Joe Hewitt for his NSImage sample code which I found here:
-- <http://www.joehewitt.com/blog/workflows_part_2.php>
--
-- Paul Hammond for creating webkit2png
-- <http://www.paulhammond.org/webkit2png/>

-- |-|-|-|-|-|-|-|-|-|-|-|-|-|-|
-- Description 
-- |-|-|-|-|-|-|-|-|-|-|-|-|-|-|

-- Welcome to the dangerous SafariCam!
--
-- This AppleScript works like a webcam for the URLs currently open
-- in your Safari web browser.
-- Once started, SafariCam will stay open and execute the following process in
-- predefined time intervals:
--
-- 1. Create a list of all URLs currently open in Safari
-- 2. Process this list to create thumbnail screenshots of the websites using webkit2png
-- 3. Create one or more SafariCam images containing all generated thumbnail screenshots
-- (4.) Create a text file containing the creation date/time of the current SafariCam images and
-- the corresponding URLs
-- 5. Now it's your turn: Write your own custom functions to further process the created SafariCam files!
--
-- All SafariCam files are saved in the Application Support folder:
-- ~/Library/Application Support/SafariCam/current/
--
-- USAGE:
-- Just open SafariCam with a double click on its icon. After a short time you will see the created
-- SafariCam files in the above mentioned Application Support folder.
--
-- NOTE:
-- SafariCam is not a ready-to-use AppleScript, but rather a proof of concept. You will have to add your
-- own custom functions to process the generated SafariCam files (upload to an FTP server, etc.).
-- I added an example function that simply opens all generated SafariCam files to get you started.
--
-- WARNING:
-- Publishing SafariCam images can result in copyright and security conflicts. Moreover using
-- SafariCam while viewing websites containing adult content can be problematic...
-- Therefor please use the blacklist property below to prevent embarrassing situations
-- for you and your environment.
--
-- KNOWN PROBLEMS:
-- SafariCam currently relies on built-in internal properties and not on
-- user-specific preferences that are imported at startup. Therefor changes made to the
-- internal properties below will affect all users using this AppleScript.
--
-- IMAGE CREATION:
-- The creation of the SafariCam images is done by a Python script (located inside the
-- Script bundle) which uses the newly introduced Scripting Bridge and the NSImage class.
-- This way SafariCam does not need to rely on external libraries or tools like PIL,
-- ImageMagick or iMagine Photo.
-- Just built-in Mac OS X technologies are used.
-- The Python script can be found here:
-- SafariCam.app/Contents/Resources/combimgs.py

-- |-|-|-|-|-|-|-|-|-|-|-|-|-|-|
-- Core Properties 
-- |-|-|-|-|-|-|-|-|-|-|-|-|-|-|

-- the name of this AppleScript
property mytitle : "SafariCam"

-- |-|-|-|-|-|-|-|-|-|-|-|-|-|-|
-- The following properties can be edited to adjust
-- the script to your very own requirements.
-- |-|-|-|-|-|-|-|-|-|-|-|-|-|-|

-- this property defines the time interval in seconds in which
-- SafariCam will create one or more SafariCam images containing
-- thumbnail screenshots of the websites currently open in Safari
-- default value: 300 (= 5 minutes)
property updfrequency : 300

-- this property defines the image format used for the SafariCam image
-- default value: "PNG" (= PNG format)
-- alternative value: "JPG" (= JPEG format)
-- >> JPEG does not offer transparency! PNG is recommended!
property safaricamimgformat : "PNG"

-- this property defines the orientation of the SafariCam image, horizontal or vertical
-- default value: "hv"
-- alternative values:
-- "h" >> one SafariCam image with horizontal orientation is produced
-- "v" >> one SafariCam image with vertical orientation is produced
-- "hv" >> two SafariCam images are produced (vertical & horizontal orientation)
property safaricamimgorient : "hv"

-- this property defines the border (in pixel) between the website thumbnails
-- in SafariCam images
-- default value : "5"
property safaricamimgborder : "5"

-- this property defines if you also want to create a text file
-- containing the corresponding URLs and the
-- creation date/time of the SafariCam image
-- the text file features UTF-8 text encoding (with BOM)
-- >> this text file can be helpful when integrating SafariCam into your
-- blog or website
-- default value: true
-- alternative value: false
property safaricaminfo : true

-- this property defines a blacklist that can be used
-- to prevent URLs from being processed by SafariCam
-- if a URL contains a word/text item found in the blacklist
-- it will be ignored and not be processed
-- default value: {} (empty list)
-- alternative values: {"adult"}
property blacklist : {}

-- |-|-|-|-|-|-|-|-|-|-|-|-|-|-|
-- Main Script
-- |-|-|-|-|-|-|-|-|-|-|-|-|-|-|

-- I am the idle handler (SafariCam is a stay-open script),
-- I am controlling the application flow
on idle
	try
		-- removing the temp folder containing the temporary image files
		-- (maybe the script did not quit properly the last time?)
		my remtmpfolder()
		-- getting the URLs of the websites currently viewed in Safari
		set safariurls to my getsafariurls()
		if safariurls is not {} then
			-- creating mission critical folder paths (if they do not yet exist)
			my crtappfolders()
			-- creating thumbnail screenshots of the websites using webkit2png
			-- the function returns a list containing the file paths of the
			-- generated images and the processed URLs
			set dict to my crtimagefiles(safariurls)
			set imagefilepaths to item 1 of dict
			set procsafariurls to item 2 of dict
			if imagefilepaths is not {} then
				-- creating the new SafariCam image(s) containing
				-- the generated thumbnail screenshots
				set safaricamimgpaths to my crtsafaricamimages(imagefilepaths)
				-- creating a text file containing the creation date/time of the current
				-- SafariCam image and the URLs of the currently viewed websites
				if safaricaminfo is true then
					set safaricaminfopath to my crtsafaricaminfofile(procsafariurls)
					set safaricamfilepaths to safaricamimgpaths & {safaricaminfopath}
				else
					set safaricamfilepaths to safaricamimgpaths
				end if
				-- ### Put your code here ###
				-- Maybe you want to use the SafariCam image
				-- as an eMail signature in MS Entourage? Or in iChat? Be creative :D
				-- The following function is an example to get you started.
				-- ### Put your code here ###
				my openfiles(safaricamfilepaths)
			end if
		end if
	on error errmsg number errnum
		my dsperrmsg(errmsg, errnum)
	end try
	return updfrequency
end idle

-- I am returning the Mac path of SafariCam's application support folder
on getmyappsuppfolderpath()
	set appsuppfolderpath to ((path to application support folder from user domain) as Unicode text)
	set myappsuppfolderpath to (appsuppfolderpath & mytitle & ":")
	return myappsuppfolderpath
end getmyappsuppfolderpath

-- I am creating mission-critical subfolders in SafariCam's application support folder 
-- 1) /Application Support/SafariCam/current/
-- 2) /Application Support/SafariCam/tmp/
on crtappfolders()
	set myappsuppfolderpath to my getmyappsuppfolderpath()
	set curfolderpath to myappsuppfolderpath & "current:"
	set tmpfolderpath to myappsuppfolderpath & "tmp:"
	repeat with folderpath in {curfolderpath, tmpfolderpath}
		set command to "mkdir -p " & quoted form of (POSIX path of folderpath)
		set command to command as «class utf8»
		do shell script command
	end repeat
end crtappfolders

-- I am returning a list of all URLs currently opened in Safari
on getsafariurls()
	set safariurls to {}
	if my appisrunning("Safari") then
		tell application "Safari"
			set safariwindows to get every window
			repeat with safariwindow in safariwindows
				try
					set windowtabs to every tab of safariwindow
					repeat with windowtab in windowtabs
						set taburl to URL of windowtab
						if taburl is not in safariurls then
							set safariurls to safariurls & taburl
						end if
					end repeat
				end try
			end repeat
		end tell
	end if
	return safariurls
end getsafariurls

-- I am creating thumbnail screenshots of the given URLs using webkit2png
-- and return a special list containing file paths of the generated images
-- as well as the processed URLs {{imagefilepaths}, {procsafariurls}}
on crtimagefiles(safariurls)
	set procsafariurls to {}
	set pyscriptpath to ((path to me) as Unicode text) & "Contents:Resources:webkit2png.py"
	set tmpfolderpath to (my getmyappsuppfolderpath() & "tmp:")
	repeat with safariurl in safariurls
		if my safariurlissafe(safariurl) then
			set command to "python " & quoted form of (POSIX path of pyscriptpath) & " -C -D " & quoted form of (POSIX path of tmpfolderpath) & space & safariurl
			set command to command as «class utf8»
			try
				do shell script command
				set procsafariurls to procsafariurls & safariurl
			end try
		end if
	end repeat
	-- getting the files of the generated website screenshots
	tell application "Finder"
		set imagefiles to every file in folder tmpfolderpath whose name ends with ".png"
	end tell
	set imagefilepaths to {}
	repeat with imagefile in imagefiles
		set imagefilepaths to imagefilepaths & (imagefile as Unicode text)
	end repeat
	return {imagefilepaths, procsafariurls}
end crtimagefiles

-- I am indicating if a URL is safe to process by matching it against the blacklist
on safariurlissafe(safariurl)
	set safe to true
	repeat with txtitem in blacklist
		if safariurl contains txtitem then
			set safe to false
			exit repeat
		end if
	end repeat
	return safe
end safariurlissafe

-- I am creating the new SafariCam images from the given image files and return a list
-- containing file paths of the created SafariCam images
on crtsafaricamimages(imagefilepaths)
	-- as we are going to talk to a Python script next, we need to convert the
	-- image file paths to a large string of quoted Posix paths
	set strpaths to ""
	repeat with imagefilepath in imagefilepaths
		set strpaths to strpaths & quoted form of (POSIX path of imagefilepath) & space
	end repeat
	
	set safaricamimagepaths to {}
	-- creating the appropriate SafariCam images
	repeat with orient in safaricamimgorient
		-- creating SafariCam image file name
		if safaricamimgformat is "PNG" then
			set safaricamimgname to "safaricam" & orient & ".png"
		else if safaricamimgformat is "JPG" then
			set safaricamimgname to "safaricam" & orient & ".jpg"
		end if
		-- creating SafariCam image file path
		set safaricamimgpath to (my getmyappsuppfolderpath() & "current:" & safaricamimgname)
		-- calling the Python script responsible for the image creation
		set pyscriptpath to ((path to me) as Unicode text) & "Contents:Resources:combimgs.py"
		set command to "python " & quoted form of (POSIX path of pyscriptpath) & space & orient & space & safaricamimgformat & space & safaricamimgborder & space & quoted form of (POSIX path of safaricamimgpath) & space & strpaths
		set command to command as «class utf8»
		do shell script command
		set safaricamimagepaths to safaricamimagepaths & safaricamimgpath
	end repeat
	return safaricamimagepaths
end crtsafaricamimages

-- I am creating an SafariCam info text file (UTF-8 + BOM) containing the creation
-- date/time of the current SafariCam images and the corresponding URLs
-- I return the file path of the info text file
on crtsafaricaminfofile(safariurls)
	set filecont to ""
	-- current date in format: 2008-05-08, 23:02:04 (GMT+0200)
	set curdate to do shell script "date \"+%Y-%m-%d, %H:%M:%S (GMT%z)\""
	set filecont to filecont & curdate
	-- adding the current application names
	repeat with safariurl in safariurls
		set filecont to filecont & return & safariurl
	end repeat
	-- creating the info text file
	set safaricaminfopath to (my getmyappsuppfolderpath() & "current:safaricam.info")
	try
		set openfile to open for access safaricaminfopath with write permission
		set eof of openfile to 0
		set BOM_UTF8 to ((ASCII character 239) & (ASCII character 187) & (ASCII character 191))
		write BOM_UTF8 to openfile
		write filecont to openfile as «class utf8» starting at eof
		close access openfile
	on error errmsg number errnum
		try
			close access openfile
		end try
		error errmsg number errnum
	end try
	return safaricaminfopath
end crtsafaricaminfofile

-- I am removing the folder containing the temporary icon images
on remtmpfolder()
	try
		set tmpfolderpath to my getmyappsuppfolderpath() & "tmp:"
		set command to "rm -r " & quoted form of (POSIX path of tmpfolderpath)
		set command to command as «class utf8»
		do shell script command
	end try
end remtmpfolder

-- I am simply trying to open the given file paths
on openfiles(filepaths)
	repeat with filepath in filepaths
		set command to "open " & quoted form of (POSIX path of filepath)
		set command to command as «class utf8»
		do shell script command
	end repeat
end openfiles

-- I am indicating if a given application is currently running
on appisrunning(appname)
	tell application "System Events"
		set processnames to name of processes
	end tell
	if appname is in processnames then
		return true
	else
		return false
	end if
end appisrunning

-- I have a rather thankless task: 
-- I am displaying error messages to the user
-- (I give up after 60 seconds)
on dsperrmsg(errmsg, errnum)
	tell me
		activate
		display dialog "Sorry, an error occured:" & return & return & errmsg & " (" & errnum & ")" buttons {"OK"} default button 1 with icon stop with title mytitle giving up after 60
	end tell
end dsperrmsg