Chepuhagram/srv/app/db/models.py

107 lines
5.2 KiB
Python

from sqlalchemy import Column, Integer, String, Sequence, create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
from sqlalchemy import Column, Integer, Text, ForeignKey, DateTime
from sqlalchemy.sql import func
from sqlalchemy import text
SQLALCHEMY_DATABASE_URL = "sqlite:///./chepuhagram.db"
engine = create_engine(SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False})
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
Base = declarative_base()
Base.metadata.create_all(bind=engine)
class User(Base):
__tablename__ = "users"
id = Column(Integer, Sequence('user_id_seq', start=100), primary_key=True, index=True)
first_name = Column(String(50), nullable=False, server_default="User")
last_name = Column(String(50), nullable=True)
username = Column(String, unique=True, index=True)
about = Column(String, nullable=True)
phone = Column(String(20), unique=True, nullable=True)
email = Column(String(255), unique=True, nullable=True)
totp_secret = Column(String(32), nullable=True)
hashed_password = Column(String)
public_key = Column(String, nullable=True)
encrypted_private_key = Column(String, nullable=True)
fcm_token = Column(String, nullable=True)
# Privacy settings
show_email = Column(Integer, nullable=False, server_default="1") # 1 = true, 0 = false
show_phone = Column(Integer, nullable=False, server_default="1")
show_avatar = Column(Integer, nullable=False, server_default="1")
show_about = Column(Integer, nullable=False, server_default="1")
show_username = Column(Integer, nullable=False, server_default="1")
show_last_online = Column(Integer, nullable=False, server_default="1")
last_online = Column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now())
class Message(Base):
__tablename__ = "messages"
id = Column(Integer, primary_key=True, index=True)
sender_id = Column(Integer, ForeignKey("users.id"))
receiver_id = Column(Integer, ForeignKey("users.id"))
content = Column(Text)
timestamp = Column(DateTime(timezone=True), server_default=func.now())
delivered_at = Column(DateTime(timezone=True), nullable=True)
read_at = Column(DateTime(timezone=True), nullable=True)
reply_to_id = Column(Integer, ForeignKey("messages.id"), nullable=True)
reply_to_text = Column(Text, nullable=True)
edited_at = Column(DateTime(timezone=True), nullable=True)
Base.metadata.create_all(bind=engine)
def _ensure_sqlite_message_columns():
# Простая авто-миграция для SQLite без Alembic.
# Добавляет колонки, если приложение обновилось на уже существующей БД.
with engine.connect() as conn:
cols = conn.execute(text("PRAGMA table_info(messages)")).fetchall()
existing = {row[1] for row in cols} # row[1] = name
if "delivered_at" not in existing:
conn.execute(text("ALTER TABLE messages ADD COLUMN delivered_at DATETIME"))
if "read_at" not in existing:
conn.execute(text("ALTER TABLE messages ADD COLUMN read_at DATETIME"))
if "reply_to_id" not in existing:
conn.execute(text("ALTER TABLE messages ADD COLUMN reply_to_id INTEGER REFERENCES messages(id)"))
if "reply_to_text" not in existing:
conn.execute(text("ALTER TABLE messages ADD COLUMN reply_to_text TEXT"))
if "edited_at" not in existing:
conn.execute(text("ALTER TABLE messages ADD COLUMN edited_at DATETIME"))
conn.commit()
_ensure_sqlite_message_columns()
def _ensure_sqlite_user_columns():
with engine.connect() as conn:
cols = conn.execute(text("PRAGMA table_info(users)")).fetchall()
existing = {row[1] for row in cols}
if "about" not in existing:
conn.execute(text("ALTER TABLE users ADD COLUMN about TEXT"))
if "phone" not in existing:
conn.execute(text("ALTER TABLE users ADD COLUMN phone VARCHAR(20)"))
if "email" not in existing:
conn.execute(text("ALTER TABLE users ADD COLUMN email VARCHAR(255)"))
if "show_email" not in existing:
conn.execute(text("ALTER TABLE users ADD COLUMN show_email INTEGER DEFAULT 1"))
if "show_phone" not in existing:
conn.execute(text("ALTER TABLE users ADD COLUMN show_phone INTEGER DEFAULT 1"))
if "show_avatar" not in existing:
conn.execute(text("ALTER TABLE users ADD COLUMN show_avatar INTEGER DEFAULT 1"))
if "show_about" not in existing:
conn.execute(text("ALTER TABLE users ADD COLUMN show_about INTEGER DEFAULT 1"))
if "show_username" not in existing:
conn.execute(text("ALTER TABLE users ADD COLUMN show_username INTEGER DEFAULT 1"))
if "show_last_online" not in existing:
conn.execute(text("ALTER TABLE users ADD COLUMN show_last_online INTEGER DEFAULT 1"))
if "last_online" not in existing:
conn.execute(text("ALTER TABLE users ADD COLUMN last_online DATETIME"))
conn.execute(text("UPDATE users SET last_online = datetime('now')"))
conn.commit()
_ensure_sqlite_user_columns()