实现删除与封禁
This commit is contained in:
67
hole.py
67
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)
|
||||||
|
|||||||
@@ -44,4 +44,10 @@ class Attention(db.Model):
|
|||||||
name_hash = db.Column(db.String(64))
|
name_hash = db.Column(db.String(64))
|
||||||
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
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
|
||||||
|
|||||||
Reference in New Issue
Block a user