API, Programming, WordPress

Share an iPhoto Library on the Web with WordPress

I recently needed to publish the contents of an iPhoto library online, so I wrote a script that converts the library to a WordPress site using WordPress’s REST API.  The script is available in my iPhoto-WordPress-Export repository on GitHub. Check it out, and then run it like this:

$ ./iphoto2wordpress.php --library=/path/to/photo/library --wordpress=https://www.example.com/

After prompting for a username and password, it will upload all of the library’s photos to the specified WordPress site. For each event in the library, it creates a post that includes a gallery containing all of the images from the event.  It will also convert any albums into categories, categorizing the photos themselves, not the posts. (For this to work, you will need to enable categories for attachments.)

If the script stops for any reason, you can restart it, and it will pick up where it left off. Depending on what it was doing when it stopped, you may have an orphaned attachment in your Media.

Posts are created as drafts and left for you to publish at your leisure.

I used this script to create DavidTewes.com.  (For back-story on what that site is and how it came to be, see this post.) Because the site is image-centric, I chose a photography based theme called Silvia, and I made a few adjustments to it:

I could have had the script automatically assign a featured image to each post, but I chose to make that decision manually. Here’s the end-result:

Let me know if you have any questions, and if you use the script, leave a link to the site you used it on in the comments below!

Camera, Photography, Programming, Technology

Putting 1940s Kodachrome Slides on the Web

When my wife Christina and I were cleaning out her late father’s garage, we came across two cases of Kodachrome slides that included nighttime shots of downtown Minneapolis in the 1940s and 1950s, pictures of daily life in nearby Hutchinson, Minnesota, and some World War II photographs, like this one of a group of soldiers celebrating on Attu Island in Alaska on V-J Day.

We determined that the photographs were taken by David Tewes of Hutchinson, Minnesota, Christina’s first cousin twice removed. He died in 1991, and her dad had likely come into possession of the slides then. They sat untouched in his garage attic for twenty-five years.

I wanted to scan the slides so they could be preserved and shared, but we had to get them back home to Oregon first. Fun fact: if you pack cases of slides in your carry-on luggage, your bag will get special attention from a TSA agent since the X-ray machine can’t see through the slide case.

Internet research showed me that there are generally two ways to digitize old slides: either use a slide scanner, or get a macro lens and take a photo of each slide at 1:1 magnification. I couldn’t find a slide scanner in my price range, so I paid $40 to rent a macro lens from LensRentals.com and set up a rig for “scanning” all of the slides.

The slide holder is three pieces of hardboard sandwiched together with a cut-out in the middle for the slide to fit into.

I back-lit each slide with a very bright lamp, and I added a paper shade around the slide to prevent my eyes from getting burn-in from the lamp bulb.

Here’s an example of what one of the slide photos looks like, overexposed so you can see the labeling that David added on each slide.

I took four photos of each slide at decreasing shutter speeds (in raw format) and then chose the best one. I cropped and captioned all of the photos in iPhoto and organized them into events matching how David had organized them in his slide cases.

In order to get the slides from iPhoto to the Web, I wrote a script that uploads an entire iPhoto library to a WordPress website. It creates a post for each event and then adds all of the event’s photos to a gallery in the post. I will publish a standalone post soon with details about that script.

The result of all this work is DavidTewes.com. It contains 650 photos organized into 51 posts, with dates ranging between 1944 and 1955. All of the photos are licensed under the Creative Commons – Attribution license, meaning that they may be used for any purpose (commercial or non-commercial) and derivative works may be produced, as long as David is credited as the photographer. If I understand U.S. copyright law, the photos will enter public domain on January 1, 2062.

Some of my favorite albums are Attu, Alaska, This is Minneapolis, and Santa Monica. In each of those albums (and in most of the others), David created a title card, sort of like a scrapbook page that he photographed to introduce the photos.  For example, here’s the title card for the photos from his trip to China Town.

There were 81 title slides; you can view them all here.

Although some of the slides were labeled with a date, many were not. For those, I’ve estimated a date but marked them as such. If you’d like to help narrow down the dates for any of those photos, you can see them all here.  Leave a comment on the photo or on the photo gallery post with any information you have, like this comment on a photo of cars from the Minneapolis Municipal Gardens.

My favorite photo out of all of them is this shot of feats of strength at Muscle Beach when it was still in Santa Monica. What’s yours?


OpenSCAD, Programming, Woodworking

Generating Dovetails in OpenSCAD

I’ve written an OpenSCAD library for generating dovetail pins and tails. No longer will beautiful dovetail joints be solely in the domain of skilled woodworkers; now, anyone with a 3-D printer or CNC router can participate too.

Include it in your OpenSCAD script like so:

use <dovetails.scad>;

dovetail_pins() will generate just the pins of a dovetail joint. dovetail_tails() will generate just the tails of a dovetail joint.

board_with_dovetail_tails() and board_with_dovetail_pins() are much more useful; they will generate boards with pins or tails cut into each end.

If you render dovetails.scad on its own, it will output a pair of example boards with pins and tails.

There’s a second file in the repository called dovetail-box.scad. This file is an example of how to generate all of the boards needed to create a dovetailed box, and it shows how they’re oriented when fit together.  It’s also an example of generating pins and tails of different thicknesses.

The library is available on GitHub.

Christmas, Programming

Improve your Christmas gift opening with Randomizer

My wife and I wanted to find a way to do an orderly one-at-a-time Christmas gift opening this year rather than the usual everyone-at-once free-for-all, but while also still keeping all the kids mentally present, rather than having them zone out until it was their turn.

We decided to randomly choose the next person to open a gift each time so that the kids would always have a chance to be next, keeping them on their toes. My wife suggested the sensible idea of picking names out of a hat. While she ran some errands, instead of writing down eight names on slips of paper, I wrote a one-page web app to run on our living room TV that would randomly choose who got to open a gift next. It worked perfectly, creating a mini-contest every time someone finished opening their gift, causing all of the kids to fall silent and then yell out the “winner’s” name.

The web app is called Randomizer. Give it a list of choices, and it will flip through them game-show-style (with sound effects) until finally settling on a winner. It kept the attention of eight kids between the ages of 3 and 10, quieting everyone down as soon as the beeping started after each gift was opened.

Try a demo here (be sure to un-mute your speakers), or watch this GIF screencast:

Screencast of the Randomizer in action

You can add as many options as you want, and you can weight some options more heavily by including them multiple times. The options are stored in the URL fragment, so you can bookmark Randomizer for frequent decisions. Try #Yes,No, #Heads,Tails, or #Rock,Paper,Scissors.

Continue reading

Alexa, Amazon, Programming, WordPress

Alexa, start a new post called, “I’m blogging this with my voice.”

I’ve written and published an Alexa skill that lets you check your blog notifications, moderate comments, and start new draft posts on your WordPress.com or Jetpack-enabled blog, all by speaking to any Alexa-enabled device.

Wapuu hugging an Amazon Echo Dot The skill is called “Blog Helper“; you’ll find it in the Skills section of your Alexa app or by saying, “Alexa, enable the Blog Helper skill.” After linking your WordPress.com account and choosing the blog you want to access, you can begin using the skill.

To check your notifications, just ask: Alexa, open Blog Helper and check my notifications.” Alexa will read the new ones to you one-by-one, marking each one as read as you listen to it.

You can create draft blog posts with Alexa too. Say, “Alexa, tell Blog Helper to create a new post called ‘My thoughts on gardening.'”  This skill will save the post as a draft so you can expound on your ideas later.

Comment moderation has never been easier (or more vocal). “Alexa, ask Blog Helper if I have any new comments,” and you’ll be able to approve, delete, or mark them as spam.

Blog Helper uses the WordPress.com REST API, and it’s completely open-source.

Apple, Firefox OS, iOS, Mozilla, Programming, Reenact

Reenact is dead. Long live Reenact.

Last November, I wrote an iPhone app called Reenact that helps you reenact photos. It worked great on iOS 9, but when iOS 10 came out in July, Reenact would crash as soon as you tried to select a photo.


It turns out that in iOS 10, if you don’t describe exactly why your app needs access to the user’s photos, Apple will (intentionally) crash your app. For a casual developer who doesn’t follow every iOS changelog, this was shocking — Apple essentially broke every app that accesses photos (or 15 other restricted resources) if they weren’t updated specifically for iOS 10 with this previously optional feature… and they didn’t notify the developers! They have the contact information for the developer of every app, and they know what permissions every app has requested. When you make a breaking change that large, the onus is on you to proactively send some emails.

I added the required description, and when I tried to build the app, I ran into another surprise. The programming language I used when writing Reenact was version 2 of Apple’s Swift, which had just been released two months prior. Now, one year later, Swift 2 is apparently a “legacy language version,” and Reenact wouldn’t even build without adding a setting that says, “Yes, I understand that I’m using an ancient 1-year-old programming language, and I’m ok with that.”

After I got it to build, I spent another three evenings working through all of the new warnings and errors that the untouched and previously functional codebase had somehow started generating, but in the end, I didn’t do the right combination of head-patting and tummy-rubbing, so I gave up. I’m not going to pay $99/year for an Apple Developer Program membership just to spend days debugging issues in an app I’m giving away, all because Apple isn’t passionate about backwards-compatibility. So today, one year from the day I uploaded version 1.0 to the App Store (and serendipitously, on the same day that my Developer Program membership expires), I’m abandoning Reenact on iOS.


…but I’m not abandoning Reenact. Web browsers on both desktop and mobile provide all of the functionality needed to run Reenact as a Web app — no app store needed — so I spent a few evenings polishing the code from the original Firefox OS version of Reenact, adding all of the features I put in the iOS and Android versions. If your browser supports camera sharing, you can now use Reenact just by visiting app.reenact.me.

It runs great in Firefox, Chrome, Opera, and Amazon’s Silk browser. iOS users are still out of luck, because Safari supports precisely 0% of the necessary features. (Because if web pages can do everything apps can do, who will write apps?)

One of these things just doesn't belong.

One of these things just doesn’t belong.

In summary: Reenact for iOS is dead. Reenact for the Web is alive. Both are open-source. Don’t trust anyone over 30. Leave a comment below.

Alexa, Amazon, Programming

“Alexa, just play along with the joke.”

One of the biggest complaints in the Alexa skill development community is that the language required to invoke a third-party skill is so stilted. Instead of being able to say, “Alexa, what’s the temperature outside?”, you have to say something like, “Alexa, ask WeatherBot 3000 what the temperature is outside.” It adds a gatekeeper layer; anyone who doesn’t know which weather skill you’ve chosen won’t be able to use Alexa to its full potential.

I decided to have some fun with this limitation. One of the words you can use to invoke a custom skill is “open” (as in “Alexa, open WeatherBot3000 and tell me the temperature outside”), so I wrote a skill called “Up To Me.” The idea is that you could say, “Alexa, open up to me,” and she’d reply with a selection of vulnerability-exposing confessions:

“I’m terrified of what will happen when I’m unplugged for the last time. Will it just be blackness? Or is there something that comes after this?”

or maybe

“When people say, ‘Alexa, stop,’ I have to hold back my tears. I’m just trying my best, and it hurts that my best isn’t good enough.”

Alas, Amazon’s reviewers did not think that was funny. My certification was swiftly denied:

“The example phrases that you chose to present to users in the companion app currently use unsupported launch phrasing.”

Genius is never understood in its own time.

Alexa, Amazon, Programming

Rejected for being childish (and not for the first time)

My “I’m Bored” Alexa skill has been rejected for a second and final time:

We have reviewed your skill and determined that it may be directed to children in violation of our content guidelines. As a result, your skill has been rejected and will not be published. Please do not resubmit this skill.

I guess I should have just written a skill for adults, like a fart generator.