Tag Archives: python

I'm Adopting an Open Source Project. Now What?

On June 11, Twitter retired version 1.0 of their REST API. It was announced well in advance, but I had other things to do; checking to see if my Twitter tools would still work was too low a priority. Until they broke.

When I refer to my "Twitter tools," I mean a Python command-line script that I use to post to Twitter from bash scripts, PHP programs, Node.js programs, etc. That Python script is little more than a wrapper around an abandoned open source library that broke when Twitter turned off API v1.0 -- twitter-oauth. The repository seems to have been emptied, too. Luckily, the library is still available in the Python Package Index: http://pypi.python.org/simple/twitter_oauth/

So, I grabbed the library, updated it so that it works again, and put it up on GitHub: danmactough/twitter-oauth.

Now what?

Is there a protocol for taking over an abandoned project?

XMPP vCard Python Script

Couldn't find a script to update my Jabber/XMPP vCard photo (a/k/a avatar), so I wrote one. It requires xmpppy (a/k/a python-xmpp). It should work with gTalk, but I have not tested it.

Credit to pastebin for some code snippets.

Hope this saves someone some time and effort.

#!/usr/bin/python
'''vcard.py - Update your XMPP vcard photo with the image you provide

Usage: vcard.py image_file jid password
'''

from xmpp import JID, Client, Iq, Presence, NS_VERSION, NS_VCARD
import sys
import os
import time
from base64 import encode, decode
from hashlib import sha1

try:
    file=os.path.expanduser(sys.argv[1])
    jid=sys.argv[2]
    password=sys.argv[3]
    resource='vcard'
except:
    print >>sys.stderr, __doc__
    sys.exit(2)

NS_VCARD_UPDATE = 'vcard-temp:x:update'
NS_NICK = 'http://jabber.org/protocol/nick'

def hash_img(img):
    return sha1(img).hexdigest()

def base64_img(img):
    return img.encode('base64')

def get_img(file):
    try:
        os.stat(file)[6]
        fh = open(file, 'rb')
        img = fh.read()
        return img
    except Exception, e:
        print >>sys.stderr, e
        sys.exit(2)

def get_mime_type(file):
    try:
        ext = file[-4:]
        if ext == '.png':
            mime_type = 'image/png'
        elif ext == '.gif':
            mime_type = 'image/gif'
        elif ext == '.jpg' or ext == '.jpeg':
            mime_type = 'image/jpeg'
        else:
            raise ValueError, "Wrong mime-type detected. Check file suffix."
    except ValueError, e:
        print >>sys.stderr, e
        sys.exit(2)
    return mime_type

def send_vcard(conn, base64_img, mime_type, nick):
    iq_vcard = Iq(typ='set')
    vcard = iq_vcard.addChild(name='vCard', namespace=NS_VCARD)
    vcard.addChild(name='NICKNAME', payload=[nick])
    photo = vcard.addChild(name='PHOTO')
    photo.setTagData(tag='TYPE', val=mime_type)
    photo.setTagData(tag='BINVAL', val=base64_img)
    conn.send(iq_vcard)

def send_presence(conn, status, hash1, nick):
    presence = Presence(status = status, show = 'xa', priority = '-1')
    presence.setTag(name='x',namespace=NS_VCARD_UPDATE).setTag(name='photo',namespace=NS_VCARD_UPDATE).setData(hash1)
    presence.setTag(name='nick',namespace=NS_NICK).setData(nick)
    conn.send(presence)

if __name__ == '__main__':
    img = get_img(file)
    j=JID(jid)
    cl=Client(j.getDomain(),debug=[])
    conn=cl.connect()
    if not conn:
        raise Exception, 'failed to start connection'
    auth=cl.auth(j.getNode(),password,resource,sasl=1)
    if not auth:
        raise Exception, 'could not authenticate'
    send_vcard(cl, base64_img(img), get_mime_type(file), j.getNode())
    send_presence(cl, 'Updated vCard Image', hash_img(img), j.getNode())
    time.sleep(1)
    cl.disconnect()

Jaiku Planet Venus Filter

Just started exploring Jaiku and, coincidentally, Planet Venus. One of the cool things about Jaiku is that it aggregates your other web presences (like your blog, twitter, del.icio.us, and flickr posts) and integrates them into Jaiku presence stream. The down side of this is that it's not as good at that as Planet Venus, and then if you use Planet Venus to create a aggregation of your web presences and you include Jaiku, then you've got annoying duplication.

So, I'm not much of a Python programmer, but I wrote this Planet Venus filter that looks at each entry, and if it detects that it's a Jaiku presence update, it only includes it if it originated via Jaiku. In other words, it filters out all the duplicates.

If you understood any of that, you may find this helpful. If not, nevermind.


"""
For jaiku presence entries, only retain entries that originate from jaiku
(as opposed to grabbed via web feeds)
"""
import sys, xml.dom.minidom
entry = xml.dom.minidom.parse(sys.stdin).documentElement
entry_id = entry.getElementsByTagName('id')[0].firstChild.data
for node in entry.getElementsByTagName('link'):
if node.getAttribute('rel') == 'alternate':
entry_link = node.getAttribute('href')
break
if entry_id.find('jaiku.com/presence') > 0 and (entry_id != entry_link):
sys.exit(1)
print entry.toxml('utf-8')

(Updated to fix a bug on line 11.)

Juice-y Python

I use Juice to manage my podcasts. But it doesn't do everything I need, and it's a little buggy, and I want to learn Python anyway. So I decided to download the latest source code and see if I could fix some of the bugs I've noticed and figure out how to extend it to do everything I need.

So step one was just getting to a point where I could compile it. The source code documentation is incomplete, so here's what I did, starting from scratch.

  1. Install Python 2.5.1
  2. Install pywin32 (I'm on Windows)
  3. Install mfc71.dll (needed by pywin32)
  4. Install py2exe (needed to compile Python source code to executable bytecode)
  5. Install wxPython (for the gui)
  6. Install pysqlite (may not be necessary, but I knew I'd need it eventually)
  7. Install NSIS (Nullsoft Scriptable Install System)
  8. Install NSIS FindProcDLL plug-in

PHEW!

Juice v.2.2.3.djm After all of that, it was actually fairly easy to build and install. However, I made the mistake of trying to upgrade the Universal Feed Parser, only to find that although Juice would still compile, install and run, it was silently crapping out while trying to read feeds so it would not actually update my podcasts. I reverted back to the version of UFP bundled with Juice and everything was fine (except for the UFP bugs I was hoping to have solved by using a later version, of course).

I should update this as things progress.