Tags

, , , , ,

This is the fifth article in a series of unknown length discussing using a tool written in Lua to publishing posts on a WordPress blog.

  • Part 1 showed how to use XML-RPC and wp.newPost
  • Part 2 added file reading to make a minimal working utility.
  • Part 3 added amenities and made the utility useful.
  • We digressed to talk about OAuth and using it at WordPress.com.
  • Part 4 switched to cURL, REST, and OAuth, but can’t yet post.

Soon we will restore the ability to make a post, and add the ability to include categories and tags with the new post.

But first, some cleanup

(The changes described in this section are checked in at 870da6391b.)

Authorization of the app is still clumsy, and requires a manual copy and paste. We won’t be fixing that yet, but we can at least make it easier to handle.

As described in all its gory detail earlier, you need to authorize the application to have access to your blog by visiting this authorization link or its equivalent if you have registered for your own WP application. When you finish filling out the form to grant access, you will be redirected to the app’s registered redirect URL. At present, that is a page at this blog but that could change if we streamline the authorization process in the future.

When you arrive on the redirection page, click in your browser’s URL field and copy the entire URL to the clipboard.

Then at a command prompt open with our REST version of wppost.lua available, enter the command (on one line):

wppost.lua --tokenurl "PASTE_IN_THE_WHOLE_TOKEN_HERE" --blog "yourblog.wordpress.com" --writeconfig

and be very sure to include the quotation marks around the pasted URL. That will update the privately stored file rest.ini (found at C:\Users\Ross\.wppost\rest.ini on my Windows 7 box, and likely in a similar place on your Windows box) to contain a copy of the OAuth 2.0 access token and its expiration date. If you aren’t granting access to curiouser.cheshireeng.com (which you really shouldn’t be able to do if you aren’t me anyway) you will need to remember to include the --blog option with the full domain name of your blog as known to WordPress and/or JetPack.

Of course, you can still peek at the saved configuration with the --showconfig option.

Here is the code that implements the --tokenurl parsing:

-- Parse the useful data out of a token redirect URL
-- Keep the token, confirm the other details.
--
-- http://<BaseURL>/#access_token=<URL-Encoded-Token>&expires_in=<seconds>&token_type=bearer&site_id=73256621
--
if args.tokenurl and #args.tokenurl >= 64 then
    local base,rest = args.tokenurl:match"^([^#]+)%#(.+)$"
    if not rest then
        lapp.error("Please provide the entire URL and be sure to quote it.")
    else
        local t={}
        for k,v in rest:gmatch"([^&=]+)=([^&=]+)" do
            t[k] = v
        end
        args.token = t.access_token
        args.expires = tostring(os.time() + (tonumber(t.expires_in) or 0))
    end
end

This first splits the provided URL into the base (everything before the # character) and the rest. We ignore the base, but in principle it could be tested to verify that the URL you pasted came from the expected redirection.

The rest of the URL is matched for all sequences that smell like name=value where neither the name nor the value can contain = or &amp; characters. Since this text was copied directly from an URL, it can be assumed to be URL encoded and making sure that no part of the URL misuses #, ?, &amp; and = characters is the whole point of URL encoding. For this code, we completely ignore the URL encoding. As discussed in part 4 it is useful to leave the token encoded, and we don’t expect any of the other fields that describe the token to actually need to be encoded. That assumption lets us use a for loop over string.gmatch() to collect all k,v pairs and add them to the temporary table t. When the loop completes, we explicitly pick out the access_token and expires_in fields and copy them to the args table where they can get written to the configuration file.

One thing to notice is that WordPress provides the expiration as the number of seconds the token has to live. We simply add the current value of os.time() to that and save the result. That is valid assuming that you request the token and then run wppost.lua --tokenurl without undue delays. Since the only thing we do with the expiration time is display it rounded to a tenth of a day, we won’t be lying to you later unless you waited more than half that time or about 72 minutes from request to --tokenurl.

Once that is done (don’t forget to include --blog and --writeconfig) the access token will be remembered until you replace it, but according to WordPress it will stop working after the expiration date they specified.

As a reminder of the token’s expiration date we can compute its time to live in days and print it:

args.expires = tonumber(args.expires)
if args.expires then
    local ttl = (args.expires - os.time()) / (24. * 3600.)
    if ttl < 0 then
        print(("WP Access Token expired %.1f days ago"):format(-ttl))
    else
        print(("WP Access Token expires in %.1f days"):format(ttl))
    end
end

As expected, the token I just retrieved is marked to expire in 14 days.

Say my name

(The changes described in this section are also checked in at 870da6391b.)

The REST endpoint /me provides useful information about the owner of the access token. This is similar to the collection of information that is shown in a balloon when you hover over a user name anywhere in the blog in a browser, along with the name and Gravatar shown on blog pages.

The previous script from part 4 simply dumped the raw JSON data blob returned from the /me endpoint. We can improve on that by parsing the JSON and printing only the most useful information.

The first thing we’ll need is a JSON parser for Lua. Luckily, LuaJSON is included in the Lua for Windows distribution that these posts all have assumed we are using so far. (That link wen’t to its documentation which you might find useful…)

For this case, using it to extract a few facts from the returned JSON is easy:

    local json = require "json"
    local me = wp_showme()
    local t = json.decode(me)
    if args.debug then
        local pretty = require "pl.pretty"
        io.write("/me = ", pretty.write(t), 'n')
    end
    print("Token user:", t.display_name or t.username)
    if t.email_verified then
        print("      email:", t.email or "unknown")
    end

The JSON decoder transformed the provided JSON string into a Lua value. JSON objects become tables with named fields. Arrays become tables with numeric indices starting at 1 as is conventional in Lua. Strings, numbers, and booleans translate naturally to their simple Lua equivalents. It has a lot of options, but we are assuming in this code that the default configuration of the decoder is sensible.

If you want to see the complete block of information returned from /me and decoded to a Lua table, use the --debug option which here uses the nifty table display provided by Penlight’s pl.pretty module.

As a friendly subset of the large amount known about the user, I’ve chosen to print either the display name or user name, and include the email address if the JSON indicates that the email has been verified by WordPress.com.

I’ve left using cURL to retrieve the user’s Gravatar and then displaying it as ASCII art in the terminal as an exercise to the reader. If you do do that, be sure to brag about it!

And soon…

With these changes in place and a valid token cached in the config file we get (why yes, I did redact some irrelevant details):

C:...wprest>wppost.lua -v
WP Access Token expires in 13.9 days
Token user:     rberteig
      email:    rberteig@example.com
wppost:Must name a file to post.

Which does look friendly, but continues to remind us that we haven’t actually implemented the ability to create a post from the REST API yet.

We really will be able to post again soon!


Written with StackEdit.