diff --git a/not2osd b/not2osd
new file mode 100755
index 0000000000000000000000000000000000000000..487f284cdd342b8448009757ef4c19055896db28
--- /dev/null
+++ b/not2osd
@@ -0,0 +1,181 @@
+#!/usr/bin/env python2
+
+#
+#   not2osd - Bridge from DBus notifications to osd
+#
+#   Copyright (c) 2009 by Henrik Hallberg (halhen@k2h.se) [program statnot]
+#   http://code.k2h.se
+#   Copyright (c) 2021 by Jiří Kalvoda (jirikalvoda@kam.mff.cuni.cz)
+#
+#   This program is free software; you can redistribute it and/or modify
+#   it under the terms of the GNU General Public License as published by
+#   the Free Software Foundation; either version 2 of the License, or
+#   (at your option) any later version.
+#
+#   This program is distributed in the hope that it will be useful,
+#   but WITHOUT ANY WARRANTY; without even the implied warranty of
+#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#   GNU General Public License for more details.
+#
+#   You should have received a copy of the GNU General Public License
+#   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+import dbus
+import dbus.service
+import dbus.mainloop.glib
+import gobject
+import os
+import subprocess
+import sys
+import thread
+import time
+from htmlentitydefs import name2codepoint as n2cp
+import re
+
+
+
+def strip_tags(value):
+  "Return the given HTML with all tags stripped."
+  return re.sub(r'<[^>]*?>', '', value)
+
+# from http://snipplr.com/view/19472/decode-html-entities/
+# also on http://snippets.dzone.com/posts/show/4569
+def substitute_entity(match):
+  ent = match.group(3)
+  if match.group(1) == "#":
+    if match.group(2) == '':
+      return unichr(int(ent))
+    elif match.group(2) == 'x':
+      return unichr(int('0x'+ent, 16))
+  else:
+    cp = n2cp.get(ent)
+    if cp:
+      return unichr(cp)
+    else:
+      return match.group()
+
+def decode_htmlentities(string):
+  entity_re = re.compile(r'&(#?)(x?)(\w+);')
+  return entity_re.subn(substitute_entity, string)[0]
+
+
+
+class NotificationFetcher(dbus.service.Object):
+    _id = 0
+
+    @dbus.service.method("org.freedesktop.Notifications",
+                         in_signature='susssasa{ss}i',
+                         out_signature='u')
+    def Notify(self, app_name, notification_id, app_icon,
+               summary, body, actions, hints, expire_timeout):
+        print "app_name", app_name
+        print "notification_id", notification_id
+        print "app_icon", app_icon
+        print "summary", summary
+        print "body", body
+        print "actions", actions
+        print "expire_timeout", expire_timeout
+        su = strip_tags(unicode(summary)).split("\n")
+        bo = strip_tags(unicode(body)).split("\n")
+        for i in range(len(su)):
+            if su[i]!="" and su[i][0]=='-':
+                su[i] = ' '+su[i];
+        for i in range(len(bo)):
+            if bo[i]!="" and bo[i][0]=='-':
+                bo[i] = ' '+bo[i];
+        if (expire_timeout <= 0) or (expire_timeout > 20000):
+            expire_timeout = 5000
+        cmd = ["osdc","--duration="+str(expire_timeout),"--min-duration=1000","--color=blue","--outline-color=red"] + su + ["--outline-color=black"] + bo
+        subprocess.call(cmd)
+
+
+        if not notification_id:
+            self._id += 1
+            notification_id = self._id
+			
+        text = ("%s %s" % (summary, body)).strip()
+        add_notification( [notification_id,
+                          text[:NOTIFICATION_MAX_LENGTH],
+                          int(expire_timeout) / 1000.0] )
+        return notification_id
+		
+    @dbus.service.method("org.freedesktop.Notifications", in_signature='', out_signature='as')
+    def GetCapabilities(self):
+        return ('actions', 'body', 'body-hyperlinks', 'body-markup')
+	
+    @dbus.service.signal('org.freedesktop.Notifications', signature='uu')
+    def NotificationClosed(self, id_in, reason_in):
+        pass
+
+    @dbus.service.method("org.freedesktop.Notifications", in_signature='u', out_signature='')
+    def CloseNotification(self, id):
+        pass
+
+    @dbus.service.method("org.freedesktop.Notifications", in_signature='', out_signature='ssss')
+    def GetServerInformation(self):
+      return ("statnot", "http://code.k2h.se", "0.0.2", "1")
+
+if __name__ == '__main__':
+    for curarg in sys.argv[1:]:
+        if curarg in ('-v', '--version'):
+            #print "%s CURVERSION" % sys.argv[0]
+            sys.exit(1)
+        elif curarg in ('-h', '--help'):
+            #print "  Usage: %s [-h] [--help] [-v] [--version] [configuration file]" % sys.argv[0]
+            #print "    -h, --help:    Print this help and exit"
+            #print "    -v, --version: Print version and exit"
+            #print ""
+            #print "  Configuration:"
+            #print "    A file can be read to set the configuration."
+            #print "    This configuration file must be written in valid python,"
+            #print "    which will be read if the filename is given on the command line."
+            #print "    You do only need to set the variables you want to change, and can"
+            #print "    leave the rest out."
+            #print ""
+            ##print "    Below is an example of a configuration which sets the defaults."
+            #print ""
+            #print "      # Default time a notification is show, unless specified in notification"
+            #print "      DEFAULT_NOTIFY_TIMEOUT = 3000 # milliseconds"
+            #print "      "
+            #print "      # Maximum time a notification is allowed to show"
+            ###print "      MAX_NOTIFY_TIMEOUT = 5000 # milliseconds"
+            #print "      "
+            #print "      # Maximum number of characters in a notification. "
+            #print "      NOTIFICATION_MAX_LENGTH = 100 # number of characters"
+            #print "      "
+            #print "      # Time between regular status updates"
+            #print "      STATUS_UPDATE_INTERVAL = 2.0 # seconds"
+            #print "      "
+            ##print "      # Command to fetch status text from. We read from stdout."
+            #print "      # Each argument must be an element in the array"
+            ##print "      # os must be imported to use os.getenv"
+            ##print "      import os"
+            #print "      STATUS_COMMAND = ['/bin/sh', '%s/.statusline.sh' % os.getenv('HOME')] "
+            ##print ""
+            #print "      # Always show text from STATUS_COMMAND? If false, only show notifications"
+            #print "      USE_STATUSTEXT=True"
+            #print "      "
+            #print "      # Put incoming notifications in a queue, so each one is shown."
+            #print "      # If false, the most recent notification is shown directly."
+            #print "      QUEUE_NOTIFICATIONS=True"
+            #print "      "
+            #print "      # update_text(text) is called when the status text should be updated"
+            #print "      # If there is a pending notification to be formatted, it is appended as"
+            #print "      # the final argument to the STATUS_COMMAND, e.g. as $1 in default shellscript"
+            ##print ""
+            #print "      # dwm statusbar update"
+            #print "      import subprocess"
+            #print "      def update_text(text):"
+            #print "          subprocess.call(['xsetroot', '-name', text])"
+            sys.exit(1)
+
+    dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
+    session_bus = dbus.SessionBus()
+    name = dbus.service.BusName("org.freedesktop.Notifications", session_bus)
+    nf = NotificationFetcher(session_bus, '/org/freedesktop/Notifications')
+
+    context = gobject.MainLoop().get_context()
+    
+    while 1:
+        context.iteration(True)
+