Finder Folder Actions not being triggered when files are added with rsync

A couple weeks ago I wrote about how I was automatically capturing the photos and videos my kids’ daycare emails to me and importing them into Photos.app. The major pieces of that script worked fine – parsing the emails, downloading the images, and then rsync’ing them down to my Mac every hour.

But what was failing was the Finder Folder Action I setup that was supposed to import the files into Photos.app whenever new ones were added to that folder.

For some reason, the Folder Action would only occasionally fire. Maybe for one out of every ten items. Sometimes, if I navigated to the folder in the Finder, the action would kick-in and import everything. But sometimes not.

All I can think is that because the files were being added to the folder via rsync – using some BSD-like filesystem APIs instead of the higher-level macOS ones – the Folder Action was never being triggered. Again, it occasionally worked, but mostly failed. So I could be entirely wrong about all of this.

Anyway, I rewrote the whole thing to just run an AppleScript every hour via cron, which handles the whole process itself. Since making that change it’s been working perfectly.

Maybe someone reading this will find it helpful.

Fixing a Broken Service With a Tiny Bit of Automation

This post is a nice, unintentional follow-up to yesterday’s one about backing up all of my family’s photos and home videos. Anyway…

My kids go to a fantastic daycare. My wife and I couldn’t be happier. The teachers are wonderful, they love our children, and our kids adore them, too. But, the third-party service the school uses to communicate with parents is absolute horseshit.

I won’t say what the service is because I don’t want to give them free publicity or maybe even alert them to what I’m doing, but if you have daycare-aged children, you probably know it. All the schools use use it.

All of the teachers carry around iPads in the classroom. They use this third-party app to check-in / check-out the children, capture photos and videos throughout the day, record what they ate for lunch and how long they napped, and (if your child is young enough) document their diaper changes. At the end of the day, after we sign them out of school, my wife and I get an automated email from the service with a summary of each kid’s day. But what we look forward to most are the photos/videos they take of our kids that get sent to us as they happen. When you’re slogging through a boring day at the office, seeing a happy picture of your kid on the playground with their friends is awesome.

Now, let me be clear. The service works. Mostly. I mean, it functions adequately. But it’s a horrorshow of app / website design.

It looks like something straight out of 2009-era iPhone development. It’s difficult to use. Crashes frequently. And from what the teachers have told me, the educator version isn’t any better.

Luckily, you don’t have to use their app. You can opt-in to get all the updates and photos sent to you via email, which is what my wife and I do. But, the HTML emails they send have never rendered properly in any email client – desktop or web – that I’ve tried. But that’s fine. They may not be pleasant to look at, but I can read the information in them.

My biggest gripe is that we often want to save any particularly good photos of our kids and share them with the grandparents. You can’t save the photo out of the email, because the embedded image is cropped to a square for some strange reason. You need to first tap on the image to load the full version in a browser and download it from there. Fine. But, any photo that contains any child in addition to your kid – like a group shot with a friend – is displayed with a transparent div on top of it so you can’t download it (at least on a mobile device) for privacy reasons. Look, I get it. Some parents might not want other parents unintentionally posting photos of their kids to social media. But it’s still annoying. It just forces us to take – and then crop – a screenshot. Also, the emails containing videos, which are often the best ones, can’t be downloaded at all.

Last night I got frustrated enough to finally do something about this.

I use Postmark to send all of my company‘s transactional emails. They’re fantastic for sending emails, but one feature they offer that I’ve never taken advantage of is handling inbound emails.

You can forward any email to a secret address they provide you, and they’ll parse the email and POST all of its information as a helpful JSON object to whatever URL you specify.

So, I setup a webhook in their control panel pointing to a PHP script on my web server. Then, I told Fastmail to forward all emails from the daycare service to my secret Postmark email address. You can see where this is going, can’t you?

When they send a new email to my server, the PHP script finds the link in the email’s HTML content that points to the full version on the service’s website. It then downloads that web page, parses out the URL to the full image, downloads that, and saves it into a folder on my server. This works for videos, too.

The PHP script I wrote is specific to the service our daycare uses, but if you’re curious, here it is…

That’s the first step.

Next, my iMac at home runs a script every hour to download any new photos or videos from my server and puts them in a folder inside my Mac’s “Pictures” folder. When that happens, a folder action I built with Automator automatically imports them into Apple’s Photos.app, where they’re synced to all of my mobile devices and iCloud. Soon after that, Google Photos on my iPhone will detect the new items and archive them in Google’s cloud, where they’re backed-up and made available on my wife’s phone as well.

Here’s a photo of the Automator action. It couldn’t be simpler – just one step…

The result? We get to see all of our kids’ photos as they happen, in the nice Photos app on our phones – rather than digging through the service’s crappy emails. And, sharing the pictures with the rest of our family is a one-tap process – even for the videos which previously weren’t available at all!

Finding Related Messages in Apple Mail

After migrating my company’s email away from Gmail a few years ago, I’ve become firmly entrenched with Apple’s Mail.app on the desktop. Everything works great, but I do miss having access to Rapportive’s Gmail extension. It’s great at providing extra information related to the person you’re emailing with. To make up for this lack of functionality, I’ve created a quick AppleScript that automatically opens up a new Mail window and finds any previous conversations I’ve had with the sender. I use it all the time whenever a customer emails so I can quickly see any past conversations.

I’ve built the script into an Alfred workflow that lets me run it via a keyboard shortcut. For Alfred users, here’s the workflow. And the raw AppleScript is below for those of you using FastScripts or some other script launcher.

Automatically Reposition the iOS Simulator on Screen

If you work with two monitors of different sizes, Xcode has an annoying bug of launching the iOS Simulator partially off screen — forcing you to manually drag it into position using the mouse. It’s not that bad the first time, but after a full eight hour working day with hundreds of launches, it gets very tedious.

Luckily, we can solve this with Xcode 4’s new “Behavior” settings and a little AppleScript.

Open up your favorite text editor and create the following script:

#!/bin/sh
osascript -e 'tell app "System Events" to set position of window 1 of process "iOS Simulator" to {-864, 134}'

Where where {-864, 134} are the {X, Y} coordinates you’d like the simulator positioned at.

Save the script somewhere appropriate and select it as a new “Run” command in Xcode’s “Run Starts” behavior.

Xcode Run Behavior

Dial a Phone Number Using Grand Central and PHP

If you’re lucky enough to have a Grand Central account, here’s a quick PHP class that will login to your account and dial a phone number. This is probably one of the more random bits of code I’ve ever written, but I think it’s useful.

<?PHP
    $gc = new GrandCentral('gc_username', 'gc_password');
    $gc->call($your_number, $their_number);

And that’s it. Grand Central will call $your_number and connect you to $their_number.

So, you can dial phone numbers from PHP. Now what?

Well, for starters, here’s an AppleScript Address Book plugin that will let you dial a contact from your Mac. Or, if you’re like me and have lots of conference calls each week, you can attach a script to your iCal events to dial you into the conference number a minute or two prior to the call start time.

As usual, the code is MIT Licensed and available in GitHub.

Contact me if you have any questions.

Managing Exchange Invites in Apple’s iCal

For better or worse, most of my coworkers live and die by their Exchange calendars. Unfortunately, as a developer working on a Mac 24/7, there aren’t many options for dealing with the barrage of Outlook invites I receive each day. I can either use Entourage which only kinda-sorta-works, or I can just deal with it and transcribe each invite manually into iCal or Google calendar. Both options are crap. (Groupcal from Snerdware used to be an option, but it doesn’t support Leopard and their developers appear to have stopped work on the product.) There’s no reason OS X shouldn’t be a full-fledged citizen in an Exchange environment. But, until that happens, here’s a collection of ever-improving AppleScript and PHP hacks I’ve written to make life in an Exchange world a little bit better

There are three problems we need to solve

  1. Viewing a user’s free/busy calendar
  2. Easily adding Exchange invites to iCal
  3. And accepting or declining those invites

My solution is a set of four Applescripts and a PHP script that (for me at least) make this nearly seamless. The bulk of the code is a PHP class called OWA which interacts with Outlook Web Access – a prerequisite for all of this working. Nearly all organizations which run Exchange have this enabled, so it shouldn’t be a problem for most people. The Applescripts are primarily just glue which pull information from Mail and pipe it into the PHP script for processing.

1. Viewing a User’s Free / Busy Schedule in iCal

I’ve placed the OWA PHP script in my Mac’s local web root. To subscribe to a user’s free / busy calendar I choose Subscribe from iCal’s Calendar menu and use the following URL:

http://localhost/owa.php?user=<username>

Where <username> is someone’s Exchange username. Behind the scenes, the PHP script logs into Outlook Web Access and scrapes the user’s calendar info and returns it as a properly formatted iCalendar file which iCal loads.

I’m the first to admit that this isn’t the most user-friendly solution, but it works. I stay subscribed to my manager and nearby coworkers’ schedules since they’re who I typically schedule meetings with. If I need to see someone more exotic, I just create a new calendar for them temporarily and delete it when I’m done.

2. Easily adding Exchange invites to iCal

To move Exchange invites from Mail into iCal, I use this AppleScript. Warning: I’m hardly an AppleScript expert, so suggestions are very much welcome.

tell application "Mail"
    set theSelectedMessages to selection
    repeat with theMessage in theSelectedMessages
        set theAttachment to first item of theMessage's mail attachments
        set theAttachmentFileName to "Macintosh HD:tmp:" & (theMessage's id as string) & ".ics"
        save theAttachment in theAttachmentFileName
        do shell script "fn='/tmp/$RANDOM.ics';cat " & quoted form of POSIX path of theAttachmentFileName & "| grep -v METHOD:REQUEST > $fn;open $fn; rm " & quoted form of POSIX path of theAttachmentFileName & "; exit 0;"
    end repeat
end tell

In a nutshell, that grabs the first attachment from the currently selected Mail message (I blindly assume it’s an invite attachment), removes the line that prevents iCal from editing the event, and tells iCal to open it. At that point iCal takes over and asks you which calendar to add the event to.

It’s important to note that while the event is now stored in your local iCal calendar, it has not been marked as accepted or declined in your Exchange calendar. You need to specifically take that action using one of the next scripts.

3. Accepting or Declining Exchange Invites in Mail

To accept or decline an event (or even mark it as tentative) I’ve provided three scripts called “Accept Invite”, “Decline Invite”, etc. that pass the event to the OWA PHP script which then marks the event as such in your public calendar. Here’s the “Accept Invite” AppleScript. The other two are basically identical.

tell application “Mail” set theSelectedMessages to selection repeat with theMessage in theSelectedMessages set theSource to content of theMessage set theFileName to “Macintosh HD:tmp:” & (theMessage’s id as string) & “.msg” set theFile to open for access file theFileName with write permission write theSource to theFile starting at eof # close access theFile do shell script “curl http://localhost/owa.php?accept=” & POSIX path of theFileName end repeat end tell

Again, I make no claims about the quality of my AppleScript – I just know that this works well enough to get the job done.

Closing Notes

And there you have it. To sum up:

  1. Download my scripts
  2. Place owa.php into your local web root
  3. Place the four Applescripts into ~/Library/Scripts/Applications/Mail

After that, it’s up to you to call those AppleScripts as needed. I use Red Sweater Software’s Fast Scripts application to assign keyboard shortcuts to them. You could also use Quicksilver or whatever method works best for you.

Like I sad above, these scripts are constantly in flux as I revise and improve them. I’ll post any significant updates to this blog – and I hope you’ll email me with any questions you have or improvements you make.