| """ |
| WhatsApp Improved Chatbot with Professional Product Search |
| Optimized for mobile WhatsApp formatting |
| """ |
|
|
| from product_search import ProductSearchEngine |
| import re |
| from typing import List, Dict, Optional, Tuple |
|
|
| class WhatsAppImprovedChatbot: |
| """Enhanced chatbot with intelligent product handling for WhatsApp""" |
| |
| def __init__(self, products: List[Tuple]): |
| """Initialize with product list""" |
| self.search_engine = ProductSearchEngine(products) |
| self.products = products |
| |
| def detect_product_query(self, message: str) -> bool: |
| """Detect if message is asking about products""" |
| product_keywords = [ |
| 'bisiklet', 'bike', 'model', 'fiyat', 'price', 'stok', 'stock', |
| 'özellikleri', 'features', 'hangi', 'which', 'var mı', 'mevcut', |
| 'kaç', 'how much', 'ne kadar', 'kampanya', 'indirim', 'discount', |
| 'karşılaştır', 'compare', 'benzer', 'similar', 'alternatif', |
| 'öneri', 'recommend', 'tavsiye', 'suggest' |
| ] |
| |
| message_lower = message.lower() |
| |
| |
| if any(keyword in message_lower for keyword in product_keywords): |
| return True |
| |
| |
| if re.search(r'\b\d+\.?\d*\b', message): |
| return True |
| |
| |
| categories = ['trek', 'marlin', 'fuel', 'slash', 'remedy', 'checkpoint', |
| 'domane', 'madone', 'emonda', 'fx', 'dual', 'wahoo', 'powerfly'] |
| if any(cat in message_lower for cat in categories): |
| return True |
| |
| return False |
| |
| def extract_query_intent(self, message: str) -> Dict: |
| """Extract the intent from user query""" |
| intent = { |
| 'type': 'general', |
| 'action': None, |
| 'filters': {} |
| } |
| |
| message_lower = message.lower() |
| |
| |
| if any(word in message_lower for word in ['fiyat', 'price', 'kaç', 'ne kadar', 'how much']): |
| intent['type'] = 'price' |
| intent['action'] = 'get_price' |
| |
| |
| elif any(word in message_lower for word in ['stok', 'stock', 'var mı', 'mevcut', 'available']): |
| intent['type'] = 'stock' |
| intent['action'] = 'check_stock' |
| |
| |
| elif any(word in message_lower for word in ['karşılaştır', 'compare', 'fark', 'difference']): |
| intent['type'] = 'comparison' |
| intent['action'] = 'compare_products' |
| |
| |
| elif any(word in message_lower for word in ['öneri', 'recommend', 'tavsiye', 'suggest', 'hangi']): |
| intent['type'] = 'recommendation' |
| intent['action'] = 'recommend' |
| |
| |
| elif any(word in message_lower for word in ['özellik', 'feature', 'spec', 'detay', 'detail']): |
| intent['type'] = 'features' |
| intent['action'] = 'get_features' |
| |
| |
| context = self.search_engine.extract_product_context(message) |
| intent['filters'] = context |
| |
| return intent |
| |
| def format_product_info_whatsapp(self, product: Tuple, intent: Dict) -> str: |
| """Format product information for WhatsApp""" |
| name = product[2] |
| info = product[1] |
| |
| |
| stock_status = info[0] if len(info) > 0 else "bilinmiyor" |
| |
| |
| response_parts = [] |
| |
| |
| if stock_status == "stokta": |
| response_parts.append(f"🚴♂️ *{name}*") |
| response_parts.append("✅ *Stokta mevcut*") |
| else: |
| response_parts.append(f"🚴♂️ *{name}*") |
| response_parts.append("❌ *Stokta yok*") |
| |
| |
| if intent['type'] in ['price', 'general'] and stock_status == "stokta" and len(info) > 1: |
| price = info[1] |
| response_parts.append(f"💰 *Fiyat:* {price} TL") |
| |
| |
| if len(info) > 4 and info[4]: |
| response_parts.append(f"🎯 *Kampanya:* {info[4]} TL") |
| |
| |
| try: |
| normal_price = float(info[1]) |
| campaign_price = float(info[4]) |
| discount = normal_price - campaign_price |
| if discount > 0: |
| response_parts.append(f"💸 *İndirim:* {discount:.0f} TL") |
| except: |
| pass |
| |
| |
| elif len(info) > 3 and info[3]: |
| response_parts.append(f"🏦 *Havale:* {info[3]} TL") |
| |
| |
| if len(info) > 2 and info[2]: |
| response_parts.append(f"🔗 Ürün sayfası: {info[2]}") |
| |
| return "\n".join(response_parts) |
| |
| def generate_product_response(self, message: str) -> str: |
| """Generate response for product queries optimized for WhatsApp""" |
| intent = self.extract_query_intent(message) |
| |
| |
| search_results = self.search_engine.search(message) |
| |
| if not search_results: |
| |
| response = self._handle_no_results_whatsapp(message) |
| elif len(search_results) == 1: |
| |
| product = search_results[0][1] |
| response = self.format_product_info_whatsapp(product, intent) |
| elif search_results[0][0] > 0.9: |
| |
| product = search_results[0][1] |
| response = self.format_product_info_whatsapp(product, intent) |
| else: |
| |
| response = self._handle_multiple_results_whatsapp(search_results[:3], intent) |
| |
| return response |
| |
| def _handle_no_results_whatsapp(self, query: str) -> str: |
| """Handle case when no products are found - WhatsApp format""" |
| response_parts = ["🤔 *Aradığınız ürünü bulamadım.*"] |
| |
| |
| suggestions = self.search_engine.generate_suggestions(query) |
| |
| if suggestions: |
| response_parts.append("\n💡 *Belki şunları arıyor olabilirsiniz:*") |
| for i, suggestion in enumerate(suggestions[:2], 1): |
| response_parts.append(f"{i}. {suggestion}") |
| else: |
| response_parts.append("\n📝 *Örnek aramalar:*") |
| response_parts.append("• Marlin 5") |
| response_parts.append("• FX 3 Disc") |
| response_parts.append("• Checkpoint ALR 5") |
| |
| return "\n".join(response_parts) |
| |
| def _handle_multiple_results_whatsapp(self, results: List[Tuple[float, Tuple]], intent: Dict) -> str: |
| """Handle multiple product results - WhatsApp format""" |
| response_parts = ["📋 *Birden fazla ürün buldum:*\n"] |
| |
| for i, (score, product) in enumerate(results, 1): |
| name = product[2] |
| stock = product[1][0] if len(product[1]) > 0 else "bilinmiyor" |
| |
| |
| if stock == "stokta": |
| status_emoji = "✅" |
| response_parts.append(f"*{i}. {name}* {status_emoji}") |
| |
| |
| if intent['type'] in ['price', 'general'] and len(product[1]) > 1: |
| price = product[1][1] |
| response_parts.append(f" 💰 {price} TL") |
| |
| |
| if len(product[1]) > 4 and product[1][4]: |
| response_parts.append(f" 🎯 Kampanya: {product[1][4]} TL") |
| |
| |
| if len(product[1]) > 2 and product[1][2]: |
| response_parts.append(f" 🔗 {product[1][2]}") |
| else: |
| status_emoji = "❌" |
| response_parts.append(f"*{i}. {name}* {status_emoji}") |
| |
| response_parts.append("") |
| |
| response_parts.append("💡 _Daha detaylı bilgi için ürün adını yazın_") |
| |
| return "\n".join(response_parts) |
| |
| def handle_comparison_whatsapp(self, message: str) -> Optional[str]: |
| """Handle product comparison requests - WhatsApp format""" |
| |
| comparison_words = ['ile', 've', 'vs', 'versus', 'karşılaştır', 'arasında'] |
| |
| products_to_compare = [] |
| |
| |
| for word in comparison_words: |
| if word in message.lower(): |
| parts = message.lower().split(word) |
| if len(parts) >= 2: |
| |
| for part in parts[:2]: |
| result = self.search_engine.find_best_match(part.strip()) |
| if result: |
| products_to_compare.append(result) |
| |
| if len(products_to_compare) < 2: |
| |
| search_results = self.search_engine.search(message) |
| products_to_compare = [r[1] for r in search_results[:2] if r[0] > 0.6] |
| |
| if len(products_to_compare) >= 2: |
| return self._format_comparison_whatsapp(products_to_compare[:2]) |
| |
| return None |
| |
| def _format_comparison_whatsapp(self, products: List[Tuple]) -> str: |
| """Format product comparison for WhatsApp""" |
| response_parts = ["📊 *Ürün Karşılaştırması*\n"] |
| |
| for i, product in enumerate(products, 1): |
| name = product[2] |
| info = product[1] |
| |
| response_parts.append(f"*{i}. {name}*") |
| |
| |
| stock = info[0] if len(info) > 0 else "bilinmiyor" |
| if stock == "stokta": |
| response_parts.append("✅ Stokta mevcut") |
| else: |
| response_parts.append("❌ Stokta yok") |
| |
| |
| if stock == "stokta" and len(info) > 1: |
| price = info[1] |
| response_parts.append(f"💰 {price} TL") |
| |
| if len(info) > 4 and info[4]: |
| response_parts.append(f"🎯 Kampanya: {info[4]} TL") |
| |
| response_parts.append("") |
| |
| return "\n".join(response_parts) |
| |
| def process_message(self, message: str) -> Dict: |
| """Process user message and return structured response optimized for WhatsApp""" |
| result = { |
| 'is_product_query': False, |
| 'response': None, |
| 'products_found': [], |
| 'intent': None |
| } |
| |
| |
| if self.detect_product_query(message): |
| result['is_product_query'] = True |
| result['intent'] = self.extract_query_intent(message) |
| |
| |
| if result['intent']['type'] == 'comparison': |
| comparison_result = self.handle_comparison_whatsapp(message) |
| if comparison_result: |
| result['response'] = comparison_result |
| return result |
| |
| |
| result['response'] = self.generate_product_response(message) |
| |
| |
| search_results = self.search_engine.search(message) |
| result['products_found'] = [r[1] for r in search_results[:2] if r[0] > 0.6] |
| |
| return result |