Spaces:
Sleeping
Sleeping
| import enum | |
| from datetime import datetime, timezone | |
| from sqlalchemy import ( | |
| Boolean, | |
| Column, | |
| DateTime, | |
| Enum, | |
| Float, | |
| ForeignKey, | |
| Integer, | |
| String, | |
| UniqueConstraint, | |
| ) | |
| from sqlalchemy.orm import relationship | |
| from .connection import Base | |
| def _utcnow() -> datetime: | |
| """Naive UTC timestamp for TIMESTAMP WITHOUT TIME ZONE columns. | |
| asyncpg rejects timezone-aware datetimes for naive TIMESTAMP columns, so we | |
| normalise to naive UTC at the application layer. | |
| """ | |
| return datetime.now(timezone.utc).replace(tzinfo=None) | |
| class UserRole(str, enum.Enum): | |
| admin = "admin" | |
| moderator = "moderator" | |
| participant = "participant" | |
| class MeetingStatus(str, enum.Enum): | |
| active = "active" | |
| ended = "ended" | |
| class MeetingRole(str, enum.Enum): | |
| """Role a user holds *within a specific meeting* (distinct from the global | |
| account role). The meeting creator is the host.""" | |
| host = "host" | |
| moderator = "moderator" | |
| participant = "participant" | |
| class User(Base): | |
| __tablename__ = "users" | |
| id = Column(Integer, primary_key=True, index=True) | |
| username = Column(String(50), unique=True, index=True, nullable=False) | |
| email = Column(String(255), unique=True, index=True, nullable=False) | |
| hashed_password = Column(String(255), nullable=False) | |
| role = Column(Enum(UserRole), default=UserRole.participant, nullable=False) | |
| is_active = Column(Boolean, default=True) | |
| created_at = Column(DateTime, default=_utcnow) | |
| meetings = relationship( | |
| "Meeting", | |
| back_populates="host", | |
| foreign_keys="Meeting.host_id", | |
| ) | |
| microphone_configs = relationship("MicrophoneConfig", back_populates="user") | |
| memberships = relationship( | |
| "MeetingMember", | |
| back_populates="user", | |
| cascade="all, delete-orphan", | |
| ) | |
| class Meeting(Base): | |
| __tablename__ = "meetings" | |
| id = Column(Integer, primary_key=True, index=True) | |
| title = Column(String(200), nullable=False) | |
| description = Column(String(500), nullable=True) | |
| host_id = Column(Integer, ForeignKey("users.id"), nullable=False) | |
| invite_token = Column(String(64), unique=True, index=True, nullable=True) | |
| created_at = Column(DateTime, default=_utcnow) | |
| ended_at = Column(DateTime, nullable=True) | |
| status = Column(Enum(MeetingStatus), default=MeetingStatus.active) | |
| host = relationship("User", back_populates="meetings", foreign_keys=[host_id]) | |
| microphone_configs = relationship("MicrophoneConfig", back_populates="meeting") | |
| speech_logs = relationship("SpeechLog", back_populates="meeting") | |
| members = relationship( | |
| "MeetingMember", | |
| back_populates="meeting", | |
| cascade="all, delete-orphan", | |
| ) | |
| class MeetingMember(Base): | |
| """Per-meeting membership with a meeting-scoped role.""" | |
| __tablename__ = "meeting_members" | |
| __table_args__ = ( | |
| UniqueConstraint("meeting_id", "user_id", name="uq_meeting_member"), | |
| ) | |
| id = Column(Integer, primary_key=True, index=True) | |
| meeting_id = Column(Integer, ForeignKey("meetings.id"), nullable=False, index=True) | |
| user_id = Column(Integer, ForeignKey("users.id"), nullable=False, index=True) | |
| role = Column( | |
| Enum(MeetingRole), default=MeetingRole.participant, nullable=False | |
| ) | |
| joined_at = Column(DateTime, default=_utcnow) | |
| meeting = relationship("Meeting", back_populates="members") | |
| user = relationship("User", back_populates="memberships") | |
| class MicrophoneConfig(Base): | |
| __tablename__ = "microphone_configs" | |
| id = Column(Integer, primary_key=True, index=True) | |
| meeting_id = Column(Integer, ForeignKey("meetings.id"), nullable=False) | |
| user_id = Column(Integer, ForeignKey("users.id"), nullable=False) | |
| name = Column(String(100), nullable=False) | |
| priority = Column(Integer, default=5) | |
| is_chairman = Column(Boolean, default=False) | |
| is_muted = Column(Boolean, default=False) | |
| created_at = Column(DateTime, default=_utcnow) | |
| meeting = relationship("Meeting", back_populates="microphone_configs") | |
| user = relationship("User", back_populates="microphone_configs") | |
| speech_logs = relationship("SpeechLog", back_populates="microphone") | |
| class SpeechLog(Base): | |
| __tablename__ = "speech_logs" | |
| id = Column(Integer, primary_key=True, index=True) | |
| meeting_id = Column(Integer, ForeignKey("meetings.id"), nullable=False) | |
| microphone_id = Column( | |
| Integer, ForeignKey("microphone_configs.id"), nullable=False | |
| ) | |
| start_time = Column(DateTime, default=_utcnow) | |
| end_time = Column(DateTime, nullable=True) | |
| peak_db = Column(Float, default=-100.0) | |
| avg_db = Column(Float, default=-100.0) | |
| meeting = relationship("Meeting", back_populates="speech_logs") | |
| microphone = relationship("MicrophoneConfig", back_populates="speech_logs") | |
| class SystemDiagnostic(Base): | |
| __tablename__ = "system_diagnostics" | |
| id = Column(Integer, primary_key=True, index=True) | |
| timestamp = Column(DateTime, default=_utcnow, index=True) | |
| cpu_usage = Column(Float, default=0.0) | |
| memory_usage = Column(Float, default=0.0) | |
| audio_latency_ms = Column(Float, default=0.0) | |
| buffer_health = Column(Float, default=100.0) | |
| packet_loss = Column(Float, default=0.0) | |