diff --git a/back/main.py b/back/main.py index 829c9b8..62b58e9 100644 --- a/back/main.py +++ b/back/main.py @@ -25,6 +25,9 @@ NEED_AUDIT = True FILE_SIZE_LIMIT_MB = 10.0 FILE_FORMATS = ["png", "jpg", "jpeg", "gif", "webp"] +def now_time(): + return datetime.now() + # --- 定义数据库结构 --- class SiteSettings(db.Model): __tablename__ = 'site_settings' @@ -51,8 +54,8 @@ class Submission(db.Model): content = db.Column(db.Text, nullable=False) identity_token = db.Column(db.String(36), nullable=True) status = db.Column(db.String(20), default='Pending') - created_at = db.Column(db.DateTime, default=lambda: datetime.now()) - updated_at = db.Column(db.DateTime, default=lambda: datetime.now()) + created_at = db.Column(db.DateTime, default=now_time) + updated_at = db.Column(db.DateTime, default=now_time, onupdate=now_time) upvotes = db.Column(db.Integer, default=0) downvotes = db.Column(db.Integer, default=0) @@ -65,7 +68,7 @@ class Comment(db.Model): nickname = db.Column(db.String(50), default='匿名用户') content = db.Column(db.Text, nullable=False) identity_token = db.Column(db.String(36), nullable=True) - created_at = db.Column(db.DateTime, default=lambda: datetime.now()) + created_at = db.Column(db.DateTime, default=now_time) parent_comment_id = db.Column(db.Integer, db.ForeignKey('comments.id'), nullable=True) class Report(db.Model): @@ -80,6 +83,9 @@ class Report(db.Model): class Hashtag(db.Model): __tablename__ = 'hashtags' + __table_args__ = ( + db.Index('ix_hashtags_type_target', 'type', 'target_id'), + ) id = db.Column(db.Integer, primary_key=True, autoincrement=True) type = db.Column(db.Integer, nullable=False) # 0: Submission, 1: Comment target_id = db.Column(db.Integer, nullable=False) @@ -103,8 +109,8 @@ class SiteNotice(db.Model): type = db.Column(db.String(10), default='md', nullable=False) content = db.Column(db.Text, default='', nullable=False) version = db.Column(db.Integer, default=0, nullable=False) - created_at = db.Column(db.DateTime, default=lambda: datetime.now()) - updated_at = db.Column(db.DateTime, default=lambda: datetime.now(), onupdate=datetime.now) + created_at = db.Column(db.DateTime, default=now_time) + updated_at = db.Column(db.DateTime, default=now_time, onupdate=now_time) # 初始化数据库函数 def init_db(): @@ -158,6 +164,38 @@ def load_config(): print(f"Loaded {len(DENY_WORDS_CACHE)} deny words.") except Exception as e: print(f"Warning: Failed to load deny words: {e}") + +def is_identity_valid(token): + if not token: + return True + return Identity.query.filter_by(token=token).first() is not None + +def normalize_identity(token): + if token and not is_identity_valid(token): + return False, None + return True, token if token else None + +def find_deny_word(content): + try: + words = DENY_WORDS_CACHE + except Exception: + words = [] + for word in words: + if word in content: + return word + return None + +def save_hashtags(tag_type, target_id, hashtopic): + if not hashtopic: + return + for tag in hashtopic: + new_tag = Hashtag( + type=tag_type, + target_id=target_id, + name=tag + ) + db.session.add(new_tag) + db.session.commit() # --- 用户普通api端点 --- @app.route('/api/settings', methods=['GET']) @@ -277,19 +315,16 @@ def submit_post(): identity_token = data.get('identity') # 违禁词检测 - for word in DENY_WORDS_CACHE: - if word in content: - return jsonify({"code": 2005, "data": "提交内容包含违禁词"}) + if find_deny_word(content): + return jsonify({"code": 2005, "data": "提交内容包含违禁词"}) # Identity 验证 - if identity_token: - if not Identity.query.filter_by(token=identity_token).first(): - return jsonify({"code": 2004, "data": "无效的 Identity Token"}) - else: - identity_token = None + ok, identity_token = normalize_identity(identity_token) + if not ok: + return jsonify({"code": 2004, "data": "无效的 Identity Token"}) # 保存 - now = datetime.now() + now = now_time() new_post = Submission( content=content, identity_token=identity_token, @@ -301,15 +336,7 @@ def submit_post(): db.session.commit() # 保存 Hashtags - if hashtopic: - for tag in hashtopic: - new_tag = Hashtag( - type=0, # 0 for Submission - target_id=new_post.id, - name=tag - ) - db.session.add(new_tag) - db.session.commit() + save_hashtags(0, new_post.id, hashtopic) code = 1002 if new_post.status == 'Pending' else 1001 return jsonify({"code": code, "data": {"id": new_post.id}}) @@ -343,16 +370,13 @@ def submit_comment(): return jsonify({"code": 2002, "data": "投稿不存在"}) # 违禁词检测 - for word in DENY_WORDS_CACHE: - if word in content: - return jsonify({"code": 2005, "data": "提交内容包含违禁词"}) + if find_deny_word(content): + return jsonify({"code": 2005, "data": "提交内容包含违禁词"}) # Identity 验证 - if identity_token: - if not Identity.query.filter_by(token=identity_token).first(): - return jsonify({"code": 2004, "data": "无效的 Identity Token"}) - else: - identity_token = None + ok, identity_token = normalize_identity(identity_token) + if not ok: + return jsonify({"code": 2004, "data": "无效的 Identity Token"}) new_comment = Comment( submission_id=submission_id, @@ -365,15 +389,7 @@ def submit_comment(): db.session.commit() # 保存 Hashtags - if hashtopic: - for tag in hashtopic: - new_tag = Hashtag( - type=1, # 1 for Comment - target_id=new_comment.id, - name=tag - ) - db.session.add(new_tag) - db.session.commit() + save_hashtags(1, new_comment.id, hashtopic) return jsonify({"code": 1001, "data": {"id": new_comment.id}}) except Exception as e: @@ -399,11 +415,9 @@ def submit_report(): return jsonify({"code": 2002, "data": "投稿不存在"}) identity_token = data.get('identity') - if identity_token: - if not Identity.query.filter_by(token=identity_token).first(): - return jsonify({"code": 2004, "data": "无效的Identity Token"}) - else: - identity_token = None + ok, identity_token = normalize_identity(identity_token) + if not ok: + return jsonify({"code": 2004, "data": "无效的Identity Token"}) report = Report( submission_id=submission_id, diff --git a/front/src/components/CreatePost.tsx b/front/src/components/CreatePost.tsx index d3a138e..a11dcd3 100644 --- a/front/src/components/CreatePost.tsx +++ b/front/src/components/CreatePost.tsx @@ -12,6 +12,7 @@ import { Button, Text, makeStyles, + mergeClasses, shorthands, tokens, Input, @@ -672,7 +673,10 @@ const CreatePost: React.FC = () => { {suggestions.map((item, idx) => (