second-automation-bot / app /studio_navigator.py
abdulsalam2121
first commit
ec2ef5e
Raw
History Blame Contribute Delete
6.15 kB
import logging
import re
import time
from typing import Optional
from urllib.parse import urlparse, parse_qs, urlencode, urlunparse
from browser_session import BrowserSession
logger = logging.getLogger("bot")
ALL_STUDIOS_URL = "https://www.adultdvdmarketplace.com/xcart/adult_dvd/studios.php"
class StudioNavigator:
def __init__(self, session: BrowserSession):
self.session = session
@property
def page(self):
return self.session.page
# ------------------------------------------------------------------
# Navigate by direct URL
# ------------------------------------------------------------------
def navigate_to_studio_url(self, url: str) -> bool:
"""Go to a studio listing URL, ensuring price ordering is set."""
url = self._ensure_price_sort(url)
logger.info(f"Opening studio URL: {url}")
if not self.session.goto(url):
return False
time.sleep(1)
logger.info("Studio page loaded")
return True
# ------------------------------------------------------------------
# Navigate by studio name
# ------------------------------------------------------------------
def _open_view_all_studios(self) -> bool:
page = self.page
top_studios_selectors = [
"a:has-text('TOP STUDIOS')",
"a:has-text('Top Studios')",
"button:has-text('TOP STUDIOS')",
"button:has-text('Top Studios')",
]
for sel in top_studios_selectors:
try:
menu = page.locator(sel).first
if menu.is_visible(timeout=1000):
try:
menu.hover(timeout=1000)
except Exception:
pass
menu.click()
time.sleep(1.5)
break
except Exception:
continue
view_all_selectors = [
"a:has-text('VIEW ALL STUDIOS...')",
"a:has-text('VIEW ALL STUDIOS')",
"a:has-text('View All Studios')",
"button:has-text('VIEW ALL STUDIOS')",
"button:has-text('View All Studios')",
]
for sel in view_all_selectors:
try:
link = page.locator(sel).first
if link.is_visible(timeout=2000):
logger.info(f"Found View All Studios link with selector: {sel}")
link.click()
page.wait_for_load_state("domcontentloaded", timeout=10000)
time.sleep(1)
logger.info("Opened all studios directory from menu")
return True
except Exception as e:
logger.debug(f"Failed to find/click VIEW ALL STUDIOS with {sel}: {e}")
continue
logger.warning("Could not open View All Studios from menu; using directory URL")
return self.session.goto(ALL_STUDIOS_URL)
def _click_studio_link(self, studio_name: str) -> bool:
page = self.page
escaped = re.escape(studio_name.strip())
patterns = [
re.compile(rf"^{escaped}\s+DVD Movies$", re.I),
re.compile(rf"^{escaped}$", re.I),
re.compile(escaped, re.I),
]
for attempt in range(1, 4):
try:
# Wait for studio directory content to render before searching links.
page.locator("a:has-text('DVD Movies')").first.wait_for(timeout=4000)
except Exception:
pass
for pattern in patterns:
try:
link = page.get_by_role("link", name=pattern).first
if link.is_visible(timeout=2000):
link.click()
page.wait_for_load_state("domcontentloaded", timeout=10000)
time.sleep(1)
return True
except Exception:
continue
try:
anchors = page.locator("a").all()
target = studio_name.lower().strip()
for anchor in anchors:
try:
text = anchor.inner_text(timeout=500).strip().lower()
if target in text and "dvd movies" in text:
anchor.click()
page.wait_for_load_state("domcontentloaded", timeout=10000)
time.sleep(1)
return True
except Exception:
continue
except Exception:
pass
if attempt < 3:
logger.warning(f"Studio link not found on attempt {attempt}; reloading all studios directory")
self.session.goto(ALL_STUDIOS_URL)
time.sleep(1)
return False
def find_studio_by_name(self, studio_name: str) -> Optional[str]:
"""Open the all-studios directory from the menu and click the matching studio."""
logger.info(f"Searching for studio: '{studio_name}'")
if not self._open_view_all_studios():
return None
if self._click_studio_link(studio_name):
current_url = self.page.url
logger.info(f"Opened studio page: {current_url}")
return self._ensure_price_sort(current_url)
logger.warning(f"Could not click studio link for: {studio_name}")
return None
# ------------------------------------------------------------------
# Helpers
# ------------------------------------------------------------------
@staticmethod
def _ensure_price_sort(url: str) -> str:
if "order_by=" in url:
return url
sep = "&" if "?" in url else "?"
return f"{url}{sep}order_by=price"
@staticmethod
def _make_absolute(href: str, base: str = "https://www.adultdvdmarketplace.com/xcart/") -> str:
if href.startswith("http"):
return href
from urllib.parse import urljoin
return urljoin(base, href)