fix(ux): Corrigir timezone e adicionar variações humanas nas mensagens
PORQUE FOI FEITA ESSA ALTERAÇÃO? Melhoria de UX. Correção de dois problemas identificados no teste: 1. Timezone: Bot usava UTC mostrando 'Boa noite' às 16h do Brasil 2. Formatação: Markdown literal (**text**) não era renderizado no Telegram QUAIS TESTES FORAM FEITOS? - pytest tests/test_onboarding.py: 12 testes passaram - Teste manual no Telegram confirmando timezone e formatação HTML A ALTERAÇÃO GEROU UM NOVO TESTE? Não, testes existentes cobrem a lógica. Alterações foram: - Uso de zoneinfo com America/Sao_Paulo - parse_mode='HTML' em todas as mensagens - 3 variações de boas-vindas (random.choice) - 3 variações de confirmação de cadastro (agradecimento natural)
This commit is contained in:
parent
8005c0c6a3
commit
14865c049f
|
|
@ -6,15 +6,64 @@ No LLM required - pure Python logic + database lookups.
|
|||
"""
|
||||
|
||||
import logging
|
||||
from typing import Optional, Dict, Any
|
||||
import random
|
||||
from typing import Optional, Dict, Any, List
|
||||
from dataclasses import dataclass, asdict
|
||||
from datetime import datetime, timezone
|
||||
from enum import Enum
|
||||
from zoneinfo import ZoneInfo
|
||||
|
||||
from src.clients import get_qdrant_client
|
||||
|
||||
logger = logging.getLogger("ArthurOnboarding")
|
||||
|
||||
# Brazil timezone
|
||||
BRAZIL_TZ = ZoneInfo("America/Sao_Paulo")
|
||||
|
||||
# Welcome message templates - will be randomized
|
||||
WELCOME_TEMPLATES = [
|
||||
(
|
||||
"Olá! {greeting}. 👋\n\n"
|
||||
"Essa parece ser a primeira vez que nos falamos. "
|
||||
"Pode me confirmar seu <b>Nome Completo</b> e <b>Empresa</b>, por favor?\n\n"
|
||||
"Exemplo: <i>João Silva, iT Guys</i>"
|
||||
),
|
||||
(
|
||||
"{greeting}! 👋\n\n"
|
||||
"Prazer em conhecê-lo! Para que eu possa te atender melhor, "
|
||||
"me conta: qual é o seu <b>nome</b> e de qual <b>empresa</b> você fala?\n\n"
|
||||
"Pode responder assim: <i>Maria Santos, Empresa XYZ</i>"
|
||||
),
|
||||
(
|
||||
"E aí! {greeting}. 😊\n\n"
|
||||
"Ainda não temos seu cadastro por aqui. "
|
||||
"Me passa seu <b>nome completo</b> e a <b>empresa</b> que você representa?\n\n"
|
||||
"Formato: <i>Nome Sobrenome, Sua Empresa</i>"
|
||||
),
|
||||
]
|
||||
|
||||
# Registration confirmation templates
|
||||
REGISTRATION_SUCCESS_TEMPLATES = [
|
||||
(
|
||||
"Perfeito, <b>{first_name}</b>! Obrigado pelas informações. ✅\n\n"
|
||||
"Você está vinculado à empresa <b>{company}</b>.\n"
|
||||
"Agora pode me descrever problemas técnicos que eu analisarei.\n\n"
|
||||
"Como posso te ajudar hoje?"
|
||||
),
|
||||
(
|
||||
"Show, <b>{first_name}</b>! Cadastro feito com sucesso. ✅\n\n"
|
||||
"Te encontrei aqui como parte da <b>{company}</b>.\n"
|
||||
"Estou pronto pra ajudar com qualquer questão técnica!\n\n"
|
||||
"O que você precisa hoje?"
|
||||
),
|
||||
(
|
||||
"Muito obrigado, <b>{first_name}</b>! Tudo certo. ✅\n\n"
|
||||
"Seu perfil está associado à <b>{company}</b>.\n"
|
||||
"Pode contar comigo para análises técnicas e suporte.\n\n"
|
||||
"Em que posso ajudar?"
|
||||
),
|
||||
]
|
||||
|
||||
|
||||
class UserStatus(Enum):
|
||||
"""Status of a user in the system."""
|
||||
|
|
@ -81,13 +130,13 @@ class OnboardingManager:
|
|||
|
||||
def get_time_greeting(self) -> str:
|
||||
"""
|
||||
Returns appropriate greeting based on current time.
|
||||
Returns appropriate greeting based on current time in Brazil.
|
||||
|
||||
- 05:00 - 11:59 -> "Bom dia"
|
||||
- 12:00 - 17:59 -> "Boa tarde"
|
||||
- 18:00 - 04:59 -> "Boa noite"
|
||||
"""
|
||||
now = datetime.now()
|
||||
now = datetime.now(BRAZIL_TZ)
|
||||
hour = now.hour
|
||||
|
||||
if 5 <= hour < 12:
|
||||
|
|
@ -169,7 +218,7 @@ class OnboardingManager:
|
|||
Start the registration flow for unknown user.
|
||||
|
||||
Returns:
|
||||
Greeting message asking for name and company.
|
||||
Greeting message asking for name and company (randomized).
|
||||
"""
|
||||
greeting = self.get_time_greeting()
|
||||
self._pending_registrations[telegram_id] = {
|
||||
|
|
@ -177,12 +226,9 @@ class OnboardingManager:
|
|||
"started_at": datetime.now(timezone.utc)
|
||||
}
|
||||
|
||||
return (
|
||||
f"Olá! {greeting}. 👋\n\n"
|
||||
"Essa parece ser a primeira vez que nos falamos. "
|
||||
"Pode me confirmar seu **Nome Completo** e **Empresa**, por favor?\n\n"
|
||||
"Exemplo: _João Silva, iT Guys_"
|
||||
)
|
||||
# Pick a random welcome template
|
||||
template = random.choice(WELCOME_TEMPLATES)
|
||||
return template.format(greeting=greeting)
|
||||
|
||||
def is_pending_registration(self, telegram_id: str) -> bool:
|
||||
"""Check if user is in the middle of registration."""
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ Integrates onboarding flow for new user identification.
|
|||
|
||||
import os
|
||||
import re
|
||||
import random
|
||||
import logging
|
||||
from typing import List, Optional
|
||||
from dataclasses import dataclass
|
||||
|
|
@ -14,7 +15,7 @@ from telegram import Update
|
|||
from telegram.ext import ApplicationBuilder, ContextTypes, CommandHandler, MessageHandler, filters
|
||||
|
||||
from src.agents.dispatcher import get_dispatcher
|
||||
from src.agents.onboarding import get_onboarding_manager, UserStatus
|
||||
from src.agents.onboarding import get_onboarding_manager, UserStatus, REGISTRATION_SUCCESS_TEMPLATES
|
||||
from src.agents.non_client_handler import get_non_client_handler
|
||||
from src.clients.financial_client import get_financial_client
|
||||
|
||||
|
|
@ -91,12 +92,13 @@ class TelegramListener:
|
|||
|
||||
await update.message.reply_text(
|
||||
f"👋 {greeting}, {name}!\n\n"
|
||||
"Pode me encaminhar tickets ou descrever problemas que eu analisarei."
|
||||
"Pode me encaminhar tickets ou descrever problemas que eu analisarei.",
|
||||
parse_mode="HTML"
|
||||
)
|
||||
else:
|
||||
# Start onboarding
|
||||
welcome_msg = self._onboarding.start_registration(telegram_id)
|
||||
await update.message.reply_text(welcome_msg)
|
||||
await update.message.reply_text(welcome_msg, parse_mode="HTML")
|
||||
|
||||
async def _handle_message(self, update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||
if not await self._check_auth(update):
|
||||
|
|
@ -117,7 +119,7 @@ class TelegramListener:
|
|||
if not is_known:
|
||||
# Start onboarding flow
|
||||
welcome_msg = self._onboarding.start_registration(telegram_id)
|
||||
await update.message.reply_text(welcome_msg)
|
||||
await update.message.reply_text(welcome_msg, parse_mode="HTML")
|
||||
return
|
||||
|
||||
# Get user context for personalized response
|
||||
|
|
@ -144,8 +146,9 @@ class TelegramListener:
|
|||
if not match:
|
||||
await update.message.reply_text(
|
||||
"📝 Por favor, informe no formato:\n"
|
||||
"_Nome Completo, Empresa_\n\n"
|
||||
"Exemplo: João Silva, iT Guys"
|
||||
"<i>Nome Completo, Empresa</i>\n\n"
|
||||
"Exemplo: João Silva, iT Guys",
|
||||
parse_mode="HTML"
|
||||
)
|
||||
return
|
||||
|
||||
|
|
@ -168,17 +171,16 @@ class TelegramListener:
|
|||
first_name = name.split()[0]
|
||||
|
||||
if tenant_id:
|
||||
# Client user - welcome!
|
||||
# Client user - welcome with random template!
|
||||
template = random.choice(REGISTRATION_SUCCESS_TEMPLATES)
|
||||
await update.message.reply_text(
|
||||
f"✅ Cadastro realizado! {greeting}, {first_name}!\n\n"
|
||||
f"Você está vinculado à empresa **{company}**.\n"
|
||||
"Agora pode me descrever problemas técnicos que eu analisarei.\n\n"
|
||||
"Como posso te ajudar hoje?"
|
||||
template.format(first_name=first_name, company=company),
|
||||
parse_mode="HTML"
|
||||
)
|
||||
else:
|
||||
# Non-client - explain limitations
|
||||
response = self._non_client.generate_response(name, company)
|
||||
await update.message.reply_text(response)
|
||||
await update.message.reply_text(response, parse_mode="HTML")
|
||||
|
||||
async def _handle_non_client_message(self, update: Update, user_ctx: dict):
|
||||
"""Handle message from non-client user (passive messenger mode)."""
|
||||
|
|
@ -221,7 +223,8 @@ class TelegramListener:
|
|||
# Send acknowledgment
|
||||
await update.message.reply_text(
|
||||
f"👋 {greeting}, {first_name}!\n"
|
||||
"🔍 Analisando sua solicitação..."
|
||||
"🔍 Analisando sua solicitação...",
|
||||
parse_mode="HTML"
|
||||
)
|
||||
|
||||
# Dispatch to Arthur
|
||||
|
|
|
|||
Loading…
Reference in New Issue