2009-12-18 11:50

The smartest thing I ever wrote

When I was migrating the comments I noticed a page looked wrong in the site, and started fixing it.

While I was reading, I noticed a couple of things:

  • It was published almost exactly 5 years ago
  • It may be the smartest thing I ever wrote

Sometimes, you get an idea, and you can give it shape. Since I really think it's not completely stupid, I translated it to spnish (there was only an english version) y "reprint" it today.

It's about programming, it's about evolution, and I hope you like Being a good Lamarckian froggie!.

2009-12-18 00:37

Migrating from Haloscan to Disqus (if you can comment on it, it worked ;-)

Introduction

If you are a Haloscan user, and are starting to wonder what can you do... this page will explain you a way to take your comments to Disqus, another free comment service.

A few days ago, Haloscan announced they were stopping their free comment service for blogs. Guess what service has in it the comments of the last 9 years of this blog? Yes, Haloscan.

They offered a simple migration to their Echo platform, which you have to pay for. While Echo looks like a perfectly nice comment platform, I am not going to spend any money on this blog if I can help it, since it already eats a lot of my time.

Luckily, the guys at Haloscan allow exporting the comments (that used to be only for their premium accounts), so thanks Haloscan, it has been nice!

So, I started researching where I could run to. There seems to be two large free comment systems:

Keep in mind that my main interest lays in not losing almost ten years of comments, not on how great the service is. That being said, they both seem to offer roughly the same features.

Let's consider how you can import comments to each service:

  • Disqus: It can import from blogger and some other hosted blog service. Not from Haloscan.
  • Intense Debate: Can import from some hosted services, and from some files. Not from the file Haloscan gave me.

So, what is a guy to do? Write a python program, of course! Here's where Disqus won: they have a public API for posting comments.

So, all I have to do then is:

  1. Grok the Disqus API
  2. Grok the Haloscan comments file (it's XML)
  3. Create the necessary threads and whatever in Disqus
  4. Post the comments from Haloscan to Disqus
  5. Hack the blog so the links to Haloscan now work for Disqus

Piece of cake. It only took me half a day, which at my current rates is what 3 years of Echo would have costed me, but where's the fun in paying?

So, let's go step by step.

1. Grok the Disqus API

Luckily, there is a reasonable Disqus Python Client library and docs for the API so, this was not hard.

Just get the library and install it:

hg clone https://[email protected]/IanLewis/disqus-python-client/
cd disqus-python-client
python setup.py install

The API usage we need is really simple, so study the API docs for 15 minutes if you want. I got almost all the tips I needed from this pybloxsom import script

Basically:

  1. Get your API Key
  2. You login
  3. You get the right "forum" (you can use a disqus account for more than one blog)
  4. Post to the right thread

2. Grok the Haloscan comments file

Not only is it XML, it's pretty simple XML!

Here's a taste:

<?xml version="1.0" encoding="iso-8859-1" ?>
<comments>
    <thread id="BB546">
      <comment>
        <datetime>2007-04-07T10:21:54-05:00</datetime>
        <name>superstoned</name>
        <email>[email protected]</email>
        <uri></uri>
        <ip>86.92.111.236</ip>
        <text><![CDATA[that is one hell of a cool website ;-)]]></text>
      </comment>
      <comment>
        <datetime>2007-04-07T16:14:53-05:00</datetime>
        <name>Remi Villatel</name>
        <email>[email protected]</email>
        <uri></uri>
        <ip>77.216.206.65</ip>
        <text><![CDATA[Thank you for these rare minutes of sweetness in this rough world...]]></text>
      </comment>
    </thread>
</comments>

So, a comments tag that contains one or more thread tags, which contain one or more comment tags. Piece of cake to traverse using ElementTree!

There is an obvious match between comments and threads in Haloscan and Disqus. Good.

3. Create the necessary threads and whatever in Disqus

This is the tricky part, really, because it requires some things from your blog.

  • You must have a permalink for each post
  • Each permalink should be a separate page. You can't have permalinks with # in the URL
  • You need to know what haloscan id you used for each post's comments, and what the permalink for each post is.

For example, suppose you have a post at //ralsina.me/weblog/posts/ADV0.html and it has a Haloscan comments link like this:

<a href="javascript:HaloScan('ADV0');" target="_self"> <script type="text/javascript">postCount('ADV0');</script></a>

You know where else that 'ADV0' appears? In Haloscan's XML file, of course! It's the "id" attribute of a thread.

Also, the title of this post is "Advogato post for 2000-01-17 17:19:57" (hey, it's my blog ;-)

Got that?

Then we want to create a thread in Disqus with that exact same data:

  • URL
  • Thread ID
  • Title

The bad news is... you need to gather this information for your entire blog and store it somewhere. If you are lucky, you may be able to get it from a database, as I did. If not... well, it's going to be a lot of work :-(

For the purpose of this explanation, I will assume you got that data nicely in a dictionary indexed by thread id:

{
  id1: (url, title),
  id2: (url, title)
}

4. Post the comments from Haloscan to Disqus

Here's the code. It's not really tested, because I had to do several attempts and fixes, but it should be close to ok (download).

#!/usr/bin/python
# -*- coding: utf-8 -*-

# Read all comments from a CAIF file, the XML haloscan exports

from disqus import DisqusService
from xml.etree import ElementTree
from datetime import datetime
import time


# Obviously these should be YOUR comment threads ;-)
threads={
    'ADV0': ('//ralsina.me/weblog/posts/ADV0.html','My first post'),
    'ADV1': ('//ralsina.me/weblog/posts/ADV1.html','My second post'),
    }

key='USE YOUR API KEY HERE'
ds=DisqusService()
ds.login(key)
forum=ds.get_forum_list()[0]

def importThread(node):
    t_id=node.attrib['id']

    # Your haloscan thread data
    thr_data=threads[t_id]

    # A Disqus thread: it will be created if needed
    thread=ds.thread_by_identifier(forum,t_id,t_id)['thread']

    # Set the disqus thread data to match your blog
    ds.update_thread(forum, thread, url=thr_data[0], title=thr_data[1])


    # Now post all the comments in this thread
    for node in node.findall('comment'):
        dt=datetime.strptime(node.find('datetime').text[:19],'%Y-%m-%dT%H:%M:%S')
        name=node.find('name').text or 'Anonymous'
        email=node.find('email').text or ''
        uri=node.find('uri').text or ''
        text=node.find('text').text or 'No text'

        print '-'*80
        print 'Name:', name
        print 'Email:', email
        print 'Date:', dt
        print 'URL:', uri
        print
        print 'Text:'
        print text

        print ds.create_post(forum, thread, text, name, email,
                                   created_at=dt, author_url=uri)
        time.sleep(1)

def importComments(fname):
    tree=ElementTree.parse(fname)
    for node in tree.findall('thread'):
        importThread(node)


# Replace comments.xml with the file you downloaded from Haloscan
importComments('comments.xml')

Now, if we are lucky, you already have a nice and fully functioning collection of comments in your Disqus account, and you should be calm knowing you have not lost your data. Ready for the final step?

2009-12-16 17:12

New 24-hour app coming (not so) soon: foley

First a short explanation:

24-hour apps are small, self-contained projects where I intend to create a decent, useful application in 24 hours. The concept is that:

  1. I will think about this app a lot for a while
  2. I will design it in my head or in written notes
  3. I will code, from scratch, for 24 hours.
  4. That's not one day, really, but 24 hours of work. I can't work 24 hours straight anymore.

The last time around this didn't quite work as I intended, but it was fun and educational (for me at least ;-) and the resulting app is really not bad!

So, what's foley going to be? A note-taking app aimed at students and conference public.

In your last geeky conference, did you notice everyone is using a computer?

And what are they taking notes on? Vi? Kwrite? OpenOffice? Whatever it is they use, it's not meant to be used for this purpose.

So, what will foley do different? I don't quite know yet, but I have some ideas:

  1. A strong timeline orientation. Every paragraph will be dated.
  2. Twitter/Identica support. Want to liveblog your notes? Just click.
  3. Multimedia incorporated in the timeline.
    • Webcam/Audio recording synced to your notes?
    • Images imported and added in the timeline?
    • Attach files to the timeline? (Useful for slides?)
  4. If provided with a PDF of slides, attach each slide to the right moment in the timeline
  5. Easy web publishing: find a way to put this on a webpage easy and quick (single-click publishing is the goal)

I have only thought about this for about 10 minutes, but I see potential here.

The bad news is... I have a ton of paying work to do. So this will probably only happen in January. However, I wanted to post it so I can take input while in this planning phase.

So, any ideas?

2009-12-11 11:04

Making a unique application using python and DBUS

No, not unique in the sense "oh, this app is a special snowflake", but unique in the sense "you can only run one copy of this application".

I tried googling for it and I always found the same answer, "use dbus, try to own the name, if it exists already, then a copy is already running".

What I could not find is one working example of this, or at least not something conveniently labeled "here is how you do a unique application using dbus and python".

So, here is how you do a unique application using dbus and python:

Supposing your application is called uRSSus (mine is):

session_bus = dbus.SessionBus()
try:
    session_bus.get_object("org.urssus.service", "/uRSSus")
    # This is the second copy, make the first one show instead
    # TODO: implement
except dbus.DBusException: # No other copy running
    # This will 'take' the DBUS name
    name = dbus.service.BusName("org.urssus.service", bus=session_bus)
    # Now, start your app:
    window=MainWindow()
    object = UrssusServer(window,name)
    :
    :
    :
    etc, etc

And that's it. No, it's not hard, but since the DBUS docs seem to be... rather they seem almost not to be sometimes, every little bit may help.

2009-12-03 10:44

I knew not doing it was smarter, or how HTML5 and Qt do my work for me.

I wrote a while ago a RSS program called uRSSus. I expect I am the only user of it because it has some problems (all of them my fault ;-) but I really like it.

For a while now I have wanted it to have podcast support. The thing is... that always seemed like a lot of work. Sure, using phonon I can create an audio player and everything, but...

I am using a HTML widget to display the posts, so I would have to find a way to add the audio player to the UI and ... too much work.

So, today I woke up and thought... wait a minute... Qt's HTML widget is based on Webkit. And Webkit supports HTML5. And HTML5 has an "audio" tag.

So, if I fixed uRSSus to fetch the enclosure links, and added them in the database, and then added this to the post template:

<?py for enclosure in  post.enclosures: ?>
  <audio autobuffer="Yes" controls="controls" src=#{enclosure.href}></audio><br>
<?py #end ?>

Wouldn't that actually work? Well, yeah!

urssus26

So there you have it, I was right not to implement it, because the easiest way is to let Qt do it ;-)

2009-12-01 09:13

Rant: Being annoying is not a way to make me your customer

I have been a customer of Fibertel for my broadband needs for several years. Their service has not sucked bad, even if I had a few problems in the past.

However, a month ago, I decided to switch to a competing service for a good reason: it's much much much cheaper [1]

Since I am not stupid, I canceled late with Fibertel, so I would have a full month of overlapping service. I thought hey, maybe I would come back if the new service sucks [2]

What happened next has been increasingly annoying.

First Fibertel called the person who contracted the service (not me). That's reasonable.

Then they called me to ask me why I was cancelling. I exlained that the other service is (all things considered) about 75% cheaper for the same performance. I suppose that's reasonable too.

What started becoming less and less reasonable are the next 5 calls, each offering cheaper rates, but still more expensive than my new service.

What was not reasonable was that they started calling to tell me technically unsound bullshit to scare me into their service again.

What is definitely not reasonable is that they called me 6 times, even after I told them to stop calling me in the third call.

What is incredibly stupid and annoying was that they decided to block my internet access in order to show me an ad about the same offers I ALREADY DECLINED and until I clicked that ad I could not use the Internet.

What is freaking nuts is that because I have an access point I couldn't see the satan-damned ad, so I was left without internet until:

  • I removed the access point
  • Hooked my notebook to the cable modem
  • Got rejected by it
  • Hooked back the AP
  • Got the MAC from it
  • Faked my notebooks MAC
  • Clicked the Cthulhu-pissed ads
  • Hooked back the AP
  • Un-faked my MAC

So, I needed to spend an hour doing this.

Therefore, dear Fibertel, your company also provides cable TV. I am pissed at you. I have decided to buy service from DirecTV exclusively to piss you off.

Yup, I, who have been paying you every month $230 for years, will pay you $0 next month. I could have paid you $100, but no, you had to be asses about it. You couldn't let me go. Well, I do not like being pestered. I do not like that you acted like a spurned 17-year old [3]

Fibertel, I kinda liked you, but my opinion of you has gone lower.

Also, any Fibertel customers out there: if you ask to cancel the service saying you switch because of the price, they will offer you 3Mbps for a year for $79. If you say no, they will offer you 3 free months.

That's a $600 saving, so go ahead and take their money.

[1] $130 a month versus $79 a month for the same bandwidth, plus it includes phone service with free local phone calls.
[2] Since it stil may suck, I am not saying who they are, they have not earned an endorsement yet.
[3] Would you go out with me? How about we go see Twilight? No? How about we go to the fair? How about I pick you tonight? How bout if I ask my dad for the car? How about if I pay dinner? -- Fibertel: that whiny teenager is you.

2009-11-24 13:08

My first public python code works!

No, this is not a post announcing I just wrote my first public python code. This is a post about my first public python code... from 1996!

In 1996, the soon-to-be-here year of the Linux desktop was fueled by one of the marquee open source applications of the time: LyX.

LyX was (is) a sort of word processor where you wrote and generated LaTeX which then produced whatever you used to print. But I am digressing: LyX was cool because it used one of the first good free graphical toolkits: XForms.

Ok, it was not really free, because you couldn't distribute patches.

And it was not all that good either, but we were comparing it with Motif, so it was much more free and much better than that monstrosity.

BTW: The latest release of XForms is from august of 2009.

At the time, a 25-year-old me was in love with Python 1.3. Here's how I described it:

Python 1.3
It's a beautiful ,free, language. Get it from ftp://ftp.python.org http://www.python.org

Yes, Python 1.3. So, I wanted to use this C GUI toolkit used in this cool app, and this neat language I was learning and use them at the same time.

I ran (not walked) to my faithful Slackware 3.0 ELF in my 486DX2 PC and started hacking. In a weekend or so I had a working binding.

I even started writing the holy grail of desktop applications, a GUI version of Pine, using python and its IMAP module (python mailer, or PyM):

//ralsina.me/static/im1.jpg
//ralsina.me/static/im2.jpg

I released version 0.1 alpha in 1996, May 13 ... and a few months later Matthias Ettrich started KDE and I found Qt and never thought about XForms again.

Until this month.

For reasons that don't matter, I mentioned PyM in the PyAr mailing list the other day, and ... well, would pyxforms still work?

Why, pretty much, yeah!

I got the pyxforms-0.1-alpha sources from somewhere in the internet, installed XForms 1.0.92sp2 (yes, the latest release, from three months ago), of course I already had python 2.6.4 installed, added a setup.py, edited 10 lines of code and...

im1

Yes, it works. You can get this 0.2 version (codename "Cthulhu was here") here just 13 years after 0.1.

No, I don't understand the weird rounded corners, or why the cursor looks weird and old when it's inside the window.

It's a REALLY small and fast toolkit, though.

Honestly, is it useful for ayone? Almost certainly not. Am I amazed something I wrote in 1996 still works? Oh, yeah I am.

2009-11-17 21:45

I'll be speaking in Mar Del Plata

I will be doing a brand-new never seen introduction to PyQt programming at the "Jornadas de Software Libre y Open Source" in Mar del Plata tomorrow or the next day.

More info at http://softwarelibre.mdp.utn.edu.ar/

If you mention this blog and ask nicely, you get a can of cheap national beer tomorrow night (limit: 2 cans ;-)

Contents © 2000-2019 Roberto Alsina