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
## Watchlist & Monitoring - ✅ Automatic domain monitoring based on subscription tier - ✅ Email alerts when domains become available - ✅ Health checks (DNS/HTTP/SSL) with caching - ✅ Expiry warnings for domains <30 days - ✅ Weekly digest emails - ✅ Instant alert toggle (optimistic UI updates) - ✅ Redesigned health check overlays with full details - 🔒 'Not public' display for .ch/.de domains without public expiry ## Portfolio Management (NEW) - ✅ Track owned domains with purchase price & date - ✅ ROI calculation (unrealized & realized) - ✅ Domain valuation with auto-refresh - ✅ Renewal date tracking - ✅ Sale recording with profit calculation - ✅ List domains for sale directly from portfolio - ✅ Full portfolio summary dashboard ## Listings / For Sale - ✅ Renamed from 'Portfolio' to 'For Sale' - ✅ Fixed listing limits: Scout=0, Trader=5, Tycoon=50 - ✅ Featured badge for Tycoon listings - ✅ Inquiries modal for sellers - ✅ Email notifications when buyer inquires - ✅ Inquiries column in listings table ## Scrapers & Data - ✅ Added 4 new registrar scrapers (Namecheap, Cloudflare, GoDaddy, Dynadot) - ✅ Increased scraping frequency to 2x daily (03:00 & 15:00 UTC) - ✅ Real historical data from database - ✅ Fixed RDAP/WHOIS for .ch/.de domains - ✅ Enhanced SSL certificate parsing ## Scheduler Jobs - ✅ Tiered domain checks (Scout=daily, Trader=hourly, Tycoon=10min) - ✅ Daily health checks (06:00 UTC) - ✅ Weekly expiry warnings (Mon 08:00 UTC) - ✅ Weekly digest emails (Sun 10:00 UTC) - ✅ Auction cleanup every 15 minutes ## UI/UX Improvements - ✅ Removed 'Back' buttons from Intel pages - ✅ Redesigned Radar page to match Market/Intel design - ✅ Less prominent check frequency footer - ✅ Consistent StatCard components across all pages - ✅ Ambient background glows - ✅ Better error handling ## Documentation - ✅ Updated README with monitoring section - ✅ Added env.example with all required variables - ✅ Updated Memory Bank (activeContext.md) - ✅ SMTP configuration requirements documented
134 lines
5.5 KiB
Python
134 lines
5.5 KiB
Python
"""GoDaddy TLD price scraper.
|
|
|
|
GoDaddy is the world's largest domain registrar with significant market share.
|
|
Their prices are important for market comparison, especially for promotional pricing.
|
|
"""
|
|
import logging
|
|
from datetime import datetime
|
|
from typing import Optional
|
|
|
|
import httpx
|
|
|
|
from app.services.tld_scraper.base import BaseTLDScraper, TLDPriceData, ScraperError
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
class GoDaddyScraper(BaseTLDScraper):
|
|
"""
|
|
Scraper for GoDaddy domain prices.
|
|
|
|
GoDaddy doesn't have a public pricing API, but we maintain
|
|
known prices for major TLDs based on their public pricing pages.
|
|
|
|
Key characteristics of GoDaddy pricing:
|
|
- Low promotional first-year prices
|
|
- Higher renewal prices (important for "renewal trap" detection)
|
|
- Frequent sales and discounts
|
|
"""
|
|
|
|
name = "godaddy"
|
|
base_url = "https://www.godaddy.com"
|
|
|
|
# Known GoDaddy prices (as of Dec 2024)
|
|
# Note: GoDaddy has aggressive promo pricing but high renewals
|
|
# Source: https://www.godaddy.com/tlds
|
|
GODADDY_PRICES = {
|
|
# Major TLDs - Note the renewal trap on many!
|
|
"com": {"reg": 11.99, "renew": 22.99, "transfer": 11.99, "promo": 0.99},
|
|
"net": {"reg": 14.99, "renew": 23.99, "transfer": 14.99},
|
|
"org": {"reg": 9.99, "renew": 23.99, "transfer": 9.99},
|
|
"info": {"reg": 2.99, "renew": 24.99, "transfer": 2.99, "promo": True},
|
|
"biz": {"reg": 16.99, "renew": 24.99, "transfer": 16.99},
|
|
|
|
# Premium ccTLDs
|
|
"io": {"reg": 44.99, "renew": 59.99, "transfer": 44.99},
|
|
"co": {"reg": 11.99, "renew": 38.99, "transfer": 11.99},
|
|
"ai": {"reg": 79.99, "renew": 99.99, "transfer": 79.99},
|
|
"me": {"reg": 2.99, "renew": 19.99, "transfer": 2.99, "promo": True},
|
|
|
|
# Tech TLDs
|
|
"dev": {"reg": 15.99, "renew": 19.99, "transfer": 15.99},
|
|
"app": {"reg": 17.99, "renew": 21.99, "transfer": 17.99},
|
|
"tech": {"reg": 4.99, "renew": 54.99, "transfer": 4.99, "promo": True}, # Major trap!
|
|
"xyz": {"reg": 0.99, "renew": 14.99, "transfer": 0.99, "promo": True},
|
|
|
|
# Budget/Promo TLDs (watch out for renewals!)
|
|
"online": {"reg": 0.99, "renew": 44.99, "transfer": 0.99, "promo": True},
|
|
"site": {"reg": 0.99, "renew": 39.99, "transfer": 0.99, "promo": True},
|
|
"store": {"reg": 0.99, "renew": 59.99, "transfer": 0.99, "promo": True},
|
|
"club": {"reg": 0.99, "renew": 16.99, "transfer": 0.99, "promo": True},
|
|
"website": {"reg": 0.99, "renew": 24.99, "transfer": 0.99, "promo": True},
|
|
"space": {"reg": 0.99, "renew": 24.99, "transfer": 0.99, "promo": True},
|
|
|
|
# European ccTLDs
|
|
"uk": {"reg": 8.99, "renew": 12.99, "transfer": 8.99},
|
|
"de": {"reg": 9.99, "renew": 14.99, "transfer": 9.99},
|
|
"eu": {"reg": 6.99, "renew": 12.99, "transfer": 6.99},
|
|
"fr": {"reg": 11.99, "renew": 14.99, "transfer": 11.99},
|
|
"nl": {"reg": 9.99, "renew": 14.99, "transfer": 9.99},
|
|
|
|
# Other popular TLDs
|
|
"ca": {"reg": 12.99, "renew": 19.99, "transfer": 12.99},
|
|
"us": {"reg": 5.99, "renew": 21.99, "transfer": 5.99},
|
|
"tv": {"reg": 34.99, "renew": 44.99, "transfer": 34.99},
|
|
"cc": {"reg": 9.99, "renew": 14.99, "transfer": 9.99},
|
|
|
|
# New gTLDs
|
|
"shop": {"reg": 2.99, "renew": 39.99, "transfer": 2.99, "promo": True},
|
|
"blog": {"reg": 2.99, "renew": 34.99, "transfer": 2.99, "promo": True},
|
|
"cloud": {"reg": 4.99, "renew": 24.99, "transfer": 4.99, "promo": True},
|
|
"live": {"reg": 2.99, "renew": 29.99, "transfer": 2.99, "promo": True},
|
|
"world": {"reg": 2.99, "renew": 34.99, "transfer": 2.99, "promo": True},
|
|
}
|
|
|
|
async def scrape(self) -> list[TLDPriceData]:
|
|
"""
|
|
Return GoDaddy's known pricing data.
|
|
|
|
Since GoDaddy doesn't expose a public pricing API,
|
|
we use curated data from their public pricing pages.
|
|
|
|
Returns:
|
|
List of TLDPriceData objects with GoDaddy pricing
|
|
"""
|
|
results = []
|
|
now = datetime.utcnow()
|
|
|
|
for tld, prices in self.GODADDY_PRICES.items():
|
|
# Determine if this is promotional pricing
|
|
is_promo = prices.get("promo", False)
|
|
promo_price = prices["reg"] if is_promo else None
|
|
|
|
results.append(TLDPriceData(
|
|
tld=tld,
|
|
registrar="godaddy",
|
|
registration_price=prices["reg"],
|
|
renewal_price=prices["renew"],
|
|
transfer_price=prices.get("transfer"),
|
|
promo_price=promo_price,
|
|
currency="USD",
|
|
source="static",
|
|
confidence=0.9, # Static data, updated periodically
|
|
scraped_at=now,
|
|
notes="High renewal trap alert" if prices["renew"] > prices["reg"] * 3 else None,
|
|
))
|
|
|
|
logger.info(f"Loaded {len(results)} GoDaddy prices")
|
|
return results
|
|
|
|
async def health_check(self) -> bool:
|
|
"""Check if GoDaddy is accessible."""
|
|
try:
|
|
async with httpx.AsyncClient(timeout=10.0) as client:
|
|
response = await client.get(
|
|
self.base_url,
|
|
headers=self.get_headers(),
|
|
follow_redirects=True,
|
|
)
|
|
return response.status_code == 200
|
|
except Exception as e:
|
|
logger.debug(f"GoDaddy health check failed: {e}")
|
|
return False
|
|
|