Home

You’re Doing That Wrong is a journal of various successes and failures by Dan Sturm.

Experiments in iSight Scripting

A week or two ago, a conversation with my girlfriend reminded me of this old video from the Defcon 18 Conference, in which a hacker by the name of Zoz recounts the tale of how he located and recovered his recently-stolen computer by way of some fancy Internet skills. In addition to being a great reminder about data safety and security, it’s a pretty damn funny story.

Re-watching the video reminded me I’ve always wanted to experiment with scripting the iSight camera on my MacBook Pro. Not necessarily for the purpose of having photo evidence in the event of a theft, but more as a fun exercise in scripting and automation. Maybe I’m easily entertained (rhetorical), but I found the process and results throughly enjoyable.

Command Line Tools

The first thing I needed was a command line interface to the iSight camera. Despite my best Googling efforts, I wasn’t able to find any native OS tools to fire the camera (I’m still not sure if there is one). But lucky for me, nearly every search I did pointed me to a free, no-longer-supported-but-still-functional CLI tool called iSightCapture. Installation is as simple as tossing it into /usr/local/bin.

Regarding syntax, here’s the pertinent information from the iSightCapture readme file:

isightcapture [-v] [-d] [-n frame-no] [-w width] [-h height] [-t jpg|png|tiff|bmp] output-filename

Options
-v output version information and exit
-d enable debugging messages. Off by default
-n capture nth-frame
-w output file pixel width. Defaults to 640 pixels.
-h output file pixel height. Defaults to 480 pixels.
-t output format - one of jpg, png, tiff or bmp. Defaults to JPEG.

Examples
$ ./isightcapture image.jpg
will output a 640x480 image in JPEG format

$ ./isightcapture -w 320 -h 240 -t png image.png
will output a scaled 320x240 image in PNG format

Triggering

I wanted the ability to remotely trigger the iSight camera from my phone, and have it run for a predefined interval of time. To do this, I’d use a watch folder and a trigger file, uploaded from my phone, to initiate the script. This would theoretically be the method I’d use to “gather photographic evidence” in the event my laptop is stolen.

As usual, to set this up, I turned to my trusty friend Dropbox. To keep things tidy, I needed a couple of folders. The directory structure looks like this:

  • iSight_backup
    • scripts
    • trigger

The photos taken by the script will be placed in the top level directory, iSight_backup. The script itself would be placed in the scripts folder, and the trigger folder remains empty, awaiting a text file to be uploaded via Dropbox on my phone.

The Script

Here’s the script, called isbackup_t.bash, and saved into my iSight_backup/scripts/ folder:

#!/bin/bash  

#   path to iSightCapture CLI tool  
APPP="/usr/local/bin/isightcapture"  

#   path to Dropbox folder to receive photos  
FPATH="/Path/To/Dropbox/iSight_backup/" 

#   path to trigger file  
TPATH="/Path/To/Dropbox/iSight_backup/trigger/"  

#   select photo filetype; jpg, png, tiff, or bmp  
XTN=".jpg"  

#   number of photos to take  
PNUM="24"  

#   interval between photos (seconds)  
PINT="300"  

for i in `seq 1 $PNUM`;  
    do
        DTS=$(date -u +"%F--%H-%M-%S")  
        $APPP "$FPATH$DTS$XTN"  
        sleep $PINT  
    done  

rm $TPATH*  

The Details

Each photo gets a date and time stamp added to the file name for easy sorting. Since the FPATH destination is set to a folder within my Dropbox, and each file is a 640x480 jpeg, approximately 25kb in size, I can see the resulting photos on my phone just seconds after their taken.

By setting PNUM to 24, and PINT to 300, the script will take a photo every 5 minutes, for the next 2 hours, then stop until I upload another trigger file. However, since the script itself lives in Dropbox, I can change the interval or duration variables from my iOS text editor at any time.

Tying The Room Together

All that’s left to complete our little project is to create a launchd task to keep an eye on our trigger folder, and fire up the script if anything lands inside. Since creating, modifying, or using launchd tasks via any method other than a GUI is currently beyond me, I turned to Lingon.

Here’s the resulting launchd task:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>isbackup triggered</string>
    <key>ProgramArguments</key>
    <array>
        <string>bash</string>
        <string>/Path/To/Dropbox/iSight_backup/scripts/isbackup_t.bash</string>
    </array>
    <key>QueueDirectories</key>
    <array>
        <string>/Path/To/Dropbox/iSight_backup/trigger</string>
    </array>
</dict>
</plist>

And just like that, we’ve got a setup that will monitor our trigger folder, fire up our script when it sees anything inside, and save each file to our Dropbox.

Extra Credit

During my research for this project, I found a number of people using iSightCapture for things other than a makeshift security tool. Some, for example, used it to take a self portrait at login every day and auto-upload it to an online photo diary.

I thought that was a fun idea, so I wrote a second, shorter version of my script to automatically take a shot every 2 hours without the need for a trigger. For my version, however, I was most definitely not interested in auto-uploading the photos.

The script:

#!/bin/bash

APPP="/usr/local/bin/isightcapture"
FPATH="/Path/To/Dropbox/iSight_backup/"
DTS=$(date -u +"%F--%H-%M-%S")
XTN=".jpg"

$APPP "$FPATH$DTS$XTN"

And the launchd task:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Disabled</key>
    <false/>
    <key>KeepAlive</key>
    <false/>
    <key>Label</key>
    <string>IS Secuirty</string>
    <key>ProgramArguments</key>
    <array>
        <string>bash</string>
        <string>/Path/To/Dropbox/iSight_backup/scripts/isbackup.bash</string>
    </array>
    <key>QueueDirectories</key>
    <array/>
    <key>RunAtLoad</key>
    <true/>
    <key>StartInterval</key>
    <integer>7200</integer>
</dict>
</plist>

Since I typically use a multiple monitor setup when working, I almost never see the green light come on when the script runs and when I check the photo directory, usually the beginning of the next day, I’m treated to at least a couple hilarious images. Like these, for example:

Hi Merlin!

I may be asleep in this photo. I can't tell.

No, that's not my poster. My girlfriend got to decorate that side of the room.

Yes, It makes Skype calls awkward. Then again, so does that hair.

Cleanup

Despite the photos being almost inconsequentially small in file size, I really don’t need to be keeping a long-running historical record of my disheveled appearance. To keep things from getting unwieldy, I created a Hazel rule that deletes files older than 2 weeks. I see no reason I’d need to keep them any longer than that.

Why?

I don’t know if it’s because this little project was so different from my day to day work, or I thought it would be a genuinely useful security tool, or I’m a narcissist that loves seeing pictures of himself (again, rhetorical), but I had a blast playing around with this little project.

As with nearly everything on this blog, I learned some things, failed a few times, and came out the other side with a fun little script I can demo to people, making it absolutely certain they’ll never ask me anything about computers again.

Running Scripts with TextExpander

I love that the Internet is full of smart people making and sharing awesome things. Like Dr. Drang and his Tidying Markdown Reference Links script. Seth Brown’s formd is another great tool I don’t know how I ever lived without. But, being the amateur that I am, I always struggle to figure out just how to use the scripts these amazing programmers have been kind enough to provide.

Lucky for me (and you), I’m able to play along with the help of everyone’s favorite writing tool, TextExpander. In the documentation for formd, Seth was gracious enough to spell it out for us laypersons[1].


To run formd with TextExpander, simply place the Markdown text to convert onto the clipboard and issue the appropriate TextExpander shortcut (I use fr or fi for referenced or inline, respectively).

It took longer than I’d like to admit, but eventually I realized this snippet could be tweaked to run any script I happen to download from a coder more skilled than myself. Additionally, since most of the scripts I want to use are built for processing text, the copy/paste activation generally works great.

#!/bin/bash
pbpaste | python /Path/To/Your/Script/script.py

With this short snippet, I can copy my text to be processed, invoke the script snippet of my choosing, and have the results immediately pasted back into my text editor, email, or wherever.

This particular snippet assumes you’re running a python script, but you can just as easily swap python for ruby or perl. Or you can omit the python call if you’re just running a standard Bash command. As long as it’s a valid command that would run in the Terminal[2], you can automate it this way. And, just as with formd, to use the snippet, you simply Copy the text to be processed, and invoke the snippet.

Boom. Done. Life is grand.

While none of this is new or revolutionary, connecting the dots between TextExpander and the Terminal is something I wish I’d have discovered long ago and, therefore, may be of interest to you.

Of course none of this would be possible without the amazing minds that write the scripts in the first place. So, along with this post, I offer a sincere Thank You to Dr. Drang and his site And now it’s all this, as well as Seth Brown and his site Dr. Bunsen.


  1. Layfolk? Laypeople? Missing the point?  ↩

  2. And frankly, I just start trying things in the Terminal until I find the correct command.  ↩

Launching Marked from Sublime Text 2

I do pretty much all my MultiMarkdown writing anymore in Sublime Text 2. I’ve come to rely on Marked for previewing my files with a variety of custom CSS files, depending on the type of project I’m writing.

At the moment, the most annoying part of this workflow is the time it takes to open Marked and locate the MultiMarkdown file I’m currently working on in Sublime Text. I think I’ve been spoiled by the speed of using Sublime Text’s Goto Anything feature (Command + P) for opening files.

To speed things along, I wrote a new build system for Sublime Text that launches the active document in Marked. Now previewing my active file is as easy as invoking the build command which, for me, is still Command + B.

The (insanely simple) code [1]:

{  
"shell": "true",  
"cmd": ["open -a marked \"$file\""]  
}  

More non-rocket-science, but a big time saver in my world.


  1. This build system is only for OS X.  ↩

Automated FTP upload with Hazel via Bash

A couple weeks ago Macdrifter had a nice post about automating FTP uploads with Hazel, Dropbox, and Python. It’s a similar idea to the setup I’ve been using to automate my MultiMarkdown workflow, but the main reason it grabbed my interest was this line:

I really like Transmit for FTP, but it seemed a little heavy handed for Hazel automation.

He’s right. Using Transmit for the FTP portion of my process was a poor decision. It just happened to be the only way I knew how, and scripting the FTP upload didn’t even occur to me at the time (there’s a reason for the name of this site).

After reading his post, I decided to swap out the slow and clunky Transmit portion of my Hazel rule with some fancy code. One problem. I don’t know anything about Python[1], and the 3 hours I spent trying to get up to speed were futile and fruitless.

Since I’ve dabbled a bit with Bash, I decided to see if there was an equivalent way to accomplish the same tasks. After a bit of searching, and a lot of trial and error (again, read the name of the site), I came up with this:

HOST=ftp.DOMAIN.com  
USER=myUserName  
PASS=myPassword  

JNAME= \ basename $1\  

ftp -inv $HOST << EOF  

user $USER $PASS  

put "$1" "$JNAME"  

EOF  

echo "http://dansturm.com/$JNAME" >> /Users/PATH/Dropbox/PATH/UPLOADS_LOG_FILE.txt

It’s faster than the Transmit method. It works more often than the Transmit method. And it even records the URL of the uploaded file to a text file in my Dropbox (my favorite idea from the Macdrifter post). I also have the Hazel rule change the file name to all lowercase and swap spaces for underscores, something is already performed in my Text to HTML conversion rule, but now the FTP rule can be used stand-alone as well as in conjunction with the MultiMarkdown process.

It has no error reporting, and you can’t even really tell it’s running (save for the evidence in the log file), but it’s way better than what I was using. Many thanks to Macdrifter for this one.

But…

I’m happy I was able to improve my exiting tools, and learn a few things in the process, but now that I’ve migrated this blog to Squarespace, I’m not sure how much I’ll actually use them considering Squarespace doesn’t support FTP access, and my home site doesn’t need updating very often.


  1. Okay, I know some Python, but only enough to customize the interface in Nuke and build some basic gizmos and comp tools.  ↩

SP-MMD Cheaters

Since Brett Terpstra gave us Cheaters, I’ve been populating the app with the various tools I use frequently.

I’ve finally gotten around to creating a cheat sheet for my MultiMarkdown Screenplay syntax. I expect it to be used by precisely one person. Me.

However I’m posting it here to serve as a shorter explanation of the way I write, to spare you from reading the whole back story. It uses the same modified CSS file I created for the Fountain cheet sheet.

Here’s the SP-MMD Cheaters page.

And here’s the cheat sheet in a web-friendly view for curious passers-by.

My Hazel CMS

It should be no surprise to anyone familiar with the app, that Noodlesoft’s Hazel is amazing. Today I setup an automated system using Dropbox, Automator, and Hazel to process MultiMarkdown documents into HTML, give them web-ready filenames, and upload them to my website.

Everything on this site starts as a MultiMarkdown text file. I preview the page in Marked, and when its ready to go live, I save a copy of the file in a folder called _1_ready_, which has 3 Hazel rules applied.

Ready

First things first, the text file needs to be converted to an HTML document. I’ve used the Run Shell Script action to call the mmd command.

html_from_new.png

Pretty straight forward. To add some flexibility, the second Hazel rule for the _1_ready_ folder checks for changes to preexisting text files, and processes them using the same bash script. That saves me from having to delete and re-copy a file to make an update.

html_from_updated.png

The last rule for the _1_ready_ folder renames the HTML file, making it entirely lowercase, replaces the spaces with underscores, and moves the new file to a folder called _2_go_.

rename_and_move.png

It’s important to make sure the name element in the with patern: section is set to lowercase, and the replace text dialog is used to swap the spaces for underscores.

Go

The _2_go_ folder automatically uploads any file it finds to the root of my site. As with _1_ready_, the final files are left in the folder to more easily make changes later. Additionally, I keep a copy of my Blog index page and rss XML in the _2_go_ folder so I can quickly update the main page with links to the new posts.

upload_to_ftp.png

To upload the files, the Hazel rule calls an Automator Workflow that uses the Transmit [1] upload action to log into my site (stored as a favorite), and drop everything in the root folder, overwriting files if necessary.

transmit_automator.png

Dropbox

The best part about this whole workflow is Dropbox. Both the _1_ready_ and _2_go_ folders are in my Dropbox, giving me the ability to drop in files from my iPhone, iPad, etc. With apps like TextExpander and Nebulous Notes, there’s no reason I can’t create, and post entirely from an iOS device. Obviously I’ll need a Mac, running and online, but the flexibility of this workflow is well worth the cost of a dedicated system.

Needless to say, I’m incredibly excited to have this new capability, and I can’t wait to see what other workflow magic I can create with Hazel


  1. Many thanks to Macdrifter for recommending Transmit. I love this app.  ↩

Update: I've since revised my upload method to use a Bash script, rather than Transmit. It's much faster and more efficient, so if this idea interests you, you should definitely check it out.