Skip to main content

Ralsina.Me — Roberto Alsina's website

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

Introduction

If you are a Haloscan user, and are start­ing to won­der what can you do... this page will ex­plain you a way to take your com­ments to Dis­qus, an­oth­er free com­ment ser­vice.

A few days ago, Haloscan an­nounced they were stop­ping their free com­ment ser­vice for blogs. Guess what ser­vice has in it the com­ments of the last 9 years of this blog? Yes, Haloscan.

They of­fered a sim­ple mi­gra­tion to their Echo plat­for­m, which you have to pay for. While Echo looks like a per­fect­ly nice com­ment plat­for­m, I am not go­ing to spend any mon­ey on this blog if I can help it, since it al­ready eats a lot of my time.

Luck­i­ly, the guys at Haloscan al­low ex­port­ing the com­ments (that used to be on­ly for their pre­mi­um ac­counts), so thanks Haloscan, it has been nice!

So, I start­ed re­search­ing where I could run to. There seems to be two large free com­ment sys­tem­s:

Keep in mind that my main in­ter­est lays in not los­ing al­most ten years of com­ments, not on how great the ser­vice is. That be­ing said, they both seem to of­fer rough­ly the same fea­tures.

Let's con­sid­er how you can im­port com­ments to each ser­vice:

  • Dis­­qus: It can im­­port from blog­ger and some oth­­er host­ed blog ser­vice. Not from Haloscan.

  • In­­tense De­­bate: Can im­­port from some host­ed ser­vices, and from some files. Not from the file Haloscan gave me.

So, what is a guy to do? Write a python pro­gram, of course! Here's where Dis­qus won: they have a pub­lic API for post­ing com­ments.

So, all I have to do then is:

  1. Grok the Dis­­qus API

  2. Grok the Haloscan com­­ments file (it's XM­L)

  3. Cre­ate the nec­es­sary threads and what­ev­er in Dis­­qus

  4. Post the com­­ments from Haloscan to Dis­­qus

  5. Hack the blog so the links to Haloscan now work for Dis­­qus

Piece of cake. It on­ly took me half a day, which at my cur­rent rates is what 3 years of Echo would have cost­ed me, but where's the fun in pay­ing?

So, let's go step by step.

1. Grok the Disqus API

Luck­i­ly, there is a rea­son­able Dis­qus Python Client li­brary and docs for the API so, this was not hard.

Just get the li­brary and in­stall it:

hg clone https://IanLewis@bitbucket.org/IanLewis/disqus-python-client/
cd disqus-python-client
python setup.py install

The API us­age we need is re­al­ly sim­ple, so study the API docs for 15 min­utes if you wan­t. I got al­most all the tips I need­ed from this py­blox­som im­port script

Ba­si­cal­ly:

  1. Get your API Key

  2. You lo­­gin

  3. You get the right "fo­rum" (y­ou can use a dis­­qus ac­­count for more than one blog)

  4. Post to the right thread

2. Grok the Haloscan comments file

Not on­ly is it XM­L, it's pret­ty sim­ple XM­L!

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>josje@aaaaaa.nl</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>maxilys@aaaaaa.fr</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 com­ments tag that con­tains one or more thread tags, which con­tain one or more com­ment tags. Piece of cake to tra­verse us­ing El­e­ment­Tree!

There is an ob­vi­ous match be­tween com­ments and threads in Haloscan and Dis­qus. Good.

3. Create the necessary threads and whatever in Disqus

This is the tricky part, re­al­ly, be­cause it re­quires some things from your blog.

  • You must have a per­ma­link for each post

  • Each per­ma­link should be a sep­a­rate page. You can't have per­ma­links with # in the URL

  • You need to know what haloscan id you used for each post's com­­ments, and what the per­ma­link for each post is.

For ex­am­ple, sup­pose you have a post at //ralsi­na.me/we­blog/­post­s/AD­V0.html and it has a Haloscan com­ments link like this:

<a hre­f="javascrip­t:HaloScan('AD­V0');" tar­get="_­self"> <script type­="­tex­t/­javascrip­t">­post­Coun­t('AD­V0');</scrip­t></a>

You know where else that 'AD­V0' ap­pears? In Haloscan's XML file, of course! It's the "id" at­tribute of a thread.

Al­so, the ti­tle of this post is "Ad­voga­to post for 2000-01-17 17:19:57" (hey, it's my blog ;-)

Got that?

Then we want to cre­ate a thread in Dis­qus with that ex­act same da­ta:

  • URL

  • Thread ID

  • Ti­­tle

The bad news is... you need to gath­er this in­for­ma­tion for your en­tire blog and store it some­where. If you are luck­y, you may be able to get it from a database, as I did. If not... well, it's go­ing to be a lot of work :-(

For the pur­pose of this ex­pla­na­tion, I will as­sume you got that da­ta nice­ly in a dic­tio­nary in­dexed by thread id:

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

4. Post the comments from Haloscan to Disqus

Here's the code. It's not re­al­ly test­ed, be­cause I had to do sev­er­al at­tempts and fix­es, but it should be close to ok (down­load).

#!/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 luck­y, you al­ready have a nice and ful­ly func­tion­ing col­lec­tion of com­ments in your Dis­qus ac­coun­t, and you should be calm know­ing you have not lost your da­ta. Ready for the fi­nal step?

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

First a short ex­pla­na­tion:

24-hour apps are smal­l, self­-­con­tained projects where I in­tend to cre­ate a de­cen­t, use­ful ap­pli­ca­tion in 24 hours. The con­cept is that:

  1. I will think about this app a lot for a while

  2. I will de­sign it in my head or in writ­ten notes

  3. I will code, from scratch, for 24 hours.

  4. That's not one day, re­al­­ly, but 24 hours of work. I can't work 24 hours straight any­­more.

The last time around this did­n't quite work as I in­tend­ed, but it was fun and ed­u­ca­tion­al (for me at least ;-) and the re­sult­ing app is re­al­ly not bad!

So, what's fo­ley go­ing to be? A note-­tak­ing app aimed at stu­dents and con­fer­ence pub­lic.

In your last geeky con­fer­ence, did you no­tice ev­ery­one is us­ing a com­put­er?

And what are they tak­ing notes on? Vi? Kwrite? OpenOf­fice? What­ev­er it is they use, it's not meant to be used for this pur­pose.

So, what will fo­ley do dif­fer­en­t? I don't quite know yet, but I have some ideas:

  1. A strong time­­line ori­en­­ta­­tion. Ev­ery para­­graph will be dat­ed.

  2. Twit­ter/I­­den­ti­­ca sup­­port. Want to live­blog your notes? Just click.

  3. Mul­ti­me­­dia in­­­cor­po­rat­ed in the time­­line.

    • We­b­­­cam/Au­­­dio record­ing synced to your notes?

    • Im­ages im­­­port­ed and added in the time­­­line?

    • At­­­tach files to the time­­­line? (Use­­­ful for slides?)

  4. If pro­vid­ed with a PDF of slides, at­­tach each slide to the right mo­­ment in the time­­line

  5. Easy web pub­­lish­ing: find a way to put this on a we­b­­page easy and quick (s­in­­gle-click pub­­lish­ing is the goal)

I have on­ly thought about this for about 10 min­utes, but I see po­ten­tial here.

The bad news is... I have a ton of pay­ing work to do. So this will prob­a­bly on­ly hap­pen in Jan­u­ary. How­ev­er, I want­ed to post it so I can take in­put while in this plan­ning phase.

So, any ideas?

Making a unique application using python and DBUS

No, not unique in the sense "o­h, this app is a spe­cial snowflake", but unique in the sense "y­ou can on­ly run one copy of this ap­pli­ca­tion".

I tried googling for it and I al­ways found the same an­swer, "use dbus, try to own the name, if it ex­ists al­ready, then a copy is al­ready run­ning".

What I could not find is one work­ing ex­am­ple of this, or at least not some­thing con­ve­nient­ly la­beled "here is how you do a unique ap­pli­ca­tion us­ing dbus and python".

So, here is how you do a unique ap­pli­ca­tion us­ing dbus and python:

Sup­pos­ing your ap­pli­ca­tion 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 al­most not to be some­times, ev­ery lit­tle bit may help.

DBUS-reactor, or AsusOSD must die!

How to write a tiny python app (less than 50 lines) that re­acts to events on the DBUS bus­es. For ex­am­ple, dis­play­ing a no­ti­fi­ca­tion when you press one of your key­board­s' spe­cial keys.

Read all about it

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

I wrote a while ago a RSS pro­gram called uRSSus. I ex­pect I am the on­ly us­er of it be­cause it has some prob­lems (all of them my fault ;-) but I re­al­ly like it.

For a while now I have want­ed it to have pod­cast sup­port. The thing is... that al­ways seemed like a lot of work. Sure, us­ing phonon I can cre­ate an au­dio play­er and ev­ery­thing, but...

I am us­ing a HTML wid­get to dis­play the post­s, so I would have to find a way to add the au­dio play­er to the UI and ... too much work.

So, to­day I woke up and thought... wait a minute... Qt's HTML wid­get is based on We­bkit. And We­bkit sup­ports HTM­L5. And HTM­L5 has an "au­dio" tag.

So, if I fixed uRSSus to fetch the en­clo­sure links, and added them in the database, and then added this to the post tem­plate:

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

Would­n't that ac­tu­al­ly work? Well, yeah!

urssus26

So there you have it, I was right not to im­ple­ment it, be­cause the eas­i­est way is to let Qt do it ;-)


Contents © 2000-2023 Roberto Alsina