Skip to content
Newer
Older
100644 146 lines (118 sloc) 4.33 KB
0d53b59 @bsstoner first commit, did this a few months ago and forgot about it, just pos…
authored
1 import logging
2 import tornado.auth
3 import tornado.escape
4 import tornado.httpserver
5 import tornado.ioloop
6 import tornado.options
7 import tornado.web
8 import os.path
9 import uuid
10
11 from datetime import datetime
12
13 # For pubsub subscriptions
14 import feedparser
15
16 try:
17 import couchdb
18 except ImportError:
19 raise ImproperlyConfigured, "Could not load couchdb dependency.\
20 \nSee http://code.google.com/p/couchdb-python/"
21
22 from tornado.options import define, options
23
24 define("port", default=8001, help="run on the given port", type=int)
25
26 class Application(tornado.web.Application):
27 def __init__(self):
28 handlers = [
29 (r"/", MainHandler),
30 (r"/feeds/getupdates", ClientUpdatesHandler),
31 (r"/feeds/update/?", FeedUpdateHandler),
32 ]
33 settings = dict(
34 cookie_secret="43oETzKXQAGaYdkL5gEmGeJJFuYh7EQnp2XdTP1o/Vo=",
35 login_url="/auth/login",
36 template_path=os.path.join(os.path.dirname(__file__), "templates"),
37 static_path=os.path.join(os.path.dirname(__file__), "static")
38 )
39 tornado.web.Application.__init__(self, handlers, **settings)
40
41 class BaseHandler(tornado.web.RequestHandler):
42 @property
43 def dbserver(self):
44 return couchdb.client.Server("http://localhost:5984")
45
46 class MessageMixin(object):
47 waiters = []
48 cache = []
49 cache_size = 200
50
51 def wait_for_messages(self, callback, cursor=None):
52 cls = MessageMixin
53 if cursor:
54 index = 0
55 for i in xrange(len(cls.cache)):
56 index = len(cls.cache) - i - 1
57 if cls.cache[index]["id"] == cursor: break
58 recent = cls.cache[index + 1:]
59 if recent:
60 callback(recent)
61 return
62 cls.waiters.append(callback)
63
64 def new_messages(self, messages):
65 cls = MessageMixin
66 logging.info("Sending new message to %r listeners", len(cls.waiters))
67 for callback in cls.waiters:
68 try:
69 callback(messages)
70 except:
71 logging.error("Error in waiter callback", exc_info=True)
72 cls.waiters = []
73 cls.cache.extend(messages)
74 if len(cls.cache) > self.cache_size:
75 cls.cache = cls.cache[-self.cache_size:]
76
77
78 class MainHandler(BaseHandler):
79
80 def get(self):
81 db = self.dbserver['entries']
82 entries_all = []
83 for row in db.view("_view/entries/all_docs",count=20,descending=True):
84 entries_all.append(row.value)
85 self.render("index.html", entries=entries_all)#MessageMixin.cache)
86
87 def post(self):
88 f = self.get_argument('feedname')
89 furl = self.get_argument('feedurl')
90
91 db = self.dbserver['feeds']
92 db.create({'name':f,'feed_url':furl})
93 self.redirect("/")
94
95 class FeedUpdateHandler(BaseHandler, MessageMixin):
96
97 def get(self):
98 c = self.get_argument('hub.challenge')
99 self.set_status(200)
100 self.set_header("Content-Type", "text/plain")
101 self.write(c)
102
103 def post(self):
104 feed = feedparser.parse(self.request.body)
105 db = self.dbserver['entries']
106 latest_es = []
107 for e in feed.entries:
108 entry_dict = {'title':e.title,
109 'link':e.link,
110 'receive_time':str(datetime.now()),
111 'full_entry':str(e)}
112
113 e_id = db.create(entry_dict)
114 entry_dict['_id'] = e_id
115 latest_es.append(entry_dict)
116
117 self.new_messages(latest_es)
118
119 self.set_status(200)
120 self.set_header("Content-Type", "text/plain")
121 self.write('OK')
122
123 class ClientUpdatesHandler(BaseHandler, MessageMixin):
124 @tornado.web.asynchronous
125 def post(self):
126 cursor = self.get_argument("cursor", None)
127 self.wait_for_messages(self.async_callback(self.on_new_messages),
128 cursor=cursor)
129
130 def on_new_messages(self, messages):
131 # Closed client connection
132 if self.request.connection.stream.closed():
133 return
134 self.finish(dict(messages=messages))
135
136
137 def main():
138 tornado.options.parse_command_line()
139 http_server = tornado.httpserver.HTTPServer(Application())
140 http_server.listen(options.port)
141 tornado.ioloop.IOLoop.instance().start()
142
143
144 if __name__ == "__main__":
145 main()
Something went wrong with that request. Please try again.