PageRenderTime 58ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/server.py

https://bitbucket.org/kelrlu/q
Python | 891 lines | 754 code | 69 blank | 68 comment | 52 complexity | ac9ec1f33b24292ce6fd4e4ab7e4c34e MD5 | raw file
Possible License(s): Apache-2.0
  1. #!/usr/bin/env python2.7
  2. """
  3. Q Server
  4. To run locally
  5. python server.py
  6. Go to http://localhost:8111 in your browser
  7. """
  8. import os
  9. from sqlalchemy import *
  10. from sqlalchemy.pool import NullPool
  11. from urlparse import urlparse, urljoin
  12. from flask import Flask, request, render_template, g, redirect, Response,flash, url_for
  13. tmpl_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'templates')
  14. app = Flask(__name__, template_folder=tmpl_dir)
  15. # XXX: The URI should be in the format of:
  16. #
  17. # postgresql://USER:PASSWORD@<IP_OF_POSTGRE_SQL_SERVER>/postgres
  18. DATABASEURI = "postgresql://krl2130:vt6jr@104.196.175.120:5432/postgres"
  19. engine = create_engine(DATABASEURI)
  20. @app.before_request
  21. def before_request():
  22. """
  23. This function is run at the beginning of every web request
  24. (every time you enter an address in the web browser).
  25. We use it to setup a database connection that can be used throughout the request
  26. The variable g is globally accessible
  27. """
  28. try:
  29. g.conn = engine.connect()
  30. except:
  31. print "uh oh, problem connecting to database"
  32. import traceback; traceback.print_exc()
  33. g.conn = None
  34. @app.teardown_request
  35. def teardown_request(exception):
  36. """
  37. At the end of the web request, this makes sure to close the database connection.
  38. If you don't the database could run out of memory!
  39. """
  40. try:
  41. g.conn.close()
  42. except Exception as e:
  43. pass
  44. def redirect_url(default='index'):
  45. return request.args.get('next') or \
  46. request.referrer or \
  47. url_for(default)
  48. #
  49. # @app.route is a decorator around index() that means:
  50. # run index() whenever the user tries to access the "/" path using a GET request
  51. #
  52. # If you wanted the user to go to e.g., localhost:8111/foobar/ with POST or GET then you could use
  53. #
  54. # @app.route("/foobar/", methods=["POST", "GET"])
  55. #
  56. # PROTIP: (the trailing / in the path is important)
  57. #
  58. # see for routing: http://flask.pocoo.org/docs/0.10/quickstart/#routing
  59. # see for decorators: http://simeonfranklin.com/blog/2012/jul/1/python-decorators-in-12-steps/
  60. #
  61. @app.route('/')
  62. def index():
  63. """
  64. request is a special object that Flask provides to access web request information:
  65. request.method: "GET" or "POST"
  66. request.form: if the browser submitted a form, this contains the data in the form
  67. request.args: dictionary of URL arguments e.g., {a:1, b:2} for http://localhost?a=1&b=2
  68. See its API: http://flask.pocoo.org/docs/0.10/api/#incoming-request-data
  69. """
  70. top_cmd = "SELECT q.qid as qid, q.content as content, a.aid as aid, a.name as author, w.wid as wid, w.name as work FROM quotes q INNER JOIN authors a ON q.author = a.aid LEFT JOIN works w on q.work = w.wid WHERE q.qid IN (SELECT qid FROM saved_quotes GROUP BY qid ORDER BY count(*) DESC LIMIT 5) and q.num_approvals >= 10"
  71. top_cursor = g.conn.execute(text(top_cmd))
  72. top_quotes = []
  73. for result in top_cursor:
  74. top_quotes.append((result['qid'],result['content'],result['aid'],result['author'],result['wid'],result['work']))
  75. top_cursor.close()
  76. recent_cmd = "SELECT q.qid as qid, q.content as content, a.aid as aid, a.name as author, w.wid as wid, w.name as work FROM quotes q INNER JOIN authors a ON q.author = a.aid LEFT JOIN works w on q.work = w.wid WHERE q.num_approvals >= 10 ORDER BY q.added_time ASC LIMIT 5"
  77. recent_cursor = g.conn.execute(text(recent_cmd))
  78. recent_quotes = []
  79. for result in recent_cursor:
  80. recent_quotes.append((result['qid'],result['content'],result['aid'],result['author'],result['wid'],result['work']))
  81. recent_cursor.close()
  82. context = dict(top_quotes = top_quotes, recent_quotes = recent_quotes)
  83. return render_template("q.html", **context)
  84. # DEBUG: this is debugging code to see what request looks like
  85. #
  86. # example of a database query
  87. #
  88. # cursor = g.conn.execute("SELECT name FROM test")
  89. # names = []
  90. # for result in cursor:
  91. # names.append(result['name']) # can also be accessed using result[0]
  92. # cursor.close()
  93. #
  94. # Flask uses Jinja templates, which is an extension to HTML where you can
  95. # pass data to a template and dynamically generate HTML based on the data
  96. # (you can think of it as simple PHP)
  97. # documentation: https://realpython.com/blog/python/primer-on-jinja-templating/
  98. #
  99. # You can see an example template in templates/index.html
  100. #
  101. # context are the variables that are passed to the template.
  102. # for example, "data" key in the context variable defined below will be
  103. # accessible as a variable in index.html:
  104. #
  105. # # will print: [u'grace hopper', u'alan turing', u'ada lovelace']
  106. # <div>{{data}}</div>
  107. #
  108. # # creates a <div> tag for each element in data
  109. # # will print:
  110. # #
  111. # # <div>grace hopper</div>
  112. # # <div>alan turing</div>
  113. # # <div>ada lovelace</div>
  114. # #
  115. # {% for n in data %}
  116. # <div>{{n}}</div>
  117. # {% endfor %}
  118. #
  119. # context = dict(data = names)
  120. #
  121. # render_template looks in the templates/ folder for files.
  122. # for example, the below file reads template/index.html
  123. #
  124. # return render_template("q.html", **context)
  125. #
  126. # This is an example of a different path. You can see it at
  127. #
  128. # localhost:8111/another
  129. #
  130. # notice that the functio name is another() rather than index()
  131. # the functions for each app.route needs to have different names
  132. # Displays profile page for a user
  133. @app.route('/profile',methods=['GET'])
  134. def profile():
  135. # Get uid from url
  136. uid = request.args.get('uid')
  137. # Check if username is for user themselves, their friend's profile, or stranger's profile
  138. self_uid = request.cookies.get('uid')
  139. self_username = request.cookies.get('username')
  140. # See if uid in friends or friend_requests or self ( means can't send friend request )
  141. cmd = 'SELECT EXISTS( SELECT 1 FROM ( (SELECT uid2 AS uid FROM is_friends WHERE uid1 = :self_uid ) UNION (SELECT uid1 AS uid FROM is_friends WHERE uid2 = :self_uid ) ) AS uids WHERE uid=:uid)'
  142. cursor = g.conn.execute(text(cmd),self_uid = self_uid,uid=uid)
  143. exists_friends = []
  144. for result in cursor:
  145. exists_friends.append(result[0])
  146. cursor.close()
  147. is_friends = exists_friends[0]
  148. # See if uid in friends or friend_requests or self ( means can't send friend request )
  149. cmd = 'SELECT EXISTS( SELECT 1 FROM ( (SELECT sender as uid FROM friend_requests WHERE receiver = :self_uid ) UNION (SELECT receiver as uid FROM friend_requests WHERE sender=:self_uid) ) AS uids WHERE uid=:uid)'
  150. cursor = g.conn.execute(text(cmd),self_uid = self_uid,uid=uid)
  151. exists_pending_friends = []
  152. for result in cursor:
  153. exists_pending_friends.append(result[0])
  154. cursor.close()
  155. is_pending_friends = exists_pending_friends[0]
  156. # Show the user's own saved quotes and recommended quotes
  157. if(uid == self_uid):
  158. cmd = 'SELECT q.qid as qid, q.content as content, a.aid as aid, a.name as author FROM saved_quotes sq INNER JOIN quotes q ON sq.qid = q.qid INNER JOIN users u ON sq.uid = u.uid INNER JOIN authors a on q.author = a.aid WHERE u.uid = :uid and q.num_approvals >= 10 LIMIT 5'
  159. cursor = g.conn.execute(text(cmd),uid=uid)
  160. profile_quotes = []
  161. for result in cursor:
  162. profile_quotes.append((result['qid'],result['content'],result['aid'],result['author'])) # can also be accessed using result[0]
  163. cursor.close()
  164. # Get all friend requests
  165. cmd = 'SELECT friend_requests.sender AS sender, users.username AS username, users.name AS name from friend_requests,users WHERE friend_requests.sender = users.uid and friend_requests.receiver = :uid'
  166. cursor = g.conn.execute(text(cmd),uid=uid)
  167. friend_requests = []
  168. for result in cursor:
  169. friend_requests.append((result['sender'],result['username'],result['name'])) # can also be accessed using result[0]
  170. cursor.close()
  171. # Render
  172. context = dict(username = self_username, uid=uid,profile_quotes = profile_quotes,user_relation='self',friend_requests = friend_requests)
  173. return render_template("profile.html", **context)
  174. # Show friend's saved quotes and shared quotes
  175. elif(is_friends == True):
  176. # Get friend username
  177. cmd = 'SELECT username FROM users WHERE users.uid = :uid '
  178. cursor = g.conn.execute(text(cmd),uid=uid)
  179. names = []
  180. for result in cursor:
  181. names.append(result['username'])
  182. cursor.close()
  183. friend_name = names[0]
  184. # Select friend's saved quotes
  185. cmd = 'SELECT q.qid as qid, q.content as content, a.aid as aid, a.name as author FROM saved_quotes sq INNER JOIN quotes q ON sq.qid = q.qid INNER JOIN users u ON sq.uid = u.uid INNER JOIN authors a on q.author = a.aid WHERE u.uid = :uid and q.num_approvals >= 10 LIMIT 5'
  186. cursor = g.conn.execute(text(cmd),uid=uid)
  187. profile_quotes = []
  188. for result in cursor:
  189. profile_quotes.append((result['qid'],result['content'],result['aid'],result['author'])) # can also be accessed using result[0]
  190. cursor.close()
  191. # Select friend's shared quotes
  192. cmd = 'SELECT qid, content, aid, name FROM ((SELECT quotes.qid, content, aid, name FROM saved_quotes,quotes,authors WHERE saved_quotes.uid = :self_uid and saved_quotes.qid = quotes.qid and authors.aid = quotes.author) INTERSECT (SELECT quotes.qid, content, aid, name FROM saved_quotes,quotes,authors WHERE saved_quotes.uid = :uid and saved_quotes.qid = quotes.qid and authors.aid = quotes.author)) AS shared_quotes LIMIT 5'
  193. cursor = g.conn.execute(text(cmd),self_uid=self_uid,uid=uid)
  194. shared_quotes = []
  195. for result in cursor:
  196. saved_quotes.append((result['qid'],result['content'],result['aid'],result['name'])) # can also be accessed using result[0]
  197. cursor.close()
  198. # Render
  199. context = dict(username = friend_name,self_uid = self_uid,uid=uid, profile_quotes = profile_quotes, shared_quotes = shared_quotes,user_relation='friend')
  200. return render_template("profile.html", **context)
  201. elif(is_pending_friends):
  202. # Get friend username
  203. cmd = 'SELECT username FROM users WHERE users.uid = :uid '
  204. cursor = g.conn.execute(text(cmd),uid=uid)
  205. names = []
  206. for result in cursor:
  207. names.append(result['username'])
  208. cursor.close()
  209. friend_name = names[0]
  210. # Select friend's saved quotes
  211. cmd = 'SELECT q.qid as qid, q.content as content, a.aid as aid, a.name as author FROM saved_quotes sq INNER JOIN quotes q ON sq.qid = q.qid INNER JOIN users u ON sq.uid = u.uid INNER JOIN authors a on q.author = a.aid WHERE u.uid = :uid and q.num_approvals >= 10 LIMIT 5'
  212. cursor = g.conn.execute(text(cmd),uid=uid)
  213. profile_quotes = []
  214. for result in cursor:
  215. profile_quotes.append((result['qid'],result['content'],result['aid'],result['author'])) # can also be accessed using result[0]
  216. cursor.close()
  217. # Select friend's shared quotes
  218. cmd = 'SELECT qid, content, aid, name FROM ((SELECT quotes.qid, content, aid, name FROM saved_quotes,quotes,authors WHERE saved_quotes.uid = :self_uid and saved_quotes.qid = quotes.qid and authors.aid = quotes.author) INTERSECT (SELECT quotes.qid, content, aid, name FROM saved_quotes,quotes,authors WHERE saved_quotes.uid = :uid and saved_quotes.qid = quotes.qid and authors.aid = quotes.author)) AS shared_quotes LIMIT 5'
  219. cursor = g.conn.execute(text(cmd),self_uid=self_uid,uid=uid)
  220. shared_quotes = []
  221. for result in cursor:
  222. saved_quotes.append((result['qid'],result['content'],result['aid'],result['name'])) # can also be accessed using result[0]
  223. cursor.close()
  224. # Render
  225. context = dict(username = friend_name,self_uid = self_uid,uid=uid, profile_quotes = profile_quotes, shared_quotes = shared_quotes,user_relation='is_pending_friends')
  226. return render_template("profile.html", **context)
  227. # Show stranger's saved_quotes and shared quotes
  228. else:
  229. # Get stranger username
  230. cmd = 'SELECT username FROM users WHERE users.uid = :uid '
  231. cursor = g.conn.execute(text(cmd),uid=uid)
  232. names = []
  233. for result in cursor:
  234. names.append(result['username'])
  235. cursor.close()
  236. stranger_name = names[0]
  237. # Select stranger's saved quotes
  238. cmd = 'SELECT q.qid as qid, q.content as content, a.aid as aid, a.name as author FROM saved_quotes sq INNER JOIN quotes q ON sq.qid = q.qid INNER JOIN users u ON sq.uid = u.uid INNER JOIN authors a on q.author = a.aid WHERE u.uid = :uid and q.num_approvals >= 10 LIMIT 5'
  239. cursor = g.conn.execute(text(cmd),uid=uid)
  240. profile_quotes = []
  241. for result in cursor:
  242. profile_quotes.append((result['qid'],result['content'],result['aid'],result['author'])) # can also be accessed using result[0]
  243. cursor.close()
  244. # Select stranger's shared quotes
  245. cmd = 'SELECT qid, content, aid, name FROM ((SELECT quotes.qid, content, aid, name FROM saved_quotes,quotes,authors WHERE saved_quotes.uid = :self_uid and saved_quotes.qid = quotes.qid and authors.aid = quotes.author) INTERSECT (SELECT quotes.qid, content, aid, name FROM saved_quotes,quotes,authors WHERE saved_quotes.uid = :uid and saved_quotes.qid = quotes.qid and authors.aid = quotes.author)) AS shared_quotes LIMIT 5'
  246. cursor = g.conn.execute(text(cmd),self_uid=self_uid,uid=uid)
  247. shared_quotes = []
  248. for result in cursor:
  249. shared_quotes.append((result['qid'],result['content'],result['aid'],result['author'])) # can also be accessed using result[0]
  250. cursor.close()
  251. # Render
  252. context = dict(username = stranger_name,self_uid = self_uid,uid=uid,profile_quotes = profile_quotes, shared_quotes = shared_quotes,user_relation='stranger')
  253. return render_template("profile.html", **context)
  254. # Displays page for search results
  255. @app.route('/search',methods=['GET'])
  256. def search():
  257. query = request.args.get('query').lower()
  258. quotes_cmd = "SELECT * FROM quotes WHERE LOWER(quotes.content) LIKE LOWER(:query) and quotes.num_approvals >= 10"
  259. quotes_cursor = g.conn.execute(text(quotes_cmd),query='%' + query + '%')
  260. quotes = []
  261. for result in quotes_cursor:
  262. quotes.append((result['qid'],result['content']))
  263. quotes_cursor.close()
  264. authors_cmd = "SELECT * FROM authors WHERE LOWER(authors.name) LIKE LOWER(:query)"
  265. authors_cursor = g.conn.execute(text(authors_cmd),query='%' + query + '%')
  266. authors = []
  267. for result in authors_cursor:
  268. authors.append((result['aid'],result['name']))
  269. authors_cursor.close()
  270. works_cmd = "SELECT * FROM works WHERE LOWER(works.name) LIKE LOWER(:query)"
  271. works_cursor = g.conn.execute(text(works_cmd),query='%' + query + '%')
  272. works = []
  273. for result in works_cursor:
  274. works.append((result['wid'],result['name']))
  275. works_cursor.close()
  276. users_cmd = "SELECT * FROM users WHERE LOWER(users.username) LIKE LOWER(:query) or LOWER(users.name) LIKE LOWER(:query)"
  277. users_cursor = g.conn.execute(text(users_cmd),query='%' + query + '%')
  278. users = []
  279. for result in users_cursor:
  280. users.append((result['uid'],result['name'],result['username']))
  281. users_cursor.close()
  282. tags_cmd = "SELECT * FROM tags WHERE LOWER(tags.name) LIKE LOWER(:query)"
  283. tags_cursor = g.conn.execute(text(tags_cmd),query='%' + query + '%')
  284. tags = []
  285. for result in tags_cursor:
  286. tags.append(result['name'])
  287. tags_cursor.close()
  288. context = dict(quotes = quotes, authors = authors,works = works,query=query,users=users,tags=tags)
  289. return render_template("search.html", **context)
  290. # Displays page for a quote
  291. @app.route('/quote',methods=['GET'])
  292. def quote():
  293. qid = request.args.get('qid')
  294. cmd = 'SELECT q.content as content, a.aid as aid, a.name as author, w.wid as wid, w.name as work FROM quotes q INNER JOIN authors a ON q.author = a.aid LEFT JOIN works w ON q.work = w.wid WHERE q.qid = (:qid)'
  295. cursor = g.conn.execute(text(cmd),qid=qid)
  296. quotes = []
  297. for result in cursor:
  298. quotes.append((result['content'],result['aid'],result['author'],result['wid'],result['work']))
  299. cursor.close()
  300. # Get tags
  301. cmd = 'SELECT tag FROM quote_tags WHERE quote_tags.qid =:qid'
  302. cursor = g.conn.execute(text(cmd),qid=qid)
  303. tags = []
  304. for result in cursor:
  305. tags.append(result[0])
  306. cursor.close()
  307. # Check if quote is saved in your quotes
  308. uid = request.cookies.get('uid')
  309. cmd= 'SELECT EXISTS(SELECT * FROM saved_quotes WHERE saved_quotes.qid= :qid and saved_quotes.uid = :uid)'
  310. cursor = g.conn.execute(text(cmd),qid=qid,uid=uid)
  311. is_saveds = []
  312. for result in cursor:
  313. is_saveds.append(result[0])
  314. cursor.close()
  315. is_saved= is_saveds[0]
  316. context = dict(data = quotes[0], tags = tags,is_saved=is_saved,uid=uid,qid=qid)
  317. return render_template("quote.html", **context)
  318. # Lets user save quotes to profile
  319. @app.route('/saveQuote',methods=['POST'])
  320. def saveQuote():
  321. uid=request.form['uid']
  322. qid=request.form['qid']
  323. # Check quote not saved
  324. cmd = 'SELECT EXISTS (SELECT 1 FROM saved_quotes WHERE saved_quotes.qid=:qid and saved_quotes.uid=:uid)'
  325. cursor = g.conn.execute(text(cmd),qid=qid,uid=uid)
  326. not_saveds = []
  327. for result in cursor:
  328. not_saveds.append(result[0])
  329. cursor.close()
  330. not_saved = not not_saveds[0]
  331. # Perform appropriate actions
  332. if(not_saved):
  333. # Insert
  334. cmd='INSERT INTO saved_quotes VALUES( :uid, :qid)'
  335. cursor = g.conn.execute(text(cmd),uid=uid,qid=qid)
  336. cursor.close()
  337. # flash('Successfully saved quote to your profile!')
  338. return redirect('/profile?uid=' + uid)
  339. else:
  340. # flash('Error: quote is already saved to your profile.')
  341. return redirect('/quote?qid=' + qid)
  342. @app.route('/shareQuote',methods=['POST'])
  343. def shareQuote():
  344. friend_username = request.form['friend_username']
  345. uid = request.form['uid']
  346. qid = request.form['qid']
  347. mtimestamp = request.form['mtimestamp']
  348. # Get friend_uid from username
  349. cmd = 'SELECT uid FROM users WHERE users.username=:friend_username'
  350. cursor = g.conn.execute(text(cmd),friend_username=friend_username)
  351. friend_uids = []
  352. for result in cursor:
  353. friend_uids.append(result['uid'])
  354. cursor.close()
  355. friend_uid = -1
  356. if(len(friend_uids) == 0):
  357. redirect('/quote?qid=' + qid)
  358. else:
  359. friend_uid = friend_uids[0]
  360. # Insert message into table
  361. cmd = 'INSERT INTO messages(sender,receiver,qid,content,mtimestamp) VALUES(:sender,:receiver,:qid,:content,:mtimestamp)'
  362. cursor = g.conn.execute(text(cmd),sender=uid,receiver=friend_uid, qid=qid, content='', mtimestamp = mtimestamp)
  363. cursor.close()
  364. # return redirect('/conversation?uid=' + sender + "&friend_uid=" + receiver)
  365. return redirect('/conversation?uid='+str(uid) + "&friend_uid=" + str(friend_uid))
  366. @app.route('/tag')
  367. def tag():
  368. name=request.args.get('name')
  369. # Get authors
  370. cmd = 'SELECT authors.name AS name,authors.aid AS aid FROM author_tags,authors WHERE author_tags.aid=authors.aid and author_tags.tag=:name'
  371. cursor = g.conn.execute(text(cmd),name=name)
  372. authors = []
  373. for result in cursor:
  374. authors.append((result['aid'],result['name']))
  375. cursor.close()
  376. # Get quotes
  377. cmd = 'SELECT quotes.qid AS qid, quotes.content AS content FROM quote_tags,quotes WHERE quote_tags.qid=quotes.qid and quote_tags.tag=:name'
  378. cursor = g.conn.execute(text(cmd),name=name)
  379. quotes = []
  380. for result in cursor:
  381. quotes.append((result['qid'],result['content']))
  382. cursor.close()
  383. # Get works
  384. cmd = 'SELECT works.wid AS wid, works.name AS name FROM work_tags,works WHERE work_tags.wid=works.wid and work_tags.tag=:name'
  385. cursor = g.conn.execute(text(cmd),name=name)
  386. works = []
  387. for result in cursor:
  388. works.append((result['wid'],result['name']))
  389. cursor.close()
  390. context = dict(tag=name, works=works,quotes=quotes,authors=authors)
  391. return render_template("tag.html",**context);
  392. # Displays page for a work
  393. @app.route('/work',methods=['GET'])
  394. def work():
  395. wid = request.args.get('wid')
  396. cmd = 'SELECT w.name as work, a.aid as aid, a.name as author FROM works w, authors a WHERE w.wid = (:wid) and w.aid = a.aid'
  397. cursor = g.conn.execute(text(cmd),wid=wid)
  398. works = []
  399. for result in cursor:
  400. works.append((result['work'],result['aid'],result['author']))
  401. cursor.close()
  402. # Get tags
  403. cmd = 'SELECT tag FROM work_tags WHERE work_tags.wid =:wid'
  404. cursor = g.conn.execute(text(cmd),wid=wid)
  405. tags = []
  406. for result in cursor:
  407. tags.append(result[0])
  408. cursor.close()
  409. context = dict(data = works[0],tags=tags)
  410. return render_template("work.html", **context)
  411. # Displays page for an authors
  412. @app.route('/author',methods=['GET'])
  413. def author():
  414. aid = request.args.get('aid')
  415. cmd = 'SELECT name, bio FROM authors a WHERE a.aid = (:aid)'
  416. cursor = g.conn.execute(text(cmd),aid=aid)
  417. authors = []
  418. for result in cursor:
  419. authors.append((result['name'], result['bio']))
  420. cursor.close()
  421. cmd = 'SELECT qid, content FROM quotes q, authors a WHERE a.aid = (:aid) and q.author = a.aid and q.num_approvals >= 10 LIMIT 5'
  422. cursor = g.conn.execute(text(cmd),aid=aid)
  423. quotes = []
  424. for result in cursor:
  425. quotes.append((result['qid'],result['content']))
  426. cursor.close()
  427. cmd = 'SELECT wid, w.name as work FROM works w, authors a WHERE a.aid = (:aid) and w.aid = a.aid LIMIT 5'
  428. cursor = g.conn.execute(text(cmd),aid=aid)
  429. works = []
  430. for result in cursor:
  431. works.append((result['wid'],result['work']))
  432. cursor.close()
  433. # Get tags
  434. cmd = 'SELECT tag FROM author_tags WHERE author_tags.aid =:aid'
  435. cursor = g.conn.execute(text(cmd),aid=aid)
  436. tags = []
  437. for result in cursor:
  438. tags.append(result[0])
  439. cursor.close()
  440. context = dict(data = authors[0], quotes = quotes, works = works,tags=tags)
  441. return render_template("author.html", **context)
  442. # Example of adding new data to the database
  443. @app.route('/add', methods=['POST'])
  444. def add():
  445. name = request.form['name']
  446. cmd = 'INSERT INTO test(name) VALUES (:name1), (:name2)';
  447. g.conn.execute(text(cmd), name1 = name, name2 = name);
  448. return redirect('/')
  449. # Retrieves cookie for user information / login
  450. @app.route('/getcookie')
  451. def getcookie():
  452. uid = request.cookies.get('uid')
  453. username = request.cookies.get('username')
  454. return '<h1>welcome '+ username + ":" + uid +'</h1>'
  455. # Logs user in and redirects
  456. @app.route('/setcookie', methods = ['POST', 'GET'])
  457. def setcookie():
  458. if request.method == 'POST':
  459. username = request.form['Username']
  460. password = request.form['Password']
  461. # Check username is in table of usernames
  462. cmd = 'SELECT EXISTS(SELECT * FROM users WHERE users.username = :username)'
  463. cursor = g.conn.execute(text(cmd),username = username)
  464. user_exists = []
  465. for result in cursor:
  466. user_exists.append((result[0]))
  467. cursor.close()
  468. user_exists = user_exists[0]
  469. if(user_exists == False):
  470. context = dict(message = "Incorrect username or password!!")
  471. return render_template("login.html",**context)
  472. # Check username and password correct
  473. cmd = 'SELECT uid,password FROM users WHERE users.username = (:username)';
  474. cursor = g.conn.execute(text(cmd),username = username)
  475. uinfo = []
  476. for result in cursor:
  477. uinfo.append((result['password'],result['uid']))
  478. cursor.close()
  479. if(uinfo[0][0] == password):
  480. resp = app.make_response(redirect('/'))
  481. resp.set_cookie('uid', str(uinfo[0][1]))
  482. resp.set_cookie('username', str(username))
  483. return resp
  484. # Error login page
  485. else:
  486. context = dict(message = "Incorrect username or password!!")
  487. return render_template("login.html",**context)
  488. # Renders page where users can login
  489. @app.route('/login')
  490. def login():
  491. return render_template("login.html")
  492. # Renders page where users can sign up
  493. @app.route('/signup')
  494. def signup():
  495. return render_template("signup.html")
  496. # Adds new user to database and redirects to login page
  497. @app.route('/adduser', methods=['POST','GET'])
  498. def adduser():
  499. if request.method == 'POST':
  500. # Get information from form
  501. name = request.form['Name']
  502. username = request.form['Username']
  503. password = request.form['Password']
  504. # Get unique uid for user
  505. cmd = 'SELECT MAX(uid) FROM users';
  506. cursor = g.conn.execute(text(cmd))
  507. uid_count = []
  508. for result in cursor:
  509. uid_count.append(result[0])
  510. cursor.close()
  511. uid = uid_count[0] + 1
  512. # Check username is unique
  513. cmd = 'SELECT EXISTS(SELECT 1 FROM users WHERE users.username = :username )'
  514. cursor = g.conn.execute(text(cmd),username = username )
  515. unique = []
  516. for result in cursor:
  517. unique.append(result[0]);
  518. if(unique[0] == True):
  519. context = dict(message = "Username is already taken - please choose another! :)")
  520. #flash("Username is already taken - please choose another! :)")
  521. return render_template("signup.html",**context)
  522. # Check that password isn't blank and is at least 5 characters
  523. elif(len(password) < 5):
  524. context = dict(message = "Password must be at least 5 characters! Try again please. :)")
  525. return render_template("signup.html", **context)
  526. # Render successful sign up if true
  527. else:
  528. cmd = 'INSERT INTO users VALUES( :uid, :name, :username, :password)'
  529. cursor = g.conn.execute(text(cmd),uid = uid,name = name,username = username, password = password)
  530. cursor.close()
  531. context = dict(message = "Successfully signed up! ^-^ Please try logging in right now.")
  532. return render_template("login.html",**context)
  533. # Displays friends lsit of users
  534. @app.route('/friends')
  535. def friends():
  536. uid = request.args.get('uid')
  537. # Get username of user
  538. cmd = 'SELECT username FROM users WHERE users.uid = :uid'
  539. cursor = g.conn.execute(text(cmd),uid=uid )
  540. usernames= []
  541. for result in cursor:
  542. usernames.append(result['username'])
  543. cursor.close()
  544. username = usernames[0]
  545. # Select friends
  546. cmd = 'SELECT * FROM users WHERE users.uid IN ((SELECT uid2 FROM is_friends WHERE uid1 = :uid ) UNION (SELECT uid1 FROM is_friends WHERE uid2 = :uid ))'
  547. cursor = g.conn.execute(text(cmd),uid=uid )
  548. friends = [];
  549. for result in cursor:
  550. friends.append((result['name'],result['username'],result['uid']))
  551. cursor.close()
  552. context = dict(friends = friends,username = username,uid=uid)
  553. return render_template("friends.html",**context)
  554. # Shows list of users you've messaged
  555. @app.route('/inbox')
  556. def messages():
  557. uid = request.args.get('uid')
  558. # Get username of user
  559. cmd = 'SELECT username FROM users WHERE users.uid = :uid '
  560. cursor = g.conn.execute(text(cmd),uid=uid )
  561. usernames= []
  562. for result in cursor:
  563. usernames.append(result['username'])
  564. cursor.close()
  565. username = usernames[0]
  566. # Get friends usernames and uid
  567. cmd = 'SELECT * FROM ((SELECT users2.username AS username, users2.uid AS uid FROM messages,quotes,users, users AS users2 WHERE messages.sender = :uid and messages.qid = quotes.qid and messages.sender = users.uid and messages.receiver = users2.uid ORDER BY mtimestamp DESC) UNION (SELECT users.username AS username, users.uid AS uid FROM messages,quotes,users, users AS users2 WHERE messages.receiver = :uid and messages.qid = quotes.qid and messages.sender = users.uid and messages.receiver = users2.uid ORDER BY mtimestamp DESC)) AS messaged_friends'
  568. cursor = g.conn.execute(text(cmd),uid=uid )
  569. friends = [];
  570. for result in cursor:
  571. friends.append((result['username'],result['uid']))
  572. cursor.close()
  573. context = dict(username=username, uid=uid, friends = friends,is_friends=True)
  574. return render_template("inbox.html", **context)
  575. # Gets conversations between two users
  576. @app.route('/conversation')
  577. def conversation():
  578. uid = request.args.get('uid')
  579. friend_uid = request.args.get('friend_uid')
  580. # Get username of user
  581. cmd = 'SELECT username FROM users WHERE users.uid = :uid '
  582. cursor = g.conn.execute(text(cmd),uid=uid )
  583. usernames= []
  584. for result in cursor:
  585. usernames.append(result['username'])
  586. cursor.close()
  587. username = usernames[0]
  588. # Get username of friend
  589. cmd = 'SELECT username FROM users WHERE users.uid = :uid '
  590. cursor = g.conn.execute(text(cmd),uid=friend_uid )
  591. friend_usernames= []
  592. for result in cursor:
  593. friend_usernames.append(result['username'])
  594. cursor.close()
  595. friend_username = friend_usernames[0]
  596. # Get messages between you and friend
  597. cmd = 'SELECT users.name AS sender, users2.name AS receiver, messages.content AS message,quotes.content AS quote,quotes.qid AS qid, messages.mtimestamp AS mtimestamp FROM messages LEFT JOIN quotes ON messages.qid = quotes.qid INNER JOIN users ON messages.sender = users.uid INNER JOIN users AS users2 ON messages.receiver = users2.uid WHERE ((messages.sender = :uid and messages.receiver = :friend_uid) or (messages.receiver = :uid and messages.sender = :friend_uid)) ORDER BY mtimestamp DESC'
  598. cursor = g.conn.execute(text(cmd),friend_uid=friend_uid,uid = uid )
  599. messages = []
  600. for result in cursor:
  601. messages.append((result['sender'],result['receiver'],result['message'],result['quote'],result['qid'],result['mtimestamp']))
  602. cursor.close()
  603. # Filter out null quotes
  604. for i in range(0,len(messages)):
  605. if(messages[i][3] == None):
  606. messages[i] = (messages[i][0],messages[i][1],messages[i][2],"",messages[i][4],messages[i][5])
  607. context = dict(username=username,uid=uid, friend_username = friend_username,friend_uid=friend_uid, messages = messages)
  608. return render_template("conversation.html", **context)
  609. @app.route('/sendMessage',methods=['POST'])
  610. def sendMessage():
  611. sender = int(request.form['sender'])
  612. receiver = int(request.form['receiver'])
  613. message = request.form['message']
  614. mtimestamp = request.form['mtimestamp']
  615. # Insert message into table
  616. cmd = 'INSERT INTO messages(sender,receiver,qid,content,mtimestamp) VALUES( :sender, :receiver, NULL, :message, :mtimestamp)'
  617. cursor = g.conn.execute(text(cmd),sender=sender,receiver=receiver, message=message, mtimestamp = mtimestamp)
  618. cursor.close()
  619. # return redirect('/conversation?uid=' + sender + "&friend_uid=" + receiver)
  620. return redirect('/conversation?uid='+str(sender) + "&friend_uid=" + str(receiver))
  621. @app.route('/addFriend',methods=['POST'])
  622. def addFriend():
  623. friend_uid = request.form['friend_uid']
  624. uid = request.form['uid']
  625. # Insert friend request into table
  626. cmd = 'INSERT INTO friend_requests VALUES( :sender, :receiver)'
  627. cursor = g.conn.execute(text(cmd),sender=uid,receiver=friend_uid)
  628. cursor.close()
  629. return redirect('/profile?uid='+friend_uid)
  630. @app.route('/deleteFriend',methods=['POST'])
  631. def deleteFriend():
  632. friend_uid = request.form['friend_uid']
  633. uid = request.form['uid']
  634. # Dlete friend request into table
  635. uid1 = min(uid,friend_uid)
  636. uid2 = max(uid,friend_uid)
  637. cmd = 'DELETE FROM is_friends WHERE uid1= :uid1 and uid2=:uid2'
  638. cursor = g.conn.execute(text(cmd),uid1=uid1,uid2=uid2)
  639. cursor.close()
  640. return redirect('/profile?uid='+friend_uid)
  641. @app.route('/rejectFriendRequest',methods=['POST'])
  642. def rejectFriendRequest():
  643. uid = request.form['uid']
  644. friend_uid = request.form['friend_uid']
  645. # Delete from friend request table
  646. cmd = 'DELETE FROM friend_requests WHERE friend_requests.sender = :friend_uid and friend_requests.receiver = :uid'
  647. cursor = g.conn.execute(text(cmd),friend_uid=friend_uid,uid=uid)
  648. cursor.close()
  649. return redirect('/profile?uid=' + uid)
  650. @app.route('/acceptFriendRequest',methods =['POST'])
  651. def acceptFriendRequest():
  652. uid = request.form['uid']
  653. friend_uid = request.form['friend_uid']
  654. # Delete from friend request table
  655. cmd = 'DELETE FROM friend_requests WHERE friend_requests.sender = :friend_uid and friend_requests.receiver = :uid'
  656. cursor = g.conn.execute(text(cmd),friend_uid=friend_uid,uid=uid)
  657. cursor.close()
  658. # Insert into friends table
  659. uid1 = min(uid,friend_uid)
  660. uid2 = max(uid,friend_uid)
  661. cmd = 'INSERT INTO is_friends VALUES( :uid1, :uid2)'
  662. cursor = g.conn.execute(text(cmd),uid1=uid1,uid2=uid2)
  663. cursor.close()
  664. return redirect('/profile?uid=' + uid)
  665. @app.route('/vote')
  666. def vote():
  667. """
  668. request is a special object that Flask provides to access web request information:
  669. request.method: "GET" or "POST"
  670. request.form: if the browser submitted a form, this contains the data in the form
  671. request.args: dictionary of URL arguments e.g., {a:1, b:2} for http://localhost?a=1&b=2
  672. See its API: http://flask.pocoo.org/docs/0.10/api/#incoming-request-data
  673. """
  674. uid = request.cookies.get('uid')
  675. unapproved_cmd = "SELECT q.qid as qid, q.content as content, a.aid as aid, a.name as author, w.wid as wid, w.name as work FROM quotes q INNER JOIN authors a ON q.author = a.aid LEFT JOIN works w on q.work = w.wid WHERE q.num_approvals < 10 ORDER BY q.added_time ASC LIMIT 5"
  676. unapproved_cursor = g.conn.execute(text(unapproved_cmd))
  677. unapproved_quotes = []
  678. for result in unapproved_cursor:
  679. unapproved_quotes.append((result['qid'],result['content'],result['aid'],result['author'],result['wid'],result['work']))
  680. unapproved_cursor.close()
  681. cmd = 'SELECT qid FROM user_approves WHERE user_approves.uid = :uid'
  682. cursor = g.conn.execute(text(cmd),uid = uid)
  683. user_approved_quotes = []
  684. for result in cursor:
  685. user_approved_quotes.append(result[0])
  686. cursor.close()
  687. context = dict(unapproved_quotes = unapproved_quotes,uid = uid,user_approved_quotes = user_approved_quotes)
  688. return render_template("voting.html", **context)
  689. @app.route('/approveQuote',methods=['POST'])
  690. def approveQuote():
  691. qid = request.form['qid']
  692. uid = request.form['uid']
  693. # updates user approves table
  694. cmd = 'INSERT INTO user_approves VALUES(:uid,:qid)'
  695. cursor = g.conn.execute(text(cmd),qid=qid,uid=uid)
  696. cursor.close()
  697. # update the quotes table
  698. cmd = 'UPDATE quotes SET num_approvals = num_approvals + 1 WHERE quotes.qid = :qid'
  699. cursor = g.conn.execute(text(cmd),qid=qid)
  700. cursor.close()
  701. return redirect('/vote')
  702. @app.teardown_request
  703. def teardown_request(exception):
  704. """
  705. At the end of the web request, this makes sure to close the database connection.
  706. If you don't the database could run out of memory!
  707. """
  708. try:
  709. g.conn.close()
  710. except Exception as e:
  711. pass
  712. # Main function for running app
  713. if __name__ == "__main__":
  714. import click
  715. @click.command()
  716. @click.option('--debug', is_flag=True)
  717. @click.option('--threaded', is_flag=True)
  718. @click.argument('HOST', default='0.0.0.0')
  719. @click.argument('PORT', default=8111, type=int)
  720. def run(debug, threaded, host, port):
  721. """
  722. This function handles command line parameters.
  723. Run the server using
  724. python server.py
  725. Show the help text using
  726. python server.py --help
  727. """
  728. HOST, PORT = host, port
  729. print "running on %s:%d" % (HOST, PORT)
  730. app.run(host=HOST, port=PORT, debug=debug, threaded=threaded)
  731. run()