mirror of https://github.com/Bunsly/JobSpy
implemented strategy design pattern for buttons in messages.
added handler for button callback Next: implement business logicpull/231/head
parent
8996c59492
commit
8195c2c884
|
@ -6,7 +6,7 @@ from telegram.ext import Application, CommandHandler, CallbackQueryHandler
|
||||||
from src.jobspy import Site
|
from src.jobspy import Site
|
||||||
from src.jobspy.scrapers.utils import create_logger
|
from src.jobspy.scrapers.utils import create_logger
|
||||||
from src.telegram_handler import TelegramIndeedHandler, TelegramDefaultHandler
|
from src.telegram_handler import TelegramIndeedHandler, TelegramDefaultHandler
|
||||||
from src.telegram_handler.telegram_callback_handler import TelegramCallHandler
|
from src.telegram_handler.button_callback.telegram_callback_handler import TelegramCallHandler
|
||||||
|
|
||||||
logger = create_logger("Main")
|
logger = create_logger("Main")
|
||||||
title_filters: list[str] = ["test", "qa", "Lead", "Full-Stack", "Full Stack", "Fullstack", "Frontend", "Front-end",
|
title_filters: list[str] = ["test", "qa", "Lead", "Full-Stack", "Full Stack", "Fullstack", "Frontend", "Front-end",
|
||||||
|
|
|
@ -44,7 +44,6 @@ class TelegramBot:
|
||||||
logger.error(f"Failed to send job to Telegram: {job.id}")
|
logger.error(f"Failed to send job to Telegram: {job.id}")
|
||||||
logger.error(f"Error: {e}")
|
logger.error(f"Error: {e}")
|
||||||
|
|
||||||
|
|
||||||
async def send_test_message(self):
|
async def send_test_message(self):
|
||||||
"""
|
"""
|
||||||
Send Test Message to Telegram chat.
|
Send Test Message to Telegram chat.
|
||||||
|
@ -65,15 +64,14 @@ class TelegramBot:
|
||||||
logger.error("Failed o send test message to Telegram")
|
logger.error("Failed o send test message to Telegram")
|
||||||
logger.error(f"Error: {e}")
|
logger.error(f"Error: {e}")
|
||||||
|
|
||||||
|
async def set_message_reaction(self, message_id: int, emoji_reaction: ReactionEmoji):
|
||||||
async def set_message_reaction(self, message_id: int, emoji_reaction: str):
|
|
||||||
"""
|
"""
|
||||||
Send Test Message to Telegram chat.
|
Send Test Message to Telegram chat.
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
await self.bot.set_message_reaction(chat_id=self.chatId, message_id=message_id,
|
await self.bot.set_message_reaction(chat_id=self.chatId, message_id=message_id,
|
||||||
reaction=ReactionEmoji[emoji_reaction])
|
reaction=emoji_reaction)
|
||||||
logger.info("Sent test message to Telegram")
|
logger.info(f"Reaction set to message: {message_id}")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error("Failed to send test message to Telegram")
|
logger.error(f"Failed to set Reaction to message: {message_id}")
|
||||||
logger.error(f"Error: {e}")
|
logger.error(f"Error: {e}")
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from src.telegram_bot import TelegramBot
|
||||||
|
from src.telegram_handler.button_callback.button_strategy import ButtonStrategy
|
||||||
|
|
||||||
|
|
||||||
|
class ButtonCallBackContext():
|
||||||
|
"""
|
||||||
|
The Context defines the interface
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, strategy: ButtonStrategy = None) -> None:
|
||||||
|
self.telegram_bot = TelegramBot()
|
||||||
|
self._strategy = strategy
|
||||||
|
|
||||||
|
@property
|
||||||
|
def strategy(self) -> ButtonStrategy:
|
||||||
|
"""
|
||||||
|
The Context maintains a reference to one of the Strategy objects. The
|
||||||
|
Context does not know the concrete class of a strategy. It should work
|
||||||
|
with all strategies via the Strategy interface.
|
||||||
|
"""
|
||||||
|
|
||||||
|
return self._strategy
|
||||||
|
|
||||||
|
@strategy.setter
|
||||||
|
def strategy(self, strategy: ButtonStrategy) -> None:
|
||||||
|
"""
|
||||||
|
Usually, the Context allows replacing a Strategy object at runtime.
|
||||||
|
"""
|
||||||
|
|
||||||
|
self._strategy = strategy
|
||||||
|
|
||||||
|
async def run(self) -> None:
|
||||||
|
# extract job id from message
|
||||||
|
# find the position in DB
|
||||||
|
# set applied to True
|
||||||
|
# save
|
||||||
|
# set reaction to message
|
||||||
|
|
||||||
|
print("Context: Starting")
|
||||||
|
await self._strategy.execute()
|
||||||
|
print("Context: Finished")
|
||||||
|
|
||||||
|
# ...
|
|
@ -0,0 +1,24 @@
|
||||||
|
from telegram import MaybeInaccessibleMessage
|
||||||
|
from telegram.constants import ReactionEmoji
|
||||||
|
|
||||||
|
from src.telegram_bot import TelegramBot
|
||||||
|
from src.telegram_handler.button_callback.button_strategy import ButtonStrategy
|
||||||
|
|
||||||
|
|
||||||
|
class FireStrategy(ButtonStrategy):
|
||||||
|
def __init__(self, data: MaybeInaccessibleMessage) -> None:
|
||||||
|
"""
|
||||||
|
Usually, the Context accepts a strategy through the constructor, but
|
||||||
|
also provides a setter to change it at runtime.
|
||||||
|
"""
|
||||||
|
self.data = data
|
||||||
|
self._emoji = ReactionEmoji.FIRE
|
||||||
|
|
||||||
|
async def execute(self):
|
||||||
|
telegram_bot = TelegramBot()
|
||||||
|
await telegram_bot.set_message_reaction(self.data.message_id, self._emoji)
|
||||||
|
# find the position in DB
|
||||||
|
# set applied to True
|
||||||
|
# save
|
||||||
|
# set reaction to message
|
||||||
|
pass
|
|
@ -0,0 +1,17 @@
|
||||||
|
from telegram import MaybeInaccessibleMessage
|
||||||
|
from telegram.constants import ReactionEmoji
|
||||||
|
|
||||||
|
from src.telegram_handler.button_callback.button_strategy import ButtonStrategy
|
||||||
|
|
||||||
|
|
||||||
|
class PooStrategy(ButtonStrategy):
|
||||||
|
def __init__(self, data: MaybeInaccessibleMessage) -> None:
|
||||||
|
"""
|
||||||
|
Usually, the Context accepts a strategy through the constructor, but
|
||||||
|
also provides a setter to change it at runtime.
|
||||||
|
"""
|
||||||
|
self.data = data
|
||||||
|
self._emoji = ReactionEmoji.PILE_OF_POO
|
||||||
|
|
||||||
|
async def execute(self):
|
||||||
|
pass
|
|
@ -0,0 +1,15 @@
|
||||||
|
from abc import ABC, abstractmethod
|
||||||
|
|
||||||
|
|
||||||
|
class ButtonStrategy(ABC):
|
||||||
|
"""
|
||||||
|
The Strategy interface declares operations common to all supported versions
|
||||||
|
of some algorithm.
|
||||||
|
|
||||||
|
The Context uses this interface to call the algorithm defined by Concrete
|
||||||
|
Strategies.
|
||||||
|
"""
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
async def execute(self):
|
||||||
|
pass
|
|
@ -0,0 +1,37 @@
|
||||||
|
from telegram import Update
|
||||||
|
from telegram.constants import ReactionEmoji
|
||||||
|
from telegram.ext import (
|
||||||
|
ContextTypes,
|
||||||
|
)
|
||||||
|
|
||||||
|
from src.telegram_bot import TelegramBot
|
||||||
|
from src.telegram_handler.button_callback.button_callback_context import ButtonCallBackContext
|
||||||
|
from src.telegram_handler.button_callback.button_fire_strategy import FireStrategy
|
||||||
|
from src.telegram_handler.button_callback.button_poo_strategy import PooStrategy
|
||||||
|
|
||||||
|
|
||||||
|
class TelegramCallHandler:
|
||||||
|
def __init__(self):
|
||||||
|
self.telegram_bot = TelegramBot()
|
||||||
|
|
||||||
|
async def button_callback(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()
|
||||||
|
button_context = ButtonCallBackContext()
|
||||||
|
if ReactionEmoji.FIRE.name == query.data:
|
||||||
|
strategy = FireStrategy(query.message)
|
||||||
|
# elif ReactionEmoji.PILE_OF_POO.name == query.data:
|
||||||
|
# strategy = PooStrategy(query.message)
|
||||||
|
else:
|
||||||
|
raise ValueError("Invalid enum value")
|
||||||
|
|
||||||
|
if not strategy:
|
||||||
|
return
|
||||||
|
|
||||||
|
button_context.strategy = strategy
|
||||||
|
await button_context.run()
|
||||||
|
|
|
@ -1,21 +0,0 @@
|
||||||
from telegram import Update
|
|
||||||
from telegram.ext import (
|
|
||||||
ContextTypes,
|
|
||||||
)
|
|
||||||
|
|
||||||
from src.telegram_bot import TelegramBot
|
|
||||||
|
|
||||||
|
|
||||||
class TelegramCallHandler:
|
|
||||||
def __init__(self):
|
|
||||||
self.telegram_bot = TelegramBot()
|
|
||||||
|
|
||||||
async def button_callback(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)
|
|
||||||
|
|
Loading…
Reference in New Issue