Permalink
Browse files

Now you can tweet from Email and Gtalk via V2EX.

  • Loading branch information...
livid committed Aug 2, 2010
1 parent 37b6a51 commit ae4be58d56080c06ab78d1ed1da334ac72e73114
Showing with 132 additions and 2 deletions.
  1. +6 −1 app.yaml.example
  2. +2 −1 v2ex/babel/__init__.py
  3. +16 −0 v2ex/babel/da/__init__.py
  4. +108 −0 xmpp.py
View
@@ -109,8 +109,13 @@ handlers:
script: mail.py
login: admin
+- url: /_ah/xmpp/.+
+ script: xmpp.py
+ login: admin
+
- url: .*
script: main.py
inbound_services:
-- mail
+- mail
+- xmpp_message
View
@@ -1,6 +1,7 @@
-SYSTEM_VERSION = '2.3.0'
+SYSTEM_VERSION = '2.3.1'
import datetime
+import hashlib
from google.appengine.ext import db
from google.appengine.api import memcache
View
@@ -1,5 +1,7 @@
# coding=utf-8
+import hashlib
+
from google.appengine.ext import db
from google.appengine.api import memcache
@@ -48,5 +50,19 @@ def GetMemberByUsername(name):
one = q[0]
memcache.set('Member::' + str(name).lower(), one, 86400)
return one
+ else:
+ return False
+
+def GetMemberByEmail(email):
+ cache = 'Member::email::' + hashlib.md5(email.lower()).hexdigest()
+ one = memcache.get(cache)
+ if one:
+ return one
+ else:
+ q = db.GqlQuery("SELECT * FROM Member WHERE email = :1", str(email).lower())
+ if q.count() == 1:
+ one = q[0]
+ memcache.set(cache, one, 86400)
+ return one
else:
return False
View
108 xmpp.py
@@ -0,0 +1,108 @@
+#!/usr/bin/env python
+# coding=utf-8
+
+import logging
+import re
+import hashlib
+import urllib
+
+from v2ex.babel import Member
+
+from v2ex.babel.da import *
+
+from google.appengine.ext import db
+from google.appengine.ext import webapp
+from google.appengine.api import xmpp
+from google.appengine.api import urlfetch
+from google.appengine.ext.webapp import xmpp_handlers
+from google.appengine.ext.webapp.util import run_wsgi_app
+
+from twitter.twitter import Api
+from twitter.oauthtwitter import OAuthApi
+from twitter.oauth import OAuthToken
+
+from config import twitter_consumer_key as CONSUMER_KEY
+from config import twitter_consumer_secret as CONSUMER_SECRET
+
+from django.utils import simplejson as json
+
+def extract_address(raw):
+ if raw.find('/') == -1:
+ return raw
+ else:
+ return raw.split('/')[0]
+
+class XMPPHandler(webapp.RequestHandler):
+ def post(self):
+ message = xmpp.Message(self.request.POST)
+ to = extract_address(message.to.lower())
+ sender = extract_address(message.sender.lower())
+ member = GetMemberByEmail(sender)
+ if member:
+ if member.twitter_oauth == 1:
+ access_token = OAuthToken.from_string(member.twitter_oauth_string)
+ twitter = OAuthApi(CONSUMER_KEY, CONSUMER_SECRET, access_token)
+ status = message.body
+ result = None
+ if len(status) > 140:
+ status = status[0:140]
+ try:
+ if message.command is not None:
+ command = message.command.lower()
+ if command == 'mentions' or command == 'm' or command == 'r':
+ logging.info('About to get mentions for @' + member.twitter_screen_name)
+ statuses = twitter.GetReplies()
+ msg = ''
+ i = 0
+ for s in statuses:
+ msg = msg + '@' + s.user.screen_name + ': ' + s.text + "\n\n"
+ i = i + 1
+ if i > 5:
+ break
+ xmpp.send_message(message.sender, msg)
+ if command == 'search' or command == 'q' or command == 's':
+ q = re.findall('/' + command + ' (.+)', message.body)[0]
+ url = 'http://twitter.com/search.json?q=' + urllib.quote(q)
+ response = urlfetch.fetch(url)
+ logging.info(response.status_code)
+ data = json.loads(response.content)
+ msg = ''
+ i = 0
+ for s in data['results']:
+ msg = msg + '@' + s['from_user'] + ': ' + s['text'] + "\n\n"
+ i = i + 1
+ if i > 5:
+ break
+ xmpp.send_message(message.sender, msg)
+ else:
+ if status.lower() == 'ls':
+ logging.info('About to get home timeline for @' + member.twitter_screen_name)
+ statuses = twitter.GetHomeTimeline(count = 5)
+ msg = ''
+ i = 0
+ for s in statuses:
+ msg = msg + '@' + s.user.screen_name + ': ' + s.text + "\n\n"
+ xmpp.send_message(message.sender, msg)
+ else:
+ logging.info("About to send tweet: " + status)
+ result = twitter.PostUpdate(status.encode('utf-8'))
+ logging.info("Successfully tweet: " + status)
+ except:
+ logging.error("Failed to tweet for " + member.username)
+ if result is not None:
+ msg = 'OK: http://twitter.com/' + result.user.screen_name + '/status/' + str(result.id)
+ xmpp.send_message(message.sender, msg)
+ else:
+ logging.error("User " + sender + " doesn't have Twitter link.")
+ else:
+ logging.error("Cannot find a corresponding member for " + message.sender)
+
+application = webapp.WSGIApplication([
+ ('/_ah/xmpp/message/chat/', XMPPHandler)
+], debug=True)
+
+def main():
+ run_wsgi_app(application)
+
+if __name__ == "__main__":
+ main()

0 comments on commit ae4be58

Please sign in to comment.