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