"""Smart warehouse stock finder for WhatsApp - GPT-5 powered""" import requests import re import os import json import xml.etree.ElementTree as ET def get_product_price_and_link(product_name, variant=None): """Get price and link from Trek website XML""" try: url = 'https://www.trekbisiklet.com.tr/output/8582384479' response = requests.get(url, verify=False, timeout=10) if response.status_code != 200: return None, None root = ET.fromstring(response.content) # Turkish character normalization FIRST (before lower) tr_map = {'İ': 'i', 'I': 'i', 'ı': 'i', 'Ğ': 'g', 'ğ': 'g', 'Ü': 'u', 'ü': 'u', 'Ş': 's', 'ş': 's', 'Ö': 'o', 'ö': 'o', 'Ç': 'c', 'ç': 'c'} # Apply normalization to original search_name_norm = product_name search_variant_norm = variant if variant else "" for tr, en in tr_map.items(): search_name_norm = search_name_norm.replace(tr, en) search_variant_norm = search_variant_norm.replace(tr, en) # Now lowercase search_name = search_name_norm.lower() search_variant = search_variant_norm.lower() best_match = None best_score = 0 for item in root.findall('item'): rootlabel_elem = item.find('rootlabel') if rootlabel_elem is None or not rootlabel_elem.text: continue item_name = rootlabel_elem.text.lower() for tr, en in tr_map.items(): item_name = item_name.replace(tr, en) # Calculate match score score = 0 name_parts = search_name.split() for part in name_parts: if part in item_name: score += 1 if variant and search_variant in item_name: score += 2 if score > best_score: best_score = score best_match = item if best_match and best_score > 0: # Extract price price_elem = best_match.find('priceTaxWithCur') price = price_elem.text if price_elem is not None and price_elem.text else None # Round price for WhatsApp display if price: try: price_float = float(price) if price_float > 200000: rounded = round(price_float / 5000) * 5000 price = f"{int(rounded):,}".replace(',', '.') + " TL" elif price_float > 30000: rounded = round(price_float / 1000) * 1000 price = f"{int(rounded):,}".replace(',', '.') + " TL" elif price_float > 10000: rounded = round(price_float / 100) * 100 price = f"{int(rounded):,}".replace(',', '.') + " TL" else: rounded = round(price_float / 10) * 10 price = f"{int(rounded):,}".replace(',', '.') + " TL" except: price = None # Extract link link_elem = best_match.find('productLink') link = link_elem.text if link_elem is not None and link_elem.text else None return price, link return None, None except Exception as e: print(f"Error getting price/link: {e}") return None, None def get_warehouse_stock_gpt5(user_message): """GPT-5 powered smart warehouse stock search for WhatsApp""" OPENAI_API_KEY = os.getenv("OPENAI_API_KEY") if not OPENAI_API_KEY: return None # Check for specific warehouse in query warehouse_keywords = { 'caddebostan': 'Caddebostan', 'ortaköy': 'Ortaköy', 'ortakoy': 'Ortaköy', 'alsancak': 'Alsancak', 'izmir': 'Alsancak', 'bahçeköy': 'Bahçeköy', 'bahcekoy': 'Bahçeköy' } user_lower = user_message.lower() asked_warehouse = None for keyword, warehouse in warehouse_keywords.items(): if keyword in user_lower: asked_warehouse = warehouse break # Get warehouse XML with retry xml_text = None for attempt in range(3): try: url = 'https://video.trek-turkey.com/bizimhesap-warehouse-xml-b2b-api-v2.php' timeout_val = 10 + (attempt * 5) response = requests.get(url, verify=False, timeout=timeout_val) xml_text = response.text break except: if attempt == 2: return None if not xml_text: return None # Extract product blocks product_pattern = r'(.*?)' all_products = re.findall(product_pattern, xml_text, re.DOTALL) # Create product summary for GPT products_summary = [] for i, product_block in enumerate(all_products): name_match = re.search(r'', product_block) variant_match = re.search(r'', product_block) if name_match: warehouses_with_stock = [] warehouse_regex = r'.*?.*?(.*?).*?' warehouses = re.findall(warehouse_regex, product_block, re.DOTALL) for wh_name, wh_stock in warehouses: try: if int(wh_stock.strip()) > 0: warehouses_with_stock.append(wh_name) except: pass if warehouses_with_stock: # Only add if has stock product_info = { "index": i, "name": name_match.group(1), "variant": variant_match.group(1) if variant_match else "", "warehouses": warehouses_with_stock } products_summary.append(product_info) # Prepare GPT-5 prompt warehouse_filter = "" if asked_warehouse: warehouse_filter = f"\nIMPORTANT: User is asking about {asked_warehouse} warehouse. Only return products available there." smart_prompt = f"""User WhatsApp message: "{user_message}" Find EXACT products matching this query. Be very precise with product names. IMPORTANT: If user asks for "madone sl 6", find products with "MADONE SL 6" in the name. DO NOT return similar products (like Marlin) if the exact product is not found. Turkish/English terms: - FORMA = jersey, TAYT = tights, İÇLİK = base layer, YAĞMURLUK = raincoat - GOBIK = Spanish textile brand - Sizes: S, M, L, XL, XXL, SMALL, MEDIUM, LARGE {warehouse_filter} Products with stock: {json.dumps(products_summary, ensure_ascii=False)} Return ONLY index numbers of EXACT matches as comma-separated list. If NO exact match found, return: -1 Examples: - "madone sl 6" -> Find only products with "MADONE SL 6" in name, NOT Marlin or other models - "gobik forma" -> Find only products with "GOBIK" AND "FORMA" in name""" headers = { "Content-Type": "application/json", "Authorization": f"Bearer {OPENAI_API_KEY}" } payload = { "model": "gpt-5-chat-latest", "messages": [ {"role": "system", "content": "You are a product matcher. Return only numbers."}, {"role": "user", "content": smart_prompt} ], "temperature": 0, "max_tokens": 100 } try: response = requests.post( "https://api.openai.com/v1/chat/completions", headers=headers, json=payload, timeout=10 ) if response.status_code != 200: return None result = response.json() indices_str = result['choices'][0]['message']['content'].strip() if not indices_str or indices_str == "-1": return None # Parse indices safely indices = [] for idx in indices_str.split(','): idx = idx.strip() if idx and idx.isdigit(): indices.append(int(idx)) if not indices: return None # Collect matched products matched_products = [] for idx in indices: # No limit, get all matches if 0 <= idx < len(all_products): product_block = all_products[idx] name_match = re.search(r'', product_block) variant_match = re.search(r'', product_block) if name_match: product_name = name_match.group(1) variant = variant_match.group(1) if variant_match else "" # Get price and link price, link = get_product_price_and_link(product_name, variant) # Get warehouse info warehouses = [] warehouse_regex = r'.*?.*?(.*?).*?' wh_matches = re.findall(warehouse_regex, product_block, re.DOTALL) for wh_name, wh_stock in wh_matches: try: if int(wh_stock.strip()) > 0: if "CADDEBOSTAN" in wh_name: warehouses.append("Caddebostan") elif "ORTAKÖY" in wh_name: warehouses.append("Ortaköy") elif "ALSANCAK" in wh_name: warehouses.append("Alsancak") elif "BAHCEKOY" in wh_name or "BAHÇEKÖY" in wh_name: warehouses.append("Bahçeköy") except: pass if warehouses: matched_products.append({ 'name': product_name, 'variant': variant, 'price': price, 'link': link, 'warehouses': warehouses }) return matched_products if matched_products else None except Exception as e: print(f"GPT-5 search error: {e}") return None