From 0e27db2b568e84d391e1f47726ea8f3a459daeab Mon Sep 17 00:00:00 2001
From: Seyed Mahdi <39972836+SeyedHashtag@users.noreply.github.com>
Date: Sat, 20 Dec 2025 14:29:27 +0330
Subject: [PATCH 01/19] feat(users): add option for displaying 1000 users in
the selection dropdown
---
core/scripts/webpanel/templates/users.html | 1 +
1 file changed, 1 insertion(+)
diff --git a/core/scripts/webpanel/templates/users.html b/core/scripts/webpanel/templates/users.html
index 12b85d2..f342e92 100644
--- a/core/scripts/webpanel/templates/users.html
+++ b/core/scripts/webpanel/templates/users.html
@@ -162,6 +162,7 @@
+
From d9f571d5a5aa89189f8ac5cee86edb2a0003be79 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Mon, 22 Dec 2025 13:16:32 +0000
Subject: [PATCH 02/19] chore(deps): Bump fastapi from 0.124.4 to 0.127.0
Bumps [fastapi](https://github.com/fastapi/fastapi) from 0.124.4 to 0.127.0.
- [Release notes](https://github.com/fastapi/fastapi/releases)
- [Commits](https://github.com/fastapi/fastapi/compare/0.124.4...0.127.0)
---
updated-dependencies:
- dependency-name: fastapi
dependency-version: 0.127.0
dependency-type: direct:production
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot]
---
requirements.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/requirements.txt b/requirements.txt
index 8433a81..7c0242c 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -28,7 +28,7 @@ pymongo==4.15.5
hysteria2-api==0.1.3
# Web panel (FastAPI stack)
-fastapi==0.124.4
+fastapi==0.127.0
Jinja2==3.1.6
python-multipart==0.0.21
hypercorn==0.18.0
From 3ae34fe3df8669bedf2867c3937ab47fbb5f0506 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Wed, 24 Dec 2025 13:12:24 +0000
Subject: [PATCH 03/19] chore(deps): Bump psutil from 7.1.3 to 7.2.0
Bumps [psutil](https://github.com/giampaolo/psutil) from 7.1.3 to 7.2.0.
- [Changelog](https://github.com/giampaolo/psutil/blob/master/HISTORY.rst)
- [Commits](https://github.com/giampaolo/psutil/compare/release-7.1.3...release-7.2.0)
---
updated-dependencies:
- dependency-name: psutil
dependency-version: 7.2.0
dependency-type: direct:production
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot]
---
requirements.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/requirements.txt b/requirements.txt
index 8433a81..6766048 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -6,7 +6,7 @@ aiofiles==25.1.0
click==8.3.1
# Utilities
-psutil==7.1.3
+psutil==7.2.0
python-dotenv==1.2.1
schedule==1.2.2
requests==2.32.5
From ea4014bceb03dc6a5b50c1c9f8d5dfb18162c516 Mon Sep 17 00:00:00 2001
From: ReturnFI <151555003+ReturnFI@users.noreply.github.com>
Date: Thu, 25 Dec 2025 17:10:42 +0000
Subject: [PATCH 04/19] fix(normalsub): conditionally generate sing-box obfs
config
---
core/scripts/normalsub/normalsub.py | 14 +++++++++-----
1 file changed, 9 insertions(+), 5 deletions(-)
diff --git a/core/scripts/normalsub/normalsub.py b/core/scripts/normalsub/normalsub.py
index af4906b..aa963e5 100644
--- a/core/scripts/normalsub/normalsub.py
+++ b/core/scripts/normalsub/normalsub.py
@@ -308,15 +308,11 @@ class SingboxConfigGenerator:
print(f"Error during Singbox config generation from URI: {e}, URI: {uri}")
return None
- return {
+ outbound_config = {
"type": "hysteria2",
"tag": unquote(parsed_url.fragment),
"server": server,
"server_port": server_port,
- "obfs": {
- "type": "salamander",
- "password": obfs_password
- },
"password": final_password,
"tls": {
"enabled": True,
@@ -325,6 +321,14 @@ class SingboxConfigGenerator:
}
}
+ if obfs_password:
+ outbound_config["obfs"] = {
+ "type": "salamander",
+ "password": obfs_password
+ }
+
+ return outbound_config
+
def combine_configs(self, all_uris: List[str], username: str, fragment: str) -> Optional[Dict[str, Any]]:
if not all_uris:
return None
From 4f5376af53c92fec64998ea8de813a8e808d3894 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Fri, 26 Dec 2025 13:14:13 +0000
Subject: [PATCH 05/19] chore(deps): Bump fastapi from 0.127.0 to 0.127.1
Bumps [fastapi](https://github.com/fastapi/fastapi) from 0.127.0 to 0.127.1.
- [Release notes](https://github.com/fastapi/fastapi/releases)
- [Commits](https://github.com/fastapi/fastapi/compare/0.127.0...0.127.1)
---
updated-dependencies:
- dependency-name: fastapi
dependency-version: 0.127.1
dependency-type: direct:production
update-type: version-update:semver-patch
...
Signed-off-by: dependabot[bot]
---
requirements.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/requirements.txt b/requirements.txt
index 46a7080..a8c8732 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -28,7 +28,7 @@ pymongo==4.15.5
hysteria2-api==0.1.3
# Web panel (FastAPI stack)
-fastapi==0.127.0
+fastapi==0.127.1
Jinja2==3.1.6
python-multipart==0.0.21
hypercorn==0.18.0
From 14f4df12128d593e1378c72984e1b16d32915f98 Mon Sep 17 00:00:00 2001
From: ReturnFI <151555003+ReturnFI@users.noreply.github.com>
Date: Sat, 27 Dec 2025 19:59:35 +0000
Subject: [PATCH 06/19] refactor(uri): Remove username from URI fragments
---
core/scripts/hysteria2/show_user_uri.py | 8 ++++----
core/scripts/hysteria2/wrapper_uri.py | 8 ++++----
2 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/core/scripts/hysteria2/show_user_uri.py b/core/scripts/hysteria2/show_user_uri.py
index 5981369..f361bf6 100644
--- a/core/scripts/hysteria2/show_user_uri.py
+++ b/core/scripts/hysteria2/show_user_uri.py
@@ -160,13 +160,13 @@ def show_uri(args: argparse.Namespace) -> None:
if args.all or args.ip_version == 4:
if ip4 and ip4 != "None":
uri = generate_uri(args.username, auth_password, ip4, local_port,
- local_obfs_password, local_sha256, local_sni, 4, local_insecure, f"{args.username}-IPv4")
+ local_obfs_password, local_sha256, local_sni, 4, local_insecure, "IPv4")
display_uri_and_qr(uri, "IPv4", args, terminal_width)
if args.all or args.ip_version == 6:
if ip6 and ip6 != "None":
uri = generate_uri(args.username, auth_password, ip6, local_port,
- local_obfs_password, local_sha256, local_sni, 6, local_insecure, f"{args.username}-IPv6")
+ local_obfs_password, local_sha256, local_sni, 6, local_insecure, "IPv6")
display_uri_and_qr(uri, "IPv6", args, terminal_width)
for node in nodes:
@@ -194,14 +194,14 @@ def show_uri(args: argparse.Namespace) -> None:
sni=node_sni,
ip_version=ip_v,
insecure=node_insecure,
- fragment_tag=f"{args.username}-{node_name}"
+ fragment_tag=node_name
)
display_uri_and_qr(uri, f"Node: {node_name} (IPv{ip_v})", args, terminal_width)
if args.singbox and is_service_active("hysteria-singbox.service"):
domain, port = get_singbox_domain_and_port()
if domain and port:
- print(f"\nSingbox Sublink:\nhttps://{domain}:{port}/sub/singbox/{args.username}/{args.ip_version}#{args.username}\n")
+ print(f"\nSingbox Sublink:\nhttps://{domain}:{port}/sub/singbox/{args.username}/{args.ip_version}#Hysteria2\n")
if args.normalsub and is_service_active("hysteria-normal-sub.service"):
domain, port, subpath = get_normalsub_domain_and_port()
diff --git a/core/scripts/hysteria2/wrapper_uri.py b/core/scripts/hysteria2/wrapper_uri.py
index d0246d3..0c5c65a 100644
--- a/core/scripts/hysteria2/wrapper_uri.py
+++ b/core/scripts/hysteria2/wrapper_uri.py
@@ -87,9 +87,9 @@ def process_users(target_usernames: List[str]) -> List[Dict[str, Any]]:
user_output = {"username": username, "ipv4": None, "ipv6": None, "nodes": [], "normal_sub": None}
if ip4 and ip4 != "None":
- user_output["ipv4"] = generate_uri(username, auth_password, ip4, default_port, base_uri_params, 4, f"{username}-IPv4")
+ user_output["ipv4"] = generate_uri(username, auth_password, ip4, default_port, base_uri_params, 4, "IPv4")
if ip6 and ip6 != "None":
- user_output["ipv6"] = generate_uri(username, auth_password, ip6, default_port, base_uri_params, 6, f"{username}-IPv6")
+ user_output["ipv6"] = generate_uri(username, auth_password, ip6, default_port, base_uri_params, 6, "IPv6")
for node in nodes:
node_name = node.get("name")
@@ -98,7 +98,7 @@ def process_users(target_usernames: List[str]) -> List[Dict[str, Any]]:
continue
ip_v = 6 if ':' in node_ip else 4
- tag = f"{username}-{node_name}"
+ tag = node_name
node_port = str(node.get("port", default_port))
node_sni = node.get("sni", default_sni)
@@ -117,7 +117,7 @@ def process_users(target_usernames: List[str]) -> List[Dict[str, Any]]:
user_output["nodes"].append({"name": node_name, "uri": uri})
if ns_domain and ns_port and ns_subpath:
- user_output["normal_sub"] = f"https://{ns_domain}:{ns_port}/{ns_subpath}/{auth_password}#{username}"
+ user_output["normal_sub"] = f"https://{ns_domain}:{ns_port}/{ns_subpath}/{auth_password}#Hysteria2"
results.append(user_output)
From 57210ba1ead87be5e1b61b82fce6198ae1429265 Mon Sep 17 00:00:00 2001
From: ReturnFI <151555003+ReturnFI@users.noreply.github.com>
Date: Sat, 27 Dec 2025 20:29:27 +0000
Subject: [PATCH 07/19] feat(outbounds): Add 'select' outbound type to the
configuration
---
core/scripts/normalsub/singbox.json | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/core/scripts/normalsub/singbox.json b/core/scripts/normalsub/singbox.json
index cbcebd1..da9789f 100644
--- a/core/scripts/normalsub/singbox.json
+++ b/core/scripts/normalsub/singbox.json
@@ -70,11 +70,19 @@
{
"outbounds": [
"auto",
- "direct"
+ "direct",
+ "select"
],
"tag": "proxy",
"type": "selector"
},
+ {
+ "type": "selector",
+ "tag": "select",
+
+ "outbounds": [],
+ "interrupt_exist_connections": false
+ },
{
"interval": "10m",
"outbounds": [],
From 975c8f32c313843a878383834b93bc57f6b21d2e Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Mon, 29 Dec 2025 13:17:38 +0000
Subject: [PATCH 08/19] chore(deps): Bump fastapi from 0.127.1 to 0.128.0
Bumps [fastapi](https://github.com/fastapi/fastapi) from 0.127.1 to 0.128.0.
- [Release notes](https://github.com/fastapi/fastapi/releases)
- [Commits](https://github.com/fastapi/fastapi/compare/0.127.1...0.128.0)
---
updated-dependencies:
- dependency-name: fastapi
dependency-version: 0.128.0
dependency-type: direct:production
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot]
---
requirements.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/requirements.txt b/requirements.txt
index a8c8732..3db72f0 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -28,7 +28,7 @@ pymongo==4.15.5
hysteria2-api==0.1.3
# Web panel (FastAPI stack)
-fastapi==0.127.1
+fastapi==0.128.0
Jinja2==3.1.6
python-multipart==0.0.21
hypercorn==0.18.0
From 4f789fb947fe2f8c80e0f42b1cb3cde21087c4c1 Mon Sep 17 00:00:00 2001
From: ReturnFI <151555003+ReturnFI@users.noreply.github.com>
Date: Tue, 30 Dec 2025 16:40:27 +0000
Subject: [PATCH 09/19] chore(deps): bump psutil from 7.2.0 to 7.2.1
---
requirements.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/requirements.txt b/requirements.txt
index a8c8732..4f962f6 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -6,7 +6,7 @@ aiofiles==25.1.0
click==8.3.1
# Utilities
-psutil==7.2.0
+psutil==7.2.1
python-dotenv==1.2.1
schedule==1.2.2
requests==2.32.5
From 6ab408c1d3f562778645d04785baaa227422ddf1 Mon Sep 17 00:00:00 2001
From: MiliAxe
Date: Wed, 31 Dec 2025 13:09:02 +0330
Subject: [PATCH 10/19] feat(cli): add option to display only the web panel URL
---
core/cli.py | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/core/cli.py b/core/cli.py
index 8518039..5c39552 100644
--- a/core/cli.py
+++ b/core/cli.py
@@ -670,10 +670,14 @@ def stop_webpanel_decoy():
click.echo(f'{e}', err=True)
@cli.command('get-webpanel-url')
-def get_web_panel_url():
+@click.option('--url-only', is_flag=True, help='Only display the URL without additional text')
+def get_web_panel_url(url_only: bool):
try:
url = cli_api.get_webpanel_url()
- click.echo(f'Hysteria web panel is now running. The service is accessible on: {url}')
+ if url_only:
+ click.echo(url)
+ else:
+ click.echo(f'Hysteria web panel is now running. The service is accessible on: {url}')
except Exception as e:
click.echo(f'{e}', err=True)
From 68ba04fd77ecb83c52f5910fff55d7769337755b Mon Sep 17 00:00:00 2001
From: MiliAxe
Date: Wed, 31 Dec 2025 13:10:11 +0330
Subject: [PATCH 11/19] feat(weburl): add handler to retrieve and display the
web panel URL
---
core/scripts/telegrambot/utils/__init__.py | 1 +
core/scripts/telegrambot/utils/common.py | 2 +-
core/scripts/telegrambot/utils/weburl.py | 8 ++++++++
3 files changed, 10 insertions(+), 1 deletion(-)
create mode 100644 core/scripts/telegrambot/utils/weburl.py
diff --git a/core/scripts/telegrambot/utils/__init__.py b/core/scripts/telegrambot/utils/__init__.py
index 49f6c6c..d771b25 100644
--- a/core/scripts/telegrambot/utils/__init__.py
+++ b/core/scripts/telegrambot/utils/__init__.py
@@ -8,3 +8,4 @@ from .search import *
from .serverinfo import *
from .cpu import *
from .check_version import *
+from .weburl import *
diff --git a/core/scripts/telegrambot/utils/common.py b/core/scripts/telegrambot/utils/common.py
index edf9c3c..e63b80a 100644
--- a/core/scripts/telegrambot/utils/common.py
+++ b/core/scripts/telegrambot/utils/common.py
@@ -4,5 +4,5 @@ def create_main_markup():
markup = types.ReplyKeyboardMarkup(resize_keyboard=True)
markup.row('β Add User', 'π Show User')
markup.row('ποΈ Delete User', 'π₯οΈ Server Info')
- markup.row('πΎ Backup Server')
+ markup.row('πΎ Backup Server', 'π Get Webpanel URL')
return markup
diff --git a/core/scripts/telegrambot/utils/weburl.py b/core/scripts/telegrambot/utils/weburl.py
new file mode 100644
index 0000000..27b4095
--- /dev/null
+++ b/core/scripts/telegrambot/utils/weburl.py
@@ -0,0 +1,8 @@
+from utils.command import *
+
+@bot.message_handler(func=lambda message: is_admin(message.from_user.id) and message.text == 'π Get Webpanel URL')
+def get_webpanel_url_handler(message):
+ command = f"python3 {CLI_PATH} get-webpanel-url --url-only"
+ result = run_cli_command(command)
+ bot.send_chat_action(message.chat.id, 'typing')
+ bot.reply_to(message, "π Webpanel URL:\n" + result)
\ No newline at end of file
From f8d6fb04da52b1891ab10c79ded9f34c63431a54 Mon Sep 17 00:00:00 2001
From: MiliAxe
Date: Wed, 31 Dec 2025 13:31:44 +0330
Subject: [PATCH 12/19] feat(weburl): add status check for webpanel service
before retrieving URL
---
core/scripts/telegrambot/utils/weburl.py | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/core/scripts/telegrambot/utils/weburl.py b/core/scripts/telegrambot/utils/weburl.py
index 27b4095..33df1bb 100644
--- a/core/scripts/telegrambot/utils/weburl.py
+++ b/core/scripts/telegrambot/utils/weburl.py
@@ -2,6 +2,13 @@ from utils.command import *
@bot.message_handler(func=lambda message: is_admin(message.from_user.id) and message.text == 'π Get Webpanel URL')
def get_webpanel_url_handler(message):
+ status_command = f"python3 {CLI_PATH} get-webpanel-services-status"
+ status_result = run_cli_command(status_command)
+
+ if "hysteria-webpanel.service: Inactive" in status_result:
+ bot.reply_to(message, "β οΈ The Webpanel service is currently inactive.")
+ return
+
command = f"python3 {CLI_PATH} get-webpanel-url --url-only"
result = run_cli_command(command)
bot.send_chat_action(message.chat.id, 'typing')
From ba72f0e9d8e40f8f73dba368b1b01507caf545a9 Mon Sep 17 00:00:00 2001
From: ReturnFI <151555003+ReturnFI@users.noreply.github.com>
Date: Wed, 31 Dec 2025 20:26:35 +0000
Subject: [PATCH 13/19] refactor: introduce settings submenu in Telegram bot
Co-authored-by: ReturnFI <151555003+ReturnFI@users.noreply.github.com>
---
core/scripts/telegrambot/utils/__init__.py | 1 +
core/scripts/telegrambot/utils/common.py | 8 +++++++-
2 files changed, 8 insertions(+), 1 deletion(-)
diff --git a/core/scripts/telegrambot/utils/__init__.py b/core/scripts/telegrambot/utils/__init__.py
index d771b25..4ec52d0 100644
--- a/core/scripts/telegrambot/utils/__init__.py
+++ b/core/scripts/telegrambot/utils/__init__.py
@@ -9,3 +9,4 @@ from .serverinfo import *
from .cpu import *
from .check_version import *
from .weburl import *
+from .settings import *
\ No newline at end of file
diff --git a/core/scripts/telegrambot/utils/common.py b/core/scripts/telegrambot/utils/common.py
index e63b80a..963b885 100644
--- a/core/scripts/telegrambot/utils/common.py
+++ b/core/scripts/telegrambot/utils/common.py
@@ -4,5 +4,11 @@ def create_main_markup():
markup = types.ReplyKeyboardMarkup(resize_keyboard=True)
markup.row('β Add User', 'π Show User')
markup.row('ποΈ Delete User', 'π₯οΈ Server Info')
- markup.row('πΎ Backup Server', 'π Get Webpanel URL')
+ markup.row('πΎ Backup Server', 'βοΈ Settings')
return markup
+
+def create_settings_markup():
+ markup = types.ReplyKeyboardMarkup(resize_keyboard=True)
+ markup.row('π Get Webpanel URL')
+ markup.row('β¬
οΈ Back')
+ return markup
\ No newline at end of file
From 694e9e895c01ba529e719204fe7470e3ba8685f3 Mon Sep 17 00:00:00 2001
From: ReturnFI <151555003+ReturnFI@users.noreply.github.com>
Date: Wed, 31 Dec 2025 20:30:03 +0000
Subject: [PATCH 14/19] feat(telegrambot): implement settings menu and back
navigation for admin users
---
core/scripts/telegrambot/utils/settings.py | 10 ++++++++++
1 file changed, 10 insertions(+)
create mode 100644 core/scripts/telegrambot/utils/settings.py
diff --git a/core/scripts/telegrambot/utils/settings.py b/core/scripts/telegrambot/utils/settings.py
new file mode 100644
index 0000000..0976044
--- /dev/null
+++ b/core/scripts/telegrambot/utils/settings.py
@@ -0,0 +1,10 @@
+from utils.command import *
+from utils.common import create_main_markup, create_settings_markup
+
+@bot.message_handler(func=lambda message: is_admin(message.from_user.id) and message.text == 'βοΈ Settings')
+def settings_menu_handler(message):
+ bot.send_message(message.chat.id, "βοΈ Settings Menu:", reply_markup=create_settings_markup())
+
+@bot.message_handler(func=lambda message: is_admin(message.from_user.id) and message.text == 'β¬
οΈ Back')
+def back_to_main_menu_handler(message):
+ bot.send_message(message.chat.id, "β¬
οΈ Returning to Main Menu...", reply_markup=create_main_markup())
\ No newline at end of file
From ddb548bf2147272680e9ca753e43035c4ae3e13e Mon Sep 17 00:00:00 2001
From: ReturnFI <151555003+ReturnFI@users.noreply.github.com>
Date: Wed, 31 Dec 2025 20:57:17 +0000
Subject: [PATCH 15/19] chore: update gitignore to track vscode settings
---
.gitignore | 1 +
1 file changed, 1 insertion(+)
diff --git a/.gitignore b/.gitignore
index 358b61c..a801946 100644
--- a/.gitignore
+++ b/.gitignore
@@ -161,3 +161,4 @@ cython_debug/
hysteria2_venv/
.vscode/
+!.vscode/settings.json
From a98ffeb41ebede63238d83b6f42286605e4a4df1 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Fri, 2 Jan 2026 13:15:11 +0000
Subject: [PATCH 16/19] chore(deps): Bump pillow from 12.0.0 to 12.1.0
Bumps [pillow](https://github.com/python-pillow/Pillow) from 12.0.0 to 12.1.0.
- [Release notes](https://github.com/python-pillow/Pillow/releases)
- [Changelog](https://github.com/python-pillow/Pillow/blob/main/CHANGES.rst)
- [Commits](https://github.com/python-pillow/Pillow/compare/12.0.0...12.1.0)
---
updated-dependencies:
- dependency-name: pillow
dependency-version: 12.1.0
dependency-type: direct:production
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot]
---
requirements.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/requirements.txt b/requirements.txt
index d00b644..184a85a 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -16,7 +16,7 @@ typing_extensions==4.15.0
pyTelegramBotAPI==4.29.1
qrcode==8.2
pypng==0.20220715.0
-pillow==12.0.0
+pillow==12.1.0
# Cache / misc
propcache==0.4.1
From a332079405e2e5e0968599807c2d4b2ac5935bf9 Mon Sep 17 00:00:00 2001
From: ReturnFI <151555003+ReturnFI@users.noreply.github.com>
Date: Fri, 2 Jan 2026 17:02:01 +0000
Subject: [PATCH 17/19] chore: update .gitignore to exclude .vscode directory
and retain settings.json
---
.gitignore | 4 +-
.vscode/settings.json | 172 ++++++++++++++++++++++++++++++++++++++++++
2 files changed, 174 insertions(+), 2 deletions(-)
create mode 100644 .vscode/settings.json
diff --git a/.gitignore b/.gitignore
index a801946..3043593 100644
--- a/.gitignore
+++ b/.gitignore
@@ -160,5 +160,5 @@ cython_debug/
#.idea/
hysteria2_venv/
-.vscode/
-!.vscode/settings.json
+# .vscode/
+# !.vscode/settings.json
diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 0000000..b19fff9
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,172 @@
+{
+ "workbench.colorTheme": "Default Dark+",
+ "workbench.colorCustomizations": {
+ "editor.background": "#252b3d",
+ "editor.foreground": "#dde1eb",
+ "activityBar.background": "#2f3648",
+ "activityBar.foreground": "#FF6B35",
+ "activityBar.activeBorder": "#FF6B35",
+ "activityBar.inactiveForeground": "#a8afc0",
+ "sideBar.background": "#2f3648",
+ "sideBar.foreground": "#dde1eb",
+ "sideBar.border": "#3a4158",
+ "sideBarTitle.foreground": "#FFA500",
+ "statusBar.background": "#2f3648",
+ "statusBar.foreground": "#58C4DC",
+ "statusBar.noFolderBackground": "#2f3648",
+ "statusBar.debuggingBackground": "#FF6347",
+ "statusBar.debuggingForeground": "#ffffff",
+ "titleBar.activeBackground": "#252b3d",
+ "titleBar.activeForeground": "#dde1eb",
+ "titleBar.inactiveBackground": "#252b3d",
+ "titleBar.inactiveForeground": "#a8afc0",
+ "titleBar.border": "#3a4158",
+ "editorGroupHeader.tabsBackground": "#252b3d",
+ "editorGroupHeader.tabsBorder": "#3a4158",
+ "tab.activeBackground": "#2f3648",
+ "tab.activeForeground": "#FFA500",
+ "tab.inactiveBackground": "#252b3d",
+ "tab.inactiveForeground": "#a8afc0",
+ "tab.border": "#3a4158",
+ "tab.activeBorder": "#FF6B35",
+ "tab.activeBorderTop": "#FF6B35",
+ "editorLineNumber.foreground": "#8891a4",
+ "editorLineNumber.activeForeground": "#58C4DC",
+ "editorCursor.foreground": "#FFA500",
+ "editor.selectionBackground": "#4a6589",
+ "editor.selectionHighlightBackground": "#4a658960",
+ "editor.lineHighlightBackground": "#2f364860",
+ "editorBracketMatch.background": "#4a658960",
+ "editorBracketMatch.border": "#FFA500",
+ "editorWidget.background": "#2f3648",
+ "editorSuggestWidget.background": "#2f3648",
+ "editorSuggestWidget.selectedBackground": "#4a6589",
+ "editorSuggestWidget.highlightForeground": "#FFA500",
+ "input.background": "#252b3d",
+ "input.border": "#3a4158",
+ "input.foreground": "#dde1eb",
+ "inputOption.activeBorder": "#58C4DC",
+ "dropdown.background": "#2f3648",
+ "dropdown.border": "#3a4158",
+ "button.background": "#3FB950",
+ "button.foreground": "#ffffff",
+ "button.hoverBackground": "#4ec55e",
+ "list.activeSelectionBackground": "#4a6589",
+ "list.activeSelectionForeground": "#ffffff",
+ "list.inactiveSelectionBackground": "#4a658960",
+ "list.hoverBackground": "#4a658950",
+ "list.focusBackground": "#4a6589",
+ "terminal.foreground": "#dde1eb",
+ "terminal.ansiGreen": "#3FB950",
+ "terminal.ansiYellow": "#D29922",
+ "terminal.ansiBlue": "#58A6FF",
+ "terminal.ansiMagenta": "#BC8CFF",
+ "terminal.ansiCyan": "#39C5CF",
+ "terminal.ansiRed": "#FF6347",
+ "gitDecoration.modifiedResourceForeground": "#D29922",
+ "gitDecoration.addedResourceForeground": "#3FB950",
+ "gitDecoration.deletedResourceForeground": "#FF6347",
+ "gitDecoration.untrackedResourceForeground": "#39C5CF",
+ "badge.background": "#FF6B35",
+ "badge.foreground": "#ffffff",
+ "notifications.background": "#2f3648",
+ "notifications.foreground": "#dde1eb",
+ "notifications.border": "#3a4158",
+ "notificationLink.foreground": "#58A6FF",
+ "panel.background": "#252b3d",
+ "panel.border": "#3a4158",
+ "panelTitle.activeForeground": "#FFA500",
+ "panelTitle.inactiveForeground": "#a8afc0",
+ "panelTitle.activeBorder": "#FF6B35"
+ },
+ "editor.tokenColorCustomizations": {
+ "textMateRules": [
+ {
+ "scope": "comment",
+ "settings": {
+ "foreground": "#8891a4",
+ "fontStyle": "italic"
+ }
+ },
+ {
+ "scope": ["keyword", "storage.type", "storage.modifier"],
+ "settings": {
+ "foreground": "#FF6347"
+ }
+ },
+ {
+ "scope": ["string", "string.quoted"],
+ "settings": {
+ "foreground": "#3FB950"
+ }
+ },
+ {
+ "scope": ["constant.numeric", "constant.language"],
+ "settings": {
+ "foreground": "#BC8CFF"
+ }
+ },
+ {
+ "scope": ["variable", "support.variable"],
+ "settings": {
+ "foreground": "#58A6FF"
+ }
+ },
+ {
+ "scope": ["entity.name.function", "support.function"],
+ "settings": {
+ "foreground": "#D29922"
+ }
+ },
+ {
+ "scope": ["entity.name.type", "entity.name.class", "support.class"],
+ "settings": {
+ "foreground": "#39C5CF"
+ }
+ },
+ {
+ "scope": ["entity.name.tag"],
+ "settings": {
+ "foreground": "#3FB950"
+ }
+ },
+ {
+ "scope": ["entity.other.attribute-name"],
+ "settings": {
+ "foreground": "#39C5CF"
+ }
+ },
+ {
+ "scope": ["support.type.property-name"],
+ "settings": {
+ "foreground": "#58A6FF"
+ }
+ },
+ {
+ "scope": ["meta.import", "meta.export"],
+ "settings": {
+ "foreground": "#BC8CFF"
+ }
+ },
+ {
+ "scope": ["punctuation.definition.tag"],
+ "settings": {
+ "foreground": "#a8afc0"
+ }
+ }
+ ]
+ },
+ "editor.fontFamily": "'JetBrains Mono', 'Fira Code', 'Cascadia Code', Consolas, 'Courier New', monospace",
+ "editor.fontSize": 13.5,
+ "editor.lineHeight": 1.6,
+ "editor.fontLigatures": true,
+ "editor.fontWeight": "400",
+ "editor.letterSpacing": 0.5,
+ "editor.cursorBlinking": "expand",
+ "editor.cursorSmoothCaretAnimation": "on",
+ "editor.smoothScrolling": true,
+ "workbench.list.smoothScrolling": true,
+ "editor.minimap.enabled": false,
+ "editor.bracketPairColorization.enabled": true,
+ "editor.guides.bracketPairs": "active"
+}
\ No newline at end of file
From 01efe34a4a3b0998bd75c73e872cd67473e936c5 Mon Sep 17 00:00:00 2001
From: ReturnFI <151555003+ReturnFI@users.noreply.github.com>
Date: Fri, 2 Jan 2026 17:27:12 +0000
Subject: [PATCH 18/19] Update changelog
---
changelog | 89 ++++++++++++++-----------------------------------------
1 file changed, 23 insertions(+), 66 deletions(-)
diff --git a/changelog b/changelog
index 5440a8a..14d1760 100644
--- a/changelog
+++ b/changelog
@@ -1,79 +1,36 @@
-# π¦ ** Release 2.5.0 β ACL & WARP fixes, safer password generation, service controls π**
+# π ** release(2.5.1): Telegram UX improvements, web panel access & outbound enhancements π **
-*Released: 2025-12-19*
+*Released: 2026-01-02*
## β¨ New Features
-### π§ **Core & Service Management**
+* π€ **Telegram Bot**: Added settings menu
+* π **Web Panel URL**:
-* π Added **Hysteria2 core version detection** and validation
-* π Display **core version** directly in the web panel
-* π Added **Restart Hysteria2** button in the web UI with proper fetch handling
-* π New API endpoint to **restart Hysteria2 service** programmatically
+ * Added service status check before retrieving web panel URL
+ * New handlers to retrieve and display web panel URL
+* π₯οΈ **CLI**: Added option to display *only* the web panel URL
+* π **Outbounds**: Introduced new `select` outbound type(SingBox)
+* π₯ **Users**: Added option to display up to **1000 users** in selection dropdown
+* β³ **Expiration**: Added validation for expiration days and improved UI
-### π **Geo & ACL Rule Management**
+### π Fixes
-* πΊοΈ Enhanced **Geo file update process** with intelligent ACL rule handling
-* π§© Added **geo rule detection & auto-update** for ACL configurations
-* π§Ή Removed redundant `geoip` / `geosite` rejection rules
-* π« Removed speedtest-related rejection from ACL rules
+* π‘οΈ Prevent enabling **Masquerade** when **OBFS** is active
+* βοΈ Conditionally generate **sing-box OBFS** configuration(SingBox)
-### π‘οΈ **Security & Password Handling**
+### β»οΈ Refactors & Improvements
-* π Replaced `pwgen` with **Python `secrets` module** for secure password generation
-* π Improved password generation for:
+* π§ Introduced settings submenu structure in Telegram bot
+* π Removed username from URI fragments
+* πΎ Streamlined upgrade backup process and removed geo data download
- * add-user
- * bulk users
- * internal password utilities
-* π§ͺ Removed implicit password auto-generation where not required
+### π§ Dependencies
-### π§° **CLI Improvements**
+* β¬οΈ **FastAPI** bumped to `0.128.0`
+* β¬οΈ **psutil** bumped to `7.2.1`
+* β¬οΈ **pillow** bumped to `12.1.0`
-* π€ Added `run_cmd_and_stream` for **real-time command output streaming**
-* βοΈ Improved error messages during **Hysteria2 installation**
-* π Updated install scripts to return meaningful output messages
-* π Replaced `pwgen` with **openssl** for:
-
- * obfs password generation
- * normalsub path generation
-
-### π **Network & IP Detection**
-
-* π Added **ip.sb fallback** for public IP detection to improve reliability
-
----
-
-## π Fixes & Improvements
-
-### π€ **User & Username Handling**
-
-* β
Allowed **underscores (`_`) in usernames**
-* π§Ό Improved validation regex and error handling
-* π§ Updated `remove-user` command syntax
-* π§ Improved user handler robustness
-
-### π **Masquerade & OBFS**
-
-* π« Prevented **OBFS usage when masquerade is enabled** to avoid conflicts
-
-### π§Ή **Scheduler & System Stability**
-
-* π Suppressed noisy `systemctl` output during scheduler setup
-* π§― Improved rule-checking logic for WARP configuration status
-
-### π§Ό **Uninstall & Cleanup**
-
-* β»οΈ Improved WARP uninstall flow:
-
- * Better config loading & error handling
- * Automatic **ACL rule reset** after uninstall
-
----
-
-## π¦ Dependency Updates
-
-* β¬οΈ **FastAPI** β 0.124.4
-* β¬οΈ **Certbot** β 5.2.2
-* β¬οΈ **python-multipart** β 0.0.21
+### β€οΈ Credits
+Special thanks to **@MiliAxe** and **@SeyedHashtag** for their valuable contributions π
From ab80f0280411a7bda6c1184eabbf5748c0a7e998 Mon Sep 17 00:00:00 2001
From: ReturnFI <151555003+ReturnFI@users.noreply.github.com>
Date: Fri, 2 Jan 2026 17:30:55 +0000
Subject: [PATCH 19/19] =?UTF-8?q?=F0=9F=94=96=20release(2.5.1):=20Telegram?=
=?UTF-8?q?=20settings=20UX,=20outbound=20enhancements=20&=20stability=20f?=
=?UTF-8?q?ixes=20=F0=9F=9A=80?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
VERSION | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/VERSION b/VERSION
index fad066f..4fd0fe3 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-2.5.0
\ No newline at end of file
+2.5.1
\ No newline at end of file