from datetime import datetime from sqlalchemy import BigInteger, Boolean, DateTime, Float, ForeignKey, Index, Integer, String, Text from sqlalchemy.orm import Mapped, mapped_column from app.db.base import Base, utcnow class TelegramUser(Base): __tablename__ = "telegram_users" id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True) telegram_id: Mapped[int] = mapped_column(BigInteger, nullable=False, unique=True, index=True) username: Mapped[str | None] = mapped_column(String(64), nullable=True) first_name: Mapped[str | None] = mapped_column(String(255), nullable=True) last_name: Mapped[str | None] = mapped_column(String(255), nullable=True) language_code: Mapped[str | None] = mapped_column(String(16), nullable=True) is_admin: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False) is_blocked: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False) discount_ever_used: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False) last_seen_at: Mapped[datetime] = mapped_column(DateTime, nullable=False, default=utcnow) created_at: Mapped[datetime] = mapped_column(DateTime, nullable=False, default=utcnow) updated_at: Mapped[datetime] = mapped_column(DateTime, nullable=False, default=utcnow, onupdate=utcnow) class RemnawaveUser(Base): __tablename__ = "remnawave_users" id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True) owner_telegram_user_id: Mapped[int | None] = mapped_column( ForeignKey("telegram_users.id", ondelete="SET NULL"), nullable=True, index=True, ) rw_uuid: Mapped[str] = mapped_column(String(36), nullable=False, unique=True, index=True) rw_id: Mapped[int] = mapped_column(BigInteger, nullable=False, unique=True) short_uuid: Mapped[str] = mapped_column(String(48), nullable=False, unique=True, index=True) username: Mapped[str] = mapped_column(String(36), nullable=False, unique=True, index=True) status: Mapped[str] = mapped_column(String(16), nullable=False) traffic_limit_bytes: Mapped[int] = mapped_column(BigInteger, nullable=False, default=0) used_traffic_bytes: Mapped[float] = mapped_column(Float(asdecimal=False), nullable=False, default=0.0) lifetime_used_traffic_bytes: Mapped[float] = mapped_column(Float(asdecimal=False), nullable=False, default=0.0) expire_at: Mapped[datetime] = mapped_column(DateTime, nullable=False) telegram_id: Mapped[int | None] = mapped_column(BigInteger, nullable=True, index=True) email: Mapped[str | None] = mapped_column(String(320), nullable=True, index=True) description: Mapped[str | None] = mapped_column(Text, nullable=True) tag: Mapped[str | None] = mapped_column(String(16), nullable=True, index=True) hwid_device_limit: Mapped[int | None] = mapped_column(Integer, nullable=True) external_squad_uuid: Mapped[str | None] = mapped_column(String(36), nullable=True) trojan_password: Mapped[str] = mapped_column(String(64), nullable=False) vless_uuid: Mapped[str] = mapped_column(String(36), nullable=False) ss_password: Mapped[str] = mapped_column(String(64), nullable=False) last_triggered_threshold: Mapped[int] = mapped_column(Integer, nullable=False, default=0) sub_revoked_at: Mapped[datetime | None] = mapped_column(DateTime, nullable=True) sub_last_user_agent: Mapped[str | None] = mapped_column(String(512), nullable=True) sub_last_opened_at: Mapped[datetime | None] = mapped_column(DateTime, nullable=True) last_traffic_reset_at: Mapped[datetime | None] = mapped_column(DateTime, nullable=True) subscription_url: Mapped[str] = mapped_column(Text, nullable=False) online_at: Mapped[datetime | None] = mapped_column(DateTime, nullable=True) first_connected_at: Mapped[datetime | None] = mapped_column(DateTime, nullable=True) last_connected_node_uuid: Mapped[str | None] = mapped_column(String(36), nullable=True) remote_created_at: Mapped[datetime] = mapped_column(DateTime, nullable=False) remote_updated_at: Mapped[datetime] = mapped_column(DateTime, nullable=False) synced_at: Mapped[datetime] = mapped_column(DateTime, nullable=False, default=utcnow) class InternalSquad(Base): __tablename__ = "internal_squads" uuid: Mapped[str] = mapped_column(String(36), primary_key=True) name: Mapped[str] = mapped_column(String(255), nullable=False) synced_at: Mapped[datetime] = mapped_column(DateTime, nullable=False, default=utcnow) class RemnawaveUserInternalSquad(Base): __tablename__ = "remnawave_user_internal_squads" user_id: Mapped[int] = mapped_column( ForeignKey("remnawave_users.id", ondelete="CASCADE"), primary_key=True, ) squad_uuid: Mapped[str] = mapped_column( ForeignKey("internal_squads.uuid", ondelete="CASCADE"), primary_key=True, ) class SubscriptionRequestLog(Base): __tablename__ = "subscription_request_logs" id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True) remote_id: Mapped[int] = mapped_column(BigInteger, nullable=False, unique=True, index=True) user_uuid: Mapped[str] = mapped_column( ForeignKey("remnawave_users.rw_uuid", ondelete="CASCADE"), nullable=False, index=True, ) request_at: Mapped[datetime] = mapped_column(DateTime, nullable=False) request_ip: Mapped[str | None] = mapped_column(String(45), nullable=True) user_agent: Mapped[str | None] = mapped_column(Text, nullable=True) synced_at: Mapped[datetime] = mapped_column(DateTime, nullable=False, default=utcnow) class Guide(Base): __tablename__ = "guides" id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True) title: Mapped[str] = mapped_column(String(255), nullable=False) short_description: Mapped[str] = mapped_column(String(512), nullable=False, default="") body_text: Mapped[str] = mapped_column(Text, nullable=False) is_active: Mapped[bool] = mapped_column(Boolean, nullable=False, default=True, index=True) created_by_telegram_id: Mapped[int | None] = mapped_column(BigInteger, nullable=True, index=True) created_at: Mapped[datetime] = mapped_column(DateTime, nullable=False, default=utcnow) updated_at: Mapped[datetime] = mapped_column(DateTime, nullable=False, default=utcnow, onupdate=utcnow) class GuidePhoto(Base): __tablename__ = "guide_photos" id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True) guide_id: Mapped[int] = mapped_column( ForeignKey("guides.id", ondelete="CASCADE"), nullable=False, index=True, ) file_id: Mapped[str] = mapped_column(String(512), nullable=False) position: Mapped[int] = mapped_column(Integer, nullable=False, default=0) created_at: Mapped[datetime] = mapped_column(DateTime, nullable=False, default=utcnow) class SupportTicket(Base): __tablename__ = "support_tickets" __table_args__ = ( Index( "ix_support_tickets_chat_message", "support_chat_id", "support_message_id", unique=True, ), ) id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True) public_id: Mapped[str] = mapped_column(String(32), nullable=False, unique=True, index=True) telegram_id: Mapped[int] = mapped_column(BigInteger, nullable=False, index=True) username: Mapped[str | None] = mapped_column(String(64), nullable=True) display_name: Mapped[str] = mapped_column(String(255), nullable=False) user_message: Mapped[str] = mapped_column(Text, nullable=False) support_chat_id: Mapped[int] = mapped_column(BigInteger, nullable=False, index=True) support_thread_id: Mapped[int | None] = mapped_column(Integer, nullable=True) support_message_id: Mapped[int | None] = mapped_column(BigInteger, nullable=True) status: Mapped[str] = mapped_column(String(16), nullable=False, default="OPEN") support_note: Mapped[str | None] = mapped_column(Text, nullable=True) closed_by_telegram_id: Mapped[int | None] = mapped_column(BigInteger, nullable=True) closed_at: Mapped[datetime | None] = mapped_column(DateTime, nullable=True) created_at: Mapped[datetime] = mapped_column(DateTime, nullable=False, default=utcnow) updated_at: Mapped[datetime] = mapped_column(DateTime, nullable=False, default=utcnow, onupdate=utcnow) class ReferralInvite(Base): __tablename__ = "referral_invites" id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True) inviter_telegram_id: Mapped[int] = mapped_column(BigInteger, nullable=False, index=True) invited_telegram_id: Mapped[int] = mapped_column(BigInteger, nullable=False, unique=True, index=True) invited_username: Mapped[str | None] = mapped_column(String(64), nullable=True) invited_display_name: Mapped[str] = mapped_column(String(255), nullable=False) discount_used: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False) created_at: Mapped[datetime] = mapped_column(DateTime, nullable=False, default=utcnow) class ReferralCode(Base): __tablename__ = "referral_codes" id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True) telegram_id: Mapped[int] = mapped_column(BigInteger, nullable=False, unique=True, index=True) code: Mapped[str] = mapped_column(String(32), nullable=False, unique=True, index=True) created_at: Mapped[datetime] = mapped_column(DateTime, nullable=False, default=utcnow) updated_at: Mapped[datetime] = mapped_column(DateTime, nullable=False, default=utcnow, onupdate=utcnow) class PromoCode(Base): __tablename__ = "promo_codes" id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True) code: Mapped[str] = mapped_column(String(32), nullable=False, unique=True, index=True) plan_code: Mapped[str | None] = mapped_column(String(64), nullable=True, index=True) discount_percent: Mapped[int] = mapped_column(Integer, nullable=False, default=0) expires_at: Mapped[datetime | None] = mapped_column(DateTime, nullable=True, index=True) is_active: Mapped[bool] = mapped_column(Boolean, nullable=False, default=True, index=True) created_by_telegram_id: Mapped[int | None] = mapped_column(BigInteger, nullable=True, index=True) created_at: Mapped[datetime] = mapped_column(DateTime, nullable=False, default=utcnow) updated_at: Mapped[datetime] = mapped_column(DateTime, nullable=False, default=utcnow, onupdate=utcnow) class PromoCodeApplication(Base): __tablename__ = "promo_code_applications" id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True) telegram_id: Mapped[int] = mapped_column(BigInteger, nullable=False, unique=True, index=True) promo_code_id: Mapped[int] = mapped_column( ForeignKey("promo_codes.id", ondelete="CASCADE"), nullable=False, index=True, ) created_at: Mapped[datetime] = mapped_column(DateTime, nullable=False, default=utcnow) updated_at: Mapped[datetime] = mapped_column(DateTime, nullable=False, default=utcnow, onupdate=utcnow) class ReferralBonus(Base): __tablename__ = "referral_bonuses" id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True) inviter_telegram_id: Mapped[int] = mapped_column(BigInteger, nullable=False, index=True) invited_telegram_id: Mapped[int] = mapped_column(BigInteger, nullable=False, index=True) source_order_uuid: Mapped[str] = mapped_column(String(36), nullable=False, unique=True, index=True) bonus_days: Mapped[int] = mapped_column(Integer, nullable=False, default=0) status: Mapped[str] = mapped_column(String(16), nullable=False, default="PENDING", index=True) applied_to_user_uuid: Mapped[str | None] = mapped_column(String(36), nullable=True, index=True) applied_at: Mapped[datetime | None] = mapped_column(DateTime, nullable=True) created_at: Mapped[datetime] = mapped_column(DateTime, nullable=False, default=utcnow) updated_at: Mapped[datetime] = mapped_column(DateTime, nullable=False, default=utcnow, onupdate=utcnow) class BotSetting(Base): __tablename__ = "bot_settings" id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True) key: Mapped[str] = mapped_column(String(64), nullable=False, unique=True, index=True) value: Mapped[str] = mapped_column(Text, nullable=False, default="") updated_by_telegram_id: Mapped[int | None] = mapped_column(BigInteger, nullable=True, index=True) created_at: Mapped[datetime] = mapped_column(DateTime, nullable=False, default=utcnow) updated_at: Mapped[datetime] = mapped_column(DateTime, nullable=False, default=utcnow, onupdate=utcnow) class SubscriptionNotification(Base): __tablename__ = "subscription_notifications" __table_args__ = ( Index( "ix_sub_notif_unique", "remnawave_user_id", "notification_type", "expire_at_snapshot", unique=True, ), ) id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True) remnawave_user_id: Mapped[int] = mapped_column( ForeignKey("remnawave_users.id", ondelete="CASCADE"), nullable=False, index=True, ) telegram_id: Mapped[int] = mapped_column(BigInteger, nullable=False, index=True) notification_type: Mapped[str] = mapped_column(String(32), nullable=False) expire_at_snapshot: Mapped[datetime] = mapped_column(DateTime, nullable=False) sent_at: Mapped[datetime] = mapped_column(DateTime, nullable=False, default=utcnow) class BroadcastPoll(Base): __tablename__ = "broadcast_polls" id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True) question_text: Mapped[str] = mapped_column(Text, nullable=False) created_by_telegram_id: Mapped[int | None] = mapped_column(BigInteger, nullable=True, index=True) created_at: Mapped[datetime] = mapped_column(DateTime, nullable=False, default=utcnow) updated_at: Mapped[datetime] = mapped_column(DateTime, nullable=False, default=utcnow, onupdate=utcnow) class BroadcastPollAnswer(Base): __tablename__ = "broadcast_poll_answers" __table_args__ = ( Index( "ix_broadcast_poll_answers_unique_user", "poll_id", "telegram_id", unique=True, ), ) id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True) poll_id: Mapped[int] = mapped_column( ForeignKey("broadcast_polls.id", ondelete="CASCADE"), nullable=False, index=True, ) telegram_id: Mapped[int] = mapped_column(BigInteger, nullable=False, index=True) username: Mapped[str | None] = mapped_column(String(64), nullable=True) first_name: Mapped[str | None] = mapped_column(String(255), nullable=True) last_name: Mapped[str | None] = mapped_column(String(255), nullable=True) answer: Mapped[str] = mapped_column(String(8), nullable=False) created_at: Mapped[datetime] = mapped_column(DateTime, nullable=False, default=utcnow) updated_at: Mapped[datetime] = mapped_column(DateTime, nullable=False, default=utcnow, onupdate=utcnow) class PaymentOrder(Base): __tablename__ = "payment_orders" id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True) order_uuid: Mapped[str] = mapped_column(String(36), nullable=False, unique=True, index=True) telegram_user_id: Mapped[int] = mapped_column( ForeignKey("telegram_users.id", ondelete="CASCADE"), nullable=False, index=True, ) telegram_id: Mapped[int] = mapped_column(BigInteger, nullable=False, index=True) plan_code: Mapped[str] = mapped_column(String(64), nullable=False, index=True) plan_title: Mapped[str] = mapped_column(String(255), nullable=False) plan_duration_days: Mapped[int] = mapped_column(Integer, nullable=False) traffic_limit_bytes: Mapped[int] = mapped_column(BigInteger, nullable=False, default=0) traffic_limit_strategy: Mapped[str] = mapped_column(String(32), nullable=False, default="NO_RESET") amount_stars: Mapped[int] = mapped_column(Integer, nullable=False) currency: Mapped[str] = mapped_column(String(8), nullable=False, default="XTR") status: Mapped[str] = mapped_column(String(32), nullable=False, default="PENDING", index=True) invoice_payload: Mapped[str] = mapped_column(String(128), nullable=False, unique=True, index=True) provision_username: Mapped[str] = mapped_column(String(36), nullable=False, index=True) remnawave_user_uuid: Mapped[str | None] = mapped_column(String(36), nullable=True, index=True) subscription_url: Mapped[str | None] = mapped_column(Text, nullable=True) telegram_payment_charge_id: Mapped[str | None] = mapped_column(String(255), nullable=True, unique=True) provider_payment_charge_id: Mapped[str | None] = mapped_column(String(255), nullable=True) error_message: Mapped[str | None] = mapped_column(Text, nullable=True) paid_at: Mapped[datetime | None] = mapped_column(DateTime, nullable=True) fulfilled_at: Mapped[datetime | None] = mapped_column(DateTime, nullable=True) created_at: Mapped[datetime] = mapped_column(DateTime, nullable=False, default=utcnow) updated_at: Mapped[datetime] = mapped_column(DateTime, nullable=False, default=utcnow, onupdate=utcnow)