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

13
CHANGELOG.md Normal file
View File

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

106
README.md
View File

@ -1,121 +1,117 @@
# <p align="center"> [everyone-mention-telegram-bot](http://t.me/everyone_mention_bot) # <p align="center"> [everyone-mention-telegram-bot](http://t.me/everyone_mention_bot)
<p align="center"> <img src="docs/logo.png" width="150"/> <p align="center"> <img src="docs/logo.png" width="150"/>
<p align="center"> simple, but useful telegram bot to gather all of group members attention!
<!-- Icon made by https://www.freepik.com from https://www.flaticon.com/ --> <!-- Icon made by https://www.freepik.com from https://www.flaticon.com/ -->
# Contents # Contents
* [Description](#description)
* [Getting started.](#getting-started) * [Getting started.](#getting-started)
* [Requirements](#requirements) * [Requirements](#requirements)
* [Installation](#installation) * [Installation](#installation)
* [Logs](#logs) * [Logs](#logs)
* [Env files](#env-files) * [Env files](#env-files)
* [Commands](#commands) * [Commands](#commands)
* [`/in`](#in) * [`/join`](#join)
* [`/out`](#out) * [`/leave`](#leave)
* [`/everyone`](#everyone) * [`/everyone`](#everyone)
* [`/groups`](#groups) * [`/groups`](#groups)
* [`/silent`](#silent) * [`/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 ## Getting started
### Requirements ### Requirements
- `docker-compose` in version `1.25.0` - `docker-compose` in version `1.25.0`
- `docker` in version `20.10.7` - `docker` in version `20.10.7`
### Installation ### Installation
- copy the repository
```bash ```bash
git clone https://github.com/miloszowi/everyone-mention-telegram-bot.git 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 ```bash
cp .env.local .env cp .env.local .env
cp docker/config/app.dist.env docker/config/app.env cp docker/config/app.dist.env docker/config/app.env
cp docker/config/database.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 ```bash
docker-compose up -d docker-compose up -d
``` ```
(`-d` flag will run containers in detached mode)
### Logs ### Logs
You can use
```bash ```bash
docker/logs <container> docker/logs <container>
``` ```
to check container logs
### Env files ### Env files
`.env` - `.env`
- `MONGODB_INTERNAL_PORT` - Mongodb internal port (should be the same as declared in `app.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_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_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` - `app.env`
- `BOT_TOKEN` - your telegram bot token from [BotFather](https://telegram.me/BotFather) - `BOT_TOKEN` - your telegram bot token from [BotFather](https://telegram.me/BotFather)
- `WEBHOOK_URL` - url for telegram webhooks (withour the bot token) - `WEBHOOK_URL` - url for telegram webhooks (withour the bot token)
- `PORT` - port used for initializing webhook & app - `PORT` - port used for initializing webhook & app
- `MONGODB_DATABASE` - MongoDB database name - `MONGODB_DATABASE` - MongoDB database name
- `MONGODB_USERNAME` - MongoDB username - `MONGODB_USERNAME` - MongoDB username
- `MONGODB_PASSWORD` - MongoDB password - `MONGODB_PASSWORD` - MongoDB password
- `MONGODB_HOSTNAME` - MongoDB host (default `database` - container name) - `MONGODB_HOSTNAME` - MongoDB host (default `database` - container name)
- `MONGODB_PORT` - MongoDB port (default `27017` - given in docker-compose configuration) - `MONGODB_PORT` - MongoDB port (default `27017` - given in docker-compose configuration)
`database.env` - `database.env`
- `MONGO_INITDB_ROOT_USERNAME` - conf from `app.env` - `MONGO_INITDB_ROOT_USERNAME` - conf from `app.env`
- `MONGO_INITDB_ROOT_PASSWORD` - conf from `app.env` - `MONGO_INITDB_ROOT_PASSWORD` - conf from `app.env`
- `MONGO_INITDB_DATABASE` - conf from `app.env` - `MONGO_INITDB_DATABASE` - conf from `app.env`
- `MONGODB_DATA_DIR` - directory to store MongoDB documents (inside a container) - `MONGODB_DATA_DIR` - directory to store MongoDB documents (inside a container)
- `MONDODB_LOG_DIR` - path to logs storage - `MONDODB_LOG_DIR` - path to logs storage
## Commands ## Commands
### `/in` ### `/join`
``` ```
/in <group_name> /join <group_name>
``` ```
(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) ### `/leave`
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`
``` ```
/out <group_name> /leave <group_name>
``` ```
Will sign you off for everyone-mentions. Leaves the group given in message (`default` if not given)
![out command example](docs/out_command.png) ![leave command example](docs/leave.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)
### `/everyone` ### `/everyone`
``` ```
/everyone <group_id> /everyone <group_id>
``` ```
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 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) ![everyone command example](docs/everyone.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)
### `/groups` ### `/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`
``` ```
/silent <group_name> /silent <group_name>
``` ```
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)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

BIN
docs/everyone.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.7 KiB

BIN
docs/groups.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.3 KiB

BIN
docs/join.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

BIN
docs/leave.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.7 KiB

BIN
docs/silent.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

BIN
docs/start.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

View File

@ -5,9 +5,9 @@ from telegram.ext.dispatcher import Dispatcher
from logger import Logger from logger import Logger
from config.credentials import BOT_TOKEN, PORT, WEBHOOK_URL 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) silentMentionHandler, startHandler)
from handler.abstractHandler import AbstractHandler from bot.handler.abstractHandler import AbstractHandler
class App: class App:

View File

@ -1,11 +1,11 @@
from abc import abstractmethod from abc import abstractmethod
from bot.message.messageData import MessageData
from logger import Logger from logger import Logger
from telegram.ext.callbackcontext import CallbackContext from telegram.ext.callbackcontext import CallbackContext
from telegram.ext.handler import Handler from telegram.ext.handler import Handler
from telegram.update import Update from telegram.update import Update
from telegram.utils.helpers import mention_markdown
from handler.vo.updateData import UpdateData
class AbstractHandler: class AbstractHandler:
@ -16,10 +16,13 @@ class AbstractHandler:
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')
@abstractmethod @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: def interpolate_reply(self, reply: str, message_data: MessageData):
return UpdateData.create_from_arguments(update, context) 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: def reply_markdown(self, update: Update, message: str) -> None:
try: try:

View File

@ -1,17 +1,16 @@
from typing import Iterable from typing import Iterable
import prettytable as pt import prettytable as pt
from bot.handler.abstractHandler import AbstractHandler
from bot.message.messageData import MessageData
from config.contents import no_groups from config.contents import no_groups
from entity.group import Group from entity.group import Group
from handler.vo.updateData import UpdateData
from logger import Logger from logger import Logger
from repository.groupRepository import GroupRepository from repository.groupRepository import GroupRepository
from telegram.ext.callbackcontext import CallbackContext from telegram.ext.callbackcontext import CallbackContext
from telegram.ext.commandhandler import CommandHandler from telegram.ext.commandhandler import CommandHandler
from telegram.update import Update from telegram.update import Update
from handler.abstractHandler import AbstractHandler
class GroupsHandler(AbstractHandler): class GroupsHandler(AbstractHandler):
bot_handler: CommandHandler bot_handler: CommandHandler
@ -22,21 +21,21 @@ class GroupsHandler(AbstractHandler):
self.group_repository = GroupRepository() self.group_repository = GroupRepository()
def handle(self, update: Update, context: CallbackContext) -> None: 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: if groups:
self.reply_html(update, self.build_groups_message(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) self.reply_markdown(update, no_groups)
def get_bot_handler(self) -> CommandHandler: def get_bot_handler(self) -> CommandHandler:
return self.bot_handler return self.bot_handler
def log_action(self, update_data: UpdateData) -> None: def log_action(self, message_data: MessageData) -> None:
Logger.info(f'User {update_data.username} called /groups for {update_data.chat_id}') Logger.info(f'User {message_data.username} called /groups for {message_data.chat_id}')
def build_groups_message(self, groups: Iterable[Group]) -> str: def build_groups_message(self, groups: Iterable[Group]) -> str:
resultTable = pt.PrettyTable(['Name', 'Members']) 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.invalidArgumentException import InvalidArgumentException
from exception.notFoundException import NotFoundException from exception.notFoundException import NotFoundException
from handler.vo.updateData import UpdateData
from logger import Logger from logger import Logger
from repository.userRepository import UserRepository from repository.userRepository import UserRepository
from telegram.ext.callbackcontext import CallbackContext from telegram.ext.callbackcontext import CallbackContext
from telegram.ext.commandhandler import CommandHandler from telegram.ext.commandhandler import CommandHandler
from telegram.update import Update from telegram.update import Update
from handler.abstractHandler import AbstractHandler
class LeaveHandler(AbstractHandler):
class OutHandler(AbstractHandler):
bot_handler: CommandHandler bot_handler: CommandHandler
user_repository: UserRepository user_repository: UserRepository
def __init__(self) -> None: def __init__(self) -> None:
self.bot_handler = CommandHandler('out', self.handle) self.bot_handler = CommandHandler('leave', self.handle)
self.user_repository = UserRepository() self.user_repository = UserRepository()
def handle(self, update: Update, context: CallbackContext) -> None: def handle(self, update: Update, context: CallbackContext) -> None:
try: try:
update_data = self.get_update_data(update, context) message_data = MessageData.create_from_arguments(update, context)
except InvalidArgumentException as e: except InvalidArgumentException as e:
return self.reply_markdown(update, str(e)) return self.reply_markdown(update, str(e))
try: 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() raise NotFoundException()
except 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.user_repository.save(user)
self.reply_markdown(update, opted_off) self.reply_markdown(update, self.interpolate_reply(left, message_data))
self.log_action(update_data) self.log_action(message_data)
def get_bot_handler(self) -> CommandHandler: def get_bot_handler(self) -> CommandHandler:
return self.bot_handler return self.bot_handler
def log_action(self, update_data: UpdateData) -> None: def log_action(self, message_data: MessageData) -> None:
Logger.info(f'User {update_data.username} left {update_data.chat_id}') Logger.info(f'User {message_data.username} left {message_data.chat_id}')

View File

@ -1,17 +1,18 @@
from typing import Iterable 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 config.contents import mention_failed
from entity.user import User from entity.user import User
from exception.invalidArgumentException import InvalidArgumentException from exception.invalidArgumentException import InvalidArgumentException
from handler.vo.updateData import UpdateData
from logger import Logger from logger import Logger
from repository.userRepository import UserRepository from repository.userRepository import UserRepository
from telegram.ext.callbackcontext import CallbackContext from telegram.ext.callbackcontext import CallbackContext
from telegram.ext.commandhandler import CommandHandler from telegram.ext.commandhandler import CommandHandler
from telegram.update import Update from telegram.update import Update
from handler.abstractHandler import AbstractHandler
class MentionHandler(AbstractHandler): class MentionHandler(AbstractHandler):
bot_handler: CommandHandler bot_handler: CommandHandler
@ -23,28 +24,24 @@ class MentionHandler(AbstractHandler):
def handle(self, update: Update, context: CallbackContext) -> None: def handle(self, update: Update, context: CallbackContext) -> None:
try: try:
update_data = self.get_update_data(update, context) message_data = MessageData.create_from_arguments(update, context)
except InvalidArgumentException as e: except InvalidArgumentException as e:
return self.reply_markdown(update, str(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: if users:
self.reply_markdown(update, self.build_mention_message(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) self.reply_markdown(update, mention_failed)
def get_bot_handler(self) -> CommandHandler: def get_bot_handler(self) -> CommandHandler:
return self.bot_handler return self.bot_handler
def log_action(self, update_data: UpdateData) -> None: def log_action(self, message_data: MessageData) -> None:
Logger.info(f'User {update_data.username} called /everyone for {update_data.chat_id}') Logger.info(f'User {message_data.username} called /everyone for {message_data.chat_id}')
def build_mention_message(self, users: Iterable[User]) -> str: 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.ext.commandhandler import CommandHandler
from telegram.update import Update from telegram.update import Update
from handler.abstractHandler import AbstractHandler from bot.handler.abstractHandler import AbstractHandler
from handler.vo.updateData import UpdateData from bot.message.messageData import MessageData
class StartHandler(AbstractHandler): class StartHandler(AbstractHandler):
@ -16,10 +16,10 @@ class StartHandler(AbstractHandler):
def handle(self, update: Update, context: CallbackContext) -> None: def handle(self, update: Update, context: CallbackContext) -> None:
self.reply_markdown(update, start_text) 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: def get_bot_handler(self) -> CommandHandler:
return self.bot_handler return self.bot_handler
def log_action(self, update_data: UpdateData) -> None: def log_action(self, message_data: MessageData) -> None:
Logger.info(f'User {update_data.username} called /start for {update_data.chat_id}') Logger.info(f'User {message_data.username} called /start for {message_data.chat_id}')

View File

@ -1,25 +1,26 @@
from __future__ import annotations from __future__ import annotations
from dataclasses import dataclass
import re import re
from dataclasses import dataclass
import names import names
from entity.group import Group
from exception.invalidArgumentException import InvalidArgumentException
from telegram.ext.callbackcontext import CallbackContext from telegram.ext.callbackcontext import CallbackContext
from telegram.update import Update from telegram.update import Update
from entity.group import Group
from exception.invalidArgumentException import InvalidArgumentException
@dataclass @dataclass
class UpdateData(): class MessageData():
user_id: str user_id: str
chat_id: str chat_id: str
group_name: str
username: str username: str
@staticmethod @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) chat_id = str(update.effective_chat.id)
group_name = Group.default_name
if context.args and context.args[0] and include_group: if context.args and context.args[0] and include_group:
group_name = str(context.args[0]).lower() group_name = str(context.args[0]).lower()
@ -41,4 +42,4 @@ class UpdateData():
if not username: if not username:
username = names.get_first_name() 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 joined = '{} joined group `{}`'
not_joined = '{} is already in group `{}`'
# These are MarkdownV2 python-telegram-bot specific left = '{} left group `{}`'
opted_in = re.escape('You have opted-in for everyone-mentions.') not_left = '{} did not join group `{}` before'
opted_in_failed = re.escape('You already opted-in for everyone-mentions.') mention_failed = 'There are no users to mention'
opted_off = re.escape('You have opted-off for everyone-mentions.') no_groups = 'There are no groups for this chat'
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.')
start_text = re.escape(""" start_text = """
Hello there. Hello there
I am `@everyone_mention_bot`. I am @everyone\_mention\_bot
I am here to help you with mass notifies. I am here to help you with mass notifies
Please take a look at available commands. Please take a look at available commands
Parameter `<group-name>` is not required, if not given, I will assign you to `default` group. `<group-name>` is not required, if not given, it is set to `default`
To opt-in for everyone-mentions use: To join group:
`/in <group-name>` `/join <group-name>`
for example: `/in gaming` for example: `/join games`
To opt-off for everyone mentions use: To leave group:
`/out <group-name>` `/leave <group-name>`
To gather everyone attention use: To gather everyone attention use:
`/everyone <group-name>` `/everyone <group-name>`
@ -30,8 +27,6 @@ To gather everyone attention use:
To see all available groups use: To see all available groups use:
`/groups` `/groups`
To display all users that opted-in for everyone-mentions use: To display all members in a group:
`/silent <group-name>` `/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 typing import Iterable, Optional
from bot.message.messageData import MessageData
from database.client import Client from database.client import Client
from entity.user import User from entity.user import User
from exception.notFoundException import NotFoundException from exception.notFoundException import NotFoundException
from handler.vo.updateData import UpdateData
class UserRepository(): class UserRepository():
@ -36,7 +36,7 @@ class UserRepository():
user.to_mongo_document() 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( self.client.insert_one(
User.collection, User.collection,
{ {