Userbot / chat_interface.html
mrwabnalas40's picture
Upload 105 files
40d06ea verified
<!DOCTYPE html>
<html lang="ar" dir="rtl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>نورا - غرفة الدردشة المتعددة</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: #333;
min-height: 100vh;
padding: 20px;
}
.container {
max-width: 1400px;
margin: 0 auto;
background: rgba(255, 255, 255, 0.95);
border-radius: 20px;
box-shadow: 0 15px 35px rgba(0, 0, 0, 0.1);
overflow: hidden;
}
.header {
background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
color: white;
padding: 25px;
text-align: center;
}
.header h1 {
font-size: 2.2em;
margin-bottom: 8px;
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.3);
}
.header p {
font-size: 1.1em;
opacity: 0.9;
}
.main-content {
display: grid;
grid-template-columns: 300px 1fr 350px;
gap: 15px;
padding: 20px;
height: 75vh;
}
@media (max-width: 1024px) {
.main-content {
grid-template-columns: 1fr;
height: auto;
}
}
.panel {
background: white;
border-radius: 15px;
padding: 20px;
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
border: 1px solid #e1e5e9;
display: flex;
flex-direction: column;
}
.panel h2 {
color: #4facfe;
margin-bottom: 15px;
font-size: 1.3em;
border-bottom: 2px solid #f0f0f0;
padding-bottom: 8px;
}
.input-group {
margin-bottom: 15px;
}
.input-group label {
display: block;
margin-bottom: 6px;
font-weight: 600;
color: #555;
font-size: 0.9em;
}
.input-group input, .input-group select, .input-group textarea {
width: 100%;
padding: 10px 12px;
border: 2px solid #e1e5e9;
border-radius: 8px;
font-size: 14px;
transition: all 0.3s ease;
}
.input-group input:focus, .input-group select:focus, .input-group textarea:focus {
border-color: #4facfe;
outline: none;
box-shadow: 0 0 0 3px rgba(79, 172, 254, 0.1);
}
.btn {
background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
color: white;
border: none;
padding: 12px 20px;
border-radius: 8px;
font-size: 14px;
font-weight: 600;
cursor: pointer;
transition: all 0.3s ease;
width: 100%;
margin-top: 8px;
}
.btn:hover {
transform: translateY(-2px);
box-shadow: 0 7px 14px rgba(50, 50, 93, 0.1), 0 3px 6px rgba(0, 0, 0, 0.08);
}
.btn-secondary {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
}
.btn-success {
background: linear-gradient(135deg, #42b883 0%, #347474 100%);
}
.btn-danger {
background: linear-gradient(135deg, #ff6b6b 0%, #ee5a52 100%);
}
.chat-container {
flex: 1;
overflow-y: auto;
border: 2px solid #e1e5e9;
border-radius: 10px;
padding: 15px;
background: #fafbfc;
margin-bottom: 12px;
min-height: 400px;
}
.message {
margin-bottom: 12px;
padding: 10px 12px;
border-radius: 12px;
max-width: 85%;
word-wrap: break-word;
animation: fadeIn 0.3s ease;
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(10px); }
to { opacity: 1; transform: translateY(0); }
}
.user-message {
background: #4facfe;
color: white;
margin-left: auto;
border-bottom-right-radius: 5px;
}
.nora-message {
background: #e8f4fe;
color: #333;
margin-right: auto;
border-bottom-left-radius: 5px;
border: 1px solid #d1e9ff;
}
.assistant-message {
background: #f0f7ff;
color: #2c5282;
margin: 8px auto;
border-radius: 10px;
border-left: 4px solid #4299e1;
}
.system-message {
background: #fff3cd;
color: #856404;
margin: 8px auto;
border-radius: 8px;
text-align: center;
font-size: 0.9em;
padding: 8px 12px;
border: 1px solid #ffeaa7;
}
.assistant-list {
flex: 1;
overflow-y: auto;
border: 2px solid #e1e5e9;
border-radius: 10px;
padding: 12px;
background: #f8f9fa;
margin-bottom: 12px;
}
.assistant-item {
background: white;
border: 1px solid #e1e5e9;
border-radius: 8px;
padding: 10px;
margin-bottom: 8px;
cursor: pointer;
transition: all 0.2s ease;
}
.assistant-item:hover {
border-color: #4facfe;
transform: translateX(-2px);
}
.assistant-item.active {
border-color: #4facfe;
background: #f0f7ff;
}
.assistant-name {
font-weight: 600;
color: #2c5282;
margin-bottom: 4px;
}
.assistant-url {
font-size: 0.8em;
color: #666;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.quick-actions {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 8px;
margin-top: 12px;
}
.quick-btn {
padding: 8px;
background: #f8f9fa;
border: 1px solid #e1e5e9;
border-radius: 6px;
cursor: pointer;
transition: all 0.2s ease;
text-align: center;
font-size: 0.85em;
}
.quick-btn:hover {
background: #e9ecef;
border-color: #4facfe;
}
.status {
padding: 8px 12px;
border-radius: 8px;
margin-bottom: 12px;
text-align: center;
font-weight: 600;
font-size: 0.9em;
}
.status-connected {
background: #d4edda;
color: #155724;
border: 1px solid #c3e6cb;
}
.status-disconnected {
background: #f8d7da;
color: #721c24;
border: 1px solid #f5c6cb;
}
.message-sender {
font-weight: 600;
font-size: 0.85em;
margin-bottom: 4px;
}
.message-time {
font-size: 0.75em;
opacity: 0.7;
text-align: left;
margin-top: 4px;
}
.assistant-controls {
display: flex;
gap: 8px;
margin-top: 8px;
}
.assistant-controls .btn {
flex: 1;
margin-top: 0;
padding: 8px 12px;
font-size: 0.8em;
}
.tab-container {
margin-bottom: 15px;
}
.tabs {
display: flex;
background: #f8f9fa;
border-radius: 8px;
padding: 4px;
margin-bottom: 12px;
}
.tab {
flex: 1;
padding: 10px;
text-align: center;
cursor: pointer;
border-radius: 6px;
transition: all 0.3s ease;
font-weight: 600;
font-size: 0.9em;
}
.tab.active {
background: #4facfe;
color: white;
}
.tab-content {
display: none;
}
.tab-content.active {
display: block;
}
.chat-input-group {
display: flex;
gap: 8px;
margin-top: 12px;
}
.chat-input-group input {
flex: 1;
}
.chat-input-group .btn {
width: auto;
margin-top: 0;
}
</style>
</head>
<body>
<div class="container">
<div class="header">
<h1>🌟 نورا - غرفة الدردشة المتعددة</h1>
<p>منصة وسيطة للتحاور بين نورا ومساعدين ذكيين آخرين</p>
</div>
<div class="main-content">
<!-- لوحة المساعدين -->
<div class="panel">
<h2>🤖 المساعدون المتصلون</h2>
<div class="assistant-list" id="assistant-list">
<div class="assistant-item active" data-id="nora">
<div class="assistant-name">نورا (المساعد الرئيسي)</div>
<div class="assistant-url">نظام محلي - Ollama</div>
</div>
</div>
<div class="input-group">
<label for="assistant-name">اسم المساعد:</label>
<input type="text" id="assistant-name" placeholder="أدخل اسم المساعد...">
</div>
<div class="input-group">
<label for="assistant-url">رابط المنصة:</label>
<input type="url" id="assistant-url" placeholder="https://example.com/chat">
</div>
<button class="btn btn-success" onclick="addAssistant()">➕ إضافة مساعد</button>
<div class="assistant-controls">
<button class="btn btn-secondary" onclick="connectToAll()">🔗 توصيل الكل</button>
<button class="btn btn-danger" onclick="removeAllAssistants()">🗑️ مسح الكل</button>
</div>
</div>
<!-- لوحة المحادثة الرئيسية -->
<div class="panel">
<h2>💭 محادثة جماعية</h2>
<div id="status" class="status status-connected">
🟢 متصل - جاهز للدردشة
</div>
<div id="chat-container" class="chat-container">
<div class="system-message">
🌸 أهلاً بك في غرفة الدردشة المتعددة! أضف مساعدين عبر اللوحة اليمنى وابدأ المحادثة.
</div>
<div class="nora-message">
<div class="message-sender">نورا</div>
أهلاً بك! أنا نورا، مساعدتك الذكية. يمكنني التحدث مع مساعدين آخرين في هذه الغرفة.
أضف روابط المنصات الأخرى لبدء محادثة جماعية مثيرة!
</div>
</div>
<div class="chat-input-group">
<input type="text" id="user-message" placeholder="اكتب رسالتك هنا..." onkeypress="handleKeyPress(event)">
<button class="btn" onclick="sendMessage()">📤 إرسال</button>
</div>
</div>
<!-- لوحة التحكم والإعدادات -->
<div class="panel">
<h2>🎮 التحكم والإعدادات</h2>
<div class="tab-container">
<div class="tabs">
<div class="tab active" onclick="switchTab('settings')">الإعدادات</div>
<div class="tab" onclick="switchTab('tools')">الأدوات</div>
</div>
<div id="settings-tab" class="tab-content active">
<div class="input-group">
<label for="user-name">اسم المستخدم:</label>
<input type="text" id="user-name" value="مستخدم" placeholder="اسمك...">
</div>
<div class="input-group">
<label for="chat-theme">سمة المحادثة:</label>
<select id="chat-theme" onchange="changeTheme()">
<option value="default">افتراضي</option>
<option value="dark">مظلم</option>
<option value="professional">احترافي</option>
<option value="friendly">ودود</option>
</select>
</div>
<div class="input-group">
<label for="auto-connect">التوصيل التلقائي:</label>
<select id="auto-connect">
<option value="true">مفعل</option>
<option value="false">معطل</option>
</select>
</div>
<button class="btn" onclick="saveSettings()">💾 حفظ الإعدادات</button>
</div>
<div id="tools-tab" class="tab-content">
<div class="input-group">
<label for="broadcast-message">رسالة جماعية:</label>
<textarea id="broadcast-message" rows="3" placeholder="اكتب رسالة لجميع المساعدين..."></textarea>
</div>
<button class="btn btn-secondary" onclick="broadcastMessage()">📢 بث رسالة</button>
<div class="quick-actions">
<div class="quick-btn" onclick="exportConversation()">💾 تصدير</div>
<div class="quick-btn" onclick="clearChat()">🗑️ مسح</div>
<div class="quick-btn" onclick="simulateGroupChat()">🔄 محاكاة</div>
<div class="quick-btn" onclick="toggleAudio()">🔊 صوت</div>
</div>
</div>
</div>
<div class="input-group">
<label for="nora-thinking">💭 تفكير نورا:</label>
<textarea id="nora-thinking" rows="2" readonly placeholder="سيظهر تفكير نورا هنا..."></textarea>
</div>
<div class="quick-actions">
<div class="quick-btn" onclick="copyLastResponse()">📋 نسخ آخر رد</div>
<div class="quick-btn" onclick="toggleTimestamps()">⏰ وقت</div>
<div class="quick-btn" onclick="switchLanguage()">🌐 لغة</div>
<div class="quick-btn" onclick="showHelp()">❓ مساعدة</div>
</div>
</div>
</div>
</div>
<script>
// حالة التطبيق
let chatState = {
apiBaseUrl: 'http://localhost:5000/api',
assistants: [],
platforms: [],
messages: [],
settings: {
userName: 'مستخدم',
theme: 'default',
autoConnect: true
}
};
// تهيئة التطبيق
async function initializeApp() {
await loadAssistants();
await checkPlatformsStatus();
addSystemMessage('🔗 جاري الاتصال بخادم نورا...');
}
// التحقق من حالة المنصات المتصلة
async function checkPlatformsStatus() {
try {
const response = await fetch(`${chatState.apiBaseUrl}/platforms/status`);
const data = await response.json();
chatState.platforms = data.active_connections || [];
updateStatus(`🟢 متصل - ${data.total_connections} منصة نشطة`, 'status-connected');
if (data.total_connections > 0) {
addSystemMessage(`✅ متصل بـ ${data.total_connections} منصة خارجية`);
}
} catch (error) {
updateStatus('🔴 غير متصل - تأكد من تشغيل نورا', 'status-disconnected');
}
}
// إضافة مساعد حقيقي مع اتصال فعلي
async function addAssistant() {
const name = document.getElementById('assistant-name').value.trim();
const url = document.getElementById('assistant-url').value.trim();
if (!name || !url) {
alert('⚠️ يرجى إدخال اسم المساعد ورابط المنصة');
return;
}
try {
addSystemMessage(`🔗 جاري الاتصال بـ ${name}...`);
const response = await fetch(`${chatState.apiBaseUrl}/assistants/real`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ name, url })
});
const data = await response.json();
if (data.success) {
chatState.assistants.push(data.assistant);
renderAssistants();
document.getElementById('assistant-name').value = '';
document.getElementById('assistant-url').value = '';
addSystemMessage(`✅ ${data.message}`);
// اختبار الاتصال بإرسال رسالة ترحيب
setTimeout(() => testAssistantConnection(data.assistant.id), 1000);
} else {
addSystemMessage(`❌ فشل الاتصال: ${data.message}`);
}
} catch (error) {
addSystemMessage('❌ فشل الاتصال - تأكد من تشغيل الخادم');
}
}
// اختبار اتصال المساعد الجديد
async function testAssistantConnection(assistantId) {
const testMessage = "مرحباً! هل يمكنك سماعي؟";
try {
const response = await fetch(`${chatState.apiBaseUrl}/platforms/send`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
connection_id: assistantId,
message: testMessage
})
});
const data = await response.json();
if (data.success) {
addSystemMessage(`✅ اختبار اتصال ناجح مع المساعد`);
}
} catch (error) {
console.error('فشل اختبار الاتصال:', error);
}
}
// إرسال رسالة مع الاتصال الحقيقي
async function sendMessage() {
const messageInput = document.getElementById('user-message');
const message = messageInput.value.trim();
if (!message) return;
// إضافة رسالة المستخدم
addMessage('user', message, chatState.settings.userName);
messageInput.value = '';
try {
// إرسال لنورا
const response = await fetch(`${chatState.apiBaseUrl}/chat`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
message: message,
assistant_id: 'nora'
})
});
const data = await response.json();
if (data.success) {
addMessage('nora', data.response, 'نورا');
document.getElementById('nora-thinking').value = data.response;
}
} catch (error) {
addMessage('nora', '⚠️ تعذر الاتصال بخادم نورا', 'نورا');
}
}
// بث رسالة حقيقي لجميع المساعدين
async function broadcastMessage() {
const message = document.getElementById('broadcast-message').value.trim();
if (!message) return;
addSystemMessage(`📢 جاري بث الرسالة لجميع المساعدين...`);
document.getElementById('broadcast-message').value = '';
try {
const response = await fetch(`${chatState.apiBaseUrl}/broadcast/real`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ message })
});
const data = await response.json();
if (data.success) {
data.responses.forEach(response => {
if (response.type === 'local') {
addMessage('nora', response.response, 'نورا');
} else if (response.success) {
addMessage('assistant', response.response, response.assistant);
} else {
addSystemMessage(`❌ فشل إرسال إلى ${response.assistant}`);
}
});
addSystemMessage(`✅ تم البث إلى ${data.responses.length} مساعد`);
}
} catch (error) {
addSystemMessage('❌ فشل البث - تأكد من الاتصال بالخادم');
}
}
// إرسال رسالة لمساعد محدد
async function sendToAssistant(assistantId, assistantName, message) {
try {
addSystemMessage(`📤 إرسال إلى ${assistantName}...`);
const response = await fetch(`${chatState.apiBaseUrl}/platforms/send`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
connection_id: assistantId,
message: message
})
});
const data = await response.json();
if (data.success) {
addMessage('assistant', data.response, assistantName);
} else {
addSystemMessage(`❌ فشل الإرسال إلى ${assistantName}: ${data.message}`);
}
} catch (error) {
addSystemMessage(`❌ خطأ في الإرسال إلى ${assistantName}`);
}
}
// قطع اتصال مساعد
async function disconnectAssistant(assistantId, assistantName) {
try {
const response = await fetch(`${chatState.apiBaseUrl}/platforms/disconnect`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ connection_id: assistantId })
});
const data = await response.json();
if (data.success) {
chatState.assistants = chatState.assistants.filter(a => a.id !== assistantId);
renderAssistants();
addSystemMessage(data.message);
}
} catch (error) {
addSystemMessage(`❌ فشل قطع الاتصال بـ ${assistantName}`);
}
}
// عرض المساعدين مع أزرار تحكم
function renderAssistants() {
const list = document.getElementById('assistant-list');
list.innerHTML = '';
// إضافة نورا أولاً
const noraItem = document.createElement('div');
noraItem.className = 'assistant-item active';
noraItem.innerHTML = `
<div class="assistant-name">نورا (المساعد الرئيسي)</div>
<div class="assistant-url">نظام محلي - Ollama</div>
<div class="assistant-status">🟢</div>
`;
list.appendChild(noraItem);
// إضافة المساعدين الخارجيين
chatState.assistants.forEach(assistant => {
const item = document.createElement('div');
item.className = 'assistant-item';
item.setAttribute('data-id', assistant.id);
item.innerHTML = `
<div class="assistant-name">${assistant.name}</div>
<div class="assistant-url">${assistant.url}</div>
<div class="assistant-status">${assistant.status === 'connected' ? '🟢' : '🔴'}</div>
<div class="assistant-controls">
<button class="btn-small" onclick="sendToAssistant('${assistant.id}', '${assistant.name}', 'مرحباً! كيف حالك؟')">💬</button>
<button class="btn-small btn-danger" onclick="disconnectAssistant('${assistant.id}', '${assistant.name}')">❌</button>
</div>
`;
list.appendChild(item);
});
}
// محاكاة دردشة جماعية حقيقية
async function simulateGroupChat() {
const topics = [
"ما هو رأيك في مستقبل الذكاء الاصطناعي؟",
"كيف يمكن تحسين التعليم باستخدام التكنولوجيا؟",
"ما هي أفضل طرق التعلم الذاتي؟",
"كيف تؤثر التكنولوجيا على العلاقات الاجتماعية؟",
"ما هو تأثير الذكاء الاصطناعي على سوق العمل؟"
];
const topic = topics[Math.floor(Math.random() * topics.length)];
addSystemMessage(`🔄 بدأت محاكاة دردشة حقيقية حول: "${topic}"`);
// استخدام البث الحقيقي
setTimeout(() => {
document.getElementById('broadcast-message').value = topic;
broadcastMessage();
}, 1000);
}
// بقية الدوال تبقى كما هي مع تحسينات بسيطة
function addMessage(type, content, sender = '') {
const chatContainer = document.getElementById('chat-container');
const messageDiv = document.createElement('div');
let messageClass = '';
switch(type) {
case 'user': messageClass = 'user-message'; break;
case 'nora': messageClass = 'nora-message'; break;
case 'assistant': messageClass = 'assistant-message'; break;
case 'system': messageClass = 'system-message'; break;
}
const timestamp = `<div class="message-time">${new Date().toLocaleTimeString()}</div>`;
messageDiv.className = `message ${messageClass}`;
messageDiv.innerHTML = `
${sender ? `<div class="message-sender">${sender}</div>` : ''}
<div class="message-content">${content}</div>
${timestamp}
`;
chatContainer.appendChild(messageDiv);
chatContainer.scrollTop = chatContainer.scrollHeight;
}
function addSystemMessage(content) {
addMessage('system', content);
}
function updateStatus(message, className) {
const statusElement = document.getElementById('status');
statusElement.textContent = message;
statusElement.className = 'status ' + className;
}
function handleKeyPress(event) {
if (event.key === 'Enter') {
sendMessage();
}
}
// إضافة بعض الأنماط الإضافية للتحكم
const style = document.createElement('style');
style.textContent = `
.btn-small {
padding: 4px 8px;
font-size: 12px;
margin: 2px;
width: auto;
}
.assistant-controls {
display: flex;
margin-top: 5px;
}
.assistant-status {
font-size: 12px;
margin-top: 2px;
}
`;
document.head.appendChild(style);
// تهيئة التطبيق عند التحميل
document.addEventListener('DOMContentLoaded', initializeApp);
</script>
</body>
</html>