|
@ -1,3 +1,4 @@ |
|
|
|
|
|
from functools import wraps |
|
|
from flask import Flask, request, render_template, send_from_directory, abort, redirect, session |
|
|
from flask import Flask, request, render_template, send_from_directory, abort, redirect, session |
|
|
from flask_sqlalchemy import SQLAlchemy |
|
|
from flask_sqlalchemy import SQLAlchemy |
|
|
from flask_limiter import Limiter |
|
|
from flask_limiter import Limiter |
|
@ -61,16 +62,31 @@ class Like(db.Model): |
|
|
|
|
|
|
|
|
db.create_all() |
|
|
db.create_all() |
|
|
|
|
|
|
|
|
|
|
|
def need_verify(func): |
|
|
|
|
|
@wraps(func) |
|
|
|
|
|
def warp(*args, **kwargs): |
|
|
|
|
|
print(session) |
|
|
|
|
|
if not session.get('verified'): |
|
|
|
|
|
abort(403) |
|
|
|
|
|
return func(*args, **kwargs) |
|
|
|
|
|
|
|
|
|
|
|
return warp |
|
|
|
|
|
|
|
|
@app.route('/img/<path:path>') |
|
|
@app.route('/img/<path:path>') |
|
|
def send_img(path): |
|
|
def send_img(path): |
|
|
return send_from_directory('static/img', path) |
|
|
return send_from_directory('static/img', path) |
|
|
|
|
|
|
|
|
@app.route('/ordinary/set_session') |
|
|
|
|
|
@limiter.limit("2 / hour; 1 / 5 minute") |
|
|
|
|
|
def set_session(): |
|
|
|
|
|
|
|
|
@app.route('/ordinary/verify', methods=['POST']) |
|
|
|
|
|
@limiter.limit("3 / hour") |
|
|
|
|
|
def verify(): |
|
|
|
|
|
for name, ques, hint, ans in C.verify: |
|
|
|
|
|
if request.form.get(name) != ans: |
|
|
|
|
|
return WRONG_ANS_HTML, 401 |
|
|
|
|
|
|
|
|
|
|
|
session.permanent = True |
|
|
|
|
|
session['verified'] = True |
|
|
if 'uid' not in session: |
|
|
if 'uid' not in session: |
|
|
session['uid'] = random.randint(0, 2000000000) |
|
|
session['uid'] = random.randint(0, 2000000000) |
|
|
session.permanent = True |
|
|
|
|
|
return redirect('.') |
|
|
return redirect('.') |
|
|
|
|
|
|
|
|
@app.route('/ordinary/') |
|
|
@app.route('/ordinary/') |
|
@ -78,9 +94,7 @@ def can_list(): |
|
|
key = request.args.get('key') |
|
|
key = request.args.get('key') |
|
|
sort_by = request.args.get('sort_by', 'time') |
|
|
sort_by = request.args.get('sort_by', 'time') |
|
|
|
|
|
|
|
|
if 'uid' not in session: |
|
|
|
|
|
return redirect('set_session') |
|
|
|
|
|
uid = session['uid'] |
|
|
|
|
|
|
|
|
uid = session.get('uid') |
|
|
|
|
|
|
|
|
q = Candidate.query |
|
|
q = Candidate.query |
|
|
q = q.order_by(db.desc('likeNum')) if sort_by=='likeNum' else q.order_by(db.desc('id')) |
|
|
q = q.order_by(db.desc('likeNum')) if sort_by=='likeNum' else q.order_by(db.desc('id')) |
|
@ -99,20 +113,16 @@ def can_list(): |
|
|
} for name, ques, hint, ans in C.verify |
|
|
} 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, base_toot_url='https://%s/web/statuses/' % C.domain) |
|
|
|
|
|
|
|
|
return render_template('list.html', pagination=pag, vs=vs, verified=session.get('verified'), showPrivate=(key==C.key), sort_by=sort_by, key=key, base_toot_url='https://%s/web/statuses/' % C.domain) |
|
|
|
|
|
|
|
|
@app.route('/ordinary/new', methods=['POST']) |
|
|
@app.route('/ordinary/new', methods=['POST']) |
|
|
@limiter.limit("5 / hour; 1 / 2 second") |
|
|
@limiter.limit("5 / hour; 1 / 2 second") |
|
|
|
|
|
@need_verify |
|
|
def new_one(): |
|
|
def new_one(): |
|
|
|
|
|
|
|
|
content = request.form.get('text') |
|
|
content = request.form.get('text') |
|
|
private = request.form.get('privateText') |
|
|
private = request.form.get('privateText') |
|
|
url = request.form.get('url') |
|
|
url = request.form.get('url') |
|
|
|
|
|
|
|
|
for name, ques, hint, ans in C.verify: |
|
|
|
|
|
if request.form.get(name) != ans: |
|
|
|
|
|
return WRONG_ANS_HTML, 401 |
|
|
|
|
|
|
|
|
|
|
|
if not content or len(content)>4000: abort(422) |
|
|
if not content or len(content)>4000: abort(422) |
|
|
if private and len(private)>1000: abort(422) |
|
|
if private and len(private)>1000: abort(422) |
|
|
if url and not re.match('https://(cloud\.tsinghua\.edu\.cn/f/[0-9a-z]+/(\?dl=1)?|closed\.social/safeShare/\d([a-zA-Z]+)?)', url): abort(422) |
|
|
if url and not re.match('https://(cloud\.tsinghua\.edu\.cn/f/[0-9a-z]+/(\?dl=1)?|closed\.social/safeShare/\d([a-zA-Z]+)?)', url): abort(422) |
|
@ -137,14 +147,9 @@ def new_one(): |
|
|
|
|
|
|
|
|
@app.route('/ordinary/judge', methods=['POST']) |
|
|
@app.route('/ordinary/judge', methods=['POST']) |
|
|
@limiter.limit("10 / hour; 1 / 2 second") |
|
|
@limiter.limit("10 / hour; 1 / 2 second") |
|
|
|
|
|
@need_verify |
|
|
def judge(): |
|
|
def judge(): |
|
|
|
|
|
|
|
|
group = request.form.get('groupType') |
|
|
group = request.form.get('groupType') |
|
|
|
|
|
|
|
|
for name, ques, hint, ans in C.verify: |
|
|
|
|
|
if request.form.get(name) != ans: |
|
|
|
|
|
return WRONG_ANS_HTML, 401 |
|
|
|
|
|
|
|
|
|
|
|
return redirect(C.groups.get(group)) |
|
|
return redirect(C.groups.get(group)) |
|
|
|
|
|
|
|
|
@limiter.limit("100 / hour; 2 / second") |
|
|
@limiter.limit("100 / hour; 2 / second") |
|
@ -178,6 +183,7 @@ def get_comments(toot): |
|
|
|
|
|
|
|
|
@limiter.limit("100 / hour") |
|
|
@limiter.limit("100 / hour") |
|
|
@app.route('/ordinary/<int:toot>/like', methods=['POST']) |
|
|
@app.route('/ordinary/<int:toot>/like', methods=['POST']) |
|
|
|
|
|
@need_verify |
|
|
def like(toot): |
|
|
def like(toot): |
|
|
c = Candidate.query.filter_by(toot=toot).first() |
|
|
c = Candidate.query.filter_by(toot=toot).first() |
|
|
if not c: |
|
|
if not c: |
|
|