From cf16d57e11e3b9649c87d1883338c0e1872927aa Mon Sep 17 00:00:00 2001 From: Jan Oliver Oelerich Date: Wed, 10 Oct 2012 16:27:08 +0200 Subject: [PATCH] initial --- .gitignore | 2 + README.md | 31 ++++++++++++++ mailchecker.py | 105 +++++++++++++++++++++++++++++++++++++++++++++++ statushandler.py | 63 ++++++++++++++++++++++++++++ wrapper.py | 37 +++++++++++++++++ 5 files changed, 238 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 mailchecker.py create mode 100644 statushandler.py create mode 100755 wrapper.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2f78cf5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +*.pyc + diff --git a/README.md b/README.md new file mode 100644 index 0000000..c55e249 --- /dev/null +++ b/README.md @@ -0,0 +1,31 @@ +# i3pystatus + +i3pystatus is a (hopefully growing) collection of python scripts for +status output compatible to i3status / i3bar of the i3 window manager. + +## Installation + +To install it, follow these steps: + + cd ~/.config/i3status/ + git clone git@github.com:janoliver/i3pystatus contrib + +Add the following to `~/.config/i3status/config`: + + general { + output_format = "i3bar" + colors = true + interval = 5 + } + +Change your i3wm config to the following: + + # i3bar + bar { + status_command i3status | python2 ~/.config/i3status/contrib/wrapper.py + position top + workspace_buttons yes + } + +And finally adjust the settings in `~/.config/i3status/contrib/wrapper.py` +as you like. diff --git a/mailchecker.py b/mailchecker.py new file mode 100644 index 0000000..ab66acc --- /dev/null +++ b/mailchecker.py @@ -0,0 +1,105 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import sys +import json +from datetime import datetime,timedelta +import imaplib + + +class MailChecker(object): + """ + This class handles mailservers and outputs i3status compatible + json data for the accumulated unread count. The mail server + functionality is implemented in the subclass MailChecker.MailServer + """ + + settings = { + 'color': '#ff0000', + 'servers': [] + } + + servers = [] + + def __init__(self, settings = None): + self.settings.update(settings) + + for server in settings['servers']: + srv = MailChecker.MailServer(server) + self.servers.append(srv) + + def output(self): + unread = 0 + for srv in self.servers: + unread += srv.get_unread_count() + + if not unread: + return None + + return {'full_text' : '%d new emails' % unread, + 'name' : 'newmail', + 'urgent' : 'true', + 'color' : self.settings['color']} + + class MailServer: + """ + This class provides the functionality to connect + to a mail server and fetch the count of unread emails. + When the server connection is lost, it returns 0 and + tries to reconnect. It checks every 'pause' seconds. + """ + + host = "" + port = "" + imap_class = imaplib.IMAP4 + username = "" + password = "" + connection = None + pause = 30 + unread_cache = 0 + last_checked = datetime.now() + + def __init__(self, settings_dict): + self.host = settings_dict['host'] + self.port = settings_dict['port'] + self.username = settings_dict['username'] + self.password = settings_dict['password'] + self.pause = settings_dict['pause'] + + if settings_dict['ssl']: + self.imap_class = imaplib.IMAP4_SSL + + self.last_checked = \ + datetime.now() - timedelta(seconds=self.pause) + + def get_connection(self): + if not self.connection: + try: + self.connection = self.imap_class(self.host, self.port) + self.connection.login(self.username, self.password) + self.connection.select() + except Exception: + self.connection = None + + try: + self.connection.select() + except Exception,e: + + print e + self.connection = None + + return self.connection + + def get_unread_count(self): + delta = datetime.now() - self.last_checked + + if delta.total_seconds() > self.pause: + unread = 0 + conn = self.get_connection() + if conn: + unread += len(conn.search(None,'UnSeen')[1][0].split()) + + self.unread_cache = unread + self.last_checked = datetime.now() + + return self.unread_cache \ No newline at end of file diff --git a/statushandler.py b/statushandler.py new file mode 100644 index 0000000..59614ee --- /dev/null +++ b/statushandler.py @@ -0,0 +1,63 @@ +#!/usr/bin/env python + +import sys +import json + +class I3statusHandler: + modules = [] + + def __init__(self): + pass + + def register_module(self, module): + """ Register a new module. """ + + # check if module implemented the + # correct functions + if not hasattr(module, 'output'): + raise Exception("Module %s does not implement \ + all the needed functions!".format(module)) + + self.modules.append(module) + + def print_line(self, message): + """ Non-buffered printing to stdout. """ + + sys.stdout.write(message + '\n') + sys.stdout.flush() + + def read_line(self): + """ Interrupted respecting reader for stdin. """ + + # try reading a line, removing any extra whitespace + try: + line = sys.stdin.readline().strip() + # i3status sends EOF, or an empty line + if not line: + sys.exit(3) + return line + # exit on ctrl-c + except KeyboardInterrupt: + sys.exit() + + def run(self): + self.print_line(self.read_line()) + self.print_line(self.read_line()) + + while True: + line, prefix = self.read_line(), '' + + # ignore comma at start of lines + if line.startswith(','): + line, prefix = line[1:], ',' + + j = json.loads(line) + + for module in self.modules: + output = module.output() + + if output: + j.insert(0, module.output()) + + # and echo back new encoded json + self.print_line(prefix+json.dumps(j)) diff --git a/wrapper.py b/wrapper.py new file mode 100755 index 0000000..c4f13e8 --- /dev/null +++ b/wrapper.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import mailchecker +from statushandler import I3statusHandler + +if __name__ == '__main__': + + status = I3statusHandler() + + #List the modules + mailsettings = { + 'color': '#ff0000', + 'servers': [ + { + 'host': 'www.testhost1.com', + 'port': '993', + 'ssl' : True, + 'username': 'your_username', + 'password': 'your_password', + 'pause': 20 + }, + { + 'host': 'www.testhost2.net', + 'port': '993', + 'ssl' : True, + 'username': 'your_username', + 'password': 'your_password', + 'pause': 20 + } + ] + } + mailchecker = mailchecker.MailChecker(mailsettings) + status.register_module(mailchecker) + + # start the handler + status.run()