Compare commits
3 Commits
34308f2cac
...
af837b54be
| Author | SHA1 | Date | |
|---|---|---|---|
| af837b54be | |||
| 9f98d9502e | |||
| 3962c57dde |
2
main.py
2
main.py
@@ -20,5 +20,5 @@ if __name__ == "__main__":
|
|||||||
|
|
||||||
# Start bot
|
# Start bot
|
||||||
bot = NwXrayBot(config.bot_token.get_secret_value())
|
bot = NwXrayBot(config.bot_token.get_secret_value())
|
||||||
bot.include_routers(HelloHandler(), MenuHandler())
|
bot.include_routers(HelloHandler(), MenuHandler(), AdminHandler())
|
||||||
uvloop.run(bot.start(skip_updates=True))
|
uvloop.run(bot.start(skip_updates=True))
|
||||||
|
|||||||
@@ -1,2 +1,3 @@
|
|||||||
from nwxraybot.bot import NwXrayBot
|
from nwxraybot.bot import NwXrayBot
|
||||||
from nwxraybot.config import Settings
|
from nwxraybot.config import Settings
|
||||||
|
from nwxraybot.utils import get_code, get_subscription_info
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
from aiogram import Bot, Dispatcher, Router
|
from aiogram import Bot, Dispatcher, Router
|
||||||
|
from aiogram.utils.callback_answer import CallbackAnswerMiddleware
|
||||||
|
|
||||||
from nwxraybot.middlewares import UserMiddleware
|
from nwxraybot.middlewares import UserMiddleware
|
||||||
|
|
||||||
@@ -10,6 +11,7 @@ class NwXrayBot:
|
|||||||
self.bot = Bot(token=token)
|
self.bot = Bot(token=token)
|
||||||
self.dp = Dispatcher()
|
self.dp = Dispatcher()
|
||||||
self.dp.message.middleware(UserMiddleware())
|
self.dp.message.middleware(UserMiddleware())
|
||||||
|
self.dp.message.middleware(CallbackAnswerMiddleware())
|
||||||
|
|
||||||
def include_routers(self, *routers: Handler):
|
def include_routers(self, *routers: Handler):
|
||||||
for router in routers:
|
for router in routers:
|
||||||
|
|||||||
@@ -1,2 +1,3 @@
|
|||||||
|
from nwxraybot.handlers.admin import AdminHandler
|
||||||
from nwxraybot.handlers.hello import HelloHandler
|
from nwxraybot.handlers.hello import HelloHandler
|
||||||
from nwxraybot.handlers.menu import MenuHandler
|
from nwxraybot.handlers.menu import MenuHandler
|
||||||
|
|||||||
53
nwxraybot/handlers/admin.py
Normal file
53
nwxraybot/handlers/admin.py
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
import re
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
from aiogram.enums import ParseMode
|
||||||
|
from aiogram.filters import Command
|
||||||
|
from aiogram.types import Message
|
||||||
|
|
||||||
|
from nwxraybot import get_code
|
||||||
|
from nwxraybot.meta import Handler
|
||||||
|
from nwxraybot.middlewares import AdminMiddleware
|
||||||
|
from nwxraybot.models import User
|
||||||
|
|
||||||
|
|
||||||
|
class AdminHandler(Handler):
|
||||||
|
def __init__(self) -> None:
|
||||||
|
super().__init__()
|
||||||
|
|
||||||
|
self.router.message.middleware(AdminMiddleware())
|
||||||
|
|
||||||
|
@self.router.message(Command('adduser'))
|
||||||
|
async def add_user(message: Message):
|
||||||
|
mask = r"^(?P<name>[a-zA-Z0-9]+)\s(?P<url>[^\s]+)($|\s(?P<date>[0-9]{2}\.[0-9]{2}\.[0-9]{4})\s(?P<time>[0-9]{2}\:[0-9]{2})$)"
|
||||||
|
text = message.text.replace('/adduser ', '')
|
||||||
|
match = re.match(mask, text)
|
||||||
|
if match is None:
|
||||||
|
await message.reply('Вы ввели команду в неверном формате. Вводите в формате:\n``` /adduser name vless://.... 01.01.1970 00:00```', parse_mode=ParseMode.MARKDOWN)
|
||||||
|
return
|
||||||
|
user_dict = match.groupdict()
|
||||||
|
date = None
|
||||||
|
if user_dict['date']:
|
||||||
|
date = datetime.strptime(f"{user_dict['date']} {
|
||||||
|
user_dict['time']}", "%d.%m.%Y %H:%M")
|
||||||
|
code = get_code()
|
||||||
|
new_user = User(
|
||||||
|
name=user_dict['name'], url=user_dict['url'], time=date, code=code)
|
||||||
|
new_user.save()
|
||||||
|
await message.answer(f'Пользователь создан. Вот его ссылка для доступа:\n`https://t.me/nwproxybot?start={code}`', parse_mode=ParseMode.MARKDOWN)
|
||||||
|
|
||||||
|
@self.router.message(Command('updateuser'))
|
||||||
|
async def update_user(message: Message):
|
||||||
|
mask = r"^(?P<name>[a-zA-Z0-9]+)\s(?P<date>[0-9]{2}\.[0-9]{2}\.[0-9]{4})\s(?P<time>[0-9]{2}\:[0-9]{2})$"
|
||||||
|
text = message.text.replace('/updateuser ', '')
|
||||||
|
match = re.match(mask, text)
|
||||||
|
if match is None:
|
||||||
|
await message.reply('Вы ввели команду в неверном формате. Вводите в формате:\n``` /updateuser name 01.01.1970 00:00```', parse_mode=ParseMode.MARKDOWN)
|
||||||
|
return
|
||||||
|
user_dict = match.groupdict()
|
||||||
|
date = datetime.strptime(f"{user_dict['date']} {
|
||||||
|
user_dict['time']}", "%d.%m.%Y %H:%M")
|
||||||
|
query = User.update(time=date).where(
|
||||||
|
User.name == user_dict['name'])
|
||||||
|
query.execute()
|
||||||
|
await message.answer('Информация о пользователе обновлена.')
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
import json
|
from typing import Optional
|
||||||
from datetime import datetime
|
|
||||||
|
|
||||||
from aiogram import F, types
|
from aiogram import F, types
|
||||||
from aiogram.enums import ParseMode
|
from aiogram.enums import ParseMode
|
||||||
@@ -7,6 +6,7 @@ from aiogram.filters import Command
|
|||||||
from aiogram.types import (CallbackQuery, InlineKeyboardButton,
|
from aiogram.types import (CallbackQuery, InlineKeyboardButton,
|
||||||
InlineKeyboardMarkup)
|
InlineKeyboardMarkup)
|
||||||
|
|
||||||
|
from nwxraybot import get_subscription_info
|
||||||
from nwxraybot.meta import Handler
|
from nwxraybot.meta import Handler
|
||||||
from nwxraybot.models import User
|
from nwxraybot.models import User
|
||||||
|
|
||||||
@@ -14,7 +14,7 @@ from nwxraybot.models import User
|
|||||||
class HelloHandler(Handler):
|
class HelloHandler(Handler):
|
||||||
def __non_admin_main_menu(self):
|
def __non_admin_main_menu(self):
|
||||||
markup = [[
|
markup = [[
|
||||||
InlineKeyboardButton(text="Обновить данные",
|
InlineKeyboardButton(text="Обновить данные🔄",
|
||||||
callback_data='update')
|
callback_data='update')
|
||||||
]]
|
]]
|
||||||
return InlineKeyboardMarkup(
|
return InlineKeyboardMarkup(
|
||||||
@@ -26,8 +26,23 @@ class HelloHandler(Handler):
|
|||||||
|
|
||||||
@self.router.message(Command("start"))
|
@self.router.message(Command("start"))
|
||||||
async def hello(message: types.Message):
|
async def hello(message: types.Message):
|
||||||
await message.reply("Приветствуем в боте NwXray! Здесь вы сможете получить информацию о своем подключении к NwXray", reply_markup=self.__non_admin_main_menu())
|
data = message.text.split()
|
||||||
|
if len(data) == 2:
|
||||||
|
code = data[1]
|
||||||
|
query = User.update(telegram_id=None).where(
|
||||||
|
User.telegram_id == message.from_user.id)
|
||||||
|
query.execute()
|
||||||
|
user: Optional[User] = User.select().where(
|
||||||
|
User.code == code).first()
|
||||||
|
if user is None:
|
||||||
|
await message.answer('Пользователь не найден, обратитесь к администратору за ссылкой!')
|
||||||
|
return
|
||||||
|
user.telegram_id = message.from_user.id
|
||||||
|
user.save()
|
||||||
|
await message.answer(f"Приветствуем в боте NwXray! Здесь вы сможете получить информацию о своем подключении к NwXray.\n\n{get_subscription_info(message.from_user.id)}",
|
||||||
|
reply_markup=self.__non_admin_main_menu(), parse_mode=ParseMode.MARKDOWN)
|
||||||
|
|
||||||
@self.router.callback_query(F.data == 'update')
|
@self.router.callback_query(F.data == 'update')
|
||||||
async def update_data(callback: CallbackQuery):
|
async def update_data(callback: CallbackQuery):
|
||||||
await callback.message.delete()
|
await callback.message.edit_text(get_subscription_info(callback.from_user.id),
|
||||||
|
reply_markup=self.__non_admin_main_menu(), parse_mode=ParseMode.MARKDOWN)
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
from aiogram import types
|
from aiogram import types
|
||||||
from aiogram.enums import ParseMode
|
from aiogram.enums import ParseMode
|
||||||
|
from aiogram.filters import Command
|
||||||
|
|
||||||
from nwxraybot.meta import Handler
|
from nwxraybot.meta import Handler
|
||||||
from nwxraybot.models import User
|
from nwxraybot.models import User
|
||||||
@@ -9,7 +10,8 @@ class MenuHandler(Handler):
|
|||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
|
||||||
@self.router.message()
|
# TODO: Temporary disabled
|
||||||
|
# @self.router.message(Command('menu'))
|
||||||
async def menu(message: types.Message) -> None:
|
async def menu(message: types.Message) -> None:
|
||||||
user: User = User.select().where(User.id == message.from_user.id).first()
|
user: User = User.select().where(User.id == message.from_user.id).first()
|
||||||
if user:
|
if user:
|
||||||
|
|||||||
@@ -1 +1,2 @@
|
|||||||
|
from nwxraybot.middlewares.admin import AdminMiddleware
|
||||||
from nwxraybot.middlewares.user import UserMiddleware
|
from nwxraybot.middlewares.user import UserMiddleware
|
||||||
|
|||||||
19
nwxraybot/middlewares/admin.py
Normal file
19
nwxraybot/middlewares/admin.py
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
from typing import Any, Awaitable, Callable, Dict, Optional
|
||||||
|
|
||||||
|
from aiogram import BaseMiddleware
|
||||||
|
from aiogram.types import Message
|
||||||
|
|
||||||
|
from nwxraybot.models import User
|
||||||
|
|
||||||
|
|
||||||
|
class AdminMiddleware(BaseMiddleware):
|
||||||
|
def __init__(self) -> None:
|
||||||
|
pass
|
||||||
|
|
||||||
|
async def __call__(self, handler: Callable[[Message, Dict[str, Any]], Awaitable[Any]], event: Message, data: Dict[str, Any]) -> Any:
|
||||||
|
user: User = User.select().where(
|
||||||
|
User.telegram_id == event.from_user.id).first()
|
||||||
|
if user is None or not user.admin:
|
||||||
|
await event.reply('Вы не обладаете правами администратора для доступа к данной команде.')
|
||||||
|
return None
|
||||||
|
return await handler(event, data)
|
||||||
@@ -14,8 +14,10 @@ class UserMiddleware(BaseMiddleware):
|
|||||||
async def __call__(self, handler: Callable[[Message, Dict[str, Any]], Awaitable[Any]], event: Message, data: Dict[str, Any]) -> Any:
|
async def __call__(self, handler: Callable[[Message, Dict[str, Any]], Awaitable[Any]], event: Message, data: Dict[str, Any]) -> Any:
|
||||||
if event.chat.type != ChatType.PRIVATE:
|
if event.chat.type != ChatType.PRIVATE:
|
||||||
return None
|
return None
|
||||||
|
if event.text.startswith('/start'):
|
||||||
|
return await handler(event, data)
|
||||||
user: Optional[User] = User.select().where(
|
user: Optional[User] = User.select().where(
|
||||||
User.id == event.from_user.id).first()
|
User.telegram_id == event.from_user.id).first()
|
||||||
if user is None:
|
if user is None:
|
||||||
await event.answer("Вы не зарегистрированы в системе, обратитесь к админам за доступом!")
|
await event.answer("Вы не зарегистрированы в системе, обратитесь к админам за доступом!")
|
||||||
return None
|
return None
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ class User(Model):
|
|||||||
url = CharField()
|
url = CharField()
|
||||||
time = DateTimeField(null=True)
|
time = DateTimeField(null=True)
|
||||||
admin = BooleanField(default=False)
|
admin = BooleanField(default=False)
|
||||||
|
telegram_id = CharField(null=True)
|
||||||
|
code = CharField()
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
database = db
|
database = db
|
||||||
|
|||||||
22
nwxraybot/utils.py
Normal file
22
nwxraybot/utils.py
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
import logging
|
||||||
|
from datetime import datetime
|
||||||
|
from secrets import token_urlsafe
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
from nwxraybot.models import User
|
||||||
|
|
||||||
|
|
||||||
|
def get_subscription_info(telegram_id: str) -> str:
|
||||||
|
user: User = User.select().where(User.telegram_id == telegram_id).first()
|
||||||
|
if user is None:
|
||||||
|
logging.error("[get_subscription_info]: User is not found")
|
||||||
|
return "Ошибка\!"
|
||||||
|
date: Optional[datetime] = user.time
|
||||||
|
date_str = "" if date is None else f'До: {
|
||||||
|
date.strftime("%d.%m.%Y %H:%M")} МСК\n'
|
||||||
|
res = f"Информация о подписке:\n{date_str}Ссылка: `{user.url}`"
|
||||||
|
return res
|
||||||
|
|
||||||
|
|
||||||
|
def get_code(length: int = 10) -> str:
|
||||||
|
return token_urlsafe(length)[:length]
|
||||||
Reference in New Issue
Block a user