Files
remnawave-minishop/bot/handlers/admin/sync_admin.py
T
2025-05-14 08:11:59 +00:00

126 lines
5.7 KiB
Python

import logging
from aiogram import Router ,types ,Bot
from aiogram .filters import Command
from typing import Optional
from config .settings import Settings
from bot .services .panel_api_service import PanelApiService
from db .database import update_sync_status ,get_last_sync_status ,sync_panel_user_data
from bot .middlewares .i18n import JsonI18n
from bot .keyboards .inline .admin_keyboards import get_back_to_admin_panel_keyboard
router =Router (name ="admin_sync_router")
@router .message (Command ("sync"))
async def sync_command_handler (
message :types .Message ,
bot :Bot ,
settings :Settings ,
i18n_data :dict ,
panel_service :PanelApiService
):
current_lang =i18n_data .get ("current_language",getattr (settings ,'DEFAULT_LANGUAGE','en'))
i18n :Optional [JsonI18n ]=i18n_data .get ("i18n_instance")
if not i18n :logging .error ("i18n missing");await message .answer ("Language error.");return
_ =lambda key ,**kwargs :i18n .gettext (current_lang ,key ,**kwargs )
await message .answer (_ ("sync_started"))
logging .info ("Admin triggered panel sync.")
users_processed_count =0
users_synced_successfully =0
sync_errors =[]
try :
panel_users_data =await panel_service .get_all_panel_users ()
if panel_users_data is None :
error_msg ="Failed to fetch users from panel or panel API issue."
sync_errors .append (error_msg )
await update_sync_status ("failed",error_msg )
await message .answer (_ ("sync_failed",details =error_msg ))
return
if not panel_users_data :
status_msg ="No users found in the panel to sync."
await update_sync_status ("success",status_msg ,0 ,0 )
await message .answer (_ ("sync_completed",status ="Success",details =status_msg ))
return
total_panel_users =len (panel_users_data )
logging .info (f"Starting sync for {total_panel_users} panel users.")
for panel_user_dict in panel_users_data :
users_processed_count +=1
telegram_id_from_panel =panel_user_dict .get ('telegramId')
panel_uuid =panel_user_dict .get ('uuid')
if not telegram_id_from_panel :
logging .info (f"Panel user {panel_uuid} (username: {panel_user_dict.get('username')}) has no 'telegramId'. Skipping TG ID based sync.")
continue
if not panel_uuid :
logging .warning (f"Panel user (TG ID: {telegram_id_from_panel}) missing 'uuid'. Skipping.")
sync_errors .append (f"Panel user data for TG ID {telegram_id_from_panel} missing UUID.")
continue
if await sync_panel_user_data (panel_user_dict ):
users_synced_successfully +=1
else :
sync_errors .append (f"Sync issue for panel user: {panel_uuid} (TG ID: {telegram_id_from_panel})")
if users_processed_count %20 ==0 :
logging .info (f"Sync progress: {users_processed_count}/{total_panel_users} users processed.")
status_msg =f"Panel users checked: {total_panel_users}. Users/Subscriptions synced via TG ID: {users_synced_successfully}."
if sync_errors :
status_msg +=f" Errors encountered: {len(sync_errors)}. See logs for details."
error_preview ="\n".join (sync_errors [:3 ])
await update_sync_status ("partial_success",status_msg +" "+error_preview ,total_panel_users ,users_synced_successfully )
await message .answer (_ ("sync_completed",status ="Partial Success",details =status_msg ))
else :
await update_sync_status ("success",status_msg ,total_panel_users ,users_synced_successfully )
await message .answer (_ ("sync_completed",status ="Success",details =status_msg ))
except Exception as e :
logging .error (f"Error during /sync command: {e}",exc_info =True )
error_detail =f"An unexpected error occurred during sync: {str(e)}"
await update_sync_status ("failed",error_detail ,users_processed_count ,users_synced_successfully )
await message .answer (_ ("sync_failed",details =error_detail ))
@router .message (Command ("syncstatus"))
async def sync_status_command_handler (message :types .Message ,i18n_data :dict ,settings :Settings ):
current_lang =i18n_data .get ("current_language",getattr (settings ,'DEFAULT_LANGUAGE','en'));i18n :Optional [JsonI18n ]=i18n_data .get ("i18n_instance")
if not i18n :await message .answer ("Language error.");return
_ =lambda key ,**kwargs :i18n .gettext (current_lang ,key ,**kwargs );status_record =await get_last_sync_status ();response_text =""
if status_record :
last_time_val =status_record ['last_sync_time'];last_time_str =last_time_val .strftime ('%Y-%m-%d %H:%M:%S UTC')if isinstance (last_time_val ,datetime )else str (last_time_val )
if isinstance (last_time_str ,str )and len (last_time_str )>19 :last_time_str =last_time_str [:19 ]
details_val =status_record ['details'];details_str =(details_val [:200 ]+"...")if details_val and len (details_val )>200 else (details_val or "N/A")
response_text =(f"<b>{_('admin_stats_last_sync_header')}</b>\n"
f" {_('admin_stats_sync_time')}: {last_time_str}\n"
f" {_('admin_stats_sync_status')}: {status_record['status']}\n"
f" {_('admin_stats_sync_users_processed')}: {status_record['users_processed_from_panel']}\n"
f" {_('admin_stats_sync_subs_synced')}: {status_record['subscriptions_synced']}\n"
f" {_('admin_stats_sync_details_label')}: {details_str}")
else :response_text =_ ("admin_sync_status_never_run")
await message .answer (response_text ,parse_mode ="HTML")