1 |
from flask import Flask |
2 |
from flask import request |
3 |
from flask import render_template |
4 |
from flask import make_response |
5 |
import lxml.html |
6 |
import pymongo |
7 |
from bson import Code |
8 |
import urllib2 |
9 |
import StringIO |
10 |
from flask import g |
11 |
from flask import redirect |
12 |
from urllib import quote_plus |
13 |
from urllib import unquote_plus |
14 |
import conf |
15 |
import sweetmaker |
16 |
import oursql |
17 |
import requests |
18 |
from flask import jsonify |
19 |
import json |
20 |
|
21 |
|
22 |
app = Flask(__name__) |
23 |
@app.before_request |
24 |
def first(): |
25 |
g.connection = pymongo.MongoClient('localhost',27017) #Create the object once and use it. |
26 |
g.db = g.connection[conf.MONGODB[0]] |
27 |
@app.teardown_request |
28 |
def close(exception): |
29 |
g.connection.disconnect() |
30 |
@app.route('/') |
31 |
def start_page() : |
32 |
d = {} |
33 |
d['foruri'] = request.args['foruri'] |
34 |
myhandler1 = urllib2.Request(d['foruri'],headers={'User-Agent':"Mozilla/5.0 (X11; U; Linux i686) Gecko/20071127 Firefox/2.0.0.11"}) #A fix to send user-agents, so that sites render properly. |
35 |
try: |
36 |
a = urllib2.urlopen(myhandler1) |
37 |
if a.geturl() != d['foruri']: |
38 |
return "There was a server redirect, please click on the <a href='http://y.a11y.in/web?foruri={0}'>link</a> to continue.".format(quote_plus(a.geturl())) |
39 |
else: |
40 |
page = a.read() |
41 |
a.close() |
42 |
except ValueError: |
43 |
return "The link is malformed, click <a href='http://y.a11y.in/web?foruri={0}&lang={1}&interactive=1'>here</a> to be redirected.".format(quote_plus(unquote_plus(d['foruri'].encode('utf-8'))),request.args['lang']) |
44 |
except urllib2.URLError: |
45 |
return render_template('error.html') |
46 |
try: |
47 |
page = unicode(page,'utf-8') #Hack to fix improperly displayed chars on wikipedia. |
48 |
except UnicodeDecodeError: |
49 |
pass #Some pages may not need be utf-8'ed |
50 |
try: |
51 |
g.root = lxml.html.parse(StringIO.StringIO(page)).getroot() |
52 |
except ValueError: |
53 |
g.root = lxml.html.parse(d['foruri']).getroot() #Sometimes creators of the page lie about the encoding, thus leading to this execption. http://lxml.de/parsing.html#python-unicode-strings |
54 |
if request.args.has_key('lang') == False and request.args.has_key('blog') == False: |
55 |
g.root.make_links_absolute(d['foruri'], resolve_base_href = True) |
56 |
for i in g.root.iterlinks(): |
57 |
if i[1] == 'href' and i[0].tag != 'link': |
58 |
try: |
59 |
i[0].attrib['href'] = 'http://{0}?foruri={1}'.format(conf.DEPLOYURL[0],quote_plus(i[0].attrib['href'])) |
60 |
except KeyError: |
61 |
i[0].attrib['href'] = '{0}?foruri={1}'.format(conf.DEPLOYURL[0],quote_plus(i[0].attrib['href'].encode('utf-8'))) |
62 |
setScripts() |
63 |
g.root.body.set("onload","a11ypi.loadOverlay();") |
64 |
return lxml.html.tostring(g.root) |
65 |
|
66 |
elif request.args.has_key('lang') == True and request.args.has_key('interactive') == True and request.args.has_key('blog') == False: |
67 |
setScripts() |
68 |
setSocialScript() |
69 |
g.root.body.set("onload","a11ypi.ren();a11ypi.tweet(); a11ypi.facebook(); a11ypi.loadOverlay();") |
70 |
g.root.make_links_absolute(d['foruri'], resolve_base_href = True) |
71 |
return lxml.html.tostring(g.root) |
72 |
|
73 |
elif request.args.has_key('lang') == True and request.args.has_key('blog') == False: |
74 |
script_jq_mini = g.root.makeelement('script') |
75 |
g.root.body.append(script_jq_mini) |
76 |
script_jq_mini.set("src", conf.JQUERYURL[0] + "/jquery.min.js") |
77 |
script_jq_mini.set("type", "text/javascript") |
78 |
d['lang'] = request.args['lang'] |
79 |
script_test = g.root.makeelement('script') |
80 |
g.root.body.append(script_test) |
81 |
script_test.set("src", conf.APPURL[0] + "/alipi/ui.js") |
82 |
script_test.set("type", "text/javascript") |
83 |
g.root.body.set("onload","a11ypi.ren()"); |
84 |
return lxml.html.tostring(g.root) |
85 |
|
86 |
elif request.args.has_key('interactive') == True and request.args.has_key('blog') == True and request.args.has_key('lang') == True: |
87 |
setScripts() |
88 |
setSocialScript() |
89 |
g.root.body.set("onload","a11ypi.filter(); a11ypi.tweet(); a11ypi.facebook(); a11ypi.loadOverlay();"); |
90 |
g.root.make_links_absolute(d['foruri'], resolve_base_href = True) |
91 |
return lxml.html.tostring(g.root) |
92 |
|
93 |
elif request.args.has_key('interactive') == False and request.args.has_key('blog') == True: |
94 |
setScripts() |
95 |
g.root.make_links_absolute(d['foruri'], resolve_base_href = True) |
96 |
g.root.body.set('onload', 'a11ypi.loadOverlay();') |
97 |
return lxml.html.tostring(g.root) |
98 |
|
99 |
def setScripts(): |
100 |
script_test = g.root.makeelement('script') |
101 |
script_edit = g.root.makeelement('script') |
102 |
g.root.body.append(script_test) |
103 |
g.root.body.append(script_edit) |
104 |
script_test.set("src", conf.APPURL[0] + "/alipi/ui.js") |
105 |
script_test.set("type", "text/javascript") |
106 |
script_edit.set("src", conf.APPURL[0] + "/alipi/wsgi/pageEditor.js") |
107 |
script_edit.set("type","text/javascript") |
108 |
script_config = g.root.makeelement('script') |
109 |
g.root.body.append(script_config) |
110 |
script_config.set("src", conf.APPURL[0] + "/alipi/config.js") |
111 |
script_config.set("type", "text/javascript") |
112 |
|
113 |
|
114 |
script_jq_mini = g.root.makeelement('script') |
115 |
g.root.body.append(script_jq_mini) |
116 |
script_jq_mini.set("src", conf.JQUERYURL[0] + "/jquery.min.js") |
117 |
script_jq_mini.set("type", "text/javascript") |
118 |
|
119 |
style = g.root.makeelement('link') |
120 |
g.root.body.append(style) |
121 |
style.set("rel","stylesheet") |
122 |
style.set("type", "text/css") |
123 |
style.set("href", conf.APPURL[0] + "/alipi/stylesheet.css") |
124 |
|
125 |
script_jq_cust = g.root.makeelement('script') |
126 |
g.root.body.append(script_jq_cust) |
127 |
script_jq_cust.set("src", conf.JQUERYUI[0] + "/jquery-ui.min.js") |
128 |
script_jq_cust.set("type", "text/javascript") |
129 |
|
130 |
style_cust = g.root.makeelement('link') |
131 |
style_cust.set("rel","stylesheet") |
132 |
style_cust.set("type", "text/css") |
133 |
style_cust.set("href", conf.JQUERYCSS[0] + "/jquery-ui.css") |
134 |
g.root.body.append(style_cust) |
135 |
|
136 |
def setSocialScript(): |
137 |
info_button = g.root.makeelement('button') |
138 |
g.root.body.append(info_button) |
139 |
info_button.set("id", "info") |
140 |
info_button.set("class", "alipi") |
141 |
info_button.set("onClick", "a11ypi.showInfo(a11ypi.responseJSON);") |
142 |
info_button.text = "Info" |
143 |
info_button.set("title", "Have a look at the information of each renarrated element") |
144 |
|
145 |
share_button = g.root.makeelement('button') |
146 |
g.root.body.append(share_button) |
147 |
share_button.set("id", "share") |
148 |
share_button.set("class", "alipi") |
149 |
share_button.set("onClick", "a11ypi.share();") |
150 |
share_button.text = "Share" |
151 |
share_button.set("title", "Share your contribution in your social network") |
152 |
|
153 |
see_orig = g.root.makeelement('button') |
154 |
g.root.body.append(see_orig) |
155 |
see_orig.set("id", "orig-button") |
156 |
see_orig.set("class", "alipi") |
157 |
see_orig.set("onClick", "a11ypi.showOriginal();") |
158 |
see_orig.text = "Original Page" |
159 |
see_orig.set("title", "Go to Original link, the original page of this renarrated") |
160 |
|
161 |
tweetroot = g.root.makeelement("div") |
162 |
tweetroot.set("id", "tweet-root") |
163 |
tweetroot.set("class", "alipi") |
164 |
tweetroot.set("style", "display:none;padding:10px;") |
165 |
g.root.body.append(tweetroot) |
166 |
|
167 |
tweet = g.root.makeelement("a") |
168 |
tweet.set("id", "tweet") |
169 |
tweet.set("href", "https://twitter.com/share") |
170 |
tweet.set("class", "alipi twitter-share-button") |
171 |
tweet.set("data-via", "a11ypi") |
172 |
tweet.set("data-lang", "en") |
173 |
tweet.set("data-url", "http://y.a11y.in/web?foruri={0}&lang={1}&interactive=1".format(quote_plus(request.args['foruri']),(request.args['lang']).encode('unicode-escape'))) |
174 |
tweet.textContent = "Tweet" |
175 |
tweetroot.append(tweet) |
176 |
|
177 |
fblike = g.root.makeelement("div") |
178 |
fblike.set("id", "fb-like") |
179 |
fblike.set("class", "alipi fb-like") |
180 |
fblike.set("style", "display:none;padding:10px;") |
181 |
fblike.set("data-href", "http://y.a11y.in/web?foruri={0}&lang={1}&interactive=1".format(quote_plus(request.args['foruri']),(request.args['lang']).encode('unicode-escape'))) |
182 |
fblike.set("data-send", "true") |
183 |
fblike.set("data-layout", "button_count") |
184 |
fblike.set("data-width", "50") |
185 |
fblike.set("data-show-faces", "true") |
186 |
fblike.set("data-font", "arial") |
187 |
g.root.body.append(fblike) |
188 |
|
189 |
style = g.root.makeelement('link') |
190 |
g.root.body.append(style) |
191 |
style.set("rel","stylesheet") |
192 |
style.set("type", "text/css") |
193 |
style.set("href", "http://y.a11y.in/alipi/stylesheet.css") |
194 |
|
195 |
|
196 |
@app.route('/directory') |
197 |
def show_directory(): |
198 |
collection = g.db['post'] |
199 |
query = collection.group( |
200 |
key = Code('function(doc){return {"about" : doc.about,"lang":doc.lang}}'), |
201 |
condition={"about":{'$regex':'^[/\S/]'}}, |
202 |
initial={'na': []}, |
203 |
reduce=Code('function(doc,out){out.na.push(doc.blog)}') |
204 |
) |
205 |
query.reverse() |
206 |
return render_template('directory.html', name=query, mymodule = quote_plus, myset=set, mylist= list) |
207 |
|
208 |
@app.route('/getLoc', methods=['GET']) |
209 |
def get_loc(): |
210 |
|
211 |
term = request.args['term'] |
212 |
connection = oursql.Connection(conf.DBHOST[0],conf.DBUSRNAME[0],conf.DBPASSWD[0],db=conf.DBNAME[0]) |
213 |
cursor = connection.cursor(oursql.DictCursor) |
214 |
cursor.execute('select l.name, c.country_name from `location` as l, `codes` as c where l.name like ? and l.code=c.code limit ?', (term+'%', 5)) |
215 |
r = cursor.fetchall() |
216 |
connection.close() |
217 |
d = {} |
218 |
d['return'] = r |
219 |
response = jsonify(d) |
220 |
response.headers['Access-Control-Allow-Origin'] = '*' |
221 |
return response |
222 |
@app.route('/getLang', methods=['GET']) |
223 |
def get_lang(): |
224 |
term = request.args['term'] |
225 |
connection = oursql.Connection(conf.DBHOST[0],conf.DBUSRNAME[0],conf.DBPASSWD[0],db=conf.DBNAME[0]) |
226 |
cursor = connection.cursor(oursql.DictCursor) |
227 |
cursor.execute('select * from `languages` as l where l.name like ? limit ?', (term+'%',5)) |
228 |
r = cursor.fetchall() |
229 |
connection.close() |
230 |
d = {} |
231 |
d['return'] = r |
232 |
response = jsonify(d) |
233 |
response.headers['Access-Control-Allow-Origin'] = '*' |
234 |
return response |
235 |
|
236 |
@app.route('/blank', methods=['GET']) |
237 |
def serve_blank(): |
238 |
return render_template('blank.html') |
239 |
|
240 |
@app.route('/info', methods=['GET']) |
241 |
def serve_info(): |
242 |
coll = g.db['post'] |
243 |
d = {} |
244 |
cntr = 0 |
245 |
for i in coll.find({"about":unquote_plus(request.args['about']),"lang":request.args['lang']}): |
246 |
i['_id'] = str(i['_id']) |
247 |
d[cntr] = i |
248 |
cntr+=1 |
249 |
response = jsonify(d) |
250 |
response.headers['Access-Control-Allow-Origin'] = '*' |
251 |
return response |
252 |
|
253 |
|
254 |
@app.route("/replace", methods=['GET']) |
255 |
def replace(): |
256 |
collection = g.db['post'] |
257 |
lang = request.args['lang'] |
258 |
url = request.args['url'] |
259 |
query = collection.group( |
260 |
key = Code('function(doc){return {"xpath" : doc.xpath, "about": doc.url}}'), |
261 |
condition={"about" : url, "lang" : lang,"elementtype":"text"}, |
262 |
initial={'narration': []}, |
263 |
reduce=Code('function(doc,out){out.narration.push(doc);}') |
264 |
) |
265 |
|
266 |
print query |
267 |
|
268 |
audio_query =collection.group( |
269 |
key = Code('function(doc){return {"xpath" : doc.xpath, "about": doc.url}}'), |
270 |
condition={"about" : url, "lang" : lang, 'elementtype':"audio/ogg"}, |
271 |
initial={'narration': []}, |
272 |
reduce=Code('function(doc,out){out.narration.push(doc);}') |
273 |
) |
274 |
|
275 |
image_query =collection.group( |
276 |
key = Code('function(doc){return {"xpath" : doc.xpath, "about": doc.url}}'), |
277 |
condition={"about" : url, "lang" : lang, 'elementtype':"image"}, |
278 |
initial={'narration': []}, |
279 |
reduce=Code('function(doc,out){out.narration.push(doc);}') |
280 |
) |
281 |
try: |
282 |
for i in audio_query: |
283 |
query.append(i) |
284 |
except IndexError: |
285 |
pass |
286 |
try: |
287 |
for i in image_query: |
288 |
query.append(i) |
289 |
except IndexError: |
290 |
pass |
291 |
|
292 |
for i in query: |
293 |
for y in i['narration']: |
294 |
del(y['_id']) |
295 |
d = {} |
296 |
d['r'] = query |
297 |
response = jsonify(d) |
298 |
response.headers['Access-Control-Allow-Origin'] = '*' |
299 |
return response |
300 |
|
301 |
@app.route('/feeds', methods=['GET']) |
302 |
def serve_feed_temp(): |
303 |
return render_template("feeds.html") |
304 |
|
305 |
@app.route('/feed', methods=['GET']) |
306 |
def serve_feed(): |
307 |
coll = g.db['post'] |
308 |
d = {} |
309 |
cntr = 0 |
310 |
for i in coll.find().sort('_id',direction=-1): |
311 |
if i['data'] != '<br/>': |
312 |
i['_id'] = str(i['_id']) |
313 |
d[cntr] = i |
314 |
cntr+=1 |
315 |
response = jsonify(d) |
316 |
response.headers['Access-Control-Allow-Origin'] = '*' |
317 |
return response |
318 |
|
319 |
@app.route('/about', methods=['GET']) |
320 |
def serve_authors(): |
321 |
coll = g.db['post'] |
322 |
d = {} |
323 |
cntr = 0 |
324 |
for i in coll.find({"about":unquote_plus(request.args['about'])}): |
325 |
i['_id'] = str(i['_id']) |
326 |
d[cntr] = i |
327 |
cntr+=1 |
328 |
response = jsonify(d) |
329 |
response.headers['Access-Control-Allow-Origin'] = '*' |
330 |
return response |
331 |
#Retrieve all information about a specific $about and a given $author. |
332 |
@app.route('/author', methods=['GET']) |
333 |
def serve_author(): |
334 |
coll = g.db['post'] |
335 |
d = {} |
336 |
cntr = 0 |
337 |
for i in coll.find({"about":unquote_plus(request.args['about']),"author":unquote_plus(request.args['author'])}): |
338 |
i['_id'] = str(i['_id']) |
339 |
d[cntr] = i |
340 |
cntr += 1 |
341 |
response = jsonify(d) |
342 |
response.headers['Access-Control-Allow-Origin'] = '*' |
343 |
return response |
344 |
|
345 |
@app.route('/getAllLang', methods=['GET']) |
346 |
def get_all_lang(): |
347 |
term = request.args['term'] |
348 |
connection = oursql.Connection(conf.DBHOST[0],conf.DBUSRNAME[0],conf.DBPASSWD[0],db=conf.DBNAME[0]) |
349 |
cursor = connection.cursor(oursql.DictCursor) |
350 |
cursor.execute('select * from `languages` as l where l.name like ?', (term+'%',)) |
351 |
r = cursor.fetchall() |
352 |
connection.close() |
353 |
d = {} |
354 |
d['return'] = r |
355 |
response = jsonify(d) |
356 |
response.headers['Access-Control-Allow-Origin'] = '*' |
357 |
return response |
358 |
|
359 |
|
360 |
@app.route('/publish', methods=['POST']) |
361 |
def publish(): |
362 |
print "entered" |
363 |
data = json.loads(request.form['data']) |
364 |
collection = g.db['post'] |
365 |
for i in data: |
366 |
i['bxpath'] = '' |
367 |
collection.insert(i) |
368 |
sweet(data) |
369 |
reply = make_response() |
370 |
return reply |
371 |
|
372 |
|
373 |
def sweet(data): |
374 |
""" A function to sweet the data that is inserted. Accepts a <list of dicts>. """ |
375 |
for i in data: |
376 |
del(i['_id']) |
377 |
sweet = sweetmaker.make(i['type'], i['author'], i['about']+i['xpath'], i['data']) |
378 |
sweetmaker.send(sweet) |
379 |
return True |
380 |
# data = json.dumps(data) |
381 |
# req = requests.api.post(conf.SWEETURL[0]+"/add",{'data':data}) |
382 |
# if req.status_code == 200: |
383 |
# reply = make_response() |
384 |
# return reply |
385 |
|
386 |
|
387 |
@app.route("/askSWeeT", methods=['POST']) |
388 |
def askSweet(): |
389 |
data = json.loads(request.form['data']) |
390 |
for i in data: |
391 |
response = requests.api.get(conf.SWEETURL[0]+"/query/"+i['id']) |
392 |
collection = g.db['post'] |
393 |
rep = response.json() |
394 |
rep['bxpath'] = '' |
395 |
if response.status_code == 200: |
396 |
collection.insert(rep) |
397 |
reply = make_response() |
398 |
return reply |
399 |
|
400 |
@app.route("/menu",methods=['GET']) |
401 |
def menuForDialog(): |
402 |
if request.args.has_key('option') == False: |
403 |
collection = g.db['post'] |
404 |
c = {} |
405 |
cntr = 0 |
406 |
print request.args['url'] |
407 |
for i in collection.find({"about":request.args['url']}).distinct('lang'): |
408 |
for j in collection.find({"about":request.args['url'],'lang':i}).distinct('type'): |
409 |
d = {} |
410 |
d['lang'] = i |
411 |
d['type'] = j |
412 |
c[cntr] = d |
413 |
cntr += 1 |
414 |
print c |
415 |
return jsonify(c) |
416 |
else: |
417 |
collection = g.db['post'] |
418 |
#get the ren languages for the received url |
419 |
langForUrl = collection.group( |
420 |
key = Code('function(doc){return {"about" : doc.about}}'), |
421 |
condition={"about" : d['url'],"blog":{'$regex':'/'+d['option']+'.*/'}}, |
422 |
initial={'lang': []}, |
423 |
reduce=Code('function(doc, out){if (out.lang.indexOf(doc.lang) == -1) out.lang.push(doc.lang)}') #here xpath for test |
424 |
) |
425 |
|
426 |
#send the response |
427 |
if (langForUrl): |
428 |
connection.disconnect() |
429 |
return json.dumps(langForUrl[0]['lang']) |
430 |
else: |
431 |
connection.disconnect() |
432 |
return "empty" |
433 |
|
434 |
|
435 |
|
436 |
import logging,os |
437 |
from logging import FileHandler |
438 |
|
439 |
fil = FileHandler(os.path.join(os.path.dirname(__file__),'logme'),mode='a') |
440 |
fil.setLevel(logging.ERROR) |
441 |
app.logger.addHandler(fil) |
442 |
|
443 |
if __name__ == '__main__': |
444 |
app.run(debug=True, host='0.0.0.0') |