From e8ef07cceb8e7c2876f1f16c9060627cada15c3a Mon Sep 17 00:00:00 2001 From: hole-thu Date: Fri, 24 Dec 2021 00:07:39 +0800 Subject: [PATCH] =?UTF-8?q?=E8=87=AA=E5=AE=9A=E4=B9=89=E5=A4=B4=E8=A1=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- clear_redis.py | 5 +++++ hole.py | 45 +++++++++++++++++++++++++++++++++------------ models.py | 2 ++ utils.py | 8 ++++++-- 4 files changed, 46 insertions(+), 14 deletions(-) create mode 100644 clear_redis.py diff --git a/clear_redis.py b/clear_redis.py new file mode 100644 index 0000000..c32ae4f --- /dev/null +++ b/clear_redis.py @@ -0,0 +1,5 @@ +# 每次重置时执行 +from utils import rds, RDS_KEY_TITLE, RDS_KEY_BLOCKED_COUNT + +rds.delete(RDS_KEY_BLOCKED_COUNT) +rds.delete(RDS_KEY_TITLE) diff --git a/hole.py b/hole.py index 7d1ca64..ad3c796 100644 --- a/hole.py +++ b/hole.py @@ -10,7 +10,7 @@ from sqlalchemy.sql.expression import func from mastodon import Mastodon from models import db, User, Post, Comment, Attention, TagRecord, Syslog -from utils import get_current_username, map_post, map_comment, map_syslog, check_attention, hash_name, look, get_num, tmp_token, is_admin, check_can_del, rds, RDS_KEY_POLL_OPTS, RDS_KEY_POLL_VOTES, gen_poll_dict, name_with_tmp_limit, RDS_KEY_BLOCK_SET, RDS_KEY_BLOCKED_COUNT, RDS_KEY_DANGEROUS_USERS +from utils import get_current_username, map_post, map_comment, map_syslog, check_attention, hash_name, look, get_num, tmp_token, is_admin, check_can_del, rds, RDS_KEY_POLL_OPTS, RDS_KEY_POLL_VOTES, gen_poll_dict, name_with_tmp_limit, RDS_KEY_BLOCK_SET, RDS_KEY_BLOCKED_COUNT, RDS_KEY_DANGEROUS_USERS, RDS_KEY_TITLE app = Flask(__name__) app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///hole.db' @@ -24,7 +24,6 @@ app.config.from_pyfile('config.py') db.init_app(app) migrate = Migrate(app, db) - CS_LOGIN_URL = Mastodon(api_base_url=app.config['MASTODON_URL']) \ .auth_request_url( client_id=app.config['CLIENT_ID'], @@ -41,9 +40,6 @@ limiter = Limiter( PER_PAGE = 50 DANGEROUS_USER_THRESHOLD = 10 -# 重置后旧的被拉黑次数可以丢弃了,但其他仍需要保留 -rds.delete(RDS_KEY_BLOCKED_COUNT) - class APIError(Exception): msg = '未知错误' @@ -138,6 +134,7 @@ def get_list(): return { 'code': 0, 'tmp_token': tmp_token(), + 'custom_title': rds.hget(RDS_KEY_TITLE, hash_name(username)), 'count': len(data), 'data': data } @@ -185,8 +182,6 @@ def get_multi(): } - - @app.route('/_api/v1/search') def search(): username = get_current_username() @@ -248,6 +243,7 @@ def do_post(): post_type = request.form.get('type') cw = request.form.get('cw', '').strip() poll_options = request.form.getlist('poll_options') + use_title = request.form.get('use_title') if not content or len(content) > 4096 or len(cw) > 32: raise APIError('无内容或超长') @@ -263,8 +259,10 @@ def do_post(): if max(map(len, poll_options)) > 32: raise APIError('选项过长') + name_hash = hash_name(username) p = Post( - name_hash=hash_name(username), + name_hash=name_hash, + author_title=rds.hget(RDS_KEY_TITLE, name_hash) if use_title else None, content=content, search_text=search_text, post_type=post_type, @@ -351,14 +349,18 @@ def do_comment(): if post.deleted and not check_can_del(username, post.name_hash): abort(451) - content = request.form.get('text') - content = content.strip() if content else None - content = '[tmp]\n' + content if username[:4] == 'tmp_' else content + content = request.form.get('text', '').strip() + if username.startswith('tmp_'): + content = '[tmp]\n' + content if not content or len(content) > 4096: abort(422) + use_title = request.form.get('use_title') + + name_hash = hash_name(username) c = Comment( - name_hash=hash_name(username), + name_hash=name_hash, + author_title=rds.hget(RDS_KEY_TITLE, name_hash) if use_title else None, content=content, ) post.comments.append(c) @@ -518,6 +520,7 @@ def system_log(): 'start_time': app.config['START_TIME'], 'salt': look(app.config['SALT']), 'tmp_token': tmp_token(), + 'custom_title': rds.hget(RDS_KEY_TITLE, hash_name(username)), 'data': [map_syslog(s, username) for s in ss] } @@ -627,5 +630,23 @@ def block_user_by_target(): } +@app.route('/_api/v1/title', methods=['POST']) +@limiter.limit("10 / hour; 1 / 2 second") +def set_title(): + username = get_current_username() + + title = request.form.get('title') + if not title: + rds.hdel(RDS_KEY_TITLE, hash_name(username)) + else: + if len(title) > 10: + raise APIError('自定义头衔太长') + if title in rds.hvals(RDS_KEY_TITLE): # 如果未来量大还是另外用个set维护 + raise APIError('已经被使用了') + rds.hset(RDS_KEY_TITLE, hash_name(username), title) + + return {'code': 0} + + if __name__ == '__main__': app.run(debug=True) diff --git a/models.py b/models.py index 870fccf..7b97fb4 100644 --- a/models.py +++ b/models.py @@ -18,6 +18,7 @@ class Post(db.Model): id = db.Column(db.Integer, primary_key=True) name_hash = db.Column(db.String(64)) + author_title = db.Column(db.String(10)) content = db.Column(db.String(4096)) search_text = db.Column(db.String(4096), default='', index=True) post_type = db.Column(db.String(8)) @@ -44,6 +45,7 @@ class Post(db.Model): class Comment(db.Model): id = db.Column(db.Integer, primary_key=True) name_hash = db.Column(db.String(64)) + author_title = db.Column(db.String(10)) content = db.Column(db.String(4096)) timestamp = db.Column(db.Integer) deleted = db.Column(db.Boolean, default=False) diff --git a/utils.py b/utils.py index db1f585..c069d6f 100644 --- a/utils.py +++ b/utils.py @@ -14,6 +14,8 @@ RDS_KEY_BLOCK_SET = 'hole_thu:block_list:%s' # key的参数是name而非namehas RDS_KEY_BLOCKED_COUNT = 'hole_thu:blocked_count' # namehash -> 被拉黑次数 RDS_KEY_DANGEROUS_USERS = 'hole_thu:dangerous_users' +RDS_KEY_TITLE = 'hole_thu:title' # 用户自己设置的专属头衔, namehash -> 头衔 + rds = redis.Redis(**RDS_CONFIG) @@ -31,7 +33,7 @@ def tmp_token(): )[5:21] -def get_current_username(): +def get_current_username() -> str: token = request.headers.get('User-Token') or request.args.get('user_token') if not token: abort(401) @@ -72,7 +74,8 @@ def map_post(p, name, mc=50): 'attention': check_attention(name, p.id), 'can_del': check_can_del(name, p.name_hash), 'allow_search': bool(p.search_text), - 'poll': None if blocked else gen_poll_dict(p.id, name) + 'poll': None if blocked else gen_poll_dict(p.id, name), + 'author_title': p.author_title } if is_admin(name): r['hot_score'] = p.hot_score @@ -134,6 +137,7 @@ def map_comment(p, name): 'blocked': (blocked := is_blocked(c.name_hash, name)), 'cid': c.id, 'name_id': gen_name_id(c.name_hash), + 'author_title': c.author_title, 'pid': p.id, 'text': '' if blocked else c.content, 'timestamp': c.timestamp,