1 #!/usr/bin/env python |
|
2 # -*- coding: utf-8 -*- |
|
3 |
|
4 from gevent import monkey; monkey.patch_all() |
|
5 # Importer d'abord, sinon exception |
|
6 import anyjson, gevent, psycopg2 |
|
7 from sqlalchemy import (Boolean, Column, BigInteger, Integer, String, |
|
8 ForeignKey, DateTime, create_engine, func) |
|
9 from sqlalchemy.orm import relationship, sessionmaker |
|
10 from sqlalchemy.ext.declarative import declarative_base |
|
11 from gevent.pywsgi import WSGIServer |
|
12 from urlparse import parse_qs |
|
13 |
|
14 Base = declarative_base() |
|
15 engine = create_engine('postgresql://postgres:doiteshimashite@localhost/tweet_live') |
|
16 Session = sessionmaker(bind=engine) |
|
17 |
|
18 class Tweet(Base): |
|
19 __tablename__ = 'tweet_tweet' |
|
20 |
|
21 id = Column(BigInteger, primary_key=True, autoincrement=False) |
|
22 created_at = Column(DateTime) |
|
23 text = Column(String) |
|
24 user_id = Column(Integer, ForeignKey('tweet_user.id')) |
|
25 user = relationship("User", backref="tweets") |
|
26 |
|
27 def jsondict(self): |
|
28 return { |
|
29 "id" : str(self.id), |
|
30 "created_at" : str(self.created_at), |
|
31 "text" : self.text, |
|
32 "user" : self.user.jsondict() |
|
33 } |
|
34 |
|
35 def __repr__(self): |
|
36 return anyjson.serialize(self.jsondict()) |
|
37 |
|
38 class User(Base): |
|
39 __tablename__ = "tweet_user" |
|
40 |
|
41 id = Column(BigInteger, primary_key=True, autoincrement=False) |
|
42 screen_name = Column(String, index=True) |
|
43 profile_image_url = Column(String) |
|
44 |
|
45 def jsondict(self): |
|
46 return { |
|
47 "id" : str(self.id), |
|
48 "screen_name" : self.screen_name, |
|
49 "profile_image_url" : self.profile_image_url |
|
50 } |
|
51 |
|
52 def __repr__(self): |
|
53 return anyjson.serialize(self.jsondict()) |
|
54 |
|
55 class TweetCast(object): |
|
56 |
|
57 def __init__(self): |
|
58 self.session = Session() |
|
59 a = self.session.query(func.max(Tweet.id)) |
|
60 self.lastid = long(a[0][0]) |
|
61 print self.lastid |
|
62 self.tweets = [] |
|
63 self.clients = [] |
|
64 self.clientpos = [] |
|
65 print "__init__" |
|
66 gevent.spawn_later(1,self.getLastTweets) |
|
67 |
|
68 def getLastTweets(self): |
|
69 result = self.session.query(Tweet).filter(Tweet.id > self.lastid).all() |
|
70 if result: |
|
71 self.lastid = result[len(result)-1].id |
|
72 for tweet in result: |
|
73 self.tweets.append(tweet) |
|
74 print "getLastTweets - LastId = %d"%self.lastid |
|
75 gevent.spawn_later(1,self.getLastTweets) |
|
76 |
|
77 def webserver(self, env, start_response): |
|
78 print env |
|
79 if env['PATH_INFO'] == '/': |
|
80 query = parse_qs(env['QUERY_STRING']) |
|
81 start_response('200 OK', [('Content-Type', 'text/html')]) |
|
82 cookie = env['HTTP_COOKIE'] |
|
83 if cookie not in self.clients: |
|
84 self.clients.append(cookie) |
|
85 self.clientpos.append(0) |
|
86 clientid = self.clients.index(cookie) |
|
87 pos = self.clientpos[clientid] |
|
88 self.clientpos[clientid] = len(self.tweets) |
|
89 return ["%s[%s]%s"%( |
|
90 "%s("%query["callback"][0] if "callback" in query else "", |
|
91 ",".join([str(tweet) for tweet in self.tweets[pos:]]), |
|
92 ")" if "callback" in query else "" |
|
93 )] |
|
94 else: |
|
95 start_response('404 Not Found', [('Content-Type', 'text/html')]) |
|
96 return ['<h1>Not Found</h1>'] |
|
97 |
|
98 tc = TweetCast() |
|
99 WSGIServer(('', 8000), tc.webserver).serve_forever() |
|