Browse Source

允许搜索

master
hole-thu 4 years ago
parent
commit
24947c9874
  1. 19
      config.sample.py
  2. 253
      hole.py
  3. 7
      models.py
  4. 14
      requirements.txt
  5. 53
      utils.py

19
config.sample.py

@ -1,15 +1,14 @@
import random, string, time import random
import string
import time
SQLALCHEMY_DATABASE_URI='sqlite:///hole.db' SQLALCHEMY_DATABASE_URI = 'sqlite:///hole.db'
SQLALCHEMY_TRACK_MODIFICATIONS=False SQLALCHEMY_TRACK_MODIFICATIONS = False
JSON_AS_ASCII=False JSON_AS_ASCII = False
CLIENT_ID='<id>' CLIENT_ID = '<id>'
CLIENT_SECRET='<secret>' CLIENT_SECRET = '<secret>'
MASTODON_URL='https://thu.closed.social' MASTODON_URL = 'https://mastodon.social'
REDIRECT_URI = 'http://hole.thu.monster/_auth' REDIRECT_URI = 'http://hole.thu.monster/_auth'
THUHOLE_ADDRESS='https://thuhole.com'
THUHOLE_HOST='thuhole.com'
THUHOLE_PID=1
SALT = ''.join(random.choices(string.ascii_letters + string.digits, k=32)) SALT = ''.join(random.choices(string.ascii_letters + string.digits, k=32))
ADMINS = ['cs_114514'] ADMINS = ['cs_114514']
START_TIME = int(time.time()) START_TIME = int(time.time())

253
hole.py

@ -1,12 +1,13 @@
from flask import Flask, request, render_template, send_from_directory, abort, redirect import re
from flask_sqlalchemy import SQLAlchemy import random
import string
from flask import Flask, request, abort, redirect
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 flask_migrate import Migrate from flask_migrate import Migrate
from mastodon import Mastodon from mastodon import Mastodon
import re, random, string, datetime, hashlib,requests
from models import db, User, Post, Comment, Attention, TagRecord, Syslog from models import db, User, Post, Comment, Attention, TagRecord, Syslog
from utils import require_token, map_post, map_comment, map_syslog, check_attention, hash_name, look, get_num, tmp_token from utils import require_token, map_post, map_comment, map_syslog, check_attention, hash_name, look, get_num, tmp_token
@ -19,18 +20,13 @@ app.config.from_pyfile('config.py')
db.init_app(app) db.init_app(app)
migrate = Migrate(app, db) migrate = Migrate(app, db)
#with app.app_context():
# db.create_all()
CS_LOGIN_URL = Mastodon(api_base_url=app.config['MASTODON_URL']) \ CS_LOGIN_URL = Mastodon(api_base_url=app.config['MASTODON_URL']) \
.auth_request_url( .auth_request_url(
client_id = app.config['CLIENT_ID'], client_id=app.config['CLIENT_ID'],
redirect_uris = app.config['REDIRECT_URI'], redirect_uris=app.config['REDIRECT_URI'],
scopes = ['read:accounts'] scopes=['read:accounts']
) )
THUHOLE_SEND_URL = f"{app.config.get('THUHOLE_ADDRESS')}/services/thuhole/api.php?action=docomment&PKUHelperAPI=3.0&jsapiver=v0.3.1.133-444340&user_token="
THUHOLE_GET_URL = f"{app.config.get('THUHOLE_ADDRESS')}/services/thuhole/api.php?action=getcomment&pid={app.config.get('THUHOLE_PID')}&PKUHelperAPI=3.0&jsapiver=v0.3.1.133-444340&user_token="
limiter = Limiter( limiter = Limiter(
app, app,
@ -40,73 +36,28 @@ limiter = Limiter(
PER_PAGE = 50 PER_PAGE = 50
@app.route('/_login') @app.route('/_login')
@limiter.limit("5 / minute, 50 / hour") @limiter.limit("5 / minute, 50 / hour")
def login(): def login():
provider = request.args.get('p') provider = request.args.get('p')
if provider == 'cs': if provider == 'cs':
return redirect(CS_LOGIN_URL) return redirect(CS_LOGIN_URL)
elif provider == 'thuhole':
token = request.args.get('token')
try:
rt = ''.join(random.choices(string.ascii_letters + string.digits, k=16))
headers = {
'user-agent': 'holeBot; hole.thu.monster',
'host': app.config.get('THUHOLE_HOST')
}
r = requests.post(
THUHOLE_SEND_URL+token,
headers=headers,
data={
'pid': app.config.get('THUHOLE_PID'),
'text': rt,
'user_token': token
}
)
r = requests.get(
THUHOLE_GET_URL+token,
headers=headers
)
c = r.json()
data = c.get('data')
mat = [c['name'] for c in data if c['text'].endswith(rt)]
if mat:
name = mat[0]
else:
abort(401)
name = 'th_' + ''.join(map(lambda s: s[0], name.split()))
u = v = User.query.filter_by(name=name).first()
if not u:
u = User(name=name)
db.session.add(u)
if not v or False: #TODO: reset token
u.token = ''.join(random.choices(string.ascii_letters + string.digits, k=16))
db.session.commit()
return redirect('/?token='+ u.token)
except :
abort(401)
abort(404) abort(404)
@app.route('/_auth') @app.route('/_auth')
@limiter.limit("5 / minute") @limiter.limit("5 / minute")
def auth(): def auth():
# Currently, only for closed.social # Currently, only for closed.social
code = request.args.get('code') code = request.args.get('code')
client = Mastodon( client = Mastodon(
client_id = app.config['CLIENT_ID'], client_id=app.config['CLIENT_ID'],
client_secret = app.config['CLIENT_SECRET'], client_secret=app.config['CLIENT_SECRET'],
api_base_url = app.config['MASTODON_URL'] api_base_url=app.config['MASTODON_URL']
) )
token = client.log_in( client.log_in(
code=code, code=code,
redirect_uri=app.config['REDIRECT_URI'], redirect_uri=app.config['REDIRECT_URI'],
scopes=['read:accounts'] scopes=['read:accounts']
@ -121,11 +72,16 @@ def auth():
u = User(name=name) u = User(name=name)
db.session.add(u) db.session.add(u)
if not v or False: #TODO: reset token if not v or False: # TODO: reset token
u.token = ''.join(random.choices(string.ascii_letters + string.digits, k=16)) u.token = ''.join(
random.choices(
string.ascii_letters +
string.digits,
k=16))
db.session.commit() db.session.commit()
return redirect('/?token='+ u.token) return redirect('/?token=%s' % u.token)
@app.route('/_api/v1/getlist') @app.route('/_api/v1/getlist')
def get_list(): def get_list():
@ -136,10 +92,12 @@ def get_list():
posts = Post.query.filter_by(deleted=False) posts = Post.query.filter_by(deleted=False)
if 'no_cw' in request.args: if 'no_cw' in request.args:
posts = posts.filter_by(cw=None) posts = posts.filter_by(cw=None)
posts = posts.order_by(db.desc('comment_timestamp')) if 'by_c' in request.args else posts.order_by(db.desc('id')) posts = posts.order_by(
db.desc('comment_timestamp')) if 'by_c' in request.args else posts.order_by(
db.desc('id'))
posts = posts.paginate(p, PER_PAGE) posts = posts.paginate(p, PER_PAGE)
data =list(map(map_post, posts.items, [u.name] * len(posts.items))) data = list(map(map_post, posts.items, [u.name] * len(posts.items)))
return { return {
'code': 0, 'code': 0,
@ -147,15 +105,19 @@ def get_list():
'count': len(data), 'count': len(data),
'data': data 'data': data
} }
@app.route('/_api/v1/getone') @app.route('/_api/v1/getone')
def get_one(): def get_one():
u = require_token() u = require_token()
pid = get_num(request.args.get('pid')) pid = request.args.get('pid', type=int)
post = Post.query.get(pid) post = Post.query.get(pid)
if not post: abort(404) if not post:
if post.deleted: abort(451) abort(404)
if post.deleted:
abort(451)
data = map_post(post, u.name) data = map_post(post, u.name)
@ -164,18 +126,45 @@ def get_one():
'data': data 'data': data
} }
@app.route('/_api/v1/search') @app.route('/_api/v1/search')
def search(): def search():
u = require_token() u = require_token()
page = get_num(request.args.get('page')) page = request.args.get('page', type=int, default=1)
pagesize = max(get_num(request.args.get('pagesize')), 200) pagesize = min(request.args.get('pagesize', type=int, default=200), 200)
keywords = request.args.get('keywords') keywords = request.args.get('keywords')
if not keywords:
abort(422)
pids = [tr.pid for tr in TagRecord.query.filter_by(tag=keywords).order_by(db.desc('pid')).paginate(page, pagesize).items] tag_pids = TagRecord.query.with_entities(
TagRecord.pid
data = [ map_post(Post.query.get(pid), u.name) ).filter_by(
for pid in pids if Post.query.get(pid) and not Post.query.get(pid).deleted tag=keywords
).all()
print(tag_pids)
tag_pids = [tag_pid for tag_pid, in tag_pids] or [0] # sql not allowed empty in
posts = Post.query.filter(
Post.search_text.like("%{}%".format(keywords))
).filter(
Post.id.notin_(tag_pids)
).order_by(
Post.id.desc()
).limit(pagesize).offset((page - 1) * pagesize).all()
if page == 1:
posts = Post.query.filter(
Post.id.in_(tag_pids)
).filter_by(deleted=False).order_by(
Post.id.desc()
).all() + posts
data = [
map_post(post, u.name)
for post in posts
] ]
return { return {
@ -185,12 +174,13 @@ def search():
} }
@app.route('/_api/v1/dopost', methods=['POST']) @app.route('/_api/v1/dopost', methods=['POST'])
@limiter.limit("50 / hour; 1 / 3 second") @limiter.limit("50 / hour; 1 / 3 second")
def do_post(): def do_post():
u = require_token() u = require_token()
allow_search = request.form.get('allow_search')
print(allow_search)
content = request.form.get('text') content = request.form.get('text')
content = content.strip() if content else None content = content.strip() if content else None
content = '[tmp]\n' + content if u.name[:4] == 'tmp_' else content content = '[tmp]\n' + content if u.name[:4] == 'tmp_' else content
@ -198,16 +188,22 @@ def do_post():
cw = request.form.get('cw') cw = request.form.get('cw')
cw = cw.strip() if cw else None cw = cw.strip() if cw else None
if not content or len(content) > 4096: abort(422) if not content or len(content) > 4096:
if cw and len(cw)>32: abort(422) abort(422)
if cw and len(cw) > 32:
abort(422)
search_text = content.replace(
'\n', '') if allow_search else ''
p = Post( p = Post(
name_hash = hash_name(u.name), name_hash=hash_name(u.name),
content = content, content=content,
post_type = post_type, search_text=search_text,
cw = cw or None, post_type=post_type,
likenum = 1, cw=cw or None,
comments = [] likenum=1,
comments=[]
) )
if post_type == 'text': if post_type == 'text':
@ -221,11 +217,11 @@ def do_post():
db.session.add(p) db.session.add(p)
db.session.commit() db.session.commit()
tags = re.findall('(^|\s)#([^#\s]{1,32})', content) tags = re.findall('(^|\\s)#([^#\\s]{1,32})', content)
#print(tags) # print(tags)
for t in tags: for t in tags:
tag = t[1] tag = t[1]
if not re.match('\d+', tag): if not re.match('\\d+', tag):
db.session.add(TagRecord(tag=tag, pid=p.id)) db.session.add(TagRecord(tag=tag, pid=p.id))
db.session.add(Attention(name_hash=hash_name(u.name), pid=p.id)) db.session.add(Attention(name_hash=hash_name(u.name), pid=p.id))
@ -236,6 +232,7 @@ def do_post():
'date': p.id 'date': p.id
} }
@app.route('/_api/v1/editcw', methods=['POST']) @app.route('/_api/v1/editcw', methods=['POST'])
@limiter.limit("50 / hour; 1 / 2 second") @limiter.limit("50 / hour; 1 / 2 second")
def edit_cw(): def edit_cw():
@ -245,16 +242,20 @@ def edit_cw():
pid = get_num(request.form.get('pid')) pid = get_num(request.form.get('pid'))
cw = cw.strip() if cw else None cw = cw.strip() if cw else None
if cw and len(cw)>32: abort(422) if cw and len(cw) > 32:
abort(422)
post = Post.query.get(pid) post = Post.query.get(pid)
if not post: abort(404) if not post:
if post.deleted: abort(451) abort(404)
if post.deleted:
abort(451)
if not (u.name in app.config.get('ADMINS') or hash_name(u.name) == post.name_hash): if not (u.name in app.config.get('ADMINS')
or hash_name(u.name) == post.name_hash):
abort(403) abort(403)
post.cw = cw; post.cw = cw
db.session.commit() db.session.commit()
return {'code': 0} return {'code': 0}
@ -267,8 +268,10 @@ def get_comment():
pid = get_num(request.args.get('pid')) pid = get_num(request.args.get('pid'))
post = Post.query.get(pid) post = Post.query.get(pid)
if not post: abort(404) if not post:
if post.deleted: abort(451) abort(404)
if post.deleted:
abort(451)
data = map_comment(post, u.name) data = map_comment(post, u.name)
@ -279,6 +282,7 @@ def get_comment():
'data': data 'data': data
} }
@app.route('/_api/v1/docomment', methods=['POST']) @app.route('/_api/v1/docomment', methods=['POST'])
@limiter.limit("50 / hour; 1 / 3 second") @limiter.limit("50 / hour; 1 / 3 second")
def do_comment(): def do_comment():
@ -287,17 +291,20 @@ def do_comment():
pid = get_num(request.form.get('pid')) pid = get_num(request.form.get('pid'))
post = Post.query.get(pid) post = Post.query.get(pid)
if not post: abort(404) if not post:
if post.deleted: abort(451) 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
content = '[tmp]\n' + content if u.name[:4] == 'tmp_' else content content = '[tmp]\n' + content if u.name[:4] == 'tmp_' else content
if not content or len(content) > 4096: abort(422) if not content or len(content) > 4096:
abort(422)
c = Comment( c = Comment(
name_hash = hash_name(u.name), name_hash=hash_name(u.name),
content = content, content=content,
) )
post.comments.append(c) post.comments.append(c)
post.comment_timestamp = c.timestamp post.comment_timestamp = c.timestamp
@ -308,21 +315,27 @@ def do_comment():
'data': pid 'data': pid
} }
@app.route('/_api/v1/attention', methods=['POST']) @app.route('/_api/v1/attention', methods=['POST'])
@limiter.limit("200 / hour; 1 / second") @limiter.limit("200 / hour; 1 / second")
def attention(): def attention():
u = require_token() u = require_token()
if u.name[:4] == 'tmp_': abort(403) if u.name[:4] == 'tmp_':
abort(403)
s = request.form.get('switch') s = request.form.get('switch')
if s not in ['0', '1']: abort(422) if s not in ['0', '1']:
abort(422)
pid = get_num(request.form.get('pid')) pid = get_num(request.form.get('pid'))
post = Post.query.get(pid) post = Post.query.get(pid)
if not post: abort(404) if not post:
abort(404)
at = Attention.query.filter_by(name_hash=hash_name(u.name), pid=pid).first() at = Attention.query.filter_by(
name_hash=hash_name(
u.name), pid=pid).first()
if not at: if not at:
at = Attention(name_hash=hash_name(u.name), pid=pid, disabled=True) at = Attention(name_hash=hash_name(u.name), pid=pid, disabled=True)
@ -330,23 +343,26 @@ def attention():
if(at.disabled != (s == '0')): if(at.disabled != (s == '0')):
at.disabled = (s == '0') at.disabled = (s == '0')
post.likenum += 1 - 2 * int(s == '0'); post.likenum += 1 - 2 * int(s == '0')
db.session.commit() db.session.commit()
return { return {
'code': 0, 'code': 0,
'likenum': post.likenum, 'likenum': post.likenum,
'attention': (s=='1') 'attention': (s == '1')
} }
@app.route('/_api/v1/getattention') @app.route('/_api/v1/getattention')
def get_attention(): def get_attention():
u = require_token() u = require_token()
ats = Attention.query.filter_by(name_hash=hash_name(u.name), disabled=False) ats = Attention.query.filter_by(
name_hash=hash_name(
u.name), disabled=False)
posts = [Post.query.get(at.pid) for at in ats.all()] posts = [Post.query.get(at.pid) for at in ats.all()]
data = [ map_post(post, 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
] ]
@ -357,6 +373,7 @@ def get_attention():
'data': data 'data': data
} }
@app.route('/_api/v1/delete', methods=['POST']) @app.route('/_api/v1/delete', methods=['POST'])
@limiter.limit("50 / hour; 1 / 3 second") @limiter.limit("50 / hour; 1 / 3 second")
def delete(): def delete():
@ -366,18 +383,21 @@ def delete():
obj_id = get_num(request.form.get('id')) obj_id = get_num(request.form.get('id'))
note = request.form.get('note') note = request.form.get('note')
if note and len(note)>100: abort(422) if note and len(note) > 100:
abort(422)
obj = None obj = None
if obj_type == 'pid': if obj_type == 'pid':
obj = Post.query.get(obj_id) obj = Post.query.get(obj_id)
elif obj_type == 'cid': elif obj_type == 'cid':
obj = Comment.query.get(obj_id) obj = Comment.query.get(obj_id)
if not obj: abort(404) if not obj:
abort(404)
if obj.name_hash == hash_name(u.name): if obj.name_hash == hash_name(u.name):
if obj_type == 'pid': if obj_type == 'pid':
if len(obj.comments): abort(403) if len(obj.comments):
abort(403)
Attention.query.filter_by(pid=obj.id).delete() Attention.query.filter_by(pid=obj.id).delete()
TagRecord.query.filter_by(pid=obj.id).delete() TagRecord.query.filter_by(pid=obj.id).delete()
db.session.delete(obj) db.session.delete(obj)
@ -402,9 +422,10 @@ def delete():
db.session.commit() db.session.commit()
return {'code': 0} return {'code': 0}
@app.route('/_api/v1/systemlog') @app.route('/_api/v1/systemlog')
def system_log(): def system_log():
u = require_token() require_token()
ss = Syslog.query.order_by(db.desc('timestamp')).limit(100).all() ss = Syslog.query.order_by(db.desc('timestamp')).limit(100).all()
@ -412,9 +433,10 @@ def system_log():
'start_time': app.config['START_TIME'], 'start_time': app.config['START_TIME'],
'salt': look(app.config['SALT']), 'salt': look(app.config['SALT']),
'tmp_token': tmp_token(), 'tmp_token': tmp_token(),
'data' : list(map(map_syslog, ss)) 'data': list(map(map_syslog, ss))
} }
@app.route('/_api/v1/report', methods=['POST']) @app.route('/_api/v1/report', methods=['POST'])
@limiter.limit("50 / hour; 1 / 3 second") @limiter.limit("50 / hour; 1 / 3 second")
def report(): def report():
@ -436,4 +458,3 @@ def report():
if __name__ == '__main__': if __name__ == '__main__':
app.run(debug=True) app.run(debug=True)

7
models.py

@ -3,6 +3,7 @@ import time
db = SQLAlchemy() db = SQLAlchemy()
class User(db.Model): class User(db.Model):
id = db.Column(db.Integer, primary_key=True) id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(16)) name = db.Column(db.String(16))
@ -11,10 +12,12 @@ class User(db.Model):
def __repr__(self): def __repr__(self):
return f"{self.name}({self.token})" return f"{self.name}({self.token})"
class Post(db.Model): class Post(db.Model):
id = db.Column(db.Integer, primary_key=True) id = db.Column(db.Integer, primary_key=True)
name_hash = db.Column(db.String(64)) name_hash = db.Column(db.String(64))
content = db.Column(db.String(4096)) content = db.Column(db.String(4096))
search_text = db.Column(db.String(4096), default='', index=True)
post_type = db.Column(db.String(8)) post_type = db.Column(db.String(8))
cw = db.Column(db.String(32)) cw = db.Column(db.String(32))
file_url = db.Column(db.String(256)) file_url = db.Column(db.String(256))
@ -32,6 +35,7 @@ class Post(db.Model):
def __repr__(self): def __repr__(self):
return f"{self.name_hash}:[{self.content}]" return f"{self.name_hash}:[{self.content}]"
class Comment(db.Model): class Comment(db.Model):
id = db.Column(db.Integer, primary_key=True) id = db.Column(db.Integer, primary_key=True)
name_hash = db.Column(db.String(64)) name_hash = db.Column(db.String(64))
@ -49,17 +53,20 @@ class Comment(db.Model):
def __repr__(self): def __repr__(self):
return f"{self.name_hash}:[{self.content}->{self.post_id}]" return f"{self.name_hash}:[{self.content}->{self.post_id}]"
class Attention(db.Model): class Attention(db.Model):
id = db.Column(db.Integer, primary_key=True) id = db.Column(db.Integer, primary_key=True)
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 TagRecord(db.Model): class TagRecord(db.Model):
id = db.Column(db.Integer, primary_key=True) id = db.Column(db.Integer, primary_key=True)
tag = db.Column(db.String(32)) tag = db.Column(db.String(32))
pid = db.Column(db.Integer) pid = db.Column(db.Integer)
class Syslog(db.Model): class Syslog(db.Model):
id = db.Column(db.Integer, primary_key=True) id = db.Column(db.Integer, primary_key=True)
log_type = db.Column(db.String(16)) log_type = db.Column(db.String(16))

14
requirements.txt

@ -1,7 +1,7 @@
Flask==1.1.2 Flask>=1.1.2
Flask-Limit==1.0.2 Flask-Limit>=1.0.2
Flask-Limiter==1.3.1 Flask-Limiter>=1.3.1
Flask-Login==0.5.0 Flask-Login>=0.5.0
Flask-Migrate==2.5.3 Flask-Migrate>=2.5.3
Flask-SQLAlchemy==2.4.4 Flask-SQLAlchemy>=2.4.4
Mastodon.py==1.5.1 Mastodon.py>=1.5.1

53
utils.py

@ -1,29 +1,40 @@
import hashlib, time import hashlib
import time
from flask import request, abort, current_app from flask import request, abort, current_app
from models import User, Attention, Syslog from models import User, Attention, Syslog
def get_config(key): def get_config(key):
return current_app.config.get(key) return current_app.config.get(key)
def tmp_token(): def tmp_token():
return hash_name(str(int(time.time() / 900)) + User.query.get(1).token)[5:21] return hash_name(str(int(time.time() / 900)) +
User.query.get(1).token)[5:21]
def require_token(): def require_token():
token = request.headers.get('User-Token') or request.args.get('user_token') token = request.headers.get('User-Token') or request.args.get('user_token')
if not token: abort(401) if not token:
abort(401)
if len(token.split('_')) == 2 and get_config('ENABLE_TMP'): if len(token.split('_')) == 2 and get_config('ENABLE_TMP'):
tt, suf = token.split('_') tt, suf = token.split('_')
if tt != tmp_token(): abort(401) if tt != tmp_token():
return User(name='tmp_'+suf) abort(401)
return User(name='tmp_' + suf)
u = User.query.filter_by(token=token).first() u = User.query.filter_by(token=token).first()
if not u or Syslog.query.filter_by(log_type='BANNED', name_hash=hash_name(u.name)).first(): abort(401) if not u or Syslog.query.filter_by(
log_type='BANNED', name_hash=hash_name(u.name)).first():
abort(401)
return u return u
def hash_name(name): def hash_name(name):
return hashlib.sha256((get_config('SALT') + name).encode('utf-8')).hexdigest() return hashlib.sha256(
(get_config('SALT') + name).encode('utf-8')).hexdigest()
def map_post(p, name, mc=50): def map_post(p, name, mc=50):
return { return {
@ -32,14 +43,16 @@ def map_post(p, name, mc=50):
'cw': p.cw, 'cw': p.cw,
'text': p.content, 'text': p.content,
'timestamp': p.timestamp, 'timestamp': p.timestamp,
'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, name) if len(p.comments) < mc else None, 'comments': map_comment(p, name) if len(p.comments) < mc else None,
'attention': check_attention(name, p.id), 'attention': check_attention(name, p.id),
'can_del': check_can_del(name, p.name_hash) 'can_del': check_can_del(name, p.name_hash),
'allow_search': bool(p.search_text)
} }
def map_comment(p, name): def map_comment(p, name):
names = {p.name_hash: 0} names = {p.name_hash: 0}
@ -56,9 +69,10 @@ def map_comment(p, name):
'text': c.content, 'text': c.content,
'timestamp': c.timestamp, 'timestamp': c.timestamp,
'can_del': check_can_del(name, c.name_hash) 'can_del': check_can_del(name, c.name_hash)
} for c in p.comments if not (c.deleted and gen_name_id(c.name_hash)>=0) } for c in p.comments if not (c.deleted and gen_name_id(c.name_hash) >= 0)
] ]
def map_syslog(s): def map_syslog(s):
return { return {
'type': s.log_type, 'type': s.log_type,
@ -67,16 +81,25 @@ def map_syslog(s):
'timestamp': s.timestamp 'timestamp': s.timestamp
} }
def check_attention(name, pid): def check_attention(name, pid):
at = Attention.query.filter_by(name_hash=hash_name(name), 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): def check_can_del(name, author_hash):
return 1 if hash_name(name) == author_hash or name in get_config('ADMINS') else 0 return 1 if hash_name(
name) == author_hash or name in get_config('ADMINS') else 0
def look(s): def look(s):
return s[:3] + '...' + s[-3:] return s[:3] + '...' + s[-3:]
def get_num(p): def get_num(p):
if not (p and p.isdigit()): abort(422) if not (p and p.isdigit()):
abort(422)
return int(p) return int(p)

Loading…
Cancel
Save