Upload 3 files
Browse files- app.py +58 -24
- enhanced_features.py +31 -3
- image_renderer.py +143 -0
app.py
CHANGED
|
@@ -27,6 +27,7 @@ from enhanced_features import (
|
|
| 27 |
initialize_enhanced_features, process_image_message,
|
| 28 |
handle_comparison_request, get_user_recommendations, profile_manager
|
| 29 |
)
|
|
|
|
| 30 |
|
| 31 |
# Gradio uyarılarını bastır
|
| 32 |
warnings.filterwarnings("ignore", category=UserWarning, module="gradio.components.chatbot")
|
|
@@ -171,14 +172,15 @@ if root is not None:
|
|
| 171 |
except (ValueError, TypeError):
|
| 172 |
price_rebate_money_order = price_rebate_money_order_str
|
| 173 |
|
| 174 |
-
#
|
| 175 |
product_link = item.find('productLink').text if item.find('productLink') is not None else ""
|
|
|
|
| 176 |
|
| 177 |
-
# Tüm fiyat bilgilerini birleştir
|
| 178 |
-
item_info = (stock_amount, price, product_link, price_eft, price_rebate, price_rebate_money_order)
|
| 179 |
else:
|
| 180 |
# Stokta olmayan ürünler için sadece stok durumunu belirt, fiyat ve link bilgisi verme
|
| 181 |
-
item_info = (stock_amount, "", "", "", "", "")
|
| 182 |
|
| 183 |
products.append((name, item_info, full_name))
|
| 184 |
|
|
@@ -412,11 +414,14 @@ def chatbot_fn(user_message, history, image=None):
|
|
| 412 |
if product_info[1][3] and product_info[1][3] != "":
|
| 413 |
eft_price = f"\nHavale indirimli fiyat: {product_info[1][3]} TL"
|
| 414 |
|
| 415 |
-
# Ürün linki
|
| 416 |
product_link = f"\nÜrün linki: {product_info[1][2]}"
|
|
|
|
|
|
|
|
|
|
| 417 |
|
| 418 |
# Tüm bilgileri birleştir
|
| 419 |
-
new_msg = f"{product_info[2]} {product_info[1][0]}\n{normal_price}{rebate_price}{discount_info}{eft_price}{rebate_money_order_price}{product_link}"
|
| 420 |
else:
|
| 421 |
# Ürün stokta yoksa sadece stok durumunu bildir
|
| 422 |
new_msg = f"{product_info[2]} {product_info[1][0]}"
|
|
@@ -456,11 +461,17 @@ def chatbot_fn(user_message, history, image=None):
|
|
| 456 |
delta = chunk_data['choices'][0]['delta']
|
| 457 |
if 'content' in delta:
|
| 458 |
partial_response += delta['content']
|
| 459 |
-
|
|
|
|
|
|
|
| 460 |
except json.JSONDecodeError as e:
|
| 461 |
print(f"JSON parse hatası: {e} - Chunk: {chunk_str}")
|
| 462 |
elif chunk_str == "data: [DONE]":
|
| 463 |
break
|
|
|
|
|
|
|
|
|
|
|
|
|
| 464 |
|
| 465 |
# Log: Asistan cevabını ekle
|
| 466 |
try:
|
|
@@ -564,6 +575,35 @@ h3 {
|
|
| 564 |
text-rendering: optimizeLegibility;
|
| 565 |
}
|
| 566 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 567 |
/* JavaScript ile placeholder eklemek için */
|
| 568 |
</style>
|
| 569 |
<script>
|
|
@@ -592,33 +632,27 @@ def enhanced_chatbot_fn(message, history, image):
|
|
| 592 |
# Demo arayüzü - Özel layout ile image upload destekli
|
| 593 |
with gr.Blocks(css=custom_css, theme="soft", title="Trek Asistanı") as demo:
|
| 594 |
gr.Markdown("# 🚲 Trek Asistanı AI")
|
| 595 |
-
gr.Markdown("**
|
| 596 |
|
| 597 |
with gr.Row():
|
| 598 |
with gr.Column(scale=4):
|
| 599 |
-
chatbot = gr.Chatbot(height=500)
|
| 600 |
|
| 601 |
with gr.Column(scale=1):
|
| 602 |
-
gr.Markdown("###
|
| 603 |
-
|
| 604 |
-
gr.Markdown("### 🔍 Özel Komutlar")
|
| 605 |
-
gr.Markdown("""
|
| 606 |
-
• **Karşılaştırma:** "Émonda ve Madone karşılaştır"
|
| 607 |
-
• **Bütçe:** "50-100K TL bütçem var"
|
| 608 |
-
• **Görsel:** Bisiklet fotoğrafı yükle
|
| 609 |
-
""")
|
| 610 |
|
| 611 |
with gr.Row():
|
| 612 |
msg = gr.Textbox(
|
| 613 |
-
placeholder="
|
| 614 |
show_label=False,
|
| 615 |
scale=4
|
| 616 |
)
|
| 617 |
submit_btn = gr.Button("Gönder", scale=1)
|
| 618 |
|
| 619 |
-
def respond(message, chat_history
|
| 620 |
-
# Enhanced chatbot fonksiyonunu çağır
|
| 621 |
-
response_generator = chatbot_fn(message, chat_history,
|
| 622 |
|
| 623 |
# Generator'dan son cevabı al
|
| 624 |
response = ""
|
|
@@ -627,10 +661,10 @@ with gr.Blocks(css=custom_css, theme="soft", title="Trek Asistanı") as demo:
|
|
| 627 |
|
| 628 |
# Chat history güncelle
|
| 629 |
chat_history.append((message, response))
|
| 630 |
-
return "", chat_history
|
| 631 |
|
| 632 |
-
submit_btn.click(respond, [msg, chatbot
|
| 633 |
-
msg.submit(respond, [msg, chatbot
|
| 634 |
|
| 635 |
if __name__ == "__main__":
|
| 636 |
demo.launch(debug=True)
|
|
|
|
| 27 |
initialize_enhanced_features, process_image_message,
|
| 28 |
handle_comparison_request, get_user_recommendations, profile_manager
|
| 29 |
)
|
| 30 |
+
from image_renderer import extract_product_info_for_gallery, format_message_with_images
|
| 31 |
|
| 32 |
# Gradio uyarılarını bastır
|
| 33 |
warnings.filterwarnings("ignore", category=UserWarning, module="gradio.components.chatbot")
|
|
|
|
| 172 |
except (ValueError, TypeError):
|
| 173 |
price_rebate_money_order = price_rebate_money_order_str
|
| 174 |
|
| 175 |
+
# Ürün linkini ve resim URL'sini al
|
| 176 |
product_link = item.find('productLink').text if item.find('productLink') is not None else ""
|
| 177 |
+
image_url = item.find('picture1Path').text if item.find('picture1Path') is not None else ""
|
| 178 |
|
| 179 |
+
# Tüm fiyat bilgilerini birleştir (resim URL'si eklendi)
|
| 180 |
+
item_info = (stock_amount, price, product_link, price_eft, price_rebate, price_rebate_money_order, image_url)
|
| 181 |
else:
|
| 182 |
# Stokta olmayan ürünler için sadece stok durumunu belirt, fiyat ve link bilgisi verme
|
| 183 |
+
item_info = (stock_amount, "", "", "", "", "", "")
|
| 184 |
|
| 185 |
products.append((name, item_info, full_name))
|
| 186 |
|
|
|
|
| 414 |
if product_info[1][3] and product_info[1][3] != "":
|
| 415 |
eft_price = f"\nHavale indirimli fiyat: {product_info[1][3]} TL"
|
| 416 |
|
| 417 |
+
# Ürün linki ve resim
|
| 418 |
product_link = f"\nÜrün linki: {product_info[1][2]}"
|
| 419 |
+
product_image = ""
|
| 420 |
+
if len(product_info[1]) > 6 and product_info[1][6]: # Resim URL'si varsa
|
| 421 |
+
product_image = f"\nÜrün resmi: {product_info[1][6]}"
|
| 422 |
|
| 423 |
# Tüm bilgileri birleştir
|
| 424 |
+
new_msg = f"{product_info[2]} {product_info[1][0]}\n{normal_price}{rebate_price}{discount_info}{eft_price}{rebate_money_order_price}{product_link}{product_image}"
|
| 425 |
else:
|
| 426 |
# Ürün stokta yoksa sadece stok durumunu bildir
|
| 427 |
new_msg = f"{product_info[2]} {product_info[1][0]}"
|
|
|
|
| 461 |
delta = chunk_data['choices'][0]['delta']
|
| 462 |
if 'content' in delta:
|
| 463 |
partial_response += delta['content']
|
| 464 |
+
# Resim formatlaması uygula
|
| 465 |
+
formatted_response = extract_product_info_for_gallery(partial_response)
|
| 466 |
+
yield formatted_response
|
| 467 |
except json.JSONDecodeError as e:
|
| 468 |
print(f"JSON parse hatası: {e} - Chunk: {chunk_str}")
|
| 469 |
elif chunk_str == "data: [DONE]":
|
| 470 |
break
|
| 471 |
+
|
| 472 |
+
# Son resim formatlaması
|
| 473 |
+
final_response = extract_product_info_for_gallery(partial_response)
|
| 474 |
+
yield final_response
|
| 475 |
|
| 476 |
# Log: Asistan cevabını ekle
|
| 477 |
try:
|
|
|
|
| 575 |
text-rendering: optimizeLegibility;
|
| 576 |
}
|
| 577 |
|
| 578 |
+
/* Resim gösterimi için özel stiller */
|
| 579 |
+
#chatbot .message img {
|
| 580 |
+
max-width: 100%;
|
| 581 |
+
height: auto;
|
| 582 |
+
border-radius: 8px;
|
| 583 |
+
margin: 8px 0;
|
| 584 |
+
}
|
| 585 |
+
|
| 586 |
+
#chatbot .message {
|
| 587 |
+
word-wrap: break-word;
|
| 588 |
+
}
|
| 589 |
+
|
| 590 |
+
/* Ürün galeri stilleri */
|
| 591 |
+
.product-gallery {
|
| 592 |
+
display: flex;
|
| 593 |
+
flex-wrap: wrap;
|
| 594 |
+
gap: 10px;
|
| 595 |
+
margin: 10px 0;
|
| 596 |
+
}
|
| 597 |
+
|
| 598 |
+
.product-card {
|
| 599 |
+
border: 1px solid #ddd;
|
| 600 |
+
border-radius: 8px;
|
| 601 |
+
padding: 8px;
|
| 602 |
+
max-width: 180px;
|
| 603 |
+
text-align: center;
|
| 604 |
+
background: white;
|
| 605 |
+
}
|
| 606 |
+
|
| 607 |
/* JavaScript ile placeholder eklemek için */
|
| 608 |
</style>
|
| 609 |
<script>
|
|
|
|
| 632 |
# Demo arayüzü - Özel layout ile image upload destekli
|
| 633 |
with gr.Blocks(css=custom_css, theme="soft", title="Trek Asistanı") as demo:
|
| 634 |
gr.Markdown("# 🚲 Trek Asistanı AI")
|
| 635 |
+
gr.Markdown("**Akıllı özellikler:** Ürün karşılaştırması, kişisel öneriler ve detaylı ürün bilgileri sunuyorum.")
|
| 636 |
|
| 637 |
with gr.Row():
|
| 638 |
with gr.Column(scale=4):
|
| 639 |
+
chatbot = gr.Chatbot(height=500, elem_id="chatbot", show_label=False)
|
| 640 |
|
| 641 |
with gr.Column(scale=1):
|
| 642 |
+
gr.Markdown("### ℹ️ Bilgi")
|
| 643 |
+
gr.Markdown("Trek bisiklet uzmanı AI asistanınız. Ürün bilgileri, fiyatlar ve öneriler için sorularınızı yazın.")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 644 |
|
| 645 |
with gr.Row():
|
| 646 |
msg = gr.Textbox(
|
| 647 |
+
placeholder="Trek bisikletleri hakkında soru sorun...",
|
| 648 |
show_label=False,
|
| 649 |
scale=4
|
| 650 |
)
|
| 651 |
submit_btn = gr.Button("Gönder", scale=1)
|
| 652 |
|
| 653 |
+
def respond(message, chat_history):
|
| 654 |
+
# Enhanced chatbot fonksiyonunu çağır (image=None)
|
| 655 |
+
response_generator = chatbot_fn(message, chat_history, None)
|
| 656 |
|
| 657 |
# Generator'dan son cevabı al
|
| 658 |
response = ""
|
|
|
|
| 661 |
|
| 662 |
# Chat history güncelle
|
| 663 |
chat_history.append((message, response))
|
| 664 |
+
return "", chat_history
|
| 665 |
|
| 666 |
+
submit_btn.click(respond, [msg, chatbot], [msg, chatbot])
|
| 667 |
+
msg.submit(respond, [msg, chatbot], [msg, chatbot])
|
| 668 |
|
| 669 |
if __name__ == "__main__":
|
| 670 |
demo.launch(debug=True)
|
enhanced_features.py
CHANGED
|
@@ -181,6 +181,25 @@ class ProductComparison:
|
|
| 181 |
def __init__(self, products_data):
|
| 182 |
self.products = products_data
|
| 183 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 184 |
def find_products_by_name(self, product_names):
|
| 185 |
"""İsimlere göre ürünleri bul"""
|
| 186 |
found_products = []
|
|
@@ -205,14 +224,23 @@ class ProductComparison:
|
|
| 205 |
|
| 206 |
# Ürün bilgilerini parse et
|
| 207 |
stock_status = item_info[0] if len(item_info) > 0 else "Bilgi yok"
|
| 208 |
-
|
| 209 |
product_link = item_info[2] if len(item_info) > 2 else ""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 210 |
|
| 211 |
comparison_data.append({
|
| 212 |
"Ürün": full_name,
|
| 213 |
"Stok": stock_status,
|
| 214 |
-
"Fiyat":
|
| 215 |
-
"Link": product_link
|
|
|
|
| 216 |
})
|
| 217 |
|
| 218 |
# DataFrame oluştur
|
|
|
|
| 181 |
def __init__(self, products_data):
|
| 182 |
self.products = products_data
|
| 183 |
|
| 184 |
+
def round_price(self, price_str):
|
| 185 |
+
"""Fiyatı yuvarlama formülüne göre yuvarla"""
|
| 186 |
+
try:
|
| 187 |
+
price_float = float(price_str)
|
| 188 |
+
# Fiyat 200000 üzerindeyse en yakın 5000'lik basamağa yuvarla
|
| 189 |
+
if price_float > 200000:
|
| 190 |
+
return str(round(price_float / 5000) * 5000)
|
| 191 |
+
# Fiyat 30000 üzerindeyse en yakın 1000'lik basamağa yuvarla
|
| 192 |
+
elif price_float > 30000:
|
| 193 |
+
return str(round(price_float / 1000) * 1000)
|
| 194 |
+
# Fiyat 10000 üzerindeyse en yakın 100'lük basamağa yuvarla
|
| 195 |
+
elif price_float > 10000:
|
| 196 |
+
return str(round(price_float / 100) * 100)
|
| 197 |
+
# Diğer durumlarda en yakın 10'luk basamağa yuvarla
|
| 198 |
+
else:
|
| 199 |
+
return str(round(price_float / 10) * 10)
|
| 200 |
+
except (ValueError, TypeError):
|
| 201 |
+
return price_str
|
| 202 |
+
|
| 203 |
def find_products_by_name(self, product_names):
|
| 204 |
"""İsimlere göre ürünleri bul"""
|
| 205 |
found_products = []
|
|
|
|
| 224 |
|
| 225 |
# Ürün bilgilerini parse et
|
| 226 |
stock_status = item_info[0] if len(item_info) > 0 else "Bilgi yok"
|
| 227 |
+
price_raw = item_info[1] if len(item_info) > 1 and item_info[1] else "Fiyat yok"
|
| 228 |
product_link = item_info[2] if len(item_info) > 2 else ""
|
| 229 |
+
image_url = item_info[6] if len(item_info) > 6 and item_info[6] else ""
|
| 230 |
+
|
| 231 |
+
# Fiyatı yuvarlama formülüne göre yuvarla
|
| 232 |
+
if price_raw != "Fiyat yok":
|
| 233 |
+
price = self.round_price(price_raw)
|
| 234 |
+
price_display = f"{price} TL"
|
| 235 |
+
else:
|
| 236 |
+
price_display = price_raw
|
| 237 |
|
| 238 |
comparison_data.append({
|
| 239 |
"Ürün": full_name,
|
| 240 |
"Stok": stock_status,
|
| 241 |
+
"Fiyat": price_display,
|
| 242 |
+
"Link": product_link,
|
| 243 |
+
"Resim": image_url if image_url else "Resim yok"
|
| 244 |
})
|
| 245 |
|
| 246 |
# DataFrame oluştur
|
image_renderer.py
ADDED
|
@@ -0,0 +1,143 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# -*- coding: utf-8 -*-
|
| 2 |
+
"""
|
| 3 |
+
Ürün Resimlerini Sohbette Gösterme Sistemi
|
| 4 |
+
"""
|
| 5 |
+
|
| 6 |
+
def round_price(price_str):
|
| 7 |
+
"""Fiyatı yuvarlama formülüne göre yuvarla"""
|
| 8 |
+
try:
|
| 9 |
+
# TL ve diğer karakterleri temizle
|
| 10 |
+
price_clean = price_str.replace(' TL', '').replace(',', '.')
|
| 11 |
+
price_float = float(price_clean)
|
| 12 |
+
|
| 13 |
+
# Fiyat 200000 üzerindeyse en yakın 5000'lik basamağa yuvarla
|
| 14 |
+
if price_float > 200000:
|
| 15 |
+
return str(round(price_float / 5000) * 5000)
|
| 16 |
+
# Fiyat 30000 üzerindeyse en yakın 1000'lik basamağa yuvarla
|
| 17 |
+
elif price_float > 30000:
|
| 18 |
+
return str(round(price_float / 1000) * 1000)
|
| 19 |
+
# Fiyat 10000 üzerindeyse en yakın 100'lük basamağa yuvarla
|
| 20 |
+
elif price_float > 10000:
|
| 21 |
+
return str(round(price_float / 100) * 100)
|
| 22 |
+
# Diğer durumlarda en yakın 10'luk basamağa yuvarla
|
| 23 |
+
else:
|
| 24 |
+
return str(round(price_float / 10) * 10)
|
| 25 |
+
except (ValueError, TypeError):
|
| 26 |
+
return price_str
|
| 27 |
+
|
| 28 |
+
def format_message_with_images(message):
|
| 29 |
+
"""Mesajdaki resim URL'lerini HTML formatına çevir"""
|
| 30 |
+
if "Ürün resmi:" not in message:
|
| 31 |
+
return message
|
| 32 |
+
|
| 33 |
+
lines = message.split('\n')
|
| 34 |
+
formatted_lines = []
|
| 35 |
+
|
| 36 |
+
for line in lines:
|
| 37 |
+
if line.startswith("Ürün resmi:"):
|
| 38 |
+
image_url = line.replace("Ürün resmi:", "").strip()
|
| 39 |
+
if image_url:
|
| 40 |
+
# HTML img tag'i oluştur
|
| 41 |
+
img_html = f"""
|
| 42 |
+
<div style="margin: 10px 0;">
|
| 43 |
+
<img src="{image_url}"
|
| 44 |
+
alt="Ürün Resmi"
|
| 45 |
+
style="max-width: 300px; max-height: 200px; border-radius: 8px; border: 1px solid #ddd; box-shadow: 0 2px 4px rgba(0,0,0,0.1);"
|
| 46 |
+
onerror="this.style.display='none'">
|
| 47 |
+
</div>"""
|
| 48 |
+
formatted_lines.append(img_html)
|
| 49 |
+
else:
|
| 50 |
+
formatted_lines.append(line)
|
| 51 |
+
else:
|
| 52 |
+
formatted_lines.append(line)
|
| 53 |
+
|
| 54 |
+
return '\n'.join(formatted_lines)
|
| 55 |
+
|
| 56 |
+
def create_product_gallery(products_with_images):
|
| 57 |
+
"""Birden fazla ürün için galeri oluştur"""
|
| 58 |
+
if not products_with_images:
|
| 59 |
+
return ""
|
| 60 |
+
|
| 61 |
+
gallery_html = """
|
| 62 |
+
<div style="display: flex; flex-wrap: wrap; gap: 15px; margin: 15px 0;">
|
| 63 |
+
"""
|
| 64 |
+
|
| 65 |
+
for product in products_with_images:
|
| 66 |
+
name = product.get('name', 'Bilinmeyen')
|
| 67 |
+
price = product.get('price', 'Fiyat yok')
|
| 68 |
+
image_url = product.get('image_url', '')
|
| 69 |
+
product_url = product.get('product_url', '')
|
| 70 |
+
|
| 71 |
+
if image_url:
|
| 72 |
+
card_html = f"""
|
| 73 |
+
<div style="border: 1px solid #ddd; border-radius: 8px; padding: 10px; max-width: 200px; text-align: center; background: white; box-shadow: 0 2px 4px rgba(0,0,0,0.1);">
|
| 74 |
+
<img src="{image_url}"
|
| 75 |
+
alt="{name}"
|
| 76 |
+
style="max-width: 180px; max-height: 120px; border-radius: 4px; margin-bottom: 8px;"
|
| 77 |
+
onerror="this.style.display='none'">
|
| 78 |
+
<div style="font-size: 12px; font-weight: bold; margin-bottom: 4px;">{name}</div>
|
| 79 |
+
<div style="font-size: 11px; color: #666; margin-bottom: 8px;">{price}</div>
|
| 80 |
+
{f'<a href="{product_url}" target="_blank" style="font-size: 10px; color: #007bff; text-decoration: none;">Detaylı Bilgi</a>' if product_url else ''}
|
| 81 |
+
</div>"""
|
| 82 |
+
gallery_html += card_html
|
| 83 |
+
|
| 84 |
+
gallery_html += "</div>"
|
| 85 |
+
return gallery_html
|
| 86 |
+
|
| 87 |
+
def extract_product_info_for_gallery(message):
|
| 88 |
+
"""Mesajdan ürün bilgilerini çıkarıp galeri formatına çevir"""
|
| 89 |
+
if "karşılaştır" in message.lower() or "öneri" in message.lower():
|
| 90 |
+
# Bu durumda galeri formatı kullan
|
| 91 |
+
lines = message.split('\n')
|
| 92 |
+
products = []
|
| 93 |
+
|
| 94 |
+
current_product = {}
|
| 95 |
+
for line in lines:
|
| 96 |
+
line = line.strip()
|
| 97 |
+
if line.startswith('•') and any(keyword in line.lower() for keyword in ['marlin', 'émonda', 'madone', 'domane', 'fuel', 'powerfly', 'fx']):
|
| 98 |
+
# Yeni ürün başladı
|
| 99 |
+
if current_product:
|
| 100 |
+
products.append(current_product)
|
| 101 |
+
|
| 102 |
+
# Ürün adı ve fiyatı parse et
|
| 103 |
+
parts = line.split(' - ')
|
| 104 |
+
name = parts[0].replace('•', '').strip()
|
| 105 |
+
price_raw = parts[1] if len(parts) > 1 else 'Fiyat yok'
|
| 106 |
+
|
| 107 |
+
# Fiyatı yuvarlama formülüne göre yuvarla
|
| 108 |
+
if price_raw != 'Fiyat yok':
|
| 109 |
+
price = round_price(price_raw) + ' TL'
|
| 110 |
+
else:
|
| 111 |
+
price = price_raw
|
| 112 |
+
|
| 113 |
+
current_product = {
|
| 114 |
+
'name': name,
|
| 115 |
+
'price': price,
|
| 116 |
+
'image_url': '',
|
| 117 |
+
'product_url': ''
|
| 118 |
+
}
|
| 119 |
+
elif "Ürün resmi:" in line and current_product:
|
| 120 |
+
current_product['image_url'] = line.replace("Ürün resmi:", "").strip()
|
| 121 |
+
elif "Ürün linki:" in line and current_product:
|
| 122 |
+
current_product['product_url'] = line.replace("Ürün linki:", "").strip()
|
| 123 |
+
|
| 124 |
+
# Son ürünü ekle
|
| 125 |
+
if current_product:
|
| 126 |
+
products.append(current_product)
|
| 127 |
+
|
| 128 |
+
if products:
|
| 129 |
+
gallery = create_product_gallery(products)
|
| 130 |
+
# Orijinal mesajdaki resim linklerini temizle
|
| 131 |
+
cleaned_message = message
|
| 132 |
+
for line in message.split('\n'):
|
| 133 |
+
if line.startswith("Ürün resmi:") or line.startswith("Ürün linki:"):
|
| 134 |
+
cleaned_message = cleaned_message.replace(line, "")
|
| 135 |
+
|
| 136 |
+
return cleaned_message.strip() + "\n\n" + gallery
|
| 137 |
+
|
| 138 |
+
return format_message_with_images(message)
|
| 139 |
+
|
| 140 |
+
def should_use_gallery_format(message):
|
| 141 |
+
"""Mesajın galeri formatı kullanması gerekip gerekmediğini kontrol et"""
|
| 142 |
+
gallery_keywords = ["karşılaştır", "öneri", "seçenek", "alternatif", "bütçe"]
|
| 143 |
+
return any(keyword in message.lower() for keyword in gallery_keywords)
|