Push it Real Good (but with less stuff)

A code post! How novel!

Yesterday I was catching up on my blog reading and I ran across Casey Liss’ Shell → Watch Notifications. I love the idea – but it’s a bit of a kludge to put together as-is.

You’ve got a shell script, running a php script and then curl, to a local Node server, which then proxies a call out to the Pushover API. Casey’s using the tools he knows (the hard part is really all in the javascript) and what he’s got works great.

I just don’t want to run a server locally to ping another server – let’s just consolidate all this. At the same time, a lot of folks don’t realize that PHP can be used directly as a shell script. And, since PHP has a kitchen-sink mentality, you can use cURL directly from PHP. So let’s put it all together with the help of the best HTTP / API testing app ever, Paw!

Here’s how I set up the initial request in Paw:

Paw Pushover Setup

And here’s the code that Paw generated for PHP:

<?php

// Get cURL resource
$ch = curl_init();

// Set url
curl_setopt($ch, CURLOPT_URL, 'https://api.pushover.net/1/messages.json');

// Set method
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');

// Set options
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

// Set headers
curl_setopt($ch, CURLOPT_HTTPHEADER, [
  "Content-Type: application/x-www-form-urlencoded; charset=utf-8",
 ]
);
// Create body
$body = [
  "message" => "This is a test message",
  "title" => "Done",
  "token" => "your-app-token",
  "user" => "your-user-token",
  ];
$body = http_build_query($body);

// Set body
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $body);

// Send the request & save response to $resp
$resp = curl_exec($ch);

if(!$resp) {
  die('Error: "' . curl_error($ch) . '" - Code: ' . curl_errno($ch));
} else {
  echo "Response HTTP Status Code : " . curl_getinfo($ch, CURLINFO_HTTP_CODE);
  echo "\nResponse HTTP Body : " . $resp;
}

// Close request to clear up some resources
curl_close($ch);

Awesome. Now we’ve got a PHP script that can send a hard-coded message – assuming, of course, that you replace your-app-token and your-user-token with your relevant Pushover account details. Let’s adapt this into something we can run from the shell and pass arguments into.

First up, I’m going to paste the above into a file called finished. For me, I put it in my ~/bin directory, because I’ve got that added to my $PATH – meaning I’ll be able to run this script from anywhere. While I’m there, I’ll do a quick chmod +x on it in the shell, so it becomes executable.

At the top of my new finished script, I’ll put the magic incantation that helps your shell know this is PHP:

#!/usr/bin/env php
<?php

That hash-bang line tells the shell to fire up the PHP interpreter. After that, the remaining PHP file gets executed automatically. Although, PHP being PHP, you still need the <?php in order for the interpreter to, well, interpret. Otherwise it will just spit out your code back to you as plain text. Try it, it’s hilarious.

Now you’ll be able to run finished on the command line and get your hard-coded message. Let’s take the arguments from the command line to turn that into the message. In a PHP shell script, $argv will be automatically available as an array of all the arguments passed into the script – including, up front, the full path to the script itself. Here’s how we turn that into the $message string at the top of the file:

$script_path = array_shift($argv); // This pops the script path off the front of the $argv array
$message = implode(' ', $argv); // Concatenates the array together with spaces

And then I modify the $body array that Paw gave us:

...
$body = [
  "message" => $message,
...

And that’s it! Now you can run:

> some --long-running=task; finished The long running task finished

Side note: I don’t call the script done because unlike Casey, I use bash, and in bash done is a control keyword – so bash just won’t run any script called done unless I always give it the full path. Meh.

This entry was posted in Code. Bookmark the permalink.