Compare commits
29 Commits
e8e2d3dc58
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 652400e50f | |||
| 95195c2749 | |||
| 9979937113 | |||
| be80c4044b | |||
| 6549c3d70b | |||
| cc520caef5 | |||
| 51eebcc165 | |||
| ffe5e2e938 | |||
| 77a00d7623 | |||
| 369bd7a6e1 | |||
| 8604774741 | |||
| 5f2a00ba4a | |||
| 355f81520c | |||
| 1af9a7b4d9 | |||
| de9c0e6724 | |||
| 3ad35c6980 | |||
| b5a2938b12 | |||
| 5b09353b06 | |||
| 872db63c0c | |||
| 9af6b71712 | |||
| bda32cca6a | |||
| b23c1a8b62 | |||
| 882a06f226 | |||
| 50b329bd35 | |||
| a2509c629e | |||
| 2307637c80 | |||
| 631e7b4c13 | |||
| 9fae1cbe1c | |||
| bbf2b1e6f9 |
4
app/FSM/__init__.py
Normal file
4
app/FSM/__init__.py
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
from .states import OrderForm, SearchForm, OrderingForm
|
||||||
|
|
||||||
|
|
||||||
|
__all__ = ["SearchForm", "OrderForm", "OrderingForm"]
|
||||||
25
app/FSM/states.py
Normal file
25
app/FSM/states.py
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
from aiogram.fsm.state import State, StatesGroup
|
||||||
|
|
||||||
|
|
||||||
|
class SearchForm(StatesGroup):
|
||||||
|
search_option = State()
|
||||||
|
data_to_search = State()
|
||||||
|
sent_messages = State()
|
||||||
|
search_result = State()
|
||||||
|
|
||||||
|
|
||||||
|
class OrderForm(StatesGroup):
|
||||||
|
id = State()
|
||||||
|
worker_id = State()
|
||||||
|
status_id = State()
|
||||||
|
counterparty = State()
|
||||||
|
customer = State()
|
||||||
|
commencement_work = State()
|
||||||
|
end_work = State()
|
||||||
|
description = State()
|
||||||
|
|
||||||
|
|
||||||
|
class OrderingForm(StatesGroup):
|
||||||
|
tools_list = State()
|
||||||
|
|
||||||
|
|
||||||
@@ -1,14 +1,8 @@
|
|||||||
import os
|
import os
|
||||||
import asyncpg
|
|
||||||
from sqlalchemy.ext.asyncio import async_sessionmaker, create_async_engine, session
|
from sqlalchemy.ext.asyncio import async_sessionmaker, create_async_engine, session
|
||||||
import dotenv
|
|
||||||
|
|
||||||
# connection = psycopg2.connect(*(os.getenv(key) for key in ["DATABASE", "DB_HOST", "DB_USER", "DB_PASSWORD"]))
|
|
||||||
# connection.autocommit = True
|
|
||||||
|
|
||||||
dotenv.load_dotenv(".env")
|
|
||||||
DATABASE_URL = (f"postgresql+asyncpg://{os.getenv('DB_USER')}:{os.getenv('DB_PASSWORD')}@"
|
DATABASE_URL = (f"postgresql+asyncpg://{os.getenv('DB_USER')}:{os.getenv('DB_PASSWORD')}@"
|
||||||
f"{os.getenv('DB_HOST')}/{os.getenv('DATABASE')}")
|
f"{os.getenv('DB_HOST')}/{os.getenv('DATABASE')}")
|
||||||
print(DATABASE_URL)
|
|
||||||
engine = create_async_engine(DATABASE_URL, echo=True)
|
engine = create_async_engine(DATABASE_URL, echo=True)
|
||||||
async_session_ = async_sessionmaker(bind=engine, expire_on_commit=False)
|
async_session_ = async_sessionmaker(bind=engine, expire_on_commit=False)
|
||||||
|
|||||||
@@ -13,10 +13,11 @@ class Base(DeclarativeBase):
|
|||||||
class Worker(Base):
|
class Worker(Base):
|
||||||
"""
|
"""
|
||||||
id SERIAL PRIMARY KEY,
|
id SERIAL PRIMARY KEY,
|
||||||
telegram_id INTEGER UNIQUE NOT NULL,
|
telegram_id BIGINT UNIQUE NOT NULL,
|
||||||
name VARCHAR NOT NULL,
|
name VARCHAR NOT NULL,
|
||||||
email VARCHAR(50),
|
email VARCHAR(50),
|
||||||
phone_number VARCHAR(20) NOT NULL,
|
phone_number VARCHAR(20),
|
||||||
|
job_title job_title default 'Сборщик',
|
||||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
updated_at TIMESTAMP
|
updated_at TIMESTAMP
|
||||||
"""
|
"""
|
||||||
@@ -27,7 +28,7 @@ class Worker(Base):
|
|||||||
name = Column(String, nullable=False)
|
name = Column(String, nullable=False)
|
||||||
email = Column(String, nullable=True)
|
email = Column(String, nullable=True)
|
||||||
phone_number = Column(String, default=None)
|
phone_number = Column(String, default=None)
|
||||||
job_title = Column(job_title, default='Сборщик'),
|
job_title = Column(job_title, default='Сборщик')
|
||||||
created_at = Column(Date, server_default=func.now())
|
created_at = Column(Date, server_default=func.now())
|
||||||
updated_at = Column(Date, onupdate=func.now())
|
updated_at = Column(Date, onupdate=func.now())
|
||||||
|
|
||||||
|
|||||||
@@ -1,19 +1,18 @@
|
|||||||
import logging
|
import os
|
||||||
|
from typing import Any
|
||||||
from aiogram.types import Message, CallbackQuery
|
from aiogram.types import Message, CallbackQuery
|
||||||
from aiogram.filters import BaseFilter
|
from aiogram.filters import BaseFilter
|
||||||
from keyboards.menu_commands import commands
|
from keyboards.menu_commands import commands
|
||||||
import os
|
|
||||||
|
|
||||||
loggger = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class IsAdmin(BaseFilter):
|
class IsAdmin(BaseFilter):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.admins_ids = os.getenv("BOT_ADMINS").split(",")
|
self.admins_ids = list(map(int, os.getenv("BOT_ADMINS").split(",")))
|
||||||
|
|
||||||
|
|
||||||
async def __call__(self, message: Message | CallbackQuery) -> bool:
|
async def __call__(self, message: Message | CallbackQuery) -> bool:
|
||||||
return str(message.from_user.id) in self.admins_ids
|
return message.from_user.id in self.admins_ids
|
||||||
|
|
||||||
|
|
||||||
class CommandFilter(BaseFilter):
|
class CommandFilter(BaseFilter):
|
||||||
@@ -23,3 +22,7 @@ class CommandFilter(BaseFilter):
|
|||||||
async def __call__(self, message: Message) -> bool:
|
async def __call__(self, message: Message) -> bool:
|
||||||
return message.text.startswith(tuple(self.commands.keys()))
|
return message.text.startswith(tuple(self.commands.keys()))
|
||||||
|
|
||||||
|
|
||||||
|
class IsRegister(BaseFilter):
|
||||||
|
async def __call__(self, message: Message | CallbackQuery, **data: dict[str, Any]) -> bool:
|
||||||
|
return data.get("through_registration") is True
|
||||||
|
|||||||
@@ -1 +1,4 @@
|
|||||||
from .Filters import IsAdmin
|
from .Filters import IsAdmin
|
||||||
|
from .Filters import IsRegister
|
||||||
|
|
||||||
|
__all__ = ["IsRegister", "IsAdmin"]
|
||||||
@@ -1,11 +1,9 @@
|
|||||||
import time
|
|
||||||
import re
|
import re
|
||||||
from aiogram import Router, Bot, F
|
|
||||||
from aiogram.types import (Message, ChatMemberUpdated, FSInputFile, CallbackQuery, ReplyKeyboardRemove)
|
|
||||||
from loguru import logger
|
from loguru import logger
|
||||||
|
from aiogram import Router, Bot, F
|
||||||
|
from aiogram.types import Message, CallbackQuery
|
||||||
from handlers.registration import registration_confirm
|
from handlers.registration import registration_confirm
|
||||||
from filters.Filters import IsAdmin, CommandFilter
|
from filters.Filters import IsAdmin
|
||||||
from database import async_session_
|
|
||||||
|
|
||||||
admin_router = Router()
|
admin_router = Router()
|
||||||
|
|
||||||
|
|||||||
@@ -1,61 +1,39 @@
|
|||||||
import asyncio
|
|
||||||
import os
|
import os
|
||||||
from pathlib import Path
|
|
||||||
import re
|
import re
|
||||||
|
from pathlib import Path
|
||||||
from aiogram import Router, Bot, F
|
from aiogram import Router, Bot, F
|
||||||
from aiogram.filters import CommandStart, Command
|
from aiogram.filters import Command
|
||||||
from aiogram.types import Message, CallbackQuery, FSInputFile, InputMediaPhoto, InputMediaVideo, ReplyKeyboardRemove
|
from aiogram.types import Message, CallbackQuery, FSInputFile, InputMediaPhoto, InputMediaVideo, ReplyKeyboardRemove
|
||||||
from aiogram.exceptions import AiogramError
|
from aiogram.exceptions import AiogramError
|
||||||
from aiogram.fsm.state import State, StatesGroup
|
|
||||||
from aiogram.fsm.context import FSMContext
|
from aiogram.fsm.context import FSMContext
|
||||||
|
from sqlalchemy import select
|
||||||
from sqlalchemy import select, insert
|
|
||||||
from loguru import logger
|
from loguru import logger
|
||||||
from filters import IsAdmin
|
from keyboards import create_inline_kb, button_create
|
||||||
from keyboards import create_inline_kb, commands, button_create
|
|
||||||
from database import async_session_, Order, Worker
|
from database import async_session_, Order, Worker
|
||||||
|
from FSM import SearchForm, OrderForm
|
||||||
|
|
||||||
orders_router = Router()
|
orders_router = Router()
|
||||||
|
|
||||||
# orders_router.message.filter()
|
|
||||||
|
|
||||||
order_operation_base = {"add_order_photo": "Добавить фото",
|
order_operation_base = {"add_order_photo": "Добавить фото",
|
||||||
"get_order_photo": "Получить фото",
|
"get_order_photo": "Получить фото",
|
||||||
"get_order_components": "Получить список комплектующих",
|
"get_order_components": "Получить список комплектующих",
|
||||||
"get_order_documentation": "Получить документацию"
|
"get_order_documentation": "Получить документацию",
|
||||||
|
"finish_work_on_order": "❌ Закрыть"
|
||||||
}
|
}
|
||||||
order_operation_update = {"add_order_documentation": "Добавить документацию"}
|
order_operation_update = {"add_order_documentation": "Добавить документацию"}
|
||||||
|
|
||||||
order_main = {"find_orders": "Найти заказ"}
|
order_main = {"find_orders": "Найти заказ", "create_order": "Создать заказ"}
|
||||||
order_main_update = {"create_order": "Создать заказ"}
|
order_main_update = {"create_order": "Создать заказ"}
|
||||||
|
|
||||||
find_order_params = {"search_by_name": "Поиск по названию", "search_by_description": "Поиск по описанию ",
|
find_order_params = {"search_by_name": "Поиск по названию", "search_by_description": "Поиск по описанию ",
|
||||||
"search_by_id": "Поиск по номеру заказа", "search_by_customer": "Поиск по заказчику"}
|
"search_by_id": "Поиск по номеру заказа", "search_by_customer": "Поиск по заказчику"}
|
||||||
|
|
||||||
|
|
||||||
class SearchForm(StatesGroup):
|
|
||||||
search_option = State()
|
|
||||||
data_to_search = State()
|
|
||||||
search_result = State()
|
|
||||||
|
|
||||||
|
|
||||||
class OrderForm(StatesGroup):
|
|
||||||
id = State()
|
|
||||||
worker_id = State()
|
|
||||||
status_id = State()
|
|
||||||
counterparty = State()
|
|
||||||
customer = State()
|
|
||||||
commencement_work = State()
|
|
||||||
end_work = State()
|
|
||||||
|
|
||||||
description = State()
|
|
||||||
|
|
||||||
|
|
||||||
@orders_router.message(Command(commands="orders"))
|
@orders_router.message(Command(commands="orders"))
|
||||||
async def orders_menu(message: Message):
|
async def orders_menu(message: Message):
|
||||||
order_main_upd = order_main_update if await IsAdmin()(message) else {}
|
|
||||||
await message.answer(text="Доступные действия с заказами:",
|
await message.answer(text="Доступные действия с заказами:",
|
||||||
reply_markup=create_inline_kb(width=1, **order_main, **order_main_upd))
|
reply_markup=create_inline_kb(width=1, **order_main))
|
||||||
|
await message.delete()
|
||||||
|
|
||||||
|
|
||||||
@orders_router.callback_query(lambda x: x.data.startswith("create_order"))
|
@orders_router.callback_query(lambda x: x.data.startswith("create_order"))
|
||||||
@@ -86,10 +64,6 @@ async def get_order_customer(callback: CallbackQuery, state: FSMContext):
|
|||||||
await state.set_state(OrderForm.customer)
|
await state.set_state(OrderForm.customer)
|
||||||
|
|
||||||
|
|
||||||
# @orders_router.callback_query(OrderForm.counterparty)
|
|
||||||
# async def get_order_customer(message: Message, state: FSMContext):
|
|
||||||
#
|
|
||||||
|
|
||||||
@orders_router.message(OrderForm.customer)
|
@orders_router.message(OrderForm.customer)
|
||||||
async def order_description(message: Message, state: FSMContext):
|
async def order_description(message: Message, state: FSMContext):
|
||||||
await message.answer("Введите описание заказа в виде ключевых слов (АВР, ПСС, НКУ и т.д.) )")
|
await message.answer("Введите описание заказа в виде ключевых слов (АВР, ПСС, НКУ и т.д.) )")
|
||||||
@@ -136,33 +110,30 @@ async def search_by_item(message: Message, state: FSMContext):
|
|||||||
selected_orders = result.scalars().all()
|
selected_orders = result.scalars().all()
|
||||||
|
|
||||||
if selected_orders:
|
if selected_orders:
|
||||||
await message.answer(text="Список найденных заказов: ",
|
await message.answer(text="Список найденных заказов: ")
|
||||||
reply_markup=create_inline_kb(width=1, **dict(
|
sent_messages = []
|
||||||
(f"show_order_{order.id}", f"Описание: {order.description or "Отсутствует"}"
|
for order in selected_orders:
|
||||||
f"Заказ: №{order.id}\n"
|
sent_messages.append(await message.answer(text=f"Номер заказа: {order.id}\n"
|
||||||
f"Заказчик: {order.customer}\n"
|
f"Заказчик: {order.customer}\n"
|
||||||
) for order in
|
f"Статус: {order.status_id}\n"
|
||||||
selected_orders)))
|
f"Дата отгрузки: {order.end_work}\n"
|
||||||
await state.update_data(search_result=selected_orders)
|
f"Дата создания: {order.created_at}\n"
|
||||||
|
f"Описание: {order.description}",
|
||||||
|
reply_markup=create_inline_kb(width=1, **{
|
||||||
|
f"show_order_{order.id}": f"Заказ: №{order.id}"})))
|
||||||
|
await state.update_data(sent_messages=sent_messages)
|
||||||
await state.set_state(SearchForm.search_result)
|
await state.set_state(SearchForm.search_result)
|
||||||
|
await state.update_data(search_result=selected_orders)
|
||||||
else:
|
else:
|
||||||
await message.answer(text="Заказов по вашему запросу не найдено")
|
await message.answer(text="Заказов по вашему запросу не найдено")
|
||||||
await state.clear()
|
await state.clear()
|
||||||
|
|
||||||
|
|
||||||
@orders_router.callback_query(SearchForm.search_result)
|
@orders_router.callback_query(SearchForm.search_result and (lambda x: "show_order_" in x.data))
|
||||||
async def show_order(callback: CallbackQuery, state: FSMContext):
|
async def show_order(callback: CallbackQuery, state: FSMContext, bot: Bot):
|
||||||
order_id = int(re.search(r"(\d+)", callback.data).group())
|
order_id = int(re.search(r"(\d+)", callback.data).group())
|
||||||
|
orders = await state.get_value("search_result")
|
||||||
try:
|
order = next(filter(lambda item: order_id == item.id, orders), None)
|
||||||
async with async_session_() as local_session:
|
|
||||||
result = await local_session.execute(select(Order).filter(Order.id == order_id))
|
|
||||||
order = result.scalars().first()
|
|
||||||
|
|
||||||
except Exception as err:
|
|
||||||
logger.warning(err)
|
|
||||||
|
|
||||||
order_operation_upd = order_operation_update if await IsAdmin()(callback) else {}
|
|
||||||
|
|
||||||
if order:
|
if order:
|
||||||
await callback.message.answer(text=f"Номер заказа: {order.id}\n"
|
await callback.message.answer(text=f"Номер заказа: {order.id}\n"
|
||||||
@@ -172,21 +143,22 @@ async def show_order(callback: CallbackQuery, state: FSMContext):
|
|||||||
f"Дата отгрузки: {order.end_work}\n"
|
f"Дата отгрузки: {order.end_work}\n"
|
||||||
f"Дата создания: {order.created_at}\n"
|
f"Дата создания: {order.created_at}\n"
|
||||||
f"Описание: {order.description}",
|
f"Описание: {order.description}",
|
||||||
reply_markup=create_inline_kb(width=2, **dict(
|
reply_markup=create_inline_kb(width=1, **dict(
|
||||||
(f"{clbk}_{order.id}", text) for clbk, text in order_operation_base.items()))
|
(f"{clbk}_{order.id}", text) for clbk, text in order_operation_base.items()))
|
||||||
)
|
)
|
||||||
|
|
||||||
await callback.message.delete()
|
for message in await state.get_value("sent_messages"):
|
||||||
|
await bot.delete_message(chat_id=callback.message.chat.id, message_id=message.message_id)
|
||||||
await state.clear()
|
await state.clear()
|
||||||
|
|
||||||
|
|
||||||
@orders_router.callback_query(lambda x: x.data.startswith("get_order_photo"))
|
@orders_router.callback_query(lambda x: x.data.startswith("get_order_photo"))
|
||||||
async def send_order_photos(callback: CallbackQuery, bot: Bot):
|
async def send_order_photos(callback: CallbackQuery, bot: Bot):
|
||||||
order_id = callback.data.split("_")[-1]
|
order_id = callback.data.split("_")[-1]
|
||||||
media_item: Path
|
|
||||||
media_group = []
|
media_group = []
|
||||||
os.makedirs(Path(f"./photos/{order_id}/"), exist_ok=True)
|
order_photos_path = Path(f"/app/photos/{order_id}/")
|
||||||
media_path = Path(f"./photos/{order_id}/").iterdir()
|
os.makedirs(order_photos_path, exist_ok=True)
|
||||||
|
media_path = order_photos_path.iterdir()
|
||||||
if not (media_item := next(media_path, None)):
|
if not (media_item := next(media_path, None)):
|
||||||
text = f"Фото по заказу \"{order_id}\" отсутствуют "
|
text = f"Фото по заказу \"{order_id}\" отсутствуют "
|
||||||
else:
|
else:
|
||||||
@@ -194,7 +166,7 @@ async def send_order_photos(callback: CallbackQuery, bot: Bot):
|
|||||||
f"")
|
f"")
|
||||||
await bot.send_message(chat_id=callback.from_user.id, text=text)
|
await bot.send_message(chat_id=callback.from_user.id, text=text)
|
||||||
while media_item or media_group:
|
while media_item or media_group:
|
||||||
if len(media_group) == 10 or (media_group and not media_item):
|
if len(media_group) == 10 or not media_item:
|
||||||
await bot.send_media_group(chat_id=callback.from_user.id, media=media_group)
|
await bot.send_media_group(chat_id=callback.from_user.id, media=media_group)
|
||||||
media_group.clear()
|
media_group.clear()
|
||||||
if media_item:
|
if media_item:
|
||||||
@@ -205,8 +177,10 @@ async def send_order_photos(callback: CallbackQuery, bot: Bot):
|
|||||||
logger.error(f"Ошибка при обработке {media_path}: {err}")
|
logger.error(f"Ошибка при обработке {media_path}: {err}")
|
||||||
|
|
||||||
media_item = next(media_path, None)
|
media_item = next(media_path, None)
|
||||||
await asyncio.sleep(600)
|
try:
|
||||||
await callback.message.delete()
|
pass
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
@orders_router.callback_query(lambda x: x.data.startswith("add_order_photo"))
|
@orders_router.callback_query(lambda x: x.data.startswith("add_order_photo"))
|
||||||
@@ -221,7 +195,7 @@ async def reply_for_photo(callback: CallbackQuery, bot: Bot):
|
|||||||
F.reply_to_message)
|
F.reply_to_message)
|
||||||
async def add_order_photo(message: Message, bot: Bot):
|
async def add_order_photo(message: Message, bot: Bot):
|
||||||
order_id = re.search(r"(\d+)", message.reply_to_message.text).group()
|
order_id = re.search(r"(\d+)", message.reply_to_message.text).group()
|
||||||
order_photos_path = f"/app/photos/{order_id}/"
|
order_photos_path = Path(f"/app/photos/{order_id}/")
|
||||||
os.makedirs(order_photos_path, exist_ok=True)
|
os.makedirs(order_photos_path, exist_ok=True)
|
||||||
|
|
||||||
item = message.video or message.photo[-1]
|
item = message.video or message.photo[-1]
|
||||||
@@ -241,3 +215,8 @@ async def add_order_photo(message: Message, bot: Bot):
|
|||||||
await bot.delete_message(chat_id=message.chat.id, message_id=message.reply_to_message.message_id)
|
await bot.delete_message(chat_id=message.chat.id, message_id=message.reply_to_message.message_id)
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@orders_router.callback_query(F.data.startswith("finish_work_on_order"))
|
||||||
|
async def finish_work_on_order(callback: CallbackQuery):
|
||||||
|
await callback.message.delete()
|
||||||
|
|||||||
@@ -1,17 +1,18 @@
|
|||||||
import os
|
import os
|
||||||
from asyncio import Event, wait_for, TimeoutError
|
from asyncio import Event, wait_for, TimeoutError
|
||||||
|
|
||||||
from aiogram import Router, Bot
|
from aiogram import Router, Bot
|
||||||
from aiogram.filters import CommandStart
|
from aiogram.filters import CommandStart
|
||||||
from aiogram.types import Message, User
|
from aiogram.types import Message, User
|
||||||
|
|
||||||
from sqlalchemy import insert, select
|
from sqlalchemy import insert, select
|
||||||
|
from loguru import logger
|
||||||
from keyboards import create_inline_kb
|
from keyboards import create_inline_kb
|
||||||
from database import async_session_, Worker
|
from database import async_session_, Worker
|
||||||
|
from filters import IsRegister
|
||||||
|
|
||||||
|
|
||||||
registration_router = Router()
|
registration_router = Router()
|
||||||
|
|
||||||
|
registration_router.message.filter(IsRegister() or CommandStart())
|
||||||
registration_confirm: dict[int, Event] = {}
|
registration_confirm: dict[int, Event] = {}
|
||||||
user_info_template = ("Новый пользователь ждет регистрации:\n"
|
user_info_template = ("Новый пользователь ждет регистрации:\n"
|
||||||
"Имя: {}\n"
|
"Имя: {}\n"
|
||||||
@@ -19,28 +20,29 @@ user_info_template = ("Новый пользователь ждет регист
|
|||||||
"Юзернейм: @{}\n"
|
"Юзернейм: @{}\n"
|
||||||
"ID: @msg_{}\n")
|
"ID: @msg_{}\n")
|
||||||
|
|
||||||
admins_ids = list(map(int, os.getenv("BOT_ADMINS").split(",")))
|
|
||||||
|
|
||||||
|
|
||||||
@registration_router.message(CommandStart())
|
@registration_router.message(CommandStart())
|
||||||
async def registration_command(message: Message, bot: Bot):
|
async def start_command(message: Message, bot: Bot):
|
||||||
async with async_session_() as session:
|
async with async_session_() as session:
|
||||||
async with session.begin():
|
|
||||||
result = await session.execute(select(Worker).where(Worker.telegram_id == message.from_user.id))
|
result = await session.execute(select(Worker).where(Worker.telegram_id == message.from_user.id))
|
||||||
user = result.scalars().first()
|
user = result.scalars().first()
|
||||||
if not user:
|
if not user:
|
||||||
|
|
||||||
user = message.from_user
|
user = message.from_user
|
||||||
dict_for_inline = {f'reg_@{user.id}': 'Allow', f'del_@{user.id}': 'Reject'}
|
dict_for_inline = {f'reg_@{user.id}': 'Allow', f'del_@{user.id}': 'Reject'}
|
||||||
user_info = user_info_template.format(user.first_name, user.last_name if user.last_name else 'Не указана',
|
user_info = user_info_template.format(user.first_name, user.last_name if user.last_name else 'Не указана',
|
||||||
user.username if user.username else 'Не указан', user.id)
|
user.username if user.username else 'Не указан', user.id)
|
||||||
for admin in admins_ids:
|
for admin in list(map(int, os.getenv("BOT_ADMINS").split(","))):
|
||||||
try:
|
try:
|
||||||
await bot.send_message(chat_id=admin, text=user_info)
|
await bot.send_message(chat_id=admin, text=user_info)
|
||||||
await bot.send_message(chat_id=admin, text='Зарегистрировать пользователя',
|
await bot.send_message(chat_id=admin, text='Зарегистрировать пользователя',
|
||||||
reply_markup=create_inline_kb(width=2, **dict_for_inline))
|
reply_markup=create_inline_kb(width=2, **dict_for_inline))
|
||||||
except Exception as err:
|
await message.answer("Запрос на регистрацию отправлен администратору, ожидайте подтверждения.")
|
||||||
pass
|
|
||||||
|
except Exception:
|
||||||
|
logger.error(f"{start_command.__name__} failed")
|
||||||
|
|
||||||
reg_confirm = Event()
|
reg_confirm = Event()
|
||||||
registration_confirm[user.id] = reg_confirm
|
registration_confirm[user.id] = reg_confirm
|
||||||
try:
|
try:
|
||||||
@@ -49,7 +51,7 @@ async def registration_command(message: Message, bot: Bot):
|
|||||||
async with local_session.begin():
|
async with local_session.begin():
|
||||||
local_session.add(Worker(telegram_id=user.id, name=user.first_name))
|
local_session.add(Worker(telegram_id=user.id, name=user.first_name))
|
||||||
|
|
||||||
await message.answer("Регистрация подтверждена")
|
await message.answer("Регистрация подтверждена, для просмотра доступных действий нажмите кнопку 'MENU'")
|
||||||
except TimeoutError:
|
except TimeoutError:
|
||||||
await message.answer("Время ожидания истекло.")
|
await message.answer("Время ожидания истекло.")
|
||||||
|
|
||||||
@@ -57,3 +59,8 @@ async def registration_command(message: Message, bot: Bot):
|
|||||||
|
|
||||||
else:
|
else:
|
||||||
await message.answer("Работа бота возобновлена")
|
await message.answer("Работа бота возобновлена")
|
||||||
|
|
||||||
|
|
||||||
|
@registration_router.message()
|
||||||
|
async def catch_message(message: Message):
|
||||||
|
await message.answer("Для работы с ботом, требуется регистрация\nНажмите /start для регистрации")
|
||||||
@@ -1,12 +1,14 @@
|
|||||||
import os
|
import os
|
||||||
import asyncio
|
import asyncio
|
||||||
from dotenv import load_dotenv
|
from dotenv import load_dotenv
|
||||||
|
|
||||||
|
load_dotenv(".env")
|
||||||
|
|
||||||
from aiogram import Dispatcher, Bot
|
from aiogram import Dispatcher, Bot
|
||||||
from handlers import *
|
from handlers import *
|
||||||
from keyboards import set_main_menu
|
from keyboards import set_main_menu
|
||||||
from middlewares import AccessCheckMiddleware
|
from middlewares import SessionMiddleware
|
||||||
|
|
||||||
load_dotenv(".env")
|
|
||||||
bot = Bot(token=os.getenv("TOKEN"))
|
bot = Bot(token=os.getenv("TOKEN"))
|
||||||
|
|
||||||
|
|
||||||
@@ -16,7 +18,7 @@ async def main() -> None:
|
|||||||
dp.startup.register(set_main_menu)
|
dp.startup.register(set_main_menu)
|
||||||
dp.include_router(registration_router)
|
dp.include_router(registration_router)
|
||||||
dp.include_router(admin_router)
|
dp.include_router(admin_router)
|
||||||
dp.update.outer_middleware(AccessCheckMiddleware())
|
dp.update.outer_middleware(SessionMiddleware())
|
||||||
dp.include_router(orders_router)
|
dp.include_router(orders_router)
|
||||||
dp.include_router(components_router)
|
dp.include_router(components_router)
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
from .outer_middlewares import AccessCheckMiddleware
|
from .outer_middlewares import SessionMiddleware
|
||||||
|
|
||||||
|
|
||||||
__all__ = ["AccessCheckMiddleware"]
|
__all__ = ["SessionMiddleware"]
|
||||||
@@ -1,29 +1,29 @@
|
|||||||
import logging
|
|
||||||
from typing import Any, Awaitable, Callable, Dict
|
from typing import Any, Awaitable, Callable, Dict
|
||||||
from aiogram import BaseMiddleware, Bot
|
from aiogram import BaseMiddleware, Bot
|
||||||
from aiogram.types import TelegramObject
|
from aiogram.types import TelegramObject
|
||||||
from database import async_session_, Worker
|
|
||||||
from sqlalchemy import select
|
from sqlalchemy import select
|
||||||
|
from loguru import logger
|
||||||
|
from database import async_session_, Worker
|
||||||
|
|
||||||
|
|
||||||
|
class SessionMiddleware(BaseMiddleware):
|
||||||
class AccessCheckMiddleware(BaseMiddleware):
|
|
||||||
sessions_in_memory_db = set()
|
sessions_in_memory_db = set()
|
||||||
|
|
||||||
async def __call__(
|
async def __call__(
|
||||||
self,
|
self,
|
||||||
handler: Callable[[TelegramObject, Dict[str, Any]], Awaitable[Any]],
|
handler: Callable[[TelegramObject, Dict[str, Any]], Awaitable[Any]],
|
||||||
event: TelegramObject,
|
event: TelegramObject,
|
||||||
data: Dict[str, Any]
|
data: Dict[str, Any]
|
||||||
) -> Any:
|
) -> Any:
|
||||||
|
logger.info("Session check")
|
||||||
event_data = event.message or event.callback_query
|
event_data = event.message or event.callback_query
|
||||||
user = event_data.from_user.id
|
user = event_data.from_user.id
|
||||||
if user not in self.sessions_in_memory_db:
|
if user not in self.sessions_in_memory_db:
|
||||||
async with async_session_() as session:
|
async with async_session_() as session:
|
||||||
async with session.begin():
|
|
||||||
result = await session.execute(select(Worker).where(Worker.telegram_id == event_data.from_user.id))
|
result = await session.execute(select(Worker).where(Worker.telegram_id == event_data.from_user.id))
|
||||||
user = result.scalars().first()
|
user_in_db = result.scalars().first()
|
||||||
if user:
|
if not user_in_db:
|
||||||
self.sessions_in_memory_db.add(event_data.from_user.id)
|
data["through_registration"] = True
|
||||||
|
else:
|
||||||
|
self.sessions_in_memory_db.add(user)
|
||||||
return await handler(event, data)
|
return await handler(event, data)
|
||||||
return None
|
|
||||||
|
|
||||||
|
|||||||
37
drone.yaml
37
drone.yaml
@@ -20,28 +20,35 @@ steps:
|
|||||||
- docker build -t myapp:${DRONE_COMMIT_SHA} .
|
- docker build -t myapp:${DRONE_COMMIT_SHA} .
|
||||||
|
|
||||||
- name: deploy
|
- name: deploy
|
||||||
image: alpine
|
image: docker
|
||||||
|
volumes:
|
||||||
|
- name: dockersock
|
||||||
|
path: /var/run/docker.sock
|
||||||
|
- name: env
|
||||||
|
path: /srv/prod/telegram_bot/
|
||||||
environment:
|
environment:
|
||||||
ENV_CONTENT:
|
TOKEN:
|
||||||
from_secret: DOT_ENV_CONTENT
|
from_secret: TOKEN
|
||||||
|
BOT_ADMINS:
|
||||||
|
from_secret: BOT_ADMINS
|
||||||
|
DATABASE:
|
||||||
|
from_secret: DATABASE
|
||||||
|
DB_HOST:
|
||||||
|
from_secret: DB_HOST
|
||||||
|
DB_USER:
|
||||||
|
from_secret: DB_USER
|
||||||
|
DB_PASSWORD:
|
||||||
|
from_secret: DB_PASSWORD
|
||||||
commands:
|
commands:
|
||||||
- apk add --no-cache openssh
|
|
||||||
- echo "$ENV_CONTENT" > .env
|
|
||||||
settings:
|
|
||||||
host: localhost
|
|
||||||
username: ronis_0505
|
|
||||||
password: 667766
|
|
||||||
script:
|
|
||||||
- docker pull myapp:${DRONE_COMMIT_SHA}
|
|
||||||
- docker stop myapp || true
|
- docker stop myapp || true
|
||||||
- docker rm myapp || true
|
- docker rm myapp || true
|
||||||
- docker run -d --name myapp \
|
- docker run --name=myapp -d --network=prod_net -v /srv/prod/telegram_bot/photos:/app/photos/ -v /srv/prod/telegram_bot/.env:/app/.env:ro myapp:${DRONE_COMMIT_SHA}
|
||||||
--network prod_net \
|
|
||||||
-v /srv/prod/telegram_bot/photos:/app/photos/ \
|
|
||||||
myapp:${DRONE_COMMIT_SHA}
|
|
||||||
|
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
- name: dockersock
|
- name: dockersock
|
||||||
host:
|
host:
|
||||||
path: /var/run/docker.sock
|
path: /var/run/docker.sock
|
||||||
|
- name: env
|
||||||
|
host:
|
||||||
|
path: /srv/prod/telegram_bot/
|
||||||
Reference in New Issue
Block a user