Skip to content

Commit

Permalink
Merge branch 'develop' into refactoring/tasks
Browse files Browse the repository at this point in the history
  • Loading branch information
SabMorgan authored Jul 4, 2023
2 parents 84f4c09 + 743b69d commit 05040aa
Show file tree
Hide file tree
Showing 13 changed files with 138 additions and 523 deletions.
20 changes: 20 additions & 0 deletions .github/ISSUE_TEMPLATE/feature_request.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: ''
assignees: ''

---

### **Why?**

*Зачем выполняется реализация задачи и какую проблему она решает.*

### **How To Do?**

*Как мы выполняем реализацию данной задачи, какие действия нужны для достижения цели.*

### **Where?**

*Где делаем реализацию задачи, какие сервисы задействованы, ссылка на требования, сcылка на API, скриншоты.*
8 changes: 7 additions & 1 deletion src/api/endpoints/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
from .categories import category_router
from .form import form_router
from .notification import users_group_notification_router
from .tasks import task_router

__all__ = ("category_router", "task_router", "form_router")
__all__ = (
"category_router",
"task_router",
"form_router",
"users_group_notification_router",
)
18 changes: 18 additions & 0 deletions src/api/endpoints/notification.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
from fastapi import APIRouter, Depends

from src.api.schemas import TelegramNotificationRequest
from src.api.services.messages import TelegramNotificationService

users_group_notification_router = APIRouter()


@users_group_notification_router.post(
"/",
description="Сообщение для группы пользователей",
)
async def send_telegram_notification(
notifications: TelegramNotificationRequest,
telegram_notification_service: TelegramNotificationService = Depends(),
) -> None:
"""Отправляет сообщение указаной группе пользователей"""
await telegram_notification_service.send_messages_to_group_of_users(notifications)
3 changes: 2 additions & 1 deletion src/api/router.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
from fastapi import APIRouter

from src.api.endpoints import category_router, form_router, task_router
from src.api.endpoints import category_router, form_router, task_router, users_group_notification_router
from src.settings import settings

api_router = APIRouter(prefix=settings.ROOT_PATH)
api_router.include_router(category_router, prefix="/categories", tags=["Categories"])
api_router.include_router(task_router, prefix="/tasks", tags=["Tasks"])
api_router.include_router(form_router, prefix="/telegram", tags=["Forms"])
api_router.include_router(users_group_notification_router, prefix="/messages", tags=["Messages"])
22 changes: 20 additions & 2 deletions src/api/schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

from pydantic import BaseModel, Extra, Field, HttpUrl, NonNegativeInt, StrictStr, root_validator

from src.core.enums import TelegramNotificationUsersGroups

from .constants import DATE_FORMAT


Expand Down Expand Up @@ -90,8 +92,24 @@ class TaskResponse(ResponseBase):
class FeedbackFormQueryParams(BaseModel):
"""Класс формирования параметров запроса для формы обратной связи."""

name: str | None = "Имя"
surname: str | None = "Фамилия"
name: str | None
surname: str | None

def as_url_query(self):
return f"?{urllib.parse.urlencode(self.dict())}"


class TelegramNotificationRequest(RequestBase):
"""Класс формирования параметров запроса для отправки
сообщения определенной группе пользователей."""

message: str = Field(..., min_length=2, max_length=500)
mode: TelegramNotificationUsersGroups

class Config:
schema_extra = {
"example": {
"message": "Type here your message for user",
"mode": "all",
}
}
34 changes: 34 additions & 0 deletions src/api/services/messages.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
from fastapi import Depends
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession
from telegram.ext import Application

from src.bot.bot import create_bot
from src.core.db import get_session
from src.core.db.models import User
from src.core.enums import TelegramNotificationUsersGroups
from src.core.services.notification import TelegramNotification


class TelegramNotificationService:
"""Класс описывающий функционал передачи сообщения
определенному пользователю"""

def __init__(
self,
telegram_bot: Application = Depends(create_bot),
session: AsyncSession = Depends(get_session),
) -> None:
self._session = session
self.telegram_notification = TelegramNotification(telegram_bot)

async def send_messages_to_group_of_users(self, notifications):
"""Отправляет сообщение указанной группе пользователей"""
match notifications.mode.upper():
case TelegramNotificationUsersGroups.ALL.name:
users = await self._session.scalars(select(User))
case TelegramNotificationUsersGroups.SUBSCRIBED.name:
users = await self._session.scalars(select(User).where(User.has_mailing == True)) # noqa
case TelegramNotificationUsersGroups.UNSUBSCRIBED.name:
users = await self._session.scalars(select(User).where(User.has_mailing == False)) # noqa
await self.telegram_notification.send_messages(message=notifications.message, users=users)
1 change: 1 addition & 0 deletions src/bot/constants/urls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
PROCHARITY_URL = "https://procharity.ru/"
8 changes: 6 additions & 2 deletions src/bot/handlers/categories.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from telegram.ext import Application, CallbackQueryHandler, ContextTypes

from src.bot.constants import callback_data
from src.bot.keyboards import get_categories_keyboard
from src.bot.keyboards import get_categories_keyboard, get_open_tasks_and_menu_keyboard
from src.bot.services.category import CategoryService
from src.core.logging.utils import logger_decor
from src.core.services.user import UserService
Expand Down Expand Up @@ -42,12 +42,16 @@ async def confirm_categories_callback(update: Update, context: ContextTypes.DEFA

categories = await user_service.get_user_categories(telegram_id)
if not categories:
await query.message.edit_text(text="Категории не выбраны.")
await query.message.edit_text(
text="Категории не выбраны.",
reply_markup=await get_open_tasks_and_menu_keyboard(),
)
else:
await query.message.edit_text(
text="Отлично! Теперь я буду присылать тебе уведомления о новых "
f"заданиях в категориях: *{', '.join(categories.values())}*.\n\n",
parse_mode=ParseMode.MARKDOWN,
reply_markup=await get_open_tasks_and_menu_keyboard(),
)
await user_service.check_and_set_has_mailing_atribute(telegram_id)

Expand Down
8 changes: 5 additions & 3 deletions src/bot/handlers/registration.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from telegram.constants import ParseMode
from telegram.ext import Application, CallbackQueryHandler, CommandHandler, ContextTypes

from src.bot.constants import commands
from src.bot.constants import callback_data, commands
from src.bot.keyboards import get_confirm_keyboard, get_start_keyboard
from src.core.logging.utils import logger_decor
from src.core.services.user import UserService
Expand All @@ -15,14 +15,16 @@ async def start_command(update: Update, context: ContextTypes.DEFAULT_TYPE):
telegram_id=update.effective_user.id,
username=update.effective_chat.username,
)
keyboard = await get_start_keyboard(telegram_id=update.effective_user.id)
categories = await user_service.get_user_categories(update.effective_user.id)
callback_data_on_start = commands.GREETING_REGISTERED_USER if categories else callback_data.CHANGE_CATEGORY
keyboard = await get_start_keyboard(callback_data_on_start=callback_data_on_start)

await context.bot.send_message(
chat_id=update.effective_user.id,
text="Привет! 👋 \n\n"
'Я бот платформы интеллектуального волонтерства <a href="https://procharity.ru/">ProCharity</a>. '
"Буду держать тебя в курсе новых задач и помогу "
"оперативно связаться с командой поддержки.",
"оперативно связаться с командой поддержки.\n\n",
reply_markup=keyboard,
parse_mode=ParseMode.HTML,
disable_web_page_preview=True,
Expand Down
20 changes: 14 additions & 6 deletions src/bot/keyboards.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from telegram import InlineKeyboardButton, InlineKeyboardMarkup

from src.bot.constants import callback_data, commands
from src.bot.constants import callback_data, urls
from src.core.db.models import Category
from src.core.services.user import UserService

Expand Down Expand Up @@ -66,11 +66,19 @@ async def get_back_menu() -> InlineKeyboardMarkup:
return InlineKeyboardMarkup(keyboard)


async def get_start_keyboard(telegram_id: int) -> InlineKeyboardMarkup:
user_service = UserService()
categories = await user_service.get_user_categories(telegram_id)
callback_const = commands.GREETING_REGISTERED_USER if categories else callback_data.CHANGE_CATEGORY
keyboard = [[InlineKeyboardButton("Начнём", callback_data=callback_const)]]
async def get_start_keyboard(callback_data_on_start: str) -> InlineKeyboardMarkup:
keyboard = [
[InlineKeyboardButton("Начнём", callback_data=callback_data_on_start)],
[InlineKeyboardButton("Перейти на сайт ProCharity", url=urls.PROCHARITY_URL)],
]
return InlineKeyboardMarkup(keyboard)


async def get_open_tasks_and_menu_keyboard() -> InlineKeyboardMarkup:
keyboard = [
[InlineKeyboardButton("Посмотреть открытые задачи", callback_data=callback_data.VIEW_TASKS)],
[InlineKeyboardButton("Открыть меню", callback_data=callback_data.MENU)],
]
return InlineKeyboardMarkup(keyboard)


Expand Down
Loading

0 comments on commit 05040aa

Please sign in to comment.