Code:
#!/usr/bin/python
# -*- coding: utf-8 -*-
###############################################################################
# conkyPidgin.py is a simple python script to display
# details of pidgin buddies, for use in conky.
#
# Author: Kaivalagi
# Created: 03/11/2008
# Modifications:
# 03/11/2008 Added --onlineonly option to only show online buddies in the list
# 03/11/2008 Added --ignorelist to handle ignoring unwanted pidgin buddy output
# 03/11/2008 Added --includelist to handle including only wanted pidgin buddy output
# 03/11/2008 Updated to handle buddy group and status_messages
# 03/11/2008 Updated to display a status of "Chatting" when the buddy is messaging
# 04/11/2008 Status message Now html striped from the text
import sys, traceback
try:
import dbus
DBUS_AVAIL = True
except ImportError:
# Dummy D-Bus library
class _Connection:
get_object = lambda *a: object()
class _Interface:
__init__ = lambda *a: None
ListNames = lambda *a: []
class Dummy: pass
dbus = Dummy()
dbus.Interface = _Interface
dbus.service = Dummy()
dbus.service.method = lambda *a: lambda f: f
dbus.service.Object = object
dbus.SessionBus = _Connection
DBUS_AVAIL = False
import re
from htmlentitydefs import name2codepoint
from optparse import OptionParser
class CommandLineParser:
parser = None
def __init__(self):
self.parser = OptionParser()
self.parser.add_option("-t", "--template", dest="template", type="string", metavar="FILE", help=u"Template file determining the format for each buddy's data. Use the following placeholders: <name>, <alias>, <group>, <status>, <status_message>.")
self.parser.add_option("-o", "--onlineonly", dest="onlineonly", default=False, action="store_true", help=u"Only show online buddies")
self.parser.add_option("-i", "--ignorelist", dest="ignorelist", type="string", metavar="LIST", help=u"A comma delimited list of names or aliases to ignore. Partial text matches on name or alias will be ignored if found")
self.parser.add_option("-I", "--includelist", dest="includelist", type="string", metavar="LIST", help=u"A comma delimited list of names or aliases to include. Partial text matches on name or alias will be included if found. The ignorelist, if used, takes precedence. if this list is omitted all buddies will be included unless ignored.")
self.parser.add_option("-v", "--verbose", dest="verbose", default=False, action="store_true", help=u"Request verbose output, not a good idea when running through conky!")
self.parser.add_option("-V", "--version", dest="version", default=False, action="store_true", help=u"Displays the version of the script.")
self.parser.add_option("-O", "--onlinestring", dest="onlinestring", type="string", metavar="string", help=u"String for \"Online\"")
self.parser.add_option("-F", "--offlinestring", dest="offlinestring", type="string", metavar="string", help=u"String for \"Offline\"")
def parse_args(self):
(options, args) = self.parser.parse_args()
return (options, args)
def print_help(self):
return self.parser.print_help()
class BuddyData:
def __init__(self, name, alias, group, status, status_message):
self.name = name
self.alias = alias
self.group = group
self.status = status
self.status_message = status_message
def __cmp__(self, other):
return cmp(self.group, other.group)
def __str__(self):
return str(self.name+"("+self.alias+")")
class ConkyPidgin:
def __init__(self, options):
self.options = options
def testDBus(self, bus, interface):
obj = bus.get_object('org.freedesktop.DBus', '/org/freedesktop/DBus')
dbus_iface = dbus.Interface(obj, 'org.freedesktop.DBus')
avail = dbus_iface.ListNames()
return interface in avail
def getTemplateOutput(self, template, name, alias, group, status, status_message):
try:
output = template
output = output.replace("<name>",name)
output = output.replace("<alias>",alias)
output = output.replace("<group>",group)
output = output.replace("<status>",status)
output = output.replace("<status_message>",status_message)
# get rid of any excess crlf's
output = output.rstrip(" \n")
return output
except Exception,e:
self.logError("getTemplateOutput:Unexpected error:" + e.__str__())
return ""
def getbuddyData(self):
buddyDataList = []
try:
bus = dbus.SessionBus()
if self.testDBus(bus, 'im.pidgin.purple.PurpleService'):
self.logInfo("Setting up dbus interface")
remote_object = bus.get_object("im.pidgin.purple.PurpleService","/im/pidgin/purple/PurpleObject")
iface = dbus.Interface(remote_object, "im.pidgin.purple.PurpleService")
self.logInfo("Calling dbus interface for IM data")
# Iterate through every active account
for acctID in iface.PurpleAccountsGetAllActive():
# get all the buddies associated with that account
buddies = iface.PurpleFindBuddies(acctID,"")
for buddyid in buddies:
# get initial data
alias = iface.PurpleBuddyGetAlias(buddyid)
name = iface.PurpleBuddyGetName(buddyid)
online = iface.PurpleBuddyIsOnline(buddyid)
if self.ignoreBuddy(name, alias) == False:
if self.includeBuddy(name, alias) == True:
# determine whether to show this buddies details
if online == 1 or self.options.onlineonly == False:
# get all the extra details we want
groupid = iface.PurpleBuddyGetGroup(buddyid)
group = iface.PurpleGroupGetName(groupid)
if self.options.onlinestring == None:
self.options.onlinestring = "Online"
if self.options.offlinestring == None:
self.options.offlinestring = "Offline"
if online == 1:
status = self.options.onlinestring
else:
status = self.options.offlinestring
# status message
presenceid = iface.PurpleBuddyGetPresence(buddyid)
statusid = iface.PurplePresenceGetActiveStatus(presenceid)
status_message = self.getCleanText(iface.PurpleStatusGetAttrString(statusid, "message")) # needed for google encoded text
if self.isBuddyChatting(name,iface):
status = "Chatting"
buddyData = BuddyData(name, alias, group, status, status_message)
buddyDataList.append(buddyData)
# tidy up
del iface
del remote_object
del bus
# sort by group
buddyDataList.sort()
return buddyDataList
except Exception, e:
self.logError("Issue calling the dbus service:"+e.__str__())
def getOutputText(self):
if self.options.template == None:
# create default template
template = "<alias> (<group>) - <status>\n\t<status_message>"
else:
# load the template file contents
try:
fileinput = open(self.options.template)
template = fileinput.read()
fileinput.close()
except:
self.logError("Template file no found!")
sys.exit(2)
try:
buddyDataList = self.getbuddyData()
for buddyData in buddyDataList:
# output pidgin buddy data using the template
output = self.getTemplateOutput(template, buddyData.name, buddyData.alias, buddyData.group, buddyData.status, buddyData.status_message)
print output.encode("utf-8")
except SystemExit:
self.logError("System Exit!")
return u""
except Exception, e:
traceback.print_exc()
self.logError("Unknown error when calling getOutputText:" + e.__str__())
return u""
def isBuddyChatting(self,name,iface):
imids = iface.PurpleGetIms()
for imid in imids:
convname = iface.PurpleConversationGetName(imid)
if convname == name:
return True
return False
def ignoreBuddy(self, name, alias):
if self.options.ignorelist != None:
# for each text in the ignore list, should we be ignoring the buddy
for ignore in self.options.ignorelist.split(","):
# has the buddy been found in the list item
if name.find(ignore) != -1 or alias.find(ignore) != -1:
return True
return False
else:
return False
def includeBuddy(self, name, alias):
if self.options.includelist != None:
# for each text in the ignore list, should we be ignoring the buddy
for include in self.options.includelist.split(","):
# has the buddy been found in the list item
if name.find(include) != -1 or alias.find(include) != -1:
return True
return False
else:
return True
def getCleanText(self,text):
text = text.replace("'","'") # workaround for ****** xml codes not compliant with html
text = re.sub('<(.|\n)+?>','',text) # remove any html tags
return re.sub('&(%s);' % '|'.join(name2codepoint), lambda m: chr(name2codepoint[m.group(1)]), text)
def logInfo(self, text):
if self.options.verbose == True:
print >> sys.stdout, "INFO: " + text
def logError(self, text):
print >> sys.stderr, "ERROR: " + text
self.error = self.error + "ERROR: " + text + "\n"
self.errorfound = True
if __name__ == "__main__":
parser = CommandLineParser()
(options, args) = parser.parse_args()
if options.version == True:
print >> sys.stdout,"conkyPidgin v.2.02"
else:
if options.verbose == True:
print >> sys.stdout,"*** INITIAL OPTIONS:"
print >> sys.stdout," template:", options.template
print >> sys.stdout," onlineonly:", options.onlineonly
print >> sys.stdout," ignorelist:", options.ignorelist
print >> sys.stdout," verbose:", options.verbose
conkyPidgin = ConkyPidgin(options)
conkyPidgin.getOutputText()
Bookmarks