diff --git a/.env.example b/.env.example index 4356d6b..fb1983e 100644 --- a/.env.example +++ b/.env.example @@ -10,5 +10,10 @@ LOG_LEVEL="INFO" WEBHOOK_HOST="https://yourdomain.com" SSL_ENABLED=True -SSL_KEY_PATH='' -SSL_CERT_PATH='' \ No newline at end of file +SSL_KEY_PATH="" +SSL_CERT_PATH="" + +# Параметры для Nextcloud +NC_URL="https://yourdomain" +NC_LOGIN="" +NC_PASSWORD="" \ No newline at end of file diff --git a/config/settings.py b/config/settings.py index cce4b0f..82cfbf7 100644 --- a/config/settings.py +++ b/config/settings.py @@ -24,6 +24,11 @@ class Settings(BaseSettings): # Настройки вебхука (опционально для продакшена) WEBHOOK_HOST: Optional[str] = Field(None, description="Публичный URL для вебхука") + # Настройки NextCloud + NC_URL: Optional[str] = Field(None, description="Адрес Nextcloud") + NC_LOGIN: Optional[str] = Field(None, description="Логин Nextcloud") + NC_PASSWORD: Optional[str] = Field(None, description="Пароль Nextcloud") + # Настройки логирования LOG_LEVEL: str = Field("INFO", description="Уровень логирования") diff --git a/handlers/bot_routes/nc_deck_routes.py b/handlers/bot_routes/nc_deck_routes.py new file mode 100644 index 0000000..0dbd21c --- /dev/null +++ b/handlers/bot_routes/nc_deck_routes.py @@ -0,0 +1,18 @@ +from aiogram import Router, types +from aiogram.filters import Command + +from handlers.handler_logging import logger +from handlers.handler_nc_deck import get_decks_in_workspace +from models.model_board import ModelBoard + +nc_deck_router = Router() + + +@nc_deck_router.message(Command("decks")) +async def get_decks(message: types.Message): + logger.info(f"Запрошен список карточек пользователем {message.from_user.id}") + decks_json = await get_decks_in_workspace() + decks = [ModelBoard.model_validate(deck) for deck in decks_json] + await message.answer( + f"Доступные списки: {', '.join([deck.title for deck in decks])}" # TODO: Дебаг + ) diff --git a/handlers/handler_bot.py b/handlers/handler_bot.py index fefa4fb..013d246 100644 --- a/handlers/handler_bot.py +++ b/handlers/handler_bot.py @@ -3,6 +3,7 @@ from config.settings import settings from handlers.bot_routes.base_routes import base_router +from handlers.bot_routes.nc_deck_routes import nc_deck_router from handlers.handler_logging import logger # Инициализация бота @@ -13,6 +14,7 @@ # Регистрируем роутеры бота dispatcher.include_router(base_router) +dispatcher.include_router(nc_deck_router) logger.info("Бот инициализирован") diff --git a/handlers/handler_nc_deck.py b/handlers/handler_nc_deck.py new file mode 100644 index 0000000..5aceccd --- /dev/null +++ b/handlers/handler_nc_deck.py @@ -0,0 +1,43 @@ +import asyncio +from httpx import ( + AsyncClient, + BasicAuth, + HTTPStatusError, + ConnectError, + ConnectTimeout, + ReadTimeout, + NetworkError, +) +from config.settings import settings +from handlers.handler_logging import logger + + +headers = { + "OCS-APIRequest": "true", + "accept": "application/json", +} + +auth = BasicAuth(username=settings.NC_LOGIN, password=settings.NC_PASSWORD) + +DECK_ENDPOINT = "/apps/deck/api/v1.0" + + +async def get_decks_in_workspace(): + BOARD_ENDPOINT = f"{settings.NC_URL}{DECK_ENDPOINT}/boards" + async with AsyncClient(auth=auth, headers=headers) as client: + try: + response = await client.get(url=BOARD_ENDPOINT) + response.raise_for_status() + except HTTPStatusError as err: + logger.error(f"Ошибка статуса: {err}") + except ConnectError: + logger.error( + f"Не удалось установить соединение с сервером {settings.NC_URL}" + ) + except ConnectTimeout: + logger.error(f"Таймаут от сервера {settings.NC_URL}") + except ReadTimeout: + logger.error(f"Таймаут при чтении ответа {settings.NC_URL}") + except NetworkError as err: + logger.error(f"Ошибка сети: {err}") + return response.json() diff --git a/models/model_board.py b/models/model_board.py new file mode 100644 index 0000000..1f64197 --- /dev/null +++ b/models/model_board.py @@ -0,0 +1,62 @@ +from pydantic import BaseModel +from typing import Dict, List, Optional, Union + +# TODO: Референсные данные - удалить после тестов +# "title": "Board title", +# "owner": { +# "primaryKey": "admin", +# "uid": "admin", +# "displayname": "Administrator" +# }, +# "color": "ff0000", +# "archived": false, +# "labels": [], +# "acl": [], +# "permissions": { +# "PERMISSION_READ": true, +# "PERMISSION_EDIT": true, +# "PERMISSION_MANAGE": true, +# "PERMISSION_SHARE": true +# }, +# "users": [], +# "shared": 0, +# "deletedAt": 0, +# "id": 10, +# "lastModified": 1586269585, +# "settings": { +# "notify-due": "off", +# "calendar": true + + +class Owner(BaseModel): + primaryKey: str + uid: str + displayname: str + + +class Permissions(BaseModel): + PERMISSION_READ: bool + PERMISSION_EDIT: bool + PERMISSION_MANAGE: bool + PERMISSION_SHARE: bool + + +class Settings(BaseModel): + notify_due: str + calendar: bool + + +class ModelBoard(BaseModel): + title: str + owner: Owner + color: str + archived: bool + labels: List[str] + acl: List[Dict] + permissions: Permissions + users: List[Dict] + shared: int + deletedAt: int + id: int + lastModified: int + settings: Optional[Union[Settings, List]] = None diff --git a/requirements.txt b/requirements.txt index 4a6dda0..bcd372c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,6 @@ aiogram==3.22.0 -fastapi==0.120.0 +fastapi==0.120.1 +httpx==0.28.1 loguru==0.7.3 pydantic==2.11.4 pydantic_settings==2.11.0