From 34a1933ecd853b458b203c40dd311d05fd4b5dd7 Mon Sep 17 00:00:00 2001 From: Yariv Menachem Date: Tue, 31 Dec 2024 15:40:35 +0200 Subject: [PATCH] fixed fire call button to update the job in db applied = true --- src/db/job_repository.py | 41 ++++++++++++++++- src/jobspy/jobs/__init__.py | 1 + .../button_callback/button_fire_strategy.py | 46 +++++++++++++++---- .../telegram_callback_handler.py | 2 +- 4 files changed, 79 insertions(+), 11 deletions(-) diff --git a/src/db/job_repository.py b/src/db/job_repository.py index 0f7fc86..c89d046 100644 --- a/src/db/job_repository.py +++ b/src/db/job_repository.py @@ -1,3 +1,5 @@ +from typing import Optional + from dotenv import load_dotenv from pymongo import UpdateOne @@ -24,12 +26,47 @@ class JobRepository: self.logger.info("Succeed connect to MongoDB") return cls._instance + def find_by_id(self, job_id: str) -> Optional[JobPost]: + """ + Finds a job document in the collection by its ID. + + Args: + job_id: The ID of the job to find. + + Returns: + The job document if found, otherwise None. + """ + result = self.collection.find_one({"id": job_id}) + return result + + def update(self, job_data: dict) -> bool: + """ + Updates a JobPost in the database. + + Args: + job_data: A dictionary representing the JobPost data. + + Returns: + True if the update was successful, False otherwise. + """ + result = self.collection.update_one({"id": job_data["id"]}, {"$set": job_data}) + return result.modified_count > 0 + def insert_job(self, job: JobPost): + """ + Inserts a new job posting into the database collection. + + Args: + job (JobPost): The JobPost object to be inserted. + + Raises: + Exception: If an error occurs during insertion. + """ job_dict = job.model_dump(exclude={"date_posted"}) self.collection.insert_one(job_dict) self.logger.info(f"Inserted new job with title {job.title}.") - def insert_many_if_not_found(self, jobs: list[JobPost]) -> tuple[list[JobPost],list[JobPost]]: + def insert_many_if_not_found(self, jobs: list[JobPost]) -> tuple[list[JobPost], list[JobPost]]: """ Perform bulk upserts for a list of JobPost objects into a MongoDB collection. Only insert new jobs and return the list of newly inserted jobs. @@ -62,4 +99,4 @@ class JobRepository: else: old_jobs.append(job) - return old_jobs ,new_jobs + return old_jobs, new_jobs diff --git a/src/jobspy/jobs/__init__.py b/src/jobspy/jobs/__init__.py index 7ad75a3..beaa1f2 100644 --- a/src/jobspy/jobs/__init__.py +++ b/src/jobspy/jobs/__init__.py @@ -279,6 +279,7 @@ class JobPost(BaseModel): is_remote: bool | None = None listing_type: str | None = None field: str | None = None + applied: bool = False # linkedin specific job_level: str | None = None diff --git a/src/telegram_handler/button_callback/button_fire_strategy.py b/src/telegram_handler/button_callback/button_fire_strategy.py index 3ab906c..31c5e2e 100644 --- a/src/telegram_handler/button_callback/button_fire_strategy.py +++ b/src/telegram_handler/button_callback/button_fire_strategy.py @@ -1,24 +1,54 @@ from telegram import MaybeInaccessibleMessage from telegram.constants import ReactionEmoji +from db.job_repository import JobRepository +from jobspy import create_logger from telegram_bot import TelegramBot from telegram_handler.button_callback.button_strategy import ButtonStrategy +def _extract_job_id(message: str) -> str: + """ + Extracts the job ID from a job description string. + + Args: + message: The string containing the job description. + + Returns: + The extracted job ID, or an empty string if not found. + """ + # Find the starting position of the ID + start_pos = message.find("Job ID: ") + if start_pos == -1: + return "" # Not found + + # Find the ending position of the ID (excluding newline) + end_pos = message.find("\n", start_pos + len("Job ID: ")) + if end_pos == -1: + end_pos = len(message) # No newline, use string end + + # Extract the ID substring + return message[start_pos + len("Job ID: "):end_pos] + + class FireStrategy(ButtonStrategy): def __init__(self, message: MaybeInaccessibleMessage) -> None: """ Usually, the Context accepts a strategy through the constructor, but also provides a setter to change it at runtime. """ - self.message = message + self._message = message self._emoji = ReactionEmoji.FIRE - self.telegram_bot = TelegramBot() + self._telegram_bot = TelegramBot() + self._job_repository = JobRepository() + self._logger = create_logger("FireStrategy") async def execute(self): - await self.telegram_bot.set_message_reaction(self.message.message_id, self._emoji) - # find the position in DB - # set applied to True - # save - # set reaction to message - pass + job_id = _extract_job_id(self._message.text) + job = self._job_repository.find_by_id(job_id) + if not job: + self._logger.error(f"Job with ID {job_id} not found.") + return + job["applied"] = True + self._job_repository.update(job) + await self._telegram_bot.set_message_reaction(self._message.message_id, self._emoji) diff --git a/src/telegram_handler/button_callback/telegram_callback_handler.py b/src/telegram_handler/button_callback/telegram_callback_handler.py index 46cd678..16a156e 100644 --- a/src/telegram_handler/button_callback/telegram_callback_handler.py +++ b/src/telegram_handler/button_callback/telegram_callback_handler.py @@ -20,6 +20,6 @@ class TelegramCallHandler: """Parses the CallbackQuery and updates the message.""" query = update.callback_query await query.answer() - button_context = ButtonCallBackContext(query.data,query.message) + button_context = ButtonCallBackContext(query.data, query.message) await button_context.run()