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()
Hi there,
I was just testing out your code, but for some reason it doesn’t work for me.
I understand that you pass the variables through the command prompt but it doesn’t recognize my file and I tried hard coding the file extension and user name, etc into the code and it says ‘permission denied’. Any ideas why that would be? I am a newbie to XMPP and just discovered the VCARD, I wanted to use the avatar.
Should I be naming the image file vcard? Because I have tried that too.
Any help is appreciated,
Thanks,
Needz
Two possibilities come to mind: (1) the python script is not executable — remember to run “chmod 755 vcard.py” (2) you (or more specifically, the script) don’t have permission to read the image file — try making the image file world readable with chmod 644.
Thanks for replying, but I am not using Linux. I run “python vcard.py …………” and then the variables and that is when I get the error. I am actually using windows vista. Could it be something to do with this line:
“file=os.path.expanduser(sys.argv[1])”
Perhaps I am passing something wrongly here?
What do you think?
Oh. Vista. Can’t help you there — I don’t have Python installed on a Vista machine. I would imagine that the User Account Controls could be a possible culprit. Or the line you mentioned. Have you tried hard-coding the filename in lieu of sys.argv[1]?
Cool. I wrote a similar one that downloads other people’s instead of updating your own. Nice to know you can go the other direction too.
http://collincode.wordpress.com/2009/01/31/xmpp-jabber-photo-module-2/
Yes, I have hard-coded it, and have had to make a few changes. That problem does not occur anymore.
I have been debugging and for some reason it will only accept a png file, strange, but now the problem is the following:
“””
Traceback (most recent call last):
File “C:\Users\Nida\Documents\CMPT 275\vcard.py”, line 86, in
send_presence(cl, ‘Updated vCard Image’, hash_img(img), j.getNode())
File “C:\Users\Nida\Documents\CMPT 275\vcard.py”, line 71, in send_presence
conn.send(presence)
File “C:\Python26\lib\site-packages\xmpppy-0.5.0rc1-py2.6.egg\xmpp\dispatcher.py”, line 367, in send
self._owner_send(stanza)
File “C:\Python26\lib\site-packages\xmpppy-0.5.0rc1-py2.6.egg\xmpp\transports.py”, line 195, in send
self._owner.disconnected()
File “C:\Python26\lib\site-packages\xmpppy-0.5.0rc1-py2.6.egg\xmpp\client.py”, line 129, in disconnected
for i in self.disconnect_handlers: i()
File “C:\Python26\lib\site-packages\xmpppy-0.5.0rc1-py2.6.egg\xmpp\client.py”, line 137, in DisconnectHandler
raise IOError(‘Disconnected from server.’)
IOError: Disconnected from server.
“””
I guess it now has a problem with conn.send(presence), I have to do some more debugging before I can fully understand why this is happening.
Any ideas?
I have realized that by simply switching the order of these two statements:
” send_vcard(cl, base64_img(img), get_mime_type(file), j.getNode())
send_presence(cl, ‘Updated vCard Image’, hash_img(img), j.getNode())
”
The code will run smoothly and update the vcard photo on jabber accounts.
However it does not work for gmail accounts. For gmail, the log in process is a little different, and when I do that, it doesn’t work anymore. Does gmail support Vcards?
I did notice a typo on the get_mime_type function, but as for gmail, like I said, I don’t know if it works. Sounds like maybe not. Google Talk certainly supports vcard avatars, but maybe you can’t set it from outside the GMail or Google Talk service.