0.1.0 Version : changed in to join and out to leave, folder structure and naming changes

This commit is contained in:
miloszowi
2021-10-06 19:44:03 +02:00
parent c588fa439e
commit 29c0fd84bb
28 changed files with 207 additions and 209 deletions

View File

@@ -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:

View File

@@ -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:

View File

@@ -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'])

46
src/bot/handler/joinHandler.py Executable file
View 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}')

View File

@@ -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}')

View File

@@ -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

View 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}')

View File

@@ -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}')

View File

@@ -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)

View File

@@ -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 `<group-name>` is not required, if not given, I will assign you to `default` group.
Please take a look at available commands
`<group-name>` is not required, if not given, it is set to `default`
To opt-in for everyone-mentions use:
`/in <group-name>`
for example: `/in gaming`
To join group:
`/join <group-name>`
for example: `/join games`
To opt-off for everyone mentions use:
`/out <group-name>`
To leave group:
`/leave <group-name>`
To gather everyone attention use:
`/everyone <group-name>`
@@ -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 <group-name>`
In case questions regarding my usage please reach out to @miloszowi
""")
"""

View File

@@ -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}')

View File

@@ -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}')

View File

@@ -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,
{