Init project

This commit is contained in:
2026-01-15 09:47:43 +03:00
commit 3e515c66ec
59 changed files with 5101 additions and 0 deletions

View File

@@ -0,0 +1,13 @@
from .cli import get_cli
from .service import NotificationsService
from .settings import NotificationsSettings
__all__ = (
# cli
"get_cli",
# service
"NotificationsService",
# settings
"NotificationsSettings",
)

View File

@@ -0,0 +1,44 @@
import asyncio
import typer
from .service import NotificationsService
from .settings import NotificationsSettings
def callback(ctx: typer.Context):
ctx.obj["settings"] = ctx.obj["settings"].notifications
def run(ctx: typer.Context):
settings: NotificationsSettings = ctx.obj["settings"]
repositories_container: RepositoriesContainer = ctx.obj["repositories_container"]
service = NotificationsService(
settings=settings,
repositories_container=repositories_container,
)
asyncio.run(service.run())
def run_once(ctx: typer.Context):
settings: NotificationsSettings = ctx.obj["settings"]
repositories_container: RepositoriesContainer = ctx.obj["repositories_container"]
service = NotificationsService(
settings=settings,
repositories_container=repositories_container,
)
asyncio.run(service.send_notifications())
def get_cli() -> typer.Typer:
cli = typer.Typer()
cli.callback()(callback)
cli.command(name="run")(run)
cli.command(name="run-once")(run_once)
return cli

View File

@@ -0,0 +1,81 @@
from datetime import date, timedelta
import facet
from aiogram import Bot
from aiogram.enums import ParseMode
from apscheduler.schedulers.asyncio import AsyncIOScheduler
from apscheduler.triggers.cron import CronTrigger
from .settings import NotificationsSettings
class NotificationsService(facet.AsyncioServiceMixin):
def __init__(
self,
settings: NotificationsSettings,
repositories_container: RepositoriesContainer,
):
self._settings = settings
self._repositories_container = repositories_container
self._bot = Bot(token=self._settings.telegram_bot_token)
async def start(self):
scheduler = AsyncIOScheduler()
scheduler.add_job(
func=self.send_notifications,
name="send_notifications",
trigger=CronTrigger.from_crontab(self._settings.cron),
)
scheduler.start()
async def send_notifications(self):
birthday = date.today() + timedelta(days=2)
users_repository = self._repositories_container.users
subscriptions_repository = self._repositories_container.subscriptions
async with users_repository.transaction():
users = await users_repository.get_users_by_birthdays(
birthday=birthday,
)
if not users:
return
async with subscriptions_repository.transaction():
subscriptions = await subscriptions_repository.get_to_users_subscriptions(
to_users_ids={user.id for user in users},
with_from_user=True,
with_to_user=True,
with_pool=True,
)
if not subscriptions:
return
for subscription in subscriptions:
if subscription.from_user.telegram_id is None:
continue
text = (
f"У {subscription.name} скоро день рождения: *{birthday.strftime('%d %B')}*\n\n"
)
if subscription.pool is not None:
if subscription.pool.owner_id == subscription.from_user.id:
text += "Вы собираете деньги на подарок\n\n"
else:
text += (
"Вы подписаны на сбор денег для подарка, вы можете отправить их сюда:\n"
f"_Телефон_: {subscription.pool.payment_data.phone}\n"
f"_Банк_: {subscription.pool.payment_data.bank.value}\n\n"
)
elif subscription.to_user.gift_payment_data is not None:
text += (
f"Вы можете отправить именнинику свой подарок сюда:\n"
f"_Телефон_: {subscription.to_user.gift_payment_data.phone}\n"
f"_Банк_: {subscription.to_user.gift_payment_data.bank.value}\n\n"
)
await self._bot.send_message(
text=text,
parse_mode=ParseMode.MARKDOWN,
chat_id=subscription.from_user.telegram_id,
)

View File

@@ -0,0 +1,6 @@
from pydantic import BaseModel
class NotificationsSettings(BaseModel):
cron: str = "0 12 * * *"
telegram_bot_token: str = "123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11"