home *** CD-ROM | disk | FTP | other *** search
/ Mac Easy 2010 May / Mac Life Ubuntu.iso / casper / filesystem.squashfs / usr / bin / purple-url-handler < prev    next >
Encoding:
Text File  |  2009-08-19  |  11.8 KB  |  399 lines

  1. #!/usr/bin/env python
  2.  
  3. import dbus
  4. import re
  5. import sys
  6. import time
  7. import urllib
  8.  
  9. bus = dbus.SessionBus()
  10. obj = None
  11. try:
  12.     obj = bus.get_object("im.pidgin.purple.PurpleService",
  13.                          "/im/pidgin/purple/PurpleObject")
  14. except dbus.DBusException, e:
  15.     if e._dbus_error_name == "org.freedesktop.DBus.Error.ServiceUnknown":
  16.         print "Error: no libpurple-powered client is running. Try starting Pidgin or Finch."
  17.         sys.exit(1)
  18. purple = dbus.Interface(obj, "im.pidgin.purple.PurpleInterface")
  19.  
  20. class CheckedObject:
  21.     def __init__(self, obj):
  22.         self.obj = obj
  23.  
  24.     def __getattr__(self, attr):
  25.         return CheckedAttribute(self, attr)
  26.  
  27. class CheckedAttribute:
  28.     def __init__(self, cobj, attr):
  29.         self.cobj = cobj
  30.         self.attr = attr
  31.  
  32.     def __call__(self, *args):
  33.         # Redirect stderr to suppress the printing of an " Introspect error"
  34.         # message if nothing is listening on the bus.  We print a friendly
  35.         # error message ourselves.
  36.         real_stderr = sys.stderr
  37.         sys.stderr = None
  38.         result = self.cobj.obj.__getattr__(self.attr)(*args)
  39.         sys.stderr = real_stderr
  40.  
  41. # This can be useful for debugging.
  42. #        if (result == 0):
  43. #            print "Error: " + self.attr + " " + str(args) + " returned " + str(result)
  44.  
  45.         return result
  46.  
  47. cpurple = CheckedObject(purple)
  48.  
  49. def extendlist(list, length, fill):
  50.     if len(list) < length:
  51.         return list + [fill] * (length - len(list))
  52.     else:
  53.         return list
  54.  
  55. def convert(value):
  56.     try:
  57.         return int(value)
  58.     except:
  59.         return value
  60.  
  61. def account_not_found():
  62.     print "No matching account found."
  63.     sys.exit(1)
  64.  
  65. def bring_account_online(account):
  66.     if not cpurple.PurpleAccountIsConnected(account):
  67.         # The last argument is meant to be a GList * but the D-Bus binding
  68.         # generator thing just wants a UInt32, which is pretty failing.
  69.         # Happily, passing a 0 to mean an empty list turns out to work anyway.
  70.         purple.PurpleAccountSetStatusList(account, "online", 1, 0)
  71.         purple.PurpleAccountConnect(account)
  72.  
  73. def findaccount(protocolname, accountname="", matcher=None):
  74.     if matcher:
  75.         for account in cpurple.PurpleAccountsGetAll():
  76.             if accountname != "" and accountname != cpurple.PurpleAccountGetUsername(a):
  77.                 continue
  78.             if matcher(account):
  79.                 bring_account_online(account)
  80.                 return account
  81.         account_not_found()
  82.  
  83.     # prefer connected accounts
  84.     account = cpurple.PurpleAccountsFindConnected(accountname, protocolname)
  85.     if (account != 0):
  86.         return account
  87.  
  88.     # try to get any account and connect it
  89.     account = cpurple.PurpleAccountsFindAny(accountname, protocolname)
  90.     if (account == 0):
  91.         account_not_found()
  92.  
  93.     bring_account_online(account)
  94.     return account
  95.  
  96. def goim(account, screenname, message=None):
  97.     # XXX: 1 == PURPLE_CONV_TYPE_IM
  98.     conversation = cpurple.PurpleConversationNew(1, account, screenname)
  99.     if message:
  100.         purple.PurpleConvSendConfirm(conversation, message)
  101.  
  102. def gochat(account, params, message=None):
  103.     connection = cpurple.PurpleAccountGetConnection(account)
  104.     purple.ServJoinChat(connection, params)
  105.  
  106.     if message != None:
  107.         for i in range(20):
  108.             # XXX: 2 == PURPLE_CONV_TYPE_CHAT
  109.             conversation = purple.PurpleFindConversationWithAccount(2, params.get("channel", params.get("room")), account)
  110.             if conversation:
  111.                 purple.PurpleConvSendConfirm(conversation, message)
  112.                 break
  113.             else:
  114.                 time.sleep(0.5)
  115.  
  116. def addbuddy(account, screenname, group="", alias=""):
  117.     cpurple.PurpleBlistRequestAddBuddy(account, screenname, group, alias)
  118.  
  119.  
  120. def aim(uri):
  121.     protocol = "prpl-aim"
  122.     match = re.match(r"^aim:([^?]*)(\?(.*))", uri)
  123.     if not match:
  124.         print "Invalid aim URI: %s" % uri
  125.         return
  126.  
  127.     command = urllib.unquote_plus(match.group(1))
  128.     paramstring = match.group(3)
  129.     params = {}
  130.     if paramstring:
  131.         for param in paramstring.split("&"):
  132.             key, value = extendlist(param.split("=", 1), 2, "")
  133.             params[key] = urllib.unquote_plus(value)
  134.     accountname = params.get("account", "")
  135.     screenname = params.get("screenname", "")
  136.  
  137.     account = findaccount(protocol, accountname)
  138.  
  139.     if command.lower() == "goim":
  140.         goim(account, screenname, params.get("message"))
  141.     elif command.lower() == "gochat":
  142.         gochat(account, params)
  143.     elif command.lower() == "addbuddy":
  144.         addbuddy(account, screenname, params.get("group", ""))
  145.  
  146. def gg(uri):
  147.     protocol = "prpl-gg"
  148.     match = re.match(r"^gg:(.*)", uri)
  149.     if not match:
  150.         print "Invalid gg URI: %s" % uri
  151.         return
  152.  
  153.     screenname = urllib.unquote_plus(match.group(1))
  154.     account = findaccount(protocol)
  155.     goim(account, screenname)
  156.  
  157. def icq(uri):
  158.     protocol = "prpl-icq"
  159.     match = re.match(r"^icq:([^?]*)(\?(.*))", uri)
  160.     if not match:
  161.         print "Invalid icq URI: %s" % uri
  162.         return
  163.  
  164.     command = urllib.unquote_plus(match.group(1))
  165.     paramstring = match.group(3)
  166.     params = {}
  167.     if paramstring:
  168.         for param in paramstring.split("&"):
  169.             key, value = extendlist(param.split("=", 1), 2, "")
  170.             params[key] = urllib.unquote_plus(value)
  171.     accountname = params.get("account", "")
  172.     screenname = params.get("screenname", "")
  173.  
  174.     account = findaccount(protocol, accountname)
  175.  
  176.     if command.lower() == "goim":
  177.         goim(account, screenname, params.get("message"))
  178.     elif command.lower() == "gochat":
  179.         gochat(account, params)
  180.     elif command.lower() == "addbuddy":
  181.         addbuddy(account, screenname, params.get("group", ""))
  182.  
  183. def irc(uri):
  184.     protocol = "prpl-irc"
  185.     match = re.match(r"^irc:(//([^/]*)/)?([^?]*)(\?(.*))?", uri)
  186.     if not match:
  187.         print "Invalid irc URI: %s" % uri
  188.         return
  189.  
  190.     server = urllib.unquote_plus(match.group(2)) or ""
  191.     target = match.group(3) or ""
  192.     query = match.group(5) or ""
  193.  
  194.     modifiers = {}
  195.     if target:
  196.         for modifier in target.split(",")[1:]:
  197.             modifiers[modifier] = True
  198.  
  199.     isnick = modifiers.has_key("isnick")
  200.  
  201.     paramstring = match.group(5)
  202.     params = {}
  203.     if paramstring:
  204.         for param in paramstring.split("&"):
  205.             key, value = extendlist(param.split("=", 1), 2, "")
  206.             params[key] = urllib.unquote_plus(value)
  207.  
  208.     def correct_server(account):
  209.         username = cpurple.PurpleAccountGetUsername(account)
  210.         user_split = (username.split("@"))
  211.         # Not all accounts have a split, so append an empty string so the
  212.         # [1] doesn't throw an IndexError.
  213.         user_split.append("")
  214.         return (server == user_split[1])
  215.  
  216.     account = findaccount(protocol, matcher=correct_server)
  217.  
  218.     if (target != ""):
  219.         if (isnick):
  220.             goim(account, urllib.unquote_plus(target.split(",")[0]), params.get("msg"))
  221.         else:
  222.             channel = urllib.unquote_plus(target.split(",")[0])
  223.             if channel[0] != "#":
  224.                 channel = "#" + channel
  225.             gochat(account, {"server": server, "channel": channel, "password": params.get("key", "")}, params.get("msg"))
  226.  
  227. def msnim(uri):
  228.     protocol = "prpl-msn"
  229.     match = re.match(r"^msnim:([^?]*)(\?(.*))", uri)
  230.     if not match:
  231.         print "Invalid msnim URI: %s" % uri
  232.         return
  233.  
  234.     command = urllib.unquote_plus(match.group(1))
  235.     paramstring = match.group(3)
  236.     params = {}
  237.     if paramstring:
  238.         for param in paramstring.split("&"):
  239.             key, value = extendlist(param.split("=", 1), 2, "")
  240.             params[key] = urllib.unquote_plus(value)
  241.     screenname = params.get("contact", "")
  242.  
  243.     account = findaccount(protocol)
  244.  
  245.     if command.lower() == "chat":
  246.         goim(account, screenname)
  247.     elif command.lower() == "add":
  248.         addbuddy(account, screenname)
  249.  
  250. def myim(uri):
  251.         protocol = "prpl-myspace"
  252.         print "TODO: send uri: ", uri
  253.         assert False, "Not implemented"
  254.  
  255. def sip(uri):
  256.     protocol = "prpl-simple"
  257.     match = re.match(r"^sip:(.*)", uri)
  258.     if not match:
  259.         print "Invalid sip URI: %s" % uri
  260.         return
  261.  
  262.     screenname = urllib.unquote_plus(match.group(1))
  263.     account = findaccount(protocol)
  264.     goim(account, screenname)
  265.  
  266. def xmpp(uri):
  267.     protocol = "prpl-jabber"
  268.     match = re.match(r"^xmpp:(//([^/?#]*)/?)?([^?#]*)(\?([^;#]*)(;([^#]*))?)?(#(.*))?", uri)
  269.     if not match:
  270.         print "Invalid xmpp URI: %s" % uri
  271.         return
  272.  
  273.     tmp = match.group(2)
  274.     if (tmp):
  275.         accountname = urllib.unquote_plus(tmp)
  276.     else:
  277.         accountname = ""
  278.  
  279.     screenname = urllib.unquote_plus(match.group(3))
  280.  
  281.     tmp = match.group(5)
  282.     if (tmp):
  283.         command = urllib.unquote_plus(tmp)
  284.     else:
  285.         command = ""
  286.  
  287.     paramstring = match.group(7)
  288.     params = {}
  289.     if paramstring:
  290.         for param in paramstring.split(";"):
  291.             key, value = extendlist(param.split("=", 1), 2, "")
  292.             params[key] = urllib.unquote_plus(value)
  293.  
  294.     account = findaccount(protocol, accountname)
  295.  
  296.     if command.lower() == "message":
  297.         goim(account, screenname, params.get("body"))
  298.     elif command.lower() == "join":
  299.         room, server = screenname.split("@")
  300.         gochat(account, {"room": room, "server": server})
  301.     elif command.lower() == "roster":
  302.         addbuddy(account, screenname, params.get("group", ""), params.get("name", ""))
  303.     else:
  304.         goim(account, screenname)
  305.  
  306. def gtalk(uri):
  307.     protocol = "prpl-jabber"
  308.     match = re.match(r"^gtalk:([^?]*)(\?(.*))", uri)
  309.     if not match:
  310.         print "Invalid gtalk URI: %s" % uri
  311.         return
  312.  
  313.     command = urllib.unquote_plus(match.group(1))
  314.     paramstring = match.group(3)
  315.     params = {}
  316.     if paramstring:
  317.         for param in paramstring.split("&"):
  318.             key, value = extendlist(param.split("=", 1), 2, "")
  319.             params[key] = urllib.unquote_plus(value)
  320.     accountname = params.get("from_jid", "")
  321.     jid = params.get("jid", "")
  322.  
  323.     account = findaccount(protocol, accountname)
  324.  
  325.     if command.lower() == "chat":
  326.         goim(account, jid)
  327.     elif command.lower() == "call":
  328.         # XXX V&V prompt to establish call
  329.         goim(account, jid)
  330.  
  331. def ymsgr(uri):
  332.     protocol = "prpl-yahoo"
  333.     match = re.match(r"^ymsgr:([^?]*)(\?([^&]*)(&(.*))?)", uri)
  334.     if not match:
  335.         print "Invalid ymsgr URI: %s" % uri
  336.         return
  337.  
  338.     command = urllib.unquote_plus(match.group(1))
  339.     screenname = urllib.unquote_plus(match.group(3))
  340.     paramstring = match.group(5)
  341.     params = {}
  342.     if paramstring:
  343.         for param in paramstring.split("&"):
  344.             key, value = extendlist(param.split("=", 1), 2, "")
  345.             params[key] = urllib.unquote_plus(value)
  346.  
  347.     account = findaccount(protocol)
  348.  
  349.     if command.lower() == "sendim":
  350.         goim(account, screenname, params.get("m"))
  351.     elif command.lower() == "chat":
  352.         gochat(account, {"room": screenname})
  353.     elif command.lower() == "addfriend":
  354.         addbuddy(account, screenname)
  355.  
  356.  
  357. def main(argv=sys.argv):
  358.     if len(argv) != 2 or argv[1] == "--help" or argv[1] == "-h":
  359.         print "Usage: %s URI" % argv[0]
  360.         print "Example: %s \"xmpp:romeo@montague.net?message\"" % argv[0]
  361.  
  362.         if len(argv) != 2:
  363.             sys.exit(1)
  364.         else:
  365.             return 0
  366.  
  367.     uri = argv[1]
  368.     type = uri.split(":")[0]
  369.  
  370.     try:
  371.         if type == "aim":
  372.             aim(uri)
  373.         elif type == "gg":
  374.             gg(uri)
  375.         elif type == "icq":
  376.             icq(uri)
  377.         elif type == "irc":
  378.             irc(uri)
  379.         elif type == "msnim":
  380.             msnim(uri)
  381.         elif type == "myim":
  382.             myim(uri)
  383.         elif type == "sip":
  384.             sip(uri)
  385.         elif type == "xmpp":
  386.             xmpp(uri)
  387.         elif type == "gtalk":
  388.             gtalk(uri)
  389.         elif type == "ymsgr":
  390.             ymsgr(uri)
  391.         else:
  392.             print "Unknown protocol: %s" % type
  393.     except dbus.DBusException, e:
  394.         print "Error: %s" % (e.message)
  395.         sys.exit(1)
  396.  
  397. if __name__ == "__main__":
  398.     main()
  399.