Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactoring code base for supporting other job portals. #943

Open
Tracked by #401
surapuramakhil opened this issue Nov 25, 2024 · 3 comments · Fixed by #973
Open
Tracked by #401

Refactoring code base for supporting other job portals. #943

surapuramakhil opened this issue Nov 25, 2024 · 3 comments · Fixed by #973
Assignees
Labels
enhancement New feature or request planned planned goal

Comments

@surapuramakhil
Copy link
Contributor

surapuramakhil commented Nov 25, 2024

python package structure

src/
└── job_portals/
    └── linkedin/
        ├── job_search/
        │   ├── __init__.py
        │   ├── job_search.py
        │   └── job_page.py
        └── easy_apply/
            ├── __init__.py
            └── easy_apply_code.py

List of use cases where browser interactions happening

  1. Landing on job poral page, login flow
  2. generating portal specific URL's for performing seraches
  3. Job Serach pages / list jobs page - get_job_from_page()
  4. conversion of job UI element to Job object
  5. next / submit flow - interacting with components filling form

Kindly add any missed use cases (by editing description)

@surapuramakhil
Copy link
Contributor Author

from abc import ABC, abstractmethod
from re import A

from constants import LINKEDIN
from src.ai_hawk.authenticator import AIHawkAuthenticator
from src.job import Job
from src.jobContext import JobContext

from selenium.webdriver.remote.webelement import WebElement
from typing import List


class WebPage(ABC):

    def __init__(self, driver):
        self.driver = driver


class BaseJobsPage(WebPage):

    def __init__(self, driver, parameters):
        super().__init__(driver)
        self.parameters = parameters

    @abstractmethod
    def next_job_page(self, position, location, page_number):
        pass

    @abstractmethod
    def job_tile_to_job(self, job_tile: WebElement) -> Job:
        pass

    @abstractmethod
    def get_jobs_from_page(self, scroll=False) -> List[WebElement]:
        pass


class BaseJobPage(WebPage):

    def __init__(self, driver):
        super().__init__(driver)

    @abstractmethod
    def goto_job_page(self, job: Job):
        pass

    @abstractmethod
    def get_apply_button(self, job_context: JobContext) -> WebElement:
        pass

    @abstractmethod
    def get_job_description(self, job: Job) -> str:
        pass

    @abstractmethod
    def get_recruiter_link(self) -> str:
        pass

    @abstractmethod
    def click_apply_button(self, job_context: JobContext) -> None:
        pass


class BaseApplicationPage(WebPage):

    def __init__(self, driver):
        super().__init__(driver)

    @abstractmethod
    def has_next_button(self) -> bool:
        pass

    @abstractmethod
    def click_next_button(self) -> None:
        pass

    @abstractmethod
    def has_submit_button(self) -> bool:
        pass

    @abstractmethod
    def click_submit_button(self) -> None:
        pass

    @abstractmethod
    def has_errors(self) -> None:
        pass

    @abstractmethod
    def handle_errors(self) -> None:
        """this methos is also called as fix errors"""
        pass
    
    @abstractmethod
    def check_for_errors(self) -> None:
        """As the current impl needs this, later when we add retry mechanism, we will be moving to has errors and handle errors"""
        pass

    @abstractmethod
    def get_input_elements(self) -> List[WebElement]:
        """ this method will update to Enum / other easy way (in future) instead of webList """
        pass

    @abstractmethod
    def is_upload_field(self, element: WebElement) -> bool:
        pass
    
    


class BaseJobPortal(ABC):

    def __init__(self, driver):
        self.driver = driver

    @property
    @abstractmethod
    def jobs_page(self) -> BaseJobsPage:
        pass

    @property
    @abstractmethod
    def job_page(self) -> BaseJobPage:
        pass

    @property
    @abstractmethod
    def authenticator(self) -> AIHawkAuthenticator:
        pass

    @property
    @abstractmethod
    def application_page(self) -> BaseApplicationPage:
        pass


def get_job_portal(portal_name, driver, parameters):
    from src.job_portals.linkedIn.linkedin import LinkedIn

    if portal_name == LINKEDIN:
        return LinkedIn(driver, parameters)
    else:
        raise ValueError(f"Unknown job portal: {portal_name}")


def get_authenticator(driver, platform):
    from src.job_portals.linkedIn.authenticator import LinkedInAuthenticator

    if platform == LINKEDIN:
        return LinkedInAuthenticator(driver)
    else:
        raise NotImplementedError(f"Platform {platform} not implemented yet.")

@surapuramakhil surapuramakhil linked a pull request Nov 30, 2024 that will close this issue
@feder-cr
Copy link
Collaborator

feder-cr commented Dec 1, 2024

@surapuramakhil According to my point of view, we should give much more freedom to plugin developers. We will only provide: CV, Cover Letter, and answers to questions. Then it will be up to the plugin creators to decide how to use them, and it will be up to the users to decide whether to use a plugin or not.

@surapuramakhil
Copy link
Contributor Author

surapuramakhil commented Dec 1, 2024

@feder-cr these are job portal plugins, "they are intended for interactions between this project and portal". Can you share use cases where it restricts?

ps. interface will always evolve accommodating use cases of Job portals i.e. plugins

We will only provide: CV, Cover Letter, and answers to questions

  1. Doing this will make this project useless, not much value of this.
  2. Plugin owners need to write job managers, job appliers and other things - a lot of work for plugin owners (which they won't be happy)
  3. not to mention security issues or other things that plugin code can create.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request planned planned goal
Projects
Status: In Progress
Development

Successfully merging a pull request may close this issue.

2 participants