text: import json
  from abc import ABC, abstractmethod
  from random import choice
  from typing import Optional, Union
  
  from selenium import webdriver
  from selenium.common.exceptions import TimeoutException, NoSuchElementException
  from selenium.webdriver.common.by import By
  from selenium.webdriver.firefox.options import Options
  from selenium.webdriver.support import expected_conditions as ec
  from selenium.webdriver.support.ui import WebDriverWait as Wait
  
  from src.utils import get_data_list
  
  
  class WrongEMailError(Exception):
      pass
  
  
  class Bot(ABC):
      _result = None
  
      def __init__(self, *, useragent: str = None, proxy: Optional[Union[list[str, int], tuple[str, int]]] = None):
          self.USERAGENT = useragent
          self.PROXY = proxy
  
          self._urls = self.__get_urls_json()
          options = Options()
          profile = webdriver.FirefoxProfile()
  
          # True - не показывать окно браузера
          options.headless = False
  
          # установка useragent
          if self.USERAGENT is not None:
              profile.set_preference("general.useragent.override", self.USERAGENT)
  
          # установка прокси
          if self.PROXY is not None:
              host, port = self.PROXY
              profile.set_preference("network.proxy.type", 1)
              profile.set_preference("network.proxy.http", host)
              profile.set_preference("network.proxy.http_port", port)
              profile.set_preference("network.proxy.https", host)
              profile.set_preference("network.proxy.https_port", port)
              profile.set_preference("network.proxy.ssl", host)
              profile.set_preference("network.proxy.ssl_port", port)
              profile.set_preference("network.proxy.ftp", host)
              profile.set_preference("network.proxy.ftp_port", port)
              profile.set_preference("network.proxy.socks", host)
              profile.set_preference("network.proxy.socks_port", port)
  
          profile.update_preferences()
          self._driver = webdriver.Firefox(firefox_profile=profile, firefox_options=options)
  
      @staticmethod
      def get_random_useragent():
          return choice(get_data_list('src/data/User-Agent.txt', size=8192))
  
      @staticmethod
      def __get_urls_json():
          return json.load(open('src/data/urls.json'))
  
      @staticmethod
      def _get_standard_number(number: str) -> str:
          return number.replace(' ', '').replace('-', '')
  
      @abstractmethod
      def get_result(self):
          pass
  
      def check_useragent_ip(self):
          self._driver.get('http://whatsmyuseragent.org')
          ua = self._driver.find_element_by_xpath('//div[@class="user-agent"]').text
          ip = self._driver.find_element_by_xpath('//div[@class="ip-address"]').text.split(':')[1].strip()
          return ua, ip
  
      def __del__(self):
          self._driver.quit()
  
  
  class MailBot(Bot):
  
      def __init__(self, target_email: str, **kwargs):
          self.__target_email = target_email
          super().__init__(**kwargs)
  
      def get_result(self) -> list:
          res = [self.__get_phone_number()]
          return res
  
      def __get_phone_number(self):
          self._driver.get(self._urls['mail'].format(self.__target_email))
  
          # Ожидает пока загрузится кнопка
          Wait(self._driver, 3).until(
  
              # ищет кнопку "Другие способы" и нажимает на неё
              ec.presence_of_element_located((By.XPATH, '//span[@data-test-id="more-link"]'))) \
              .find_element_by_class_name('base-0-2-69').click()
  
          # номер
          phone_number = self._driver.find_element_by_xpath('//span[@data-test-id="phone-link"]')
          return phone_number.get_attribute('data-item')
  
  
  class AutoRuParser(Bot):
      _result = []
  
      def __init__(self, model: str, **kwargs):
          self.__model = model
          super().__init__(**kwargs)
  
      def get_result(self) -> list:
          res = []
  
          for i in self.__get_urls_by_model():
              try:
                  res.append(self.__get_phone(i))
              except TimeoutException as e:
                  print(repr(e))
                  continue
  
          return res
  
      def __get_urls_by_model(self) -> list:
  
          self._driver.get(self._urls['autoru'].format(self.__model))
  
          links = self._driver.find_elements_by_xpath('//a[@class="Link ListingItemTitle-module__link"]')[1:10]
  
          res = []
          for i in links:
              res.append(i.get_attribute('href'))
          return res
  
      def __get_phone(self, url: str) -> tuple:
          self._driver.get(url)
  
          try:
              model = self._driver.find_element_by_xpath('//h1[@class="vvPW6PJaQXQwmDJz3qWOG__title"]').text.strip()
          except NoSuchElementException:
              model = '[NF]'
  
          try:
              price = self._driver.find_element_by_xpath('//span[@class="OfferPriceCaption__price"]').text.strip()
          except NoSuchElementException:
              price = '[NF]'
  
          Wait(self._driver, 3).until(
  
              # ищет кнопку "Показать номер" и нажимает на нее
              ec.presence_of_element_located((By.XPATH,
                                              '//button[@class="Button Button_color_green Button_size_l '
                                              'Button_type_button Button_width_full Button_radius_r4 '
                                              'OfferPhone-module__phone CardOwner-module__phone '
                                              'OfferPhone-module__phoneButton"]'))).click()
  
          try:
              number = self._driver.find_element_by_xpath('//div[@class="OfferPhone-module__phone-title"]').text
              number = self._get_standard_number(number)
          except NoSuchElementException:
              number = '[NF]'
          return model, price, number
  