feat: model proxy domain in SQLAlchemy

This commit is contained in:
agatha 2026-03-14 13:02:42 -04:00
parent 3c38333e9c
commit 9360077c5e

View File

@ -0,0 +1,117 @@
import enum
import uuid
from datetime import datetime
from sqlalchemy import (
Boolean,
Float,
ForeignKey,
Index,
Integer,
String,
Text,
func,
)
from sqlalchemy.dialects.postgresql import ENUM, INET
from sqlalchemy.orm import Mapped, mapped_column, relationship
from proxy_pool.db.base import Base, TimestampMixin, UUIDPrimaryKeyMixin
class ProxyProtocol(str, enum.Enum):
HTTP = "http"
HTTPS = "https"
SOCKS4 = "socks4"
SOCKS5 = "socks5"
class ProxyStatus(str, enum.Enum):
UNCHECKED = "unchecked"
ACTIVE = "active"
DEAD = "dead"
class AnonymityLevel(str, enum.Enum):
TRANSPARENT = "transparent"
ANONYMOUS = "anonymous"
ELITE = "elite"
class ProxySource(UUIDPrimaryKeyMixin, TimestampMixin, Base):
__tablename__ = "proxy_sources"
url: Mapped[str] = mapped_column(String(2048), unique=True)
parser_name: Mapped[str] = mapped_column(String(64))
cron_schedule: Mapped[str | None] = mapped_column(String(64))
default_protocol: Mapped[ProxyProtocol] = mapped_column(
ENUM(ProxyProtocol, name="proxy_protocol"),
)
is_active: Mapped[bool] = mapped_column(default=True)
last_scraped_at: Mapped[datetime | None] = mapped_column()
proxies: Mapped[list["Proxy"]] = relationship(back_populates="source")
class Proxy(UUIDPrimaryKeyMixin, TimestampMixin, Base):
__tablename__ = "proxies"
__table_args__ = (
Index("ix_proxies_ip_port_proto", "ip", "port", "protocol", unique=True),
Index("ix_proxies_status_score", "status", "score"),
)
ip: Mapped[str] = mapped_column(INET)
port: Mapped[int] = mapped_column(Integer)
protocol: Mapped[ProxyProtocol] = mapped_column(
ENUM(ProxyProtocol, name="proxy_protocol", create_type=False),
)
source_id: Mapped[uuid.UUID] = mapped_column(
ForeignKey("proxy_sources.id"),
)
status: Mapped[ProxyStatus] = mapped_column(
ENUM(ProxyStatus, name="proxy_status"),
default=ProxyStatus.UNCHECKED,
)
anonymity: Mapped[AnonymityLevel | None] = mapped_column(
ENUM(AnonymityLevel, name="anonymity_level"),
)
exit_ip: Mapped[str | None] = mapped_column(INET)
country: Mapped[str | None] = mapped_column(String(2))
score: Mapped[float] = mapped_column(Float, default=0.0)
avg_latency_ms: Mapped[float | None] = mapped_column(Float)
uptime_pct: Mapped[float | None] = mapped_column(Float)
first_seen_at: Mapped[datetime] = mapped_column(server_default=func.now())
last_checked_at: Mapped[datetime | None] = mapped_column()
source: Mapped["ProxySource"] = relationship(back_populates="proxies")
checks: Mapped[list["ProxyCheck"]] = relationship(back_populates="proxy")
tags: Mapped[list["ProxyTag"]] = relationship(back_populates="proxy")
class ProxyCheck(UUIDPrimaryKeyMixin, TimestampMixin, Base):
__tablename__ = "proxy_checks"
__table_args__ = (Index("ix_checks_proxy_created", "proxy_id", "created_at"),)
proxy_id: Mapped[uuid.UUID] = mapped_column(
ForeignKey("proxies.id", ondelete="CASCADE"),
)
checker_name: Mapped[str] = mapped_column(String(64))
stage: Mapped[int] = mapped_column(Integer)
passed: Mapped[bool] = mapped_column(Boolean)
latency_ms: Mapped[float | None] = mapped_column(Float)
detail: Mapped[str | None] = mapped_column(Text)
exit_ip: Mapped[str | None] = mapped_column(INET)
proxy: Mapped["Proxy"] = relationship(back_populates="checks")
class ProxyTag(UUIDPrimaryKeyMixin, Base):
__tablename__ = "proxy_tags"
__table_args__ = (Index("ix_tags_proxy_key", "proxy_id", "key", unique=True),)
proxy_id: Mapped[uuid.UUID] = mapped_column(
ForeignKey("proxies.id", ondelete="CASCADE"),
)
key: Mapped[str] = mapped_column(String(64))
value: Mapped[str] = mapped_column(String(256))
proxy: Mapped["Proxy"] = relationship(back_populates="tags")