diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..c14ce3a --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,13 @@ +# Change Log +All notable changes to this project will be documented in this file. + +## [0.1.0] - 06.10.2021 +### Features +- `/join` command +- `/leave` command +- `/groups` command +- `/everyone` command +- `/start` command +- `/silent` command +- possibility to have multiple contexts for one chat +- docker setup & docker commands \ No newline at end of file diff --git a/README.md b/README.md index c5c90a8..d99b678 100755 --- a/README.md +++ b/README.md @@ -1,121 +1,117 @@ #

[everyone-mention-telegram-bot](http://t.me/everyone_mention_bot)

-

simple, but useful telegram bot to gather all of group members attention! # Contents +* [Description](#description) * [Getting started.](#getting-started) * [Requirements](#requirements) * [Installation](#installation) * [Logs](#logs) * [Env files](#env-files) * [Commands](#commands) - * [`/in`](#in) - * [`/out`](#out) + * [`/join`](#join) + * [`/leave`](#leave) * [`/everyone`](#everyone) * [`/groups`](#groups) * [`/silent`](#silent) + * [`/start`](#start) +## Description +Everyone Mention Bot is simple, but useful telegram bot to gather group members attention. + +You can create groups per chat to mention every user that joined the group by calling one command instead of mentioning them one by one. ## Getting started - ### Requirements - `docker-compose` in version `1.25.0` - `docker` in version `20.10.7` ### Installation +- copy the repository ```bash git clone https://github.com/miloszowi/everyone-mention-telegram-bot.git ``` -after that, you need to copy env files and fulfill it with correct values +- copy environment files and fulfill empty values ```bash cp .env.local .env cp docker/config/app.dist.env docker/config/app.env cp docker/config/database.dist.env docker/config/app.env ``` -and finally, you can run the bot by launching docker containers +- start the project (`-d` flag will run containers in detached mode) ```bash docker-compose up -d ``` -(`-d` flag will run containers in detached mode) ### Logs -You can use ```bash docker/logs ``` -to check container logs ### Env files -`.env` -- `MONGODB_INTERNAL_PORT` - Mongodb internal port (should be the same as declared in `app.env`) -- `APP_INTERNAL_PORT` - App internal port (should be the same as declared in `app.env`) -- `APP_EXPOSED_PORT` - App exposed port (if you are not using any reverse proxy it should be also the same as declared in `app.env`) +- `.env` + - `MONGODB_INTERNAL_PORT` - Mongodb internal port (should be the same as declared in `app.env`) + - `APP_INTERNAL_PORT` - App internal port (should be the same as declared in `app.env`) + - `APP_EXPOSED_PORT` - App exposed port (if you are not using any reverse proxy it should be also the same as declared in `app.env`) -`app.env` -- `BOT_TOKEN` - your telegram bot token from [BotFather](https://telegram.me/BotFather) -- `WEBHOOK_URL` - url for telegram webhooks (withour the bot token) -- `PORT` - port used for initializing webhook & app -- `MONGODB_DATABASE` - MongoDB database name -- `MONGODB_USERNAME` - MongoDB username -- `MONGODB_PASSWORD` - MongoDB password -- `MONGODB_HOSTNAME` - MongoDB host (default `database` - container name) -- `MONGODB_PORT` - MongoDB port (default `27017` - given in docker-compose configuration) +- `app.env` + - `BOT_TOKEN` - your telegram bot token from [BotFather](https://telegram.me/BotFather) + - `WEBHOOK_URL` - url for telegram webhooks (withour the bot token) + - `PORT` - port used for initializing webhook & app + - `MONGODB_DATABASE` - MongoDB database name + - `MONGODB_USERNAME` - MongoDB username + - `MONGODB_PASSWORD` - MongoDB password + - `MONGODB_HOSTNAME` - MongoDB host (default `database` - container name) + - `MONGODB_PORT` - MongoDB port (default `27017` - given in docker-compose configuration) -`database.env` -- `MONGO_INITDB_ROOT_USERNAME` - conf from `app.env` -- `MONGO_INITDB_ROOT_PASSWORD` - conf from `app.env` -- `MONGO_INITDB_DATABASE` - conf from `app.env` -- `MONGODB_DATA_DIR` - directory to store MongoDB documents (inside a container) -- `MONDODB_LOG_DIR` - path to logs storage +- `database.env` + - `MONGO_INITDB_ROOT_USERNAME` - conf from `app.env` + - `MONGO_INITDB_ROOT_PASSWORD` - conf from `app.env` + - `MONGO_INITDB_DATABASE` - conf from `app.env` + - `MONGODB_DATA_DIR` - directory to store MongoDB documents (inside a container) + - `MONDODB_LOG_DIR` - path to logs storage ## Commands -### `/in` +### `/join` ``` -/in +/join ``` -(blank `group_name` will assign you to `default` group) +Joins the group (and create if it did not exist before) given in message (`default` if not given) -Will sign you in for everyone-mentions. +![join command example](docs/join.png) -![in command example](docs/in_command.png) - -If you have already opted-in before, alternative reply will be displayed. - -![in command when someone already opted in example](docs/in_command_already_opted_in.png) - -### `/out` +### `/leave` ``` -/out +/leave ``` -Will sign you off for everyone-mentions. +Leaves the group given in message (`default` if not given) -![out command example](docs/out_command.png) - -If you haven't opted-in before, alternative reply will be displayed. - -![out command when someone did not opt in example](docs/out_command_did_not_opt_in_before.png) +![leave command example](docs/leave.png) ### `/everyone` ``` /everyone ``` -Will mention everyone that opted-in for everyone-mentions separated by spaces. +Will mention every member of given group (`default` if not given). If user does not have nickname, it will first try to assign his firstname, then random firstname from `names` python library -![everybody command example](docs/everyone_command.png) - -If there are no users that opted-in for mentioning, alternative reply will be displayed. - -![everybone noone to mention example](docs/everyone_noone_to_mention.png) - +![everyone command example](docs/everyone.png) ### `/groups` -Will display available groups for this chat as well with members count that opted-in for specific group +Will display available groups for this chat as well with members count. + +![groups command example](docs/groups.png) ### `/silent` ``` /silent ``` -Will display all users that opted-in but without notyfing them. +Will display all every member of given group (`default` if not given) but without notyfing them. + +![silent command example](docs/silent.png) + +### `/start` +Start & Help message + +![start command example](docs/start.png) diff --git a/docs/commands.png b/docs/commands.png deleted file mode 100755 index 24caf9d..0000000 Binary files a/docs/commands.png and /dev/null differ diff --git a/docs/everyone.png b/docs/everyone.png new file mode 100644 index 0000000..63b2550 Binary files /dev/null and b/docs/everyone.png differ diff --git a/docs/everyone_command.png b/docs/everyone_command.png deleted file mode 100755 index 37c75c9..0000000 Binary files a/docs/everyone_command.png and /dev/null differ diff --git a/docs/everyone_noone_to_mention.png b/docs/everyone_noone_to_mention.png deleted file mode 100755 index 88200a1..0000000 Binary files a/docs/everyone_noone_to_mention.png and /dev/null differ diff --git a/docs/groups.png b/docs/groups.png new file mode 100644 index 0000000..c4e1ead Binary files /dev/null and b/docs/groups.png differ diff --git a/docs/in_command.png b/docs/in_command.png deleted file mode 100755 index fc08bcf..0000000 Binary files a/docs/in_command.png and /dev/null differ diff --git a/docs/in_command_already_opted_in.png b/docs/in_command_already_opted_in.png deleted file mode 100755 index 4370a08..0000000 Binary files a/docs/in_command_already_opted_in.png and /dev/null differ diff --git a/docs/join.png b/docs/join.png new file mode 100644 index 0000000..85749ec Binary files /dev/null and b/docs/join.png differ diff --git a/docs/leave.png b/docs/leave.png new file mode 100644 index 0000000..2d60996 Binary files /dev/null and b/docs/leave.png differ diff --git a/docs/out_command.png b/docs/out_command.png deleted file mode 100755 index 062b913..0000000 Binary files a/docs/out_command.png and /dev/null differ diff --git a/docs/out_command_did_not_opt_in_before.png b/docs/out_command_did_not_opt_in_before.png deleted file mode 100755 index f7a7732..0000000 Binary files a/docs/out_command_did_not_opt_in_before.png and /dev/null differ diff --git a/docs/silent.png b/docs/silent.png new file mode 100644 index 0000000..1db4c9b Binary files /dev/null and b/docs/silent.png differ diff --git a/docs/start.png b/docs/start.png new file mode 100644 index 0000000..0e48122 Binary files /dev/null and b/docs/start.png differ diff --git a/src/app.py b/src/app.py index f31204e..b70a888 100755 --- a/src/app.py +++ b/src/app.py @@ -5,9 +5,9 @@ from telegram.ext.dispatcher import Dispatcher from logger import Logger from config.credentials import BOT_TOKEN, PORT, WEBHOOK_URL -from handler import (groupsHandler, inHandler, mentionHandler, outHandler, +from bot.handler import (groupsHandler, joinHandler, mentionHandler, leaveHandler, silentMentionHandler, startHandler) -from handler.abstractHandler import AbstractHandler +from bot.handler.abstractHandler import AbstractHandler class App: diff --git a/src/handler/abstractHandler.py b/src/bot/handler/abstractHandler.py similarity index 67% rename from src/handler/abstractHandler.py rename to src/bot/handler/abstractHandler.py index c0cddab..553f4d8 100755 --- a/src/handler/abstractHandler.py +++ b/src/bot/handler/abstractHandler.py @@ -1,11 +1,11 @@ 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 handler.vo.updateData import UpdateData +from telegram.utils.helpers import mention_markdown class AbstractHandler: @@ -16,10 +16,13 @@ class AbstractHandler: def handle(self, update: Update, context: CallbackContext) -> None: raise Exception('handle method is not implemented') @abstractmethod - def log_action(self, update_data: UpdateData) -> None: raise Exception('log_action method is not implemented') + def log_action(self, message_data: MessageData) -> None: raise Exception('log_action method is not implemented') - def get_update_data(self, update: Update, context: CallbackContext) -> UpdateData: - return UpdateData.create_from_arguments(update, context) + 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: diff --git a/src/handler/groupsHandler.py b/src/bot/handler/groupsHandler.py similarity index 71% rename from src/handler/groupsHandler.py rename to src/bot/handler/groupsHandler.py index 8e679fe..0270404 100644 --- a/src/handler/groupsHandler.py +++ b/src/bot/handler/groupsHandler.py @@ -1,17 +1,16 @@ 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 handler.vo.updateData import UpdateData 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 -from handler.abstractHandler import AbstractHandler - class GroupsHandler(AbstractHandler): bot_handler: CommandHandler @@ -22,21 +21,21 @@ class GroupsHandler(AbstractHandler): self.group_repository = GroupRepository() def handle(self, update: Update, context: CallbackContext) -> None: - update_data = UpdateData.create_from_arguments(update, context, False) + message_data = MessageData.create_from_arguments(update, context, False) - groups = self.group_repository.get_by_chat_id(update_data.chat_id) + 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(update_data) + 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, update_data: UpdateData) -> None: - Logger.info(f'User {update_data.username} called /groups for {update_data.chat_id}') + 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']) diff --git a/src/bot/handler/joinHandler.py b/src/bot/handler/joinHandler.py new file mode 100755 index 0000000..5262a16 --- /dev/null +++ b/src/bot/handler/joinHandler.py @@ -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}') diff --git a/src/handler/outHandler.py b/src/bot/handler/leaveHandler.py similarity index 51% rename from src/handler/outHandler.py rename to src/bot/handler/leaveHandler.py index 736e38a..73b7588 100755 --- a/src/handler/outHandler.py +++ b/src/bot/handler/leaveHandler.py @@ -1,46 +1,45 @@ -from config.contents import opted_off, opted_off_failed +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 handler.vo.updateData import UpdateData 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 -from handler.abstractHandler import AbstractHandler - -class OutHandler(AbstractHandler): +class LeaveHandler(AbstractHandler): bot_handler: CommandHandler user_repository: UserRepository def __init__(self) -> None: - self.bot_handler = CommandHandler('out', self.handle) + self.bot_handler = CommandHandler('leave', self.handle) self.user_repository = UserRepository() def handle(self, update: Update, context: CallbackContext) -> None: try: - update_data = self.get_update_data(update, context) + 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(update_data.user_id) + user = self.user_repository.get_by_id(message_data.user_id) - if not user.is_in_chat(update_data.chat_id): + if not user.is_in_chat(message_data.chat_id): raise NotFoundException() except NotFoundException: - return self.reply_markdown(update, opted_off_failed) + return self.reply_markdown(update, self.interpolate_reply(not_left, message_data)) - user.remove_from_chat(update_data.chat_id) + user.remove_from_chat(message_data.chat_id) self.user_repository.save(user) - self.reply_markdown(update, opted_off) - self.log_action(update_data) + 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, update_data: UpdateData) -> None: - Logger.info(f'User {update_data.username} left {update_data.chat_id}') + def log_action(self, message_data: MessageData) -> None: + Logger.info(f'User {message_data.username} left {message_data.chat_id}') diff --git a/src/handler/mentionHandler.py b/src/bot/handler/mentionHandler.py similarity index 65% rename from src/handler/mentionHandler.py rename to src/bot/handler/mentionHandler.py index e6687de..d44e8cb 100755 --- a/src/handler/mentionHandler.py +++ b/src/bot/handler/mentionHandler.py @@ -1,17 +1,18 @@ 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 handler.vo.updateData import UpdateData 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 -from handler.abstractHandler import AbstractHandler - class MentionHandler(AbstractHandler): bot_handler: CommandHandler @@ -23,28 +24,24 @@ class MentionHandler(AbstractHandler): def handle(self, update: Update, context: CallbackContext) -> None: try: - update_data = self.get_update_data(update, context) + 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(update_data.chat_id) + 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(update_data) + 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, update_data: UpdateData) -> None: - Logger.info(f'User {update_data.username} called /everyone for {update_data.chat_id}') + 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: - result = '' + return ' '.join([mention_markdown(user.user_id, user.username) for user in users]) - for user in users: - result += f'*[{user.username}](tg://user?id={user.user_id})* ' - - return result diff --git a/src/bot/handler/silentMentionHandler.py b/src/bot/handler/silentMentionHandler.py new file mode 100644 index 0000000..c1a0248 --- /dev/null +++ b/src/bot/handler/silentMentionHandler.py @@ -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}') diff --git a/src/handler/startHandler.py b/src/bot/handler/startHandler.py similarity index 63% rename from src/handler/startHandler.py rename to src/bot/handler/startHandler.py index ee32f7a..8454d08 100644 --- a/src/handler/startHandler.py +++ b/src/bot/handler/startHandler.py @@ -4,8 +4,8 @@ from telegram.ext.callbackcontext import CallbackContext from telegram.ext.commandhandler import CommandHandler from telegram.update import Update -from handler.abstractHandler import AbstractHandler -from handler.vo.updateData import UpdateData +from bot.handler.abstractHandler import AbstractHandler +from bot.message.messageData import MessageData class StartHandler(AbstractHandler): @@ -16,10 +16,10 @@ class StartHandler(AbstractHandler): def handle(self, update: Update, context: CallbackContext) -> None: self.reply_markdown(update, start_text) - self.log_action(UpdateData.create_from_arguments(update, context)) + self.log_action(MessageData.create_from_arguments(update, context)) def get_bot_handler(self) -> CommandHandler: return self.bot_handler - def log_action(self, update_data: UpdateData) -> None: - Logger.info(f'User {update_data.username} called /start for {update_data.chat_id}') + def log_action(self, message_data: MessageData) -> None: + Logger.info(f'User {message_data.username} called /start for {message_data.chat_id}') diff --git a/src/handler/vo/updateData.py b/src/bot/message/messageData.py similarity index 86% rename from src/handler/vo/updateData.py rename to src/bot/message/messageData.py index a43f433..49ab6ff 100644 --- a/src/handler/vo/updateData.py +++ b/src/bot/message/messageData.py @@ -1,26 +1,27 @@ from __future__ import annotations -from dataclasses import dataclass 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 -from entity.group import Group - -from exception.invalidArgumentException import InvalidArgumentException @dataclass -class UpdateData(): +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) -> UpdateData: + 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): @@ -41,4 +42,4 @@ class UpdateData(): if not username: username = names.get_first_name() - return UpdateData(user_id, chat_id, username) + return MessageData(user_id, chat_id, group_name, username) diff --git a/src/config/contents.py b/src/config/contents.py index a898669..6ad7118 100755 --- a/src/config/contents.py +++ b/src/config/contents.py @@ -1,28 +1,25 @@ -import re - -# These are MarkdownV2 python-telegram-bot specific -opted_in = re.escape('You have opted-in for everyone-mentions.') -opted_in_failed = re.escape('You already opted-in for everyone-mentions.') -opted_off = re.escape('You have opted-off for everyone-mentions.') -opted_off_failed = re.escape('You need to opt-in first before processing this command.') -mention_failed = re.escape('There are no users to mention.') -no_groups = re.escape('There are no groups for this chat.') +joined = '{} joined group `{}`' +not_joined = '{} is already in group `{}`' +left = '{} left group `{}`' +not_left = '{} did not join group `{}` before' +mention_failed = 'There are no users to mention' +no_groups = 'There are no groups for this chat' -start_text = re.escape(""" -Hello there. -I am `@everyone_mention_bot`. -I am here to help you with mass notifies. +start_text = """ +Hello there +I am @everyone\_mention\_bot +I am here to help you with mass notifies -Please take a look at available commands. -Parameter `` is not required, if not given, I will assign you to `default` group. +Please take a look at available commands +`` is not required, if not given, it is set to `default` -To opt-in for everyone-mentions use: -`/in ` -for example: `/in gaming` +To join group: +`/join ` +for example: `/join games` -To opt-off for everyone mentions use: -`/out ` +To leave group: +`/leave ` To gather everyone attention use: `/everyone ` @@ -30,8 +27,6 @@ To gather everyone attention use: To see all available groups use: `/groups` -To display all users that opted-in for everyone-mentions use: +To display all members in a group: `/silent ` - -In case questions regarding my usage please reach out to @miloszowi -""") \ No newline at end of file +""" \ No newline at end of file diff --git a/src/handler/inHandler.py b/src/handler/inHandler.py deleted file mode 100755 index b2745e5..0000000 --- a/src/handler/inHandler.py +++ /dev/null @@ -1,46 +0,0 @@ -from handler.vo.updateData import UpdateData -from logger import Logger -from config.contents import opted_in, opted_in_failed -from exception.invalidArgumentException import InvalidArgumentException -from exception.notFoundException import NotFoundException -from repository.userRepository import UserRepository -from telegram.ext.callbackcontext import CallbackContext -from telegram.ext.commandhandler import CommandHandler -from telegram.update import Update - -from handler.abstractHandler import AbstractHandler - - -class InHandler(AbstractHandler): - bot_handler: CommandHandler - user_repository: UserRepository - - def __init__(self) -> None: - self.bot_handler = CommandHandler('in', self.handle) - self.user_repository = UserRepository() - - def handle(self, update: Update, context: CallbackContext) -> None: - try: - update_data = self.get_update_data(update, context) - except InvalidArgumentException as e: - return self.reply_markdown(update, str(e)) - - try: - user = self.user_repository.get_by_id(update_data.user_id) - - if user.is_in_chat(update_data.chat_id): - return self.reply_markdown(update, opted_in_failed) - - user.add_to_chat(update_data.chat_id) - self.user_repository.save(user) - except NotFoundException: - self.user_repository.save_by_update_data(update_data) - - self.reply_markdown(update, opted_in) - self.log_action(update_data) - - def get_bot_handler(self) -> CommandHandler: - return self.bot_handler - - def log_action(self, update_data: UpdateData) -> None: - Logger.info(f'User {update_data.username} joined {update_data.chat_id}') diff --git a/src/handler/silentMentionHandler.py b/src/handler/silentMentionHandler.py deleted file mode 100644 index 19be822..0000000 --- a/src/handler/silentMentionHandler.py +++ /dev/null @@ -1,26 +0,0 @@ -from typing import Iterable - -from entity.user import User -from logger import Logger -from telegram.ext.commandhandler import CommandHandler - -from handler.abstractHandler import AbstractHandler -from handler.mentionHandler import MentionHandler -from handler.vo.updateData import UpdateData - - -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: - result = '' - - for user in users: - result += f'*{user.username}\({user.user_id}\)*\n' - - return result - - def log_action(self, update_data: UpdateData) -> None: - Logger.info(f'User {update_data.username} called /silent for {update_data.chat_id}') diff --git a/src/repository/userRepository.py b/src/repository/userRepository.py index 5b485a7..d4371f6 100644 --- a/src/repository/userRepository.py +++ b/src/repository/userRepository.py @@ -1,9 +1,9 @@ from typing import Iterable, Optional +from bot.message.messageData import MessageData from database.client import Client from entity.user import User from exception.notFoundException import NotFoundException -from handler.vo.updateData import UpdateData class UserRepository(): @@ -36,7 +36,7 @@ class UserRepository(): user.to_mongo_document() ) - def save_by_update_data(self, data: UpdateData) -> None: + def save_by_message_data(self, data: MessageData) -> None: self.client.insert_one( User.collection, {