Compare commits
3 Commits
af837b54be
...
7d50cf95cf
| Author | SHA1 | Date | |
|---|---|---|---|
| 7d50cf95cf | |||
| b5a893e5aa | |||
| 9ee8e43fb4 |
@@ -22,7 +22,7 @@ services:
|
||||
POSTGRES_USER: ${POSTGRES_USER:-postgres}
|
||||
POSTGRES_DB: ${POSTGRES_DB:-postgres}
|
||||
ports:
|
||||
- 5432
|
||||
- "127.0.0.1:${POSTGRES_PORT}:5432"
|
||||
healthcheck:
|
||||
test: ["CMD", "pg_isready"]
|
||||
interval: 10s
|
||||
|
||||
12
main.py
12
main.py
@@ -1,3 +1,4 @@
|
||||
import asyncio
|
||||
import logging
|
||||
from sys import exit
|
||||
|
||||
@@ -7,6 +8,10 @@ from nwxraybot import NwXrayBot, Settings
|
||||
from nwxraybot.handlers import *
|
||||
from nwxraybot.models import User
|
||||
|
||||
|
||||
async def main(bot: NwXrayBot, skip_updates: bool = True) -> None:
|
||||
await asyncio.create_task(bot.start())
|
||||
|
||||
if __name__ == "__main__":
|
||||
config = Settings() # Load config from .env
|
||||
logging.basicConfig(level=logging.DEBUG if config.debug else logging.INFO)
|
||||
@@ -18,7 +23,12 @@ if __name__ == "__main__":
|
||||
|
||||
User.create_table()
|
||||
|
||||
asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())
|
||||
loop = uvloop.new_event_loop()
|
||||
asyncio.set_event_loop(loop)
|
||||
|
||||
# Start bot
|
||||
bot = NwXrayBot(config.bot_token.get_secret_value())
|
||||
bot.include_routers(HelloHandler(), MenuHandler(), AdminHandler())
|
||||
uvloop.run(bot.start(skip_updates=True))
|
||||
|
||||
asyncio.run(main(bot))
|
||||
|
||||
@@ -2,6 +2,7 @@ from aiogram import Bot, Dispatcher, Router
|
||||
from aiogram.utils.callback_answer import CallbackAnswerMiddleware
|
||||
|
||||
from nwxraybot.middlewares import UserMiddleware
|
||||
from nwxraybot.notifiers import setup_subscription_notifier
|
||||
|
||||
from .meta import Handler
|
||||
|
||||
@@ -12,6 +13,7 @@ class NwXrayBot:
|
||||
self.dp = Dispatcher()
|
||||
self.dp.message.middleware(UserMiddleware())
|
||||
self.dp.message.middleware(CallbackAnswerMiddleware())
|
||||
setup_subscription_notifier(self.bot)
|
||||
|
||||
def include_routers(self, *routers: Handler):
|
||||
for router in routers:
|
||||
|
||||
@@ -19,7 +19,7 @@ class AdminHandler(Handler):
|
||||
|
||||
@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})$)"
|
||||
mask = r"^(?P<name>[a-zA-Z0-9]+)\s(?P<url>vless://[^\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:
|
||||
|
||||
@@ -27,22 +27,33 @@ class HelloHandler(Handler):
|
||||
@self.router.message(Command("start"))
|
||||
async def hello(message: types.Message):
|
||||
data = message.text.split()
|
||||
user: Optional[User] = None
|
||||
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 = User.select().where(
|
||||
User.code == code).first()
|
||||
if user is None:
|
||||
await message.answer('Пользователь не найден, обратитесь к администратору за ссылкой!')
|
||||
return
|
||||
user.telegram_id = message.from_user.id
|
||||
user.code = ''
|
||||
user.save()
|
||||
user = User.select().where(User.telegram_id == message.from_user.id).first()
|
||||
if user is None:
|
||||
await message.answer('Пользователь не найден, обратитесь к администратору за ссылкой!')
|
||||
return
|
||||
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')
|
||||
async def update_data(callback: CallbackQuery):
|
||||
await callback.message.edit_text(get_subscription_info(callback.from_user.id),
|
||||
reply_markup=self.__non_admin_main_menu(), parse_mode=ParseMode.MARKDOWN)
|
||||
text = get_subscription_info(callback.from_user.id)
|
||||
try:
|
||||
await callback.message.edit_text(get_subscription_info(callback.from_user.id),
|
||||
reply_markup=self.__non_admin_main_menu(), parse_mode=ParseMode.MARKDOWN)
|
||||
except:
|
||||
await callback.answer('Обновлений нет', show_alert=True)
|
||||
return
|
||||
|
||||
1
nwxraybot/notifiers/__init__.py
Normal file
1
nwxraybot/notifiers/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from nwxraybot.notifiers.subscription import setup_subscription_notifier
|
||||
28
nwxraybot/notifiers/subscription.py
Normal file
28
nwxraybot/notifiers/subscription.py
Normal file
@@ -0,0 +1,28 @@
|
||||
import asyncio
|
||||
import datetime
|
||||
import logging
|
||||
|
||||
from aiogram import Bot
|
||||
from apscheduler.schedulers.asyncio import AsyncIOScheduler
|
||||
|
||||
from nwxraybot.models import User
|
||||
|
||||
|
||||
# TODO: This shit is not working
|
||||
async def send_subscription_notification(bot: Bot, telegram_id: int) -> None:
|
||||
logging.debug(f"Sending subscription notification to {telegram_id}")
|
||||
|
||||
|
||||
async def check_subscription_status(bot: Bot):
|
||||
logging.debug('Running notifier task')
|
||||
await asyncio.sleep(1)
|
||||
for user in User.select():
|
||||
if user.telegram_id != '':
|
||||
await bot.send_message(user.telegram_id, 'Your subscription is active')
|
||||
|
||||
|
||||
def setup_subscription_notifier(bot: Bot) -> None:
|
||||
scheduler = AsyncIOScheduler(event_loop=asyncio.get_event_loop())
|
||||
scheduler.add_job(check_subscription_status,
|
||||
'interval', seconds=10, args=[bot])
|
||||
scheduler.start()
|
||||
@@ -10,7 +10,7 @@ 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 "Ошибка\!"
|
||||
return "Ошибка!"
|
||||
date: Optional[datetime] = user.time
|
||||
date_str = "" if date is None else f'До: {
|
||||
date.strftime("%d.%m.%Y %H:%M")} МСК\n'
|
||||
|
||||
59
poetry.lock
generated
59
poetry.lock
generated
@@ -1,4 +1,4 @@
|
||||
# This file is automatically @generated by Poetry 1.8.4 and should not be changed by hand.
|
||||
# This file is automatically @generated by Poetry 1.8.5 and should not be changed by hand.
|
||||
|
||||
[[package]]
|
||||
name = "aiofiles"
|
||||
@@ -185,6 +185,33 @@ files = [
|
||||
{file = "ansicon-1.89.0.tar.gz", hash = "sha256:e4d039def5768a47e4afec8e89e83ec3ae5a26bf00ad851f914d1240b444d2b1"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "apscheduler"
|
||||
version = "3.11.0"
|
||||
description = "In-process task scheduler with Cron-like capabilities"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "APScheduler-3.11.0-py3-none-any.whl", hash = "sha256:fc134ca32e50f5eadcc4938e3a4545ab19131435e851abb40b34d63d5141c6da"},
|
||||
{file = "apscheduler-3.11.0.tar.gz", hash = "sha256:4c622d250b0955a65d5d0eb91c33e6d43fd879834bf541e0a18661ae60460133"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
tzlocal = ">=3.0"
|
||||
|
||||
[package.extras]
|
||||
doc = ["packaging", "sphinx", "sphinx-rtd-theme (>=1.3.0)"]
|
||||
etcd = ["etcd3", "protobuf (<=3.21.0)"]
|
||||
gevent = ["gevent"]
|
||||
mongodb = ["pymongo (>=3.0)"]
|
||||
redis = ["redis (>=3.0)"]
|
||||
rethinkdb = ["rethinkdb (>=2.4.0)"]
|
||||
sqlalchemy = ["sqlalchemy (>=1.4)"]
|
||||
test = ["APScheduler[etcd,mongodb,redis,rethinkdb,sqlalchemy,tornado,zookeeper]", "PySide6", "anyio (>=4.5.2)", "gevent", "pytest", "pytz", "twisted"]
|
||||
tornado = ["tornado (>=4.3)"]
|
||||
twisted = ["twisted"]
|
||||
zookeeper = ["kazoo"]
|
||||
|
||||
[[package]]
|
||||
name = "attrs"
|
||||
version = "24.3.0"
|
||||
@@ -882,6 +909,34 @@ files = [
|
||||
{file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tzdata"
|
||||
version = "2024.2"
|
||||
description = "Provider of IANA time zone data"
|
||||
optional = false
|
||||
python-versions = ">=2"
|
||||
files = [
|
||||
{file = "tzdata-2024.2-py2.py3-none-any.whl", hash = "sha256:a48093786cdcde33cad18c2555e8532f34422074448fbc874186f0abd79565cd"},
|
||||
{file = "tzdata-2024.2.tar.gz", hash = "sha256:7d85cc416e9382e69095b7bdf4afd9e3880418a2413feec7069d533d6b4e31cc"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tzlocal"
|
||||
version = "5.2"
|
||||
description = "tzinfo object for the local timezone"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "tzlocal-5.2-py3-none-any.whl", hash = "sha256:49816ef2fe65ea8ac19d19aa7a1ae0551c834303d5014c6d5a62e4cbda8047b8"},
|
||||
{file = "tzlocal-5.2.tar.gz", hash = "sha256:8d399205578f1a9342816409cc1e46a93ebd5755e39ea2d85334bea911bf0e6e"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
tzdata = {version = "*", markers = "platform_system == \"Windows\""}
|
||||
|
||||
[package.extras]
|
||||
devenv = ["check-manifest", "pytest (>=4.3)", "pytest-cov", "pytest-mock (>=3.3)", "zest.releaser"]
|
||||
|
||||
[[package]]
|
||||
name = "uvloop"
|
||||
version = "0.21.0"
|
||||
@@ -1085,4 +1140,4 @@ propcache = ">=0.2.0"
|
||||
[metadata]
|
||||
lock-version = "2.0"
|
||||
python-versions = "^3.13"
|
||||
content-hash = "9b455b4a27b4038063fad5d023c0d2af06d7277a9b7ee02cc2d366e458f195b4"
|
||||
content-hash = "57654abddded59b21f10fc936a3f75bf5897bc0fd9ebcc81da38a5699d7ca90a"
|
||||
|
||||
@@ -14,6 +14,7 @@ peewee = "^3.17.8"
|
||||
uvloop = "^0.21.0"
|
||||
jurigged = "^0.6.0"
|
||||
psycopg2-binary = "^2.9.10"
|
||||
apscheduler = "^3.11.0"
|
||||
|
||||
|
||||
[build-system]
|
||||
|
||||
Reference in New Issue
Block a user