from flask_sqlalchemy import SQLAlchemy from datetime import datetime db = SQLAlchemy() class Board(db.Model): id = db.Column(db.Integer, primary_key=True) slug = db.Column(db.String(10), unique=True, nullable=False) name = db.Column(db.String(50), nullable=False) description = db.Column(db.String(200)) posts = db.relationship("Post", backref="board", lazy=True) class User(db.Model): id = db.Column(db.Integer, primary_key=True) nickname = db.Column(db.String(50), unique=True, nullable=False) created_at = db.Column(db.DateTime, default=datetime.utcnow) last_seen_at = db.Column(db.DateTime, default=datetime.utcnow) posts = db.relationship("Post", backref="user", lazy=True) class PostFile(db.Model): id = db.Column(db.Integer, primary_key=True) post_id = db.Column(db.Integer, db.ForeignKey("post.id"), nullable=False) filename = db.Column(db.String(100), nullable=False) original_filename = db.Column(db.String(100), nullable=False) class Post(db.Model): id = db.Column(db.Integer, primary_key=True) thread_id = db.Column( db.Integer, db.ForeignKey("post.id"), nullable=True ) # If null, it's a thread starter board_id = db.Column(db.Integer, db.ForeignKey("board.id"), nullable=False) user_id = db.Column( db.Integer, db.ForeignKey("user.id"), nullable=True ) # Nullable for backward compatibility content = db.Column(db.Text, nullable=True) nickname = db.Column(db.String(50), default="Anonyme") # Keep for historical posts created_at = db.Column(db.DateTime, default=datetime.utcnow) updated_at = db.Column(db.DateTime, default=datetime.utcnow) # For bumping ip_address = db.Column(db.String(50), nullable=True) files = db.relationship("PostFile", backref="post", lazy=True) # Relationship to access replies easily replies = db.relationship( "Post", backref=db.backref("parent", remote_side=[id]), lazy=True ) class BannedIP(db.Model): id = db.Column(db.Integer, primary_key=True) ip_address = db.Column(db.String(50), unique=True, nullable=False) reason = db.Column(db.String(200)) created_at = db.Column(db.DateTime, default=datetime.utcnow)