Compare commits

...

16 Commits

Author SHA1 Message Date
ff615e2b67 Обновить .woodpecker/pipeline.yml
Some checks are pending
ci/woodpecker/push/pipeline Pipeline is pending
ci/woodpecker/manual/pipeline Pipeline is pending
2025-04-05 23:59:19 +03:00
1a93336d30 Deploy: change deployment
Some checks are pending
ci/woodpecker/push/pipeline Pipeline was successful
ci/woodpecker/manual/pipeline Pipeline is pending
2025-01-22 13:26:00 +03:00
17a1e4bb36 Feat: change deployment
All checks were successful
ci/woodpecker/push/pipeline Pipeline was successful
2025-01-22 13:25:45 +03:00
d5b045984f Deploy: update woodpecker
All checks were successful
ci/woodpecker/push/pipeline Pipeline was successful
ci/woodpecker/manual/pipeline Pipeline was successful
2025-01-22 12:59:58 +03:00
0faff426a7 Feat: update woodpecker
All checks were successful
ci/woodpecker/push/pipeline Pipeline was successful
2025-01-22 12:59:35 +03:00
e3a15dad50 Hotfix: pg_isready
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/manual/woodpecker Pipeline was successful
2025-01-20 15:27:47 +03:00
970a0e6fd4 Hotfix: pg_isready healthcheck
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2025-01-20 15:27:31 +03:00
8420ff3f52 Deploy: Added url correcter
All checks were successful
ci/woodpecker/manual/woodpecker Pipeline was successful
ci/woodpecker/push/woodpecker Pipeline was successful
2025-01-20 13:47:27 +03:00
c13eb62770 Feat: url correcter util
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2025-01-20 13:44:54 +03:00
8be7677f4b Deploy: Get users command
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/manual/woodpecker Pipeline was successful
2025-01-17 14:25:47 +03:00
0fa538d079 Feat: get users command
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2025-01-17 14:24:41 +03:00
fed548e9e8 Feat: admin help command 2025-01-17 14:10:02 +03:00
3ad4c2ea3e First hotfix
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/manual/woodpecker Pipeline was successful
2025-01-17 14:04:35 +03:00
e3c7f96693 Merge branch 'hotfix-start-command' 2025-01-17 13:52:33 +03:00
e82c392fc8 Hotfix: user deleting tg_id 2025-01-17 13:51:57 +03:00
0a844f7369 Deploy: First ever deploy
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/manual/woodpecker Pipeline was successful
2025-01-17 13:20:41 +03:00
8 changed files with 69 additions and 12 deletions

View File

@@ -5,5 +5,6 @@ POSTGRES_PASSWORD=postgres
POSTGRES_DB=postgres
POSTGRES_HOST=postgres
POSTGRES_PORT=5432
DOMAIN_NAME=localhost
COMPOSE_PROJECT_NAME=nwxraybot

View File

@@ -1,6 +1,3 @@
when:
- branch: [master, deploy]
event: [push, manual]
steps:
- name: build
image: docker:latest
@@ -13,7 +10,8 @@ steps:
ENV_FILE:
from_secret: ENV_FILE
when:
- event: [push, manual]
- branch: [deploy, master]
event: [push, manual]
- name: deploy
image: docker:latest
commands:
@@ -24,6 +22,7 @@ steps:
environment:
ENV_FILE:
from_secret: ENV_FILE
depends_on: [build]
depends_on: build
when:
- event: manual
- branch: deploy
event: manual

View File

@@ -24,7 +24,7 @@ services:
ports:
- "127.0.0.1:${POSTGRES_PORT}:5432"
healthcheck:
test: ["CMD", "pg_isready"]
test: ["CMD-SHELL", "pg_isready -d $${POSTGRES_DB} -U $${POSTGRES_USER}"]
interval: 10s
timeout: 5s
retries: 10

View File

@@ -1,3 +1,4 @@
from nwxraybot.bot import NwXrayBot
from nwxraybot.config import Settings
from nwxraybot.utils import get_code, get_subscription_info
from nwxraybot.utils import (get_code, get_correct_user_url,
get_subscription_info)

View File

@@ -10,6 +10,7 @@ class Settings(BaseSettings):
postgres_db: str = Field('db', env="POSTGRES_DB")
postgres_host: str = Field('localhost', env="POSTGRES_HOST")
postgres_port: int = Field(5432, env="POSTGRES_PORT")
domain_name: str = Field('localhost', env="DOMAIN_NAME")
@property
def postgres_url(self) -> str:

View File

@@ -16,6 +16,7 @@ from nwxraybot.fsm import BroadcastStates
from nwxraybot.meta import Handler
from nwxraybot.middlewares import AdminMiddleware
from nwxraybot.models import User
from nwxraybot.utils import get_correct_user_url
class AdminHandler(Handler):
@@ -24,6 +25,17 @@ class AdminHandler(Handler):
self.router.message.middleware(AdminMiddleware())
help_text = """Список команда администратора:
`/adduser name url [01.01.1970 00:00]` - добавить пользователя
`/updateuser name 01.01.1970 00:00` - обновить информацию о пользователе
`/broadcast` - рассылка (пошагово)
`/get_users` - список пользователей
"""
@self.router.message(Command('ahelp'))
async def help(message: Message):
await message.reply(help_text, parse_mode=ParseMode.MARKDOWN)
@self.router.message(Command('adduser'))
async def add_user(message: Message):
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})$)"
@@ -33,13 +45,15 @@ class AdminHandler(Handler):
await message.reply('Вы ввели команду в неверном формате. Вводите в формате:\n``` /adduser name vless://.... 01.01.1970 00:00```', parse_mode=ParseMode.MARKDOWN)
return
user_dict = match.groupdict()
url = user_dict['url']
url = get_correct_user_url(url)
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)
name=user_dict['name'], url=url, time=date, code=code)
new_user.save()
await message.answer(f'Пользователь создан. Вот его ссылка для доступа:\n`https://t.me/nwproxybot?start={code}`', parse_mode=ParseMode.MARKDOWN)
@@ -59,6 +73,24 @@ class AdminHandler(Handler):
query.execute()
await message.answer('Информация о пользователе обновлена.')
@self.router.message(Command('get_users'))
async def get_users(message: Message):
def get_user_info(user: User) -> str:
date_str = "" if user.time is None else f'До: {
user.time.strftime("%d.%m.%Y %H:%M")} МСК\n'
return f"Информация о пользователе `{user.name}`:\n{date_str}Ссылка: `{user.url}`\ncode: `{user.code if user.code else 'None'}`\n\n"
users = User.select()
res = ""
for user in users:
res += get_user_info(user)
try:
await message.answer(res, parse_mode=ParseMode.MARKDOWN)
except Exception as e:
await message.answer(f"Error while getting users: {e}")
logging.error(f"Error while getting user {
user.telegram_id}: {e}")
@self.router.message(Command('broadcast'))
async def start_broadcast(message: Message, state: FSMContext):
await message.answer('Отправьте для рассылки')

View File

@@ -30,14 +30,20 @@ class HelloHandler(Handler):
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 = User.select().where(
User.telegram_id == message.from_user.id).first()
if user is not None:
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)
return
user = User.select().where(
User.code == code).first()
if user is None:
await message.answer('Пользователь не найден, обратитесь к администратору за ссылкой!')
return
query = User.update(telegram_id=None).where(
User.telegram_id == message.from_user.id)
query.execute()
user.telegram_id = message.from_user.id
user.code = ''
user.save()

View File

@@ -2,9 +2,13 @@ import logging
from datetime import datetime
from secrets import token_urlsafe
from typing import Optional
from urllib.parse import parse_qs, urlencode, urlparse, urlunparse
from nwxraybot import Settings
from nwxraybot.models import User
config = Settings()
def get_subscription_info(telegram_id: str) -> str:
user: User = User.select().where(User.telegram_id == telegram_id).first()
@@ -20,3 +24,16 @@ def get_subscription_info(telegram_id: str) -> str:
def get_code(length: int = 10) -> str:
return token_urlsafe(length)[:length]
def get_correct_user_url(url: str) -> str:
parsed_url = urlparse(url)
query = parse_qs(parsed_url.query)
query['fp'] = 'chrome'
query['alpn'] = 'h2,h3'
query['packetEncoding'] = 'xudp'
query['security'] = 'tls'
new_query = urlencode(query, doseq=True)
new_url = urlunparse((parsed_url.scheme, parsed_url.netloc.replace("127.0.0.1:1234", f"{
config.domain_name}:443"), parsed_url.path, parsed_url.params, new_query, parsed_url.fragment))
return new_url