- Небольшая реорганизация кода в bd

- добавление работы меню ~ в процессе
- Переделал работу tarif_setting
This commit is contained in:
Disledg
2024-10-07 20:38:44 +03:00
parent 0b0d56c045
commit 4dfa80ffae
4 changed files with 173 additions and 74 deletions

109
bot.py
View File

@@ -2,14 +2,15 @@
from telegram import InlineKeyboardButton, InlineKeyboardMarkup, Update from telegram import InlineKeyboardButton, InlineKeyboardMarkup, Update
from telegram.ext import Application, CallbackQueryHandler, CommandHandler, ContextTypes from telegram.ext import Application, CallbackQueryHandler, CommandHandler, ContextTypes
from db import User, VPNServer, Transaction, Subscription from db import User, VPNServer, Transaction, Subscription
from db import last_subscription, create_user , get_sub_list
import db
from sqlalchemy import desc
import json
import string
from datetime import datetime
from db import get_db_session from db import get_db_session
from db import init_db, SessionLocal from db import init_db, SessionLocal
from db_operations import last_subscription, create_user , get_sub_list,buy_sub
from sqlalchemy import desc
import json
from datetime import datetime
from logger_config import setup_logger from logger_config import setup_logger
with open('config.json', 'r') as file: with open('config.json', 'r') as file:
config = json.load(file) config = json.load(file)
@@ -42,19 +43,29 @@ async def personal_account(update: Update, context: ContextTypes.DEFAULT_TYPE) -
session = next(get_db_session()) session = next(get_db_session())
if session.query(User).filter(User.telegram_id == str(update.effective_user.id)).first() == None: if session.query(User).filter(User.telegram_id == str(update.callback_query.from_user.id)).first() == None:
create_user(str(update.effective_user.id),update.effective_user.username) create_user(str(update.callback_query.from_user.id),update.effective_user.username)
user = session.query(User).filter(User.telegram_id == str(update.effective_user.id)).first() user = session.query(User).filter(User.telegram_id == str(update.callback_query.from_user.id)).first()
subscription = last_subscription(session=session,user=user) subscription = last_subscription(session=session,user=user)
loading_message = await context.bot.send_message(chat_id=update.callback_query.message.chat.id, text="Загрузка...")
loading_message_id = loading_message.message_id # Сохраняем ID сообщения
if not subscription: if not subscription:
await update.message.reply_text(f'Профиль {user.username}\nВы не приобретали ещё у нас подписку, но это явно стоит сделать:)',reply_markup=reply_markup) await loading_message_id.edit_text(
# проверяем, истекла ли подписка f'Профиль {user.username}, {user.telegram_id}\nВы не приобретали ещё у нас подписку, но это явно стоит сделать:)\nВаш счёт составляет: {user.balance}'
)
# Проверяем, истекла ли подписка
elif subscription.expiry_date < datetime.now(): elif subscription.expiry_date < datetime.now():
await update.message.reply_text(f'Ваш профиль {user.username},Ваша подписка действует до - {subscription.expiry_date}',reply_markup=reply_markup) await loading_message_id.edit_text(
f'Ваш профиль {user.username}, {user.telegram_id}, Ваша подписка действует до - {subscription.expiry_date}'
)
else: else:
await update.message.reply_text(f'Ваш профиль {user.username},\nВаша подписка истекла - {subscription.expiry_date}',reply_markup=reply_markup) await loading_message_id.edit_text(
f'Ваш профиль {user.username}, {user.telegram_id},\nВаша подписка истекла - {subscription.expiry_date}'
)
async def about(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None: async def about(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
keyboard = [ keyboard = [
@@ -62,7 +73,7 @@ async def about(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
InlineKeyboardButton("Главное меню", callback_data="account") InlineKeyboardButton("Главное меню", callback_data="account")
]] ]]
reply_markup = InlineKeyboardMarkup(keyboard) reply_markup = InlineKeyboardMarkup(keyboard)
await update.message.reply_text(f'Игорь чё нить напишет, я продублирую',reply_markup=reply_markup) await update.callback_query.message.reply_text(f'Игорь чё нить напишет, я продублирую',reply_markup=reply_markup)
async def support(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None: async def support(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
keyboard = [ keyboard = [
@@ -71,7 +82,7 @@ async def support(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
InlineKeyboardButton("Написать", callback_data="sup") # Нужно через каллбек доделать InlineKeyboardButton("Написать", callback_data="sup") # Нужно через каллбек доделать
]] ]]
reply_markup = InlineKeyboardMarkup(keyboard) reply_markup = InlineKeyboardMarkup(keyboard)
await update.message.reply_text(f'Что бы отправить сообщение поддержке выберите в меню кнопку "Написать", а далее изложите в одном сообщении свою ошибку.',reply_markup=reply_markup) await update.callback_query.message.reply_text(f'Что бы отправить сообщение поддержке выберите в меню кнопку "Написать", а далее изложите в одном сообщении свою ошибку.',reply_markup=reply_markup)
async def pop_up(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None: async def pop_up(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
keyboard = [ keyboard = [
@@ -79,7 +90,7 @@ async def pop_up(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
InlineKeyboardButton("Главное меню", callback_data="account"), InlineKeyboardButton("Главное меню", callback_data="account"),
]] ]]
reply_markup = InlineKeyboardMarkup(keyboard) reply_markup = InlineKeyboardMarkup(keyboard)
await update.message.reply_text(f'Когда нибудь эта штука заработает',reply_markup=reply_markup) await update.callback_query.message.reply_text(f'Когда нибудь эта штука заработает',reply_markup=reply_markup)
async def buy_subscription(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None: async def buy_subscription(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
keyboard = [ keyboard = [
@@ -88,22 +99,25 @@ async def buy_subscription(update: Update, context: ContextTypes.DEFAULT_TYPE) -
]] ]]
reply_markup = InlineKeyboardMarkup(keyboard) reply_markup = InlineKeyboardMarkup(keyboard)
session = next(get_db_session()) session = next(get_db_session())
user = session.query(User).filter(User.telegram_id == str(update.effective_user.id)).first() user = session.query(User).filter(User.telegram_id == str(update.callback_query.from_user.id)).first()
check = last_subscription(session=session,user=user) check = last_subscription(session=session,user=user)
if not check: if not check:
keyboard = [ keyboard = [
[ [
InlineKeyboardButton("Тариф 1 \"Бимжик\"", callback_data="bimzhik"), InlineKeyboardButton("Тариф 1 \"Бимжик\"", callback_data="Бимжик"),
], ],
[ [
InlineKeyboardButton("Тариф 2 \"Бизнес хомячёк\"", callback_data="homyachok"), InlineKeyboardButton("Тариф 2 \"Бизнес хомячёк\"", callback_data="Бизнес_хомячёк"),
], ],
[ [
InlineKeyboardButton("Тариф 2 \"Продвинутый Акулёнок\"", callback_data="akulenok"), InlineKeyboardButton("Тариф 3 \"Продвинутый Акулёнок\"", callback_data="Продвинутый_Акулёнок"),
],
[
InlineKeyboardButton("Главное меню", callback_data="account"),
]] ]]
reply_markup = InlineKeyboardMarkup(keyboard) reply_markup = InlineKeyboardMarkup(keyboard)
await update.message.reply_text(f'Какую подписку вы хотели бы приобрести\nТариф 1 "Бимжик" - 200 рубликов - 1 месяцок\nТариф 2 "Бизнес хомячёк" - 500 рубликов - 3 месяцка\nТариф 3 "Продвинутый Акулёнок" - 888 рубликов - 888 рубликов\n',reply_markup=reply_markup) await update.callback_query.message.reply_text(f'Какую подписку вы хотели бы приобрести\nТариф 1 "Бимжик" - 200 рубликов - 1 месяцок\nТариф 2 "Бизнес хомячёк" - 500 рубликов - 3 месяцка\nТариф 3 "Продвинутый Акулёнок" - 888 рубликов - 6 месяцков\n',reply_markup=reply_markup)
# проверяем, истекла ли подписка # проверяем, истекла ли подписка
else: else:
keyboard = [ keyboard = [
@@ -111,7 +125,7 @@ async def buy_subscription(update: Update, context: ContextTypes.DEFAULT_TYPE) -
InlineKeyboardButton("Главное меню", callback_data="account"), InlineKeyboardButton("Главное меню", callback_data="account"),
]] ]]
reply_markup = InlineKeyboardMarkup(keyboard) reply_markup = InlineKeyboardMarkup(keyboard)
await update.message.reply_text(f'У вас уже приобретена подписка',reply_markup=reply_markup) await update.callback_query.message.reply_text(f'У вас уже приобретена подписка',reply_markup=reply_markup)
async def faq(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None: async def faq(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
@@ -120,7 +134,50 @@ async def faq(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
InlineKeyboardButton("Главное меню", callback_data="account"), InlineKeyboardButton("Главное меню", callback_data="account"),
]] ]]
reply_markup = InlineKeyboardMarkup(keyboard) reply_markup = InlineKeyboardMarkup(keyboard)
await update.message.reply_text(f'Когда нибудь что нибудь здесь будет написано!!;)',reply_markup=reply_markup) await update.callback_query.message.reply_text(f'Когда нибудь что нибудь здесь будет написано!!;)',reply_markup=reply_markup)
async def button_handler(update: Update, context):
query = update.callback_query
loading_message = await query.message.reply_text("Загрузка...")
await query.answer()
session = next(get_db_session())
try:
if query.data == 'account':
await personal_account(update, context=context)
elif query.data == 'about':
await about(update, context)
elif query.data == 'support':
await support(update, context)
elif query.data == 'pop_up':
await pop_up(update, context)
elif query.data == 'buy_tarif':
await buy_subscription(update, context)
elif query.data == 'faq':
await faq(update, context)
elif query.data == 'payment_history':
await active_sub(update, context)
if query.data in ['Бимжик', 'Бизнес_хомячёк', 'Продвинутый_Акулёнок']:
plan = query.data.replace('_', ' ') if '_' in query.data else query.data
check = buy_sub(session, query.from_user.id, plan, logger)
if check != "OK":
await loading_message.edit_text("Неизвестный тариф.")
else:
await loading_message.edit_text("Тариф успешно установлен!")
except Exception as e:
logger.error(f"Ошибка при обработке запроса пользователя {query.from_user.id}: {e}")
await loading_message.edit_text("Произошла ошибка. Пожалуйста, попробуйте снова.")
finally:
session.close()
async def active_sub(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None: async def active_sub(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
keyboard = [ keyboard = [
[ [
@@ -128,7 +185,7 @@ async def active_sub(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None
]] ]]
reply_markup = InlineKeyboardMarkup(keyboard) reply_markup = InlineKeyboardMarkup(keyboard)
session = next(get_db_session()) session = next(get_db_session())
list_sub = get_sub_list(session, 10, update.effective_user.id) list_sub = get_sub_list(session, 10, update.callback_query.from_user.id)
if list_sub: if list_sub:
message = "Ваши подписки:\n" message = "Ваши подписки:\n"
@@ -139,10 +196,9 @@ async def active_sub(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None
message += f" Устаревшая: {cur_sub.plan}, Дата покупки: {cur_sub.created_at}\n" message += f" Устаревшая: {cur_sub.plan}, Дата покупки: {cur_sub.created_at}\n"
else: else:
message = "Ты пидор, не приобрел у нас подписку?!" message = "Ты пидор, не приобрел у нас подписку?!"
await update.message.reply_text(message,reply_markup=reply_markup) await update.callback_query.message.reply_text(message,reply_markup=reply_markup)
def main() -> None: def main() -> None:
init_db() init_db()
db = SessionLocal() db = SessionLocal()
application = Application.builder().token(config['token']).build() application = Application.builder().token(config['token']).build()
@@ -155,6 +211,7 @@ def main() -> None:
application.add_handler(CommandHandler("buy_subscription", buy_subscription)) application.add_handler(CommandHandler("buy_subscription", buy_subscription))
application.add_handler(CommandHandler("faq", faq)) application.add_handler(CommandHandler("faq", faq))
application.add_handler(CommandHandler("active_sub", active_sub)) application.add_handler(CommandHandler("active_sub", active_sub))
application.add_handler(CallbackQueryHandler(button_handler))
application.run_polling(allowed_updates=Update.ALL_TYPES) application.run_polling(allowed_updates=Update.ALL_TYPES)

37
db.py
View File

@@ -13,43 +13,6 @@ def generate_uuid():
return str(uuid.uuid4()) return str(uuid.uuid4())
def last_subscription(session,user):
last_subscription = (
session.query(Subscription)
.filter(Subscription.user_id == user.id)
.order_by(desc(Subscription.created_at))
.first()
)
return last_subscription
def get_sub_list(session,count,user_id):
subscriptions = (
session.query(Subscription)
.filter(Subscription.user_id == str(user_id))
.order_by(desc(Subscription.created_at))
.limit(count) # Ограничиваем результат 10 записями
.all() # Получаем все записи
)
return subscriptions
def create_user(telegram_id: str, username: str = None, balance: float = 0.0):
db = next(get_db_session())
try:
new_user = User(
telegram_id=telegram_id,
username=username,
balance=balance
)
db.add(new_user)
db.commit()
db.refresh(new_user)
return new_user
except Exception as e:
db.rollback()
raise e
finally:
db.close()
#Пользователи #Пользователи
class User(Base): class User(Base):
__tablename__ = 'users' __tablename__ = 'users'

74
db_operations.py Normal file
View File

@@ -0,0 +1,74 @@
from service import UserService
#DataBase
from sqlalchemy import desc
from db import get_db_session
from db import User
from db import Subscription
from db import Transaction
from db import VPNServer
import json
with open('config.json', 'r') as file:
config = json.load(file)
def last_subscription(session,user):
last_subscription = (
session.query(Subscription)
.filter(Subscription.user_id == user.id)
.order_by(desc(Subscription.created_at))
.first()
)
return last_subscription
def get_sub_list(session,count,user_id):
subscriptions = (
session.query(Subscription)
.filter(Subscription.user_id == str(user_id))
.order_by(desc(Subscription.created_at))
.limit(count) # Ограничиваем результат 10 записями
.all() # Получаем все записи
)
return subscriptions
def create_user(telegram_id: str, username: str = None, balance: float = 0.0):
db = next(get_db_session())
try:
new_user = User(
telegram_id=telegram_id,
username=username,
balance=balance
)
db.add(new_user)
db.commit()
db.refresh(new_user)
return new_user
except Exception as e:
db.rollback()
raise e
finally:
db.close()
def buy_sub(session, telegram_id: str, plan: str, logger):
try:
user = session.query(User).filter(User.telegram_id == str(telegram_id)).first()
if user is None:
logger.error(f"Пользователь с Telegram ID {telegram_id} не найден.")
return "error"
current_plan = config['subscription_templates'].get(plan)
if current_plan is None:
logger.error(f"Тариф {plan} не найден в шаблонах.")
return "error"
if user.balance == current_plan['cost']:
service = UserService(logger)
service.tariff_setting(user, plan, current_plan['duration'])
return "OK"
else:
logger.error(f"Недостаточно средств на счету пользователя {telegram_id} для тарифа {plan}.")
return "error"
except Exception as e:
logger.error(f"Ошибка при покупке тарифа для пользователя {telegram_id}: {e}")

View File

@@ -2,6 +2,7 @@ from db import User
from db import Subscription from db import Subscription
from db import Transaction from db import Transaction
from db import VPNServer from db import VPNServer
from sqlalchemy import desc
from datetime import datetime,timedelta from datetime import datetime,timedelta
from db import get_db_session from db import get_db_session
import json import json
@@ -62,27 +63,31 @@ class UserService:
finally: finally:
session.close() session.close()
def tariff_setting(self,telegram_id: int,plan: str): def tariff_setting(self, user, plan: str, expiry_duration):
session = next(get_db_session()) session = next(get_db_session())
try: try:
user = session.query(User).filter(User.telegram_id == telegram_id).first() server = (
if user:
server = (
session.query(VPNServer) session.query(VPNServer)
.filter(VPNServer.current_users < VPNServer.max_users) .filter(VPNServer.current_users < VPNServer.max_users)
.order_by(VPNServer.current_users.asc()) .order_by(VPNServer.current_users.asc())
.first()) .first()
current_plan = config['subscription_templates'].get(plan) )
expiry_ = datetime.now() + timedelta(days=current_plan['expiry_duration'])
new_subscription = Subscription(user_id = user.id,vpn_server_id = server.id,plan = plan,expiry_date = expiry_) if server is None:
session.add(new_subscription) self.logger.error("Нет доступных VPN серверов.")
session.commit() return
expiry_ = datetime.now() + timedelta(days=expiry_duration)
new_subscription = Subscription(user_id=user.id, vpn_server_id=server.id, plan=plan, expiry_date=expiry_)
session.add(new_subscription)
session.commit()
except Exception as e: except Exception as e:
self.logger.error(f"Чё то ошибка в установке тарифа: {e}") self.logger.error(f"Ошибка в установке тарифа: {e}")
finally: finally:
session.close() session.close()
def create_uri(self,telegram_id,): def create_uri(self,telegram_id,):
session = next(get_db_session()) session = next(get_db_session())
try: try: