📜 ⬆️ ⬇️

Gmail Notifier DIY

image I started settling in under Linux and found that I greatly lack those beautiful popups, notifying of the arrival of new mail, which Google Talk can show under Windows. Googling found several ready-made scripts that allow you to implement such pop-ups (among others: bash-script, bash-script + python-script, plus pidgin can check mail), but I didn’t like all approaches slightly and needed updating with a file, so I I decided to do everything from scratch (let it be ugly, but my own!). About the things that I encountered in the process and will be discussed ...



Background: the choice of WM (window manager)

')
In Linux, managing windows, drawing any frames and system menus is given to the X server by the so-called window managers . Therefore, under Linux, unlike Windows, you can flexibly customize the appearance of windows, as well as their behavior and location.

I must say that all the “abnormal programmers” have their own window managers for Linux. The haskellists have xmonad , and the lua's like me have Ion and the modestly named awesome . Finally, C-Schnick has an ultra-light dwm , the only way to reconfigure that is editing and reassembling.

All of the above-mentioned window managers belong to the tiling window manager class (Wikipedia offers the translation “frame (or mosaic) window manager” ), a small overview of such managers has recently been on Habré . A distinctive feature of such WM is that individual windows are placed on the screen without overlaps, covering it like a mosaic:



This screenshot shows that as a Wiccan and lunopath , as well as a person who respects modesty, I settled on awesome.

In general, awesome has some problems with documentation (well, well, this is the scourge of many not only open, but also proprietary projects). The API is well documented, but some things have to be guessed or fumbled on the wiki.

A detailed procedure for installing the latest versions on Ubuntu is described, for example, here .

Display notifications


I love to move in the development of backwards, so I first became interested in the question: “how can I show a pop in awesome?” . The answer was found quickly: using the built-in library naughty (I think the reader has already caught the general direction of the names?). For example, if you execute such code in the context of awesome:
 naughty.notify {
     title = title, 
     text = text, 
     timeout = 10, 
     fg = "# afbe01", 
     width = 500, 
     icon = icon_big,
     icon_size = 32
 }

then in a given place on the screen a moderately beautiful popup pops up with the title title , the text of the text message and the icon_big icon.

You can execute Lua code in the awesome context using the awesome-client utility. In fact, this is a shell that accepts lua scripts as input (one at a line) and sequentially executes them.

Thus, if you want to show a popup from some independently working program / script, you need to substitute their values ​​for title, text and icon_big, then transfer the resulting line (without line breaks!) To the input awesome-client.

Since I write most of the scripts on lua and constantly alternate normal lua code and forming lines for awesome-client, I don’t want to, I used a special metatable magic to write a mechanism that allows you to transparently call code in an awesome context. It is enough to write in the script:
 local naughty = proxy "naughty"

and further work with table fields (calls and assignments) naughty will be transparently performed in an awesome context.

And naughty is friends with dbus , but so far I have managed without it.

Us a letter?


So, I can show a notification, but it is completely incomprehensible to me where to get information about the arrival of a new letter. You can, of course, allow POP access to the box and check its contents every N seconds or (prompted by @merlin_rterm), you can open IMAP access and pick up, get notifications ( [RFC 2177] IMAP 4 IDLE Command ). You can take the Atom feed of the mailbox and parse it every M seconds with a python script or use bash & wget & grep-fu . None of these solutions seemed elegant enough. I entered into Google a couple of requests that contained, among other things, the words “gmail” , “api” and “lua” , but received only a fig. My despair was so great that I wanted to throw everything to hell and hang myself to seduce myself into the pythonists ’camp, but then a bright thought came to my head: once google talk shows notifications, once pidgin checks mail, it means it’s somehow connected with the XMPP protocol, popularly known as Jabber, on top of which Google Talk is implemented! Inspired by this revelation, I entered google talk api into google and after a couple of mouse clicks I found myself on a page with a talking name Gmail Notifications .

Even to the Finnish rocks brown I treat with a pun.


STANCE and (obsolete) stanz, stanza, (fr. Stance from it. Stanza) (lit.). In verses - stanza, which is a complete syntactic period.

XMPP is such a fun protocol in which Romeo and Juliet clients and servers exchange XML stanza between themselves. [RFC 3920] XMPP Core describes three types of stanzas: <iq /> (Info / Query), <presence /> (actually user information), and <message /> . In general, XMPP Core is quite a simple protocol, but I didn’t smile at all to botch standards and was busy with parsing XML, TLS, SASL and other details, and implementing everything from scratch, so I reopened Google and told him xmpp lua .

The very first link led me to the Verse page - a lua-library built over Str <> phe (again with a slope!), Which in turn is a C-library for working with XMPP. Strophe takes all the low-level work: connection (with TLS support), authorization (SASL) and parsing XML, as well as processing core stans. Verse offers a convenient way to support extensions (XEP = XMPP Extension Protocols, formerly known as JEP), the ability to register event handlers that are triggered at the time of the arrival of a certain form.

My joy could not be described by any stanzas ... I quickly downloaded both libraries. Collected Strophe, tried to collect Verse and broke off. It turned out that to build Verse, you need to patch Strophe in a special way ... Popatchil, rebuilt, rebuilt ... Hooray, the example works!

Google, Google, I am Aleph! Welcome, welcome!


I try to connect to Google:

 conn = verse.connect ("mister.aleph@gmail.com/epsilon3", password, handler, "talk.google.com");


mister.aleph@gmail.com/epsilon3 is my Jabber ID. A strange suffix / epsilon3 identifies the resource. This allows one mister.aleph@gmail.com to log in to Jabber from several different places.

Run the script. I get a fig. It turns out that by default Strophe is going without TLS support, so you have to rebuild everything again. The benefit is not written in C ++ with boost :: mpl, so I don’t even have time to drink tea during the build.

Now everything is logged in, and I even see how I get stanza <presence /> from my contacts. However, I am not interested in these stanzas, for I do not intend to make a full-fledged chat (I will probably do a defective, but later). I am only interested in the stanzas described in the Gmail Notifications JEP.

I register in Verse a new protocol with two events:

 local gmail = {xmlns = "google: mail: notify"};
 verse.protocols.gmail = gmail;

 gmail.events = {
   response = {
     {name = "iq";  type = "result";  xmlns = gmail.xmlns};
     mailbox = "/ iq / mailbox";
   };

   newmail = {
       {name = "iq";  type = "set"};

       id = "/ iq / @ id";
       newmail = "/ iq / new-mail";
   };
 }


The response event will be triggered when the server sends me a stans response to my mailbox request. In the mailbox node, threads will be described, with detailed information (senders, tags, the date of the last message). In the event handler for this event, I will sort through these threads and display notifications about new mail using naughty and show the total counter of unread emails in the tray.

The newmail event will be triggered when the server sends me a stanza-notification of changes in the mailbox. In response to this stanza, I will send a stanza-request for information about the contents of the box.

Actually the full code can be viewed here .

By the way, in the description of Gmail Notifications JEP it is indicated that you can request not only unread messages, but generally make a completely arbitrary request, for example, ask all threads marked with #lua label ( "label: #lua" ).

The fairy tale has a quick effect, but it is not done quickly.


I run the script, get a couple of popups and a segmentation fault, as soon as luavm wanted to collect garbage. It looks like Matthew Wild (by Verse), knowingly warns on the main page:
Please note that this is ALPHA status software. It does have crasher bugs, which I am aware of ...

But not on those attacked, we Russian all crazy Luashniki everything on the shoulder. I arm myself with a magic valgrind , gdb, piece of paper, a twenty-sided dice, a rosary, a bottle of brandy left with a NG, and a brain ... After half an hour, the segmentation fault disappears and the memory almost stops flowing away in an unknown direction.

Registration


The designer, illustrator or artist of me is none, so I turned back to Google and found on the site of Shris Ivarson a set of multi-colored gmail-ovsky icons (red, blue, green, black, pink) in ICNS format. I overtook these icons in PNG using the icns2png utility. I took the text color from the wonderful Daft Punk wallpaper .

Total


I shift the finished script along with the icons in ~ / .config / awesome / gmail and add its launch to rc.lua:



Victory!

Some trite conclusions

Source: https://habr.com/ru/post/48370/


All Articles