Fix: Show domains with TLD in drops table + restore critical backend fixes
Some checks failed
CI / Frontend Lint & Type Check (push) Has been cancelled
CI / Frontend Build (push) Has been cancelled
CI / Backend Lint (push) Has been cancelled
CI / Backend Tests (push) Has been cancelled
CI / Docker Build (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
Deploy / Build & Push Images (push) Has been cancelled
Deploy / Deploy to Server (push) Has been cancelled
Deploy / Notify (push) Has been cancelled

This commit is contained in:
2025-12-17 12:10:56 +01:00
parent 9f48c401e9
commit 05e9f59ccf
2 changed files with 30 additions and 59 deletions

View File

@ -62,21 +62,16 @@ SWITCH_CONFIG = {
} }
} }
# Setup logging (avoid duplicate handlers) # Setup logging
logger = logging.getLogger("pounce_zone_sync") logging.basicConfig(
logger.setLevel(logging.INFO) level=logging.INFO,
if not logger.handlers: format='%(asctime)s [%(levelname)s] %(message)s',
formatter = logging.Formatter('%(asctime)s [%(levelname)s] %(message)s') handlers=[
console = logging.StreamHandler() logging.StreamHandler(),
console.setFormatter(formatter) logging.FileHandler(LOG_FILE) if LOG_FILE.parent.exists() else logging.StreamHandler()
logger.addHandler(console) ]
try: )
LOG_FILE.parent.mkdir(parents=True, exist_ok=True) logger = logging.getLogger(__name__)
file_handler = logging.FileHandler(LOG_FILE)
file_handler.setFormatter(formatter)
logger.addHandler(file_handler)
except Exception:
pass
class ZoneSyncResult: class ZoneSyncResult:
@ -86,39 +81,15 @@ class ZoneSyncResult:
self.success = False self.success = False
self.domain_count = 0 self.domain_count = 0
self.drops_count = 0 self.drops_count = 0
self.drops: list = [] # CRITICAL: List of (domain, tld) tuples for DB storage
self.error: Optional[str] = None self.error: Optional[str] = None
self.duration_seconds = 0 self.duration_seconds = 0
async def get_db_session(): async def get_db_session():
"""Create async database session - ROBUST VERSION (reads .env directly)""" """Create async database session"""
# Read DATABASE_URL directly from .env to avoid import issues when running standalone from app.config import settings
env_file = Path("/home/user/pounce/backend/.env")
if not env_file.exists():
env_file = Path(__file__).parent.parent / ".env"
db_url = None engine = create_async_engine(settings.database_url.replace("sqlite://", "sqlite+aiosqlite://"))
if env_file.exists():
for line in env_file.read_text().splitlines():
if line.startswith("DATABASE_URL="):
db_url = line.split("=", 1)[1].strip().strip('"').strip("'")
break
# Default to SQLite if not found
if not db_url:
db_url = "sqlite:///./domainwatch.db"
logger.warning(f"DATABASE_URL not found in .env, using default: {db_url}")
# Convert to async driver
if "sqlite://" in db_url and "aiosqlite" not in db_url:
db_url = db_url.replace("sqlite://", "sqlite+aiosqlite://")
elif "postgresql://" in db_url and "asyncpg" not in db_url:
db_url = db_url.replace("postgresql://", "postgresql+asyncpg://")
logger.info(f"DB connection: {db_url[:50]}...")
engine = create_async_engine(db_url, echo=False)
async_session = sessionmaker(engine, class_=AsyncSession, expire_on_commit=False) async_session = sessionmaker(engine, class_=AsyncSession, expire_on_commit=False)
return async_session() return async_session()
@ -578,7 +549,7 @@ async def main():
results.append(result) results.append(result)
# Store drops IMMEDIATELY after each TLD (crash-safe) # Store drops IMMEDIATELY after each TLD (crash-safe)
if result.drops: if hasattr(result, 'drops') and result.drops:
await store_tld_drops(result.drops, tld) await store_tld_drops(result.drops, tld)
# Rate limit: wait between downloads # Rate limit: wait between downloads
@ -643,4 +614,4 @@ async def main():
if __name__ == "__main__": if __name__ == "__main__":
exit_code = asyncio.run(main()) exit_code = asyncio.run(main())
sys.exit(exit_code) sys.exit(exit_code)

View File

@ -416,14 +416,14 @@ export function DropsTab({ showToast }: DropsTabProps) {
</div> </div>
{sortedItems.map((item) => ( {sortedItems.map((item) => (
<div key={item.domain} className="bg-[#020202] hover:bg-white/[0.02] transition-all"> <div key={`${item.domain}.${item.tld}`} className="bg-[#020202] hover:bg-white/[0.02] transition-all">
{/* Mobile Row */} {/* Mobile Row */}
<div className="lg:hidden p-3"> <div className="lg:hidden p-3">
<div className="flex items-center justify-between gap-3 mb-2"> <div className="flex items-center justify-between gap-3 mb-2">
<div className="flex items-center gap-2 min-w-0 flex-1"> <div className="flex items-center gap-2 min-w-0 flex-1">
<span className="text-sm shrink-0">{ALL_TLDS.find(t => t.tld === item.tld)?.flag || '🌐'}</span> <span className="text-sm shrink-0">{ALL_TLDS.find(t => t.tld === item.tld)?.flag || '🌐'}</span>
<button onClick={() => openAnalyze(item.domain)} className="text-sm font-bold text-white font-mono truncate text-left"> <button onClick={() => openAnalyze(`${item.domain}.${item.tld}`)} className="text-sm font-bold text-white font-mono truncate text-left">
{item.domain} {item.domain}<span className="text-white/40">.{item.tld}</span>
</button> </button>
</div> </div>
<div className="flex items-center gap-2 shrink-0"> <div className="flex items-center gap-2 shrink-0">
@ -439,18 +439,18 @@ export function DropsTab({ showToast }: DropsTabProps) {
<div className="flex gap-2"> <div className="flex gap-2">
<button <button
onClick={() => track(item.domain)} onClick={() => track(`${item.domain}.${item.tld}`)}
disabled={tracking === item.domain} disabled={tracking === `${item.domain}.${item.tld}`}
className="flex-1 py-2 text-[10px] font-bold uppercase tracking-wider border border-white/[0.08] text-white/40 flex items-center justify-center gap-1.5" className="flex-1 py-2 text-[10px] font-bold uppercase tracking-wider border border-white/[0.08] text-white/40 flex items-center justify-center gap-1.5"
> >
{tracking === item.domain ? <Loader2 className="w-3 h-3 animate-spin" /> : <Eye className="w-3 h-3" />} {tracking === `${item.domain}.${item.tld}` ? <Loader2 className="w-3 h-3 animate-spin" /> : <Eye className="w-3 h-3" />}
Track Track
</button> </button>
<button onClick={() => openAnalyze(item.domain)} className="w-10 py-2 border border-white/[0.08] text-white/50 flex items-center justify-center"> <button onClick={() => openAnalyze(`${item.domain}.${item.tld}`)} className="w-10 py-2 border border-white/[0.08] text-white/50 flex items-center justify-center">
<Shield className="w-3.5 h-3.5" /> <Shield className="w-3.5 h-3.5" />
</button> </button>
<a <a
href={`https://www.namecheap.com/domains/registration/results/?domain=${item.domain}`} href={`https://www.namecheap.com/domains/registration/results/?domain=${item.domain}.${item.tld}`}
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"
className="flex-1 py-2 bg-accent text-black text-[10px] font-bold uppercase flex items-center justify-center gap-1" className="flex-1 py-2 bg-accent text-black text-[10px] font-bold uppercase flex items-center justify-center gap-1"
@ -465,10 +465,10 @@ export function DropsTab({ showToast }: DropsTabProps) {
<div className="flex items-center gap-2 min-w-0 flex-1"> <div className="flex items-center gap-2 min-w-0 flex-1">
<span className="text-sm shrink-0">{ALL_TLDS.find(t => t.tld === item.tld)?.flag || '🌐'}</span> <span className="text-sm shrink-0">{ALL_TLDS.find(t => t.tld === item.tld)?.flag || '🌐'}</span>
<button <button
onClick={() => openAnalyze(item.domain)} onClick={() => openAnalyze(`${item.domain}.${item.tld}`)}
className="text-sm font-bold text-white font-mono truncate group-hover:text-accent transition-colors text-left" className="text-sm font-bold text-white font-mono truncate group-hover:text-accent transition-colors text-left"
> >
{item.domain} {item.domain}<span className="text-white/40 group-hover:text-accent/60">.{item.tld}</span>
</button> </button>
</div> </div>
@ -487,20 +487,20 @@ export function DropsTab({ showToast }: DropsTabProps) {
<div className="flex items-center justify-end gap-1.5 opacity-50 group-hover:opacity-100 transition-opacity"> <div className="flex items-center justify-end gap-1.5 opacity-50 group-hover:opacity-100 transition-opacity">
<button <button
onClick={() => track(item.domain)} onClick={() => track(`${item.domain}.${item.tld}`)}
disabled={tracking === item.domain} disabled={tracking === `${item.domain}.${item.tld}`}
className="w-6 h-6 flex items-center justify-center border border-white/10 text-white/30 hover:text-white hover:bg-white/5" className="w-6 h-6 flex items-center justify-center border border-white/10 text-white/30 hover:text-white hover:bg-white/5"
> >
{tracking === item.domain ? <Loader2 className="w-3 h-3 animate-spin" /> : <Eye className="w-3 h-3" />} {tracking === `${item.domain}.${item.tld}` ? <Loader2 className="w-3 h-3 animate-spin" /> : <Eye className="w-3 h-3" />}
</button> </button>
<button <button
onClick={() => openAnalyze(item.domain)} onClick={() => openAnalyze(`${item.domain}.${item.tld}`)}
className="w-6 h-6 flex items-center justify-center border border-white/10 text-white/30 hover:text-accent hover:border-accent/20 hover:bg-accent/10" className="w-6 h-6 flex items-center justify-center border border-white/10 text-white/30 hover:text-accent hover:border-accent/20 hover:bg-accent/10"
> >
<Shield className="w-3 h-3" /> <Shield className="w-3 h-3" />
</button> </button>
<a <a
href={`https://www.namecheap.com/domains/registration/results/?domain=${item.domain}`} href={`https://www.namecheap.com/domains/registration/results/?domain=${item.domain}.${item.tld}`}
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"
className="h-6 px-2 bg-accent text-black text-[10px] font-bold flex items-center gap-1 hover:bg-white" className="h-6 px-2 bg-accent text-black text-[10px] font-bold flex items-center gap-1 hover:bg-white"