ruby, twitter, growl
update : added icons to script
I know, I know, others have already done it, and you’re probably using a Twitter client that does it : piping the tweets to Growl.
Anyway, I wanted to get rid of my current Twitter client (1 window less) and get incoming tweets via Growl while ‘posting’ tweets via my Twitter home page.
So I started looking for a Ruby – Growl bridge and, as I’m a user of the fine LimeChat, I went straight to GrowlNotifier which is a spin off of the growl notification found in LimeChat.
GrowlNotifier is available as a gem, but, like LimeChat, requires RubyCocoa, then it’s just
sudo gem install --no-ri --no-rdoc \ rufus-verbs rufus-lru json_pure growlnotifier
(you can go for ‘json’ instead of ‘json_pure’ if you can)
and the script goes like :
require 'rubygems'
require 'rufus/verbs' # gem rufus-verbs
require 'rufus/lru' # gem rufus-lru
require 'json' # gem json or json_pure
require 'growl' # gem growlnotifier (and rubycocoa)
USER = ENV['TWUSER']
PASS = ENV['TWPASS']
raise 'TWUSER and/or TWPASS not set' \
if (not USER) or (not PASS)
GROWL = Growl::Notifier.sharedInstance
GROWL.register(
'twatch', ['twitter_update', 'issue'])
SEEN = LruHash.new(100) # max hash size
def fetch_tweets
res = Rufus::Verbs.get(
"https://twitter.com"+
"/statuses/friends_timeline.json",
:hba => [ USER, PASS ])
raise "#{res.code} != 200" \
if res.code.to_i != 200
o = JSON.parse(res.body)
o.each do |message|
id = message['id']
next if SEEN[id]
user = message['user']
u = user['profile_image_url']
u = OSX::NSURL.alloc.initWithString(u)
i = OSX::NSImage.alloc.initWithContentsOfURL(u)
GROWL.notify(
'twitter_update',
"#{user['name']} (#{user['screen_name']})",
message['text'],
:icon => i)
SEEN[id] = true
end
end
loop do
begin
fetch_tweets
rescue Exception => e
p e
GROWL.notify('issue', 'twatch issue', e.to_s)
end
sleep 45 # seconds
end
Next steps :
- clickable notifications for replies
- …
This is great, thanks. However since I don’t like to have the process just take 15M of RAM all day I updated the script so it will exit after each run and added it to launchd. To store the state of the program I used memcached (sudo port install memcached && sudo gem install memcache-client). And because I don’t want to store the plain password on disk I used KeyChain to retrieve it. Attached is a diff from your script:
0a1
> #!/usr/bin/env ruby
6a8
> require ‘memcache’
8,9c10,20
< USER = ENV['TWUSER']
def get_password key
> result = `/usr/bin/security 2>&1 >/dev/null find-internet-password -gs #{key}`
> if result =~ /password: “(.*)”/
> $1
> else
> raise “Unknown password”
> end
> end
>
> USER = ENV['TWUSER']
> PASS = get_password “twitter.com”
18c29,31
# SEEN = LruHash.new(100) # max hash size
> CACHE = MemCache.new ‘localhost:11211′, :namespace => ‘twitter’
> SEEN = (CACHE['seen'] || LruHash.new(100))
52,61c65,69
< loop do
<
< begin
< fetch_tweets
e
< p e
< GROWL.notify(‘issue’, ‘twatch issue’, e.to_s)
< end
<
begin
> fetch_tweets
> rescue Exception => e
> p e
> GROWL.notify(‘issue’, ‘twatch issue’, e.to_s)
62a71,72
>
> CACHE['seen'] = SEEN
The .plist file to launch
Label
com.gpetrica.twitter
Program
/usr/local/bin/twitter.rb
LowPriorityIO
Nice
10
StartInterval
60
LimitLoadToSessionType
Aqua
If you want files please let me know.
gpetrica
January 30, 2009 at 11:11 am
Hello,
thanks a lot, it’s very nice, I don’t have a memcache server around but the get_password/launchd leverage are great.
If you’d like to paste your files somewhere, I’d recommend http://gist.github.com
An example : http://gist.github.com/54409
You can post anonymously.
Best regards, thanks again,
John Mettraux
January 30, 2009 at 12:25 pm
So, I too didn’t want the script sitting around running, but rather on a 10 minute cron job, like my facebook growl updates.
So, a modified version that saves state to disk and quits:
http://pastie.org/426077
Disk serializing thanks to: http://marcuswestinblog.blogspot.com/2008/03/save-ruby-objects-to-disk-for-later.html
I’m a python hacker, not somuch with the ruby. Apologies for gross negligence.
Steven Skoczen
March 25, 2009 at 12:26 am
Hi Steven,
very nice, thanks for sharing !
John Mettraux
March 25, 2009 at 12:29 am
Just wanted to thank you for posting this — I was able to modify it into a highly useful little script that uses Prowl to push notifications about @replies to my iPhone. :)
David Edmiston
September 15, 2009 at 12:57 am
Very cool !
John Mettraux
September 15, 2009 at 12:57 am