Deprecated: Return type of I::current() should either be compatible with Iterator::current(): mixed, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /home/public/kirby/toolkit/lib/i.php on line 62

Deprecated: Return type of I::next() should either be compatible with Iterator::next(): void, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /home/public/kirby/toolkit/lib/i.php on line 91

Deprecated: Return type of I::key() should either be compatible with Iterator::key(): mixed, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /home/public/kirby/toolkit/lib/i.php on line 71

Deprecated: Return type of I::valid() should either be compatible with Iterator::valid(): bool, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /home/public/kirby/toolkit/lib/i.php on line 101

Deprecated: Return type of I::rewind() should either be compatible with Iterator::rewind(): void, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /home/public/kirby/toolkit/lib/i.php on line 53

Deprecated: Return type of Collection::count() should either be compatible with Countable::count(): int, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /home/public/kirby/toolkit/lib/collection.php on line 80

Deprecated: parse_str(): Passing null to parameter #1 ($string) of type string is deprecated in /home/public/kirby/toolkit/lib/url.php on line 135
One Tap Less | Exporting Actions to Drafts…from your Mac

Exporting Actions to Drafts…from your Mac


Deprecated: trim(): Passing null to parameter #1 ($string) of type string is deprecated in /home/public/kirby/toolkit/lib/str.php on line 506

Deprecated: trim(): Passing null to parameter #1 ($string) of type string is deprecated in /home/public/kirby/toolkit/lib/str.php on line 506

Deprecated: trim(): Passing null to parameter #1 ($string) of type string is deprecated in /home/public/kirby/toolkit/lib/str.php on line 506

Warning: Trying to access array offset on value of type null in /home/public/kirby/vendors/parsedownextra.php on line 305

Deprecated: substr(): Passing null to parameter #2 ($offset) of type int is deprecated in /home/public/kirby/vendors/parsedownextra.php on line 305

Warning: Trying to access array offset on value of type null in /home/public/kirby/vendors/parsedownextra.php on line 305

Deprecated: substr(): Passing null to parameter #2 ($offset) of type int is deprecated in /home/public/kirby/vendors/parsedownextra.php on line 305

Warning: Trying to access array offset on value of type null in /home/public/kirby/vendors/parsedownextra.php on line 305

Deprecated: substr(): Passing null to parameter #2 ($offset) of type int is deprecated in /home/public/kirby/vendors/parsedownextra.php on line 305

Warning: Trying to access array offset on value of type null in /home/public/kirby/vendors/parsedownextra.php on line 305

Deprecated: substr(): Passing null to parameter #2 ($offset) of type int is deprecated in /home/public/kirby/vendors/parsedownextra.php on line 305

How many countless days I was on the couch, swiping through my Instapaper and Fever and someone posted a great action for Drafts. Then I would unlock my iPhone, use iCloud Tabs or even the feeds to find the article and the exact point where I’d be blessed with the link to import the action to Drafts. Then I’d lock my iPhone and read the rest of the article. So I started studying ways to make this workflow easier for us (there are so many actions) and after many frustrated attempts, I found a way.

Using the Pushover API

Pushover is the key-piece to pull through this workflow and you can also integrate it with IFTTT, which is fantastic for countries lacking SMS or Phone support, such as mine. Pushover sends push notifications to your iOS devices and you can even attach a link into them. After you grab a copy of Pushover, you’ll create an account and receive your User Token, a 30-digits alpha-numeric string, which is the one you put in IFTTT to integrate both services. We gonna use that later.

Now we must create an application, so head to pushover.net, check your dashboard and create a new application/plugin. Choose a short name and pick “Script” for your type. Everything else is up to you. They’ll lend you completely different token, your API Token. If you miss it, you can find a link to your application in your dashboard and your API Token will be there in billboard characters.

With both tokens, we’re ready to move to our next adventure.

Using Keyboard Maestro

This crusade began trying to create a service in Automator to grab the url contained in a selected text and send it to my iOS device through Pushover. Then came the first surprise: Automator is not smart enough to give you URL services when you right-click on a url unless it is explicitly a “http://“ address written down. Therefore, the only way to place the import_action (I often add a direct import link right above the raw script) is right-clicking and using Copy Link, sending our desired content to the clipboard.

After wasting hours trying to find a way to make the impossible, I gave up on Apple tools1 and moved to an app I learned to love: Keyboard Maestro, which is the closest thing on OS X to make magic happen. I won’t tell you what Keyboard Maestro can do, but if you want to earn the ultimate star in the MacGeek course, you just gotta have it.

It begins by creating a new macro, I called it Import to Drafts and assigned a hotkey trigger with ^⎇⇧⌘D, then I picked the first action: Set Variable to Clipboard, I named the variable as action and then I added an If then Else clause, checking if the variable action contains the string drafts://x-callback-url/import_action?, if true, it will execute the following shell script:

#!/bin/sh

curl -s \
    -F "token=INSERT APP TOKEN HERE” \
    -F "user=INSERT USER TOKEN HERE” \
    -F "message=Import" \
    -F "url=$KMVAR_action" \
    -F "url_title=to Drafts" \
    https://api.pushover.net/1/messages.json

Remember the tokens we got after registering our app at Pushover? We gonna include them now. Replace INSERT APP TOKEN HERE for your App Token and INSERT USER TOKEN HERE for your personal token. The outcome will look like this2:

#!/bin/sh

curl -s \
    -F "token=ger7we6hip9mer8ilj5irs9yot0Hu5” \
    -F "user=eTh5noo1swip0cIf6oN7Hyg1weg8It” \
    -F "message=Import" \
    -F "url=$KMVAR_action" \
    -F "url_title=to Drafts" \
    https://api.pushover.net/1/messages.json

Here’s the full Keyboard Maestro macro so you can compare with yours:

Remember that for this action to work, the import_action must be in your clipboard, so you’ll always use Copy Link to grab it. Sorry about that, blame OS X3. But I didn’t stop looking for a method to avoid Copy Link and I suddenly realized that, maybe, PopClip was able to do it.

PopClip

If you don’t know PopClip, it is a little wizard that sneaks every time you select some text to do some hocus-pocus. It is also the app Brett Terpstra would take to a desert island4. I couldn’t recall the last time I actually played with PopClip, as a keyboard guy, I never got used to it, but the time came to create my first extension.

Which failed for a simple reason: PopClip can’t pick a contained url unless it recognizes it as one, which would be great if our urls didn’t all start with drafts://, making them invisible to PopClip. I emailed Nick Moore, the developer, with a few questions after writing down my first extension, he replied in a blink with a regex to solve one of my issues and ANYONE who replies your support email with something like (?xi)(?:\b((?:(?:drafts))(?:[^\s()<>]+|([^\s()]+))+(?:([^\s()]+)|[^\s`!()[]{};:’”.,<>?«»“”‘’]))) is an awesome person5.

I was devastated, PopClip would be perfect for this action, but then I created a workaround. Unable to grab the import action directly, I decided to create one based on the action itself. This meant no regex for me, but I wouldn’t leave PopClip empty-handed6. You can download the PopClip extension here. It works by selecting the url of the action you want to import to Drafts, like drafts://x-callback-url/create?text=Hello, as you trigger the extension, it will run a shell script using the selection url encoded7 and call Pushover. You’ll get your link in your iOS device, however, when you import the action, you’ll notice that you can’t change the name, they’re always called POPCLIPPED since there’s no way to get a user input where you could pick a title.

Back to Keyboard Maestro

The only reason our PopClip extension isn’t perfect is the lack of a prompt for user input, hence he would be able to include a name to the action you’re exporting. Going back to Keyboard Maestro we can manage that.

First I’ll set a new hot key trigger, ^⎇⇧⌘D, and simulate a ⌘C, to copy the selected text. I’ll convert that right away to a variable named action so I don’t rely on the clipboard any further and percent encode the action. Next step is selecting a title for our action. I used a Prompt for User Input action within an Until loop to guarantee the resulting variable won’t be empty. We clone our name variable into title and percent encode the previous. We prepare our scheme using our name and action encoded variables to build the import action to Drafts. Next, we run our shell script using our title variable to give you a warming welcome message in your Pushover notification. Remember to set your user and api tokens in the shell script otherwise this action will fail. Get your iPhone and click the link on the notification to install the action on Drafts.


  1. Someone will probably show up with an Automator workflow triggered by a hotkey. Thanks in advance. 

  2. Those are not real Pushover tokens, I used 1Password to generate a random string with a similar recipe. 

  3. If Mavericks comes with a method to properly copy links, I’ll be really angry. 

  4. Probably. 

  5. Thank you, Nick! 

  6. You probably already noticed how stubborn am I. 

  7. PopClip does that using $POPCLIP_URLENCODED_TEXT