From 5453efadb531bbb17e1600e4769c93bf828e59f0 Mon Sep 17 00:00:00 2001
From: Legacyyy777 <162005411+Legacyyy777@users.noreply.github.com>
Date: Wed, 17 Sep 2025 16:07:56 +0500
Subject: [PATCH 1/3] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?=
=?UTF-8?q?=D0=BD=20=D1=84=D0=B0=D0=B9=D0=BB=20=D0=BA=D0=BE=D0=BD=D1=84?=
=?UTF-8?q?=D0=B8=D0=B3=D1=83=D1=80=D0=B0=D1=86=D0=B8=D0=B8=20=D0=B4=D0=BB?=
=?UTF-8?q?=D1=8F=20=D0=B0=D0=B2=D1=82=D0=BE=D0=BC=D0=B0=D1=82=D0=B8=D1=87?=
=?UTF-8?q?=D0=B5=D1=81=D0=BA=D0=BE=D0=B3=D0=BE=20=D0=B4=D0=B5=D0=BF=D0=BB?=
=?UTF-8?q?=D0=BE=D1=8F=20=D0=B1=D0=BE=D1=82=D0=B0=20=D0=BD=D0=B0=20VPS=20?=
=?UTF-8?q?=D0=BF=D1=80=D0=B8=20=D0=BF=D1=83=D1=88=D0=B5=20=D0=B2=20=D0=B2?=
=?UTF-8?q?=D0=B5=D1=82=D0=BA=D1=83=20DEV.?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.github/workflows/deploy.yml | 37 ++++++++++++++++++++++++++++++++++++
1 file changed, 37 insertions(+)
create mode 100644 .github/workflows/deploy.yml
diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml
new file mode 100644
index 00000000..2e158c49
--- /dev/null
+++ b/.github/workflows/deploy.yml
@@ -0,0 +1,37 @@
+name: Deploy Bot
+
+on:
+ push:
+ branches:
+ - DEV # деплой только при пуше в DEV
+
+jobs:
+ deploy:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout repo
+ uses: actions/checkout@v3
+
+ - name: Deploy to VPS
+ uses: appleboy/ssh-action@v1.0.3
+ with:
+ host: ${{ secrets.VPS_HOST }}
+ username: ${{ secrets.VPS_USER }}
+ key: ${{ secrets.VPS_SSH_KEY }}
+ script: |
+ # если папки ещё нет — клонируем
+ if [ ! -d /opt/mybot/.git ]; then
+ rm -rf /opt/mybot
+ git clone https://github.com/Legacyyy777/remnawave-bedolaga-telegram-bot_777.git /opt/mybot
+ fi
+
+ cd /opt/mybot
+
+ # обновляем и переключаемся на DEV
+ git fetch origin
+ git checkout DEV
+ git reset --hard origin/DEV
+
+ # пересобираем и запускаем контейнер
+ docker compose build --no-cache
+ docker compose up -d --force-recreate
From d29ad223a75c3dc260dc0f6b9644aa478a410fe4 Mon Sep 17 00:00:00 2001
From: Legacyyy777 <162005411+Legacyyy777@users.noreply.github.com>
Date: Wed, 17 Sep 2025 19:22:43 +0500
Subject: [PATCH 2/3] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?=
=?UTF-8?q?=D0=BD=D0=BE=20=D1=83=D0=B2=D0=B5=D0=B4=D0=BE=D0=BC=D0=BB=D0=B5?=
=?UTF-8?q?=D0=BD=D0=B8=D0=B5=20=D0=BF=D0=BE=D0=BB=D1=8C=D0=B7=D0=BE=D0=B2?=
=?UTF-8?q?=D0=B0=D1=82=D0=B5=D0=BB=D1=8E=20=D0=BE=20=D0=BF=D0=BE=D0=BF?=
=?UTF-8?q?=D0=BE=D0=BB=D0=BD=D0=B5=D0=BD=D0=B8=D0=B8/=D1=81=D0=BF=D0=B8?=
=?UTF-8?q?=D1=81=D0=B0=D0=BD=D0=B8=D0=B8=20=D0=B1=D0=B0=D0=BB=D0=B0=D0=BD?=
=?UTF-8?q?=D1=81=D0=B0.=20=D0=A0=D0=B5=D0=B0=D0=BB=D0=B8=D0=B7=D0=BE?=
=?UTF-8?q?=D0=B2=D0=B0=D0=BD=D0=B0=20=D0=BE=D1=82=D0=BF=D1=80=D0=B0=D0=B2?=
=?UTF-8?q?=D0=BA=D0=B0=20=D1=81=D0=BE=D0=BE=D0=B1=D1=89=D0=B5=D0=BD=D0=B8?=
=?UTF-8?q?=D0=B9=20=D1=87=D0=B5=D1=80=D0=B5=D0=B7=20Telegram-=D0=B1=D0=BE?=
=?UTF-8?q?=D1=82=D0=B0=20=D1=81=20=D0=B8=D0=BD=D1=84=D0=BE=D1=80=D0=BC?=
=?UTF-8?q?=D0=B0=D1=86=D0=B8=D0=B5=D0=B9=20=D0=BE=20=D1=82=D1=80=D0=B0?=
=?UTF-8?q?=D0=BD=D0=B7=D0=B0=D0=BA=D1=86=D0=B8=D0=B8=20=D0=B8=20=D0=B0?=
=?UTF-8?q?=D0=B4=D0=BC=D0=B8=D0=BD=D0=B8=D1=81=D1=82=D1=80=D0=B0=D1=82?=
=?UTF-8?q?=D0=BE=D1=80=D0=B5,=20=D0=B2=D1=8B=D0=BF=D0=BE=D0=BB=D0=BD?=
=?UTF-8?q?=D0=B8=D0=B2=D1=88=D0=B5=D0=BC=20=D0=BE=D0=BF=D0=B5=D1=80=D0=B0?=
=?UTF-8?q?=D1=86=D0=B8=D1=8E.?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
app/handlers/admin/users.py | 3 +-
app/services/user_service.py | 80 ++++++++++++++++++++++++++++++++++--
2 files changed, 79 insertions(+), 4 deletions(-)
diff --git a/app/handlers/admin/users.py b/app/handlers/admin/users.py
index d0e858e4..9b7a9c2a 100644
--- a/app/handlers/admin/users.py
+++ b/app/handlers/admin/users.py
@@ -685,7 +685,8 @@ async def process_balance_edit(
description = f"Списание администратором: {int(amount_rubles)} ₽"
success = await user_service.update_user_balance(
- db, user_id, amount_kopeks, description, db_user.id
+ db, user_id, amount_kopeks, description, db_user.id,
+ bot=message.bot, admin_name=db_user.full_name
)
if success:
diff --git a/app/services/user_service.py b/app/services/user_service.py
index 0c65fde0..f26e14b2 100644
--- a/app/services/user_service.py
+++ b/app/services/user_service.py
@@ -3,6 +3,8 @@ from datetime import datetime, timedelta
from typing import Optional, List, Dict, Any
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import delete, select, update
+from aiogram import Bot
+from aiogram.exceptions import TelegramBadRequest, TelegramForbiddenError
from app.database.crud.user import (
get_user_by_id, get_user_by_telegram_id, get_users_list,
get_users_count, get_users_statistics, get_inactive_users,
@@ -23,6 +25,59 @@ logger = logging.getLogger(__name__)
class UserService:
+ async def _send_balance_notification(
+ self,
+ bot: Bot,
+ user: User,
+ amount_kopeks: int,
+ admin_name: str
+ ) -> bool:
+ """Отправляет уведомление пользователю о пополнении/списании баланса"""
+ try:
+ if amount_kopeks > 0:
+ # Пополнение
+ emoji = "💰"
+ action = "пополнен"
+ amount_text = f"+{settings.format_price(amount_kopeks)}"
+ message = (
+ f"{emoji} Баланс пополнен!\n\n"
+ f"💵 Сумма: {amount_text}\n"
+ f"👤 Администратор: {admin_name}\n"
+ f"💳 Текущий баланс: {settings.format_price(user.balance_kopeks)}\n\n"
+ f"Спасибо за использование нашего сервиса! 🎉"
+ )
+ else:
+ # Списание
+ emoji = "💸"
+ action = "списан"
+ amount_text = f"-{settings.format_price(abs(amount_kopeks))}"
+ message = (
+ f"{emoji} Средства списаны с баланса\n\n"
+ f"💵 Сумма: {amount_text}\n"
+ f"👤 Администратор: {admin_name}\n"
+ f"💳 Текущий баланс: {settings.format_price(user.balance_kopeks)}\n\n"
+ f"Если у вас есть вопросы, обратитесь в поддержку."
+ )
+
+ await bot.send_message(
+ chat_id=user.telegram_id,
+ text=message,
+ parse_mode="HTML"
+ )
+
+ logger.info(f"✅ Уведомление о изменении баланса отправлено пользователю {user.telegram_id}")
+ return True
+
+ except TelegramForbiddenError:
+ logger.warning(f"⚠️ Пользователь {user.telegram_id} заблокировал бота")
+ return False
+ except TelegramBadRequest as e:
+ logger.error(f"❌ Ошибка Telegram API при отправке уведомления пользователю {user.telegram_id}: {e}")
+ return False
+ except Exception as e:
+ logger.error(f"❌ Неожиданная ошибка при отправке уведомления пользователю {user.telegram_id}: {e}")
+ return False
+
async def get_user_profile(
self,
db: AsyncSession,
@@ -128,22 +183,41 @@ class UserService:
user_id: int,
amount_kopeks: int,
description: str,
- admin_id: int
+ admin_id: int,
+ bot: Optional[Bot] = None,
+ admin_name: Optional[str] = None
) -> bool:
try:
user = await get_user_by_id(db, user_id)
if not user:
return False
+ # Сохраняем старый баланс для уведомления
+ old_balance = user.balance_kopeks
+
if amount_kopeks > 0:
await add_user_balance(db, user, amount_kopeks, description=description)
logger.info(f"Админ {admin_id} пополнил баланс пользователя {user_id} на {amount_kopeks/100}₽")
- return True
+ success = True
else:
success = await subtract_user_balance(db, user, abs(amount_kopeks), description)
if success:
logger.info(f"Админ {admin_id} списал с баланса пользователя {user_id} {abs(amount_kopeks)/100}₽")
- return success
+
+ # Отправляем уведомление пользователю, если операция прошла успешно
+ if success and bot:
+ # Обновляем пользователя для получения нового баланса
+ await db.refresh(user)
+
+ # Получаем имя администратора
+ if not admin_name:
+ admin_user = await get_user_by_id(db, admin_id)
+ admin_name = admin_user.full_name if admin_user else f"Админ #{admin_id}"
+
+ # Отправляем уведомление (не блокируем операцию если не удалось отправить)
+ await self._send_balance_notification(bot, user, amount_kopeks, admin_name)
+
+ return success
except Exception as e:
logger.error(f"Ошибка изменения баланса пользователя: {e}")
From 5e94b287b90754bf069b8892152e8b4f8f1b9843 Mon Sep 17 00:00:00 2001
From: Egor
Date: Thu, 18 Sep 2025 03:08:50 +0300
Subject: [PATCH 3/3] Delete .github/workflows/deploy.yml
---
.github/workflows/deploy.yml | 37 ------------------------------------
1 file changed, 37 deletions(-)
delete mode 100644 .github/workflows/deploy.yml
diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml
deleted file mode 100644
index 2e158c49..00000000
--- a/.github/workflows/deploy.yml
+++ /dev/null
@@ -1,37 +0,0 @@
-name: Deploy Bot
-
-on:
- push:
- branches:
- - DEV # деплой только при пуше в DEV
-
-jobs:
- deploy:
- runs-on: ubuntu-latest
- steps:
- - name: Checkout repo
- uses: actions/checkout@v3
-
- - name: Deploy to VPS
- uses: appleboy/ssh-action@v1.0.3
- with:
- host: ${{ secrets.VPS_HOST }}
- username: ${{ secrets.VPS_USER }}
- key: ${{ secrets.VPS_SSH_KEY }}
- script: |
- # если папки ещё нет — клонируем
- if [ ! -d /opt/mybot/.git ]; then
- rm -rf /opt/mybot
- git clone https://github.com/Legacyyy777/remnawave-bedolaga-telegram-bot_777.git /opt/mybot
- fi
-
- cd /opt/mybot
-
- # обновляем и переключаемся на DEV
- git fetch origin
- git checkout DEV
- git reset --hard origin/DEV
-
- # пересобираем и запускаем контейнер
- docker compose build --no-cache
- docker compose up -d --force-recreate