PEP-8 coding standards, used dataclasses for User and UpdateData classes

This commit is contained in:
miloszowi 2021-09-28 17:03:11 +02:00
parent 2b0728b58c
commit bbb1706dbe
9 changed files with 99 additions and 124 deletions

View File

@ -14,15 +14,15 @@ class App:
self.updater = Updater(BOT_TOKEN) self.updater = Updater(BOT_TOKEN)
def run(self) -> None: def run(self) -> None:
self.registerHandlers() self.register_handlers()
self.updater.start_polling() self.updater.start_polling()
self.updater.idle() self.updater.idle()
def registerHandlers(self) -> None: def register_handlers(self) -> None:
for handler in AbstractHandler.__subclasses__(): for handler in AbstractHandler.__subclasses__():
self.updater.dispatcher.add_handler( self.updater.dispatcher.add_handler(
handler().getBotHandler() handler().get_bot_handler()
) )

View File

@ -8,7 +8,7 @@ from pymongo.database import Database
class Client(): class Client():
mongoClient: MongoClient mongo_client: MongoClient
database: Database database: Database
def __init__(self) -> None: def __init__(self) -> None:
@ -17,19 +17,19 @@ class Client():
MONGODB_HOSTNAME, MONGODB_PORT, MONGODB_DATABASE MONGODB_HOSTNAME, MONGODB_PORT, MONGODB_DATABASE
) )
self.mongoClient = MongoClient(uri) self.mongo_client = MongoClient(uri)
self.database = self.mongoClient[MONGODB_DATABASE] self.database = self.mongo_client[MONGODB_DATABASE]
def insertOne(self, collection: str, data: dict) -> None: def insert_one(self, collection: str, data: dict) -> None:
self.database.get_collection(collection).insert_one(data) self.database.get_collection(collection).insert_one(data)
def findOne(self, collection: str, query: dict) -> dict: def find_one(self, collection: str, query: dict) -> dict:
return self.database.get_collection(collection).find_one(query) return self.database.get_collection(collection).find_one(query)
def findMany(self, collection: str, filter: dict) -> dict: def find_many(self, collection: str, filter: dict) -> dict:
return self.database.get_collection(collection).find(filter) return self.database.get_collection(collection).find(filter)
def updateOne(self, collection: str, filter: dict, data: dict) -> None: def update_one(self, collection: str, filter: dict, data: dict) -> None:
self.database.get_collection(collection).update_one( self.database.get_collection(collection).update_one(
filter, filter,
{ "$set" : data } { "$set" : data }

View File

@ -1,52 +1,40 @@
from __future__ import annotations from __future__ import annotations
from dataclasses import dataclass
from typing import Iterable from typing import Iterable
@dataclass
class User(): class User():
collection: str = 'users' user_id: str
idIndex: str = '_id'
chatsIndex: str = 'chats'
usernameIndex: str = 'username'
userId: str
username: str username: str
chats: Iterable[str] chats: Iterable[str]
def __init__(self, userId, username, chats) -> None: collection: str = 'users'
self.userId = userId id_index: str = '_id'
self.username = username chats_index: str = 'chats'
self.chats = chats username_index: str = 'username'
def getUserId(self) -> str: def is_in_chat(self, chat_id: str) -> bool:
return self.userId return chat_id in self.chats
def getUsername(self) -> str:
return self.username
def getChats(self) -> Iterable[str]:
return self.chats
def isInChat(self, chatId: str) -> bool:
return chatId in self.getChats()
def addToChat(self, chatId: str) -> None: def add_to_chat(self, chat_id: str) -> None:
self.chats.append(chatId) self.chats.append(chat_id)
def removeFromChat(self, chatId: str) -> None: def remove_from_chat(self, chat_id: str) -> None:
if chatId in self.getChats(): if chat_id in self.chats:
self.chats.remove(chatId) self.chats.remove(chat_id)
def toMongoDocument(self) -> dict: def to_mongo_document(self) -> dict:
return { return {
self.usernameIndex: self.getUsername(), self.username_index: self.username,
self.chatsIndex: self.getChats() self.chats_index: self.chats
} }
@staticmethod @staticmethod
def fromMongoDocument(mongoDocument: dict) -> User: def from_mongo_document(mongo_document: dict) -> User:
return User( return User(
mongoDocument[User.idIndex], mongo_document[User.id_index],
mongoDocument[User.usernameIndex], mongo_document[User.username_index],
mongoDocument[User.chatsIndex] mongo_document[User.chats_index]
) )

View File

@ -8,17 +8,14 @@ from handler.vo.updateData import UpdateData
class AbstractHandler: class AbstractHandler:
def __init__(self) -> None:
pass
@abstractmethod @abstractmethod
def getBotHandler(self) -> Handler: raise Exception('getBotHandler method is not implemented') def get_bot_handler(self) -> Handler: raise Exception('get_bot_handler method is not implemented')
@abstractmethod @abstractmethod
def handle(self, update: Update, context: CallbackContext) -> None: raise Exception('handle method is not implemented') def handle(self, update: Update, context: CallbackContext) -> None: raise Exception('handle method is not implemented')
def getUpdateData(self, update: Update) -> UpdateData: def get_update_data(self, update: Update) -> UpdateData:
return UpdateData.createFromUpdate(update) return UpdateData.create_from_update(update)
def reply(self, update: Update, message: str) -> None: def reply(self, update: Update, message: str) -> None:
update.effective_message.reply_markdown_v2(text=message) update.effective_message.reply_markdown_v2(text=message)

View File

@ -9,30 +9,30 @@ from handler.abstractHandler import AbstractHandler
class InHandler(AbstractHandler): class InHandler(AbstractHandler):
botHandler: CommandHandler bot_handler: CommandHandler
userRepository: UserRepository user_repository: UserRepository
def __init__(self) -> None: def __init__(self) -> None:
self.botHandler = CommandHandler('in', self.handle) self.bot_handler = CommandHandler('in', self.handle)
self.userRepository = UserRepository() self.user_repository = UserRepository()
def handle(self, update: Update, context: CallbackContext) -> None: def handle(self, update: Update, context: CallbackContext) -> None:
updateData = self.getUpdateData(update) update_data = self.get_update_data(update)
try: try:
user = self.userRepository.getById(updateData.getUserId()) user = self.user_repository.get_by_id(update_data.user_id)
if user.isInChat(updateData.getChatId()): if user.is_in_chat(update_data.chat_id):
self.reply(update, opted_in_failed) self.reply(update, opted_in_failed)
return return
user.addToChat(updateData.getChatId()) user.add_to_chat(update_data.chat_id)
self.userRepository.save(user) self.user_repository.save(user)
except NotFoundException: except NotFoundException:
self.userRepository.saveByUpdateData(updateData) self.user_repository.save_by_update_data(update_data)
self.reply(update, opted_in) self.reply(update, opted_in)
def getBotHandler(self) -> CommandHandler: def get_bot_handler(self) -> CommandHandler:
return self.botHandler return self.bot_handler

View File

@ -11,37 +11,37 @@ from handler.abstractHandler import AbstractHandler
class MentionHandler(AbstractHandler): class MentionHandler(AbstractHandler):
botHandler: CommandHandler bot_handler: CommandHandler
userRepository: UserRepository user_repository: UserRepository
silent: str = 'silent' silent: str = 'silent'
def __init__(self) -> None: def __init__(self) -> None:
self.botHandler = CommandHandler('everyone', self.handle) self.bot_handler = CommandHandler('everyone', self.handle)
self.userRepository = UserRepository() self.user_repository = UserRepository()
def handle(self, update: Update, context: CallbackContext) -> None: def handle(self, update: Update, context: CallbackContext) -> None:
updateData = self.getUpdateData(update) updateData = self.get_update_data(update)
users = self.userRepository.getAllForChat(updateData.getChatId()) users = self.user_repository.get_all_for_chat(updateData.chat_id)
if users: if users:
self.reply(update, self.buildMentionMessage(users, self.isSilent(context))) self.reply(update, self.build_mention_message(users, self.isSilent(context)))
return return
self.reply(update, mention_failed) self.reply(update, mention_failed)
def getBotHandler(self) -> CommandHandler: def get_bot_handler(self) -> CommandHandler:
return self.botHandler return self.bot_handler
def buildMentionMessage(self, users: Iterable[User], silent: bool = False) -> str: def build_mention_message(self, users: Iterable[User], silent: bool = False) -> str:
result = '' result = ''
for user in users: for user in users:
if not silent: if not silent:
result += f'*[{user.getUsername()}](tg://user?id={user.getUserId()})* ' result += f'*[{user.username}](tg://user?id={user.user_id})* '
else: else:
result += f'*{user.getUsername()}\({user.getUserId()}\)*\n' result += f'*{user.username}\({user.user_id}\)*\n'
return result return result
def isSilent(self, context: CallbackContext) -> bool: def isSilent(self, context: CallbackContext) -> bool:
return context.args and context.args[0] == self.silent return self.silent in context.args

View File

@ -9,28 +9,29 @@ from handler.abstractHandler import AbstractHandler
class OutHandler(AbstractHandler): class OutHandler(AbstractHandler):
botHandler: CommandHandler bot_handler: CommandHandler
userRepository: UserRepository user_repository: UserRepository
def __init__(self) -> None: def __init__(self) -> None:
self.botHandler = CommandHandler('out', self.handle) self.bot_handler = CommandHandler('out', self.handle)
self.userRepository = UserRepository() self.user_repository = UserRepository()
def handle(self, update: Update, context: CallbackContext) -> None: def handle(self, update: Update, context: CallbackContext) -> None:
updateData = self.getUpdateData(update) updateData = self.get_update_data(update)
try: try:
user = self.userRepository.getById(updateData.getUserId()) user = self.user_repository.get_by_id(updateData.user_id)
if not user.isInChat(updateData.getChatId()):
if not user.is_in_chat(updateData.chat_id):
raise NotFoundException() raise NotFoundException()
except NotFoundException: except NotFoundException:
self.reply(update, opted_off_failed) self.reply(update, opted_off_failed)
return return
user.removeFromChat(updateData.getChatId()) user.remove_from_chat(updateData.chat_id)
self.userRepository.save(user) self.user_repository.save(user)
self.reply(update, opted_off) self.reply(update, opted_off)
def getBotHandler(self) -> CommandHandler: def get_bot_handler(self) -> CommandHandler:
return self.botHandler return self.bot_handler

View File

@ -1,35 +1,24 @@
from __future__ import annotations from __future__ import annotations
from dataclasses import dataclass
import names import names
from telegram.update import Update from telegram.update import Update
@dataclass
class UpdateData(): class UpdateData():
userId: str user_id: str
chatId: str chat_id: str
username: str username: str
def __init__(self, userId: str, chatId: str, username: str) -> None:
self.userId = userId
self.chatId = chatId
self.username = username
def getUserId(self) -> str:
return self.userId
def getChatId(self) -> str:
return self.chatId
def getUsername(self) -> str:
return self.username
@staticmethod @staticmethod
def createFromUpdate(update: Update) -> UpdateData: def create_from_update(update: Update) -> UpdateData:
userId = str(update.effective_user.id) user_id = str(update.effective_user.id)
chatId = str(update.effective_chat.id) chat_id = str(update.effective_chat.id)
username = update.effective_user.username or update.effective_user.first_name username = update.effective_user.username or update.effective_user.first_name
if not username: if not username:
username = names.get_first_name() username = names.get_first_name()
return UpdateData(userId, chatId, username) return UpdateData(user_id, chat_id, username)

View File

@ -12,11 +12,11 @@ class UserRepository():
def __init__(self) -> None: def __init__(self) -> None:
self.client = Client() self.client = Client()
def getById(self, id: str) -> User: def get_by_id(self, id: str) -> User:
user = self.client.findOne( user = self.client.find_one(
User.collection, User.collection,
{ {
User.idIndex: id User.id_index: id
} }
) )
@ -24,41 +24,41 @@ class UserRepository():
raise NotFoundException(f'Could not find user with "{id}" id') raise NotFoundException(f'Could not find user with "{id}" id')
return User( return User(
user[User.idIndex], user[User.id_index],
user[User.usernameIndex], user[User.username_index],
user[User.chatsIndex] user[User.chats_index]
) )
def save(self, user: User) -> None: def save(self, user: User) -> None:
self.client.updateOne( self.client.update_one(
User.collection, User.collection,
{ User.idIndex: user.getUserId() }, { User.id_index: user.user_id },
user.toMongoDocument() user.to_mongo_document()
) )
def saveByUpdateData(self, data: UpdateData) -> None: def save_by_update_data(self, data: UpdateData) -> None:
self.client.insertOne( self.client.insert_one(
User.collection, User.collection,
{ {
User.idIndex: data.getUserId(), User.id_index: data.user_id,
User.usernameIndex: data.getUsername(), User.username_index: data.username,
User.chatsIndex: [data.getChatId()] User.chats_index: [data.chat_id]
} }
) )
def getAllForChat(self, chatId: str) -> Iterable[User]: def get_all_for_chat(self, chat_id: str) -> Iterable[User]:
result = [] result = []
users = self.client.findMany( users = self.client.find_many(
User.collection, User.collection,
{ {
User.chatsIndex: { User.chats_index: {
"$in" : [chatId] "$in" : [chat_id]
} }
} }
) )
for record in users: for record in users:
result.append(User.fromMongoDocument(record)) result.append(User.from_mongo_document(record))
return result return result