diff --git a/davtelepot/authorization.py b/davtelepot/authorization.py
index eea4b4f..d0f8b62 100644
--- a/davtelepot/authorization.py
+++ b/davtelepot/authorization.py
@@ -2,7 +2,7 @@
# Standard library modules
from collections import OrderedDict
-from typing import Callable, Union
+from typing import Callable, Union, List
# Project modules
from .bot import Bot
@@ -68,14 +68,14 @@ class Role:
roles = OrderedDict()
default_role_code = 100
- def __init__(self, code, name, symbol, singular, plural,
- can_appoint, can_be_appointed_by):
+ def __init__(self, code: int, name: str, symbol: str,
+ singular: str, plural: str,
+ can_appoint: List[int], can_be_appointed_by: List[int]):
"""Instantiate Role object.
code : int
The higher the code, the less privileges are connected to that
- role.
- Use 0 for banned users.
+ role. Use 0 for banned users.
name : str
Short name for role.
symbol : str
@@ -84,7 +84,7 @@ class Role:
Singular full name of role.
plural : str
Plural full name of role.
- can_appoint : lsit of int
+ can_appoint : list of int
List of role codes that this role can appoint.
can_be_appointed_by : list of int
List of role codes this role can be appointed by.
@@ -178,23 +178,74 @@ class Role:
cls.default_role_code = role
@classmethod
- def get_user_role_panel(cls, user_record):
- """Get text and buttons for user role panel."""
- user_role = cls.get_user_role(user_record=user_record)
- text = (
- """👤 {u[username]}\n"""
+ def get_user_role_text(cls,
+ user_record: OrderedDict,
+ user_role: 'Role' = None) -> str:
+ """
+ Get a string to describe the role of a user.
+
+ @param user_record: record of table `users` about the user; it must
+ contain at least a [username | last_name | first_name] and a
+ telegram identifier.
+ @param user_role: Role instance about user permissions.
+ @return: String to describe the role of a user, like this:
+ ```
+ 👤 LinkedUsername
+ 🔑 Admin ⚜️
+ ```
+ """
+ if user_role is None:
+ user_role = cls.get_user_role(user_record=user_record)
+ return (
+ f"""👤 {get_user(record=user_record)}\n"""
f"🔑 {user_role.singular.capitalize()} {user_role.symbol}"
- ).format(
- u=user_record,
)
- buttons = [
+
+ @classmethod
+ def get_user_role_buttons(cls,
+ user_record: OrderedDict,
+ admin_record: OrderedDict,
+ user_role: 'Role' = None,
+ admin_role: 'Role' = None) -> List[dict]:
+ """ Return buttons to edit user permissions.
+ @param user_record: record of table `users` about the user; it must
+ contain at least a [username | last_name | first_name] and a
+ telegram identifier.
+ @param admin_record: record of table `users` about the admin; it must
+ contain at least a [username | last_name | first_name] and a
+ telegram identifier.
+ @param user_role: Role instance about user permissions.
+ @param admin_role: Role instance about admin permissions.
+ @return: list of `InlineKeyboardButton`s.
+ """
+ if admin_role is None:
+ admin_role = cls.get_user_role(user_record=admin_record)
+ if user_role is None:
+ user_role = cls.get_user_role(user_record=user_record)
+ return [
make_button(
f"{role.symbol} {role.singular.capitalize()}",
prefix='auth:///',
data=['set', user_record['id'], code]
)
for code, role in cls.roles.items()
+ if (admin_role > user_role
+ and code in admin_role.can_appoint)
]
+
+ @classmethod
+ def get_user_role_text_and_buttons(cls,
+ user_record: OrderedDict,
+ admin_record: OrderedDict):
+ """Get text and buttons for user role panel."""
+ admin_role = cls.get_user_role(user_record=admin_record)
+ user_role = cls.get_user_role(user_record=user_record)
+ text = cls.get_user_role_text(user_record=user_record,
+ user_role=user_role)
+ buttons = cls.get_user_role_buttons(user_record=user_record,
+ user_role=user_role,
+ admin_record=admin_record,
+ admin_role=admin_role)
return text, buttons
def __eq__(self, other):
@@ -258,51 +309,64 @@ def get_authorization_function(bot):
return is_authorized
-async def _authorization_command(bot, update, user_record):
- text = get_cleaned_text(bot=bot, update=update, replace=['auth'])
+async def _authorization_command(bot, update, user_record, ban=False):
+ to_be_replaced = []
+ if ban:
+ to_be_replaced.append('ban')
+ else:
+ to_be_replaced.append('auth')
+ db = bot.db
+ text = get_cleaned_text(bot=bot, update=update, replace=to_be_replaced)
reply_markup = None
- # noinspection PyUnusedLocal
+ admin_record = user_record.copy()
+ admin_role = bot.Role.get_user_role(user_record=admin_record)
result = bot.get_message(
'authorization', 'auth_command', 'unhandled_case',
- update=update, user_record=user_record
+ update=update, user_record=admin_record
)
if not text:
if 'reply_to_message' not in update:
return bot.get_message(
'authorization', 'auth_command', 'instructions',
- update=update, user_record=user_record
+ update=update, user_record=admin_record
)
else:
- with bot.db as db:
- user_record = db['users'].find_one(
- telegram_id=update['reply_to_message']['from']['id']
- )
- else:
- with bot.db as db:
- user_record = list(
- db.query(
- "SELECT * "
- "FROM users "
- "WHERE COALESCE("
- " first_name || last_name || username,"
- " last_name || username,"
- " first_name || username,"
- " username,"
- " first_name || last_name,"
- " last_name,"
- " first_name"
- f") LIKE '%{text}%'"
+ if ban and 0 in admin_role.can_appoint:
+ db['users'].update(
+ dict(
+ telegram_id=update['reply_to_message']['from']['id'],
+ privileges=0
+ ),
+ ['telegram_id']
)
+ user_record = db['users'].find_one(
+ telegram_id=update['reply_to_message']['from']['id']
)
+ else:
+ user_record = list(
+ db.query(
+ "SELECT * "
+ "FROM users "
+ "WHERE COALESCE("
+ " first_name || last_name || username,"
+ " last_name || username,"
+ " first_name || username,"
+ " username,"
+ " first_name || last_name,"
+ " last_name,"
+ " first_name"
+ f") LIKE '%{text}%'"
+ )
+ )
if user_record is None:
result = bot.get_message(
'authorization', 'auth_command', 'unknown_user',
- update=update, user_record=user_record
+ update=update, user_record=admin_record
)
elif type(user_record) is list and len(user_record) > 1:
result = bot.get_message(
'authorization', 'auth_command', 'choose_user',
- update=update, user_record=user_record,
+ update=update, user_record=admin_record,
n=len(user_record)
)
reply_markup = make_inline_keyboard(
@@ -319,12 +383,14 @@ async def _authorization_command(bot, update, user_record):
elif type(user_record) is list and len(user_record) == 0:
result = bot.get_message(
'authorization', 'auth_command', 'no_match',
- update=update, user_record=user_record,
+ update=update, user_record=admin_record,
+ )
+ elif type(user_record) is list and len(user_record) == 1:
+ user_record = user_record[0]
+ result, buttons = bot.Role.get_user_role_text_and_buttons(
+ user_record=user_record,
+ admin_record=admin_record
)
- else:
- if type(user_record) is list:
- user_record = user_record[0]
- result, buttons = bot.Role.get_user_role_panel(user_record)
reply_markup = make_inline_keyboard(buttons, 1)
return dict(
text=result,
@@ -343,10 +409,13 @@ async def _authorization_button(bot, update, user_record, data):
else:
other_user_id = None
result, text, reply_markup = '', '', None
+ db = bot.db
if command in ['show']:
- with bot.db as db:
- other_user_record = db['users'].find_one(id=other_user_id)
- text, buttons = bot.Role.get_user_role_panel(other_user_record)
+ other_user_record = db['users'].find_one(id=other_user_id)
+ text, buttons = bot.Role.get_user_role_text_and_buttons(
+ user_record=other_user_record,
+ admin_record=user_record
+ )
reply_markup = make_inline_keyboard(buttons, 1)
elif command in ['set'] and len(arguments) > 1:
other_user_id, new_privileges, *_ = arguments
@@ -358,8 +427,7 @@ async def _authorization_button(bot, update, user_record, data):
'authorization', 'auth_button', 'confirm',
update=update, user_record=user_record,
)
- with bot.db as db:
- other_user_record = db['users'].find_one(id=other_user_id)
+ other_user_record = db['users'].find_one(id=other_user_id)
user_role = bot.Role.get_user_role(user_record=user_record)
other_user_role = bot.Role.get_user_role(user_record=other_user_record)
if other_user_role.code == new_privileges:
@@ -404,20 +472,22 @@ async def _authorization_button(bot, update, user_record, data):
1
)
else:
- with bot.db as db:
- db['users'].update(
- dict(
- id=other_user_id,
- privileges=new_privileges
- ),
- ['id']
- )
- other_user_record = db['users'].find_one(id=other_user_id)
+ db['users'].update(
+ dict(
+ id=other_user_id,
+ privileges=new_privileges
+ ),
+ ['id']
+ )
+ other_user_record = db['users'].find_one(id=other_user_id)
result = bot.get_message(
'authorization', 'auth_button', 'appointed',
update=update, user_record=user_record
)
- text, buttons = bot.Role.get_user_role_panel(other_user_record)
+ text, buttons = bot.Role.get_user_role_text_and_buttons(
+ user_record=other_user_record,
+ admin_record=user_record
+ )
reply_markup = make_inline_keyboard(buttons, 1)
if text:
return dict(
@@ -431,14 +501,9 @@ async def _authorization_button(bot, update, user_record, data):
return result
-async def _ban_command(bot, update, user_record):
- # TODO define this function!
- return
-
-
def default_get_administrators_function(bot: Bot):
return list(
- bot.db['users'].find(privileges=[1,2])
+ bot.db['users'].find(privileges=[1, 2])
)
@@ -498,6 +563,6 @@ def init(telegram_bot: Bot,
@telegram_bot.command('/ban', aliases=[], show_in_keyboard=False,
description=authorization_messages['ban_command']['description'],
- authorization_level='admin')
+ authorization_level='moderator')
async def ban_command(bot, update, user_record):
- return await _ban_command(bot, update, user_record)
+ return await _authorization_command(bot, update, user_record, ban=True)
diff --git a/davtelepot/suggestions.py b/davtelepot/suggestions.py
index de30225..63f72b8 100644
--- a/davtelepot/suggestions.py
+++ b/davtelepot/suggestions.py
@@ -162,7 +162,7 @@ async def _suggestions_button(bot: davtelepot.bot.Bot, update, user_record, data
)['suggestion']
suggestion_message = bot.get_message(
'suggestions', 'suggestions_command', 'received_suggestion', 'text',
- user=bot.Role.get_user_role_panel(registered_user)[0],
+ user=bot.Role.get_user_role_text(user_record=registered_user),
suggestion=suggestion_text,
bot=bot,
update=update, user_record=user_record,