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')