Wishful Coding

Didn't you ever wish your computer understood you?

Twitter in your inbox

I have been working on this for quite a while, with initial plans to make it a service. But I have changed plans, and am releasing it to the world.

What have I been working on, you ask? Not that I like sliced bread, but it's at least as good as that: It solves some problems while it introduces some others. It's a proxy between Twitter and your email client that sits on your computer or a server translating mail-language(POP, SMTP) to Twtter-language(REST API).

This way you can read your tweets in your mail client, store them in folders, search though them, and do all the other stuff mail clients are good at. It even allows you to reply and forward(retweet in Twitter lingo) tweets.

Here is how to get it. You go to my GitHub repo, which lives at the link below, and pull/download the code.

http://github.com/pepijndevos/Twemail

The next step is to get the dependencies, which include Twisted, OAuth2 and Twitter-Text-Python. You might try to use setup.py for that, but I'm not sure it works.

Now you simply run "twistd -ny twemail.tac" in the Twemail directory. If everything went well you'll see some messages rolling by about starting services.

Now all that remains is to configure your mail client with the following information"

  • email: username@twitter.com
  • password: your Twitter password
  • POP server: localhost on port 1100
  • SMTP server: localhost on port 2500

Here is how it works.

  • You can send messages by mailing post@twitter.com
  • Replying is done by hitting reply and replacing the subject line.
  • Retweets are done by forwarding to the sender of the tweet

In the future I also want to handle attachments and IMAP, but this is currently not included.
Posted

Search Google in running browser

After reading this hint, I wanted to get it working with my previous script to open links in the currently running browser.

I did not use OnMyCommand, but instead just made an Automator service. Here is how:

  • Open Automator and create a service
  • Set the type to text
  • Add the ‘Run shell script’ action
  • Set the shell to Python and the input to ‘as arguments’
  • Paste the script below

The script(this text serves only to satisfy Posterous’s parsing engine, which is seriously pissing me off):

import sys
import urllib
import webbrowser
webbrowser.open("http://www.google.nl/search?q=" + urllib.quote(sys.argv[1]))

Automator

You need to have my previous script installed to do the actual opening of the url. With some more trickery, it is even possible to add this service as a keyboard shortcut. I suggest you Google around a bit, and comment if you find something revolutionary.

Posted

Messing with the REPL with Twisted

I love to try out things on the REPL(read eval print loop) before I write scripts with them. The trouble with Twisted is that everything returns deferreds, and after your start the reactor, you can’t do anything anymore.

All this is solved by this one single command. It gives you a REPL powered by the Twisted event loop. To make things even better: It prints the value of a deferred once it is finished!

python -m twisted.conch.stdio

Added hint: Put this in a file, do “chmod +x” on it and put it on your $PATH.

Posted

Twisted SMTP server with authentication

This is the next post about Twisted, this time about Twisted.mail. After my Twisted project is done I'm going to contribute all my findings in some examples, docstrings and maybe even a howto. This post mainly serves as my notebook for things to remember about SMTP in Twisted.

This is a twistd app taken from the Twisted examples section, and modified to support authentication. Below you'll find all my notes.
  • If you want anything beyond a toy, you'll need to use ESMTP instead of SMTP
  • You need to have a portal with a realm and a checker set up to use the AUTH command
  • challengers are what provide the protocol for logging in, note that they are located in twisted.imap4
  • A portal takes one checker instance per authentication method, so you can have one for handling strange tokens, and one for regular username/password authentication, but not two for the same type.
  • Take a look at the source for InMemoryUsernamePasswordDatabaseDontUse, it is really simple to write your own checker.
Posted

Twitter xAuth in Python using Twisted and Twitty Twister

This is the first post in what will most likely be a series of posts related to Twitter, POP3, SMTP and Twisted. This post will be about asynchronous authentication with Twitter using xAuth.

xAuth is a simplified form of OAuth. Instead of doing the dance, you use credentials(like basic auth), but exchange them for an access token. You need to send a request to api@twitter.com to enable it.

This technique is also applicable to getting OAuth tokens, although that is more complicated.

We are going to use Twitty Twister, which is a Twitter lib for Twisted which supports signing OAuth requests. It does not, however, include code for obtaining an access token.

To obtain the token, it is suggested to use an external library. But since my app is 100% Twisted, and most OAuth libs blocking, I had a problem right there. We don’t want to have our nice reactor sit idle while we request our token, do we?

The solution is to use python-oauth to make the request, but just before we send it, you call request.to_postdata() and use twisted.web.client.getPage to send the request in an asynchronous manner.

My main resources where: http://dev.twitter.com/pages/xauth http://github.com/simplegeo/python-oauth2#readme http://twistedmatrix.com/documents/10.1.0/api/twisted.web.client.getPage.html

The resulting code(insert your key, secret, username and password):

from oauth import oauth
from twisted.web.client import getPage
from twisted.internet import reactor
from twittytwister import twitter
import cgi

url = "https://api.twitter.com/oauth/access_token"
consumer = oauth.OAuthConsumer("key", "secret")

def respond(tokens):
    params = cgi.parse_qs(tokens, keep_blank_values=False)
    key = params['oauth_token'][0]
    secret = params['oauth_token_secret'][0]
    print "got access"

    token = oauth.OAuthToken(key, secret)
    tweet = twitter.Twitter(consumer=consumer, token=token).update("Hello world! First tweet using xauth via #Twisted and #Python")
    tweet.addCallback(posted)

def posted(message):
    print "message:", message

request = oauth.OAuthRequest.from_consumer_and_token(oauth_consumer=consumer, http_method='POST', http_url=url,
    parameters = {
        'x_auth_mode': 'client_auth',
        'x_auth_username': 'username',
        'x_auth_password': 'password'
    }
)
request.sign_request(oauth.OAuthSignatureMethod_HMAC_SHA1(), consumer, None)

page = getPage(url, method='POST', postdata=request.to_postdata())
page.addCallback(respond)

print "running..."
reactor.run()
Posted

Save your date with PyMouse

With PyMouse this would never have happened. Don't risk your date, get PyMouse right now at its GitHub page! All that it takes to wiggle your pointer with PyMouse is this:
from pymouse import PyMouse
from time import sleep
from random import randint

m = PyMouse()
w, h = m.screen_size()
while True:
    try:
        m.move(randint(0, w), randint(0, h))
        sleep(20)
    except KeyboardInterrupt:
        print "Goodby!"
        break
Posted

Delicious bookmarks in Safari

I recently started using Delicious, and while they have a nice Firefox plugin and a bunch of bookmarklets, there is no easy way to get Delicious bookmarks into the Safari bookmarks bar. To get this done I wrote an Applescript with a little piece of Python to get Delicious bookmarks right in Safari. Here is how it looks:
Here is how to do it:
  1. Get the 2 scripts below and save them to a suitable location. You might want to place it in ~/Library/Scripts/Applications/Safari
  2. Edit the Applescript with the location of the Python script and the URL of your Delicious feed.
  3. Run the Applescript.
  4. Drag the resulting bookmarks folder or its content anywhere you want.
This will work for any RSS and maybe even Atom feed, you could even bookmark the feed of your Twitter account, for... *hum* easy access to individual tweets. This is the Python code:
import feedparser
print "<dl>"
for e in feedparser.parse( "http://feeds.delicious.com/v2/rss/pepijndevos" ).entries:
    print '<dt><a href="%s">%s</dt>' % (e.link, e.title.encode('ascii','ignore'))
print "</dl>"
Don't ask me why, but Safari needs broken html to import. Maybe because it is meant to import IE bookmarks? Anyway, this is the Applescript, the real thing:
do shell script "python ~/bin/feed2html.py > ~/Documents/delicious.html"
tell application "Safari"
        activate
        tell application "System Events"
                tell application process "Safari"
                        click menu item "Import Bookmarks…" of menu "File" of menu bar item "File" of menu bar 1
                        keystroke "g" using {shift down, command down}
                        keystroke "~/Documents/delicious.html"
                        keystroke return
                        keystroke return
                end tell
        end tell
end tell
Posted

PyMouse 1.0: Mouse control and events on Python

Since the first release of PyMouse I received a lot of feature requests. A list of all requests ordered by quantity:
  1. Receive mouse events
  2. Keyboard support
Digging around in platform specific APIs is not my favorite hobby, but when Aldo came to me with a good start for the Unix code, and copyrights send me some Windows code, I could do nothing but finish my Mac code and adapt everything to a common API. I'm also very grateful for the help from mailing list members of PyObjC and Python Xlib. Without their help I'd probably have to reverse the current version number. Keyboard support is not yet there, and I do not currently have time to write it. But I wrote down everything I know about the APIs I worked with on the PyMouse wiki, so it shouldn't be to hard to figure out for anyone willing to do it.

Download PyMouse

Posted

easy_install: no eggs found

I blogged about this before, but I was bitten by the same issue again! When you run an old version of setuptools and easy_install, you might get an error concerning eggs not being found. If you're having the same problem, the solution is simple:
easy_install -U setuptools
Posted

Tweet-o-Graph

Back in 2009 I made a hackish Python script that would generate a graph like the one shown here from your Twitter account. It turned out few people are willing to fumble with Python scripts to get 'just an image'. Luckily, I'm releasing a completely rewritten web app for the same cool idea! tweetograph.pepijn.cqhosting.nl Now with support for oauth, mentions, retweets, replies, gif, svg, dot, and a lot more. It is written with Python and web.py, using this script from my previous post.
Posted