Initial commit
This commit is contained in:
@@ -0,0 +1,127 @@
|
||||
import logging
|
||||
import re
|
||||
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 .start import send_main_menu
|
||||
|
||||
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|;|\*\/|\/\*)")
|
||||
|
||||
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 )
|
||||
)
|
||||
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}'")
|
||||
|
||||
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 )
|
||||
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()}")
|
||||
|
||||
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 callback .answer ("Promo code input cancelled.",show_alert =False )
|
||||
Reference in New Issue
Block a user