From 7297eb9be2a98207b3175028cb41209decce52e8 Mon Sep 17 00:00:00 2001 From: Whispering Wind <151555003+ReturnFI@users.noreply.github.com> Date: Mon, 14 Apr 2025 00:08:14 +0330 Subject: [PATCH] feat: enhance kick functionality with specific user kick and integration --- core/cli.py | 12 +++++++++++ core/cli_api.py | 13 +++++++++++ core/scripts/hysteria2/kickuser.sh | 31 +++++++++++++++++++++++++++ core/scripts/hysteria2/remove_user.sh | 2 +- 4 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 core/scripts/hysteria2/kickuser.sh diff --git a/core/cli.py b/core/cli.py index 12d633e..a226786 100644 --- a/core/cli.py +++ b/core/cli.py @@ -169,11 +169,23 @@ def reset_user(username: str): @click.option('--username', '-u', required=True, help='Username for the user to remove', type=str) def remove_user(username: str): try: + cli_api.kick_user_by_name(username) + cli_api.traffic_status() cli_api.remove_user(username) click.echo(f"User '{username}' removed successfully.") except Exception as e: click.echo(f'{e}', err=True) +@cli.command('kick-user') +@click.option('--username', '-u', required=True, help='Username of the user to kick') +def kick_user(username: str): + """Kicks a specific user by username.""" + try: + cli_api.kick_user_by_name(username) + click.echo(f"User '{username}' kicked successfully.") + except Exception as e: + click.echo(f'{e}', err=True) + @cli.command('show-user-uri') @click.option('--username', '-u', required=True, help='Username for the user to show the URI', type=str) diff --git a/core/cli_api.py b/core/cli_api.py index e072bb0..01abcec 100644 --- a/core/cli_api.py +++ b/core/cli_api.py @@ -49,6 +49,8 @@ class Command(Enum): SERVICES_STATUS = os.path.join(SCRIPT_DIR, 'services_status.sh') VERSION = os.path.join(SCRIPT_DIR, 'hysteria2', 'version.py') LIMIT_SCRIPT = os.path.join(SCRIPT_DIR, 'hysteria2', 'limit.sh') + KICK_USER_SCRIPT = os.path.join(SCRIPT_DIR, 'hysteria2', 'kickuser.sh') + # region Custom Exceptions @@ -302,6 +304,17 @@ def remove_user(username: str): ''' run_cmd(['bash', Command.REMOVE_USER.value, username]) +def kick_user_by_name(username: str): + '''Kicks a specific user by username.''' + if not username: + raise InvalidInputError('Username must be provided to kick a specific user.') + script_path = Command.KICK_USER_SCRIPT.value + if not os.path.exists(script_path): + raise ScriptNotFoundError(f"Kick user script not found at: {script_path}") + try: + subprocess.run(['bash', script_path, username], check=True) + except subprocess.CalledProcessError as e: + raise CommandExecutionError(f"Failed to execute kick user script: {e}") # TODO: it's better to return json def show_user_uri(username: str, qrcode: bool, ipv: int, all: bool, singbox: bool, normalsub: bool) -> str | None: diff --git a/core/scripts/hysteria2/kickuser.sh b/core/scripts/hysteria2/kickuser.sh new file mode 100644 index 0000000..d8f6b03 --- /dev/null +++ b/core/scripts/hysteria2/kickuser.sh @@ -0,0 +1,31 @@ +#!/bin/bash + +USERNAME="$1" + +if [ -z "$USERNAME" ]; then + echo "Usage: kickuser.sh " + exit 1 +fi + +source /etc/hysteria/core/scripts/path.sh + +SECRET=$(jq -r '.trafficStats.secret' "$CONFIG_FILE") +KICK_ENDPOINT="http://127.0.0.1:25413/kick" + +if [ -z "$SECRET" ]; then + echo "Error: Could not retrieve trafficStats secret from config.json" + exit 1 +fi + +echo "Kicking user: $USERNAME" + +curl -s -H "Authorization: $SECRET" -X POST -d "[\"$USERNAME\"]" "$KICK_ENDPOINT" + +if [ $? -eq 0 ]; then + echo "User '$USERNAME' kicked successfully." +else + echo "Error kicking user '$USERNAME'." + exit 1 +fi + +exit 0 \ No newline at end of file diff --git a/core/scripts/hysteria2/remove_user.sh b/core/scripts/hysteria2/remove_user.sh index 1a396d2..361f1d7 100644 --- a/core/scripts/hysteria2/remove_user.sh +++ b/core/scripts/hysteria2/remove_user.sh @@ -24,5 +24,5 @@ remove_user() { echo -e "${red}Error:${NC} Config file $USERS_FILE not found." fi } -python3 "$CLI_PATH" restart-hysteria2 > /dev/null 2>&1 +# python3 "$CLI_PATH" restart-hysteria2 > /dev/null 2>&1 remove_user "$1"