Emacs IRC (ERC) with Noticeable Notifications

August 7, 2008 at 12:35 am | In Emacs, Linux, Lisp, Python | 2 Comments

I use ERC for all my IRC chatting. I finally got fed up with not noticing someones message because I didn't have emacs focused. So I spent my evening concocting a more noticeable messaging system through Pymacs and libnotify.

Half way though implementing this, wouldn't you know it, I found ErcPageMe which does exactly what I wanted. I figured I was learning quite a bit and I continued writing my own version. I expanded on their code and (at least for me) made some improvements. So kudos go to whoever wrote ErcPageMe :)

The following code will pop up a message on your gnome desktop alerting you whenever you receive a personal message or when someone mentions your nickname in a channel. It also avoids notification for the same user in the same channel if they triggered a message within the last 30 seconds.

Emacs ERC Notification through libnotify

Here is my lisp and embedded python/pymacs code:


(defun notify-desktop (title message &optional duration &optional icon)
  "Pop up a message on the desktop with an optional duration (forever otherwise)"
  (pymacs-exec "import pynotify")
  (pymacs-exec "pynotify.init('Emacs')")
  (if icon
      (pymacs-exec (format "msg = pynotify.Notification('%s','%s','%s')"
                           title message icon))
    (pymacs-exec (format "msg = pynotify.Notification('%s','%s')" title message))
    )
  (if duration
      (pymacs-exec (format "msg.set_timeout(%s)" duration))
    )
  (pymacs-exec "msg.show()")
  )

;; Notify me when someone wants to talk to me.
;; Heavily based off of ErcPageMe on emacswiki.org, with some improvements.
;; I wanted to learn and I used my own notification system with pymacs
;; Delay is on a per user, per channel basis now.
(defvar erc-page-nick-alist nil
  "Alist of 'nickname|target' and last time they triggered a notification"
  )
(defun erc-notify-allowed (nick target &optional delay)
  "Return true if a certain nick has waited long enough to notify"
  (unless delay (setq delay 30))
  (let ((cur-time (time-to-seconds (current-time)))
        (cur-assoc (assoc (format "%s|%s" nick target) erc-page-nick-alist))
        (last-time))
    (if cur-assoc
        (progn
          (setq last-time (cdr cur-assoc))
          (setcdr cur-assoc cur-time)
          (> (abs (- cur-time last-time)) delay))
      (push (cons (format "%s|%s" nick target) cur-time) erc-page-nick-alist)
      t)
    )
  )
(defun erc-notify-PRIVMSG (proc parsed)
  (let ((nick (car (erc-parse-user (erc-response.sender parsed))))
	(target (car (erc-response.command-args parsed)))
	(msg (erc-response.contents parsed)))
    ;;Handle true private/direct messages (non channel)
    (when (and (not (erc-is-message-ctcp-and-not-action-p msg))
               (erc-current-nick-p target)
	       (erc-notify-allowed nick target)
	       )
      ;Do actual notification
      (ding)
      (notify-desktop (format "%s - %s" nick
                              (format-time-string "%b %d %I:%M %p"))
                      msg 0 "gnome-emacs")
      )
    ;;Handle channel messages when my nick is mentioned
    (when (and (not (erc-is-message-ctcp-and-not-action-p msg))
               (string-match (erc-current-nick) msg)
               (erc-notify-allowed nick target)
	       )
      ;Do actual notification
      (ding)
      (notify-desktop (format "%s - %s" target
                              (format-time-string "%b %d %I:%M %p"))
                      (format "%s: %s" nick msg) 0 "gnome-emacs")
      )
    )

  )

(add-hook 'erc-server-PRIVMSG-functions 'erc-notify-PRIVMSG)

2 comments - Leave a comment

cycle_xrandr.py : dual and single displays on Ubuntu

July 10, 2008 at 6:24 am | In Linux, Python | No Comments

Linux power management has gotten good recently. My last two laptops (HP dv9000 and Macbook Pro) have supported hardware suspend mode out of the box. I'm impressed!

Being that I hardly ever turn off the laptop (I just suspend now) I'm left with an annoyance: I use two displays at work and one everywhere else. In Ubuntu, I was easily able to setup dual and single modes such that when I boot up, Xorg detects how many displays are connected appropriately. But now that I don't turn off the machine, I want to be able to just plug in another monitor and go. I don't want to have to reboot the computer. I don't even want to have to log out. I want to plug the monitor in, leave all my apps running and in the state they are in.

Xrandr does this and it works great. But what if I'm in dual display mode but I only actually have one monitor connected? Can I get to an open terminal to use xrandr? Easily? Probably not.

I wrote the following python script to take care of this. It detects all of the modes that xrandr knows about and cycles to the next size listed. I then bind this script to a custom keyboard shortcut so I don't have to type or even see anything on the screen:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

__author__ = "Ryan McGuire (ryan@enigmacurry.com)"
__date__   = "Thu Jul 10 15:27:18 2008"

"""Cycle through all screen resolutions detected by xrandr"""

from subprocess import Popen, PIPE
import re

size_re = re.compile("^   ([0-9]*x[0-9]*)\W*[0-9]*\.[0-9]*(\*)?")

def list_sizes():
    """List all sizes detected by xrandr,
    ordered by the next resolution to cycle to"""
    p1 = Popen(['xrandr'], stdout=PIPE)
    sizes = []
    current_size_index = 0
    for line in  p1.communicate()[0].split("\n"):
        m = size_re.match(line)
        if m:
            sizes.append(m.group(1))
            if m.group(2) == "*":
                current_size_index = len(sizes) - 1
    return sizes[current_size_index+1:] + sizes[:current_size_index+1]

if __name__ == '__main__':
    Popen(['xrandr','-s',list_sizes()[0]])

No comments - Leave a comment

New Slacker Screenlet released

April 4, 2008 at 10:43 pm | In Linux, Python | 9 Comments

Check it out: I updated my Slacker Screenlet today.

New in this version:

  • Bug fixed where the screenlet-manager would respawn infinitely
  • Integrated LastSlacker support

You can read more about the original version in my previous post.

LastSlacker is a way to scrobble what you listen to on Last.FM. This lets you share a log of what you listen to with friends. I've been meaning to add this feature for a long time now, until today it's been in a sorta working state for months! It feels good to have finally gotten this project pretty much finished.


9 comments - Leave a comment

Backing up my (online) brain

February 22, 2008 at 11:22 pm | In Backups, Gmail, Linux | 3 Comments

Files from my computer are disappearing.

No worries though, this is intentional.

As time goes on, more and more of my files are ending up in places like:

  • Google
  • Flickr
  • Del.icio.us
  • Facebook

And things are great. I can access these services from anywhere in the world, from any computer. What a great time to be alive!

But there is a bit of uneasiness in the back of my mind about all of this. Yes, these services liberate me (as well as my data), but at the same time, I've become a new breed of slave — my data is no longer mine to control.

Privacy concerns aside, the biggest thing that haunts me is what if one of these services were to blow up? My data would be gone. When the data resided on my computer I could back it up myself anytime I wanted and have some sense of safety. With data on Google's server, honestly I feel pretty darn safe, but the cost of losing my data is still quite high.

My goal: Get my data back into my hands.

I'd like to start writing up my experiences on wrangling all of my data from my online services back onto media I control.

If you want to follow along, I'll be tagging these posts 'Backups'.

Gmail

The first service I'll start with is Gmail. Google, in the realm of free mail hosts, is very accommodating when it comes to accessing your mail in bulk. They have both POP3 and IMAP access. Retrieving your mail with any number of clients is trivial.

But there's more to Gmail than just your email: tags. POP3 won't get the tags, but IMAP will organize tags into folders. However, most IMAP clients only download messages on-the-fly as you read them, not all at once (like for backups).

Solution: OfflineIMAP.

OfflineIMAP will completely download all your Gmail messages into folders corresponding to all your tags. It actually does much more than this, OfflineIMAP is a full two-way synchronization of your email. Once you've downloaded your email you can take it with you while you're offline, read it, delete it and when you come back online you synchronize with gmail again deleting those same messages off of the server and retrieving new messages.

OfflineIMAP works really well for it's stated purpose: using IMAP offline. It is also useful for backing up IMAP accounts but you have to understand how it works so that you don't accidentally start deleting mail from your gmail account. Since we're using OfflineIMAP as a backup device instead of a tool to read our email I would recommend that you never open the email that it downloads with any sort of mail reader. If you do, and you accidentally move messages to a different location (mutt does this to read messages for instance), OfflineIMAP might think you deleted the message and it will delete the same message off your server (In Gmail's case it actually just removes the tag and keeps the message in All Mail, but still..) If you ever need to use the downloaded email, its safer to use a copy instead.

Caveat Emptor. Onward to configuring OfflineIMAP.

On Ubuntu:

sudo apt-get install offlineimap

Create a file called ~/.offlineimaprc :

[general]
accounts = GMail
maxsyncaccounts = 3

[Account GMail]
localrepository = Local
remoterepository = Remote

[Repository Local]
type = Maildir
localfolders = /storage/Gmail_Backup

[Repository Remote]
type = IMAP
remotehost = imap.gmail.com
remoteuser = your_username@gmail.com
remotepass = your_password
ssl = yes
maxconnections = 1

#Setting realdelete = yes will Really Delete email from the server.
#Otherwise "deleting" a message will just remove any labels and
#retain the message in the All Mail folder.
realdelete = no

The things you need to change are:

  • localfolders - This is the full path to where it will save the email
  • remoteuser - This is your gmail email address
  • remotepass - This is your gmail password (required for automated backups, otherwise it asks everytime)

You can now run offlineimap and you should start to see it download your email. By default, OfflineIMAP gives you a graphical or textual interface that shows you what it is doing. This is good especially for the first time you download your email.

After you've downloaded all of your email, you'll want to automate the task so it runs at least every day:

Put the following in your crontab:

00 23 * * * offlineimap -u Noninteractive.Quiet

This will run OfflineIMAP everyday at 11PM.

Again, because OfflineIMAP is not technically a backup solution in itself, you might also care to make a seperate rsyncd copy of the mail somewhere else:

rsync -a /storage/Gmail_Backup/ /storage/Gmail_Backup_Copy

You can similarly run rsync in your crontab after your offlineimap finishes. By making this seperate copy, you avoid the possible deletion of emails by OfflineIMAP. This second copy will also retain messages that you delete later on in Gmail (The offlineimap syncd copy will not). This may or may not be what you want.

Stay tuned for the next installment: Flickr backups!


3 comments - Leave a comment

Slacker Screenlet

November 20, 2007 at 12:54 pm | In Linux, Python | 2 Comments

Showing of the Slacker Screenlet

Having an absurdly large music collection can sometimes have it's downsides. Slacker is a nice way to listen to music when you can't decide what to listen to. Like with Pandora or Last.fm, you can create your own radio station by telling the player what kind of music you like and the player will automatically choose music to play for you. With Slacker, you can customize how much or how little new music you want to allow into the mix, which is the main reason I prefer it over Pandora.

On Windows, Slacker has created a nice standalone player. On Linux or Mac you're stuck with the web player. The nice thing about a standalone player is it won't interfere with my habit of closing my browser (thus killing my music). I decided I needed to find a way to separate the player from my main browser.

Screenlets are little, graphical, single-purpose eye-candy (written in Python :)). They can do things like show you the time or the current weather forecast, CPU load, the word of the day etc. Compiz allows these applications to run in their own layer such that they can appear and disappear quickly with the press of a button. They are quick and easy to get to, but stay out of your way when not needed.

I decided a screenlet for Slacker would be ideal, so I wrote one.

You can download my Slacker Screenlet for yourself.

Also see the following:


2 comments - Leave a comment

Building Multi-TTY Emacs from CVS on Ubuntu Gutsy Gibbon

October 21, 2007 at 6:25 pm | In Emacs, Linux | 6 Comments

(Historical note May 2008: The build instructions below, while they should still work, are unnecessary as Multi-TTY has been merged into the main Emacs 23 branch and is available in ubuntu repositories: apt-get install emacs-snapshot)

Last spring I wrote an article about Multi-TTY Emacs. I had promised that I would update instructions for building it on Ubuntu, but since then I have been mainly using Gentoo on my laptop and never got around to updating it. Sorry :)

I switched to Ubuntu Gutsy Gibbon yesterday. I also got Multi-TTY Emacs running, and here's the video to prove it (If this is too small to see, download the original ogg theora version) :

Building CVS Emacs the old fashioned way

For those of you that want the easy way out, I've prebuilt an emacs CVS package that includes the Multi-TTY patch. I've tested that the package works on both Gutsy as well as Feisty.

For those of you that would like to learn how this is done, here's my recipe:

Install all the dependencies

sudo apt-get install build-essential cvs texinfo libx11-dev libxpm-dev libjpeg-dev libpng-dev libgif-dev libtiff-dev libgtk2.0-dev checkinstall

Check out the Emacs code from CVS

cvs -z3 -d:pserver:anonymous@cvs.savannah.gnu.org:/cvsroot/emacs co emacs

Compile the source

cd emacs
./configure --with-gtk --prefix=/usr/local
make bootstrap
make

Checkinstall will build a basic emacs package for us with a minimum of fuss. We don't want to automatically install this package though for reasons we'll see below

sudo checkinstall -D --install=no

Checkinstall will ask you to change some values. I changed the maintainer email and the version number.

Checkinstall is great, and works for 99% percent of the packages that I've tried it with. Emacs is a bit different though — the package that checkinstall creates doesn't include everything that emacs requires, like all the .el files in the lisp folder among other things. So we have to edit the package a bit. For the following code, we'll assume the .deb file that checkinstall creates is just called "emacs_cvs-10202007-1_i386.deb", so adjust for whatever checkinstall called your .deb file:

Extract the data from the .deb

dpkg-deb -x emacs_cvs-10202007-1_i386.deb emacs_cvs-10202007-1_i386 #Or whatever your .deb is called

Extract the control information from the .deb

dpkg-deb -e emacs_cvs-10202007-1_i386.deb emacs_cvs-10202007-1_i386/DEBIAN

Now we need to add some of the files that checkinstall left out of the package

cp -a lisp/* emacs_cvs-10202007-1_i386/usr/local/share/emacs/23.0.50/site-lisp/
mkdir emacs_cvs-10202007-1_i386/usr/local/share/emacs/23.0.50/lisp
mkdir -p emacs_cvs-10202007-1_i386/usr/local/libexec/emacs/23.0.50/i686-pc-linux-gnu
cp -a etc emacs_cvs-10202007-1_i386/usr/local/share/emacs/23.0.50/
mkdir emacs_cvs-10202007-1_i386/etc
ln -s ../usr/local/share/emacs/23.0.50/etc/termcap.src emacs_cvs-10202007-1_i386/etc/termcap

Rebuild the modified package

dpkg-deb -b emacs_cvs-10202007-1_i386 emacs_modified.deb

To totally revolutionize the way you use Emacs, remember to check out my earlier post on Multi-TTY Emacs.


6 comments - Leave a comment

Recovering an Ncftp password

October 15, 2007 at 2:25 pm | In Linux, Python | No Comments

A coworker today asked me for the password to an FTP account we use. I didn't have any idea what it was because I just have it stored in an ncftp bookmark. I looked in my ~/.ncftp/bookmarks file and sure enough it was in there but it was encoded.

For future reference, I just wanted to document here that the password is simply base64 encoded. So it's pretty easy to decode using a bit of python:


>>> import base64
>>> base64.decodestring("TheEncodedPassword")


No comments - Leave a comment

Jungle Disk, Linux, and Mono

October 3, 2007 at 5:17 pm | In Linux | No Comments

Jungle Disk is a really neat application that allows you to store/backup files online using the Amazon S3 storage service. Basically it is a really inexpensive, fast and efficient way to save important files and access them from anywhere. On top of all that, it runs on just about every platform I would ever use: Linux, Mac OS X, and Windows. (In no order of preference, oh wait… )

If you're not much into computer science, that's pretty much all you need to know. If you are though, keep reading. :)

Jungle Disk is not open source. This would normally raise a huge dilemma for me. Without it being open source, how can I be absolutely sure that I will be able to retrieve my data in the future? The software could have a lockout feature of some kind hidden inside the application that would prevent me from getting my data. I refuse to be held hostage by stupid software!

(By no means am I an open source zealot purist that only uses free software. I use a few high quality closed source, commercial applications (VMWare workstation comes to mind) I just think that open source software tends to be of much higher quality and is able to mature a lot faster than your typical closed source variety. I also detest software patents.)

Jungle Disk is a bit different, even though it's closed source, they have released a portion of their code under the GPL: the decoding/retrieval code. What this proves is that your data can be retrieved without any dependence on closed source, secretive, software.

But I still don't want to take their word for it. So I set out to compile the code and try it myself. The code is written for Visual Studio (which only runs on windows), but that's not so much of a problem because the Mono project has brought most of the .NET framework to Linux.

Here's how to compile the Jungle disk retrieval code on Linux using Mono:

Install the latest version of Mono (I used 1.2.4. 1.2.2.1 didn't have all of the functionality I needed).

Download and extract the source code:


mkdir jds
cd jds
wget http://downloads.jungledisk.com/jungledisk/JungleDiskSourceExample.zip
unzip JungleDiskSourceExample.zip

Compile the code:


gmcs *.cs -r:System.Web -out:jungle_example.exe

Cool! It compiled without warnings nor errors.

Now try running it:

mono jungle_example.exe Your_S3_ID Your_S3_Key listbuckets

Error executing command: Error getting response stream (Trust failure): TrustFailure
System.Net.WebException: Error getting response stream (Trust failure): TrustFailure ---> System.Net.WebException: Error getting response stream (Trust failure): TrustFailure ---> System.IO.IOException: The authentication or decryption has failed. ---> Mono.Security.Protocol.Tls.TlsException: Invalid certificate received from server.

Ouch, we're not accepting the certificate for whatever reason. I don't know much about CSharp at all, but I found a page on the Mono project site that explains the problem and possible solutions. I applied the dumbest of all the possible solutions, which is to ignore the certificate trust issue altogether — caveat emptor. Here's my patch.

Apply the patch and recompile


wget http://tinyurl.com/2zutxz -O - | patch -p1
gmcs *.cs -r:System.Web -out:jungle_example.exe

Try running again:


mono jungle_example.exe Your_S3_ID Your_S3_Key listbuckets

If it lists your buckets, it worked!

You can also list files in the directory like so:


mono jungle_example.exe Your_S3_ID Your_S3_Key dir default /
mono jungle_example.exe Your_S3_ID Your_S3_Key dir default /pictures
mono jungle_example.exe Your_S3_ID Your_S3_Key dir default /music

You can retrieve your files like so:


mono jungle_example.exe ID Key getfile default "/Some File.zip" stuff.zip


No comments - Leave a comment

Streaming my music collection from anywhere.

September 18, 2007 at 11:27 pm | In Geeky, Linux | 6 Comments

I'm really in love with MPD. It lets me listen to my music anywhere and let's me use the same interface whether I'm stitting at home or at the office.

Recently I got a Nokia N800 which is great because it has wifi and and a great soundcard (even great speakers for a device of this size): it's begging to be a portable WIFI boombox.

The only problem is that MPD only supports Ogg vorbis through Icecast. Ogg vorbis is available through alsa applications on the N800 but most of the applications on the N800 are not alsa aware, which means that the nice little desktop applet for media streams won't communicate with MPD/Icecast.

I figured out recently that MPD CAN stream in Mp3 format (albeit in a bit of an indirect fashion):

MPD -> JACK -> oddcastv3 -> Icecast -> N800

The process was a little bit involved but not too terribly difficult once I figured out the correct pipeline. It's late and I don't really feel like writing up the whole process. If anyone is interested, make a comment and I'll post some more details.


6 comments - Leave a comment

Single sign-on everywhere

July 2, 2007 at 9:35 pm | In Linux, Python, Security | No Comments

Using a single password for every site you visit is really stupid. However, the alternative, making unique and secure passwords for every single site you visit can get tedious and unmanageable quickly.

A long while ago I started memorizing about 10 different passwords of various security levels, thinking that I can mitigate the risk by grouping similar sites together under one password. Memorizing 10 passwords really isn't that hard to do if you're dedicated.. but it still isn't that much smarter than a single password.

Then I started using KisKis, a Java application with which I could store all my passwords in an encrypted form. Although it's very secure and I liked it at first, it became really tedious to create a new entry every single time I made a new account somewhere and then to open the application up and look up the password every time I needed it. Add to that that I had to come up with a way of synchronizing my passwords on all of the machines I use - it became a real pain.

In about 2004, Firefox came along with the ability to store passwords in an encrypted form right inside your browser. What a godsend! Now I can make a new unique password for every site I visit and have the browser remember it for me.

However, I still have one problem. I use a lot of different computers and there is still no easy way to synchronize passwords between firefoxen on different machines.

A couple days ago I found this: PwdHash. PwdHash is a rather ingenious method for generating a unique, secure password for every single site you visit and yet the password is based on a function of a master password and the URL itself, so you don't even need to store the password, you can simply generate it whenever you need it. Almost magic really.

However, I still have a few security related issues with it. I think that it is likely there are websites out there that could implement a keystroke logger in JavaScript or even more likely in Macromedia flash. So the ideal solution for me is to have the same functionality outside of the browser completely. This isn't so bad when combined with Firefox's ability to cache passwords. To PwdHash's credit, the developers have gone to great lengths to make sure that PwdHash is secure, I'm just paranoid. It's my flaw, not theirs.

So here is my first stab at a PwdHash-like python application (Note that this is not compatible with PwdHash. I didn't want to have the temptation of using their software when I'm at some public terminal.) You can run this standalone on any unix like OS (I find it most convenient to have it long running inside of GNU Screen.)

How to run:

  • python site_pass.py
  • The first time it is run you have to create a master password
  • Now simply enter a URL (either a full URL like http://www.enigmacurry.com or simply enigmacurry.com)
  • It will generate an eight character password for you, now copy and paste that into your webbrowser and have firefox remember the password.
  • If you ever need to look up the password again, simply rerun the application, enter the URL, and you'll get the exact same password back again. Since it is a hash of your master password and the domain name you don't ever have to store the password (except in your browser for convenience). Just generate it again whenever you need it.
  • Do the same for all your other accounts and only look up your password again on other computers that have yet to cache the password

Now you'll never have to go through the process of "I forgot my password" again!

One word of caution however. Don't run this on your friend's box or any other place where you don't have full control of the root account. Your master password resides in memory and could be seen by root if he really wanted to.

Also, this is an alpha release (I wrote it in about an hour's time just today). Progressive.com, my car insurance doesn't like any punctuation in a password. If I find other sites that don't like the generated password I may have to modify the hashing function which would mean that any passwords created with this version would need to change to use a forthcoming version.

Download


No comments - Leave a comment
Next Page »

Powered by WordPress.
Entries and comments feeds. Valid XHTML and CSS. ^Top^
XML Sitemap