Initial commit

This commit is contained in:
2024-07-17 23:35:45 +03:00
parent 7a1a025471
commit a7bfd5ed4a
42 changed files with 2041 additions and 2 deletions

0
templates/__init__.py Normal file
View File

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

64
templates/ban_words.py Normal file
View File

@@ -0,0 +1,64 @@
from aiogram.types import InlineKeyboardButton, InlineKeyboardMarkup
from aiogram.utils.keyboard import InlineKeyboardBuilder
from aiogram.fsm.state import StatesGroup, State
class SendState(StatesGroup):
words = State()
send_words_text = """
Отправь список слов по одному или столбцом
"""
success_text = """
Слова {action}!
"""
not_success_remove_text = """
Что-то пошло не так. Не удалил слова:
{words}
"""
def send_words_ikb() -> InlineKeyboardMarkup:
"""
-⬅️ Назад
:return: объект клавиатуры для параметра reply_markup
"""
builder = InlineKeyboardBuilder()
builder.add(
InlineKeyboardButton(
text='⬅️ Назад',
callback_data='come_back_ban_words'
)
)
builder.adjust(1)
return builder.as_markup()
def actions_ikb() -> InlineKeyboardMarkup:
"""
- Добавить
- Удалить
-⬅️ Назад
:return: объект клавиатуры для параметра reply_markup
"""
builder = InlineKeyboardBuilder()
builder.add(
InlineKeyboardButton(
text=' Добавить',
callback_data='ban_words_action_add'
),
InlineKeyboardButton(
text=' Удалить',
callback_data='ban_words_action_remove'
),
InlineKeyboardButton(
text='⬅️ Назад',
callback_data='come_back_menu'
)
)
builder.adjust(1)
return builder.as_markup()

62
templates/commands.py Normal file
View File

@@ -0,0 +1,62 @@
from aiogram.types import InlineKeyboardButton, InlineKeyboardMarkup
from aiogram.utils.keyboard import InlineKeyboardBuilder
from utils.db import Postgres
start_text = """
Привет, Админ!
"""
async def start_ikb() -> InlineKeyboardMarkup:
"""
-🚫 Стоп слова
-💬 Стоп сообщение
-Запретить / Разрешить видео без опис.
-Запретить / Разрешить фото без опис.
:return: объект клавиатуры для параметра reply_markup
"""
builder = InlineKeyboardBuilder()
ban_media_photo = {'text': '', 'callback_data': ''}
ban_media_video = {'text': '', 'callback_data': ''}
ban_media = await Postgres().get_data(
table_name='ban_media'
)
if not ban_media[0]['photo']:
ban_media_photo['text'] = 'Запретить фото без описания'
ban_media_photo['callback_data'] = 'enable_ban_media_photo'
else:
ban_media_photo['text'] = 'Разрешить фото без описания'
ban_media_photo['callback_data'] = 'disable_ban_media_photo'
if not ban_media[0]['video']:
ban_media_video['text'] = 'Запретить видео без описания'
ban_media_video['callback_data'] = 'enable_ban_media_video'
else:
ban_media_video['text'] = 'Разрешить видео без описания'
ban_media_video['callback_data'] = 'disable_ban_media_video'
builder.add(
InlineKeyboardButton(
text='🚫 Стоп слова',
callback_data='ban_words'
),
InlineKeyboardButton(
text='💬 Стоп сообщение',
callback_data='message'
),
InlineKeyboardButton(
text=ban_media_video['text'],
callback_data=ban_media_video['callback_data']
),
InlineKeyboardButton(
text=ban_media_photo['text'],
callback_data=ban_media_photo['callback_data']
)
)
builder.adjust(1)
return builder.as_markup()

226
templates/message.py Normal file
View File

@@ -0,0 +1,226 @@
import json
from aiogram.fsm.state import StatesGroup, State
from aiogram.types import InlineKeyboardButton, InlineKeyboardMarkup
from aiogram.types import Message
from aiogram.utils.keyboard import InlineKeyboardBuilder
from core import bot
class SendState(StatesGroup):
message = State()
buttons = State()
actions_text = """
Сообщение включено: <b>{include}</b>
Выберите действие:
"""
send_message_text = """
Отправьте сообщение с прикреплением до одного фото:
"""
send_buttons_text = """
Отправьте кнопки в таком формате:
<b>Кнопка в первом ряду - http://example.com</b>
<b>Кнопка во втором ряду - http://example.com</b>
Используйте разделитель " | ", чтобы добавить до 8 кнопок в один ряд (допустимо 6 рядов):
<b>Кнопка в ряду - http://example.com | Другая кнопка в ряду - http://example.com</b>
"""
incorrect_data_text = """
<b>Не верный формат данных</b>
"""
check_data_text = """
Проверьте введённые данные
"""
publish_message_text = """
Обуликовано успешно
"""
def check_data_ikb() -> InlineKeyboardMarkup:
"""
-✅ Опубликовать
-⬅️ Назад
:return: объект клавиатуры для параметра reply_markup
"""
builder = InlineKeyboardBuilder()
builder.add(
InlineKeyboardButton(
text='✅ Опубликовать',
callback_data='publish_message'
),
InlineKeyboardButton(
text='⬅️ Назад',
callback_data='come_back_buttons'
)
)
builder.adjust(1)
return builder.as_markup()
async def send_preview(message_data: dict, chat_id: int, username='') -> Message | None:
"""
Присылает превью сообщения
:param message_data: Данные сообщения из бд
:param chat_id: ID телеграм чата куда надо прислать превью
:param username: Username пользователя
:return:
"""
msg_text = message_data['text']
if username:
msg_text = f'{username}\n\n' + message_data['text']
if message_data['media']:
preview_msg = await bot.send_photo(
chat_id=chat_id,
caption=msg_text,
photo=message_data['media'],
reply_markup=url_ikb(
row_buttons=message_data['buttons']
)
)
else:
preview_msg = await bot.send_message(
chat_id=chat_id,
text=msg_text,
reply_markup=url_ikb(
row_buttons=message_data['buttons']
)
)
return preview_msg
def send_buttons_ikb() -> InlineKeyboardMarkup:
"""
-➡️ Пропустить
-⬅️ Назад
:return: объект клавиатуры для параметра reply_markup
"""
builder = InlineKeyboardBuilder()
builder.add(
InlineKeyboardButton(
text='➡️ Пропустить',
callback_data='pass_buttons'
),
InlineKeyboardButton(
text='⬅️ Назад',
callback_data='come_back_message'
)
)
builder.adjust(1)
return builder.as_markup()
def send_message_ikb() -> InlineKeyboardMarkup:
"""
-⬅️ Назад
:return: объект клавиатуры для параметра reply_markup
"""
builder = InlineKeyboardBuilder()
builder.add(
InlineKeyboardButton(
text='⬅️ Назад',
callback_data='come_back_preview'
)
)
builder.adjust(1)
return builder.as_markup()
def actions_ikb(included: bool) -> InlineKeyboardMarkup:
"""
-Вкл✅ \ Выкл ❌
-📝 Редактировать
-⬅️ Назад
:param included: bool включено ли сообщение или нет
:return: объект клавиатуры для параметра reply_markup
"""
builder = InlineKeyboardBuilder()
if included:
included_btn = InlineKeyboardButton(
text='Выкл ❌',
callback_data='included_message_false'
)
else:
included_btn = InlineKeyboardButton(
text='Вкл ✅',
callback_data='included_message_true'
)
builder.add(
included_btn,
InlineKeyboardButton(
text='📝 Редактировать',
callback_data='edit_message'
),
InlineKeyboardButton(
text='⬅️ Назад',
callback_data='come_back_menu'
)
)
builder.adjust(1)
return builder.as_markup()
def build_url_ikb(msg_text: str) -> list:
"""
Создаёт клавиатуру с url кнопками пользователя
:param msg_text: Текст сообщения с заданными параметры клавиатуру
:return: list с кнопками клавиатуры
"""
try:
paragraphs = msg_text.split('\n')
row_buttons = []
for paragraph in paragraphs:
row = []
for button_text_data in paragraph.split(' | '):
row.append(button_text_data.strip().split(' - '))
row_buttons.append(row)
return row_buttons
except:
return []
def url_ikb(row_buttons: list | str) -> InlineKeyboardMarkup | None:
"""
Создаёт клавиатуру с url кнопками пользователя
:param row_buttons: List с кнопками клавиатуры
:return: В случае ошибки False, если норм то объект клавиатуры для параметра reply_markup
"""
try:
if isinstance(row_buttons, str):
row_buttons = json.loads(row_buttons)
builder = InlineKeyboardBuilder()
rows_len = [0, 0, 0, 0, 0, 0]
i = 0
for row in row_buttons:
rows_len[i] = len(row)
for button in row:
builder.add(
InlineKeyboardButton(
text=button[0],
url=button[1]
)
)
i += 1
builder.adjust(*rows_len)
if row_buttons:
return builder.as_markup()
return None
except:
return None

458
templates/moderation.py Normal file
View File

@@ -0,0 +1,458 @@
import datetime
import logging
from aiogram.fsm.state import StatesGroup, State
from aiogram.types import InlineKeyboardButton, InlineKeyboardMarkup, FSInputFile
from aiogram.utils.keyboard import InlineKeyboardBuilder
from config import FILES_PATH, ROLE_MODERATOR_ID, ROLE_CURATOR_ID
from core import bot
from utils.bitrix import notify
from utils.db import get_data, query
class ModerationState(StatesGroup):
confirm = State()
confirm_confirm = State()
revision = State()
grade = State()
reject = State()
check_revision_comment = State()
check_reject_comment = State()
date = State()
new_idea_text = """
{name}, пожалуйста, ознакомьтесь с новой НеоИдеей.
"""
new_idea_data_text = """
<b>Автор:</b> {author_name}
<b>Дата:</b> {creation_date}
<b>Подразделение:</b> {department}
<b>Категория:</b> {category}
<b>Город:</b> {city}
<b>Название:</b> «{idea_name}»
<b>Содержание:</b> {idea_content}
"""
choose_action_text = """
Пожалуйста, выберите одно из следующих действий:
"""
confirm_action_text = """
<b>Вы согласовываете НеоИдею:</b>
«{idea_name}».
<b>Автор:</b> {author_name}
"""
choose_responsible_text = """
Пожалуйста, выберите <b>Ответственного за категорию</b> для передачи НеоИдеи в работу.
"""
send_date_text = """
В календаре укажите крайние сроки выполнения:
"""
confirm_responsible_date_text = """
Вы передаёте НеоИдею в работу.
<b>Название:</b> «{idea_name}».
<b>Автор:</b> {author_name}
<b>Ответственный за категорию:</b> {responsible_name}
<b>Крайние сроки выполнения:</b> {date}
"""
confirm_action_send_text = """
Спасибо! Вы передали НеоИдею в работу.
"""
revision_action_text = """
<b>Вы возвращаете на доработку НеоИдею:</b>
«{idea_name}».
<b>Автор:</b> {author_name}
Оставьте комментарий для того, чтобы отправить НеоИдею на доработку.
"""
send_revision_comment_text = """
Оставьте комментарий для того, чтобы отправить НеоИдею на доработку
"""
send_comment_text = """
Пожалуйста, оставьте свой комментарий:
"""
check_comment = """
Проверьте правильность введенных данных:
{comment}
"""
revision_action_send_text = """
Вы отправили НеоИдею на доработку.
"""
grade_action_text = """
<b>Вы направляете НеоИдею на оценку:</b>
«{idea_name}».
<b>Автор:</b> {author_name}
НеоИдея будет передана Куратору.
"""
grade_action_send_text = """
Спасибо! НеоИдея передана Куратору.
"""
reject_action_text = """
<b>Вы отклоняете НеоИдею:</b>
«{idea_name}».
<b>Автор:</b> {author_name}
Пожалуйста, оставьте свой комментарий.
"""
reject_action_send_text = """
Спасибо! НеоИдея отклонена.
"""
you_rejected = """
Здравствуйте, {name}.
Ваша НеоИдея "{idea_name}" была отклонена с комментарием:
"{comment}"
"""
you_revision = """
Ваша НеоИдея возвращена на доработку, пожалуйста проработайте комментарии от генерального директора и отправьте заявку заново.
НеоИдея: "{idea_name}"
Комментарий: "{comment}"
"""
accept_notify_author_text = """
Поздравляем! Ваша НеоИдея передана к внедрению
"""
accept_notify_curator_text = """
Быстрая НеоИдея автора {author_name} передана к внедрению {responsible_name}
"""
grade_curator_text = """
Вам на оценку передана НеоИдея "{idea_name}".
"""
confirm_notify_curator_text = """
Быстрая НеоИдея автора {author_name} передана к ответственному за категорию {responsible_name}
"""
confirm_notify_author_text = """
Ваша НеоИдея передана ответственному за категорию
"""
def confirm_action_ikb() -> InlineKeyboardMarkup:
"""
-Да, продолжить ✅
-Нет, вернуться назад ❌
:return: объект клавиатуры для параметра reply_markup
"""
builder = InlineKeyboardBuilder()
builder.add(
InlineKeyboardButton(
text='Да, продолжить ✅',
callback_data='confirm_action_confirm'
),
InlineKeyboardButton(
text='Нет, вернуться назад ❌',
callback_data='confirm_action_reject'
)
)
builder.adjust(1)
return builder.as_markup()
def choose_action_ikb(idea_id: str | int, msg_id: str | int) -> InlineKeyboardMarkup:
"""
-Согласовать и передать в работу
-Вернуть Автору на доработку
-Направить на оценку
-Отклонить
:param idea_id: ID идеи
:param msg_id: ID сообщения с клавиатурой
:return: объект клавиатуры для параметра reply_markup
"""
builder = InlineKeyboardBuilder()
builder.add(
InlineKeyboardButton(
text='Согласовать и передать в работу',
callback_data=f'moderation_confirm_{idea_id}_{msg_id}'
),
InlineKeyboardButton(
text='Вернуть Автору на доработку',
callback_data=f'moderation_revision_{idea_id}_{msg_id}'
),
InlineKeyboardButton(
text='Направить на оценку',
callback_data=f'moderation_grade_{idea_id}_{msg_id}'
),
InlineKeyboardButton(
text='Отклонить',
callback_data=f'moderation_reject_{idea_id}_{msg_id}'
)
)
builder.adjust(1)
return builder.as_markup()
async def choose_responsible_ikb(category_id: int) -> InlineKeyboardMarkup:
"""
-Ответственный 1
-Ответственный 2
:param category_id: ID категории идеи
:return: объект клавиатуры для параметра reply_markup
"""
builder = InlineKeyboardBuilder()
responsible_list = await get_data(
table_name='user_to_categories',
query_filter={'category_id': category_id}
)
for responsible in responsible_list:
responsible_data = await get_data(
table_name='users',
query_filter={'id': responsible['user_id']}
)
builder.add(
InlineKeyboardButton(
text=responsible_data[0]['full_name'],
callback_data=f'choose_responsible_{responsible_data[0]["id"]}',
)
)
builder.adjust(1)
return builder.as_markup()
async def send_new_idea_on_moderation(
idea_id: int, user_name: str, department: str, idea_title: str,
idea_content: str, relation_id: int, city_id: int, category_id: int, creation_date: datetime.datetime):
"""
Присылает новую идею модераторам из списка
:param idea_id: Данные идеи
:param user_name: Имя пользователя
:param department: Отдел пользователя
:param idea_title: Название идеи
:param idea_content: Описание идеи
:param relation_id: id отношения к идее
:param city_id: id города, где работает пользователь
:param category_id: id категории
:param creation_date: Дата создания идеи
:return:
"""
moderators = await get_data(
table_name='user_to_roles',
query_filter={'role_id': ROLE_MODERATOR_ID}
)
city = await get_data(
table_name='cities',
query_filter={'id': city_id}
)
files = await get_data(
table_name='idea_to_files',
query_filter={'idea_id': idea_id}
)
category = await get_data(
table_name='categories',
query_filter={'id': category_id}
)
notify_text = new_idea_data_text.format(
author_name=user_name,
creation_date=creation_date,
department=department,
idea_name=idea_title,
idea_content=idea_content,
city=city[0]['name'],
category=category[0]['name']
)
for moderator_id in moderators:
try:
moderator = await get_data(
table_name='users',
query_filter={'id': moderator_id['user_id']}
)
formatted_new_idea_text = new_idea_text.format(
name=moderator[0]['full_name'],
)
await bot.send_message(
chat_id=moderator[0]['telegram_id'],
text=formatted_new_idea_text
)
await bot.send_message(
chat_id=moderator[0]['telegram_id'],
text=notify_text
)
for file in files:
file_data = await get_data(
table_name='files',
query_filter={'id': file['file_id']}
)
await bot.send_document(
chat_id=moderator[0]['telegram_id'],
document=FSInputFile(FILES_PATH + file_data[0]['file'])
)
last_msg = await bot.send_message(
chat_id=moderator[0]['telegram_id'],
text=choose_action_text,
reply_markup=choose_action_ikb(
idea_id=idea_id,
msg_id=0
)
)
await bot.edit_message_reply_markup(
message_id=last_msg.message_id,
chat_id=moderator[0]['telegram_id'],
reply_markup=choose_action_ikb(
idea_id=idea_id,
msg_id=last_msg.message_id
)
)
moderator_user_data = await get_data(
table_name='users',
query_filter={'id': moderator_id['user_id']}
)
await notify(
user_id=moderator_user_data[0]['external_id'],
message='Новая быстрая НеоИдея!'
)
except Exception as e:
logging.error(e)
curators = await get_data(
table_name='user_to_roles',
query_filter={'role_id': ROLE_CURATOR_ID}
)
for curator in curators:
try:
user_data = await get_data(
table_name='users',
query_filter={'id': curator['user_id']}
)
await notify(
user_id=user_data[0]['external_id'],
message='Новая быстрая НеоИдея!'
)
except Exception as e:
logging.error(f'не могу отправить уведомление куратору о новой идее {e}')
async def accept_notify(author_name: str, responsible_id: str, author_id: int) -> None:
"""
Уведомляет куратора и автора о принятии идеи
:param responsible_id: ID кому передают идею
:param author_name: Имя автора идеи
:param author_id: ID автора
:return:
"""
responsible_data = await get_data(
table_name='users',
query_filter={'id': responsible_id}
)
notify_text = notify_curator_text.format(
author_name=author_name,
responsible_name=responsible_data[0]['full_name']
)
curators = await get_data(
table_name='user_to_roles',
query_filter={'role_id': ROLE_CURATOR_ID}
)
for curator in curators:
try:
user_data = await get_data(
table_name='users',
query_filter={'id': curator['user_id']}
)
await notify(
user_id=user_data[0]['external_id'],
message=notify_text
)
await bot.send_message(
chat_id=user_data[0]['telegram_id'],
text=notify_text
)
except Exception as e:
logging.error(f'не могу отправить уведомление куратору о принятии идеи {e}')
try:
author_data = await get_data(
table_name='users',
query_filter={'id': author_id}
)
await notify(
user_id=author_data[0]['external_id'],
message=notify_author_text
)
await bot.send_message(
chat_id=author_data[0]['telegram_id'],
text=notify_author_text
)
except Exception as e:
logging.error(f'Не смог отправить уведомление автору идеи {e}')
async def confirm_notify(author_name: str, responsible_id: str, author_id: int) -> None:
"""
Уведомляет куратора и автора о согласовании идеи
:param responsible_id: ID кому передают идею
:param author_name: Имя автора идеи
:param author_id: ID автора
:return:
"""
responsible_data = await get_data(
table_name='users',
query_filter={'id': responsible_id}
)
notify_text = confirm_notify_curator_text.format(
author_name=author_name,
responsible_name=responsible_data[0]['full_name']
)
curators = await get_data(
table_name='user_to_roles',
query_filter={'role_id': ROLE_CURATOR_ID}
)
for curator in curators:
try:
user_data = await get_data(
table_name='users',
query_filter={'id': curator['user_id']}
)
await notify(
user_id=user_data[0]['external_id'],
message=notify_text
)
await bot.send_message(
chat_id=user_data[0]['telegram_id'],
text=notify_text
)
except Exception as e:
logging.error(f'не могу отправить уведомление куратору о принятии идеи {e}')
try:
author_data = await get_data(
table_name='users',
query_filter={'id': author_id}
)
await notify(
user_id=author_data[0]['external_id'],
message=notify_author_text
)
await bot.send_message(
chat_id=author_data[0]['telegram_id'],
text=notify_author_text
)
except Exception as e:
logging.error(f'Не смог отправить уведомление автору идеи {e}')