scraps

Mostly descriptions and instructions for little bits of technology I've found useful.

Sunday, July 26, 2009

Read your friends' twitter updates in Google Reader

I try to use Google Reader as much as I can for following news, comics, blogs and websites - it's a huge timesaver over visiting lots of different websites every day, and also prevents me from forgetting about content I like.

I came up with this half-baked solution for reading my friends' twitter updates in Google Reader. The problem is that Google Reader does not support authenticated RSS feeds, which is required by twitter RSS feeds because your friends may not have made their updates available to the public. The solution I use is to proxy my twitter RSS feed through my own web server, transforming the authenticated feed into an unauthenticated one only accessible by Google Reader (kind of - it just checks the HTTP_USER_AGENT). Here's the python script I use.

from mod_python import apache
import urllib2

def auth_request(url, realm, user, password):
auth_handler = urllib2.HTTPBasicAuthHandler()
auth_handler.add_password(realm=realm,
uri=url,
user=user,
passwd=password)
opener = urllib2.build_opener(auth_handler)
return opener.open(url)

def twitter_rss(req):
req.add_common_vars()
if (req.subprocess_env.has_key("HTTP_USER_AGENT") and
req.subprocess_env["HTTP_USER_AGENT"].startswith("Feedfetcher-Google")):
req.content_type = "text/xml"
request = auth_request("http://twitter.com/statuses/friends_timeline/$YOUR_RSS_FEED_NUMBER.rss",
"Twitter API",
"$YOUR_TWITTER_LOGIN",
"$YOUR_TWITTER_PASSWORD")
req.write(request.read())
return apache.OK

req.content_type = "text/plain"
req.write(req.get_remote_host())
return apache.OK


You'll have to substitute $YOUR_RSS_FEED_NUMBER (search for the "RSS feed" link on your twitter home page), $YOUR_TWITTER_LOGIN, and $YOUR_TWITTER_PASSWORD in the script above. This uses apache2 and mod_python - I had to set up a directory on my web server with a mod_python handler by putting the following in my apache2 site config.

<Directory /var/www/matt/cgipy>
SetHandler mod_python
PythonHandler mod_python.publisher
# uncomment the following to figure out why it's not working
# PythonDebug On
</Directory>


Copy this python script into your mod_python-handled directory (also be sure to chmod +x), add the url to the python script as a Google Reader subscription, and you should be all set!

One downside is that Google Reader will only refresh the feed every 3 hours because there's only one subscriber - they seem to update more frequently for more popular RSS feeds. Also, you may be thinking, "Anyone can access this page by changing their HTTP_USER_AGENT!" You'd be right - in theory this opens up your friends' protected twitter updates for the world to see. So it's not a perfect solution, but I like that it lets me keep up with twitter from both desktop and mobile Google Reader, without having to visit yet another site or use yet another program.

Asus eee 1000 xmonad configs

I'm running Ubuntu 8.10 (Intrepid Ibex) on my Asus eee 1000, using the array.org kernel (highly recommended). I've been mostly happy with it - it provides a completely acceptable web browsing, ssh-ing and emacs text editing experience, and I'm much happier carrying it around on my back than my huge 15" MacBook Pro. Two of my major complaints, though, are that the screen is very small (1024 x 800) and the touchpad is very annoying.

I decided to try xmonad, a tiling window manager that lets me minimize both the amount of wasted space at the top and bottom of my screen (compared to GNOME) and the frequency with which I have to fight with the touchpad. I set up xmonad with a tabbed layout (the screen is way too small for tiling windows IMHO), a vertically-minimal xmobar with some basic information, and a runOrRaise prompt for starting programs. I've been using this configuration for a few months and I'm very happy with it. Check out some screenshots, and listed below are the configurations I'm using if you'd like to try it yourself.

xmonad.hs
import qualified Data.Map as M
import XMonad
import XMonad.Hooks.DynamicLog
import XMonad.Hooks.ManageDocks
import XMonad.Layout.Tabbed
import XMonad.Prompt
import XMonad.Prompt.RunOrRaise
import XMonad.Util.Run(spawnPipe)
import XMonad.Util.EZConfig(additionalKeys)
import System.IO

main = do
xmproc <- spawnPipe "/usr/local/bin/xmobar /home/matt/.xmobarrc"
xmonad $ defaultConfig {
manageHook = manageDocks <+> manageHook defaultConfig,
layoutHook = avoidStruts $ simpleTabbed,
logHook = dynamicLogWithPP $ xmobarPP {
ppOutput = hPutStrLn xmproc,
ppLayout = const "",
ppTitle = xmobarColor "green" "" . shorten 66
},
modMask = mod4Mask,
borderWidth = 1,
normalBorderColor = "#404040",
focusedBorderColor = "#808080",
keys = allKeys
}

allKeys x = M.union (keys defaultConfig x) (M.fromList (myKeys x))
myKeys x =
[ ((modMask x, xK_x), runOrRaisePrompt defaultXPConfig),
((modMask x .|. shiftMask, xK_q), spawn "gnome-session-save --kill") ]

.xmobarrc
Config { font = "-Misc-Fixed-Bold-R-Normal--13-120-75-75-C-70-ISO8859-1"
, bgColor = "black"
, fgColor = "grey"
, position = TopW L 90
, commands = [ Run Cpu ["-L","3","-H","50","--normal","green","--high","red"] 10
, Run Memory ["-t","Mem: %"] 10
, Run Swap [] 10
, Run Date "%a %b %_d %l:%M" "date" 10
, Run StdinReader
]
, sepChar = "%"
, alignSep = "}{"
, template = "%StdinReader% }{ %cpu% %memory% %swap% %date%"
}

.xsession
xrdb -merge .Xresources

trayer --edge top --align right --SetDockType true --SetPartialStrut true \
--expand true --width 10 --transparent true --tint 0x000000 --height 12 &

xsetroot -solid black

if [ -x /usr/bin/gnome-settings-daemon ] ; then
gnome-settings-daemon &
fi

if [ -x /usr/bin/nm-applet ] ; then
nm-applet --sm-disable &
fi

if [ -x /usr/bin/gnome-power-manager ] ; then
gnome-power-manager &
fi

exec xmonad

Followers