mirror of
https://github.com/miloszowi/everyone-mention-telegram-bot.git
synced 2025-12-29 18:17:28 +00:00
0.1.0 Version : changed in to join and out to leave, folder structure and naming changes
This commit is contained in:
37
src/bot/handler/abstractHandler.py
Executable file
37
src/bot/handler/abstractHandler.py
Executable file
@@ -0,0 +1,37 @@
|
||||
from abc import abstractmethod
|
||||
|
||||
from bot.message.messageData import MessageData
|
||||
from logger import Logger
|
||||
from telegram.ext.callbackcontext import CallbackContext
|
||||
from telegram.ext.handler import Handler
|
||||
from telegram.update import Update
|
||||
from telegram.utils.helpers import mention_markdown
|
||||
|
||||
|
||||
class AbstractHandler:
|
||||
@abstractmethod
|
||||
def get_bot_handler(self) -> Handler: raise Exception('get_bot_handler method is not implemented')
|
||||
|
||||
@abstractmethod
|
||||
def handle(self, update: Update, context: CallbackContext) -> None: raise Exception('handle method is not implemented')
|
||||
|
||||
@abstractmethod
|
||||
def log_action(self, message_data: MessageData) -> None: raise Exception('log_action method is not implemented')
|
||||
|
||||
def interpolate_reply(self, reply: str, message_data: MessageData):
|
||||
return reply.format(
|
||||
mention_markdown(message_data.user_id, message_data.username),
|
||||
message_data.group_name
|
||||
)
|
||||
|
||||
def reply_markdown(self, update: Update, message: str) -> None:
|
||||
try:
|
||||
update.effective_message.reply_markdown_v2(text=message)
|
||||
except Exception as err:
|
||||
Logger.error(str(err))
|
||||
|
||||
def reply_html(self, update: Update, html: str) -> None:
|
||||
try:
|
||||
update.effective_message.reply_html(text=html)
|
||||
except Exception as err:
|
||||
Logger.error(str(err))
|
||||
45
src/bot/handler/groupsHandler.py
Normal file
45
src/bot/handler/groupsHandler.py
Normal file
@@ -0,0 +1,45 @@
|
||||
from typing import Iterable
|
||||
|
||||
import prettytable as pt
|
||||
from bot.handler.abstractHandler import AbstractHandler
|
||||
from bot.message.messageData import MessageData
|
||||
from config.contents import no_groups
|
||||
from entity.group import Group
|
||||
from logger import Logger
|
||||
from repository.groupRepository import GroupRepository
|
||||
from telegram.ext.callbackcontext import CallbackContext
|
||||
from telegram.ext.commandhandler import CommandHandler
|
||||
from telegram.update import Update
|
||||
|
||||
|
||||
class GroupsHandler(AbstractHandler):
|
||||
bot_handler: CommandHandler
|
||||
group_repository: GroupRepository
|
||||
|
||||
def __init__(self) -> None:
|
||||
self.bot_handler = CommandHandler('groups', self.handle)
|
||||
self.group_repository = GroupRepository()
|
||||
|
||||
def handle(self, update: Update, context: CallbackContext) -> None:
|
||||
message_data = MessageData.create_from_arguments(update, context, False)
|
||||
|
||||
groups = self.group_repository.get_by_chat_id(message_data.chat_id)
|
||||
|
||||
if groups:
|
||||
self.reply_html(update, self.build_groups_message(groups))
|
||||
return self.log_action(message_data)
|
||||
|
||||
self.reply_markdown(update, no_groups)
|
||||
|
||||
def get_bot_handler(self) -> CommandHandler:
|
||||
return self.bot_handler
|
||||
|
||||
def log_action(self, message_data: MessageData) -> None:
|
||||
Logger.info(f'User {message_data.username} called /groups for {message_data.chat_id}')
|
||||
|
||||
def build_groups_message(self, groups: Iterable[Group]) -> str:
|
||||
resultTable = pt.PrettyTable(['Name', 'Members'])
|
||||
|
||||
resultTable.add_rows([[record.group_name, record.users_count] for record in groups])
|
||||
|
||||
return f'<pre>{str(resultTable)}</pre>'
|
||||
46
src/bot/handler/joinHandler.py
Executable file
46
src/bot/handler/joinHandler.py
Executable file
@@ -0,0 +1,46 @@
|
||||
from telegram.utils.helpers import mention_markdown
|
||||
from bot.handler.abstractHandler import AbstractHandler
|
||||
from bot.message.messageData import MessageData
|
||||
from config.contents import joined, not_joined
|
||||
from exception.invalidArgumentException import InvalidArgumentException
|
||||
from exception.notFoundException import NotFoundException
|
||||
from logger import Logger
|
||||
from repository.userRepository import UserRepository
|
||||
from telegram.ext.callbackcontext import CallbackContext
|
||||
from telegram.ext.commandhandler import CommandHandler
|
||||
from telegram.update import Update
|
||||
|
||||
|
||||
class JoinHandler(AbstractHandler):
|
||||
bot_handler: CommandHandler
|
||||
user_repository: UserRepository
|
||||
|
||||
def __init__(self) -> None:
|
||||
self.bot_handler = CommandHandler('join', self.handle)
|
||||
self.user_repository = UserRepository()
|
||||
|
||||
def handle(self, update: Update, context: CallbackContext) -> None:
|
||||
try:
|
||||
message_data = MessageData.create_from_arguments(update, context)
|
||||
except InvalidArgumentException as e:
|
||||
return self.reply_markdown(update, str(e))
|
||||
|
||||
try:
|
||||
user = self.user_repository.get_by_id(message_data.user_id)
|
||||
|
||||
if user.is_in_chat(message_data.chat_id):
|
||||
return self.reply_markdown(update, self.interpolate_reply(not_joined, message_data))
|
||||
|
||||
user.add_to_chat(message_data.chat_id)
|
||||
self.user_repository.save(user)
|
||||
except NotFoundException:
|
||||
self.user_repository.save_by_message_data(message_data)
|
||||
|
||||
self.reply_markdown(update, self.interpolate_reply(joined, message_data))
|
||||
self.log_action(message_data)
|
||||
|
||||
def get_bot_handler(self) -> CommandHandler:
|
||||
return self.bot_handler
|
||||
|
||||
def log_action(self, message_data: MessageData) -> None:
|
||||
Logger.info(f'User {message_data.username} joined {message_data.chat_id}')
|
||||
45
src/bot/handler/leaveHandler.py
Executable file
45
src/bot/handler/leaveHandler.py
Executable file
@@ -0,0 +1,45 @@
|
||||
from bot.handler.abstractHandler import AbstractHandler
|
||||
from bot.message.messageData import MessageData
|
||||
from config.contents import left, not_left
|
||||
from exception.invalidArgumentException import InvalidArgumentException
|
||||
from exception.notFoundException import NotFoundException
|
||||
from logger import Logger
|
||||
from repository.userRepository import UserRepository
|
||||
from telegram.ext.callbackcontext import CallbackContext
|
||||
from telegram.ext.commandhandler import CommandHandler
|
||||
from telegram.update import Update
|
||||
|
||||
|
||||
class LeaveHandler(AbstractHandler):
|
||||
bot_handler: CommandHandler
|
||||
user_repository: UserRepository
|
||||
|
||||
def __init__(self) -> None:
|
||||
self.bot_handler = CommandHandler('leave', self.handle)
|
||||
self.user_repository = UserRepository()
|
||||
|
||||
def handle(self, update: Update, context: CallbackContext) -> None:
|
||||
try:
|
||||
message_data = MessageData.create_from_arguments(update, context)
|
||||
except InvalidArgumentException as e:
|
||||
return self.reply_markdown(update, str(e))
|
||||
|
||||
try:
|
||||
user = self.user_repository.get_by_id(message_data.user_id)
|
||||
|
||||
if not user.is_in_chat(message_data.chat_id):
|
||||
raise NotFoundException()
|
||||
except NotFoundException:
|
||||
return self.reply_markdown(update, self.interpolate_reply(not_left, message_data))
|
||||
|
||||
user.remove_from_chat(message_data.chat_id)
|
||||
self.user_repository.save(user)
|
||||
|
||||
self.reply_markdown(update, self.interpolate_reply(left, message_data))
|
||||
self.log_action(message_data)
|
||||
|
||||
def get_bot_handler(self) -> CommandHandler:
|
||||
return self.bot_handler
|
||||
|
||||
def log_action(self, message_data: MessageData) -> None:
|
||||
Logger.info(f'User {message_data.username} left {message_data.chat_id}')
|
||||
47
src/bot/handler/mentionHandler.py
Executable file
47
src/bot/handler/mentionHandler.py
Executable file
@@ -0,0 +1,47 @@
|
||||
from typing import Iterable
|
||||
|
||||
from telegram.utils.helpers import mention_markdown
|
||||
|
||||
from bot.handler.abstractHandler import AbstractHandler
|
||||
from bot.message.messageData import MessageData
|
||||
from config.contents import mention_failed
|
||||
from entity.user import User
|
||||
from exception.invalidArgumentException import InvalidArgumentException
|
||||
from logger import Logger
|
||||
from repository.userRepository import UserRepository
|
||||
from telegram.ext.callbackcontext import CallbackContext
|
||||
from telegram.ext.commandhandler import CommandHandler
|
||||
from telegram.update import Update
|
||||
|
||||
|
||||
class MentionHandler(AbstractHandler):
|
||||
bot_handler: CommandHandler
|
||||
user_repository: UserRepository
|
||||
|
||||
def __init__(self) -> None:
|
||||
self.bot_handler = CommandHandler('everyone', self.handle)
|
||||
self.user_repository = UserRepository()
|
||||
|
||||
def handle(self, update: Update, context: CallbackContext) -> None:
|
||||
try:
|
||||
message_data = MessageData.create_from_arguments(update, context)
|
||||
except InvalidArgumentException as e:
|
||||
return self.reply_markdown(update, str(e))
|
||||
|
||||
users = self.user_repository.get_all_for_chat(message_data.chat_id)
|
||||
|
||||
if users:
|
||||
self.reply_markdown(update, self.build_mention_message(users))
|
||||
return self.log_action(message_data)
|
||||
|
||||
self.reply_markdown(update, mention_failed)
|
||||
|
||||
def get_bot_handler(self) -> CommandHandler:
|
||||
return self.bot_handler
|
||||
|
||||
def log_action(self, message_data: MessageData) -> None:
|
||||
Logger.info(f'User {message_data.username} called /everyone for {message_data.chat_id}')
|
||||
|
||||
def build_mention_message(self, users: Iterable[User]) -> str:
|
||||
return ' '.join([mention_markdown(user.user_id, user.username) for user in users])
|
||||
|
||||
21
src/bot/handler/silentMentionHandler.py
Normal file
21
src/bot/handler/silentMentionHandler.py
Normal file
@@ -0,0 +1,21 @@
|
||||
from typing import Iterable
|
||||
|
||||
from entity.user import User
|
||||
from logger import Logger
|
||||
from telegram.ext.commandhandler import CommandHandler
|
||||
|
||||
from bot.handler.abstractHandler import AbstractHandler
|
||||
from bot.handler.mentionHandler import MentionHandler
|
||||
from bot.message.messageData import MessageData
|
||||
|
||||
|
||||
class MentionHandler(MentionHandler, AbstractHandler):
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
self.bot_handler = CommandHandler('silent', self.handle)
|
||||
|
||||
def build_mention_message(self, users: Iterable[User]) -> str:
|
||||
return ' '.join([user.username for user in users])
|
||||
|
||||
def log_action(self, message_data: MessageData) -> None:
|
||||
Logger.info(f'User {message_data.username} called /silent for {message_data.chat_id}')
|
||||
25
src/bot/handler/startHandler.py
Normal file
25
src/bot/handler/startHandler.py
Normal file
@@ -0,0 +1,25 @@
|
||||
from config.contents import start_text
|
||||
from logger import Logger
|
||||
from telegram.ext.callbackcontext import CallbackContext
|
||||
from telegram.ext.commandhandler import CommandHandler
|
||||
from telegram.update import Update
|
||||
|
||||
from bot.handler.abstractHandler import AbstractHandler
|
||||
from bot.message.messageData import MessageData
|
||||
|
||||
|
||||
class StartHandler(AbstractHandler):
|
||||
bot_handler: CommandHandler
|
||||
|
||||
def __init__(self) -> None:
|
||||
self.bot_handler = CommandHandler('start', self.handle)
|
||||
|
||||
def handle(self, update: Update, context: CallbackContext) -> None:
|
||||
self.reply_markdown(update, start_text)
|
||||
self.log_action(MessageData.create_from_arguments(update, context))
|
||||
|
||||
def get_bot_handler(self) -> CommandHandler:
|
||||
return self.bot_handler
|
||||
|
||||
def log_action(self, message_data: MessageData) -> None:
|
||||
Logger.info(f'User {message_data.username} called /start for {message_data.chat_id}')
|
||||
45
src/bot/message/messageData.py
Normal file
45
src/bot/message/messageData.py
Normal file
@@ -0,0 +1,45 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import re
|
||||
from dataclasses import dataclass
|
||||
|
||||
import names
|
||||
from entity.group import Group
|
||||
from exception.invalidArgumentException import InvalidArgumentException
|
||||
from telegram.ext.callbackcontext import CallbackContext
|
||||
from telegram.update import Update
|
||||
|
||||
|
||||
@dataclass
|
||||
class MessageData():
|
||||
user_id: str
|
||||
chat_id: str
|
||||
group_name: str
|
||||
username: str
|
||||
|
||||
@staticmethod
|
||||
def create_from_arguments(update: Update, context: CallbackContext, include_group: bool = True) -> MessageData:
|
||||
chat_id = str(update.effective_chat.id)
|
||||
group_name = Group.default_name
|
||||
|
||||
if context.args and context.args[0] and include_group:
|
||||
group_name = str(context.args[0]).lower()
|
||||
if not re.match(r"^[A-Za-z]+$", group_name):
|
||||
raise InvalidArgumentException(re.escape('Group name must contain only letters.'))
|
||||
|
||||
if group_name == Group.default_name:
|
||||
raise InvalidArgumentException(re.escape(f'Group can not be `{Group.default_name}`.'))
|
||||
|
||||
if len(group_name) > 20:
|
||||
raise InvalidArgumentException(re.escape(f'Group name length can not be greater than 20.'))
|
||||
|
||||
chat_id += f'~{group_name}'
|
||||
|
||||
|
||||
user_id = str(update.effective_user.id)
|
||||
username = update.effective_user.username or update.effective_user.first_name
|
||||
|
||||
if not username:
|
||||
username = names.get_first_name()
|
||||
|
||||
return MessageData(user_id, chat_id, group_name, username)
|
||||
Reference in New Issue
Block a user