mirror of
https://github.com/house-of-vanity/OutFleet.git
synced 2025-10-23 16:59:08 +00:00
Fixed TG messages quotes. Fixed sync tasks loop.
This commit is contained in:
@@ -182,7 +182,7 @@ class TelegramBotManager:
|
|||||||
|
|
||||||
# Prepare user info
|
# Prepare user info
|
||||||
user_info = access_request.display_name
|
user_info = access_request.display_name
|
||||||
telegram_info = f"@{access_request.telegram_username}" if access_request.telegram_username else f"ID: {access_request.telegram_user_id}"
|
telegram_info = f"`@{access_request.telegram_username}`" if access_request.telegram_username else f"ID: {access_request.telegram_user_id}"
|
||||||
date = access_request.created_at.strftime("%Y-%m-%d %H:%M")
|
date = access_request.created_at.strftime("%Y-%m-%d %H:%M")
|
||||||
message = access_request.message_text[:200] + "..." if len(access_request.message_text) > 200 else access_request.message_text
|
message = access_request.message_text[:200] + "..." if len(access_request.message_text) > 200 else access_request.message_text
|
||||||
|
|
||||||
@@ -703,7 +703,7 @@ class TelegramBotManager:
|
|||||||
# Format detailed information
|
# Format detailed information
|
||||||
details = f"**📋 Request Details**\n\n"
|
details = f"**📋 Request Details**\n\n"
|
||||||
details += f"**👤 User:** {request.display_name}\n"
|
details += f"**👤 User:** {request.display_name}\n"
|
||||||
details += f"**📱 Telegram:** @{request.telegram_username}" if request.telegram_username else f"**📱 Telegram ID:** {request.telegram_user_id}\n"
|
details += f"**📱 Telegram:** `@{request.telegram_username}`" if request.telegram_username else f"**📱 Telegram ID:** {request.telegram_user_id}\n"
|
||||||
details += f"**📅 Date:** {request.created_at.strftime('%Y-%m-%d %H:%M:%S')}\n"
|
details += f"**📅 Date:** {request.created_at.strftime('%Y-%m-%d %H:%M:%S')}\n"
|
||||||
details += f"**🆔 Request ID:** {request.id}\n"
|
details += f"**🆔 Request ID:** {request.id}\n"
|
||||||
details += f"**👤 Desired Username:** {request.desired_username}\n\n"
|
details += f"**👤 Desired Username:** {request.desired_username}\n\n"
|
||||||
|
@@ -155,7 +155,7 @@ class TelegramMessage(models.Model):
|
|||||||
def display_name(self):
|
def display_name(self):
|
||||||
"""Get best available display name"""
|
"""Get best available display name"""
|
||||||
if self.telegram_username:
|
if self.telegram_username:
|
||||||
return f"@{self.telegram_username}"
|
return f"`@{self.telegram_username}`"
|
||||||
return self.full_name
|
return self.full_name
|
||||||
|
|
||||||
|
|
||||||
@@ -294,7 +294,7 @@ class AccessRequest(models.Model):
|
|||||||
def display_name(self):
|
def display_name(self):
|
||||||
"""Get best available display name"""
|
"""Get best available display name"""
|
||||||
if self.telegram_username:
|
if self.telegram_username:
|
||||||
return f"@{self.telegram_username}"
|
return f"`@{self.telegram_username}`"
|
||||||
|
|
||||||
name_parts = []
|
name_parts = []
|
||||||
if self.telegram_first_name:
|
if self.telegram_first_name:
|
||||||
|
@@ -469,13 +469,45 @@ class ServerAdmin(PolymorphicParentModelAdmin, BaseVPNAdmin):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
from vpn.tasks import sync_server_users
|
from vpn.tasks import sync_server_users
|
||||||
|
from celery import current_app
|
||||||
|
|
||||||
tasks_started = 0
|
tasks_started = 0
|
||||||
errors = []
|
errors = []
|
||||||
|
scheduled_tasks = set() # Track already scheduled tasks to avoid duplicates
|
||||||
|
|
||||||
for server in queryset:
|
for server in queryset:
|
||||||
try:
|
try:
|
||||||
|
# Check if a task is already running for this server
|
||||||
|
task_key = f"sync_server_{server.id}"
|
||||||
|
|
||||||
|
# Use Celery's inspect to check active tasks (optional, for better UX)
|
||||||
|
inspect = current_app.control.inspect()
|
||||||
|
active_tasks = inspect.active()
|
||||||
|
|
||||||
|
# Check if task is already scheduled for this server
|
||||||
|
task_already_running = False
|
||||||
|
if active_tasks:
|
||||||
|
for worker, tasks in active_tasks.items():
|
||||||
|
for task_info in tasks:
|
||||||
|
if task_info.get('name') == 'sync_server_users' and \
|
||||||
|
server.id in str(task_info.get('args', [])):
|
||||||
|
task_already_running = True
|
||||||
|
break
|
||||||
|
|
||||||
|
if task_already_running:
|
||||||
|
self.message_user(
|
||||||
|
request,
|
||||||
|
f"⏳ Sync already in progress for '{server.name}'",
|
||||||
|
level=messages.WARNING
|
||||||
|
)
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Avoid scheduling duplicate tasks in this batch
|
||||||
|
if server.id in scheduled_tasks:
|
||||||
|
continue
|
||||||
|
|
||||||
task = sync_server_users.delay(server.id)
|
task = sync_server_users.delay(server.id)
|
||||||
|
scheduled_tasks.add(server.id)
|
||||||
tasks_started += 1
|
tasks_started += 1
|
||||||
self.message_user(
|
self.message_user(
|
||||||
request,
|
request,
|
||||||
|
@@ -815,9 +815,14 @@ class XrayServerV2Admin(PolymorphicChildModelAdmin):
|
|||||||
actions = ['sync_users', 'sync_inbounds', 'get_status']
|
actions = ['sync_users', 'sync_inbounds', 'get_status']
|
||||||
|
|
||||||
def sync_users(self, request, queryset):
|
def sync_users(self, request, queryset):
|
||||||
|
from vpn.tasks import sync_server_users
|
||||||
|
scheduled_count = 0
|
||||||
for server in queryset:
|
for server in queryset:
|
||||||
server.sync_users()
|
# Directly schedule the task instead of calling server.sync_users()
|
||||||
self.message_user(request, f"Scheduled user sync for {queryset.count()} servers")
|
# to avoid potential recursion issues
|
||||||
|
sync_server_users.delay(server.id)
|
||||||
|
scheduled_count += 1
|
||||||
|
self.message_user(request, f"Scheduled user sync for {scheduled_count} servers")
|
||||||
sync_users.short_description = "Sync users for selected servers"
|
sync_users.short_description = "Sync users for selected servers"
|
||||||
|
|
||||||
def sync_inbounds(self, request, queryset):
|
def sync_inbounds(self, request, queryset):
|
||||||
|
55
vpn/tasks.py
55
vpn/tasks.py
@@ -123,8 +123,29 @@ def sync_xray_users(self, server_id):
|
|||||||
create_task_log(task_id, "sync_xray_users", f"Starting user sync for {server.name}", 'STARTED', server=server)
|
create_task_log(task_id, "sync_xray_users", f"Starting user sync for {server.name}", 'STARTED', server=server)
|
||||||
logger.info(f"Starting user sync for Xray server {server.name}")
|
logger.info(f"Starting user sync for Xray server {server.name}")
|
||||||
|
|
||||||
|
# Don't call sync_users() which would create another task - directly perform the sync
|
||||||
|
from vpn.models import User
|
||||||
|
from vpn.models_xray import UserSubscription
|
||||||
|
|
||||||
|
# Get all users who should have access to this server
|
||||||
|
users_to_sync = User.objects.filter(
|
||||||
|
xray_subscriptions__active=True,
|
||||||
|
xray_subscriptions__subscription_group__is_active=True
|
||||||
|
).distinct()
|
||||||
|
|
||||||
real_server = server.get_real_instance()
|
real_server = server.get_real_instance()
|
||||||
user_result = real_server.sync_users()
|
|
||||||
|
added_count = 0
|
||||||
|
failed_count = 0
|
||||||
|
for user in users_to_sync:
|
||||||
|
try:
|
||||||
|
if real_server.add_user(user):
|
||||||
|
added_count += 1
|
||||||
|
except Exception as e:
|
||||||
|
failed_count += 1
|
||||||
|
logger.error(f"Failed to sync user {user.username} on server {server.name}: {e}")
|
||||||
|
|
||||||
|
user_result = {"users_added": added_count, "total_users": users_to_sync.count(), "failed": failed_count}
|
||||||
|
|
||||||
success_message = f"Successfully synced {user_result.get('users_added', 0)} users for {server.name}"
|
success_message = f"Successfully synced {user_result.get('users_added', 0)} users for {server.name}"
|
||||||
logger.info(f"{success_message}. Result: {user_result}")
|
logger.info(f"{success_message}. Result: {user_result}")
|
||||||
@@ -247,16 +268,36 @@ def sync_users(self, server_id):
|
|||||||
|
|
||||||
create_task_log(task_id, "sync_all_users_on_server", f"Found {user_count} users to sync", 'STARTED', server=server, message=f"Users: {user_list}")
|
create_task_log(task_id, "sync_all_users_on_server", f"Found {user_count} users to sync", 'STARTED', server=server, message=f"Users: {user_list}")
|
||||||
|
|
||||||
# For Xray servers, use the new sync methods
|
# For Xray servers, use the sync_server_users task to avoid recursion
|
||||||
from vpn.server_plugins.xray_v2 import XrayServerV2
|
from vpn.server_plugins.xray_v2 import XrayServerV2
|
||||||
if isinstance(server.get_real_instance(), XrayServerV2):
|
if isinstance(server.get_real_instance(), XrayServerV2):
|
||||||
logger.info(f"Using XrayServerV2 sync for server {server.name}")
|
logger.info(f"Using XrayServerV2 sync for server {server.name}")
|
||||||
# Just call the sync method which schedules tasks asynchronously
|
# Call sync_server_users directly to perform the actual sync
|
||||||
sync_result = server.sync_users()
|
# Avoid calling server.sync_users() which would create another task
|
||||||
logger.info(f"Scheduled async sync for Xray server {server.name}")
|
from vpn.models import User
|
||||||
|
from vpn.models_xray import UserSubscription
|
||||||
|
|
||||||
|
# Get all users who should have access to this server
|
||||||
|
users_to_sync = User.objects.filter(
|
||||||
|
xray_subscriptions__active=True,
|
||||||
|
xray_subscriptions__subscription_group__is_active=True
|
||||||
|
).distinct()
|
||||||
|
|
||||||
|
added_count = 0
|
||||||
|
failed_count = 0
|
||||||
|
for user in users_to_sync:
|
||||||
|
try:
|
||||||
|
if server.add_user(user):
|
||||||
|
added_count += 1
|
||||||
|
except Exception as e:
|
||||||
|
failed_count += 1
|
||||||
|
logger.error(f"Failed to sync user {user.username} on server {server.name}: {e}")
|
||||||
|
|
||||||
|
sync_result = {"users_added": added_count, "total_users": users_to_sync.count(), "failed": failed_count}
|
||||||
|
logger.info(f"Directly synced {added_count} users for Xray server {server.name}")
|
||||||
else:
|
else:
|
||||||
# For non-Xray servers, just sync users
|
# For non-Xray servers, sync users directly (non-Xray servers should not create tasks)
|
||||||
sync_result = server.sync_users()
|
sync_result = server.sync_all_users()
|
||||||
|
|
||||||
# Check if sync was successful (can be boolean or dict/string)
|
# Check if sync was successful (can be boolean or dict/string)
|
||||||
sync_successful = bool(sync_result) and (
|
sync_successful = bool(sync_result) and (
|
||||||
|
Reference in New Issue
Block a user