|
|
- from flask import Flask, request, render_template, send_from_directory, abort, redirect, session
- from flask_sqlalchemy import SQLAlchemy
- from flask_limiter import Limiter
- from flask_limiter.util import get_remote_address
- import re
- import random
- from datetime import datetime
- from dateutil.tz import tzlocal
- import html2text
- from config_fudan import C
-
- app = Flask(__name__)
- app.config.from_object('config_fudan.C')
- app.secret_key = C.session_key
-
- limiter = Limiter(
- app,
- key_func=get_remote_address,
- default_limits=["50 / minute"],
- )
-
- db = SQLAlchemy(app)
-
- class Candidate(db.Model):
- id = db.Column(db.Integer, primary_key=True)
- content = db.Column(db.String(4000))
- private = db.Column(db.String(1000))
- time = db.Column(db.DateTime)
- likeNum = db.Column(db.Integer, default=0)
-
- # always increment 1 for the id of a new record
- __table_args__ = { 'sqlite_autoincrement': True }
-
- class Like(db.Model):
- id = db.Column(db.Integer, primary_key=True)
- cid = db.Column(db.Integer) # (member) id of class Candidate
- uid = db.Column(db.Integer) # id of user
-
- db.create_all()
-
- @app.route('/img/<path:path>')
- def send_img(path):
- return send_from_directory('static/img', path)
-
- @app.route('/ordinary/set_session')
- @limiter.limit("2 / hour; 1 / 5 minute")
- def set_session():
- if 'uid' not in session:
- session['uid'] = random.randint(0, 2000000000)
- session.permanent = True
- return redirect('.')
-
- @app.route('/ordinary/')
- def can_list():
- key = request.args.get('key')
- sort_by = request.args.get('sort_by', 'time')
-
- if 'uid' not in session:
- return redirect('set_session')
- uid = session['uid']
-
- q = Candidate.query
- q = q.order_by(db.desc('likeNum')) if sort_by=='likeNum' else q.order_by(db.desc('id'))
- pag = q.paginate(max_per_page=100)
-
- def check_like(c):
- c.liked = 'liked' if Like.query.filter_by(uid=uid, cid=c.id).count() else 'like'
- return c
-
- pag.items = map(check_like, pag.items)
-
- vs = [{
- 'name': name,
- 'ques': ques,
- 'hint': hint
- } for name, ques, hint, ans in C.verify
- ]
-
- return render_template('list.html', pagination=pag, vs=vs, showPrivate=(key==C.key), sort_by=sort_by, key=key, text1=C.text1, text2=C.text2)
-
- @app.route('/ordinary/new', methods=['POST'])
- @limiter.limit("5 / hour; 1 / 2 second")
- def new_one():
-
- content = request.form.get('text')
- private = request.form.get('privateText')
-
- for name, ques, hint, ans in C.verify:
- if request.form.get(name) != ans:
- return '''<html>
- <head>
- <meta charset='UTF-8'>
- <meta name='viewport' content='width=device-width initial-scale=1'>
- <title>错误</title>
- </head>
- <body>
- <h1>验证问题回答错误</h1>
- <a href="##" onclick="window.history.back()">回退</a>
- </body>
- </html>
- ''', 401
-
- if not content or len(content)>4000: abort(422)
- if private and len(private)>1000: abort(422)
-
- if not Candidate.query.filter_by(content=content).first():
- c = Candidate(
- content=content,
- private=private,
- time=datetime.now()
- )
- db.session.add(c)
- db.session.commit()
-
- return redirect(".")
-
- @limiter.limit("100 / hour")
- @app.route('/ordinary/<int:id>/like', methods=['POST'])
- def like(id):
- c = Candidate.query.get(id)
- if not c:
- abort(404)
-
- uid = session['uid']
- if not uid: abort(401)
- if Like.query.filter_by(uid=uid, cid=id).first():
- return '点赞过了', 403
-
- l = Like(uid=uid, cid=id)
- c.likeNum += 1
- db.session.add(l)
- db.session.commit()
-
- return str(c.likeNum)
-
- @app.route('/ordinary/<int:id>/delete', methods=['POST'])
- def delete(id):
- key = request.form.get('key')
- if key != C.key:
- abort(401)
-
- c = Candidate.query.get(id)
- if not c:
- abort(404)
-
- db.session.delete(c)
- db.session.commit()
-
- return redirect('..')
-
- if __name__ == '__main__':
- app.run(debug=True)
-
|