66
77from telegram import Update , InlineKeyboardButton , InlineKeyboardMarkup
88from telegram .ext import ContextTypes , ConversationHandler
9+ from telegram .helpers import escape_markdown
910from sqlalchemy import select
1011from sqlalchemy .orm import selectinload
1112
@@ -235,23 +236,24 @@ async def handle_quota_selection(update: Update, context: ContextTypes.DEFAULT_T
235236 validity_display = "1 Week" if validity == ValidityPeriod .WEEK .value else "1 Month"
236237
237238 # Send success message with connection details
239+ escaped_access_url = escape_markdown (access_url , version = 2 )
238240 message = (
239- f"🎉 **VPN Connection Created Successfully!**\n \n "
240- f"🖥️ **Server:** { server .name } \n "
241- f"⏰ **Validity:** { validity_display } \n "
242- f"📊 **Traffic Quota:** { quota } \n "
243- f"⏰ **Expires:** { expires_str } \n \n "
241+ f"🎉 **VPN Connection Created Successfully\\ !**\n \n "
242+ f"🖥️ **Server:** { escape_markdown ( server .name , version = 2 ) } \n "
243+ f"⏰ **Validity:** { escape_markdown ( validity_display , version = 2 ) } \n "
244+ f"📊 **Traffic Quota:** { escape_markdown ( quota , version = 2 ) } \n "
245+ f"⏰ **Expires:** { escape_markdown ( expires_str , version = 2 ) } \n \n "
244246 f"🔗 **Connection URL:**\n "
245- f"`{ access_url } `\n \n "
247+ f"`{ escaped_access_url } `\n \n "
246248 f"📱 **Setup Instructions:**\n "
247- f"1. Install Outline app on your device\n "
248- f"2. Copy the connection URL above\n "
249- f"3. Paste it in the Outline app\n "
250- f"4. Start using your VPN!\n \n "
249+ f"1\\ . Install Outline app on your device\n "
250+ f"2\\ . Copy the connection URL above\n "
251+ f"3\\ . Paste it in the Outline app\n "
252+ f"4\\ . Start using your VPN\\ !\n \n "
251253 f"📋 Use /mykeys to view all your connections"
252254 )
253255
254- await query .edit_message_text (message , parse_mode = 'Markdown ' )
256+ await query .edit_message_text (message , parse_mode = 'MarkdownV2 ' )
255257
256258 except OutlineAPIError as e :
257259 logger .error (f"Failed to create VPN key: { e } " )
@@ -310,20 +312,27 @@ async def my_keys(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
310312 message += "🟢 **Active Connections:**\n "
311313 for key in active_keys :
312314 expires_str = key .expires_at .strftime ("%Y-%m-%d %H:%M" )
315+ escaped_server_name = escape_markdown (key .server .name , version = 2 )
316+ escaped_quota = escape_markdown (key .traffic_quota , version = 2 )
317+ escaped_expires = escape_markdown (expires_str , version = 2 )
318+ escaped_url_preview = escape_markdown (key .access_url [:50 ] + "..." , version = 2 )
313319 message += (
314- f"• **{ key . server . name } ** ( { key . traffic_quota } )\n "
315- f" 📅 Expires: { expires_str } UTC\n "
316- f" 🔗 `{ key . access_url [: 50 ] } ... `\n \n "
320+ f"• **{ escaped_server_name } ** \\ ( { escaped_quota } \\ )\n "
321+ f" 📅 Expires: { escaped_expires } UTC\n "
322+ f" 🔗 `{ escaped_url_preview } `\n \n "
317323 )
318324
319325 # Show expired keys
320326 if expired_keys :
321327 message += "🔴 **Expired Connections:**\n "
322328 for key in expired_keys :
323329 expires_str = key .expires_at .strftime ("%Y-%m-%d %H:%M" )
330+ escaped_server_name = escape_markdown (key .server .name , version = 2 )
331+ escaped_quota = escape_markdown (key .traffic_quota , version = 2 )
332+ escaped_expires = escape_markdown (expires_str , version = 2 )
324333 message += (
325- f"• **{ key . server . name } ** ( { key . traffic_quota } )\n "
326- f" 📅 Expired: { expires_str } UTC\n \n "
334+ f"• **{ escaped_server_name } ** \\ ( { escaped_quota } \\ )\n "
335+ f" 📅 Expired: { escaped_expires } UTC\n \n "
327336 )
328337
329338 # Show disabled keys
@@ -332,15 +341,19 @@ async def my_keys(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
332341 for key in disabled_keys :
333342 disabled_str = key .disabled_at .strftime ("%Y-%m-%d %H:%M" )
334343 reason = key .disabled_reason or "Unknown"
344+ escaped_server_name = escape_markdown (key .server .name , version = 2 )
345+ escaped_quota = escape_markdown (key .traffic_quota , version = 2 )
346+ escaped_disabled = escape_markdown (disabled_str , version = 2 )
347+ escaped_reason = escape_markdown (reason , version = 2 )
335348 message += (
336- f"• **{ key . server . name } ** ( { key . traffic_quota } )\n "
337- f" 🚫 Disabled: { disabled_str } UTC\n "
338- f" 📝 Reason: { reason } \n \n "
349+ f"• **{ escaped_server_name } ** \\ ( { escaped_quota } \\ )\n "
350+ f" 🚫 Disabled: { escaped_disabled } UTC\n "
351+ f" 📝 Reason: { escaped_reason } \n \n "
339352 )
340353
341354 message += f"📊 **Summary:** { len (active_keys )} active, { len (expired_keys )} expired, { len (disabled_keys )} disabled"
342355
343- await update .message .reply_text (message , parse_mode = 'Markdown ' )
356+ await update .message .reply_text (message , parse_mode = 'MarkdownV2 ' )
344357
345358
346359async def help_command (update : Update , context : ContextTypes .DEFAULT_TYPE ) -> None :
0 commit comments