Code Refactoring
This commit is contained in:
+139
-106
@@ -1,127 +1,160 @@
|
||||
import logging
|
||||
import re
|
||||
from aiogram import Router ,F ,types ,Bot
|
||||
from aiogram .fsm .context import FSMContext
|
||||
from aiogram import Router, F, types, Bot
|
||||
from aiogram.fsm.context import FSMContext
|
||||
from typing import Optional
|
||||
|
||||
from config .settings import Settings
|
||||
from bot .states .user_states import UserPromoStates
|
||||
from bot .services .promo_code_service import PromoCodeService
|
||||
from bot .services .subscription_service import SubscriptionService
|
||||
from bot .keyboards .inline .user_keyboards import get_back_to_main_menu_markup
|
||||
from bot .middlewares .i18n import JsonI18n
|
||||
from aiogram .utils .markdown import hcode
|
||||
from config.settings import Settings
|
||||
from bot.states.user_states import UserPromoStates
|
||||
from bot.services.promo_code_service import PromoCodeService
|
||||
from bot.services.subscription_service import SubscriptionService
|
||||
from bot.keyboards.inline.user_keyboards import get_back_to_main_menu_markup
|
||||
from bot.middlewares.i18n import JsonI18n
|
||||
from aiogram.utils.markdown import hcode
|
||||
|
||||
from .start import send_main_menu
|
||||
|
||||
router =Router (name ="user_promo_router")
|
||||
router = Router(name="user_promo_router")
|
||||
|
||||
SUSPICIOUS_SQL_KEYWORDS_REGEX =re .compile (
|
||||
r"\b(DROP\s*TABLE|DELETE\s*FROM|ALTER\s*TABLE|TRUNCATE\s*TABLE|UNION\s*SELECT|;\s*SELECT|;\s*INSERT|;\s*UPDATE|;\s*DELETE|xp_cmdshell|sysdatabases|sysobjects|INFORMATION_SCHEMA)\b",
|
||||
re .IGNORECASE
|
||||
)
|
||||
SUSPICIOUS_CHARS_REGEX =re .compile (r"(--|#\s|;|\*\/|\/\*)")
|
||||
SUSPICIOUS_SQL_KEYWORDS_REGEX = re.compile(
|
||||
r"\b(DROP\s*TABLE|DELETE\s*FROM|ALTER\s*TABLE|TRUNCATE\s*TABLE|UNION\s*SELECT|;\s*SELECT|;\s*INSERT|;\s*UPDATE|;\s*DELETE|xp_cmdshell|sysdatabases|sysobjects|INFORMATION_SCHEMA)\b",
|
||||
re.IGNORECASE)
|
||||
SUSPICIOUS_CHARS_REGEX = re.compile(r"(--|#\s|;|\*\/|\/\*)")
|
||||
|
||||
async def prompt_promo_code_input (
|
||||
callback :types .CallbackQuery ,
|
||||
state :FSMContext ,
|
||||
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 callback .answer ("Language error.",show_alert =True );return
|
||||
_ =lambda key ,**kwargs :i18n .gettext (current_lang ,key ,**kwargs )
|
||||
|
||||
if not callback .message :
|
||||
logging .error ("CallbackQuery has no message in prompt_promo_code_input")
|
||||
await callback .answer (_ ("error_occurred_processing_request"),show_alert =True )
|
||||
async def prompt_promo_code_input(callback: types.CallbackQuery,
|
||||
state: FSMContext, 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 callback.answer("Language error.", show_alert=True)
|
||||
return
|
||||
_ = lambda key, **kwargs: i18n.gettext(current_lang, key, **kwargs)
|
||||
|
||||
if not callback.message:
|
||||
logging.error(
|
||||
"CallbackQuery has no message in prompt_promo_code_input")
|
||||
await callback.answer(_("error_occurred_processing_request"),
|
||||
show_alert=True)
|
||||
return
|
||||
|
||||
try :
|
||||
await callback .message .edit_text (
|
||||
text =_ (key ="promo_code_prompt"),
|
||||
reply_markup =get_back_to_main_menu_markup (current_lang ,i18n )
|
||||
try:
|
||||
await callback.message.edit_text(
|
||||
text=_(key="promo_code_prompt"),
|
||||
reply_markup=get_back_to_main_menu_markup(current_lang, i18n))
|
||||
except Exception as e:
|
||||
logging.warning(f"Failed to edit message for promo prompt: {e}")
|
||||
await callback.message.answer(
|
||||
text=_(key="promo_code_prompt"),
|
||||
reply_markup=get_back_to_main_menu_markup(current_lang, i18n))
|
||||
|
||||
await callback.answer()
|
||||
await state.set_state(UserPromoStates.waiting_for_promo_code)
|
||||
logging.info(
|
||||
f"User {callback.from_user.id} entered state UserPromoStates.waiting_for_promo_code. FSM state: {await state.get_state()}"
|
||||
)
|
||||
|
||||
|
||||
@router.message(UserPromoStates.waiting_for_promo_code, F.text)
|
||||
async def process_promo_code_input(message: types.Message, state: FSMContext,
|
||||
settings: Settings, i18n_data: dict,
|
||||
promo_code_service: PromoCodeService,
|
||||
bot: Bot):
|
||||
logging.info(
|
||||
f"Processing promo code input from user {message.from_user.id} in state {await state.get_state()}: '{message.text}'"
|
||||
)
|
||||
|
||||
current_lang = i18n_data.get("current_language",
|
||||
getattr(settings, 'DEFAULT_LANGUAGE', 'en'))
|
||||
i18n: Optional[JsonI18n] = i18n_data.get("i18n_instance")
|
||||
|
||||
if not i18n or not promo_code_service:
|
||||
logging.error("Deps missing in process_promo_code_input")
|
||||
await message.reply("Service error. Please try again.")
|
||||
await state.clear()
|
||||
return
|
||||
|
||||
_ = lambda key, **kwargs: i18n.gettext(current_lang, key, **kwargs)
|
||||
code_input = message.text.strip()
|
||||
user = message.from_user
|
||||
is_suspicious = False
|
||||
if SUSPICIOUS_SQL_KEYWORDS_REGEX.search(
|
||||
code_input) or SUSPICIOUS_CHARS_REGEX.search(code_input) or len(
|
||||
code_input) > 100:
|
||||
is_suspicious = True
|
||||
logging.warning(
|
||||
f"Suspicious input for promo by user {user.id} (len: {len(code_input)}): '{code_input}'"
|
||||
)
|
||||
except Exception as e :
|
||||
logging .warning (f"Failed to edit message for promo prompt: {e}")
|
||||
await callback .message .answer (text =_ (key ="promo_code_prompt"),reply_markup =get_back_to_main_menu_markup (current_lang ,i18n ))
|
||||
|
||||
await callback .answer ()
|
||||
await state .set_state (UserPromoStates .waiting_for_promo_code )
|
||||
logging .info (f"User {callback.from_user.id} entered state UserPromoStates.waiting_for_promo_code. FSM state: {await state.get_state()}")
|
||||
response_to_user_text = ""
|
||||
if is_suspicious:
|
||||
admin_notify_key = "admin_suspicious_promo_attempt_notification_no_username" if not user.username else "admin_suspicious_promo_attempt_notification"
|
||||
admin_lang = settings.DEFAULT_LANGUAGE
|
||||
_admin = lambda k, **kw: i18n.gettext(admin_lang, k, **kw)
|
||||
admin_notification_text = _admin(admin_notify_key,
|
||||
user_id=user.id,
|
||||
user_username=user.username or "N/A",
|
||||
user_first_name=user.first_name
|
||||
or "N/A",
|
||||
promo_code_input=hcode(code_input))
|
||||
try:
|
||||
await bot.send_message(settings.ADMIN_ID,
|
||||
admin_notification_text,
|
||||
parse_mode="HTML")
|
||||
except Exception as e_admin_notify:
|
||||
logging.error(
|
||||
f"Failed to send suspicious promo notification to admin: {e_admin_notify}"
|
||||
)
|
||||
response_to_user_text = _("promo_code_not_found",
|
||||
code=code_input.upper())
|
||||
else:
|
||||
success, response_text_from_service = await promo_code_service.apply_promo_code(
|
||||
user.id, code_input, current_lang)
|
||||
response_to_user_text = response_text_from_service
|
||||
|
||||
await message.answer(response_to_user_text,
|
||||
reply_markup=get_back_to_main_menu_markup(
|
||||
current_lang, i18n))
|
||||
await state.clear()
|
||||
logging.info(
|
||||
f"Promo code '{code_input}' processing finished for user {message.from_user.id}. State cleared."
|
||||
)
|
||||
|
||||
|
||||
@router .message (UserPromoStates .waiting_for_promo_code ,F .text )
|
||||
async def process_promo_code_input (
|
||||
message :types .Message ,
|
||||
state :FSMContext ,
|
||||
settings :Settings ,
|
||||
i18n_data :dict ,
|
||||
promo_code_service :PromoCodeService ,
|
||||
bot :Bot
|
||||
):
|
||||
logging .info (f"Processing promo code input from user {message.from_user.id} in state {await state.get_state()}: '{message.text}'")
|
||||
|
||||
current_lang =i18n_data .get ("current_language",getattr (settings ,'DEFAULT_LANGUAGE','en'))
|
||||
i18n :Optional [JsonI18n ]=i18n_data .get ("i18n_instance")
|
||||
|
||||
if not i18n or not promo_code_service :
|
||||
logging .error ("Deps missing in process_promo_code_input")
|
||||
await message .reply ("Service error. Please try again.")
|
||||
await state .clear ();return
|
||||
|
||||
_ =lambda key ,**kwargs :i18n .gettext (current_lang ,key ,**kwargs )
|
||||
code_input =message .text .strip ();user =message .from_user
|
||||
is_suspicious =False
|
||||
if SUSPICIOUS_SQL_KEYWORDS_REGEX .search (code_input )or SUSPICIOUS_CHARS_REGEX .search (code_input )or len (code_input )>100 :
|
||||
is_suspicious =True
|
||||
logging .warning (f"Suspicious input for promo by user {user.id} (len: {len(code_input)}): '{code_input}'")
|
||||
|
||||
response_to_user_text =""
|
||||
if is_suspicious :
|
||||
admin_notify_key ="admin_suspicious_promo_attempt_notification_no_username"if not user .username else "admin_suspicious_promo_attempt_notification"
|
||||
admin_lang =settings .DEFAULT_LANGUAGE
|
||||
_admin =lambda k ,**kw :i18n .gettext (admin_lang ,k ,**kw )
|
||||
admin_notification_text =_admin (admin_notify_key ,user_id =user .id ,user_username =user .username or "N/A",user_first_name =user .first_name or "N/A",promo_code_input =hcode (code_input ))
|
||||
try :await bot .send_message (settings .ADMIN_ID ,admin_notification_text ,parse_mode ="HTML")
|
||||
except Exception as e_admin_notify :logging .error (f"Failed to send suspicious promo notification to admin: {e_admin_notify}")
|
||||
response_to_user_text =_ ("promo_code_not_found",code =code_input .upper ())
|
||||
else :
|
||||
success ,response_text_from_service =await promo_code_service .apply_promo_code (user .id ,code_input ,current_lang )
|
||||
response_to_user_text =response_text_from_service
|
||||
|
||||
await message .answer (response_to_user_text ,reply_markup =get_back_to_main_menu_markup (current_lang ,i18n ))
|
||||
await state .clear ()
|
||||
logging .info (f"Promo code '{code_input}' processing finished for user {message.from_user.id}. State cleared.")
|
||||
|
||||
|
||||
|
||||
@router .callback_query (F .data =="main_action:back_to_main",UserPromoStates .waiting_for_promo_code )
|
||||
async def cancel_promo_input_via_button (
|
||||
callback :types .CallbackQuery ,
|
||||
state :FSMContext ,
|
||||
settings :Settings ,
|
||||
i18n_data :dict ,
|
||||
subscription_service :SubscriptionService
|
||||
):
|
||||
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 in cancel_promo_input_via_button")
|
||||
await callback .answer ("Language error",show_alert =True )
|
||||
@router.callback_query(F.data == "main_action:back_to_main",
|
||||
UserPromoStates.waiting_for_promo_code)
|
||||
async def cancel_promo_input_via_button(
|
||||
callback: types.CallbackQuery, state: FSMContext, settings: Settings,
|
||||
i18n_data: dict, subscription_service: SubscriptionService):
|
||||
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 in cancel_promo_input_via_button")
|
||||
await callback.answer("Language error", show_alert=True)
|
||||
return
|
||||
|
||||
logging .info (f"User {callback.from_user.id} cancelled promo code input via button from state {await state.get_state()}. Clearing state.")
|
||||
await state .clear ()
|
||||
logging .info (f"State after clear for user {callback.from_user.id}: {await state.get_state()}")
|
||||
logging.info(
|
||||
f"User {callback.from_user.id} cancelled promo code input via button from state {await state.get_state()}. Clearing state."
|
||||
)
|
||||
await state.clear()
|
||||
logging.info(
|
||||
f"State after clear for user {callback.from_user.id}: {await state.get_state()}"
|
||||
)
|
||||
|
||||
if callback .message :
|
||||
show_trial_button_on_back =False
|
||||
if settings .TRIAL_ENABLED and not await subscription_service .has_had_any_subscription (callback .from_user .id ):
|
||||
show_trial_button_on_back =True
|
||||
if callback.message:
|
||||
show_trial_button_on_back = False
|
||||
if settings.TRIAL_ENABLED and not await subscription_service.has_had_any_subscription(
|
||||
callback.from_user.id):
|
||||
show_trial_button_on_back = True
|
||||
|
||||
await send_main_menu (callback ,settings ,i18n_data ,show_trial_button_flag =show_trial_button_on_back ,is_edit =True )
|
||||
else :
|
||||
await send_main_menu(callback,
|
||||
settings,
|
||||
i18n_data,
|
||||
show_trial_button_flag=show_trial_button_on_back,
|
||||
is_edit=True)
|
||||
else:
|
||||
|
||||
await callback .answer ("Promo code input cancelled.",show_alert =False )
|
||||
await callback.answer("Promo code input cancelled.", show_alert=False)
|
||||
|
||||
Reference in New Issue
Block a user