summaryrefslogtreecommitdiff
path: root/files/TG_bot_VPN-main/handlers/custom_heandlers/location_handlers.py
blob: 45490e4a700f2d7ac54d6e822c2f0472ab82cac4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
from telebot.types import Message

from config_data.config import CHANNEL_ID
from database.models import User, Server, VPNKey
from loader import bot, app_logger, scheduler
from keyboards.inline.servers import get_locations_markup, get_instruction_markup
from states.states import GetVPNKey
from utils.functions import is_subscribed
from utils.generate_vpn_keys import generate_key
from utils.tasks import cancel_key_revocation
from utils.work_vpn_keys import revoke_key


@bot.message_handler(commands=["location"])
def location_handler(message: Message):
    """ Хендлер для выбора сервера подключения """
    app_logger.info(f"Пользователь {message.from_user.full_name} вызвал команду /location")
    cur_user = User.get(User.user_id == message.from_user.id)

    if is_subscribed(CHANNEL_ID, message.from_user.id):
        cur_user.is_subscribed = True
        bot.send_message(message.chat.id, "🌍 Пожалуйста, выберите сервер для подключения:", reply_markup=get_locations_markup())
        bot.set_state(message.chat.id, GetVPNKey.get_server)
    else:
        bot.send_message(message.chat.id, f"🚫 Вы не подписаны на [наш канал](https://t.me/{CHANNEL_ID[1:]})!\n"
                                          f"Подпишитесь, чтобы получить доступ ко всему функционалу.",
                         parse_mode="Markdown")
        cur_user.is_subscribed = False
    cur_user.save()


@bot.callback_query_handler(func=None, state=GetVPNKey.get_server)
def get_server_handler(call):
    """ Хендлер для получения сервера подключения """
    bot.answer_callback_query(callback_query_id=call.id)

    server_id = call.data

    cur_user: User = User.get(User.user_id == call.from_user.id)
    cur_server: Server = Server.get_by_id(server_id)

    # Проверка на то, что текущий VPN ключ пользователя удален.
    try:
        VPNKey.get_by_id(cur_user.vpn_key)
    except Exception:
        app_logger.warning(f"Внимание! У пользователя {cur_user.full_name} не нашлось ключа VPN!")
        cur_user.vpn_key = None
        cur_user.save()

    app_logger.info(f"Пользователь {cur_user.full_name} выбрал сервер {cur_server.location}")

    # Получение всех vpn ключей данного сервера и выбор одного
    for vpn_key_obj in cur_server.keys:
        if vpn_key_obj.is_valid:
            if cur_user.vpn_key is not None:
                users_vpn = VPNKey.get_by_id(cur_user.vpn_key)
                users_vpn.is_valid = True
                users_vpn.save()
                app_logger.info(f"VPN ключ {users_vpn.name} теперь свободен.")
            cur_user.vpn_key = vpn_key_obj
            cur_user.save()
            vpn_key_obj.is_valid = False
            vpn_key_obj.save()
            app_logger.info(f"Пользователь {cur_user.full_name} зарезервировал ключ {vpn_key_obj.name}")
            with open(vpn_key_obj.qr_code, "rb") as qr_code:
                bot.send_photo(
                    call.message.chat.id,
                    qr_code,
                    caption=(
                        "🔒 Мы не храним информацию о ваших подключениях!\n\n"
                        f"🔑 Имя ключа: *{vpn_key_obj.name}*\n"
                        f"🌍 Сервер: *{cur_server.location}*\n"
                        f"🔗 URL для подключения:\n\n`{vpn_key_obj.key}`"
                    ),
                    parse_mode="Markdown",
                    reply_markup=get_instruction_markup()
                )
            bot.set_state(call.message.chat.id, None)
            return

    # Если нет свободных ключей, генерируем новый
    app_logger.warning(f"Внимание! Для сервера {cur_server.location} не нашлось свободных VPN ключей! "
                       f"Генерирую новый...")
    bot.send_message(call.message.chat.id, "⌛ Пожалуйста, подождите... Идет генерация нового VPN ключа...")

    new_key: VPNKey = generate_key(cur_server)
    if new_key is None:
        app_logger.error("Внимание! Не удалось сгенерировать новый ключ!")
        bot.send_message(call.message.chat.id, "❌ Ведутся технические работы на стороне сервера, поэтому "
                                               "генерация нового ключа пока невозможна!\n"
                                               "Мы приносим свои извинения, попробуйте позже 😊")
        bot.set_state(call.message.chat.id, None)
        return
    app_logger.info(f"Сгенерирован новый ключ {new_key.name}!")

    if cur_user.vpn_key is not None:
        users_vpn = VPNKey.get_by_id(cur_user.vpn_key)
        revoke_key(users_vpn)

    cur_user.vpn_key = new_key
    cur_user.save()

    new_key.is_valid = False
    new_key.save()
    app_logger.info(f"Пользователь {cur_user.full_name} зарезервировал новый ключ {new_key.name}")
    with open(new_key.qr_code, "rb") as qr_code:
        bot.send_photo(
            call.message.chat.id,
            qr_code,
            caption=(
                "🔒 Мы не храним информацию о ваших подключениях!\n\n"
                f"🔑 Имя ключа: *{new_key.name}*\n"
                f"🌍 Сервер: *{cur_server.location}*\n"
                f"🔗 URL для подключения:\n\n`{new_key.key}`"
            ),
            parse_mode="Markdown",
            reply_markup=get_instruction_markup()
        )
    bot.set_state(call.message.chat.id, None)


@bot.callback_query_handler(func=lambda call: call.data.startswith("renew_"))
def renew_key_handler(call):
    bot.answer_callback_query(callback_query_id=call.id)
    try:
        vpn_key_id = int(call.data.split("_")[1])
        vpn_key = VPNKey.get_by_id(vpn_key_id)
        # Отменяем запланированную задачу отзыва
        cancel_key_revocation(vpn_key, scheduler)
        bot.send_message(call.message.chat.id,
                         f"✅ Ваш VPN ключ «{vpn_key.name}» успешно продлён!")
        app_logger.info(f"VPN ключ {vpn_key.name} продлён пользователем {call.from_user.full_name}.")
    except Exception as e:
        app_logger.error(f"Ошибка в обработчике продления ключа: {e}")
        bot.send_message(call.message.chat.id, "❌ Произошла ошибка при продлении ключа.")