tweetcast/twisted/server/tweetcast.py
author Raphael Velt <raph.velt@gmail.com>
Wed, 30 Nov 2011 12:11:59 +0100
changeset 403 dd1686ae5506
parent 311 13702105c5ee
permissions -rwxr-xr-x
minor changes
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
305
436a31d11f1d Ajout du streaming des tweets par WebSocket
Raphael Velt <raph.velt@gmail.com>
parents:
diff changeset
     1
#!/usr/bin/env python
436a31d11f1d Ajout du streaming des tweets par WebSocket
Raphael Velt <raph.velt@gmail.com>
parents:
diff changeset
     2
# -*- coding: utf-8 -*-
436a31d11f1d Ajout du streaming des tweets par WebSocket
Raphael Velt <raph.velt@gmail.com>
parents:
diff changeset
     3
436a31d11f1d Ajout du streaming des tweets par WebSocket
Raphael Velt <raph.velt@gmail.com>
parents:
diff changeset
     4
import anyjson
436a31d11f1d Ajout du streaming des tweets par WebSocket
Raphael Velt <raph.velt@gmail.com>
parents:
diff changeset
     5
from twisted.enterprise import adbapi
436a31d11f1d Ajout du streaming des tweets par WebSocket
Raphael Velt <raph.velt@gmail.com>
parents:
diff changeset
     6
from twisted.internet import reactor, task
436a31d11f1d Ajout du streaming des tweets par WebSocket
Raphael Velt <raph.velt@gmail.com>
parents:
diff changeset
     7
from twisted.internet.protocol import Protocol, Factory
436a31d11f1d Ajout du streaming des tweets par WebSocket
Raphael Velt <raph.velt@gmail.com>
parents:
diff changeset
     8
from autobahn.websocket import WebSocketServerFactory, WebSocketServerProtocol
436a31d11f1d Ajout du streaming des tweets par WebSocket
Raphael Velt <raph.velt@gmail.com>
parents:
diff changeset
     9
436a31d11f1d Ajout du streaming des tweets par WebSocket
Raphael Velt <raph.velt@gmail.com>
parents:
diff changeset
    10
connectstring = "dbname='tweet_live' user='postgres' host='localhost' password='doiteshimashite'"
309
e26d4354b578 Modifications mineures
Raphael Velt <raph.velt@gmail.com>
parents: 306
diff changeset
    11
columns = [ 'id', 'created_at', 'text', 'user_id', 'screen_name', 'profile_image_url' ]
e26d4354b578 Modifications mineures
Raphael Velt <raph.velt@gmail.com>
parents: 306
diff changeset
    12
selectcommon = "SELECT tweet_tweet.id, tweet_tweet.created_at, text, user_id, screen_name, profile_image_url FROM tweet_tweet JOIN tweet_user ON tweet_tweet.user_id = tweet_user.id"
311
13702105c5ee Réorganisation de Tweetcast
Raphael Velt <raph.velt@gmail.com>
parents: 309
diff changeset
    13
annotations = {
13702105c5ee Réorganisation de Tweetcast
Raphael Velt <raph.velt@gmail.com>
parents: 309
diff changeset
    14
	"positive" : '++',
13702105c5ee Réorganisation de Tweetcast
Raphael Velt <raph.velt@gmail.com>
parents: 309
diff changeset
    15
	"negative" : '--',
13702105c5ee Réorganisation de Tweetcast
Raphael Velt <raph.velt@gmail.com>
parents: 309
diff changeset
    16
	"reference" : '==',
13702105c5ee Réorganisation de Tweetcast
Raphael Velt <raph.velt@gmail.com>
parents: 309
diff changeset
    17
	"question" : '??'
13702105c5ee Réorganisation de Tweetcast
Raphael Velt <raph.velt@gmail.com>
parents: 309
diff changeset
    18
	}
305
436a31d11f1d Ajout du streaming des tweets par WebSocket
Raphael Velt <raph.velt@gmail.com>
parents:
diff changeset
    19
436a31d11f1d Ajout du streaming des tweets par WebSocket
Raphael Velt <raph.velt@gmail.com>
parents:
diff changeset
    20
dbpool = adbapi.ConnectionPool("psycopg2",connectstring)
436a31d11f1d Ajout du streaming des tweets par WebSocket
Raphael Velt <raph.velt@gmail.com>
parents:
diff changeset
    21
311
13702105c5ee Réorganisation de Tweetcast
Raphael Velt <raph.velt@gmail.com>
parents: 309
diff changeset
    22
class Tweet:
13702105c5ee Réorganisation de Tweetcast
Raphael Velt <raph.velt@gmail.com>
parents: 309
diff changeset
    23
13702105c5ee Réorganisation de Tweetcast
Raphael Velt <raph.velt@gmail.com>
parents: 309
diff changeset
    24
	def __init__(self, ligne):
13702105c5ee Réorganisation de Tweetcast
Raphael Velt <raph.velt@gmail.com>
parents: 309
diff changeset
    25
		self.data = dict((columns[i], str(ligne[i])) for i in range(len(columns)))
13702105c5ee Réorganisation de Tweetcast
Raphael Velt <raph.velt@gmail.com>
parents: 309
diff changeset
    26
		self.data['annotations'] = []
13702105c5ee Réorganisation de Tweetcast
Raphael Velt <raph.velt@gmail.com>
parents: 309
diff changeset
    27
		for a in annotations:
13702105c5ee Réorganisation de Tweetcast
Raphael Velt <raph.velt@gmail.com>
parents: 309
diff changeset
    28
			n = self.data['text'].count(annotations[a])
13702105c5ee Réorganisation de Tweetcast
Raphael Velt <raph.velt@gmail.com>
parents: 309
diff changeset
    29
			if n:
13702105c5ee Réorganisation de Tweetcast
Raphael Velt <raph.velt@gmail.com>
parents: 309
diff changeset
    30
				self.data['annotations'].append({
13702105c5ee Réorganisation de Tweetcast
Raphael Velt <raph.velt@gmail.com>
parents: 309
diff changeset
    31
					"name" : a,
13702105c5ee Réorganisation de Tweetcast
Raphael Velt <raph.velt@gmail.com>
parents: 309
diff changeset
    32
					"text" : annotations[a],
13702105c5ee Réorganisation de Tweetcast
Raphael Velt <raph.velt@gmail.com>
parents: 309
diff changeset
    33
					"count" : n
13702105c5ee Réorganisation de Tweetcast
Raphael Velt <raph.velt@gmail.com>
parents: 309
diff changeset
    34
				})
13702105c5ee Réorganisation de Tweetcast
Raphael Velt <raph.velt@gmail.com>
parents: 309
diff changeset
    35
13702105c5ee Réorganisation de Tweetcast
Raphael Velt <raph.velt@gmail.com>
parents: 309
diff changeset
    36
	def __repr__(self):
13702105c5ee Réorganisation de Tweetcast
Raphael Velt <raph.velt@gmail.com>
parents: 309
diff changeset
    37
		return anyjson.serialize(self.data)
13702105c5ee Réorganisation de Tweetcast
Raphael Velt <raph.velt@gmail.com>
parents: 309
diff changeset
    38
305
436a31d11f1d Ajout du streaming des tweets par WebSocket
Raphael Velt <raph.velt@gmail.com>
parents:
diff changeset
    39
class TweetCast:
311
13702105c5ee Réorganisation de Tweetcast
Raphael Velt <raph.velt@gmail.com>
parents: 309
diff changeset
    40
13702105c5ee Réorganisation de Tweetcast
Raphael Velt <raph.velt@gmail.com>
parents: 309
diff changeset
    41
	lastid = 0L
13702105c5ee Réorganisation de Tweetcast
Raphael Velt <raph.velt@gmail.com>
parents: 309
diff changeset
    42
	tweets = []
305
436a31d11f1d Ajout du streaming des tweets par WebSocket
Raphael Velt <raph.velt@gmail.com>
parents:
diff changeset
    43
	
436a31d11f1d Ajout du streaming des tweets par WebSocket
Raphael Velt <raph.velt@gmail.com>
parents:
diff changeset
    44
	def __init__(self):
436a31d11f1d Ajout du streaming des tweets par WebSocket
Raphael Velt <raph.velt@gmail.com>
parents:
diff changeset
    45
		self.lastid = 0L
436a31d11f1d Ajout du streaming des tweets par WebSocket
Raphael Velt <raph.velt@gmail.com>
parents:
diff changeset
    46
		self.serverfactory = TweetcastServerFactory(tweetcast=self)
311
13702105c5ee Réorganisation de Tweetcast
Raphael Velt <raph.velt@gmail.com>
parents: 309
diff changeset
    47
		dbpool.runQuery("%s ORDER BY tweet_tweet.id DESC LIMIT 20"%selectcommon).addCallback(self.callbackInit)
305
436a31d11f1d Ajout du streaming des tweets par WebSocket
Raphael Velt <raph.velt@gmail.com>
parents:
diff changeset
    48
	
436a31d11f1d Ajout du streaming des tweets par WebSocket
Raphael Velt <raph.velt@gmail.com>
parents:
diff changeset
    49
	def callbackInit(self, result):
311
13702105c5ee Réorganisation de Tweetcast
Raphael Velt <raph.velt@gmail.com>
parents: 309
diff changeset
    50
		if result:
13702105c5ee Réorganisation de Tweetcast
Raphael Velt <raph.velt@gmail.com>
parents: 309
diff changeset
    51
			self.lastid = result[0][0]
13702105c5ee Réorganisation de Tweetcast
Raphael Velt <raph.velt@gmail.com>
parents: 309
diff changeset
    52
			for ligne in result:
13702105c5ee Réorganisation de Tweetcast
Raphael Velt <raph.velt@gmail.com>
parents: 309
diff changeset
    53
				self.tweets.insert(0, Tweet(ligne))
13702105c5ee Réorganisation de Tweetcast
Raphael Velt <raph.velt@gmail.com>
parents: 309
diff changeset
    54
		print "Requesting older tweets"
305
436a31d11f1d Ajout du streaming des tweets par WebSocket
Raphael Velt <raph.velt@gmail.com>
parents:
diff changeset
    55
		task.LoopingCall(self.scheduleTweets).start(1)
436a31d11f1d Ajout du streaming des tweets par WebSocket
Raphael Velt <raph.velt@gmail.com>
parents:
diff changeset
    56
436a31d11f1d Ajout du streaming des tweets par WebSocket
Raphael Velt <raph.velt@gmail.com>
parents:
diff changeset
    57
	def scheduleTweets(self):
306
70c9688a1486 Ajout de l'envoi des anciens tweets
Raphael Velt <raph.velt@gmail.com>
parents: 305
diff changeset
    58
		dbpool.runQuery("%s WHERE tweet_tweet.id > %d ORDER BY tweet_tweet.id ASC"%(selectcommon, self.lastid)).addCallback(self.callbackTweets)
305
436a31d11f1d Ajout du streaming des tweets par WebSocket
Raphael Velt <raph.velt@gmail.com>
parents:
diff changeset
    59
	
436a31d11f1d Ajout du streaming des tweets par WebSocket
Raphael Velt <raph.velt@gmail.com>
parents:
diff changeset
    60
	def callbackTweets(self, result):
436a31d11f1d Ajout du streaming des tweets par WebSocket
Raphael Velt <raph.velt@gmail.com>
parents:
diff changeset
    61
		if result:
436a31d11f1d Ajout du streaming des tweets par WebSocket
Raphael Velt <raph.velt@gmail.com>
parents:
diff changeset
    62
			self.lastid = result[len(result)-1][0]
311
13702105c5ee Réorganisation de Tweetcast
Raphael Velt <raph.velt@gmail.com>
parents: 309
diff changeset
    63
			newtweets = [ Tweet(ligne) for ligne in result ]
13702105c5ee Réorganisation de Tweetcast
Raphael Velt <raph.velt@gmail.com>
parents: 309
diff changeset
    64
			data = { "tweets" : [ tweet.data for tweet in newtweets ] }
13702105c5ee Réorganisation de Tweetcast
Raphael Velt <raph.velt@gmail.com>
parents: 309
diff changeset
    65
			self.serverfactory.broadcast(anyjson.serialize(data))
13702105c5ee Réorganisation de Tweetcast
Raphael Velt <raph.velt@gmail.com>
parents: 309
diff changeset
    66
			print "%d new tweets"%len(result)
13702105c5ee Réorganisation de Tweetcast
Raphael Velt <raph.velt@gmail.com>
parents: 309
diff changeset
    67
			for tweet in newtweets:
13702105c5ee Réorganisation de Tweetcast
Raphael Velt <raph.velt@gmail.com>
parents: 309
diff changeset
    68
				self.tweets.append(tweet)
305
436a31d11f1d Ajout du streaming des tweets par WebSocket
Raphael Velt <raph.velt@gmail.com>
parents:
diff changeset
    69
436a31d11f1d Ajout du streaming des tweets par WebSocket
Raphael Velt <raph.velt@gmail.com>
parents:
diff changeset
    70
class TweetcastServerProtocol(WebSocketServerProtocol):
306
70c9688a1486 Ajout de l'envoi des anciens tweets
Raphael Velt <raph.velt@gmail.com>
parents: 305
diff changeset
    71
70c9688a1486 Ajout de l'envoi des anciens tweets
Raphael Velt <raph.velt@gmail.com>
parents: 305
diff changeset
    72
	def onOpen(self):
70c9688a1486 Ajout de l'envoi des anciens tweets
Raphael Velt <raph.velt@gmail.com>
parents: 305
diff changeset
    73
		self.factory.register(self)
311
13702105c5ee Réorganisation de Tweetcast
Raphael Velt <raph.velt@gmail.com>
parents: 309
diff changeset
    74
		if len(self.factory.tweetcast.tweets):
13702105c5ee Réorganisation de Tweetcast
Raphael Velt <raph.velt@gmail.com>
parents: 309
diff changeset
    75
			data = { "tweets" : [ tweet.data for tweet in self.factory.tweetcast.tweets ] }
13702105c5ee Réorganisation de Tweetcast
Raphael Velt <raph.velt@gmail.com>
parents: 309
diff changeset
    76
			self.sendMessage(anyjson.serialize(data))
13702105c5ee Réorganisation de Tweetcast
Raphael Velt <raph.velt@gmail.com>
parents: 309
diff changeset
    77
			print "sending %d old tweets to new client"%len(self.factory.tweetcast.tweets)
306
70c9688a1486 Ajout de l'envoi des anciens tweets
Raphael Velt <raph.velt@gmail.com>
parents: 305
diff changeset
    78
70c9688a1486 Ajout de l'envoi des anciens tweets
Raphael Velt <raph.velt@gmail.com>
parents: 305
diff changeset
    79
	def connectionLost(self, reason):
70c9688a1486 Ajout de l'envoi des anciens tweets
Raphael Velt <raph.velt@gmail.com>
parents: 305
diff changeset
    80
		WebSocketServerProtocol.connectionLost(self, reason)
70c9688a1486 Ajout de l'envoi des anciens tweets
Raphael Velt <raph.velt@gmail.com>
parents: 305
diff changeset
    81
		self.factory.unregister(self)
70c9688a1486 Ajout de l'envoi des anciens tweets
Raphael Velt <raph.velt@gmail.com>
parents: 305
diff changeset
    82
70c9688a1486 Ajout de l'envoi des anciens tweets
Raphael Velt <raph.velt@gmail.com>
parents: 305
diff changeset
    83
	def onMessage(self, msg, binary):
70c9688a1486 Ajout de l'envoi des anciens tweets
Raphael Velt <raph.velt@gmail.com>
parents: 305
diff changeset
    84
		print "Got message: " + msg
305
436a31d11f1d Ajout du streaming des tweets par WebSocket
Raphael Velt <raph.velt@gmail.com>
parents:
diff changeset
    85
436a31d11f1d Ajout du streaming des tweets par WebSocket
Raphael Velt <raph.velt@gmail.com>
parents:
diff changeset
    86
class TweetcastServerFactory(WebSocketServerFactory):
436a31d11f1d Ajout du streaming des tweets par WebSocket
Raphael Velt <raph.velt@gmail.com>
parents:
diff changeset
    87
 
436a31d11f1d Ajout du streaming des tweets par WebSocket
Raphael Velt <raph.velt@gmail.com>
parents:
diff changeset
    88
   protocol = TweetcastServerProtocol
436a31d11f1d Ajout du streaming des tweets par WebSocket
Raphael Velt <raph.velt@gmail.com>
parents:
diff changeset
    89
 
436a31d11f1d Ajout du streaming des tweets par WebSocket
Raphael Velt <raph.velt@gmail.com>
parents:
diff changeset
    90
   def __init__(self, tweetcast=None):
436a31d11f1d Ajout du streaming des tweets par WebSocket
Raphael Velt <raph.velt@gmail.com>
parents:
diff changeset
    91
      WebSocketServerFactory.__init__(self)
436a31d11f1d Ajout du streaming des tweets par WebSocket
Raphael Velt <raph.velt@gmail.com>
parents:
diff changeset
    92
      self.clients = []
306
70c9688a1486 Ajout de l'envoi des anciens tweets
Raphael Velt <raph.velt@gmail.com>
parents: 305
diff changeset
    93
      self.tweetcast = tweetcast
305
436a31d11f1d Ajout du streaming des tweets par WebSocket
Raphael Velt <raph.velt@gmail.com>
parents:
diff changeset
    94
 
436a31d11f1d Ajout du streaming des tweets par WebSocket
Raphael Velt <raph.velt@gmail.com>
parents:
diff changeset
    95
   def register(self, client):
436a31d11f1d Ajout du streaming des tweets par WebSocket
Raphael Velt <raph.velt@gmail.com>
parents:
diff changeset
    96
      if not client in self.clients:
436a31d11f1d Ajout du streaming des tweets par WebSocket
Raphael Velt <raph.velt@gmail.com>
parents:
diff changeset
    97
         print "registered client " + client.peerstr
436a31d11f1d Ajout du streaming des tweets par WebSocket
Raphael Velt <raph.velt@gmail.com>
parents:
diff changeset
    98
         self.clients.append(client)
436a31d11f1d Ajout du streaming des tweets par WebSocket
Raphael Velt <raph.velt@gmail.com>
parents:
diff changeset
    99
 
436a31d11f1d Ajout du streaming des tweets par WebSocket
Raphael Velt <raph.velt@gmail.com>
parents:
diff changeset
   100
   def unregister(self, client):
436a31d11f1d Ajout du streaming des tweets par WebSocket
Raphael Velt <raph.velt@gmail.com>
parents:
diff changeset
   101
      if client in self.clients:
436a31d11f1d Ajout du streaming des tweets par WebSocket
Raphael Velt <raph.velt@gmail.com>
parents:
diff changeset
   102
         print "unregistered client " + client.peerstr
436a31d11f1d Ajout du streaming des tweets par WebSocket
Raphael Velt <raph.velt@gmail.com>
parents:
diff changeset
   103
         self.clients.remove(client)
436a31d11f1d Ajout du streaming des tweets par WebSocket
Raphael Velt <raph.velt@gmail.com>
parents:
diff changeset
   104
 
436a31d11f1d Ajout du streaming des tweets par WebSocket
Raphael Velt <raph.velt@gmail.com>
parents:
diff changeset
   105
   def broadcast(self, msg):
306
70c9688a1486 Ajout de l'envoi des anciens tweets
Raphael Velt <raph.velt@gmail.com>
parents: 305
diff changeset
   106
      print "broadcasting ids up to %d" % self.tweetcast.lastid
305
436a31d11f1d Ajout du streaming des tweets par WebSocket
Raphael Velt <raph.velt@gmail.com>
parents:
diff changeset
   107
      for c in self.clients:
436a31d11f1d Ajout du streaming des tweets par WebSocket
Raphael Velt <raph.velt@gmail.com>
parents:
diff changeset
   108
         print "send to " + c.peerstr
436a31d11f1d Ajout du streaming des tweets par WebSocket
Raphael Velt <raph.velt@gmail.com>
parents:
diff changeset
   109
         c.sendMessage(msg)
436a31d11f1d Ajout du streaming des tweets par WebSocket
Raphael Velt <raph.velt@gmail.com>
parents:
diff changeset
   110
436a31d11f1d Ajout du streaming des tweets par WebSocket
Raphael Velt <raph.velt@gmail.com>
parents:
diff changeset
   111
class FlashPolicySocketProtocol(Protocol):
436a31d11f1d Ajout du streaming des tweets par WebSocket
Raphael Velt <raph.velt@gmail.com>
parents:
diff changeset
   112
    def dataReceived(self, data):
436a31d11f1d Ajout du streaming des tweets par WebSocket
Raphael Velt <raph.velt@gmail.com>
parents:
diff changeset
   113
        self.transport.write("<?xml version=\"1.0\"?><!DOCTYPE cross-domain-policy SYSTEM \"/xml/dtds/cross-domain-policy.dtd\"><cross-domain-policy><site-control permitted-cross-domain-policies=\"master-only\"/><allow-access-from domain=\"*\" to-ports=\"*\" /></cross-domain-policy>\0") 
436a31d11f1d Ajout du streaming des tweets par WebSocket
Raphael Velt <raph.velt@gmail.com>
parents:
diff changeset
   114
 
436a31d11f1d Ajout du streaming des tweets par WebSocket
Raphael Velt <raph.velt@gmail.com>
parents:
diff changeset
   115
class FlashPolicyFactory(Factory):
436a31d11f1d Ajout du streaming des tweets par WebSocket
Raphael Velt <raph.velt@gmail.com>
parents:
diff changeset
   116
    def __init__(self):
436a31d11f1d Ajout du streaming des tweets par WebSocket
Raphael Velt <raph.velt@gmail.com>
parents:
diff changeset
   117
        self.protocol = FlashPolicySocketProtocol;
436a31d11f1d Ajout du streaming des tweets par WebSocket
Raphael Velt <raph.velt@gmail.com>
parents:
diff changeset
   118
436a31d11f1d Ajout du streaming des tweets par WebSocket
Raphael Velt <raph.velt@gmail.com>
parents:
diff changeset
   119
tc = TweetCast()
436a31d11f1d Ajout du streaming des tweets par WebSocket
Raphael Velt <raph.velt@gmail.com>
parents:
diff changeset
   120
reactor.listenTCP(843, FlashPolicyFactory())
436a31d11f1d Ajout du streaming des tweets par WebSocket
Raphael Velt <raph.velt@gmail.com>
parents:
diff changeset
   121
reactor.listenTCP(9000, tc.serverfactory)
436a31d11f1d Ajout du streaming des tweets par WebSocket
Raphael Velt <raph.velt@gmail.com>
parents:
diff changeset
   122
reactor.run()