simple_notify.py 5.09 KB
Newer Older
mathieui's avatar
mathieui committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
"""
This plugin lets you execute a command, to notify you from new important
messages.

Installation and configuration
------------------------------

You need to create a plugin configuration file. Create a file named :file:`simple_notify.cfg`
into your plugins configuration directory (:file:`~/.config/poezio/plugins` by
default), and fill it like this:

First example:

.. code-block:: ini

    [simple_notify]
    command = notify-send -i /path/to/poezio/data/poezio_80.png "New message from %(from)s" "%(body)s"

Second example:

.. code-block:: ini

    [simple_notify]
24
    command = echo \\<%(from)s\\> %(body)s >> some.fifo
mathieui's avatar
mathieui committed
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
    delay = 3
    after_command = echo >> some.fifo

You can put any command, instead of these ones. You can also use the
special keywords ``%(from)s`` and ``%(body)s`` that will be replaced
directly in the command line by the author of the message, and the body.

The first example shown above will display something like this:

.. figure:: ../images/simple_notify_example.png
    :alt: Simple notify example

The second example will first write the author and the message in a
fifo, that fifo can locally be read by some other program (was tested
with the xmobar PipeReader command, which displays what is read from a
fifo into a status bar. Be careful, you have two different fifos in
that case, don’t get confused). The :term:`delay` and :term:`after_command` options
are used to erase/delete/kill the notification after a certain
delay.  In our example it is used to display an empty message in our
xmobar, erasing the notification after 3 seconds.

46 47 48 49 50 51 52
Third example:

.. code-block:: ini

    [simple_notify]
    command = notify-send -i /path/to/poezio/data/poezio_80.png "New message from %(from)s" "%(body)s"
    muc_too = true
53
    muc_list = someroom@conference.jabber.org,someotherroom@conference.jabber.org
54 55 56 57

If present and set to ``True``, the ``muc_too`` option will also trigger a
notification when a new message arrives on a Multi User Chat you've joined.

58 59 60 61
If present and set to a comma separated list of muc JIDs, muc_list together 
with muc_too = true will only notify when a new message arrives on a Multi 
User Chat, you've joined if it is present on the list.

mathieui's avatar
mathieui committed
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
.. note:: If you set the :term:`exec_remote` option to ``true`` into the
    main configuration file, the command will be executed remotely
    (as explained in the :ref:`link-plugin` plugin help).

Options defined
---------------

.. glossary::
    :sorted:

    command
        The command to execute (with special keywords ``%{from}s`` and ``${body}s``)

    delay
        Delay after which :term:`after_command` must be executed.

    after_command
        Command to run after :term:`delay`. You probably want to clean up things.

81 82 83 84
    muc_too
        Boolean indicating whether new messages in Multi User Chat rooms should
        trigger a notification or not.

mathieui's avatar
mathieui committed
85 86
"""

87
from plugin import BasePlugin
88
from xhtml import get_body_from_message_stanza
89
from timed_events import DelayedEvent
louiz’'s avatar
louiz’ committed
90
import shlex
91 92
import common

louiz’'s avatar
louiz’ committed
93 94 95

class Plugin(BasePlugin):
    def init(self):
96 97
        self.api.add_event_handler('private_msg', self.on_private_msg)
        self.api.add_event_handler('conversation_msg', self.on_conversation_msg)
98 99
        if self.config.get('muc_too', False):
            self.api.add_event_handler('muc_msg', self.on_muc_msg)
100
        self.api.add_event_handler('highlight', self.on_highlight)
louiz’'s avatar
louiz’ committed
101 102 103 104 105

    def on_private_msg(self, message, tab):
        fro = message['from']
        self.do_notify(message, fro)

106 107 108 109
    def on_highlight(self, message, tab):
        fro = message['from'].resource
        self.do_notify(message, fro)

louiz’'s avatar
louiz’ committed
110 111 112 113
    def on_conversation_msg(self, message, tab):
        fro = message['from'].bare
        self.do_notify(message, fro)

114
    def on_muc_msg(self, message, tab):
115 116 117 118
        fro = message['from'].full
        muc = message['from'].bare
        whitelist=self.config.get('muc_list', '').split(',')

119 120 121 122
        # Prevent old messages to be notified
        # find_delayed_tag(message) returns (True, the datetime) or
        # (False, None)
        if not common.find_delayed_tag(message)[0]:
123 124 125
            # Only notify if whitelist is empty or muc in whitelist
            if whitelist == [''] or muc in whitelist:
                self.do_notify(message, fro)
126

louiz’'s avatar
louiz’ committed
127
    def do_notify(self, message, fro):
128
        body = get_body_from_message_stanza(message, use_xhtml=False)
louiz’'s avatar
louiz’ committed
129 130
        if not body:
            return
louiz’'s avatar
louiz’ committed
131 132
        command_str = self.config.get('command', '').strip()
        if not command_str:
133
            self.api.information('No notification command was provided in the configuration file', 'Warning')
louiz’'s avatar
louiz’ committed
134
            return
louiz’'s avatar
louiz’ committed
135 136 137 138
        command = [arg % {'body': body.replace('\n', ' '), 'from': fro} for arg in shlex.split(command_str)]
        self.core.exec_command(command)
        after_command_str = self.config.get('after_command', '').strip()
        if not after_command_str:
139
            return
louiz’'s avatar
louiz’ committed
140 141
        after_command = [arg % {'body': body.replace('\n', ' '), 'from': fro} for arg in shlex.split(after_command_str)]
        delayed_event = DelayedEvent(self.config.get('delay', 1), self.core.exec_command, after_command)
142
        self.api.add_timed_event(delayed_event)