mirror of
https://github.com/olegvodyanov/docbot.git
synced 2025-12-19 23:57:05 +03:00
add task
This commit is contained in:
parent
070f446159
commit
6a69c0d4d2
21
new_version.sh
Executable file
21
new_version.sh
Executable file
@ -0,0 +1,21 @@
|
|||||||
|
#/usr/bin/env bash
|
||||||
|
|
||||||
|
set -ex
|
||||||
|
|
||||||
|
stop=$1
|
||||||
|
|
||||||
|
if [[ -z "$stop" ]]; then
|
||||||
|
echo "stopping containers"
|
||||||
|
docker stop chatbot webhook
|
||||||
|
|
||||||
|
docker rm chatbot webhook
|
||||||
|
|
||||||
|
echo "deleting images"
|
||||||
|
docker rmi docbot-webhook docbot-chat
|
||||||
|
|
||||||
|
echo "starting services"
|
||||||
|
docker-compose --progress=plain --profile development up -d
|
||||||
|
else
|
||||||
|
docker-compose --progress=plain --profile development down
|
||||||
|
fi
|
||||||
|
|
||||||
62
poetry.lock
generated
62
poetry.lock
generated
@ -89,6 +89,34 @@ doc = ["Sphinx (>=8.2,<9.0)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)",
|
|||||||
test = ["anyio[trio]", "blockbuster (>=1.5.23)", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "trustme", "truststore (>=0.9.1) ; python_version >= \"3.10\"", "uvloop (>=0.21) ; platform_python_implementation == \"CPython\" and platform_system != \"Windows\" and python_version < \"3.14\""]
|
test = ["anyio[trio]", "blockbuster (>=1.5.23)", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "trustme", "truststore (>=0.9.1) ; python_version >= \"3.10\"", "uvloop (>=0.21) ; platform_python_implementation == \"CPython\" and platform_system != \"Windows\" and python_version < \"3.14\""]
|
||||||
trio = ["trio (>=0.26.1)"]
|
trio = ["trio (>=0.26.1)"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "apscheduler"
|
||||||
|
version = "3.11.0"
|
||||||
|
description = "In-process task scheduler with Cron-like capabilities"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.8"
|
||||||
|
groups = ["main"]
|
||||||
|
files = [
|
||||||
|
{file = "APScheduler-3.11.0-py3-none-any.whl", hash = "sha256:fc134ca32e50f5eadcc4938e3a4545ab19131435e851abb40b34d63d5141c6da"},
|
||||||
|
{file = "apscheduler-3.11.0.tar.gz", hash = "sha256:4c622d250b0955a65d5d0eb91c33e6d43fd879834bf541e0a18661ae60460133"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
tzlocal = ">=3.0"
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
doc = ["packaging", "sphinx", "sphinx-rtd-theme (>=1.3.0)"]
|
||||||
|
etcd = ["etcd3", "protobuf (<=3.21.0)"]
|
||||||
|
gevent = ["gevent"]
|
||||||
|
mongodb = ["pymongo (>=3.0)"]
|
||||||
|
redis = ["redis (>=3.0)"]
|
||||||
|
rethinkdb = ["rethinkdb (>=2.4.0)"]
|
||||||
|
sqlalchemy = ["sqlalchemy (>=1.4)"]
|
||||||
|
test = ["APScheduler[etcd,mongodb,redis,rethinkdb,sqlalchemy,tornado,zookeeper]", "PySide6 ; platform_python_implementation == \"CPython\" and python_version < \"3.14\"", "anyio (>=4.5.2)", "gevent ; python_version < \"3.14\"", "pytest", "pytz", "twisted ; python_version < \"3.14\""]
|
||||||
|
tornado = ["tornado (>=4.3)"]
|
||||||
|
twisted = ["twisted"]
|
||||||
|
zookeeper = ["kazoo"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "asyncpg"
|
name = "asyncpg"
|
||||||
version = "0.30.0"
|
version = "0.30.0"
|
||||||
@ -1111,6 +1139,7 @@ files = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
|
apscheduler = {version = ">=3.10.4,<3.12.0", optional = true, markers = "extra == \"job-queue\""}
|
||||||
httpx = ">=0.27,<1.0"
|
httpx = ">=0.27,<1.0"
|
||||||
|
|
||||||
[package.extras]
|
[package.extras]
|
||||||
@ -1352,6 +1381,37 @@ files = [
|
|||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
typing-extensions = ">=4.12.0"
|
typing-extensions = ">=4.12.0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tzdata"
|
||||||
|
version = "2025.2"
|
||||||
|
description = "Provider of IANA time zone data"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=2"
|
||||||
|
groups = ["main"]
|
||||||
|
markers = "platform_system == \"Windows\""
|
||||||
|
files = [
|
||||||
|
{file = "tzdata-2025.2-py2.py3-none-any.whl", hash = "sha256:1a403fada01ff9221ca8044d701868fa132215d84beb92242d9acd2147f667a8"},
|
||||||
|
{file = "tzdata-2025.2.tar.gz", hash = "sha256:b60a638fcc0daffadf82fe0f57e53d06bdec2f36c4df66280ae79bce6bd6f2b9"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tzlocal"
|
||||||
|
version = "5.3.1"
|
||||||
|
description = "tzinfo object for the local timezone"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.9"
|
||||||
|
groups = ["main"]
|
||||||
|
files = [
|
||||||
|
{file = "tzlocal-5.3.1-py3-none-any.whl", hash = "sha256:eb1a66c3ef5847adf7a834f1be0800581b683b5608e74f86ecbcef8ab91bb85d"},
|
||||||
|
{file = "tzlocal-5.3.1.tar.gz", hash = "sha256:cceffc7edecefea1f595541dbd6e990cb1ea3d19bf01b2809f362a03dd7921fd"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
tzdata = {version = "*", markers = "platform_system == \"Windows\""}
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
devenv = ["check-manifest", "pytest (>=4.3)", "pytest-cov", "pytest-mock (>=3.3)", "zest.releaser"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "uvicorn"
|
name = "uvicorn"
|
||||||
version = "0.34.2"
|
version = "0.34.2"
|
||||||
@ -1597,4 +1657,4 @@ files = [
|
|||||||
[metadata]
|
[metadata]
|
||||||
lock-version = "2.1"
|
lock-version = "2.1"
|
||||||
python-versions = "^3.12"
|
python-versions = "^3.12"
|
||||||
content-hash = "337def2431e36d8fde59d4273d3db93edf87a73ac78c74307f5c44def8c0a04d"
|
content-hash = "33b9101bfbd65f8f77dfaf7e39b2103e7ea7e8c41dbcb72bed9063198e4ed0ca"
|
||||||
|
|||||||
@ -18,7 +18,7 @@ build-backend = "poetry.core.masonry.api"
|
|||||||
|
|
||||||
[tool.poetry.dependencies]
|
[tool.poetry.dependencies]
|
||||||
python = "^3.12"
|
python = "^3.12"
|
||||||
python-telegram-bot = "22.1" # или aiogram v3
|
python-telegram-bot = {extras = ["job-queue"], version = "22.1"}
|
||||||
fastapi = "0.115.12"
|
fastapi = "0.115.12"
|
||||||
uvicorn = {extras = ["standard"], version = "0.34.2"}
|
uvicorn = {extras = ["standard"], version = "0.34.2"}
|
||||||
sqlalchemy = "2.0.41"
|
sqlalchemy = "2.0.41"
|
||||||
|
|||||||
@ -13,6 +13,7 @@ from docbot.handlers.doctors.add_payments_method import get_add_payment_method_h
|
|||||||
from docbot.handlers.utils.help import get_help_handler
|
from docbot.handlers.utils.help import get_help_handler
|
||||||
from docbot.handlers.utils.unknown import get_unknown_handler
|
from docbot.handlers.utils.unknown import get_unknown_handler
|
||||||
from docbot.handlers.utils.cancel_handler import get_cancel_handler
|
from docbot.handlers.utils.cancel_handler import get_cancel_handler
|
||||||
|
from docbot.tasks.payments import map_payments
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
@ -41,6 +42,13 @@ def main():
|
|||||||
app.add_handler(get_unknown_handler())
|
app.add_handler(get_unknown_handler())
|
||||||
|
|
||||||
logger.info("Все хэндлеры зарегистрированы, запускаем polling")
|
logger.info("Все хэндлеры зарегистрированы, запускаем polling")
|
||||||
|
|
||||||
|
logger.info("Запускаем таски")
|
||||||
|
job_queue = app.job_queue
|
||||||
|
|
||||||
|
payments_mapping_task = job_queue.run_repeating(map_payments, interval=60, first=10)
|
||||||
|
logger.info("Таски запущены")
|
||||||
|
|
||||||
app.run_polling()
|
app.run_polling()
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
32
src/docbot/services/payments_service.py
Normal file
32
src/docbot/services/payments_service.py
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
from sqlalchemy import select
|
||||||
|
|
||||||
|
from db.session import AsyncSessionLocal
|
||||||
|
from db.models import (
|
||||||
|
Sessions,
|
||||||
|
PaymentsRegistered
|
||||||
|
)
|
||||||
|
from core.logging import logger
|
||||||
|
|
||||||
|
|
||||||
|
async def save_payment_completed_info_from_prodamus(code: str) -> bool:
|
||||||
|
async with AsyncSessionLocal() as session:
|
||||||
|
async with session.begin():
|
||||||
|
payment_completed = PaymentsRegistered(
|
||||||
|
code=code
|
||||||
|
)
|
||||||
|
session.add(payment_completed)
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
async def get_not_mapped_payments() -> Sequence[Row[Tuple[PaymentsRegistered]]] | None:
|
||||||
|
async with AsyncSessionLocal() as session:
|
||||||
|
result = await session.execute(
|
||||||
|
select(PaymentsRegistered)
|
||||||
|
)
|
||||||
|
|
||||||
|
return result.all()
|
||||||
@ -48,17 +48,6 @@ async def create_session(telegram_id: int, phone: str, consultation_date_time: s
|
|||||||
return code
|
return code
|
||||||
|
|
||||||
|
|
||||||
async def save_payment_completed_info_from_prodamus(code: str) -> bool:
|
|
||||||
async with AsyncSessionLocal() as session:
|
|
||||||
async with session.begin():
|
|
||||||
payment_completed = PaymentsRegistered(
|
|
||||||
code=code
|
|
||||||
)
|
|
||||||
session.add(payment_completed)
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
async def mark_consulted(code: str) -> bool:
|
async def mark_consulted(code: str) -> bool:
|
||||||
"""
|
"""
|
||||||
Отмечает, что консультация получена (добавляет consulted_at).
|
Отмечает, что консультация получена (добавляет consulted_at).
|
||||||
@ -110,3 +99,15 @@ async def get_session_info(code: str) -> dict | None:
|
|||||||
"sent_at": sc.sent_at,
|
"sent_at": sc.sent_at,
|
||||||
"consulted_at": sc.consulted_at,
|
"consulted_at": sc.consulted_at,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async def get_sessions_awaiting_payments() -> Sequence[Row[Sessions]]:
|
||||||
|
async with AsyncSessionLocal() as session:
|
||||||
|
async with session.begin():
|
||||||
|
result = await session.execute(
|
||||||
|
select(Sessions).where(Sessions.paid_at.is_(None))
|
||||||
|
)
|
||||||
|
sc: Sessions | None = result.scalars()
|
||||||
|
if not sc:
|
||||||
|
return False
|
||||||
|
return result.all()
|
||||||
17
src/docbot/tasks/payments.py
Normal file
17
src/docbot/tasks/payments.py
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
from telegram.ext import (
|
||||||
|
ContextTypes
|
||||||
|
)
|
||||||
|
from docbot.services.payments_service import get_not_mapped_payments
|
||||||
|
from docbot.services.session_service import get_sessions_awaiting_payments
|
||||||
|
from core.logging import logger
|
||||||
|
|
||||||
|
# Сопоставляем оплаты, которые пришли от продамуса с сессиями, по которым ещё не было оплаты
|
||||||
|
async def map_payments(context: ContextTypes.DEFAULT_TYPE) -> None:
|
||||||
|
not_mapped_payments: Sequence[Row[PaymentsRegistered]] = await get_not_mapped_payments()
|
||||||
|
sessions_awaiting_payments: Sequence[Row[Sessions]] = await get_sessions_awaiting_payments()
|
||||||
|
|
||||||
|
for payment in not_mapped_payments:
|
||||||
|
logger.info(f"Оплата с продамуса: {payment.PaymentsRegistered.code}")
|
||||||
|
|
||||||
|
for session in sessions_awaiting_payments:
|
||||||
|
logger.info(f"Неоплаченная сессия: {session.Sessions.code}")
|
||||||
@ -1,7 +1,7 @@
|
|||||||
from fastapi import FastAPI, Request, Header, HTTPException
|
from fastapi import FastAPI, Request, Header, HTTPException
|
||||||
from starlette.background import BackgroundTask
|
from starlette.background import BackgroundTask
|
||||||
from typing import Any, Dict
|
from typing import Any, Dict
|
||||||
from docbot.services.session_service import save_payment_completed_info_from_prodamus
|
from docbot.services.payments_service import save_payment_completed_info_from_prodamus
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user