samirerty commited on
Commit
1ea58dc
·
verified ·
1 Parent(s): 9e9ed87

Upload streamlit_app.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. streamlit_app.py +528 -0
streamlit_app.py ADDED
@@ -0,0 +1,528 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import time
3
+ import random
4
+ import datetime
5
+ from utils import (
6
+ analyze_sentiment,
7
+ generate_ai_response,
8
+ get_mock_users,
9
+ get_mock_rooms,
10
+ get_initial_messages
11
+ )
12
+
13
+ # --- PAGE CONFIGURATION ---
14
+ st.set_page_config(
15
+ page_title="چت روم هوشمند",
16
+ page_icon="🤖",
17
+ layout="wide",
18
+ initial_sidebar_state="expanded"
19
+ )
20
+
21
+ # --- CSS STYLING (Ported from PHP/HTML) ---
22
+ st.markdown("""
23
+ <style>
24
+ /* Import Fonts */
25
+ @import url('https://fonts.googleapis.com/css2?family=Vazirmatn:wght@100;300;400;500;700;900&display=swap');
26
+ @import url('https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css');
27
+
28
+ :root {
29
+ --glass-bg: rgba(255, 255, 255, 0.05);
30
+ --glass-border: rgba(255, 255, 255, 0.1);
31
+ --primary-gradient: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
32
+ --text-color: #ffffff;
33
+ --bg-gradient: linear-gradient(-45deg, #0f0c29, #302b63, #24243e, #4a1c40);
34
+ }
35
+
36
+ /* Global resets */
37
+ .stApp {
38
+ background: var(--bg-gradient);
39
+ background-size: 400% 400%;
40
+ animation: gradientBG 20s ease infinite;
41
+ font-family: 'Vazirmatn', sans-serif !important;
42
+ color: var(--text-color);
43
+ direction: rtl;
44
+ }
45
+
46
+ @keyframes gradientBG {
47
+ 0% { background-position: 0% 50%; }
48
+ 50% { background-position: 100% 50%; }
49
+ 100% { background-position: 0% 50%; }
50
+ }
51
+
52
+ /* Hide Streamlit Default Elements */
53
+ #MainMenu {visibility: hidden;}
54
+ footer {visibility: hidden;}
55
+ header {visibility: hidden;}
56
+ .stDeployButton {display: none;}
57
+
58
+ /* Glassmorphism Containers */
59
+ .glass-panel {
60
+ background: var(--glass-bg);
61
+ backdrop-filter: blur(20px);
62
+ -webkit-backdrop-filter: blur(20px);
63
+ border: 1px solid var(--glass-border);
64
+ border-radius: 24px;
65
+ box-shadow: 0 8px 32px 0 rgba(0, 0, 0, 0.3);
66
+ }
67
+
68
+ /* Login Page Specifics */
69
+ .login-container {
70
+ display: flex;
71
+ justify-content: center;
72
+ align-items: center;
73
+ min-height: 80vh;
74
+ }
75
+
76
+ .login-box {
77
+ max-width: 450px;
78
+ width: 100%;
79
+ padding: 40px;
80
+ text-align: center;
81
+ }
82
+
83
+ /* Chat Layout */
84
+ .chat-layout {
85
+ display: flex;
86
+ gap: 20px;
87
+ height: calc(100vh - 100px);
88
+ padding: 20px;
89
+ box-sizing: border-box;
90
+ }
91
+
92
+ .sidebar-area {
93
+ width: 280px;
94
+ display: flex;
95
+ flex-direction: column;
96
+ padding: 20px;
97
+ }
98
+
99
+ .main-chat-area {
100
+ flex: 1;
101
+ display: flex;
102
+ flex-direction: column;
103
+ padding: 20px;
104
+ overflow: hidden;
105
+ }
106
+
107
+ /* User List */
108
+ .user-item {
109
+ display: flex;
110
+ align-items: center;
111
+ gap: 10px;
112
+ padding: 10px;
113
+ margin-bottom: 8px;
114
+ background: rgba(255,255,255,0.02);
115
+ border-radius: 10px;
116
+ transition: background 0.2s;
117
+ }
118
+
119
+ .user-item:hover {
120
+ background: rgba(255,255,255,0.08);
121
+ }
122
+
123
+ .user-avatar {
124
+ width: 40px;
125
+ height: 40px;
126
+ border-radius: 50%;
127
+ background: var(--primary-gradient);
128
+ display: flex;
129
+ align-items: center;
130
+ justify-content: center;
131
+ font-weight: bold;
132
+ }
133
+
134
+ .status-dot {
135
+ width: 10px;
136
+ height: 10px;
137
+ border-radius: 50%;
138
+ background: #555;
139
+ }
140
+
141
+ .status-online {
142
+ background: #00d2d3;
143
+ box-shadow: 0 0 8px #00d2d3;
144
+ }
145
+
146
+ /* Messages */
147
+ .messages-container {
148
+ flex: 1;
149
+ overflow-y: auto;
150
+ padding: 10px;
151
+ margin-bottom: 20px;
152
+ display: flex;
153
+ flex-direction: column;
154
+ gap: 15px;
155
+ scrollbar-width: thin;
156
+ scrollbar-color: rgba(255,255,255,0.2) transparent;
157
+ }
158
+
159
+ .message {
160
+ max-width: 70%;
161
+ padding: 12px 16px;
162
+ border-radius: 16px;
163
+ position: relative;
164
+ line-height: 1.5;
165
+ animation: fadeIn 0.3s ease;
166
+ }
167
+
168
+ @keyframes fadeIn {
169
+ from { opacity: 0; transform: translateY(10px); }
170
+ to { opacity: 1; transform: translateY(0); }
171
+ }
172
+
173
+ .message.own {
174
+ align-self: flex-end;
175
+ background: var(--primary-gradient);
176
+ border-bottom-right-radius: 4px;
177
+ }
178
+
179
+ .message.other {
180
+ align-self: flex-start;
181
+ background: rgba(255, 255, 255, 0.1);
182
+ border: 1px solid rgba(255, 255, 255, 0.1);
183
+ border-bottom-left-radius: 4px;
184
+ }
185
+
186
+ .message-header {
187
+ display: flex;
188
+ justify-content: space-between;
189
+ font-size: 0.75rem;
190
+ opacity: 0.8;
191
+ margin-bottom: 5px;
192
+ }
193
+
194
+ .message-content {
195
+ white-space: pre-wrap;
196
+ }
197
+
198
+ /* Input Area */
199
+ .chat-input-container {
200
+ display: flex;
201
+ gap: 10px;
202
+ align-items: center;
203
+ }
204
+
205
+ .emoji-bar {
206
+ display: flex;
207
+ gap: 8px;
208
+ margin-top: 10px;
209
+ }
210
+
211
+ .emoji-btn {
212
+ background: rgba(255,255,255,0.05);
213
+ border: none;
214
+ color: white;
215
+ width: 35px;
216
+ height: 35px;
217
+ border-radius: 50%;
218
+ cursor: pointer;
219
+ transition: transform 0.2s;
220
+ font-size: 1.2rem;
221
+ }
222
+
223
+ .emoji-btn:hover {
224
+ transform: scale(1.2);
225
+ background: rgba(255,255,255,0.15);
226
+ }
227
+
228
+ /* Custom Streamlit Elements overrides */
229
+ div[data-testid="stTextInput"] > div > div > input {
230
+ background: rgba(0,0,0,0.3);
231
+ color: white;
232
+ border: 1px solid var(--glass-border);
233
+ border-radius: 12px;
234
+ }
235
+
236
+ div[data-testid="stSelectbox"] > div > div > select {
237
+ background: rgba(0,0,0,0.3);
238
+ color: white;
239
+ border: 1px solid var(--glass-border);
240
+ }
241
+
242
+ .stButton > button {
243
+ border-radius: 12px;
244
+ font-weight: bold;
245
+ transition: all 0.2s;
246
+ }
247
+
248
+ .primary-btn {
249
+ background: var(--primary-gradient) !important;
250
+ border: none !important;
251
+ color: white !important;
252
+ }
253
+
254
+ .secondary-btn {
255
+ background: rgba(255,255,255,0.1) !important;
256
+ border: 1px solid rgba(255,255,255,0.2) !important;
257
+ color: white !important;
258
+ }
259
+
260
+ /* Admin Actions */
261
+ .admin-actions {
262
+ font-size: 0.7rem;
263
+ margin-top: 5px;
264
+ text-align: left;
265
+ cursor: pointer;
266
+ color: #ff6b6b;
267
+ }
268
+ </style>
269
+ """, unsafe_allow_html=True)
270
+
271
+ # --- SESSION STATE INITIALIZATION ---
272
+ if 'logged_in' not in st.session_state:
273
+ st.session_state.logged_in = False
274
+ if 'username' not in st.session_state:
275
+ st.session_state.username = ""
276
+ if 'role' not in st.session_state:
277
+ st.session_state.role = "user" # or 'admin'
278
+ if 'current_room' not in st.session_state:
279
+ st.session_state.current_room = 1
280
+ if 'messages' not in st.session_state:
281
+ st.session_state.messages = get_initial_messages()
282
+ if 'users' not in st.session_state:
283
+ st.session_state.users = get_mock_users()
284
+
285
+ # --- HELPER FUNCTIONS ---
286
+
287
+ def render_message(msg):
288
+ is_own = msg['user_id'] == st.session_state.username # Simulating ID check
289
+
290
+ msg_class = "own" if is_own else "other"
291
+ sender_name = "شما" if is_own else msg['username']
292
+
293
+ # Admin delete button logic
294
+ admin_html = ""
295
+ if st.session_state.role == 'admin' and not is_own:
296
+ admin_html = f"""
297
+ <div class="admin-actions" onclick="deleteMessage({msg['id']})">
298
+ <i class="fas fa-trash"></i> حذف پیام
299
+ </div>
300
+ """
301
+
302
+ time_str = msg['time']
303
+
304
+ return f"""
305
+ <div class="message {msg_class}">
306
+ <div class="message-header">
307
+ <span>{sender_name}</span>
308
+ <span>{time_str}</span>
309
+ </div>
310
+ <div class="message-content">{msg['text']}</div>
311
+ {admin_html}
312
+ </div>
313
+ """
314
+
315
+ def get_room_name(room_id):
316
+ rooms = get_mock_rooms()
317
+ for r in rooms:
318
+ if r['id'] == room_id:
319
+ return r['name']
320
+ return "اتاق ناشناس"
321
+
322
+ # --- PAGES ---
323
+
324
+ def login_page():
325
+ st.markdown("""
326
+ <div class="login-container">
327
+ <div class="glass-panel login-box">
328
+ <div style="font-size: 3rem; margin-bottom: 20px;">🤖</div>
329
+ <h1 style="margin-bottom: 10px;">چت روم هوشمند</h1>
330
+ <p style="opacity: 0.7; margin-bottom: 30px;">ورود به دنیای هوش مصنوعی</p>
331
+ <a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank" style="font-size: 0.8rem; color: rgba(255, 255, 255, 0.5); text-decoration: none; border: 1px solid rgba(255, 255, 255, 0.1); padding: 4px 12px; border-radius: 20px; display: inline-block; margin-bottom: 20px;">
332
+ Built with anycoder
333
+ </a>
334
+ </div>
335
+ </div>
336
+ """, unsafe_allow_html=True)
337
+
338
+ with st.container():
339
+ col1, col2, col3 = st.columns([1, 2, 1])
340
+ with col2:
341
+ # Hidden Login Form logic
342
+ with st.form("login_form", clear_on_submit=True):
343
+ username_input = st.text_input("نام کاربری", placeholder="نام کاربری خود را وارد کنید")
344
+ password_input = st.text_input("رمز عبور", type="password", placeholder="رمز عبور")
345
+ submit_btn = st.form_submit_button("ورود به سیستم", use_container_width=True)
346
+
347
+ # Simple auth simulation
348
+ if submit_btn:
349
+ if username_input and password_input:
350
+ st.session_state.logged_in = True
351
+ st.session_state.username = username_input
352
+ # Simulate admin login if username is admin
353
+ st.session_state.role = 'admin' if username_input.lower() == 'admin' else 'user'
354
+ st.rerun()
355
+ else:
356
+ st.error("لطفاً ن��م کاربری و رمز عبور را وارد کنید.")
357
+
358
+ st.markdown("<div style='text-align: center; margin-top: 20px; opacity: 0.5;'>حساب کاربری ندارید؟ <a href='#' style='color: #a29bfe;'>ثبت نام کنید</a></div>", unsafe_allow_html=True)
359
+
360
+ def chat_page():
361
+ # Layout
362
+ sidebar, main = st.columns([1, 3])
363
+
364
+ current_room_id = st.session_state.current_room
365
+ room_name = get_room_name(current_room_id)
366
+
367
+ # --- SIDEBAR ---
368
+ with sidebar:
369
+ st.markdown(f"""
370
+ <div class="glass-panel sidebar-area">
371
+ <h3 style="margin-top:0;"><i class="fas fa-users"></i> کاربران آنلاین</h3>
372
+ <div style="margin-bottom: 20px; font-size: 0.9rem; opacity: 0.8;">{room_name}</div>
373
+ """, unsafe_allow_html=True)
374
+
375
+ # Room Selector
376
+ rooms = get_mock_rooms()
377
+ room_options = {r['name']: r['id'] for r in rooms}
378
+ selected_room_name = st.selectbox(
379
+ "تغییر اتاق",
380
+ options=list(room_options.keys()),
381
+ index=list(room_options.values()).index(current_room_id),
382
+ label_visibility="collapsed"
383
+ )
384
+
385
+ if selected_room_name != room_name:
386
+ st.session_state.current_room = room_options[selected_room_name]
387
+ st.rerun()
388
+
389
+ st.markdown("---")
390
+
391
+ # User List
392
+ users_html = ""
393
+ for user in st.session_state.users:
394
+ status_class = "status-online" if user['online'] else ""
395
+ status_text = "آنلاین" if user['online'] else "آفلاین"
396
+
397
+ users_html += f"""
398
+ <div class="user-item">
399
+ <div class="user-avatar">{user['name'][0]}</div>
400
+ <div style="flex:1">
401
+ <div>{user['name']}</div>
402
+ <div style="font-size: 0.75rem; opacity: 0.6;">
403
+ <span class="status-dot {status_class}"></span> {status_text}
404
+ </div>
405
+ </div>
406
+ </div>
407
+ """
408
+ st.markdown(users_html, unsafe_allow_html=True)
409
+
410
+ st.markdown("</div>", unsafe_allow_html=True) # Close sidebar
411
+
412
+ # Logout
413
+ if st.button("خروج از سیستم", use_container_width=True, key="logout_btn"):
414
+ st.session_state.logged_in = False
415
+ st.session_state.messages = [] # clear session
416
+ st.rerun()
417
+
418
+ # --- MAIN CHAT AREA ---
419
+ with main:
420
+ st.markdown(f"""
421
+ <div class="glass-panel main-chat-area">
422
+ <div style="display:flex; justify-content:space-between; align-items:center; margin-bottom:20px; border-bottom: 1px solid rgba(255,255,255,0.1); padding-bottom: 15px;">
423
+ <div>
424
+ <h2 style="margin:0;"><i class="fas fa-comments"></i> {room_name}</h2>
425
+ <p style="margin:0; opacity:0.6; font-size:0.9rem;">گفتگوی آزاد و محترمانه</p>
426
+ </div>
427
+ <div>
428
+ {f'<button class="secondary-btn" onclick="alert(\'Only Admin\')" style="padding: 5px 15px; font-size: 0.8rem;"><i class="fas fa-trash"></i> پاک کردن</button>' if st.session_state.role == 'admin' else ''}
429
+ </div>
430
+ </div>
431
+ """, unsafe_allow_html=True)
432
+
433
+ # Messages Container
434
+ with st.container():
435
+ msg_container = st.container()
436
+
437
+ # Filter messages for current room
438
+ room_messages = [m for m in st.session_state.messages if m['room_id'] == current_room_id]
439
+
440
+ with msg_container:
441
+ st.markdown('<div class="messages-container">', unsafe_allow_html=True)
442
+ if not room_messages:
443
+ st.markdown("""
444
+ <div style="text-align: center; opacity: 0.5; margin-top: 50px;">
445
+ <i class="fas fa-comments" style="font-size: 3rem;"></i>
446
+ <p>هنوز هیچ پیامی نیست. اولین نفر باشید!</p>
447
+ </div>
448
+ """, unsafe_allow_html=True)
449
+ else:
450
+ for msg in room_messages:
451
+ st.markdown(render_message(msg), unsafe_allow_html=True)
452
+ st.markdown("</div>", unsafe_allow_html=True)
453
+
454
+ # Input Area
455
+ with st.form("chat_form", clear_on_submit=True):
456
+ col_input, col_send = st.columns([5, 1])
457
+ with col_input:
458
+ user_input = st.text_input("message_input", placeholder="پیام خود را بنویسید...", label_visibility="collapsed")
459
+ with col_send:
460
+ submit = st.form_submit_button("ارسال", use_container_width=True)
461
+
462
+ # Emoji Bar (Custom HTML buttons)
463
+ st.markdown("""
464
+ <div class="emoji-bar">
465
+ <button class="emoji-btn" onclick="setInput('😊')">���</button>
466
+ <button class="emoji-btn" onclick="setInput('😂')">😂</button>
467
+ <button class="emoji-btn" onclick="setInput('❤️')">❤️</button>
468
+ <button class="emoji-btn" onclick="setInput('👍')">👍</button>
469
+ </div>
470
+ """, unsafe_allow_html=True)
471
+
472
+ # JS to handle emoji clicks (using streamlit's set_query_param or similar trick is hard,
473
+ # so we stick to Python handling for simplicity here, or just visual buttons)
474
+ # For a functional emoji click in Streamlit without components, we can use st.session_state
475
+
476
+ emojis = ["😊", "😂", "❤️", "👍"]
477
+ cols = st.columns(4)
478
+ for i, emoji in enumerate(emojis):
479
+ if cols[i].button(emoji, key=f"emoji_{i}"):
480
+ st.session_state.temp_input = user_input + emoji
481
+ st.rerun()
482
+
483
+ if submit and user_input:
484
+ # Add User Message
485
+ new_msg = {
486
+ "id": int(time.time() * 1000),
487
+ "room_id": current_room_id,
488
+ "user_id": st.session_state.username,
489
+ "username": st.session_state.username,
490
+ "text": user_input,
491
+ "time": datetime.datetime.now().strftime("%H:%M"),
492
+ "is_deleted": False
493
+ }
494
+ st.session_state.messages.append(new_msg)
495
+ st.rerun()
496
+
497
+ # Simulate AI/Bot Response
498
+ time.sleep(0.5) # Simulate thinking
499
+ response_text = generate_ai_response(user_input)
500
+
501
+ bot_msg = {
502
+ "id": int(time.time() * 1000) + 1,
503
+ "room_id": current_room_id,
504
+ "user_id": "ai_bot",
505
+ "username": "دستیار هوشمند",
506
+ "text": response_text,
507
+ "time": datetime.datetime.now().strftime("%H:%M"),
508
+ "is_deleted": False
509
+ }
510
+ st.session_state.messages.append(bot_msg)
511
+ st.rerun()
512
+
513
+ st.markdown("</div>", unsafe_allow_html=True) # Close main-chat-area
514
+
515
+ # --- MAIN NAVIGATION LOGIC ---
516
+
517
+ # Use temp_input for emoji appending
518
+ if 'temp_input' not in st.session_state:
519
+ st.session_state.temp_input = ""
520
+
521
+ def main():
522
+ if not st.session_state.logged_in:
523
+ login_page()
524
+ else:
525
+ chat_page()
526
+
527
+ if __name__ == "__main__":
528
+ main()