2008-08-07

Dbus, knotify and pidgin

Threw together an ugly python script sendind pidgin notifications to knotify:

#!/usr/bin/env python

import re

html_tags = re.compile('<.*?>')

def my_func(account, sender, message, conversation, flags):
kn.event("receivedImMsg", "pidgin", [], '<b>' + sender + '</b>: ' + html_tags.sub('', message), [0,0,0,0], [], 0, dbus_interface="org.kde.KNotify")

import dbus, gobject
from dbus.mainloop.glib import DBusGMainLoop
dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
bus = dbus.SessionBus()

kn = bus.get_object("org.kde.knotify", "/Notify")

bus.add_signal_receiver(my_func,
dbus_interface="im.pidgin.purple.PurpleInterface",
signal_name="ReceivedImMsg")

loop = gobject.MainLoop()
loop.run()

Combine with this file: $HOME/.kde/share/config/pidgin.notifyrc


[Event/receivedImMsg]
Action=Sound|Popup|Taskbar
Execute=
KTTS=
Logfile=
Sound=KDE-Im-Message-In.ogg

... and your're good to go ;)

Pidgin reference

2008-08-06

The story of dbus, knotify4 and erc

I'm using erc in Emacs as my irc client and by default there is no notification outside of Emacs. Trying to get something working in kde4 I first tried calling kdialog, it worked, but it wasn't a fair sight.

After deciding that the kdialog popup is too ugly I started looking for alternatives. The alternative I found where right in front of my eyes: The Notify plasmoid. The problem was that there's no easy way of calling knotify (like kdialog --passivepopup) but some googling turned up http://mvidner.blogspot.com/2008/06/knotify-client.html which describes how to patch knotify4 (the dbus signature is apparently erronous) and how to call it from python.

Sure enough, after patching knotify, the nicely skinned notices popped up, and the text were even customizable using html.

Starting from emacs 23 dbus support is built-in, and luckily I am running a cvs version. I started trying to make some dbus calls but I always got an error stating that the "event" method of knotify did not exist. After many hours and double-checking the parameters I tried it with perl, worked instantly. Now I was starting to lose hope, thinking that maybe Emacs dbus implementation didn't really work.

Just as I were beginning to give up, after staring myself blind on the function signatures, I tried the following, thinking it was really a long shot:

(dbus-call-method :session "org.kde.knotify" "/Notify" "org.kde.KNotify" "event" "warning" "kde" '(:array (:variant nil)) "message" '(:array :byte 0 :byte 0 :byte 0 :byte 0) '(:array) :int64 0)

And there it was (albeit a bit ugly)! My notification popup, called from Emacs!

But I wasn't finished yet, it still said "from kde" and it was apparently a "warning". Trying to change does values didn't bring up anything.. curios. Looking around my ~/.kde/share/config I found kopete.notifyrc. It was the key! Creating my own called emacs.notifyrc and entering


[Event/erc_nick]
Action=Sound|Popup|Taskbar
Execute=
KTTS=
Logfile=
Sound=KDE-Im-Message-In.ogg


I could call "erc_nick" and "emacs" and now I had my "own" notification. It even got the Emacs icon!

Finally I added this code to my personal erc file and I hade working erc notification:




(defun thomasa88-erc-knotify4 (type message) 
(dbus-call-method :session "org.kde.knotify" "/Notify" "org.kde.KNotify"
"event"
type "emacs" '(:array (:variant nil)) message '(:array :byte 0 :byte 0 :byte 0 :byte 0) '(:array) :int64 0)

)

;;test (dbus-call-method :session "org.kde.knotify" "/Notify" "org.kde.KNotify" "event" "erc_nick" "emacs" '(:array (:variant nil)) "message" '(:array :byte 0 :byte 0 :byte 0 :byte 0) '(:array) :int64 0)

(defun thomasa88-erc-notify-match (type from rawmsg)
(let ((erc-resp (get-text-property 0 'erc-parsed rawmsg)))
(when (and (or (eq type 'current-nick) (eq type 'keyword))
(equal (erc-response.command erc-resp) "PRIVMSG"))
(thomasa88-erc-notify erc-resp nil))))

(defun thomasa88-erc-notify-PRIVMSG (proc erc-resp)
(thomasa88-erc-notify erc-resp t))

(defun thomasa88-erc-notify (erc-resp check-privmsg)
(let ((target (first (erc-response.command-args erc-resp)))
(from-nick (first (erc-parse-user (erc-response.sender erc-resp))))
(message (erc-response.contents erc-resp)))
(when (or (not check-privmsg)
(and (erc-current-nick-p target)
(not (erc-is-message-ctcp-and-not-action-p message))))
(thomasa88-erc-knotify4 "erc_nick"
(concat target " &lt;" from-nick "&gt; " message)))))

(add-hook 'erc-text-matched-hook 'thomasa88-erc-notify-match)
(add-hook 'erc-server-PRIVMSG-functions 'thomasa88-erc-notify-PRIVMSG t)



edit: Current svn knotify has a correct signature