0qwpifs commited on
Commit
bd94d91
·
verified ·
1 Parent(s): d25de9d

Update app.py from anycoder

Browse files
Files changed (1) hide show
  1. app.py +469 -0
app.py ADDED
@@ -0,0 +1,469 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import random
3
+ import time
4
+ from datetime import datetime
5
+ from typing import List, Dict, Tuple
6
+
7
+ # Данные друзей и чатов
8
+ friends_data = {
9
+ "AlexGamer": {"status": "online", "avatar": "🎮", "last_seen": "Сейчас"},
10
+ "ProPlayer": {"status": "online", "avatar": "🏆", "last_seen": "Сейчас"},
11
+ "BuilderMaster": {"status": "away", "avatar": "🏗️", "last_seen": "5 мин назад"},
12
+ "SpeedRunner": {"status": "offline", "avatar": "⚡", "last_seen": "1 час назад"},
13
+ "CreativeMind": {"status": "online", "avatar": "🎨", "last_seen": "Сейчас"},
14
+ "TeamLeader": {"status": "online", "avatar": "👑", "last_seen": "Сейчас"},
15
+ "NinjaWarrior": {"status": "offline", "avatar": "🥷", "last_seen": "2 часа назад"},
16
+ "MysteryPlayer": {"status": "away", "avatar": "🎭", "last_seen": "15 мин назад"}
17
+ }
18
+
19
+ # История чатов
20
+ chat_history = {
21
+ "AlexGamer": [
22
+ {"role": "user", "content": "Привет! Как игра?", "time": "14:30"},
23
+ {"role": "friend", "content": "Привет! Отлично, новый рекорд поставил!", "time": "14:31"},
24
+ {"role": "user", "content": "Круто! В какую играл?", "time": "14:32"},
25
+ {"role": "friend", "content": "Tower of Hell, дошел до 15 уровня", "time": "14:33"}
26
+ ],
27
+ "ProPlayer": [
28
+ {"role": "friend", "content": "Готов к турниру сегодня?", "time": "13:45"},
29
+ {"role": "user", "content": "Да, жду не дождусь!", "time": "13:50"},
30
+ {"role": "friend", "content": "Встречаемся в 7 по серверу", "time": "13:52"}
31
+ ],
32
+ "BuilderMaster": [
33
+ {"role": "friend", "content": "Посмотри мой новый мир!", "time": "12:00"},
34
+ {"role": "user", "content": "Вау, это потрясающе!", "time": "12:15"}
35
+ ]
36
+ }
37
+
38
+ def get_status_color(status: str) -> str:
39
+ colors = {
40
+ "online": "#00ff00",
41
+ "away": "#ffaa00",
42
+ "offline": "#666666"
43
+ }
44
+ return colors.get(status, "#666666")
45
+
46
+ def format_chat_history(history: List[Dict]) -> List[Tuple[str, str]]:
47
+ formatted = []
48
+ for msg in history:
49
+ if msg["role"] == "user":
50
+ formatted.append((msg["content"], None))
51
+ else:
52
+ formatted.append((None, msg["content"]))
53
+ return formatted
54
+
55
+ def send_message(message: str, current_friend: str, history: List[Tuple[str, str]]) -> Tuple[List[Tuple[str, str]], str]:
56
+ if not message.strip():
57
+ return history, ""
58
+
59
+ current_time = datetime.now().strftime("%H:%M")
60
+
61
+ # Добавляем сообщение в историю
62
+ if current_friend not in chat_history:
63
+ chat_history[current_friend] = []
64
+
65
+ chat_history[current_friend].append({
66
+ "role": "user",
67
+ "content": message,
68
+ "time": current_time
69
+ })
70
+
71
+ # Форматируем для отображения
72
+ new_history = format_chat_history(chat_history[current_friend])
73
+
74
+ # Симулируем ответ друга
75
+ time.sleep(1)
76
+ responses = [
77
+ "Отлично! 👍",
78
+ "Понял, согласен!",
79
+ "Круто, давай так!",
80
+ "😄 Отличная идея!",
81
+ "Обязательно попробую!",
82
+ "Спасибо за информацию!",
83
+ "Погнали! 🚀",
84
+ "Это просто эпик!"
85
+ ]
86
+
87
+ bot_response = random.choice(responses)
88
+ chat_history[current_friend].append({
89
+ "role": "friend",
90
+ "content": bot_response,
91
+ "time": current_time
92
+ })
93
+
94
+ final_history = format_chat_history(chat_history[current_friend])
95
+ return final_history, ""
96
+
97
+ def select_friend(friend_name: str) -> Tuple[List[Tuple[str, str]], str]:
98
+ if friend_name in chat_history:
99
+ return format_chat_history(chat_history[friend_name]), f"Чат с {friend_name}"
100
+ return [], f"Начните чат с {friend_name}"
101
+
102
+ def get_friends_list() -> List[Dict]:
103
+ friends_list = []
104
+ for name, info in friends_data.items():
105
+ status_color = get_status_color(info["status"])
106
+ friends_list.append({
107
+ "name": name,
108
+ "status": info["status"],
109
+ "avatar": info["avatar"],
110
+ "last_seen": info["last_seen"],
111
+ "status_color": status_color
112
+ })
113
+ return friends_list
114
+
115
+ def create_friends_html() -> str:
116
+ friends_html = ""
117
+ for name, info in friends_data.items():
118
+ status_color = get_status_color(info["status"])
119
+ status_icon = "🟢" if info["status"] == "online" else "🟡" if info["status"] == "away" else "🔴"
120
+
121
+ friends_html += f"""
122
+ <div class="friend-item" onclick="selectFriend('{name}')" style="cursor: pointer; padding: 12px; margin: 5px 0; border-radius: 10px; background: rgba(255, 255, 255, 0.05); transition: all 0.3s ease;">
123
+ <div style="display: flex; align-items: center; gap: 10px;">
124
+ <span style="font-size: 24px;">{info['avatar']}</span>
125
+ <div style="flex: 1;">
126
+ <div style="display: flex; align-items: center; gap: 5px;">
127
+ <span style="color: white; font-weight: bold;">{name}</span>
128
+ <span style="color: {status_color}; font-size: 12px;">{status_icon}</span>
129
+ </div>
130
+ <div style="color: #888; font-size: 12px;">{info['last_seen']}</div>
131
+ </div>
132
+ </div>
133
+ </div>
134
+ """
135
+ return friends_html
136
+
137
+ # CSS для стилизации в стиле Roblox Aero
138
+ custom_css = """
139
+ /* Основные стили в стиле Roblox Aero */
140
+ .gradio-container {
141
+ background: linear-gradient(135deg, #0a0a0a 0%, #1a1a1a 100%);
142
+ color: #ffffff;
143
+ font-family: 'Kalam', cursive;
144
+ min-height: 100vh;
145
+ }
146
+
147
+ /* Glass эффект для компонентов */
148
+ .glass-effect {
149
+ background: rgba(20, 20, 20, 0.7) !important;
150
+ backdrop-filter: blur(10px);
151
+ -webkit-backdrop-filter: blur(10px);
152
+ border: 1px solid rgba(255, 255, 255, 0.1) !important;
153
+ box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.1);
154
+ }
155
+
156
+ /* Стили для чата */
157
+ .message-user {
158
+ background: linear-gradient(135deg, #ffd700, #ffed4e) !important;
159
+ color: #000000 !important;
160
+ border-radius: 18px 18px 4px 18px !important;
161
+ margin-left: auto !important;
162
+ font-weight: bold;
163
+ }
164
+
165
+ .message-friend {
166
+ background: rgba(255, 255, 255, 0.1) !important;
167
+ color: #ffffff !important;
168
+ border-radius: 18px 18px 18px 4px !important;
169
+ border: 1px solid rgba(255, 215, 0, 0.3);
170
+ }
171
+
172
+ /* Стили для кнопок */
173
+ .btn-primary {
174
+ background: linear-gradient(135deg, #ffd700, #ffed4e) !important;
175
+ color: #000000 !important;
176
+ border: none !important;
177
+ border-radius: 20px !important;
178
+ font-weight: bold !important;
179
+ transition: all 0.3s ease !important;
180
+ }
181
+
182
+ .btn-primary:hover {
183
+ transform: translateY(-2px) !important;
184
+ box-shadow: 0 6px 30px rgba(255, 215, 0, 0.5) !important;
185
+ }
186
+
187
+ /* Стили для друзей */
188
+ .friend-item:hover {
189
+ background: rgba(255, 215, 0, 0.1) !important;
190
+ border: 1px solid rgba(255, 215, 0, 0.3) !important;
191
+ transform: translateX(5px);
192
+ }
193
+
194
+ /* Заголовки */
195
+ .chat-header {
196
+ background: rgba(20, 20, 20, 0.9) !important;
197
+ border-bottom: 2px solid #ffd700 !important;
198
+ color: #ffd700 !important;
199
+ font-weight: bold !important;
200
+ }
201
+
202
+ /* Анимации */
203
+ @keyframes glow {
204
+ from { filter: drop-shadow(0 0 20px rgba(255, 215, 0, 0.5)); }
205
+ to { filter: drop-shadow(0 0 30px rgba(255, 215, 0, 0.8)); }
206
+ }
207
+
208
+ .glow-text {
209
+ animation: glow 2s ease-in-out infinite alternate;
210
+ }
211
+
212
+ /* Поле ввода */
213
+ .input-message {
214
+ background: rgba(255, 255, 255, 0.1) !important;
215
+ border: 1px solid rgba(255, 215, 0, 0.3) !important;
216
+ border-radius: 20px !important;
217
+ color: #ffffff !important;
218
+ }
219
+
220
+ .input-message::placeholder {
221
+ color: rgba(255, 255, 255, 0.5) !important;
222
+ }
223
+
224
+ /* Табы */
225
+ .tab-nav {
226
+ background: rgba(20, 20, 20, 0.8) !important;
227
+ border-bottom: 1px solid rgba(255, 215, 0, 0.3) !important;
228
+ }
229
+
230
+ .tab-nav button {
231
+ color: #ffffff !important;
232
+ border: none !important;
233
+ background: transparent !important;
234
+ }
235
+
236
+ .tab-nav button.selected {
237
+ color: #ffd700 !important;
238
+ border-bottom: 2px solid #ffd700 !important;
239
+ }
240
+ """
241
+
242
+ # JavaScript для интерактивности
243
+ custom_js = """
244
+ function selectFriend(friendName) {
245
+ // Находим и кликаем на соответствующего друга в интерфейсе
246
+ const friendButtons = document.querySelectorAll('[data-testid="radio"]');
247
+ friendButtons.forEach(btn => {
248
+ if(btn.textContent.includes(friendName)) {
249
+ btn.click();
250
+ }
251
+ });
252
+ }
253
+
254
+ // Добавляем анимацию для новых сообщений
255
+ const observer = new MutationObserver((mutations) => {
256
+ mutations.forEach((mutation) => {
257
+ if (mutation.type === 'childList') {
258
+ const newMessages = mutation.addedNodes;
259
+ newMessages.forEach(node => {
260
+ if(node.classList && node.classList.contains('message-user')) {
261
+ node.style.animation = 'slideInRight 0.3s ease';
262
+ } else if(node.classList && node.classList.contains('message-friend')) {
263
+ node.style.animation = 'slideInLeft 0.3s ease';
264
+ }
265
+ });
266
+ }
267
+ });
268
+ });
269
+
270
+ // Наблюдаем за изменениями в чате
271
+ const chatContainer = document.querySelector('[data-testid="chatbot"]');
272
+ if(chatContainer) {
273
+ observer.observe(chatContainer, { childList: true, subtree: true });
274
+ }
275
+
276
+ // Добавляем CSS анимации
277
+ const style = document.createElement('style');
278
+ style.textContent = `
279
+ @keyframes slideInRight {
280
+ from { transform: translateX(100%); opacity: 0; }
281
+ to { transform: translateX(0); opacity: 1; }
282
+ }
283
+ @keyframes slideInLeft {
284
+ from { transform: translateX(-100%); opacity: 0; }
285
+ to { transform: translateX(0); opacity: 1; }
286
+ }
287
+ `;
288
+ document.head.appendChild(style);
289
+ """
290
+
291
+ with gr.Blocks() as demo:
292
+ gr.HTML("""
293
+ <style>
294
+ @import url('https://fonts.googleapis.com/css2?family=Kalam:wght@300;400;700&family=Caveat:wght@400;700&display=swap');
295
+ </style>
296
+ """)
297
+
298
+ gr.HTML("""
299
+ <div style="text-align: center; padding: 20px; background: linear-gradient(135deg, rgba(20,20,20,0.9), rgba(10,10,10,0.9));
300
+ border-bottom: 2px solid #ffd700; margin-bottom: 20px; border-radius: 15px;">
301
+ <h1 style="color: #ffd700; font-family: 'Caveat', cursive; font-size: 48px; margin: 0; text-shadow: 0 0 20px rgba(255, 215, 0, 0.5);">
302
+ 💬 Чат с друзьями
303
+ </h1>
304
+ <p style="color: #b0b0b0; font-family: 'Kalam', cursive; margin: 10px 0 0 0;">
305
+ Общайся с друзьями в реальном времени
306
+ </p>
307
+ <p style="margin-top: 10px;">
308
+ <a href="https://huggingface.co/spaces/akhaliq/anycoder"
309
+ style="color: #ffd700; text-decoration: none; font-size: 14px;">
310
+ Built with anycoder
311
+ </a>
312
+ </p>
313
+ </div>
314
+ """)
315
+
316
+ with gr.Row(equal_height=True):
317
+ # Список друзей
318
+ with gr.Column(scale=1):
319
+ gr.HTML('<h3 style="color: #ffd700; margin-bottom: 15px;">👥 Друзья</h3>')
320
+ with gr.Group(elem_classes=["glass-effect"]):
321
+ friends_html = gr.HTML(create_friends_html())
322
+
323
+ # Статистика
324
+ gr.HTML(f"""
325
+ <div style="margin-top: 20px; padding: 15px; background: rgba(255,215,0,0.1); border-radius: 10px;">
326
+ <div style="color: #ffd700; font-weight: bold; margin-bottom: 10px;">📊 Статистика</div>
327
+ <div style="color: #ffffff; font-size: 14px;">
328
+ <div>🟢 Онлайн: {sum(1 for f in friends_data.values() if f['status'] == 'online')}</div>
329
+ <div>🟡 Отошли: {sum(1 for f in friends_data.values() if f['status'] == 'away')}</div>
330
+ <div>🔴 Офлайн: {sum(1 for f in friends_data.values() if f['status'] == 'offline')}</div>
331
+ <div>📝 Всего друзей: {len(friends_data)}</div>
332
+ </div>
333
+ </div>
334
+ """)
335
+
336
+ # Основная область чата
337
+ with gr.Column(scale=2):
338
+ with gr.Row():
339
+ # Выбор друга
340
+ friend_choice = gr.Radio(
341
+ choices=list(friends_data.keys()),
342
+ value="AlexGamer",
343
+ label="Выберите друга для чата",
344
+ elem_classes=["glass-effect"],
345
+ interactive=True
346
+ )
347
+
348
+ # История чата
349
+ chatbot = gr.Chatbot(
350
+ value=format_chat_history(chat_history.get("AlexGamer", [])),
351
+ height=400,
352
+ show_copy_button=True,
353
+ bubble_full_width=False,
354
+ elem_classes=["glass-effect"],
355
+ avatar_images=(None, None)
356
+ )
357
+
358
+ # Поле ввода сообщения
359
+ with gr.Row():
360
+ msg_input = gr.Textbox(
361
+ placeholder="Введите сообщение...",
362
+ label="Сообщение",
363
+ elem_classes=["input-message"],
364
+ scale=4,
365
+ container=False
366
+ )
367
+ send_btn = gr.Button(
368
+ "➤",
369
+ elem_classes=["btn-primary"],
370
+ scale=1,
371
+ size="lg"
372
+ )
373
+
374
+ # Кнопки действий
375
+ with gr.Row():
376
+ emoji_btn = gr.Button("😊 Эмодзи", elem_classes=["btn-primary"], scale=1)
377
+ voice_btn = gr.Button("🎤 Голос", elem_classes=["btn-primary"], scale=1)
378
+ photo_btn = gr.Button("📷 Фото", elem_classes=["btn-primary"], scale=1)
379
+ clear_btn = gr.Button("🗑️ Очистить", elem_classes=["btn-primary"], scale=1)
380
+
381
+ # Обработчики событий
382
+ def handle_friend_change(friend_name):
383
+ return format_chat_history(chat_history.get(friend_name, []))
384
+
385
+ friend_choice.change(
386
+ handle_friend_change,
387
+ inputs=[friend_choice],
388
+ outputs=[chatbot]
389
+ )
390
+
391
+ def handle_send(message, friend, history):
392
+ if message.strip():
393
+ return send_message(message, friend, history)
394
+ return history, ""
395
+
396
+ send_btn.click(
397
+ handle_send,
398
+ inputs=[msg_input, friend_choice, chatbot],
399
+ outputs=[chatbot, msg_input]
400
+ )
401
+
402
+ msg_input.submit(
403
+ handle_send,
404
+ inputs=[msg_input, friend_choice, chatbot],
405
+ outputs=[chatbot, msg_input]
406
+ )
407
+
408
+ # Обработка кнопок эмодзи
409
+ def add_emoji(emoji_type):
410
+ emojis = {
411
+ "😊": "😊 😂 🤣 😍 😎 🤔 🤗 😴 🥳 🎉",
412
+ "🎮": "🎮 🎯 🎪 🎨 🎭 🎪 🎯 🎲",
413
+ "❤️": "❤️ 💛 💚 💙 💜 🖤 💔"
414
+ }
415
+ return emojis.get(emoji_type, "😊")
416
+
417
+ emoji_btn.click(
418
+ lambda: gr.Info("Выберите эмодзи: 😊 😂 🤣 😍 😎 🤔 🤗 😴 🥳 🎉"),
419
+ inputs=[],
420
+ outputs=[]
421
+ )
422
+
423
+ voice_btn.click(
424
+ lambda: gr.Info("🎤 Голосовые сообщения в разработке"),
425
+ inputs=[],
426
+ outputs=[]
427
+ )
428
+
429
+ photo_btn.click(
430
+ lambda: gr.Info("📷 Загрузка изображений в разработке"),
431
+ inputs=[],
432
+ outputs=[]
433
+ )
434
+
435
+ clear_btn.click(
436
+ lambda: ([], ""),
437
+ outputs=[chatbot, msg_input]
438
+ )
439
+
440
+ demo.launch(
441
+ theme=gr.themes.Soft(
442
+ primary_hue="yellow",
443
+ secondary_hue="orange",
444
+ neutral_hue="slate",
445
+ font=gr.themes.GoogleFont("Kalam"),
446
+ text_size="lg",
447
+ spacing_size="lg",
448
+ radius_size="md"
449
+ ).set(
450
+ body_background_fill="*primary_950",
451
+ block_background_fill="*neutral_950",
452
+ block_border_width="1px",
453
+ block_border_color="*neutral_800",
454
+ block_radius="15px",
455
+ button_primary_background_fill="linear-gradient(135deg, *primary_600, *primary_400)",
456
+ button_primary_background_fill_hover="linear-gradient(135deg, *primary_500, *primary_300)",
457
+ button_primary_text_color="*neutral_950",
458
+ chatbot_background_fill="*neutral_950",
459
+ chatbot_message_user_background_fill="linear-gradient(135deg, *primary_600, *primary_400)",
460
+ chatbot_message_user_text_color="*neutral_950",
461
+ chatbot_message_assistant_background_fill="*neutral_800",
462
+ chatbot_message_assistant_text_color="*neutral_100"
463
+ ),
464
+ css=custom_css,
465
+ js=custom_js,
466
+ footer_links=[
467
+ {"label": "Built with anycoder", "url": "https://huggingface.co/spaces/akhaliq/anycoder"}
468
+ ]
469
+ )