@ -1,2 +1,6 @@
|
||||
1. Fix: Changed geo category
|
||||
2. Reject(malware, phishing, cryptominers)
|
||||
3. Add: GeoCountry(Iran, China, and Russia)
|
||||
4. Add: Geo Update flag --country option(cli)
|
||||
5. Add: CPU monitoring module(Telegram-Bot)
|
||||
6. Add: Search users by the `blocked` status(Telegram-Bot)
|
||||
|
||||
@ -289,10 +289,14 @@ def ip_address(edit, ipv4, ipv6):
|
||||
run_cmd(['bash', Command.IP_ADD.value, 'add'])
|
||||
|
||||
@cli.command('update-geo')
|
||||
def cli_update_geo():
|
||||
@click.option('--country', '-c',
|
||||
type=click.Choice(['iran', 'china', 'russia'], case_sensitive=False),
|
||||
default='iran',
|
||||
help='Select country for geo files (default: iran)')
|
||||
def cli_update_geo(country):
|
||||
script_path = Command.UPDATE_GEO.value
|
||||
try:
|
||||
subprocess.run(['python3', script_path], check=True)
|
||||
subprocess.run(['python3', script_path, country.lower()], check=True)
|
||||
except subprocess.CalledProcessError as e:
|
||||
print(f"Failed to update geo files: {e}")
|
||||
except FileNotFoundError:
|
||||
|
||||
@ -1,46 +1,70 @@
|
||||
#!/usr/bin/env python3
|
||||
import os
|
||||
import subprocess
|
||||
from enum import Enum
|
||||
import sys
|
||||
import requests
|
||||
|
||||
|
||||
class GeoCountry(Enum):
|
||||
IRAN = {
|
||||
'geosite': 'https://github.com/chocolate4u/Iran-v2ray-rules/releases/latest/download/geosite.dat',
|
||||
'geoip': 'https://github.com/chocolate4u/Iran-v2ray-rules/releases/latest/download/geoip.dat'
|
||||
}
|
||||
CHINA = {
|
||||
'geosite': 'https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geosite.dat',
|
||||
'geoip': 'https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geoip.dat'
|
||||
}
|
||||
RUSSIA = {
|
||||
'geosite': 'https://github.com/runetfreedom/russia-v2ray-rules-dat/releases/latest/download/geosite.dat',
|
||||
'geoip': 'https://github.com/runetfreedom/russia-v2ray-rules-dat/releases/latest/download/geoip.dat'
|
||||
}
|
||||
|
||||
GEOSITE_PATH = "/etc/hysteria/geosite.dat"
|
||||
GEOIP_PATH = "/etc/hysteria/geoip.dat"
|
||||
GEOSITE_URL = "https://raw.githubusercontent.com/Chocolate4U/Iran-v2ray-rules/release/geosite.dat"
|
||||
GEOIP_URL = "https://raw.githubusercontent.com/Chocolate4U/Iran-v2ray-rules/release/geoip.dat"
|
||||
|
||||
|
||||
def remove_file(file_path):
|
||||
if os.path.exists(file_path):
|
||||
os.remove(file_path)
|
||||
print(f"Removed existing file: {file_path}")
|
||||
|
||||
|
||||
def download_file(url, destination):
|
||||
try:
|
||||
subprocess.run(
|
||||
["wget", "-O", destination, url],
|
||||
stdout=subprocess.DEVNULL,
|
||||
stderr=subprocess.DEVNULL,
|
||||
check=True
|
||||
)
|
||||
print(f"Downloaded {url} to {destination}")
|
||||
except subprocess.CalledProcessError:
|
||||
print(f"Failed to download {url}")
|
||||
if os.path.exists(file_path):
|
||||
os.remove(file_path)
|
||||
print(f"Removed existing file: {file_path}")
|
||||
except Exception as e:
|
||||
print(f"Error removing file {file_path}: {e}")
|
||||
|
||||
|
||||
def update_geo_files():
|
||||
def download_file(url, destination, chunk_size=8192):
|
||||
try:
|
||||
print("Starting geo files update...")
|
||||
destination_dir = os.path.dirname(destination)
|
||||
if destination_dir and not os.path.exists(destination_dir):
|
||||
os.makedirs(destination_dir)
|
||||
|
||||
response = requests.get(url, stream=True)
|
||||
response.raise_for_status()
|
||||
|
||||
with open(destination, "wb") as file:
|
||||
for chunk in response.iter_content(chunk_size=chunk_size):
|
||||
file.write(chunk)
|
||||
|
||||
print(f"File successfully downloaded to: {destination}")
|
||||
|
||||
except requests.exceptions.RequestException as e:
|
||||
print(f"Error: Failed to download the file from '{url}'.\n{e}")
|
||||
except IOError as e:
|
||||
print(f"Error: Failed to save the file to '{destination}'.\n{e}")
|
||||
|
||||
def update_geo_files(country='iran'):
|
||||
try:
|
||||
print(f"Starting geo files update for {country.upper()}...")
|
||||
country_enum = GeoCountry[country.upper()]
|
||||
remove_file(GEOSITE_PATH)
|
||||
remove_file(GEOIP_PATH)
|
||||
download_file(GEOSITE_URL, GEOSITE_PATH)
|
||||
download_file(GEOIP_URL, GEOIP_PATH)
|
||||
|
||||
download_file(country_enum.value['geosite'], GEOSITE_PATH)
|
||||
download_file(country_enum.value['geoip'], GEOIP_PATH)
|
||||
print("Geo files update completed successfully.")
|
||||
|
||||
except KeyError:
|
||||
print(f"Invalid country selection. Available options: {', '.join([c.name.lower() for c in GeoCountry])}")
|
||||
except Exception as e:
|
||||
print(f"An error occurred during the update process: {e}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
update_geo_files()
|
||||
country = sys.argv[1] if len(sys.argv) > 1 else 'iran'
|
||||
update_geo_files(country)
|
||||
|
||||
@ -7,6 +7,9 @@ from utils.deleteuser import *
|
||||
from utils.edituser import *
|
||||
from utils.search import *
|
||||
from utils.serverinfo import *
|
||||
from utils.cpu import *
|
||||
import threading
|
||||
import time
|
||||
|
||||
@bot.message_handler(commands=['start'])
|
||||
def send_welcome(message):
|
||||
@ -16,5 +19,12 @@ def send_welcome(message):
|
||||
else:
|
||||
bot.reply_to(message, "Unauthorized access. You do not have permission to use this bot.")
|
||||
|
||||
def monitoring_thread():
|
||||
while True:
|
||||
monitor_system_resources()
|
||||
time.sleep(60)
|
||||
|
||||
if __name__ == '__main__':
|
||||
monitor_thread = threading.Thread(target=monitoring_thread, daemon=True)
|
||||
monitor_thread.start()
|
||||
bot.polling(none_stop=True)
|
||||
|
||||
64
core/scripts/telegrambot/utils/cpu.py
Normal file
64
core/scripts/telegrambot/utils/cpu.py
Normal file
@ -0,0 +1,64 @@
|
||||
import psutil
|
||||
import time
|
||||
from utils.command import *
|
||||
|
||||
|
||||
def get_system_usage():
|
||||
cpu_usage = psutil.cpu_percent(interval=1)
|
||||
ram = psutil.virtual_memory()
|
||||
ram_usage = ram.percent
|
||||
return cpu_usage, ram_usage
|
||||
|
||||
def format_alert_message(cpu_usage, ram_usage):
|
||||
return (
|
||||
"🚨ALERT🚨\n"
|
||||
"High CPU and RAM usage detected ⚠️\n\n"
|
||||
f"📈 CPU: {cpu_usage:.1f}%\n"
|
||||
f"📋 RAM: {ram_usage:.1f}%"
|
||||
)
|
||||
|
||||
def monitor_system_resources():
|
||||
# Thresholds
|
||||
CPU_THRESHOLD = 90.0
|
||||
RAM_THRESHOLD = 90.0
|
||||
CONFIRMATION_DELAY = 60 # seconds
|
||||
|
||||
try:
|
||||
cpu_usage, ram_usage = get_system_usage()
|
||||
|
||||
if cpu_usage > CPU_THRESHOLD and ram_usage > RAM_THRESHOLD:
|
||||
time.sleep(CONFIRMATION_DELAY)
|
||||
cpu_usage, ram_usage = get_system_usage()
|
||||
|
||||
if cpu_usage > CPU_THRESHOLD and ram_usage > RAM_THRESHOLD:
|
||||
alert_message = format_alert_message(cpu_usage, ram_usage)
|
||||
|
||||
for admin_id in ADMIN_USER_IDS:
|
||||
try:
|
||||
bot.send_message(admin_id, alert_message)
|
||||
except Exception as e:
|
||||
print(f"Failed to send alert to admin {admin_id}: {str(e)}")
|
||||
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error monitoring system resources: {str(e)}")
|
||||
|
||||
return False
|
||||
|
||||
@bot.message_handler(commands=['system'])
|
||||
def check_system(message):
|
||||
if not is_admin(message.from_user.id):
|
||||
bot.reply_to(message, "Unauthorized access. You do not have permission to use this command.")
|
||||
return
|
||||
|
||||
try:
|
||||
cpu_usage, ram_usage = get_system_usage()
|
||||
response = (
|
||||
"📊 System Resource Usage 📊\n\n"
|
||||
f"📈 CPU Usage: {cpu_usage:.1f}%\n"
|
||||
f"📋 RAM Usage: {ram_usage:.1f}%"
|
||||
)
|
||||
bot.reply_to(message, response)
|
||||
except Exception as e:
|
||||
bot.reply_to(message, f"Error checking system resources: {str(e)}")
|
||||
@ -1,7 +1,6 @@
|
||||
from telebot import types
|
||||
from utils.command import *
|
||||
|
||||
|
||||
@bot.inline_handler(lambda query: is_admin(query.from_user.id))
|
||||
def handle_inline_query(query):
|
||||
command = f"python3 {CLI_PATH} list-users"
|
||||
@ -14,21 +13,40 @@ def handle_inline_query(query):
|
||||
|
||||
query_text = query.query.lower()
|
||||
results = []
|
||||
for username, details in users.items():
|
||||
if query_text in username.lower():
|
||||
title = f"{username}"
|
||||
description = f"Traffic Limit: {details['max_download_bytes'] / (1024 ** 3):.2f} GB, Expiration Days: {details['expiration_days']}"
|
||||
results.append(types.InlineQueryResultArticle(
|
||||
id=username,
|
||||
title=title,
|
||||
description=description,
|
||||
input_message_content=types.InputTextMessageContent(
|
||||
message_text=f"Name: {username}\n"
|
||||
f"Traffic limit: {details['max_download_bytes'] / (1024 ** 3):.2f} GB\n"
|
||||
f"Days: {details['expiration_days']}\n"
|
||||
f"Account Creation: {details['account_creation_date']}\n"
|
||||
f"Blocked: {details['blocked']}"
|
||||
)
|
||||
))
|
||||
|
||||
if query_text == "block":
|
||||
for username, details in users.items():
|
||||
if details.get('blocked', False):
|
||||
title = f"{username} (Blocked)"
|
||||
description = f"Traffic Limit: {details['max_download_bytes'] / (1024 ** 3):.2f} GB, Expiration Days: {details['expiration_days']}"
|
||||
results.append(types.InlineQueryResultArticle(
|
||||
id=username,
|
||||
title=title,
|
||||
description=description,
|
||||
input_message_content=types.InputTextMessageContent(
|
||||
message_text=f"Name: {username}\n"
|
||||
f"Traffic limit: {details['max_download_bytes'] / (1024 ** 3):.2f} GB\n"
|
||||
f"Days: {details['expiration_days']}\n"
|
||||
f"Account Creation: {details['account_creation_date']}\n"
|
||||
f"Blocked: {details['blocked']}"
|
||||
)
|
||||
))
|
||||
else:
|
||||
for username, details in users.items():
|
||||
if query_text in username.lower():
|
||||
title = f"{username}"
|
||||
description = f"Traffic Limit: {details['max_download_bytes'] / (1024 ** 3):.2f} GB, Expiration Days: {details['expiration_days']}"
|
||||
results.append(types.InlineQueryResultArticle(
|
||||
id=username,
|
||||
title=title,
|
||||
description=description,
|
||||
input_message_content=types.InputTextMessageContent(
|
||||
message_text=f"Name: {username}\n"
|
||||
f"Traffic limit: {details['max_download_bytes'] / (1024 ** 3):.2f} GB\n"
|
||||
f"Days: {details['expiration_days']}\n"
|
||||
f"Account Creation: {details['account_creation_date']}\n"
|
||||
f"Blocked: {details['blocked']}"
|
||||
)
|
||||
))
|
||||
|
||||
bot.answer_inline_query(query.id, results, cache_time=0)
|
||||
53
menu.sh
53
menu.sh
@ -589,6 +589,57 @@ obfs_handler() {
|
||||
done
|
||||
}
|
||||
|
||||
geo_update_handler() {
|
||||
echo "Configure Geo Update Options:"
|
||||
echo "1. Update Iran Geo Files"
|
||||
echo "2. Update China Geo Files"
|
||||
echo "3. Update Russia Geo Files"
|
||||
echo "4. Check Current Geo Files"
|
||||
echo "0. Cancel"
|
||||
|
||||
read -p "Select an option: " option
|
||||
|
||||
case $option in
|
||||
1)
|
||||
echo "Updating Iran Geo Files..."
|
||||
python3 $CLI_PATH update-geo --country iran
|
||||
;;
|
||||
2)
|
||||
echo "Updating China Geo Files..."
|
||||
python3 $CLI_PATH update-geo --country china
|
||||
;;
|
||||
3)
|
||||
echo "Updating Russia Geo Files..."
|
||||
python3 $CLI_PATH update-geo --country russia
|
||||
;;
|
||||
4)
|
||||
echo "Current Geo Files Information:"
|
||||
echo "--------------------------"
|
||||
if [ -f "/etc/hysteria/geosite.dat" ]; then
|
||||
echo "GeoSite File:"
|
||||
ls -lh /etc/hysteria/geosite.dat
|
||||
echo "Last modified: $(stat -c %y /etc/hysteria/geosite.dat)"
|
||||
else
|
||||
echo "GeoSite file not found!"
|
||||
fi
|
||||
echo
|
||||
if [ -f "/etc/hysteria/geoip.dat" ]; then
|
||||
echo "GeoIP File:"
|
||||
ls -lh /etc/hysteria/geoip.dat
|
||||
echo "Last modified: $(stat -c %y /etc/hysteria/geoip.dat)"
|
||||
else
|
||||
echo "GeoIP file not found!"
|
||||
fi
|
||||
;;
|
||||
0)
|
||||
echo "Geo update configuration canceled."
|
||||
;;
|
||||
*)
|
||||
echo "Invalid option. Please try again."
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Function to display the main menu
|
||||
display_main_menu() {
|
||||
clear
|
||||
@ -737,7 +788,7 @@ advance_menu() {
|
||||
9) hysteria2_change_sni_handler ;;
|
||||
10) obfs_handler ;;
|
||||
11) edit_ips ;;
|
||||
12) python3 $CLI_PATH update-geo ;;
|
||||
12) geo_update_handler ;;
|
||||
13) python3 $CLI_PATH restart-hysteria2 ;;
|
||||
14) python3 $CLI_PATH update-hysteria2 ;;
|
||||
15) python3 $CLI_PATH uninstall-hysteria2 ;;
|
||||
|
||||
@ -4,3 +4,4 @@ python-dotenv==1.0.1
|
||||
requests==2.32.3
|
||||
aiohttp==3.10.5
|
||||
click==8.1.7
|
||||
psutil==6.1.1
|
||||
|
||||
Reference in New Issue
Block a user