Spaces:
Running
Running
import streamlit as st | |
import time | |
import random | |
import json | |
from datetime import datetime | |
import os | |
# تنظیمات اصلی چتبات | |
ADMIN_USERNAME = "admin" | |
ADMIN_PASSWORD = "password" | |
# CSS بهبود یافته با انیمیشنها و افکتهای جدید | |
CUSTOM_CSS = """ | |
<style> | |
@import url('https://fonts.googleapis.com/css2?family=Vazirmatn:wght@300;400;500;700&display=swap'); | |
@import url('https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css'); | |
:root { | |
--primary-color: #3b82f6; | |
--secondary-color: #6366f1; | |
--accent-color: #10b981; | |
--background-color: #f8fafc; | |
--chat-bg: #ffffff; | |
--user-message-bg: #e0e7ff; | |
--bot-message-bg: #f1f5f9; | |
--text-primary: #1e293b; | |
--text-secondary: #475569; | |
--border-color: #e2e8f0; | |
--error-color: #ef4444; | |
--success-color: #22c55e; | |
} | |
/* === انیمیشنهای جدید === */ | |
@keyframes slideIn { | |
from { transform: translateY(20px); opacity: 0; } | |
to { transform: translateY(0); opacity: 1; } | |
} | |
@keyframes pulse { | |
0% { transform: scale(1); } | |
50% { transform: scale(1.05); } | |
100% { transform: scale(1); } | |
} | |
@keyframes fadeIn { | |
from { opacity: 0; } | |
to { opacity: 1; } | |
} | |
/* === استایلهای اصلی === */ | |
body { | |
font-family: 'Vazirmatn', sans-serif !important; | |
background-color: var(--background-color); | |
direction: rtl; | |
} | |
.chat-container { | |
max-width: 900px; | |
margin: 2rem auto; | |
background: var(--chat-bg); | |
border-radius: 1rem; | |
box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1); | |
animation: slideIn 0.5s ease-out; | |
} | |
.chat-header { | |
background: linear-gradient(to left, var(--primary-color), var(--secondary-color)); | |
color: white; | |
padding: 1.5rem; | |
border-radius: 1rem 1rem 0 0; | |
text-align: center; | |
position: relative; | |
overflow: hidden; | |
} | |
.chat-header::before { | |
content: ''; | |
position: absolute; | |
top: -50%; | |
left: -50%; | |
width: 200%; | |
height: 200%; | |
background: linear-gradient( | |
45deg, | |
transparent 0%, | |
rgba(255, 255, 255, 0.1) 50%, | |
transparent 100% | |
); | |
animation: shine 3s infinite linear; | |
} | |
@keyframes shine { | |
from { transform: translateX(-100%) rotate(45deg); } | |
to { transform: translateX(100%) rotate(45deg); } | |
} | |
.chat-header h1 { | |
font-size: 1.75rem; | |
font-weight: 700; | |
margin: 0; | |
display: flex; | |
align-items: center; | |
justify-content: center; | |
gap: 0.75rem; | |
} | |
.chat-header h1 i { | |
animation: pulse 2s infinite; | |
} | |
.chat-messages { | |
height: 500px; | |
overflow-y: auto; | |
padding: 1.5rem; | |
background: var(--chat-bg); | |
scroll-behavior: smooth; | |
} | |
.message { | |
margin-bottom: 1rem; | |
max-width: 80%; | |
padding: 1rem; | |
border-radius: 0.75rem; | |
position: relative; | |
animation: fadeIn 0.3s ease-out; | |
transition: transform 0.2s; | |
} | |
.message:hover { | |
transform: translateY(-2px); | |
} | |
.message.user { | |
background: var(--user-message-bg); | |
margin-left: auto; | |
color: var(--text-primary); | |
box-shadow: 2px 2px 10px rgba(99, 102, 241, 0.1); | |
} | |
.message.bot { | |
background: var(--bot-message-bg); | |
margin-right: auto; | |
color: var(--text-primary); | |
box-shadow: 2px 2px 10px rgba(241, 245, 249, 0.3); | |
} | |
.message::before { | |
content: ''; | |
position: absolute; | |
width: 0; | |
height: 0; | |
border: 8px solid transparent; | |
} | |
.message.user::before { | |
border-left-color: var(--user-message-bg); | |
right: -16px; | |
top: 50%; | |
transform: translateY(-50%); | |
} | |
.message.bot::before { | |
border-right-color: var(--bot-message-bg); | |
left: -16px; | |
top: 50%; | |
transform: translateY(-50%); | |
} | |
.chat-input { | |
padding: 1.5rem; | |
border-top: 1px solid var(--border-color); | |
display: flex; | |
gap: 1rem; | |
align-items: center; | |
background: rgba(255, 255, 255, 0.9); | |
backdrop-filter: blur(10px); | |
} | |
.chat-input input { | |
flex: 1; | |
padding: 0.75rem 1rem; | |
border: 2px solid var(--border-color); | |
border-radius: 0.5rem; | |
font-family: 'Vazirmatn', sans-serif; | |
font-size: 0.875rem; | |
transition: all 0.3s; | |
} | |
.chat-input input:focus { | |
outline: none; | |
border-color: var(--primary-color); | |
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1); | |
} | |
.chat-input button { | |
background: var(--primary-color); | |
color: white; | |
border: none; | |
padding: 0.75rem 1.5rem; | |
border-radius: 0.5rem; | |
cursor: pointer; | |
display: flex; | |
align-items: center; | |
gap: 0.5rem; | |
transition: all 0.2s; | |
font-weight: 500; | |
} | |
.chat-input button:hover { | |
background: var(--secondary-color); | |
transform: translateY(-2px); | |
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1); | |
} | |
.chat-input button:active { | |
transform: translateY(0); | |
} | |
/* === قابلیتهای جدید === */ | |
.typing-indicator { | |
display: flex; | |
gap: 0.5rem; | |
padding: 1rem; | |
background: var(--bot-message-bg); | |
border-radius: 0.75rem; | |
width: fit-content; | |
margin-bottom: 1rem; | |
animation: fadeIn 0.3s; | |
} | |
.typing-dot { | |
width: 8px; | |
height: 8px; | |
background: var(--primary-color); | |
border-radius: 50%; | |
animation: typingDot 1s infinite; | |
} | |
.typing-dot:nth-child(2) { animation-delay: 0.2s; } | |
.typing-dot:nth-child(3) { animation-delay: 0.4s; } | |
@keyframes typingDot { | |
0%, 100% { transform: translateY(0); } | |
50% { transform: translateY(-5px); } | |
} | |
.quick-replies { | |
display: flex; | |
gap: 0.5rem; | |
flex-wrap: wrap; | |
margin-top: 1rem; | |
} | |
.quick-reply { | |
background: var(--accent-color); | |
color: white; | |
padding: 0.5rem 1rem; | |
border-radius: 2rem; | |
cursor: pointer; | |
transition: all 0.2s; | |
font-size: 0.875rem; | |
} | |
.quick-reply:hover { | |
transform: translateY(-2px); | |
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); | |
} | |
/* === پنل مدیریت === */ | |
.admin-panel { | |
background: white; | |
padding: 1.5rem; | |
border-radius: 0.75rem; | |
margin-bottom: 1rem; | |
box-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1); | |
} | |
.admin-panel h2 { | |
color: var(--text-primary); | |
font-size: 1.25rem; | |
margin-bottom: 1rem; | |
display: flex; | |
align-items: center; | |
gap: 0.5rem; | |
} | |
.admin-controls { | |
display: flex; | |
flex-direction: column; | |
gap: 1rem; | |
} | |
.admin-button { | |
display: flex; | |
align-items: center; | |
gap: 0.5rem; | |
padding: 0.75rem 1rem; | |
border-radius: 0.5rem; | |
cursor: pointer; | |
transition: all 0.2s; | |
border: none; | |
font-family: 'Vazirmatn', sans-serif; | |
font-weight: 500; | |
} | |
.admin-button.danger { | |
background: var(--error-color); | |
color: white; | |
} | |
.admin-button.success { | |
background: var(--success-color); | |
color: white; | |
} | |
.admin-button:hover { | |
transform: translateY(-2px); | |
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1); | |
} | |
.statistics { | |
background: white; | |
padding: 1rem; | |
border-radius: 0.5rem; | |
margin-top: 1rem; | |
} | |
.stat-item { | |
display: flex; | |
justify-content: space-between; | |
padding: 0.5rem 0; | |
border-bottom: 1px solid var(--border-color); | |
} | |
.stat-item:last-child { | |
border-bottom: none; | |
} | |
</style> | |
""" | |
class EnhancedChatbot: | |
def __init__(self): | |
self.conversation_history = [] | |
self.admin_logged_in = False | |
self.quick_replies = [ | |
"بخشنامههای جدید", | |
"راهنمای استفاده", | |
"تماس با پشتیبانی", | |
"گزارش مشکل" | |
] | |
self.stats = { | |
'total_messages': 0, | |
'user_messages': 0, | |
'bot_messages': 0, | |
'start_time': datetime.now() | |
} | |
self.load_responses() | |
def load_responses(self): | |
"""بارگذاری پاسخهای از پیش تعریف شده""" | |
self.responses = { | |
'greeting': [ | |
"سلام! چطور میتونم کمکتون کنم؟", | |
"درود! من پاسخگوی هوشمند بخشنامه هستم. چه کمکی از دستم برمیاد؟", | |
"خوش آمدید! در خدمت شما هستم." | |
], | |
'help': [ | |
"برای راهنمایی بیشتر میتونید از گزینههای سریع پایین استفاده کنید.", | |
"من میتونم در موارد زیر کمکتون کنم:\n- جستجوی بخشنامهها\n- پاسخ به سوالات متداول\n- راهنمایی در مورد فرآیندها", | |
], | |
'unknown': [ | |
"متوجه نشدم. میشه بیشتر توضیح بدید؟", | |
"میتونید سوالتون رو به شکل دیگهای بپرسید؟", | |
"برای راهنمایی بهتر، لطفاً جزئیات بیشتری ارائه کنید." | |
] | |
} | |
def chat_response(self, message): | |
"""پردازش پیام کاربر و ارائه پاسخ هوشمند""" | |
self.stats['total_messages'] += 1 | |
self.stats['user_messages'] += 1 | |
# افزودن پیام کاربر | |
self.conversation_history.append({ | |
'type': 'user', | |
'message': message, | |
'timestamp': datetime.now().strftime("%H:%M") | |
}) | |
# شبیهسازی تایپ کردن | |
time.sleep(1) | |
# انتخاب پاسخ مناسب | |
if any(word in message.lower() for word in ['سلام', 'درود', 'خوش آمدید']): | |
response = random.choice(self.responses['greeting']) | |
elif 'راهنمایی' in message.lower() or 'کمک' in message.lower(): | |
response = random.choice(self.responses['help']) | |
else: | |
response = random.choice(self.responses['unknown']) | |
self.stats['bot_messages'] += 1 | |
# افزودن پاسخ ربات | |
self.conversation_history.append({ | |
'type': 'bot', | |
'message': response, | |
'timestamp': datetime.now().strftime("%H:%M") | |
}) | |
return self.conversation_history | |
def get_stats(self): | |
"""دریافت آمار چتبات""" | |
uptime = datetime.now() - self.stats['start_time'] | |
return { | |
'total_messages': self.stats['total_messages'], | |
'user_messages': self.stats['user_messages'], | |
'bot_messages': self.stats['bot_messages'], | |
'uptime': str(uptime).split('.')[0], | |
'response_rate': f"{(self.stats['bot_messages'] / self.stats['user_messages'] * 100):.1f}%" if self.stats['user_messages'] > 0 else "0%" | |
} | |
# تنظیمات اولیه استریملیت | |
# ادامه کد قبلی... | |
# تنظیمات اولیه استریملیت | |
st.set_page_config( | |
page_title="پاسخگوی هوشمند بخشنامه", | |
page_icon="🤖", | |
layout="wide", | |
initial_sidebar_state="expanded" | |
) | |
# اعمال CSS | |
st.markdown(CUSTOM_CSS, unsafe_allow_html=True) | |
# ایجاد نمونه از چتبات | |
if 'chatbot' not in st.session_state: | |
st.session_state.chatbot = EnhancedChatbot() | |
# نمایش هدر اصلی | |
st.markdown(""" | |
<div class="chat-container"> | |
<div class="chat-header"> | |
<h1> | |
<i class="fas fa-robot"></i> | |
پاسخگوی هوشمند بخشنامه | |
<span class="status-badge online"> | |
<i class="fas fa-circle"></i> | |
</span> | |
</h1> | |
</div> | |
<div class="chat-messages" id="chat-messages"> | |
""", unsafe_allow_html=True) | |
# نمایش پیامها | |
for message in st.session_state.chatbot.conversation_history: | |
message_class = "user" if message['type'] == 'user' else "bot" | |
icon = "user" if message['type'] == 'user' else "robot" | |
st.markdown(f""" | |
<div class="message {message_class}"> | |
<div class="message-header"> | |
<i class="fas fa-{icon}"></i> | |
<span class="timestamp">{message['timestamp']}</span> | |
</div> | |
<div class="message-content"> | |
{message['message']} | |
</div> | |
</div> | |
""", unsafe_allow_html=True) | |
# نمایش نشانگر تایپ کردن | |
if st.session_state.get('is_typing', False): | |
st.markdown(""" | |
<div class="typing-indicator"> | |
<div class="typing-dot"></div> | |
<div class="typing-dot"></div> | |
<div class="typing-dot"></div> | |
</div> | |
""", unsafe_allow_html=True) | |
# پاسخهای سریع | |
st.markdown(""" | |
<div class="quick-replies"> | |
""", unsafe_allow_html=True) | |
for reply in st.session_state.chatbot.quick_replies: | |
st.markdown(f""" | |
<div class="quick-reply" onclick="document.getElementById('user-input').value='{reply}'"> | |
{reply} | |
</div> | |
""", unsafe_allow_html=True) | |
st.markdown("</div>", unsafe_allow_html=True) | |
# بخش ورودی پیام | |
col1, col2 = st.columns([4, 1]) | |
with col1: | |
user_message = st.text_input( | |
"", | |
placeholder="پیام خود را بنویسید...", | |
key="user_message", | |
help="برای ارسال پیام، متن خود را وارد کرده و دکمه ارسال را بزنید" | |
) | |
with col2: | |
send_button = st.button( | |
"ارسال پیام", | |
key="send_button", | |
help="برای ارسال پیام کلیک کنید" | |
) | |
if send_button and user_message: | |
st.session_state['is_typing'] = True | |
st.session_state.chatbot.chat_response(user_message) | |
st.session_state['is_typing'] = False | |
st.experimental_rerun() | |
st.markdown("</div>", unsafe_allow_html=True) | |
# پنل مدیریت در سایدبار | |
with st.sidebar: | |
st.markdown(""" | |
<div class="admin-panel"> | |
<h2> | |
<i class="fas fa-cog"></i> | |
پنل مدیریت | |
</h2> | |
</div> | |
""", unsafe_allow_html=True) | |
if st.checkbox("نمایش آمار"): | |
stats = st.session_state.chatbot.get_stats() | |
st.markdown(""" | |
<div class="statistics"> | |
<h3>آمار سیستم</h3> | |
""", unsafe_allow_html=True) | |
for key, value in stats.items(): | |
st.markdown(f""" | |
<div class="stat-item"> | |
<span>{key}:</span> | |
<strong>{value}</strong> | |
</div> | |
""", unsafe_allow_html=True) | |
st.markdown("</div>", unsafe_allow_html=True) | |
if st.button("پاک کردن تاریخچه", key="clear_history"): | |
st.session_state.chatbot.conversation_history = [] | |
st.experimental_rerun() | |
# تنظیمات ظاهری | |
st.markdown("### تنظیمات ظاهری") | |
font_size = st.slider("اندازه متن", 12, 20, 14) | |
st.markdown(f""" | |
<style> | |
.message {{ font-size: {font_size}px; }} | |
</style> | |
""", unsafe_allow_html=True) | |
# اضافه کردن اسکریپتهای جاوااسکریپت برای عملکرد بهتر | |
st.markdown(""" | |
<script> | |
// اسکرول خودکار به آخرین پیام | |
function scrollToBottom() { | |
const messages = document.querySelector('.chat-messages'); | |
messages.scrollTop = messages.scrollHeight; | |
} | |
// اجرای اسکرول در لود صفحه | |
window.onload = scrollToBottom; | |
// مدیریت کلیدهای میانبر | |
document.addEventListener('keydown', function(event) { | |
if (event.key === 'Enter' && !event.shiftKey) { | |
const sendButton = document.querySelector('button:contains("ارسال پیام")'); | |
if (sendButton) { | |
sendButton.click(); | |
} | |
} | |
}); | |
</script> | |
""", unsafe_allow_html=True) |