From 7f7d7f96d6c881f6574e3c5deb8d1046059bf59c Mon Sep 17 00:00:00 2001 From: Yariv Menachem <yariv220895@gmail.com> Date: Sun, 29 Dec 2024 17:11:05 +0200 Subject: [PATCH] added buttons to job message sent to chat and a callback to update the message --- src/main.py | 5 +- src/telegram_bot.py | 70 ++++++++++++++----- .../telegram_default_handler.py | 13 +++- .../telegram_indeed_handler.py | 2 +- src/tests/test_telegram.py | 9 +-- 5 files changed, 74 insertions(+), 25 deletions(-) diff --git a/src/main.py b/src/main.py index c753d44..36d568b 100644 --- a/src/main.py +++ b/src/main.py @@ -1,7 +1,7 @@ import os from telegram import Update -from telegram.ext import Application, CommandHandler +from telegram.ext import Application, CommandHandler, CallbackQueryHandler from src.jobspy import Site from src.jobspy.scrapers.utils import create_logger @@ -10,7 +10,7 @@ from src.telegram_handler import TelegramIndeedHandler, TelegramDefaultHandler logger = create_logger("Main") title_filters: list[str] = ["test", "qa", "Lead", "Full-Stack", "Full Stack", "Fullstack", "Frontend", "Front-end", "Front End", "DevOps", "Physical", "Staff", - "automation", "BI", "Principal", "Architect", "Android", "Machine Learning", "Student", + "automation", "BI ", "Principal", "Architect", "Android", "Machine Learning", "Student", "Data Engineer", "DevSecOps"] if __name__ == "__main__": @@ -47,5 +47,6 @@ if __name__ == "__main__": title_filters=title_filters, search_term=search_term) application.add_handler(CommandHandler(Site.INDEED.value, tg_handler_indeed.handle)) + application.add_handler(CallbackQueryHandler(tg_handler_linkedin.button)) logger.info("Run polling from telegram") application.run_polling(allowed_updates=Update.ALL_TYPES) diff --git a/src/telegram_bot.py b/src/telegram_bot.py index d34084b..77d433e 100644 --- a/src/telegram_bot.py +++ b/src/telegram_bot.py @@ -1,14 +1,8 @@ import os from dotenv import load_dotenv -from telegram import Bot, Update -from telegram.ext import ( - Application, - CommandHandler, - ContextTypes, - ConversationHandler, - MessageHandler, - filters, -) +from telegram import Bot, InlineKeyboardButton, InlineKeyboardMarkup +from telegram.constants import ReactionEmoji + from src.jobspy.jobs import JobPost from src.jobspy.scrapers.utils import create_logger @@ -24,18 +18,62 @@ class TelegramBot: self.chatId = os.getenv("TELEGRAM_CHAT_ID") self.bot = Bot(token=self._api_token) - async def sendJob(self, job: JobPost): + async def send_job(self, job: JobPost): """ Send JobPost details to Telegram chat. """ message = f"Job ID: {job.id}\n" \ - f"Job Title: {job.title}\n" \ - f"Company: {job.company_name}\n" \ - f"Location: {job.location.display_location()}\n" \ - f"Link: {job.job_url}\n" + f"Job Title: {job.title}\n" \ + f"Company: {job.company_name}\n" \ + f"Location: {job.location.display_location()}\n" \ + f"Link: {job.job_url}\n" + + keyboard = [ + [ + InlineKeyboardButton(ReactionEmoji.FIRE, callback_data=ReactionEmoji.FIRE.name), + InlineKeyboardButton(ReactionEmoji.PILE_OF_POO, callback_data=ReactionEmoji.PILE_OF_POO.name) + ], + ] + + reply_markup = InlineKeyboardMarkup(keyboard) + try: - await self.bot.sendMessage(chat_id=self.chatId, text=message) + await self.bot.sendMessage(chat_id=self.chatId, text=message, reply_markup=reply_markup) logger.info(f"Sent job to Telegram: {job.id}") except Exception as e: logger.error(f"Failed to send job to Telegram: {job.id}") - logger.error(f"Error: {e}") \ No newline at end of file + logger.error(f"Error: {e}") + + + async def send_test_message(self): + """ + Send Test Message to Telegram chat. + """ + message = "Test Test Testing" + try: + keyboard = [ + [ + InlineKeyboardButton(ReactionEmoji.FIRE, callback_data=ReactionEmoji.FIRE.name), + InlineKeyboardButton(ReactionEmoji.PILE_OF_POO, callback_data=ReactionEmoji.PILE_OF_POO.name) + ], + ] + + reply_markup = InlineKeyboardMarkup(keyboard) + await self.bot.sendMessage(chat_id=self.chatId, text=message, reply_markup=reply_markup) + logger.info("Sent test message to Telegram") + except Exception as e: + logger.error("Failed o send test message to Telegram") + logger.error(f"Error: {e}") + + + async def set_message_reaction(self, message_id: int, emoji_reaction: str): + """ + Send Test Message to Telegram chat. + """ + try: + await self.bot.set_message_reaction(chat_id=self.chatId, message_id=message_id, + reaction=ReactionEmoji[emoji_reaction]) + logger.info("Sent test message to Telegram") + except Exception as e: + logger.error("Failed to send test message to Telegram") + logger.error(f"Error: {e}") diff --git a/src/telegram_handler/telegram_default_handler.py b/src/telegram_handler/telegram_default_handler.py index 49b71dd..23d8496 100644 --- a/src/telegram_handler/telegram_default_handler.py +++ b/src/telegram_handler/telegram_default_handler.py @@ -16,13 +16,22 @@ class TelegramDefaultHandler(TelegramHandler): self.locations = locations self.search_term = search_term self.title_filters = title_filters - self.telegramBot = TelegramBot() + self.telegram_bot = TelegramBot() self.jobRepository = JobRepository() if len(sites) == 1: self.logger = create_logger(f"Telegram{sites[0].name.title()}Handler") else: self.logger = create_logger("TelegramAllHandler") + async def button(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> None: + """Parses the CallbackQuery and updates the message text.""" + query = update.callback_query + + # CallbackQueries need to be answered, even if no notification to the user is needed + # Some clients may have trouble otherwise. See https://core.telegram.org/bots/api#callbackquery + await query.answer() + await self.telegram_bot.set_message_reaction(query.message.message_id, query.data) + async def handle(self, update: Update, context: ContextTypes.DEFAULT_TYPE): self.logger.info("start handling") jobs = scrape_jobs( @@ -36,5 +45,5 @@ class TelegramDefaultHandler(TelegramHandler): self.logger.info(f"Found {len(jobs)} jobs") new_jobs = self.jobRepository.insertManyIfNotFound(jobs) for newJob in new_jobs: - await self.telegramBot.sendJob(newJob) + await self.telegram_bot.send_job(newJob) self.logger.info("finished handling") diff --git a/src/telegram_handler/telegram_indeed_handler.py b/src/telegram_handler/telegram_indeed_handler.py index 21dd975..de3b237 100644 --- a/src/telegram_handler/telegram_indeed_handler.py +++ b/src/telegram_handler/telegram_indeed_handler.py @@ -34,5 +34,5 @@ class TelegramIndeedHandler(TelegramHandler): self.logger.info(f"Found {len(jobs)} jobs") new_jobs = self.jobRepository.insertManyIfNotFound(jobs) for newJob in new_jobs: - await self.telegramBot.sendJob(newJob) + await self.telegramBot.send_job(newJob) self.logger.info("finished handling") diff --git a/src/tests/test_telegram.py b/src/tests/test_telegram.py index eca0cac..a2296ed 100644 --- a/src/tests/test_telegram.py +++ b/src/tests/test_telegram.py @@ -1,8 +1,9 @@ import asyncio + from dotenv import load_dotenv -from jobspy.db.job_repository import JobRepository -from jobspy.telegram_bot import TelegramBot -from tests.test_util import createMockJob + +from src.telegram_bot import TelegramBot +from src.tests.test_util import createMockJob load_dotenv() @@ -21,7 +22,7 @@ class TelegramTests: Sents a mock job Telegram using Telegram Bot. """ job = createMockJob() - await self.bot.sendJob(job) + await self.bot.send_job(job) print(f"Test sent job finished.")