Spaces:
Sleeping
Sleeping
Commit ·
0a5b9f7
1
Parent(s): 4fa43d3
Make email optional and show results as HTML in Gradio - solves HuggingFace Spaces SMTP timeout issue
Browse files
app.py
CHANGED
|
@@ -838,7 +838,7 @@ def get_fetcher():
|
|
| 838 |
logger.debug("[FETCHER] HTTP fetcher kullanılıyor")
|
| 839 |
return http_fetcher
|
| 840 |
|
| 841 |
-
def run_full_report():
|
| 842 |
"""Tam rapor çalıştırır (PHP tefas_daily_report.php'nin aynısı)"""
|
| 843 |
logger.info("="*50)
|
| 844 |
logger.info("[REPORT] Tam rapor başlatılıyor...")
|
|
@@ -862,7 +862,7 @@ def run_full_report():
|
|
| 862 |
logger.info(f"[REPORT] HTTP fallback başarılı, {len(fon_data_list)} fon verisi çekildi")
|
| 863 |
except Exception as e2:
|
| 864 |
logger.error(f"[REPORT] HTTP fallback de başarısız: {str(e2)}")
|
| 865 |
-
return f"❌ Veri çekilemedi!
|
| 866 |
|
| 867 |
# Dict'e çevir
|
| 868 |
fon_dict = {}
|
|
@@ -875,23 +875,47 @@ def run_full_report():
|
|
| 875 |
portfolios = portfolio_calc.calculate_all_portfolios(fon_dict)
|
| 876 |
logger.info(f"[REPORT] {len(portfolios)} portföy hesaplandı")
|
| 877 |
|
| 878 |
-
#
|
| 879 |
-
logger.info(f"[REPORT] E-posta gönderiliyor: {config['email']['to_email']}")
|
| 880 |
email_sender = EmailSender(config)
|
| 881 |
-
|
| 882 |
|
| 883 |
-
|
| 884 |
-
|
| 885 |
-
|
| 886 |
-
logger.info(f"[REPORT]
|
| 887 |
-
|
| 888 |
-
|
| 889 |
-
|
| 890 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 891 |
|
| 892 |
except Exception as e:
|
| 893 |
logger.error(f"[REPORT] Genel hata: {str(e)}", exc_info=True)
|
| 894 |
-
return f"❌ Hata oluştu:
|
| 895 |
|
| 896 |
def fetch_fund(fund_code):
|
| 897 |
"""Tek bir fon için veri çeker ve formatlar"""
|
|
@@ -954,12 +978,27 @@ with gr.Blocks(title="TEFAS Fon Takip", theme=gr.themes.Soft()) as app:
|
|
| 954 |
""")
|
| 955 |
|
| 956 |
with gr.Tabs():
|
| 957 |
-
with gr.Tab("🚀 Tam Rapor
|
| 958 |
-
gr.Markdown("### Tüm fonları çekip, portföy analizi yapıp
|
| 959 |
-
|
| 960 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 961 |
|
| 962 |
-
btn_full_report.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 963 |
|
| 964 |
with gr.Tab("🔍 Tek Fon Sorgula"):
|
| 965 |
fund_input_single = gr.Textbox(
|
|
|
|
| 838 |
logger.debug("[FETCHER] HTTP fetcher kullanılıyor")
|
| 839 |
return http_fetcher
|
| 840 |
|
| 841 |
+
def run_full_report(send_email=True):
|
| 842 |
"""Tam rapor çalıştırır (PHP tefas_daily_report.php'nin aynısı)"""
|
| 843 |
logger.info("="*50)
|
| 844 |
logger.info("[REPORT] Tam rapor başlatılıyor...")
|
|
|
|
| 862 |
logger.info(f"[REPORT] HTTP fallback başarılı, {len(fon_data_list)} fon verisi çekildi")
|
| 863 |
except Exception as e2:
|
| 864 |
logger.error(f"[REPORT] HTTP fallback de başarısız: {str(e2)}")
|
| 865 |
+
return f"<div style='color: #e74c3c; padding: 20px; background: #ffe6e6; border-radius: 8px;'>❌ <strong>Veri çekilemedi!</strong><br><br>Selenium hatası: {escape(str(e))}<br>HTTP hatası: {escape(str(e2))}</div>"
|
| 866 |
|
| 867 |
# Dict'e çevir
|
| 868 |
fon_dict = {}
|
|
|
|
| 875 |
portfolios = portfolio_calc.calculate_all_portfolios(fon_dict)
|
| 876 |
logger.info(f"[REPORT] {len(portfolios)} portföy hesaplandı")
|
| 877 |
|
| 878 |
+
# Sonuçları HTML olarak oluştur
|
|
|
|
| 879 |
email_sender = EmailSender(config)
|
| 880 |
+
html_content = email_sender.generate_html_email(fon_dict, portfolios)
|
| 881 |
|
| 882 |
+
# E-posta göndermeyi dene (opsiyonel)
|
| 883 |
+
email_result = None
|
| 884 |
+
if send_email:
|
| 885 |
+
logger.info(f"[REPORT] E-posta gönderiliyor: {config['email']['to_email']}")
|
| 886 |
+
try:
|
| 887 |
+
email_result = email_sender.send_report(fon_dict, portfolios)
|
| 888 |
+
if email_result['success']:
|
| 889 |
+
logger.info("[REPORT] E-posta başarıyla gönderildi")
|
| 890 |
+
else:
|
| 891 |
+
logger.warning(f"[REPORT] E-posta gönderilemedi: {email_result['message']}")
|
| 892 |
+
except Exception as e:
|
| 893 |
+
logger.warning(f"[REPORT] E-posta gönderme hatası (devam ediliyor): {str(e)}")
|
| 894 |
+
email_result = {'success': False, 'message': str(e)}
|
| 895 |
+
|
| 896 |
+
# Sonuç HTML'ine e-posta durumunu ekle
|
| 897 |
+
basarili = sum(1 for f in fon_data_list if not f.get('error'))
|
| 898 |
+
hatali = sum(1 for f in fon_data_list if f.get('error'))
|
| 899 |
+
|
| 900 |
+
status_html = f"""
|
| 901 |
+
<div style="background: #ecf0f1; padding: 15px; margin: 20px 0; border-radius: 8px; border-left: 4px solid #3498db;">
|
| 902 |
+
<h3 style="margin-top: 0; color: #2c3e50;">📊 Rapor Özeti</h3>
|
| 903 |
+
<p><strong>Başarılı fon:</strong> {basarili} | <strong>Hatalı fon:</strong> {hatali}</p>
|
| 904 |
+
<p><strong>Portföy sayısı:</strong> {len(portfolios)}</p>
|
| 905 |
+
{f"<p style='color: #27ae60;'><strong>✅ E-posta gönderildi:</strong> {config['email']['to_email']}</p>" if send_email and email_result and email_result.get('success') else ""}
|
| 906 |
+
{f"<p style='color: #e74c3c;'><strong>⚠️ E-posta gönderilemedi:</strong> {escape(email_result.get('message', 'Bilinmeyen hata') if email_result else 'E-posta gönderilmedi')}<br><small>HuggingFace Spaces dış SMTP bağlantılarını engelliyor olabilir. Sonuçlar aşağıda görüntülenebilir.</small></p>" if send_email and (not email_result or not email_result.get('success')) else ""}
|
| 907 |
+
{f"<p style='color: #7f8c8d;'><small>E-posta gönderilmedi (opsiyonel kapatıldı)</small></p>" if not send_email else ""}
|
| 908 |
+
</div>
|
| 909 |
+
"""
|
| 910 |
+
|
| 911 |
+
# HTML içeriğini status ile birleştir
|
| 912 |
+
final_html = status_html + html_content
|
| 913 |
+
|
| 914 |
+
return final_html
|
| 915 |
|
| 916 |
except Exception as e:
|
| 917 |
logger.error(f"[REPORT] Genel hata: {str(e)}", exc_info=True)
|
| 918 |
+
return f"<div style='color: #e74c3c; padding: 20px; background: #ffe6e6; border-radius: 8px;'>❌ <strong>Hata oluştu:</strong><br><br>{escape(str(e))}</div>"
|
| 919 |
|
| 920 |
def fetch_fund(fund_code):
|
| 921 |
"""Tek bir fon için veri çeker ve formatlar"""
|
|
|
|
| 978 |
""")
|
| 979 |
|
| 980 |
with gr.Tabs():
|
| 981 |
+
with gr.Tab("🚀 Tam Rapor"):
|
| 982 |
+
gr.Markdown("### Tüm fonları çekip, portföy analizi yapıp rapor oluşturur")
|
| 983 |
+
|
| 984 |
+
with gr.Row():
|
| 985 |
+
send_email_checkbox = gr.Checkbox(
|
| 986 |
+
label="E-posta Gönder (Opsiyonel - HuggingFace Spaces'te çalışmayabilir)",
|
| 987 |
+
value=False,
|
| 988 |
+
info="E-posta göndermeyi denemek için işaretleyin. HuggingFace Spaces dış SMTP bağlantılarını engelliyor olabilir."
|
| 989 |
+
)
|
| 990 |
|
| 991 |
+
btn_full_report = gr.Button("📊 Tam Rapor Oluştur", variant="primary", size="lg")
|
| 992 |
+
output_full_report = gr.HTML(label="Rapor")
|
| 993 |
+
|
| 994 |
+
def run_report_with_email(send_email):
|
| 995 |
+
return run_full_report(send_email=send_email)
|
| 996 |
+
|
| 997 |
+
btn_full_report.click(
|
| 998 |
+
fn=run_report_with_email,
|
| 999 |
+
inputs=send_email_checkbox,
|
| 1000 |
+
outputs=output_full_report
|
| 1001 |
+
)
|
| 1002 |
|
| 1003 |
with gr.Tab("🔍 Tek Fon Sorgula"):
|
| 1004 |
fund_input_single = gr.Textbox(
|