Browse Source

cookie维护点赞者,支持按赞数排序

fudan
欧醚 3 years ago
parent
commit
3a2522c4a5
Signed by: OmmyZhang GPG Key ID: 757D312E7C9D13F7
3 changed files with 36 additions and 16 deletions
  1. +30
    -13
      app.py
  2. BIN
     
  3. +6
    -3
      templates/list.html

+ 30
- 13
app.py View File

@ -1,9 +1,10 @@
from flask import Flask, request, render_template, send_from_directory, abort, redirect
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
from flask_limiter.util import get_remote_address from flask_limiter.util import get_remote_address
from mastodon import Mastodon from mastodon import Mastodon
import re import re
import random
from datetime import datetime from datetime import datetime
from dateutil.tz import tzlocal from dateutil.tz import tzlocal
import html2text import html2text
@ -11,6 +12,7 @@ from config import C
app = Flask(__name__) app = Flask(__name__)
app.config.from_object('config.C') app.config.from_object('config.C')
app.secret_key = C.session_key
th = Mastodon( th = Mastodon(
access_token = C.token, access_token = C.token,
@ -35,11 +37,12 @@ class Candidate(db.Model):
url = db.Column(db.String(50)) url = db.Column(db.String(50))
time = db.Column(db.DateTime) time = db.Column(db.DateTime)
toot = db.Column(db.BigInteger) toot = db.Column(db.BigInteger)
likeNum = db.Column(db.Integer, default=0)
class Like(db.Model): class Like(db.Model):
id = db.Column(db.Integer, primary_key=True) id = db.Column(db.Integer, primary_key=True)
cid = db.Column(db.Integer) cid = db.Column(db.Integer)
ip = db.Column(db.String(45))
uid = db.Column(db.Integer)
db.create_all() db.create_all()
@ -47,16 +50,28 @@ db.create_all()
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("3 / hour; 1 / 5 minute")
def set_session():
if 'uid' not in session:
session['uid'] = random.randint(0, 2000000000)
return redirect('.')
@app.route('/ordinary/') @app.route('/ordinary/')
def can_list(): def can_list():
key = request.args.get('key') key = request.args.get('key')
rip = request.remote_addr
sort_by = request.args.get('sort_by', 'time')
if 'uid' not in session:
return redirect('set_session')
uid = session['uid']
pag = Candidate.query.order_by(db.desc('id')).paginate(max_per_page=100)
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): def check_like(c):
c.likeNum = Like.query.filter_by(cid=c.id).count()
c.liked = 'liked' if Like.query.filter_by(ip=rip, cid=c.id).count() else 'like'
c.liked = 'liked' if Like.query.filter_by(uid=uid, cid=c.id).count() else 'like'
return c return c
pag.items = map(check_like, pag.items) pag.items = map(check_like, pag.items)
@ -66,12 +81,12 @@ def can_list():
'ques': ques, 'ques': ques,
'hint': hint 'hint': hint
} 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))
return render_template('list.html', pagination=pag, vs=vs, showPrivate=(key==C.key), sort_by=sort_by, key=key)
@app.route('/ordinary/new', methods=['POST']) @app.route('/ordinary/new', methods=['POST'])
@limiter.limit("3 / hour; 1 / 2 second")
@limiter.limit("5 / hour; 1 / 2 second")
def new_one(): def new_one():
content = request.form.get('text') content = request.form.get('text')
@ -139,15 +154,17 @@ def like(toot):
if not c: if not c:
abort(404) abort(404)
rip = request.remote_addr
if Like.query.filter_by(ip=rip, cid=c.id).first():
uid = session['uid']
if not uid: abort(401)
if Like.query.filter_by(uid=uid, cid=c.id).first():
return '点赞过了', 403 return '点赞过了', 403
l = Like(ip=rip, cid=c.id)
l = Like(uid=uid, cid=c.id)
c.likeNum += 1
db.session.add(l) db.session.add(l)
db.session.commit() db.session.commit()
return str(Like.query.filter_by(cid=c.id).count())
return str(c.likeNum)
if __name__ == '__main__': if __name__ == '__main__':

BIN
View File


+ 6
- 3
templates/list.html View File

@ -256,12 +256,13 @@
</div> </div>
{% endfor %} {% endfor %}
<p><a href="?sort_by=time">按时间</a> | <a href="?sort_by=likeNum">按赞数</a></p>
<nav> <nav>
<ul class="pagination"> <ul class="pagination">
{%- for page in pagination.iter_pages() %} {%- for page in pagination.iter_pages() %}
{% if page %} {% if page %}
{% if page != pagination.page %} {% if page != pagination.page %}
<li class="page-item"><a class="page-link" href="{{ url_for('can_list', page=page, per_page=pagination.per_page ) }}">{{ page }}</a></li>
<li class="page-item"><a class="page-link" href="{{ url_for('can_list', page=page, per_page=pagination.per_page, key=key, sort_by=sort_by) }}">{{ page }}</a></li>
{% else %} {% else %}
<li class="page-item active"> <li class="page-item active">
<a class="page-link" href="#">{{ page }}<span class="sr-only">(current)</span></a> <a class="page-link" href="#">{{ page }}<span class="sr-only">(current)</span></a>
@ -279,7 +280,7 @@
</div> </div>
<div class="footer"> <div class="footer">
<p> <p>
<a href="//closed.social" target="_blank">闭社</a>提供技术支持。本报名系统以AGPL协议开源于<a href="//git.closed.social/closed-social/ordinary" target="_blank">碧茶</a>
<a href="//closed.social" target="_blank">闭社</a>提供技术支持
</p> </p>
<p> 🄯 2020 Copyleft: closed.social</p> <p> 🄯 2020 Copyleft: closed.social</p>
</div> </div>
@ -289,8 +290,10 @@
$('.timeago').timeago(); $('.timeago').timeago();
function like(toot) { function like(toot) {
if ($(`#like-${toot} svg`).hasClass("liked"))
if ($(`#like-${toot} svg`).hasClass("liked")) {
alert('赞都赞了,别撤回嘛');
return; return;
}
$.ajax({ $.ajax({
type: 'POST', type: 'POST',
url: toot + '/like', url: toot + '/like',

Loading…
Cancel
Save