It seems that anyone involved in helping musicians with their web presence has to learn to tolerate MySpace. I don’t think I know anyone who actually enjoys the process of using MySpace, but a strong presence there is a must have for almost every musician these days.
I’ve long wished for a decent API that would help me integrate MySpace with websites I run for musicians—after all, it isn’t very DRY to post the same content in several places when it could be automated—but as time has gone on it’s become clear that an API would be entirely anathema to MySpace’s approach to the web.
So while working on some updates to a friend’s website I decided to try out the Ruby port of WWW::Mechanize to automate the process of posting blog entries over at MySpace.
Firstly, we need to be able to log in. To do that, you can almost copy some of the library’s examples as it’s as simple as:
agent = WWW::Mechanize.new
agent.user_agent_alias = 'Mac Safari'
page = agent.get('http://www.myspace.com')
login_form = page.forms.with.name('theForm').first
login_form.email = username
login_form.password = password
logged_in = agent.submit(login_form)
Posting a blog entry is a little trickier, as MySpace uses javascript to change forms’ ‘action’ attributes based on which button you click, and occasionally inserts tokens in the URLs, but after a little exploration I came up with:
blog_page = agent.get('http://blog.myspace.com/index.cfm?fuseaction=blog.create&editor=false')
blog_form = blog_page.forms.with.name('theForm').first
# Here we have to grab the action as it includes a token which can change
new_action = blog_page.body.match(/document.theForm.action = '(.+?)'/)
blog_form.action = new_action[1]
blog_form.subject = subject
blog_form.BlogCategoryID = category
blog_form.body = body
now = DateTime.now
blog_form.postMonth = now.month
blog_form.postDay = now.mday
blog_form.postYear = now.year
blog_form.postHour = now.strftime('%I')
blog_form.postMinute = now.min
blog_form.postTimeMarker = now.strftime('%p')
submitted = agent.submit(blog_form)
confirm_form = submitted.forms.with.name('theForm').first
confirm_form.action = 'http://blog.myspace.com/index.cfm?fuseaction=blog.processCreate'
posted = agent.submit(confirm_form)
And that’s all there is to it. I’m impressed with how easy WWW::Mechanize makes interacting with forms, and generally how pleasant it is to work with. Performance is pretty good too, specially given how problem prone MySpace is. It’s nice to be able to imagine a scenario in which clients can cross-post their content to MySpace. If we’re lucky, we never need actually visit that website again!
I’m working on packaging up the code, probably with support for posting event dates and ‘bulletins’, and adding in error handling to deal with the 75% of the time (based on my usage this afternoon) when MySpace returns an error page. It may be a few days, but I’ll post a note here when it’s ready.