Browse Source

实现删除与封禁

master
hole-thu 5 years ago
parent
commit
44d1b26079
  1. 65
      hole.py
  2. 6
      models.py
  3. 31
      utils.py

65
hole.py

@ -6,8 +6,8 @@ from flask_limiter.util import get_remote_address
from mastodon import Mastodon from mastodon import Mastodon
import time, re, random, string, datetime, hashlib import time, re, random, string, datetime, hashlib
from models import db, User, Post, Comment, Attention from models import db, User, Post, Comment, Attention, Syslog
from utils import require_token, map_post, map_comment, check_attention from utils import require_token, map_post, map_comment, check_attention, hash_name
app = Flask(__name__) app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///hole.db' app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///hole.db'
@ -26,10 +26,7 @@ CS_LOGIN_URL = Mastodon(api_base_url=app.config['MASTODON_URL']) \
redirect_uris = app.config['REDIRECT_URI'], redirect_uris = app.config['REDIRECT_URI'],
scopes = ['read:accounts'] scopes = ['read:accounts']
) )
PER_PAGE = 25 PER_PAGE = 50
def hash_name(name):
return hashlib.sha256((app.config['SALT'] + name).encode('utf-8')).hexdigest()
@app.route('/_login') @app.route('/_login')
def login(): def login():
@ -76,10 +73,10 @@ def get_list():
p = request.args.get('p') p = request.args.get('p')
p = int(p) if p and p.isdigit() else -1 p = int(p) if p and p.isdigit() else -1
posts = Post.query.filter_by(deleted=False).order_by(db.desc('timestamp')).paginate(page=p, per_page=PER_PAGE) posts = Post.query.filter_by(deleted=False).order_by(db.desc('timestamp')).paginate(p, PER_PAGE)
data =list(map(map_post, posts.items, [hash_name(u.name)] * len(posts.items))) data =list(map(map_post, posts.items, [u.name] * len(posts.items)))
return { return {
'code': 0, 'code': 0,
@ -97,7 +94,7 @@ def get_one():
if not post: abort(404) if not post: abort(404)
if post.deleted: abort(451) if post.deleted: abort(451)
data = map_post(post, name_hash=hash_name(u.name)) data = map_post(post, u.name)
return { return {
'code': 0, 'code': 0,
@ -161,8 +158,9 @@ def get_comment():
post = Post.query.get(pid) post = Post.query.get(pid)
if not post: abort(404) if not post: abort(404)
if post.deleted: abort(451)
data = map_comment(post) data = map_comment(post, u.name)
return { return {
'code': 0, 'code': 0,
@ -182,6 +180,7 @@ def do_comment():
post = Post.query.get(pid) post = Post.query.get(pid)
if not post: abort(404) if not post: abort(404)
if post.deleted: abort(451)
content = request.form.get('text') content = request.form.get('text')
content = content.strip() if content else None content = content.strip() if content else None
@ -237,7 +236,7 @@ def get_attention():
posts = [Post.query.get(at.pid) for at in ats.all()] posts = [Post.query.get(at.pid) for at in ats.all()]
print(posts) print(posts)
data = [ map_post(post, hash_name(u.name), 10) data = [ map_post(post, u.name, 10)
for post in posts[::-1] for post in posts[::-1]
if post and not post.deleted if post and not post.deleted
] ]
@ -248,6 +247,50 @@ def get_attention():
'data': data 'data': data
} }
@app.route('/_api/v1/delete', methods=['POST'])
def delete():
u = require_token()
obj_type = request.form.get('type')
obj_id = request.form.get('id')
note = request.form.get('note')
if obj_id and obj_id.isdigit():
obj_id = int(obj_id)
else:
abort(422)
if note and len(note)>100: abort(422)
obj = None
if obj_type == 'pid':
obj = Post.query.get(obj_id)
if len(obj.comments): abort(403)
elif obj_type == 'cid':
obj = Comment.query.get(obj_id)
if not obj: abort(404)
if obj.name_hash == hash_name(u.name):
db.session.delete(obj)
elif u.name in app.config.get('ADMINS'):
obj.deleted = True
db.session.add(Syslog(
log_type='ADMIN DELETE',
log_detail=f"{type}={obj_id}\nnote",
name_hash=hash_name(u.name)
))
if note.startswith('!ban'):
db.session.add(Syslog(
log_type='BANNED',
log_detail=f"{type}={obj_id}\nnote",
name_hash=obj.name_hash
))
else:
abort(403)
db.session.commit()
return {'code': 0}
if __name__ == '__main__': if __name__ == '__main__':
app.run(debug=True) app.run(debug=True)

6
models.py

@ -45,3 +45,9 @@ class Attention(db.Model):
pid = db.Column(db.Integer) pid = db.Column(db.Integer)
disabled = db.Column(db.Boolean, default=False) disabled = db.Column(db.Boolean, default=False)
class Syslog(db.Model):
id = db.Column(db.Integer, primary_key=True)
log_type = db.Column(db.String(16))
log_detail = db.Column(db.String(128))
name_hash = db.Column(db.String(64))

31
utils.py

@ -1,13 +1,20 @@
import hashlib import hashlib
from flask import request, abort from flask import request, abort, current_app
from models import User, Attention from models import User, Attention, Syslog
def get_config(key):
return current_app.config.get(key)
def require_token(): def require_token():
token = request.args.get('user_token') token = request.args.get('user_token')
u = User.query.filter_by(token=token).first() if token else None u = User.query.filter_by(token=token).first() if token else None
if Syslog.query.filter_by(log_type='BANNED', name_hash=hash_name(u.name)).first(): abort(403)
return u if u else abort(401) return u if u else abort(401)
def map_post(p, name_hash, mc=50): def hash_name(name):
return hashlib.sha256((get_config('SALT') + name).encode('utf-8')).hexdigest()
def map_post(p, name, mc=50):
return { return {
'pid': p.id, 'pid': p.id,
'likenum': p.likenum, 'likenum': p.likenum,
@ -17,11 +24,12 @@ def map_post(p, name_hash, mc=50):
'type' : p.post_type, 'type' : p.post_type,
'url' : p.file_url, 'url' : p.file_url,
'reply': len(p.comments), 'reply': len(p.comments),
'comments': map_comment(p) if len(p.comments) < mc else None, 'comments': map_comment(p, name) if len(p.comments) < mc else None,
'attention': check_attention(name_hash, p.id) 'attention': check_attention(name, p.id),
'can_del': check_can_del(name, p.name_hash)
} }
def map_comment(p): def map_comment(p, name):
names = {p.name_hash: 0} names = {p.name_hash: 0}
@ -36,10 +44,13 @@ def map_comment(p):
'pid': p.id, 'pid': p.id,
'text': c.content, 'text': c.content,
'timestamp': c.timestamp, 'timestamp': c.timestamp,
#'cw': None # comments may have cw in future 'can_del': check_can_del(name, c.name_hash)
} for c in p.comments } for c in p.comments if not c.deleted
] ]
def check_attention(name_hash, pid): def check_attention(name, pid):
at = Attention.query.filter_by(name_hash=name_hash, pid=pid, disabled=False).first() at = Attention.query.filter_by(name_hash=hash_name(name), pid=pid, disabled=False).first()
return 1 if at else 0 return 1 if at else 0
def check_can_del(name, author_hash):
return 1 if hash_name(name) == author_hash or name in get_config('ADMINS') else 0

Loading…
Cancel
Save