TwineTubular – Twine macro for a YouTube background video

I’ve been quietly playing about with Twine recently. While working on something completely unrelated, I happened across this jQuery plugin called Tubular. I immediately thought it would be a cool thing to use in Twine games, after seeing how Porpentine has pulled off spectacular usage of YouTube-sourced audio in her games.

So I spent what turned out to be an entire sleepless night hacking jQuery and a jQuery plugin into the form of a Twine macro.

I have only tested this on the default Sugarcane template in Firefox 21 and Chrome 27. I can’t really provide any support, as I have no time to do so.

Here it is. Hope you’ll all get some use out of it.

Here’s a demo.

Update 2013-05-27: You can now use multiple videos in a single game (this didn’t work before as the plugin wasn’t cleaning up properly upon termination). You can now also use the audio from the YouTube video when you specify another argument.

After Posterous

Now that Posterous is leaving the building, I have moved this space to WordPress.com and a new domain name, jonathanprior.com. I’ve done this so I don’t need to fiddle around with updating a WordPress install which I’ll likely leave fallow for months to years on end.

And no, I still don’t really have time to blog. Every once in a while, though, I’ll churn out something. But my current attitude towards blogging hasn’t really changed.

PayPal, You Suck, Your API Sucks, And So Does Your Documentation

For the past two weeks I have been grappling with creating a PayPal integration for Gameolith. PayPal’s documentation (located at x.com) is frequently outdated, inaccurate, incomplete and even contradicts itself many a time. Their sandbox is buggy and broken, and went down shortly before I was about to launch, forcing me to delay its launch for more than a week.

This post documents my many trials and tribulations of dealing with their API, sandbox and documentation, in no particular order.

The documentation is disorganised and confusing

To make sense of the PayPal Express Checkout API, I downloaded 4 separate PDF files. I also referred to 3 pages off this API reference to do with Express Checkout operations. 

When it came to implementing IPN (Instant Payment Notification, basically a webhook) I had a hard time finding any information on the different payment statuses of an order on the PayPal X website. After looking it up on Google, I found it in a completely different part of the website.

I can’t set an NOTIFYURL (for IPN) in a SetExpressCheckout call

This makes IPN essentially useless in Express Checkout. Instead, I have to define a RETURNURL and set up a separate page (accessed by the user) to process the transaction and redirect the user as appropriate. I would rather do this in an IPN call.

GetExpressCheckoutDetails returns an undocumented value, CHECKOUTSTATUS

The GetExpressCheckoutDetails call returns a CHECKOUTSTATUS value rather than a PAYMENTSTATUS value, which is what I had come to expect after reading the NVP API reference. This post on the X.com forum reveals that CHECKOUTSTATUS is not a documented value, provides some information on it, and mentions that they’d “submitted a Doc update for this to be included in the guide”.

Last year.

What is CALLBACK for?

The NVP API reference defines CALLBACK as follows:

CALLBACK

(Optional) URLto which the callback request from PayPal is sent. It must startwith HTTPS for production integration. It can start with HTTPS orHTTP for sandbox testing.

Character length and limitations:1024 characters

But what on earth is the callback for? I assumed it sent back payment details to a URL of my choosing. But when I actually came to try and use it, I got an error which implied it was actually for postage calculations.

PayPal’s laughable lack of customer service

The day I was due to launch, which was July 14th 2011, I changed the PayPal credentials to the ones we would be using in production.

They didn’t work.

It failed because PayPal Express Checkout for Digital Goods hadn’t been activated on the account yet. Except I had rang them several days earlier to do just that, and they assured me it had been done. It hadn’t.

Cue a day full of phone calls, ringing PayPal to try and resolve it. I rang Customer Service (who I had contacted the other day), and they directed me to another number, which turned out to be telesales. Telesales directed me to Merchant Technical Support. Merchant Technical Support sent me right back to Telesales again. I filled out a form on the PayPal website, ostensibly about signing up for Digital Goods, and got an e-mail back welcoming me to PayPal, as if I didn’t have an account already. I replied to the e-mail asking them to activate my account, and got another phone call with a lady telling me I needed help with my integration, which I didn’t, BECAUSE IT WAS OTHERWISE WORKING PERFECTLY.

So the woman told me I would receive a phone call the next morning from the Integration team. I put out messages on Twitter, Facebook, and e-mailed all my partners to let them know I had to delay the launch yet again. And I must say that the response was outstanding.

Django: How to use the permission_required decorator with the method_decorator in a class-based view

Since the documentation on the method_decorator in Django is quite confusing, and Google didn’t turn up any useful results for me, I had to resort to trial and error to work out how to use the permission_required decorator in class-based views.

If the decorator doesn’t accept the view as an argument, you can just call it as a method. You just need to wrap the dispatch() method as normal.

@method_decorator(permission_required(‘products.change_game’))
def dispatch(self, *args, **kwargs):
        return super(MyView, self).dispatch(*args, **kwargs)

That’s it.

On Keeping Your Users

Zed Shaw brought up a good point about yesterday’s post on user-friendly registration, the fact that through handing off authentication to a third party, you would be handing off control of your users.

However, you can take precautions which will keep some semblance of control over your users and their login flows. You need a ‘I Cannot Login’ link. It’s like a ‘Forgot Password’ link, but the process would involve removing external authentication and replacing it with the traditional password (if it isn’t used already). This is because it’s pretty much impossible to remotely diagnose a faulty external auth provider.

Then you should build this functionality into your backend, but allow for batches of users to have their external auth details revoked. The next time they attempt to login, they will be prompted to add a new password (after checking their e-mail for a verification link, of course). This means you can quickly deal with users who are authenticating against a provider who has (for example) blocked your service.

Of course, the other problem with implicitly trusting external auth at all is that if the auth server gets hacked and starts logging sessions, it could steal your users accounts. The only real way around this is to have a whitelist of providers. Again, this begets some trust. You can also allow users to link a different provider to their account, but you should be careful not to make this too confusing.

In the end, all the users who don’t have external auth available will be asked for a password. That is inherently problematic if you don’t want to store passwords. Zed Shaw’s Autho.me is a step in the right direction, although not ready for general use. But using bcrypt and SSL is the current best practice until we can come up with the best replacement.

Once more, it boils down to the trust problem. It’s really up to you whether you mind handing over some control of your registration/login flow to a third party. It’s not the best solution to the age-old problem of easy login, but I think it’s the best we have right now. In terms of sheer convenience — not having to create new passwords for everything for the user, not needing to store passwords for all users for the developer — it’s a no-brainer. But from a security point of view, you should take reasonable precautions, and when things go wrong you can deal with them quickly and effectively.

How User Registration Should Work

I've been doing rather too much research into different authentication systems. They all suck.

  1. You have the basic username and password, which is nice and simple until you have a lot of websites clamouring for unique passwords. This means you will probably either use the same password everywhere, which is generally a bad idea if one of those sites gets their password database hacked, or a password manager, which suffers from the same problem.
  2. You have OpenID. A nice idea in concept, but again there are problems. The early implementations ask for users to insert an 'OpenID URL'. From an end user's point of view, why the hell would you want to type in, copy or paste some website address to log in? It simply makes no logical sense. Since its adoption by the likes of Google though, the only thing going for it is that much of this can be hidden behind shiny provider buttons. But the choices are often overwhelming, when there are 6-8 possible providers on screen at once and you have accounts with all of them.
  3. You have OAuth, which has the worst API known to man. Every time I look at documentation on OAuth I want to run away screaming. Nice idea in theory, but in practice it's painful. There are libraries, but I'm one of those programmers that likes to understand what the hell the library's supposed to do before I use it. And there is nothing simple about OAuth. At all.
  4. And WebFinger, which nobody uses. It was enough of a fight trying to get anyone to adopt OpenID, so I really don't have much hope for this protocol.
But WebFinger takes a design concept which has a lot of potential. Using the e-mail address as the identifier. And in fact, it is possible to implement this design concept with a mishmash of all the above protocols.

From a user's point of view, all that would happen is that they enter their e-mail address, and if their provider uses any one of the systems above for authentication, then it redirects to them to login, and no password ever needs to be stored. If no external authentication is used, the point where you ask for a password would be when the verification e-mail comes in.

This in theory would near-seamlessly integrate OpenID with the traditional registration flow.

Note: I believe Google have created an example implementation of this concept, but I can't find it right now. I will update this post if I do.