переход на postresql

This commit is contained in:
Vlad
2024-09-21 00:21:23 +03:00
parent 4316f44390
commit 51b46bfe65
9 changed files with 266 additions and 251 deletions
-6
View File
@@ -1,10 +1,4 @@
import requests
import json
from config import ADMIN_USERNAME, ADMIN_PASSWORD, GET_INBOUNDS_URL, DATABASE_PATH
import uuid
from auth import login_with_credentials
from datetime import datetime, timedelta
import aiosqlite
def add_client(session, client_id: str, email: str, tg_id: str, limit_ip: int, total_gb: int, expiry_time: int, enable: bool, flow: str):
url = 'https://solonet.pocomacho.ru:62553/solonet/panel/api/inbounds/addClient'
+65 -65
View File
@@ -1,84 +1,84 @@
import aiosqlite
import asyncpg
from datetime import datetime
from config import DATABASE_PATH
from config import DATABASE_URL # Example: "postgresql://user:password@localhost:5432/dbname"
async def init_db():
async with aiosqlite.connect(DATABASE_PATH) as db:
await db.execute('''
CREATE TABLE IF NOT EXISTS connections (
tg_id INTEGER PRIMARY KEY NOT NULL,
balance REAL NOT NULL DEFAULT 0.0,
trial INTEGER NOT NULL DEFAULT 0
)
''')
await db.execute('''
CREATE TABLE IF NOT EXISTS keys (
tg_id INTEGER NOT NULL,
client_id TEXT NOT NULL,
email TEXT NOT NULL,
created_at INTEGER NOT NULL,
expiry_time INTEGER NOT NULL,
key TEXT NOT NULL,
PRIMARY KEY (tg_id, client_id)
)
''')
await db.commit()
conn = await asyncpg.connect(DATABASE_URL)
await conn.execute('''
CREATE TABLE IF NOT EXISTS connections (
tg_id BIGINT PRIMARY KEY NOT NULL,
balance REAL NOT NULL DEFAULT 0.0,
trial INTEGER NOT NULL DEFAULT 0
)
''')
await conn.execute('''
CREATE TABLE IF NOT EXISTS keys (
tg_id BIGINT NOT NULL,
client_id TEXT NOT NULL,
email TEXT NOT NULL,
created_at BIGINT NOT NULL,
expiry_time BIGINT NOT NULL,
key TEXT NOT NULL,
PRIMARY KEY (tg_id, client_id)
)
''')
await conn.close()
async def add_connection(tg_id: int, balance: float = 0.0, trial: int = 0):
async with aiosqlite.connect(DATABASE_PATH) as db:
await db.execute('''
INSERT INTO connections (tg_id, balance, trial)
VALUES (?, ?, ?)
''', (tg_id, balance, trial))
await db.commit()
conn = await asyncpg.connect(DATABASE_URL)
await conn.execute('''
INSERT INTO connections (tg_id, balance, trial)
VALUES ($1, $2, $3)
''', tg_id, balance, trial)
await conn.close()
async def store_key(tg_id: int, client_id: str, email: str, expiry_time: int, key: str):
async with aiosqlite.connect(DATABASE_PATH) as db:
await db.execute('''
INSERT INTO keys (tg_id, client_id, email, created_at, expiry_time, key)
VALUES (?, ?, ?, ?, ?, ?)
''', (tg_id, client_id, email, int(datetime.utcnow().timestamp() * 1000), expiry_time, key))
await db.commit()
conn = await asyncpg.connect(DATABASE_URL)
await conn.execute('''
INSERT INTO keys (tg_id, client_id, email, created_at, expiry_time, key)
VALUES ($1, $2, $3, $4, $5, $6)
''', tg_id, client_id, email, int(datetime.utcnow().timestamp() * 1000), expiry_time, key)
await conn.close()
async def get_keys(tg_id: int):
async with aiosqlite.connect(DATABASE_PATH) as db:
async with db.execute('''
SELECT client_id, email, created_at, key
FROM keys
WHERE tg_id = ?
''', (tg_id,)) as cursor:
return await cursor.fetchall()
conn = await asyncpg.connect(DATABASE_URL)
records = await conn.fetch('''
SELECT client_id, email, created_at, key
FROM keys
WHERE tg_id = $1
''', tg_id)
await conn.close()
return records
async def has_active_key(tg_id: int) -> bool:
async with aiosqlite.connect(DATABASE_PATH) as db:
async with db.execute("SELECT COUNT(*) FROM keys WHERE tg_id = ?", (tg_id,)) as cursor:
count = await cursor.fetchone()
return count[0] > 0
conn = await asyncpg.connect(DATABASE_URL)
count = await conn.fetchval("SELECT COUNT(*) FROM keys WHERE tg_id = $1", tg_id)
await conn.close()
return count > 0
async def get_balance(tg_id: int) -> float:
async with aiosqlite.connect(DATABASE_PATH) as db:
async with db.execute("SELECT balance FROM connections WHERE tg_id = ?", (tg_id,)) as cursor:
record = await cursor.fetchone()
return record[0] if record else 0.0
conn = await asyncpg.connect(DATABASE_URL)
balance = await conn.fetchval("SELECT balance FROM connections WHERE tg_id = $1", tg_id)
await conn.close()
return balance if balance is not None else 0.0
async def update_balance(tg_id: int, amount: float):
async with aiosqlite.connect(DATABASE_PATH) as db:
await db.execute('''
UPDATE connections
SET balance = balance + ?
WHERE tg_id = ?
''', (amount, tg_id))
await db.commit()
conn = await asyncpg.connect(DATABASE_URL)
await conn.execute('''
UPDATE connections
SET balance = balance + $1
WHERE tg_id = $2
''', amount, tg_id)
await conn.close()
async def get_trial(tg_id: int) -> int:
async with aiosqlite.connect(DATABASE_PATH) as db:
async with db.execute("SELECT trial FROM connections WHERE tg_id = ?", (tg_id,)) as cursor:
record = await cursor.fetchone()
return record[0] if record else 0
conn = await asyncpg.connect(DATABASE_URL)
trial = await conn.fetchval("SELECT trial FROM connections WHERE tg_id = $1", tg_id)
await conn.close()
return trial if trial is not None else 0
async def get_key_count(tg_id: int) -> int:
async with aiosqlite.connect(DATABASE_PATH) as db:
async with db.execute('SELECT COUNT(*) FROM keys WHERE tg_id = ?', (tg_id,)) as cursor:
count = await cursor.fetchone()
return count[0] if count else 0
conn = await asyncpg.connect(DATABASE_URL)
count = await conn.fetchval('SELECT COUNT(*) FROM keys WHERE tg_id = $1', tg_id)
await conn.close()
return count if count is not None else 0
Binary file not shown.
Binary file not shown.
Binary file not shown.
+143 -133
View File
@@ -1,10 +1,11 @@
import asyncpg
from aiogram import types, Router
import aiosqlite
from bot import bot
from datetime import datetime, timedelta
from database import get_balance, update_balance, get_trial
from client import extend_client_key, login_with_credentials
from config import ADMIN_USERNAME, DATABASE_PATH, ADMIN_PASSWORD
from client import extend_client_key
from config import ADMIN_USERNAME, DATABASE_URL, ADMIN_PASSWORD
from auth import login_with_credentials
router = Router()
@@ -14,35 +15,38 @@ async def process_callback_view_keys(callback_query: types.CallbackQuery):
tg_id = callback_query.from_user.id
try:
async with aiosqlite.connect(DATABASE_PATH) as db:
async with db.execute('''
SELECT email FROM keys WHERE tg_id = ?
''', (tg_id,)) as cursor:
records = await cursor.fetchall()
conn = await asyncpg.connect(DATABASE_URL)
try:
records = await conn.fetch('''
SELECT email FROM keys WHERE tg_id = $1
''', tg_id)
if records:
# Создаем кнопки для каждого ключа
buttons = []
for record in records:
key_name = record[0] # Предполагается, что email - это название ключа
button = types.InlineKeyboardButton(text=key_name, callback_data=f'view_key_{key_name}')
buttons.append([button])
if records:
# Создаем кнопки для каждого ключа
buttons = []
for record in records:
key_name = record['email'] # Предполагается, что email - это название ключа
button = types.InlineKeyboardButton(text=key_name, callback_data=f'view_key_{key_name}')
buttons.append([button])
# Создаем клавиатуру с кнопками
inline_keyboard = types.InlineKeyboardMarkup(inline_keyboard=buttons)
response_message = "Выберите ключ для просмотра информации:"
# Редактируем сообщение с клавиатурой
await bot.edit_message_text(response_message, chat_id=tg_id, message_id=callback_query.message.message_id, reply_markup=inline_keyboard)
else:
# Если нет ключей, добавляем кнопку "Создать ключ"
response_message = "У вас нет ключей."
# Кнопка "Создать ключ"
create_key_button = types.InlineKeyboardButton(text='Создать ключ', callback_data='create_key')
keyboard = types.InlineKeyboardMarkup(inline_keyboard=[[create_key_button]])
await bot.edit_message_text(response_message, chat_id=tg_id, message_id=callback_query.message.message_id, reply_markup=keyboard)
# Создаем клавиатуру с кнопками
inline_keyboard = types.InlineKeyboardMarkup(inline_keyboard=buttons)
response_message = "Выберите ключ для просмотра информации:"
# Редактируем сообщение с клавиатурой
await bot.edit_message_text(response_message, chat_id=tg_id, message_id=callback_query.message.message_id, reply_markup=inline_keyboard)
else:
# Если нет ключей, добавляем кнопку "Создать ключ"
response_message = "У вас нет ключей."
# Кнопка "Создать ключ"
create_key_button = types.InlineKeyboardButton(text='Создать ключ', callback_data='create_key')
keyboard = types.InlineKeyboardMarkup(inline_keyboard=[[create_key_button]])
await bot.edit_message_text(response_message, chat_id=tg_id, message_id=callback_query.message.message_id, reply_markup=keyboard)
finally:
await conn.close()
except Exception as e:
await handle_error(tg_id, callback_query, f"Ошибка при получении ключей: {e}")
@@ -57,146 +61,152 @@ async def process_callback_view_key(callback_query: types.CallbackQuery):
key_name = callback_query.data.split('_', 2)[2] # Получаем имя ключа
try:
async with aiosqlite.connect(DATABASE_PATH) as db:
async with db.execute('''
conn = await asyncpg.connect(DATABASE_URL)
try:
record = await conn.fetchrow('''
SELECT k.key, k.expiry_time
FROM keys k
JOIN connections c ON k.tg_id = c.tg_id
WHERE k.tg_id = ? AND k.email = ?
''', (tg_id, key_name)) as cursor:
record = await cursor.fetchone()
WHERE k.tg_id = $1 AND k.email = $2
''', tg_id, key_name)
if record:
key, expiry_time = record
expiry_date = datetime.utcfromtimestamp(expiry_time / 1000)
current_date = datetime.utcnow()
days_left = (expiry_date - current_date).days
if record:
key = record['key']
expiry_time = record['expiry_time']
expiry_date = datetime.utcfromtimestamp(expiry_time / 1000)
current_date = datetime.utcnow()
days_left = (expiry_date - current_date).days
days_left_message = f"Осталось дней: {days_left}" if days_left > 0 else "Ключ истек."
response_message = (f"Ваш ключ:\n<pre>{key}</pre>\n"
f"Дата окончания: <b>{expiry_date.strftime('%Y-%m-%d %H:%M:%S')}</b>\n"
f"{days_left_message}")
days_left_message = f"Осталось дней: {days_left}" if days_left > 0 else "Ключ истек."
response_message = (f"Ваш ключ:\n<pre>{key}</pre>\n"
f"Дата окончания: <b>{expiry_date.strftime('%Y-%m-%d %H:%M:%S')}</b>\n"
f"{days_left_message}")
# Кнопки для продления и инструкций
renew_button = types.InlineKeyboardButton(text='Продлить ключ', callback_data='renew_key')
instructions_button = types.InlineKeyboardButton(text='Инструкции по использованию', callback_data='instructions')
back_button = types.InlineKeyboardButton(text='Назад в профиль', callback_data='view_profile')
keyboard = types.InlineKeyboardMarkup(inline_keyboard=[[renew_button], [instructions_button], [back_button]])
# Кнопки для продления и инструкций
renew_button = types.InlineKeyboardButton(text='Продлить ключ', callback_data='renew_key')
instructions_button = types.InlineKeyboardButton(text='Инструкции по использованию', callback_data='instructions')
back_button = types.InlineKeyboardButton(text='Назад в профиль', callback_data='view_profile')
keyboard = types.InlineKeyboardMarkup(inline_keyboard=[[renew_button], [instructions_button], [back_button]])
await bot.edit_message_text(response_message, chat_id=tg_id, message_id=callback_query.message.message_id, reply_markup=keyboard, parse_mode="HTML")
else:
await bot.edit_message_text("Информация о ключе не найдена.", chat_id=tg_id, message_id=callback_query.message.message_id, parse_mode="HTML")
await bot.edit_message_text(response_message, chat_id=tg_id, message_id=callback_query.message.message_id, reply_markup=keyboard, parse_mode="HTML")
else:
await bot.edit_message_text("Информация о ключе не найдена.", chat_id=tg_id, message_id=callback_query.message.message_id, parse_mode="HTML")
finally:
await conn.close()
except Exception as e:
await handle_error(tg_id, callback_query, f"Ошибка при получении информации о ключе: {e}")
await callback_query.answer()
# Остальные функции остаются без изменений...
# Обработка ошибок
async def handle_error(tg_id, callback_query, message):
await bot.edit_message_text(message, chat_id=tg_id, message_id=callback_query.message.message_id, parse_mode="HTML")
# Обработка запроса на продление ключа
@router.callback_query(lambda c: c.data == 'renew_key')
async def process_callback_renew_key(callback_query: types.CallbackQuery):
tg_id = callback_query.from_user.id
try:
async with aiosqlite.connect(DATABASE_PATH) as db:
async with db.execute('SELECT client_id, email, expiry_time FROM keys WHERE tg_id = ?', (tg_id,)) as cursor:
record = await cursor.fetchone()
conn = await asyncpg.connect(DATABASE_URL)
try:
record = await conn.fetchrow('SELECT client_id, email, expiry_time FROM keys WHERE tg_id = $1', tg_id)
if record:
client_id, email, expiry_time = record
current_time = datetime.utcnow().timestamp() * 1000
if expiry_time <= current_time:
await callback_query.message.answer("Ваш ключ уже истек и не может быть продлен.")
return
# Создаем клавиатуру для выбора плана продления
keyboard = types.InlineKeyboardMarkup(inline_keyboard=[
[types.InlineKeyboardButton(text='Продлить на 1 месяц (100 руб.)', callback_data='renew_1_month')],
[types.InlineKeyboardButton(text='Продлить на 3 месяца (250 руб.)', callback_data='renew_3_months')],
[types.InlineKeyboardButton(text='Назад', callback_data='view_profile')]
])
if record:
client_id = record['client_id']
email = record['email']
expiry_time = record['expiry_time']
current_time = datetime.utcnow().timestamp() * 1000
balance = await get_balance(tg_id)
response_message = (f"Выберите план продления:\n"
f"Баланс: <b>{balance} руб.</b>\n"
f"Действующий ключ истекает <b>{datetime.utcfromtimestamp(expiry_time / 1000).strftime('%Y-%m-%d %H:%M:%S')}</b>")
if expiry_time <= current_time:
await callback_query.message.answer("Ваш ключ уже истек и не может быть продлен.")
return
await delete_previous_message(callback_query)
await bot.send_message(tg_id, response_message, parse_mode="HTML", reply_markup=keyboard)
# Создаем клавиатуру для выбора плана продления
keyboard = types.InlineKeyboardMarkup(inline_keyboard=[
[types.InlineKeyboardButton(text='Продлить на 1 месяц (100 руб.)', callback_data='renew_1_month')],
[types.InlineKeyboardButton(text='Продлить на 3 месяца (250 руб.)', callback_data='renew_3_months')],
[types.InlineKeyboardButton(text='Назад', callback_data='view_profile')]
])
balance = await get_balance(tg_id)
response_message = (f"Выберите план продления:\n"
f"Баланс: <b>{balance} руб.</b>\n"
f"Действующий ключ истекает <b>{datetime.utcfromtimestamp(expiry_time / 1000).strftime('%Y-%m-%d %H:%M:%S')}</b>")
await delete_previous_message(callback_query)
await bot.send_message(tg_id, response_message, parse_mode="HTML", reply_markup=keyboard)
finally:
await conn.close()
except Exception as e:
await callback_query.message.answer(f"Ошибка при выборе плана: {e}")
await callback_query.answer()
# Обработка выбора плана продления
@router.callback_query(lambda c: c.data.startswith('renew_'))
async def process_callback_renew_plan(callback_query: types.CallbackQuery):
tg_id = callback_query.from_user.id
plan = callback_query.data.split('_')[1] # '1' или '3'
days_to_extend = 30 * int(plan) # 30 дней или 90 дней
try:
async with aiosqlite.connect(DATABASE_PATH) as db:
async with db.execute('SELECT client_id, email, expiry_time FROM keys WHERE tg_id = ?', (tg_id,)) as cursor:
record = await cursor.fetchone()
if record:
client_id = record[0]
email = record[1]
expiry_time = record[2]
current_time = datetime.utcnow().timestamp() * 1000
if expiry_time <= current_time:
await callback_query.message.answer("Ваш ключ уже истек и не может быть продлен.")
return
# Рассчитываем новый срок окончания, добавляя дни в зависимости от выбранного плана
new_expiry_time = int(expiry_time + timedelta(days=days_to_extend).total_seconds() * 1000)
# Определяем стоимость продления
cost = 100 if plan == '1' else 250
# Проверка баланса
balance = await get_balance(tg_id)
if balance < cost:
replenish_button = types.InlineKeyboardButton(text='Пополнить баланс', callback_data='replenish_balance')
back_button = types.InlineKeyboardButton(text='Назад', callback_data='view_keys')
keyboard = types.InlineKeyboardMarkup(inline_keyboard=[[replenish_button], [back_button]])
await callback_query.message.answer("Недостаточно средств для продления ключа.", reply_markup=keyboard)
return
# Создаем сессию для API-запросов
session = login_with_credentials(ADMIN_USERNAME, ADMIN_PASSWORD)
# Обновляем ключ через API
success = extend_client_key(session, tg_id, client_id, email, new_expiry_time)
if success:
await update_balance(tg_id, -cost) # Списание средств с баланса
await db.execute('UPDATE keys SET expiry_time = ? WHERE client_id = ?', (new_expiry_time, client_id))
await db.commit()
response_message = f"Ваш ключ был успешно продлен на {days_to_extend // 30} месяц(-)."
back_button = types.InlineKeyboardButton(text='Назад', callback_data='view_keys')
keyboard = types.InlineKeyboardMarkup(inline_keyboard=[[back_button]])
await bot.send_message(tg_id, response_message, reply_markup=keyboard)
else:
await bot.send_message(tg_id, "Ошибка при продлении ключа.")
conn = await asyncpg.connect(DATABASE_URL)
try:
record = await conn.fetchrow('SELECT client_id, email, expiry_time FROM keys WHERE tg_id = $1', tg_id)
if record:
client_id = record['client_id']
email = record['email']
expiry_time = record['expiry_time']
current_time = datetime.utcnow().timestamp() * 1000
if expiry_time <= current_time:
await callback_query.message.answer("Ваш ключ уже истек и не может быть продлен.")
return
# Рассчитываем новый срок окончания
new_expiry_time = int(expiry_time + timedelta(days=days_to_extend).total_seconds() * 1000)
# Определяем стоимость продления
cost = 100 if plan == '1' else 250
# Проверка баланса
balance = await get_balance(tg_id)
if balance < cost:
replenish_button = types.InlineKeyboardButton(text='Пополнить баланс', callback_data='replenish_balance')
back_button = types.InlineKeyboardButton(text='Назад', callback_data='view_keys')
keyboard = types.InlineKeyboardMarkup(inline_keyboard=[[replenish_button], [back_button]])
await callback_query.message.answer("Недостаточно средств для продления ключа.", reply_markup=keyboard)
return
# Создаем сессию для API-запросов
session = login_with_credentials(ADMIN_USERNAME, ADMIN_PASSWORD)
# Обновляем ключ через API
success = extend_client_key(session, tg_id, client_id, email, new_expiry_time)
if success:
await update_balance(tg_id, -cost) # Списание средств с баланса
await conn.execute('UPDATE keys SET expiry_time = $1 WHERE client_id = $2', new_expiry_time, client_id)
response_message = f"Ваш ключ был успешно продлен на {days_to_extend // 30} месяц(-)."
back_button = types.InlineKeyboardButton(text='Назад', callback_data='view_keys')
keyboard = types.InlineKeyboardMarkup(inline_keyboard=[[back_button]])
await bot.send_message(tg_id, response_message, reply_markup=keyboard)
else:
await bot.send_message(tg_id, "У вас нет ключей для продления.")
await bot.send_message(tg_id, "Ошибка при продлении ключа.")
else:
await bot.send_message(tg_id, "У вас нет ключей для продления.")
finally:
await conn.close()
except Exception as e:
await bot.send_message(tg_id, f"Ошибка при продлении ключа: {e}")
await callback_query.answer()
@@ -208,4 +218,4 @@ async def delete_previous_message(callback_query: types.CallbackQuery):
# Обработка ошибок
async def handle_error(tg_id, callback_query, message):
await delete_previous_message(callback_query)
await bot.send_message(tg_id, message)
await bot.send_message(tg_id, message)
+30 -25
View File
@@ -3,10 +3,11 @@ from aiogram.types import InlineKeyboardButton, InlineKeyboardMarkup
from aiogram.fsm.context import FSMContext
from aiogram.fsm.state import State, StatesGroup
import aiosqlite
from config import DATABASE_PATH, ADMIN_ID
from config import ADMIN_ID, DATABASE_URL
from database import get_balance, update_balance, get_key_count
from bot import bot
from handlers.profile import process_callback_view_profile
import asyncpg
router = Router()
@@ -183,36 +184,41 @@ async def process_admin_confirmation(callback_query: types.CallbackQuery, state:
state_data = await state.get_data()
requisites_message_id = state_data.get('requisites_message_id')
if action == 'confirm':
async with aiosqlite.connect(DATABASE_PATH) as db:
# Подключаемся к базе данных PostgreSQL
conn = await asyncpg.connect(DATABASE_URL)
try:
# Обновляем баланс пользователя
await update_balance(user_id, amount)
await db.commit()
balance = await get_balance(user_id)
# Получаем обновленный баланс
balance = await get_balance(user_id)
# Создаем клавиатуру с кнопкой "Профиль"
profile_button = InlineKeyboardButton(text='Профиль', callback_data='view_profile')
profile_keyboard = InlineKeyboardMarkup(inline_keyboard=[[profile_button]])
# Создаем клавиатуру с кнопкой "Профиль"
profile_button = InlineKeyboardButton(text='Профиль', callback_data='view_profile')
profile_keyboard = InlineKeyboardMarkup(inline_keyboard=[[profile_button]])
# Отправляем уведомление с кнопкой "Профиль" администратору
await send_message_with_deletion(callback_query.from_user.id, f"Баланс пользователя успешно пополнен на {amount} RUB.\nТекущий баланс: {balance}", state=state, message_key='admin_confirm_message_id')
# Отправляем уведомление с кнопкой "Профиль" администратору
await send_message_with_deletion(callback_query.from_user.id, f"Баланс пользователя успешно пополнен на {amount} RUB.\nТекущий баланс: {balance}", state=state, message_key='admin_confirm_message_id')
# Отправляем уведомление пользователю с кнопкой "Профиль"
await bot.send_message(
user_id,
f"Ваш баланс был успешно пополнен на {amount} RUB.",
reply_markup=profile_keyboard
)
# Отправляем уведомление пользователю с кнопкой "Профиль"
await bot.send_message(
user_id,
f"Ваш баланс был успешно пополнен на {amount} RUB.",
reply_markup=profile_keyboard
)
# Удаляем сообщение с реквизитами
state_data = await state.get_data()
requisites_message_id = state_data.get('requisites_message_id')
if requisites_message_id:
try:
await bot.delete_message(chat_id=user_id, message_id=requisites_message_id)
except Exception as e:
print(f"Ошибка при удалении сообщения с реквизитами: {e}")
# Удаляем сообщение с реквизитами
requisites_message_id = state_data.get('requisites_message_id')
if requisites_message_id:
try:
await bot.delete_message(chat_id=user_id, message_id=requisites_message_id)
except Exception as e:
print(f"Ошибка при удалении сообщения с реквизитами: {e}")
finally:
# Закрываем соединение с базой данных
await conn.close()
elif action == 'decline':
await send_message_with_deletion(callback_query.from_user.id, "Пополнение баланса отклонено.", state=state, message_key='admin_decline_message_id')
@@ -226,7 +232,6 @@ async def process_admin_confirmation(callback_query: types.CallbackQuery, state:
await callback_query.answer()
@router.message(lambda m: m.text and m.text.startswith('Недостаточно средств для продления'))
async def handle_insufficient_funds(message: types.Message):
user_id = message.from_user.id
-2
View File
@@ -3,8 +3,6 @@ from aiogram.types import InlineKeyboardButton, InlineKeyboardMarkup
from aiogram.fsm.context import FSMContext
from aiogram.fsm.state import State, StatesGroup
from datetime import datetime
import aiosqlite
from config import DATABASE_PATH
from database import get_balance, get_key_count
router = Router()
+28 -20
View File
@@ -1,8 +1,7 @@
from datetime import datetime, timedelta
import asyncio
import re
import uuid
import aiosqlite
import asyncio
from datetime import datetime, timedelta
from aiogram import Bot, Dispatcher, Router, types, F
from aiogram.filters import Command
from aiogram.types import InlineKeyboardButton, InlineKeyboardMarkup, CallbackQuery, Message
@@ -11,12 +10,13 @@ from aiogram.fsm.state import State, StatesGroup
from auth import login_with_credentials, link
from client import add_client
from config import API_TOKEN, ADMIN_PASSWORD, ADMIN_USERNAME, ADMIN_CHAT_ID, DATABASE_PATH
from config import API_TOKEN, ADMIN_PASSWORD, ADMIN_USERNAME, ADMIN_CHAT_ID, DATABASE_URL
from database import add_connection, has_active_key, get_balance, store_key, update_balance
from bot import dp
from handlers.start import start_command
from bot import dp, bot
from handlers.profile import process_callback_view_profile
from bot import bot
from handlers.start import start_command
import asyncpg
router = Router()
@@ -118,15 +118,18 @@ async def handle_key_name_input(message: Message, state: FSMContext):
connection_link = link(session, client_id, email)
# Проверка существующей записи
async with aiosqlite.connect(DATABASE_PATH) as db:
cursor = await db.execute('SELECT * FROM connections WHERE tg_id = ?', (tg_id,))
existing_connection = await cursor.fetchone()
conn = await asyncpg.connect(DATABASE_URL)
try:
existing_connection = await conn.fetchrow('SELECT * FROM connections WHERE tg_id = $1', tg_id)
if existing_connection:
await db.execute('UPDATE connections SET trial = 1 WHERE tg_id = ?', (tg_id,))
await conn.execute('UPDATE connections SET trial = 1 WHERE tg_id = $1', tg_id)
else:
await add_connection(tg_id, 0, 1)
finally:
await conn.close()
await store_key(tg_id, client_id, email, expiry_time, connection_link)
keyboard = InlineKeyboardMarkup(inline_keyboard=[
@@ -168,20 +171,25 @@ async def handle_back_to_main(callback_query: CallbackQuery, state: FSMContext):
async def renew_expired_keys():
while True:
current_time = datetime.utcnow()
async with aiosqlite.connect(DATABASE_PATH) as db:
async with db.execute('SELECT tg_id FROM connections WHERE trial > 0') as cursor:
active_keys = await cursor.fetchall()
conn = await asyncpg.connect(DATABASE_URL)
try:
active_keys = await conn.fetch('SELECT tg_id FROM connections WHERE trial > 0')
for tg_id, in active_keys:
finally:
await conn.close()
for record in active_keys:
tg_id = record['tg_id']
balance = await get_balance(tg_id)
if balance >= 100:
new_expiry_time = int((current_time + timedelta(days=30)).timestamp() * 1000)
async with aiosqlite.connect(DATABASE_PATH) as db:
await db.execute('UPDATE keys SET expiry_time = ? WHERE tg_id = ?', (new_expiry_time, tg_id))
await db.commit()
await update_balance(tg_id, -100)
conn = await asyncpg.connect(DATABASE_URL)
try:
await conn.execute('UPDATE keys SET expiry_time = $1 WHERE tg_id = $2', new_expiry_time, tg_id)
await update_balance(tg_id, -100)
finally:
await conn.close()
print(f"Ключ для пользователя {tg_id} продлен на месяц и списано 100 рублей.")
else: