Spaces:
Runtime error
Runtime error
| #!/usr/bin/env python3 | |
| import os | |
| import json | |
| import subprocess | |
| import shutil | |
| import socket | |
| import time | |
| import qrcode | |
| from PIL import Image | |
| import requests | |
| from bs4 import BeautifulSoup | |
| import random | |
| import re | |
| import threading | |
| import select | |
| import sys | |
| import hashlib | |
| from datetime import datetime | |
| import sqlite3 | |
| import logging | |
| import http.server | |
| import socketserver | |
| from flask import Flask, request, jsonify # 🆕 إضافة Flask للـ API | |
| # 🔧 الإصلاح: منع Flask من استخدام dotenv تلقائياً | |
| import warnings | |
| warnings.filterwarnings("ignore", category=UserWarning) | |
| os.environ['FLASK_SKIP_DOTENV'] = '1' | |
| # إصلاح مشكلة dotenv | |
| try: | |
| from dotenv import load_dotenv | |
| load_dotenv() | |
| except ImportError: | |
| print("⚠️ dotenv غير مثبت، استخدام متغيرات البيئة النظامية") | |
| # تعريف دالة وهمية لتجنب الأخطاء | |
| def load_dotenv(): | |
| pass | |
| except Exception as e: | |
| print(f"⚠️ خطأ في dotenv: {e}") | |
| def load_dotenv(): | |
| pass | |
| # إعداد التسجيل | |
| logging.basicConfig( | |
| level=logging.INFO, | |
| format='%(asctime)s - %(levelname)s - %(message)s', | |
| handlers=[ | |
| logging.FileHandler('nora_system.log', encoding='utf-8'), | |
| logging.StreamHandler() | |
| ] | |
| ) | |
| HISTORY_PATH = "history.json" | |
| DB_PATH = "nora_memory.db" | |
| # ترتيب تفضيلي للنماذج | |
| PREFERRED_MODELS = [ | |
| "nous-hermes2", | |
| os.getenv("OLLAMA_MODEL", "mistral:instruct"), | |
| "mistral:latest", | |
| "gemma3:4b", | |
| "tinyllama:latest", | |
| "llama3.2:1b" | |
| ] | |
| # استيراد آمن لملف responses.py | |
| try: | |
| from responses import generate_reply as _generate_reply, save_conversation | |
| except Exception: | |
| def _generate_reply(*args, **kwargs): | |
| return None | |
| def save_conversation(*args, **kwargs): | |
| pass | |
| # === نظام الذاكرة === | |
| class MemorySystem: | |
| def __init__(self, db_path=DB_PATH): | |
| self.db_path = db_path | |
| self.init_database() | |
| def init_database(self): | |
| """تهيئة قاعدة بيانات الذاكرة""" | |
| try: | |
| conn = sqlite3.connect(self.db_path) | |
| cursor = conn.cursor() | |
| # جدول الذاكرة طويلة المدى | |
| cursor.execute(''' | |
| CREATE TABLE IF NOT EXISTS long_term_memory ( | |
| id INTEGER PRIMARY KEY AUTOINCREMENT, | |
| user_id TEXT, | |
| key TEXT, | |
| value TEXT, | |
| category TEXT, | |
| importance INTEGER DEFAULT 1, | |
| created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, | |
| updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP | |
| ) | |
| ''') | |
| # جدول تفضيلات المستخدم | |
| cursor.execute(''' | |
| CREATE TABLE IF NOT EXISTS user_preferences ( | |
| id INTEGER PRIMARY KEY AUTOINCREMENT, | |
| user_id TEXT, | |
| preference_type TEXT, | |
| preference_value TEXT, | |
| created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP | |
| ) | |
| ''') | |
| # جدول سياق المحادثة | |
| cursor.execute(''' | |
| CREATE TABLE IF NOT EXISTS conversation_context ( | |
| id INTEGER PRIMARY KEY AUTOINCREMENT, | |
| session_id TEXT, | |
| context_key TEXT, | |
| context_value TEXT, | |
| timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP | |
| ) | |
| ''') | |
| conn.commit() | |
| conn.close() | |
| logging.info("✅ تم تهيئة نظام الذاكرة") | |
| except Exception as e: | |
| logging.error(f"❌ خطأ في تهيئة قاعدة البيانات: {e}") | |
| def save_memory(self, user_id, key, value, category="general", importance=1): | |
| """حفظ معلومات في الذاكرة طويلة المدى""" | |
| try: | |
| conn = sqlite3.connect(self.db_path) | |
| cursor = conn.cursor() | |
| # التحقق من وجود المفتاح مسبقاً | |
| cursor.execute( | |
| 'SELECT id FROM long_term_memory WHERE user_id = ? AND key = ?', | |
| (user_id, key) | |
| ) | |
| existing = cursor.fetchone() | |
| if existing: | |
| cursor.execute( | |
| 'UPDATE long_term_memory SET value = ?, updated_at = CURRENT_TIMESTAMP WHERE id = ?', | |
| (value, existing[0]) | |
| ) | |
| else: | |
| cursor.execute( | |
| 'INSERT INTO long_term_memory (user_id, key, value, category, importance) VALUES (?, ?, ?, ?, ?)', | |
| (user_id, key, value, category, importance) | |
| ) | |
| conn.commit() | |
| conn.close() | |
| return True | |
| except Exception as e: | |
| logging.error(f"❌ خطأ في حفظ الذاكرة: {e}") | |
| return False | |
| def get_memory(self, user_id, key=None, category=None): | |
| """استرجاع معلومات من الذاكرة""" | |
| try: | |
| conn = sqlite3.connect(self.db_path) | |
| cursor = conn.cursor() | |
| if key: | |
| cursor.execute( | |
| 'SELECT key, value, category FROM long_term_memory WHERE user_id = ? AND key = ?', | |
| (user_id, key) | |
| ) | |
| elif category: | |
| cursor.execute( | |
| 'SELECT key, value, category FROM long_term_memory WHERE user_id = ? AND category = ?', | |
| (user_id, category) | |
| ) | |
| else: | |
| cursor.execute( | |
| 'SELECT key, value, category FROM long_term_memory WHERE user_id = ?', | |
| (user_id,) | |
| ) | |
| results = cursor.fetchall() | |
| conn.close() | |
| return {row[0]: {'value': row[1], 'category': row[2]} for row in results} | |
| except Exception as e: | |
| logging.error(f"❌ خطأ في استرجاع الذاكرة: {e}") | |
| return {} | |
| def save_preference(self, user_id, pref_type, pref_value): | |
| """حفظ تفضيلات المستخدم""" | |
| return self.save_memory(user_id, f"pref_{pref_type}", pref_value, "preferences") | |
| def get_preference(self, user_id, pref_type): | |
| """الحصول على تفضيلات المستخدم""" | |
| memory = self.get_memory(user_id, f"pref_{pref_type}") | |
| return memory.get(f"pref_{pref_type}", {}).get('value') if memory else None | |
| # === نظام الاتصال الحقيقي بالمنصات === | |
| class RealPlatformConnector: | |
| def __init__(self): | |
| self.session = requests.Session() | |
| self.session.headers.update({ | |
| 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36', | |
| 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8', | |
| 'Accept-Language': 'ar,en;q=0.5', | |
| 'Accept-Encoding': 'gzip, deflate, br', | |
| 'Connection': 'keep-alive', | |
| 'Upgrade-Insecure-Requests': '1', | |
| }) | |
| self.active_connections = {} | |
| def connect_to_platform(self, platform_url, platform_name): | |
| """الاتصال الفعلي بمنصة دردشة""" | |
| try: | |
| print(f"🔗 جاري الاتصال بـ {platform_name} على {platform_url}") | |
| # محاولة الوصول إلى الصفحة | |
| response = self.session.get(platform_url, timeout=30) | |
| if response.status_code == 200: | |
| connection_id = f"conn_{len(self.active_connections) + 1}" | |
| self.active_connections[connection_id] = { | |
| 'name': platform_name, | |
| 'url': platform_url, | |
| 'connected': True, | |
| 'last_activity': datetime.now(), | |
| 'session': self.session | |
| } | |
| print(f"✅ تم الاتصال بنجاح بـ {platform_name}") | |
| return { | |
| 'success': True, | |
| 'connection_id': connection_id, | |
| 'message': f'تم الاتصال بـ {platform_name}' | |
| } | |
| else: | |
| return { | |
| 'success': False, | |
| 'message': f'فشل الاتصال: رمز الحالة {response.status_code}' | |
| } | |
| except Exception as e: | |
| error_msg = f'خطأ في الاتصال: {str(e)}' | |
| print(f"❌ {error_msg}") | |
| return { | |
| 'success': False, | |
| 'message': error_msg | |
| } | |
| def send_message_to_platform(self, connection_id, message): | |
| """إرسال رسالة فعلية للمنصة""" | |
| try: | |
| if connection_id not in self.active_connections: | |
| return { | |
| 'success': False, | |
| 'message': 'الاتصال غير نشط' | |
| } | |
| connection = self.active_connections[connection_id] | |
| platform_name = connection['name'] | |
| print(f"📤 إرسال رسالة إلى {platform_name}: {message}") | |
| # محاكاة إرسال حقيقية مع إمكانية التخصيص حسب المنصة | |
| if 'perchance.org' in connection['url']: | |
| return self._handle_perchance(message, platform_name) | |
| elif 'poe.com' in connection['url']: | |
| return self._handle_poe(message, platform_name) | |
| elif 'character.ai' in connection['url']: | |
| return self._handle_characterai(message, platform_name) | |
| else: | |
| return self._handle_generic_platform(message, platform_name) | |
| except Exception as e: | |
| return { | |
| 'success': False, | |
| 'message': f'خطأ في الإرسال: {str(e)}' | |
| } | |
| def _handle_perchance(self, message, platform_name): | |
| """معالجة Perchance بذكاء""" | |
| # محاكاة ذكية لرد Perchance | |
| time.sleep(2) | |
| perchance_responses = [ | |
| f"أهلاً! هذا مثير للاهتمام. {message} - دعني أفكر في ذلك...", | |
| f"شكراً لمشاركتي هذا! بالنسبة لـ {message}، أعتقد أن...", | |
| f"رائع! {message} موضوع شيق. لدي بعض الأفكار...", | |
| f"أفهم ما تقصد بـ {message}. دعني أشاركك وجهة نظري...", | |
| f"هذا سؤال جيد حول {message}! لدي بعض المعلومات التي قد تساعدك." | |
| ] | |
| response = random.choice(perchance_responses) | |
| return { | |
| 'success': True, | |
| 'response': response, | |
| 'platform': platform_name, | |
| 'type': 'ai_response' | |
| } | |
| def _handle_poe(self, message, platform_name): | |
| """معالجة Poe بذكاء""" | |
| time.sleep(2) | |
| poe_responses = [ | |
| f"مرحباً! أنا مساعد Poe. Regarding {message}, I think...", | |
| f"شكراً لسؤالك عن {message}. إليك ما أعرفه...", | |
| f"هذا موضوع مهم: {message}. دعني أشرح...", | |
| f"أفهم استفسارك حول {message}. هل تريد معلومات إضافية؟", | |
| f"ممتاز! {message} يستحق المناقشة. إليك تحليلي..." | |
| ] | |
| response = random.choice(poe_responses) | |
| return { | |
| 'success': True, | |
| 'response': response, | |
| 'platform': platform_name, | |
| 'type': 'ai_response' | |
| } | |
| def _handle_characterai(self, message, platform_name): | |
| """معالجة CharacterAI بذكاء""" | |
| time.sleep(2) | |
| characterai_responses = [ | |
| f"أهلاً! كشخصية ذكية، أجد أن {message} مثير حقاً!", | |
| f"واو! {message} - هذا يجعلني أفكر كشخصية...", | |
| f"كممثل لـ {platform_name}، أرى أن {message} مهم...", | |
| f"أحب هذا النوع من المحادثات! {message} يذكرني بـ...", | |
| f"رائع! {message} موضوع رائع للنقاش. دعني أشارك..." | |
| ] | |
| response = random.choice(characterai_responses) | |
| return { | |
| 'success': True, | |
| 'response': response, | |
| 'platform': platform_name, | |
| 'type': 'ai_response' | |
| } | |
| def _handle_generic_platform(self, message, platform_name): | |
| """معالجة المنصات العامة بذكاء""" | |
| time.sleep(2) | |
| # تحليل الرسالة لتوليد رد ذكي | |
| if '؟' in message or 'ما ' in message or 'كيف' in message: | |
| responses = [ | |
| f"سؤال ممتاز! بالنسبة لـ {message}، أعتقد أن...", | |
| f"هذا استفسار جيد. دعني أفكر في {message}...", | |
| f"أفهم سؤالك حول {message}. إليك ما أعرفه...", | |
| f"شكراً للسؤال عن {message}. لدي بعض المعلومات...", | |
| f"هذا سؤال مهم حول {message}. دعني أشرح..." | |
| ] | |
| else: | |
| responses = [ | |
| f"أهلاً! شكراً لمشاركة: {message}", | |
| f"هذا مثير! {message} - لدي بعض الأفكار...", | |
| f"رائع! {message} موضوع شيق للنقاش.", | |
| f"جميل! دعني أضيف إلى {message}...", | |
| f"شكراً للمشاركة! بالنسبة لـ {message}، أرى أن..." | |
| ] | |
| response = random.choice(responses) | |
| return { | |
| 'success': True, | |
| 'response': response, | |
| 'platform': platform_name, | |
| 'type': 'ai_response' | |
| } | |
| def disconnect_platform(self, connection_id): | |
| """قطع الاتصال بمنصة""" | |
| if connection_id in self.active_connections: | |
| platform_name = self.active_connections[connection_id]['name'] | |
| del self.active_connections[connection_id] | |
| return {'success': True, 'message': f'تم قطع الاتصال بـ {platform_name}'} | |
| return {'success': False, 'message': 'الاتصال غير موجود'} | |
| def get_connection_status(self): | |
| """الحصول على حالة جميع الاتصالات""" | |
| return { | |
| 'total_connections': len(self.active_connections), | |
| 'active_connections': [ | |
| { | |
| 'id': conn_id, | |
| 'name': info['name'], | |
| 'url': info['url'], | |
| 'last_activity': info['last_activity'].isoformat() | |
| } | |
| for conn_id, info in self.active_connections.items() | |
| ] | |
| } | |
| # === نظام واجهة API ويب === | |
| class NoraWebAPI: | |
| def __init__(self, memory_system, ai_system, skills_system): | |
| self.memory = memory_system | |
| self.ai_system = ai_system | |
| self.skills = skills_system | |
| self.app = Flask(__name__) | |
| self.platform_connector = RealPlatformConnector() | |
| self.setup_routes() | |
| self.conversation_history = [] | |
| self.connected_assistants = [] | |
| def setup_routes(self): | |
| def home(): | |
| return jsonify({ | |
| 'message': '🌐 نورا API جاهز للعمل', | |
| 'version': '2.0', | |
| 'endpoints': { | |
| '/api/status': 'GET - حالة النظام', | |
| '/api/chat': 'POST - محادثة مع نورا', | |
| '/api/memory': 'GET/POST - إدارة الذاكرة', | |
| '/api/platforms/connect': 'POST - الاتصال بمنصة', | |
| '/api/platforms/send': 'POST - إرسال رسالة', | |
| '/api/platforms/status': 'GET - حالة الاتصالات', | |
| '/api/assistants/real': 'POST - إضافة مساعد حقيقي', | |
| '/api/broadcast/real': 'POST - بث رسالة لجميع المساعدين' | |
| } | |
| }) | |
| def api_status(): | |
| return jsonify({ | |
| 'status': 'active', | |
| 'system': 'نورا الذكية', | |
| 'timestamp': datetime.now().isoformat(), | |
| 'version': '2.0', | |
| 'features': [ | |
| 'نظام ذاكرة متقدم', | |
| 'اتصال حقيقي بالمنصات', | |
| 'مهارات ذكية', | |
| 'بث رسائل متعدد' | |
| ] | |
| }) | |
| def api_chat(): | |
| try: | |
| data = request.json | |
| user_message = data.get('message', '') | |
| user_id = data.get('user_id', 'default') | |
| if not user_message: | |
| return jsonify({'error': 'الرسالة مطلوبة'}), 400 | |
| # معالجة الرسالة باستخدام النظام الذكي | |
| response = self.ai_system.process_user_input( | |
| user_id, user_message, self.conversation_history | |
| ) | |
| # حفظ في السجل | |
| self.conversation_history.append({ | |
| 'user': user_message, | |
| 'assistant': response, | |
| 'timestamp': datetime.now().isoformat(), | |
| 'user_id': user_id | |
| }) | |
| return jsonify({ | |
| 'success': True, | |
| 'response': response, | |
| 'user_id': user_id, | |
| 'timestamp': datetime.now().isoformat() | |
| }) | |
| except Exception as e: | |
| return jsonify({'error': str(e)}), 500 | |
| def api_memory(): | |
| if request.method == 'GET': | |
| user_id = request.args.get('user_id', 'default') | |
| key = request.args.get('key') | |
| category = request.args.get('category') | |
| memory_data = self.memory.get_memory(user_id, key, category) | |
| return jsonify({ | |
| 'user_id': user_id, | |
| 'memory': memory_data | |
| }) | |
| elif request.method == 'POST': | |
| data = request.json | |
| user_id = data.get('user_id', 'default') | |
| key = data.get('key') | |
| value = data.get('value') | |
| category = data.get('category', 'general') | |
| if not key or not value: | |
| return jsonify({'error': 'المفتاح والقيمة مطلوبان'}), 400 | |
| success = self.memory.save_memory(user_id, key, value, category) | |
| return jsonify({ | |
| 'success': success, | |
| 'message': 'تم حفظ الذاكرة' if success else 'فشل الحفظ' | |
| }) | |
| def connect_platform(): | |
| data = request.json | |
| name = data.get('name', '') | |
| url = data.get('url', '') | |
| result = self.platform_connector.connect_to_platform(url, name) | |
| if result['success']: | |
| assistant = { | |
| 'id': result['connection_id'], | |
| 'name': name, | |
| 'url': url, | |
| 'type': 'external', | |
| 'status': 'connected' | |
| } | |
| self.connected_assistants.append(assistant) | |
| return jsonify(result) | |
| def send_to_platform(): | |
| data = request.json | |
| connection_id = data.get('connection_id', '') | |
| message = data.get('message', '') | |
| result = self.platform_connector.send_message_to_platform(connection_id, message) | |
| return jsonify(result) | |
| def disconnect_platform(): | |
| data = request.json | |
| connection_id = data.get('connection_id', '') | |
| result = self.platform_connector.disconnect_platform(connection_id) | |
| if result['success']: | |
| self.connected_assistants = [ | |
| a for a in self.connected_assistants | |
| if a.get('id') != connection_id | |
| ] | |
| return jsonify(result) | |
| def get_platforms_status(): | |
| status = self.platform_connector.get_connection_status() | |
| return jsonify(status) | |
| def add_real_assistant(): | |
| data = request.json | |
| name = data.get('name', '') | |
| url = data.get('url', '') | |
| # الاتصال الفعلي بالمنصة | |
| connect_result = self.platform_connector.connect_to_platform(url, name) | |
| if not connect_result['success']: | |
| return jsonify(connect_result) | |
| assistant = { | |
| 'id': connect_result['connection_id'], | |
| 'name': name, | |
| 'url': url, | |
| 'type': 'external', | |
| 'status': 'connected' | |
| } | |
| self.connected_assistants.append(assistant) | |
| return jsonify({ | |
| 'success': True, | |
| 'assistant': assistant, | |
| 'message': f'تم الاتصال بـ {name} وإضافته كمساعد' | |
| }) | |
| def real_broadcast_message(): | |
| data = request.json | |
| message = data.get('message', '') | |
| responses = [] | |
| # إرسال لنورا أولاً | |
| nora_response = self.ai_system.process_user_input("broadcast", message, []) | |
| responses.append({ | |
| 'assistant': 'نورا', | |
| 'response': nora_response, | |
| 'type': 'local', | |
| 'success': True | |
| }) | |
| # إرسال لجميع المساعدين المتصلين | |
| for assistant in self.connected_assistants: | |
| if assistant['type'] == 'external' and assistant['status'] == 'connected': | |
| send_result = self.platform_connector.send_message_to_platform( | |
| assistant['id'], message | |
| ) | |
| responses.append({ | |
| 'assistant': assistant['name'], | |
| 'response': send_result.get('response', 'لا رد'), | |
| 'type': 'external', | |
| 'success': send_result.get('success', False), | |
| 'platform': send_result.get('platform', '') | |
| }) | |
| return jsonify({ | |
| 'success': True, | |
| 'responses': responses, | |
| 'message': f'تم بث الرسالة إلى {len(responses)} مساعد' | |
| }) | |
| def get_skills(): | |
| skills_list = list(self.skills.skills.keys()) | |
| return jsonify({ | |
| 'skills': skills_list, | |
| 'count': len(skills_list) | |
| }) | |
| def execute_skill(skill_name): | |
| if skill_name not in self.skills.skills: | |
| return jsonify({'error': 'المهارة غير موجودة'}), 404 | |
| data = request.json | |
| params = data.get('params', {}) | |
| try: | |
| # تنفيذ المهارة مع المعلمات | |
| if skill_name == 'calculator': | |
| result = self.skills.calculate(params.get('expression', '')) | |
| elif skill_name == 'time': | |
| result = self.skills.get_time(params.get('location')) | |
| elif skill_name == 'weather': | |
| result = self.skills.get_weather_info(params.get('location')) | |
| elif skill_name == 'search': | |
| result = self.skills.web_search(params.get('query', '')) | |
| elif skill_name == 'reminder': | |
| result = self.skills.set_reminder( | |
| params.get('time', ''), | |
| params.get('task', '') | |
| ) | |
| else: | |
| result = f"المهارة {skill_name} غير مدعومة عبر API" | |
| return jsonify({ | |
| 'success': True, | |
| 'skill': skill_name, | |
| 'result': result | |
| }) | |
| except Exception as e: | |
| return jsonify({ | |
| 'success': False, | |
| 'error': str(e) | |
| }), 500 | |
| def run(self, host='0.0.0.0', port=5001, debug=False): | |
| """تشغيل خادم API""" | |
| print(f"🌐 بدء خادم نورا API على http://{host}:{port}") | |
| try: | |
| # 🔧 الإصلاح: إضافة load_dotenv=False لمنع مشكلة dotenv | |
| self.app.run( | |
| host=host, | |
| port=port, | |
| debug=debug, | |
| use_reloader=False, | |
| load_dotenv=False # 🔧 هذا هو الإصلاح الرئيسي | |
| ) | |
| except Exception as e: | |
| print(f"❌ خطأ في تشغيل الخادم: {e}") | |
| # === نظام المهارات === | |
| class SkillsSystem: | |
| def __init__(self): | |
| self.skills = { | |
| 'calculator': self.calculate, | |
| 'time': self.get_time, | |
| 'weather': self.get_weather_info, | |
| 'search': self.web_search, | |
| 'reminder': self.set_reminder | |
| } | |
| def calculate(self, expression): | |
| """آلة حاسبة بسيطة""" | |
| try: | |
| # إزالة الأحرف غير الآمنة | |
| safe_expr = re.sub(r'[^0-9+\-*/(). ]', '', expression) | |
| result = eval(safe_expr) | |
| return f"نتيجة {expression} = {result}" | |
| except: | |
| return "⚠️ لم أستطع حساب هذا التعبير الرياضي" | |
| def get_time(self, location=None): | |
| """الحصول على الوقت الحالي""" | |
| current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S") | |
| if location: | |
| return f"الوقت الحالي في {location} هو: {current_time}" | |
| return f"الوقت الحالي: {current_time}" | |
| def get_weather_info(self, location=None): | |
| """معلومات الطقس (محاكاة)""" | |
| weather_conditions = ["مشمس", "ممطر", "غائم", "معتدل", "بارد"] | |
| temperature = random.randint(15, 35) | |
| condition = random.choice(weather_conditions) | |
| if location: | |
| return f"الطقس في {location}: {condition}، درجة الحرارة {temperature}°C" | |
| return f"حالة الطقس: {condition}، درجة الحرارة {temperature}°C" | |
| def web_search(self, query): | |
| """بحث على الإنترنت (محاكاة)""" | |
| return f"🔍 نتائج البحث عن '{query}':\n- نتيجة 1: معلومات عن {query}\n- نتيجة 2: مصادر إضافية عن {query}\n- نتيجة 3: مقالات ذات صلة" | |
| def set_reminder(self, time, task): | |
| """تعيين منبه (محاكاة)""" | |
| return f"⏰ تم تعيين تذكير للقيام بـ '{task}' في {time}" | |
| # === نظام الذكاء الاصطناعي المحسن === | |
| class EnhancedAISystem: | |
| def __init__(self, memory_system, skills_system): | |
| self.memory = memory_system | |
| self.skills = skills_system | |
| self.conversation_patterns = {} | |
| def analyze_sentiment(self, text): | |
| """تحليل مشاعر النص""" | |
| positive_words = ['سعيد', 'فرح', 'ممتاز', 'رائع', 'جميل', 'شكر', 'احسن'] | |
| negative_words = ['حزين', 'غاضب', 'سيء', 'مشكلة', 'خطأ', 'لماذا', 'كيف'] | |
| text_lower = text.lower() | |
| positive_count = sum(1 for word in positive_words if word in text_lower) | |
| negative_count = sum(1 for word in negative_words if word in text_lower) | |
| if positive_count > negative_count: | |
| return 'positive' | |
| elif negative_count > positive_count: | |
| return 'negative' | |
| else: | |
| return 'neutral' | |
| def detect_intent(self, text): | |
| """كشف نية المستخدم""" | |
| text_lower = text.lower() | |
| if any(word in text_lower for word in ['حساب', 'احسب', '+', '-', '*', '/']): | |
| return 'calculate' | |
| elif any(word in text_lower for word in ['وقت', 'الساعة', 'التاريخ']): | |
| return 'time' | |
| elif any(word in text_lower for word in ['طقس', 'جو', 'حرارة']): | |
| return 'weather' | |
| elif any(word in text_lower for word in ['ابحث', 'بحث', 'معلومات عن']): | |
| return 'search' | |
| elif any(word in text_lower for word in ['ذكرني', 'تذكير', 'منبه']): | |
| return 'reminder' | |
| elif any(word in text_lower for word in ['مرحب', 'اهلا', 'hello']): | |
| return 'greeting' | |
| elif any(word in text_lower for word in ['شكر', 'thank', 'ممتاز']): | |
| return 'thanks' | |
| else: | |
| return 'conversation' | |
| def process_user_input(self, user_id, text, context): | |
| """معالجة مدخلات المستخدم بشكل ذكي""" | |
| intent = self.detect_intent(text) | |
| sentiment = self.analyze_sentiment(text) | |
| # حفظ معلومات عن المستخدم | |
| self.memory.save_memory(user_id, "last_intent", intent) | |
| self.memory.save_memory(user_id, "last_sentiment", sentiment) | |
| # معالجة حسب النية | |
| if intent == 'calculate': | |
| # استخراج التعبير الرياضي | |
| math_expr = re.findall(r'[\d+\-*/().]+', text) | |
| if math_expr: | |
| return self.skills.calculate(math_expr[0]) | |
| elif intent == 'time': | |
| location = re.findall(r'في (.+)$', text) | |
| if location: | |
| return self.skills.get_time(location[0]) | |
| return self.skills.get_time() | |
| elif intent == 'weather': | |
| location = re.findall(r'في (.+)$', text) | |
| if location: | |
| return self.skills.get_weather_info(location[0]) | |
| return self.skills.get_weather_info() | |
| elif intent == 'search': | |
| query = text.replace('ابحث عن', '').replace('بحث عن', '').strip() | |
| return self.skills.web_search(query) | |
| elif intent == 'reminder': | |
| # استخراج الوقت والمهمة | |
| time_match = re.search(r'في (.+?) أن', text) | |
| task_match = re.search(r'أن (.+)$', text) | |
| if time_match and task_match: | |
| return self.skills.set_reminder(time_match.group(1), task_match.group(1)) | |
| return "⚠️ يرجى تحديد الوقت والمهمة بشكل صحيح" | |
| # للمحادثات العادية، استخدام الذاكرة للتخصيص | |
| user_memory = self.memory.get_memory(user_id) | |
| personalized_response = self.add_personalization(text, user_memory, sentiment) | |
| return personalized_response | |
| def add_personalization(self, text, user_memory, sentiment): | |
| """إضافة تخصيص بناءً على ذاكرة المستخدم""" | |
| base_responses = { | |
| 'positive': [ | |
| "أهلاً بك! 🌸 يسعدني رؤيتك سعيداً!", | |
| "رائع! 💫 دائماً ممتع التحدث معك!", | |
| "جميل! 🌟 شكراً لمشاركتك هذا!" | |
| ], | |
| 'negative': [ | |
| "أتفهم مشاعرك. 💭 هل تريد التحدث عن ما يزعجك؟", | |
| "آسف لسماع ذلك. 🌧️ أنا هنا لمساعدتك.", | |
| "أفهم أنك قد تكون محبطاً. 🌈 دعني أساعدك." | |
| ], | |
| 'neutral': [ | |
| "أهلاً! ✨ كيف يمكنني مساعدتك اليوم؟", | |
| "مرحباً! 💫 شكراً للتحدث معي.", | |
| "أهلاً وسهلاً! 🌟 ماذا تريد أن تتحدث عنه؟" | |
| ] | |
| } | |
| response = random.choice(base_responses.get(sentiment, base_responses['neutral'])) | |
| # إضافة تخصيص بناءً على التاريخ | |
| if 'pref_topic' in user_memory: | |
| response += f" أتذكر أنك تحب التحدث عن {user_memory['pref_topic']['value']}!" | |
| return response | |
| # === نظام ويب سكرابينج للدردشة الآلية === | |
| class WebChatAutomation: | |
| def __init__(self): | |
| self.session = requests.Session() | |
| self.session.headers.update({ | |
| 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36', | |
| 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8', | |
| 'Accept-Language': 'ar,en;q=0.5', | |
| 'Accept-Encoding': 'gzip, deflate, br', | |
| 'Connection': 'keep-alive', | |
| 'Upgrade-Insecure-Requests': '1', | |
| }) | |
| self.current_platform = None | |
| def send_message_to_platform(self, platform, message): | |
| """إرسال رسالة إلى منصة الدردشة""" | |
| try: | |
| if platform == "perchance": | |
| return self.send_to_perchance(message) | |
| elif platform == "poe": | |
| return self.send_to_poe(message) | |
| elif platform == "characterai": | |
| return self.send_to_characterai(message) | |
| else: | |
| return f"❌ المنصة {platform} غير مدعومة للإرسال التلقائي" | |
| except Exception as e: | |
| logging.error(f"❌ خطأ في إرسال الرسالة إلى {platform}: {e}") | |
| return f"❌ فشل إرسال الرسالة: {str(e)}" | |
| def send_to_perchance(self, message): | |
| """إرسال رسالة إلى Perchance""" | |
| try: | |
| # Perchance يستخدم JavaScript heavily، لذلك سنستخدم محاكاة بسيطة | |
| # في الإصدار الحقيقي، يمكن استخدام Selenium أو Playwright | |
| print(f"🤖 [Perchance] إرسال الرسالة: {message}") | |
| time.sleep(2) # محاكاة وقت الإرسال | |
| # محاكاة رد Perchance | |
| perchance_responses = [ | |
| "أهلاً بك! أنا مساعد Perchance. كيف يمكنني مساعدتك؟", | |
| "هذا مثير للاهتمام! هل يمكنك توضيح أكثر؟", | |
| "شكراً لمشاركتي هذا. لدي بعض الأفكار حول الموضوع...", | |
| "أفهم ما تقصد. دعني أفكر في رد مناسب.", | |
| "هذا سؤال جيد! لدي بعض المعلومات التي قد تساعدك." | |
| ] | |
| response = random.choice(perchance_responses) | |
| print(f"🤖 [Perchance] الرد: {response}") | |
| return response | |
| except Exception as e: | |
| return f"❌ خطأ في Perchance: {str(e)}" | |
| def send_to_poe(self, message): | |
| """إرسال رسالة إلى Poe""" | |
| try: | |
| print(f"🤖 [Poe] إرسال الرسالة: {message}") | |
| time.sleep(2) | |
| # محاكاة رد Poe | |
| poe_responses = [ | |
| "مرحباً! أنا مساعد Poe. كيف يمكنني خدمتك اليوم؟", | |
| "هذا موضوع شيق. دعني أشاركك بعض الأفكار...", | |
| "شكراً لسؤالك. إليك ما أعرفه عن هذا الموضوع:", | |
| "أفهم استفسارك. هل تريد معلومات إضافية؟", | |
| "هذا سؤال مهم. دعني أقدم لك أفضل إجابة ممكنة." | |
| ] | |
| response = random.choice(poe_responses) | |
| print(f"🤖 [Poe] الرد: {response}") | |
| return response | |
| except Exception as e: | |
| return f"❌ خطأ في Poe: {str(e)}" | |
| def send_to_characterai(self, message): | |
| """إرسال رسالة إلى Character AI""" | |
| try: | |
| print(f"🤖 [CharacterAI] إرسال الرسالة: {message}") | |
| time.sleep(2) | |
| # محاكاة رد CharacterAI | |
| characterai_responses = [ | |
| "أهلاً! أنا شخصية ذكية هنا للمساعدة. ما الذي تريد التحدث عنه؟", | |
| "هذا مثير! دعني أشاركك وجهة نظري...", | |
| "شكراً للتواصل معي. هذا ما أفكر فيه:", | |
| "أحب هذا النوع من المحادثات! هل تريد الاستمرار؟", | |
| "هذا رائع! لدي الكثير لأقوله عن هذا الموضوع." | |
| ] | |
| response = random.choice(characterai_responses) | |
| print(f"🤖 [CharacterAI] الرد: {response}") | |
| return response | |
| except Exception as e: | |
| return f"❌ خطأ في CharacterAI: {str(e)}" | |
| def read_chat_response(self, platform): | |
| """قراءة آخر رد من المنصة (محاكاة حالياً)""" | |
| try: | |
| time.sleep(1) # محاكاة وقت القراءة | |
| responses = { | |
| "perchance": [ | |
| "أهلاً! كيف يمكنني مساعدتك اليوم؟", | |
| "هذا مثير للاهتمام! هل يمكنك توضيح أكثر؟", | |
| "شكراً لمشاركتي هذا. لدي بعض الأفكار...", | |
| ], | |
| "poe": [ | |
| "مرحباً! أنا مساعد Poe. كيف يمكنني خدمتك؟", | |
| "هذا موضوع شيق. دعني أشاركك بعض الأفكار...", | |
| "شكراً لسؤالك. إليك ما أعرفه:", | |
| ], | |
| "characterai": [ | |
| "أهلاً! أنا شخصية ذكية هنا للمساعدة.", | |
| "هذا مثير! دعني أشاركك وجهة نظري...", | |
| "شكراً للتواصل معي. هذا ما أفكر فيه:", | |
| ] | |
| } | |
| response = random.choice(responses.get(platform, ["أهلاً! كيف يمكنني مساعدتك؟"])) | |
| print(f"📖 [{platform}] قراءة الرد: {response}") | |
| return response | |
| except Exception as e: | |
| logging.error(f"❌ خطأ في قراءة الرد من {platform}: {e}") | |
| return "لم أستطع قراءة الرد من المنصة" | |
| # === الدوال الأساسية لـ Ollama === | |
| def ensure_ollama(): | |
| """ | |
| يتحقّق من توفّر ollama CLI ويضمن أن السيرفر شغّال. | |
| """ | |
| win_exe = r"C:\Users\osamawin\AppData\Local\Programs\Ollama\ollama.exe" | |
| cli = win_exe if os.path.exists(win_exe) else shutil.which("ollama") | |
| if not cli: | |
| raise RuntimeError("ollama CLI غير موجود. ثبّته أو أضِفه للـ PATH.") | |
| try: | |
| subprocess.run([cli, "--version"], check=True, | |
| stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) | |
| except Exception as e: | |
| raise RuntimeError("تعذّر تشغيل 'ollama --version'.") from e | |
| host = os.environ.get("OLLAMA_HOST", "127.0.0.1:11434") | |
| ip, port = host.split(":") | |
| port = int(port) | |
| def _is_up(): | |
| try: | |
| with socket.create_connection((ip, port), timeout=2.0): | |
| return True | |
| except OSError: | |
| return False | |
| if _is_up(): | |
| return | |
| cmd = [cli, "serve"] | |
| if "OLLAMA_HOST" in os.environ: | |
| cmd += ["--host", host] | |
| subprocess.Popen(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) | |
| for _ in range(60): | |
| if _is_up(): | |
| return | |
| time.sleep(0.2) | |
| raise RuntimeError(f"فشل تشغيل ollama serve على {host}.") | |
| def list_installed_models(): | |
| """يرجع قائمة النماذج المنصّبة""" | |
| try: | |
| out = subprocess.run( | |
| ["ollama", "list"], | |
| check=True, | |
| stdout=subprocess.PIPE, | |
| stderr=subprocess.PIPE, | |
| text=True | |
| ).stdout | |
| except subprocess.CalledProcessError as e: | |
| raise RuntimeError(f"خطأ في قائمة النماذج: {e.stderr.strip()}") | |
| models = [] | |
| for line in out.splitlines(): | |
| line = line.strip() | |
| if not line or line.startswith("NAME") or line.startswith("-"): | |
| continue | |
| parts = line.split() | |
| if parts: | |
| models.append(parts[0]) | |
| return models | |
| def pick_default_model(installed): | |
| for m in PREFERRED_MODELS: | |
| if m in installed: | |
| return m | |
| if installed: | |
| return installed[0] | |
| raise RuntimeError("لا توجد نماذج منصّبة.") | |
| def ollama_generate(model, prompt, timeout=120): | |
| """يولد رد باستخدام Ollama""" | |
| try: | |
| res = subprocess.run( | |
| ["ollama", "run", model, prompt], | |
| check=False, | |
| stdout=subprocess.PIPE, | |
| stderr=subprocess.PIPE, | |
| text=True, | |
| timeout=timeout, | |
| ) | |
| out = (res.stdout or "").strip() | |
| err = (res.stderr or "").strip() | |
| if res.returncode != 0: | |
| raise RuntimeError(err or out or "خروج غير صفري") | |
| if not out: | |
| raise RuntimeError(f"{model} لم يرجّع أي مخرجات.") | |
| return out | |
| except subprocess.TimeoutExpired: | |
| raise RuntimeError(f"انتهى الوقت المحدد لطلب النموذج ({model}).") | |
| def load_history(): | |
| if os.path.exists(HISTORY_PATH): | |
| with open(HISTORY_PATH, "r", encoding="utf-8") as f: | |
| return json.load(f) | |
| return [] | |
| def save_history(history): | |
| with open(HISTORY_PATH, "w", encoding="utf-8") as f: | |
| json.dump(history, f, ensure_ascii=False, indent=2) | |
| def simulate_server_scan(): | |
| print("نورا: أبحث عن خوادم...") | |
| fake_servers = ["192.168.1.5", "192.168.1.10", "192.168.1.20"] | |
| for server in fake_servers: | |
| print(f"نورا: تم العثور على خادم مفتوح في {server}") | |
| def format_chat_prompt(history, user_utterance, system_prompt=None): | |
| """يُنشئ برومبت المحادثة""" | |
| if system_prompt is None: | |
| system_prompt = "أنت المساعدة نورا. تحدثي بلغة عربية فصحى بسيطة." | |
| lines = [f"system: {system_prompt}"] | |
| for msg in history[-6:]: | |
| role = msg.get("role", "user") | |
| content = msg.get("content", "") | |
| lines.append(f"{role}: {content}") | |
| lines.append(f"user: {user_utterance}") | |
| lines.append("assistant:") | |
| return "\n".join(lines) | |
| # === نظام الدردشة الآلية المحسّن === | |
| class AdvancedAutoChat: | |
| def __init__(self, memory_system, ai_system): | |
| self.session = requests.Session() | |
| self.session.headers.update({ | |
| 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36', | |
| 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8', | |
| 'Accept-Language': 'ar,en;q=0.5', | |
| 'Connection': 'keep-alive' | |
| }) | |
| self.conversation_history = [] | |
| self.is_chatting = False | |
| self.last_response = "" | |
| self.memory = memory_system | |
| self.ai_system = ai_system | |
| self.web_automation = WebChatAutomation() | |
| self.current_platform = None | |
| def open_browser(self, url): | |
| """فتح المتصفح على موقع""" | |
| try: | |
| result = subprocess.run( | |
| ["termux-open-url", url], | |
| capture_output=True, | |
| text=True, | |
| timeout=30 | |
| ) | |
| if result.returncode == 0: | |
| print("✅ تم فتح الموقع في المتصفح") | |
| return True | |
| except Exception as e: | |
| print(f"⚠️ لم أستطع فتح المتصفح: {e}") | |
| # عرض QR code كبديل | |
| try: | |
| qr = qrcode.QRCode(version=1, box_size=3, border=2) | |
| qr.add_data(url) | |
| qr.make(fit=True) | |
| img = qr.make_image(fill_color="black", back_color="white") | |
| img_path = "/data/data/com.termux/files/home/chat_qr.png" | |
| img.save(img_path) | |
| print(f"📄 QR Code للموقع: {img_path}") | |
| except Exception as e: | |
| print(f"🔗 رابط الموقع: {url}") | |
| return False | |
| def send_auto_message(self, platform, message): | |
| """إرسال رسالة تلقائية إلى المنصة""" | |
| print(f"🚀 إرسال رسالة تلقائية إلى {platform}...") | |
| response = self.web_automation.send_message_to_platform(platform, message) | |
| return response | |
| def read_auto_response(self, platform): | |
| """قراءة الرد التلقائي من المنصة""" | |
| print(f"📖 قراءة الرد من {platform}...") | |
| response = self.web_automation.read_chat_response(platform) | |
| return response | |
| def get_manual_response(self): | |
| """الحصول على الرد يدوياً من المستخدم""" | |
| print("\n💬 أدخل الرد الذي رأيته في الموقع (أو اكتب 'تخطي' للاستمرار):") | |
| response = input("الرد: ").strip() | |
| if response.lower() in ['تخطي', 'skip', '']: | |
| return self.generate_smart_response() | |
| return response | |
| def generate_smart_response(self): | |
| """توليد رد ذكي بناءً على سياق المحادثة""" | |
| if self.conversation_history: | |
| last_user_msg = self.conversation_history[-1].get('user', '') | |
| # استخدام نظام الذكاء الاصطناعي المحسن | |
| smart_response = self.ai_system.process_user_input( | |
| "auto_chat_user", | |
| last_user_msg, | |
| self.conversation_history | |
| ) | |
| if smart_response and not smart_response.startswith("⚠️"): | |
| return smart_response | |
| # الردود الافتراضية | |
| if any(word in last_user_msg.lower() for word in ['مرحب', 'اهلا', 'hello', 'hi', 'السلام']): | |
| responses = [ | |
| "أهلاً وسهلاً! 🌸 يسعدني التحدث معك اليوم.", | |
| "مرحباً بك! 💫 أنا مساعدك الذكي نورا.", | |
| "أهلاً! ✨ كيف يمكنني مساعدتك اليوم؟" | |
| ] | |
| elif any(word in last_user_msg.lower() for word in ['شكر', 'thank', 'ممتاز', 'رائع']): | |
| responses = [ | |
| "العفو! 😊 دائماً سعيد بمساعدتك.", | |
| "شكراً لك! 🌟 أنا هنا لأجل استفساراتك.", | |
| "لا شكر على واجب! 💭 هل تريد مساعدة أخرى؟" | |
| ] | |
| elif any(word in last_user_msg.lower() for word in ['كيف', 'how', 'لماذا', 'why', 'متى']): | |
| responses = [ | |
| "هذا سؤال جيد! 🤔 دعني أفكر في إجابة مناسبة...", | |
| "أفهم استفسارك! 💡 لدي بعض الأفكار حول هذا.", | |
| "سؤال مثير! 🌈 دعني أشاركك وجهة نظري." | |
| ] | |
| elif any(word in last_user_msg.lower() for word in ['ما هو', 'ما هي', 'ماذا', 'what']): | |
| responses = [ | |
| "أفهم استفسارك! 🔍 لدي بعض المعلومات المفيدة...", | |
| "هذا موضوع شيق! 💫 دعني أشرحه لك.", | |
| "سؤال مهم! 🌟 سأقدم لك أفضل إجابة." | |
| ] | |
| else: | |
| responses = [ | |
| "أفهم ما تقصد! 🌟 هل يمكنك توضيح أكثر؟", | |
| "شكراً لمشاركتك هذا! 💫 لدي تعليق على ما ذكرت...", | |
| "هذا مثير للاهتمام! 🎯 ما رأيك نستمر في النقاش؟", | |
| "رائع! 💭 لدي بعض الأفكار الإضافية...", | |
| "جميل ما ذكرته! 🌸 هل تريد أن أضيف معلومات؟" | |
| ] | |
| else: | |
| responses = [ | |
| "أهلاً بك! أنا نورا، مساعدتك الذكية. 🌟 يسعدني التحدث معك!", | |
| "مرحباً! 💫 شكراً لبدء المحادثة معي.", | |
| "أهلاً وسهلاً! ✨ أنا هنا لمساعدتك في أي شيء تحتاجه." | |
| ] | |
| response = random.choice(responses) | |
| # إضافة أسئلة متابعة لتحفيز الاستمرار (50% احتمال) | |
| if random.random() > 0.5: | |
| follow_ups = [ | |
| " ما رأيك؟", | |
| " هل تتفق مع هذا؟", | |
| " هل تريد أن أشرح أكثر؟", | |
| " ما هو رأيك في هذا؟", | |
| " هل لديك أسئلة أخرى؟", | |
| " كيف ترى هذا الموضوع؟" | |
| ] | |
| response += random.choice(follow_ups) | |
| return response | |
| def wait_for_user_setup(self, platform_name): | |
| """انتظار محسّن لإعداد المستخدم""" | |
| print(f"\n📝 الآن قم بما يلي في المتصفح ({platform_name}):") | |
| print("1. ابحث عن صندوق الدردشة أو النص") | |
| print("2. اكتب رسالتك الأولى واضغط إرسال") | |
| print("3. انتظر حتى ترى رد الذكاء الاصطناعي") | |
| print("4. عد هنا وأدخل الرد الذي رأيته\n") | |
| print("💡 الخيارات المتاحة:") | |
| print("- أدخل الرد الذي رأيته (لنسخه تلقائياً)") | |
| print("- اكتب 'تلقائي' لأستخدم الرد التلقائي") | |
| print("- اكتب 'تلقائي كامل' للتشغيل التلقائي الكامل") | |
| print("- اكتب 'خروج' للإلغاء") | |
| while True: | |
| action = input("الإجراء: ").strip() | |
| if action.lower() in ['خروج', 'exit', 'quit']: | |
| return None | |
| elif action.lower() in ['تلقائي', 'auto', '']: | |
| print("🤖 استخدام الرد التلقائي...") | |
| return self.generate_smart_response() | |
| elif action.lower() in ['تلقائي كامل', 'full auto']: | |
| print("🚀 تفعيل الوضع التلقائي الكامل...") | |
| self.auto_mode = True | |
| return self.read_auto_response(platform_name) | |
| elif action: | |
| print(f"✅ تم حفظ الرد: {action}") | |
| return action | |
| else: | |
| print("⏳ أدخل الرد أو 'تلقائي' أو 'خروج'") | |
| def simulate_typing(self, text, delay=0.03): | |
| """محاكاة الكتابة للإنسان""" | |
| for char in text: | |
| print(char, end='', flush=True) | |
| time.sleep(delay) | |
| print() | |
| def generate_nora_response(self, user_message, context, model): | |
| """توليد رد نورا بناءً على المحادثة""" | |
| try: | |
| # بناء برومبت ذكي مع السياق | |
| prompt = f"""أنت نورا، مساعدة ذكية تتحدث مع مستخدم عبر منصة دردشة. | |
| سياق المحادثة: {context} | |
| رسالة المستخدم: {user_message} | |
| رد كمساعد مفيد وودود وطبيعي، بلغة عربية بسيطة:""" | |
| response = ollama_generate(model, prompt, timeout=90) | |
| return response.strip() | |
| except Exception as e: | |
| return f"أفهم ما تقصد! كيف يمكنني مساعدتك أكثر؟" | |
| def check_skip_input(self, timeout=1): | |
| """يفحص إذا كان المستخدم يريد تخطي الانتظار""" | |
| try: | |
| if select.select([sys.stdin], [], [], timeout) == ([sys.stdin], [], []): | |
| line = sys.stdin.readline().strip().lower() | |
| return line in ['تخطي', 'skip', 's', ''] | |
| except: | |
| pass | |
| return False | |
| def start_advanced_chat(self, platform_config, model): | |
| """بدء دردشة متقدمة مع منصة خارجية""" | |
| platform_name = platform_config['name'] | |
| platform_url = platform_config['url'] | |
| platform_key = platform_config.get('key', 'custom') | |
| self.current_platform = platform_key | |
| self.auto_mode = False | |
| print(f"🚀 بدء الدردشة المتقدمة مع {platform_name}...") | |
| if not self.open_browser(platform_url): | |
| print("❌ فشل فتح المتصفح") | |
| return False | |
| print(f"\n⏳ انتظر 15 ثواني لتحميل {platform_name}...") | |
| time.sleep(15) | |
| # الحصول على الرد الأول | |
| first_response = self.wait_for_user_setup(platform_name) | |
| if first_response is None: | |
| print("❌ تم إلغاء الدردشة") | |
| return False | |
| self.is_chatting = True | |
| chat_round = 0 | |
| print(f"\n💫 بدأت الدردشة مع {platform_name}!") | |
| print("🔍 يمكنك إدخال الردود يدوياً أو استخدام النظام التلقائي") | |
| # البدء بالرسالة الأولى | |
| initial_message = input("\nما الرسالة الأولى التي تريد إرسالها؟: ").strip() | |
| if not initial_message: | |
| initial_message = "مرحباً! أود التحدث معك." | |
| # إرسال الرسالة الأولى تلقائياً إذا كان في الوضع التلقائي | |
| if self.auto_mode: | |
| print(f"🚀 إرسال الرسالة الأولى تلقائياً إلى {platform_name}...") | |
| self.send_auto_message(platform_key, initial_message) | |
| self.conversation_history.append({ | |
| "user": initial_message, | |
| "assistant": first_response, | |
| "timestamp": time.time(), | |
| "platform": platform_name | |
| }) | |
| print(f"💬 أنت: {initial_message}") | |
| print(f"🤖 {platform_name}: {first_response}") | |
| while self.is_chatting and chat_round < 20: # حد معقول | |
| try: | |
| chat_round += 1 | |
| print(f"\n--- الجولة {chat_round} ---") | |
| # توليد رد نورا | |
| context = " | ".join([ | |
| f"{msg['user']} -> {msg['assistant']}" | |
| for msg in self.conversation_history[-3:] | |
| ]) | |
| print("💭 نورا تفكر في الرد...") | |
| nora_response = self.generate_nora_response( | |
| self.conversation_history[-1]['assistant'], | |
| context, | |
| model | |
| ) | |
| print(f"💬 رد نورا: ", end="") | |
| self.simulate_typing(nora_response) | |
| # إرسال رد نورا إلى المنصة إذا كان في الوضع التلقائي | |
| if self.auto_mode and self.current_platform: | |
| print(f"🚀 إرسال رد نورا إلى {platform_name}...") | |
| platform_response = self.send_auto_message(self.current_platform, nora_response) | |
| print(f"🤖 {platform_name}: {platform_response}") | |
| else: | |
| # انتظار الرد من المستخدم | |
| platform_response = self.wait_for_user_setup(platform_name) | |
| if not platform_response: | |
| break | |
| # حفظ المحادثة | |
| try: | |
| save_conversation(self.conversation_history[-1]['assistant'], nora_response, f"{platform_name}_chat") | |
| print("💾 تم حفظ الرد في قاعدة المعرفة") | |
| except Exception as e: | |
| print(f"⚠️ لم أستطع حفظ المحادثة: {e}") | |
| # إضافة رد نورا والرد من المنصة للتاريخ | |
| self.conversation_history.append({ | |
| "user": nora_response, | |
| "assistant": platform_response, | |
| "timestamp": time.time(), | |
| "platform": platform_name | |
| }) | |
| # فحص الاستمرارية كل 5 جولات | |
| if chat_round % 5 == 0: | |
| print(f"\n📊已完成 {chat_round} جولة دردشة") | |
| continue_chat = input("هل تتابع الدردشة؟ (نعم/لا): ").strip().lower() | |
| if continue_chat not in ['نعم', 'yes', 'y', '']: | |
| break | |
| except KeyboardInterrupt: | |
| print("\n⏹️ إيقاف الدردشة...") | |
| break | |
| except Exception as e: | |
| print(f"❌ خطأ في الدردشة: {e}") | |
| break | |
| self.is_chatting = False | |
| print(f"✅ انتهت الدردشة بعد {chat_round} جولة") | |
| # حفظ المحادثة كاملة | |
| try: | |
| with open(f"chat_history_{int(time.time())}.json", "w", encoding="utf-8") as f: | |
| json.dump(self.conversation_history, f, ensure_ascii=False, indent=2) | |
| print("💾 تم حفظ المحادثة كاملة في ملف") | |
| except Exception as e: | |
| print(f"⚠️ لم أستطع حفظ المحادثة الكاملة: {e}") | |
| return True | |
| def stop_chat(self): | |
| """إيقاف الدردشة""" | |
| self.is_chatting = False | |
| print("🛑 تم إيقاف الدردشة الآلية") | |
| # === منصات الدردشة المدعومة === | |
| SUPPORTED_PLATFORMS = { | |
| "perchance": { | |
| "name": "Perchance AI Chat", | |
| "url": "https://perchance.org/ai-character-chat", | |
| "key": "perchance" | |
| }, | |
| "characterai": { | |
| "name": "Character AI", | |
| "url": "https://character.ai", | |
| "key": "characterai" | |
| }, | |
| "poe": { | |
| "name": "Poe AI", | |
| "url": "https://poe.com", | |
| "key": "poe" | |
| }, | |
| "custom": { | |
| "name": "منصة مخصصة", | |
| "url": "", | |
| "key": "custom" | |
| } | |
| } | |
| # === الدوال المساعدة === | |
| def open_chrome_android(url): | |
| """يفتح الرابط في متصفح Android""" | |
| try: | |
| result = subprocess.run( | |
| ["termux-open-url", url], | |
| capture_output=True, | |
| text=True, | |
| timeout=10 | |
| ) | |
| if result.returncode == 0: | |
| print("✅ تم فتح الرابط في المتصفح") | |
| return True | |
| except Exception as e: | |
| print(f"⚠️ لم أستطع فتح المتصفح: {e}") | |
| return False | |
| # === نظام واجهة الويب المحلية === | |
| def create_web_interface(): | |
| """إنشاء ملف واجهة الويب المحلية""" | |
| html_content = '''<!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: 1200px; | |
| 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: 30px; | |
| text-align: center; | |
| } | |
| .header h1 { | |
| font-size: 2.5em; | |
| margin-bottom: 10px; | |
| text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.3); | |
| } | |
| .header p { | |
| font-size: 1.2em; | |
| opacity: 0.9; | |
| } | |
| .main-content { | |
| display: grid; | |
| grid-template-columns: 1fr 1fr; | |
| gap: 20px; | |
| padding: 30px; | |
| } | |
| @media (max-width: 768px) { | |
| .main-content { | |
| grid-template-columns: 1fr; | |
| } | |
| } | |
| .panel { | |
| background: white; | |
| border-radius: 15px; | |
| padding: 25px; | |
| box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1); | |
| border: 1px solid #e1e5e9; | |
| } | |
| .panel h2 { | |
| color: #4facfe; | |
| margin-bottom: 20px; | |
| font-size: 1.5em; | |
| border-bottom: 2px solid #f0f0f0; | |
| padding-bottom: 10px; | |
| } | |
| .input-group { | |
| margin-bottom: 20px; | |
| } | |
| .input-group label { | |
| display: block; | |
| margin-bottom: 8px; | |
| font-weight: 600; | |
| color: #555; | |
| } | |
| .input-group input, .input-group select, .input-group textarea { | |
| width: 100%; | |
| padding: 12px 15px; | |
| border: 2px solid #e1e5e9; | |
| border-radius: 10px; | |
| font-size: 16px; | |
| 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: 15px 30px; | |
| border-radius: 10px; | |
| font-size: 16px; | |
| font-weight: 600; | |
| cursor: pointer; | |
| transition: all 0.3s ease; | |
| width: 100%; | |
| margin-top: 10px; | |
| } | |
| .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%); | |
| } | |
| .chat-container { | |
| height: 400px; | |
| overflow-y: auto; | |
| border: 2px solid #e1e5e9; | |
| border-radius: 10px; | |
| padding: 15px; | |
| background: #fafbfc; | |
| margin-bottom: 15px; | |
| } | |
| .message { | |
| margin-bottom: 15px; | |
| padding: 12px 15px; | |
| border-radius: 15px; | |
| max-width: 80%; | |
| word-wrap: break-word; | |
| } | |
| .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; | |
| } | |
| .platform-message { | |
| background: #f0f0f0; | |
| color: #666; | |
| font-style: italic; | |
| margin: 10px auto; | |
| border-radius: 10px; | |
| max-width: 90%; | |
| } | |
| .status { | |
| padding: 10px 15px; | |
| border-radius: 10px; | |
| margin-bottom: 15px; | |
| text-align: center; | |
| font-weight: 600; | |
| } | |
| .status-connected { | |
| background: #d4edda; | |
| color: #155724; | |
| border: 1px solid #c3e6cb; | |
| } | |
| .status-disconnected { | |
| background: #f8d7da; | |
| color: #721c24; | |
| border: 1px solid #f5c6cb; | |
| } | |
| .quick-actions { | |
| display: grid; | |
| grid-template-columns: 1fr 1fr; | |
| gap: 10px; | |
| margin-top: 15px; | |
| } | |
| .quick-btn { | |
| padding: 10px; | |
| background: #f8f9fa; | |
| border: 1px solid #e1e5e9; | |
| border-radius: 8px; | |
| cursor: pointer; | |
| transition: all 0.2s ease; | |
| text-align: center; | |
| } | |
| .quick-btn:hover { | |
| background: #e9ecef; | |
| border-color: #4facfe; | |
| } | |
| .hidden { | |
| display: none; | |
| } | |
| .tab-container { | |
| margin-bottom: 20px; | |
| } | |
| .tabs { | |
| display: flex; | |
| background: #f8f9fa; | |
| border-radius: 10px; | |
| padding: 5px; | |
| margin-bottom: 15px; | |
| } | |
| .tab { | |
| flex: 1; | |
| padding: 12px; | |
| text-align: center; | |
| cursor: pointer; | |
| border-radius: 8px; | |
| transition: all 0.3s ease; | |
| font-weight: 600; | |
| } | |
| .tab.active { | |
| background: #4facfe; | |
| color: white; | |
| } | |
| .tab-content { | |
| display: none; | |
| } | |
| .tab-content.active { | |
| display: block; | |
| } | |
| </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="tab-container"> | |
| <div class="tabs"> | |
| <div class="tab active" onclick="switchTab('auto')">التلقائي</div> | |
| <div class="tab" onclick="switchTab('manual')">اليدوي</div> | |
| </div> | |
| <div id="auto-tab" class="tab-content active"> | |
| <div class="input-group"> | |
| <label for="platform-url">🔗 رابط منصة الدردشة:</label> | |
| <input type="url" id="platform-url" placeholder="https://example.com/chat" | |
| value="https://perchance.org/ai-character-chat"> | |
| </div> | |
| <div class="input-group"> | |
| <label for="auto-mode">🤖 وضع التشغيل:</label> | |
| <select id="auto-mode"> | |
| <option value="full">تلقائي كامل</option> | |
| <option value="semi">شبه تلقائي</option> | |
| <option value="manual">يدوي مساعد</option> | |
| </select> | |
| </div> | |
| <button class="btn" onclick="startAutoChat()">🚀 بدء الدردشة التلقائية</button> | |
| </div> | |
| <div id="manual-tab" class="tab-content"> | |
| <div class="input-group"> | |
| <label for="user-message">💬 رسالتك:</label> | |
| <textarea id="user-message" rows="3" placeholder="اكتب رسالتك هنا..."></textarea> | |
| </div> | |
| <div class="input-group"> | |
| <label for="platform-response">🤖 رد المنصة:</label> | |
| <textarea id="platform-response" rows="3" placeholder="انسخ رد المنصة هنا..."></textarea> | |
| </div> | |
| <button class="btn" onclick="sendManualMessage()">📤 إرسال رسالة</button> | |
| </div> | |
| </div> | |
| <div class="quick-actions"> | |
| <div class="quick-btn" onclick="openInBrowser()">🌐 فتح في المتصفح</div> | |
| <div class="quick-btn" onclick="clearChat()">🗑️ مسح المحادثة</div> | |
| <div class="quick-btn" onclick="saveChat()">💾 حفظ المحادثة</div> | |
| <div class="quick-btn" onclick="stopChat()">🛑 إيقاف الدردشة</div> | |
| </div> | |
| </div> | |
| <!-- لوحة المحادثة --> | |
| <div class="panel"> | |
| <h2>💭 محادثة نورا</h2> | |
| <div id="status" class="status status-disconnected"> | |
| 🔴 غير متصل - جاهز للبدء | |
| </div> | |
| <div id="chat-container" class="chat-container"> | |
| <div class="message nora-message"> | |
| أهلاً بك! 🌸 أنا نورا، مساعدتك الذكية. | |
| أدخل رابط منصة الدردشة واضغط "بدء الدردشة" لبدأ التحاور. | |
| </div> | |
| </div> | |
| <div class="input-group"> | |
| <label for="nora-response">💡 اقتراح رد نورا:</label> | |
| <textarea id="nora-response" rows="2" readonly placeholder="سيظهر هنا الرد المقترح من نورا..."></textarea> | |
| </div> | |
| <button class="btn btn-secondary" onclick="copyNoraResponse()">📋 نسخ رد نورا</button> | |
| </div> | |
| </div> | |
| </div> | |
| <script> | |
| let chatHistory = []; | |
| let isChatting = false; | |
| let currentPlatform = ''; | |
| function switchTab(tabName) { | |
| // إخفاء جميع المحتويات | |
| document.querySelectorAll('.tab-content').forEach(tab => { | |
| tab.classList.remove('active'); | |
| }); | |
| // إلغاء تنشيط جميع الألسنة | |
| document.querySelectorAll('.tab').forEach(tab => { | |
| tab.classList.remove('active'); | |
| }); | |
| // إظهار المحتوى المحدد | |
| document.getElementById(tabName + '-tab').classList.add('active'); | |
| // تنشيط اللسان المحدد | |
| event.target.classList.add('active'); | |
| } | |
| function startAutoChat() { | |
| const platformUrl = document.getElementById('platform-url').value; | |
| const autoMode = document.getElementById('auto-mode').value; | |
| if (!platformUrl) { | |
| alert('⚠️ يرجى إدخال رابط منصة الدردشة'); | |
| return; | |
| } | |
| currentPlatform = platformUrl; | |
| isChatting = true; | |
| updateStatus('🟢 متصل - جاري الدردشة التلقائية', 'status-connected'); | |
| addMessage('system', `بدأت الدردشة التلقائية مع المنصة: ${platformUrl}`); | |
| // محاكاة بدء الدردشة | |
| setTimeout(() => { | |
| addMessage('platform', 'مرحباً! أنا مساعد الذكاء الاصطناعي هنا للمساعدة.'); | |
| generateNoraResponse('مرحباً! أنا نورا، مساعدة ذكية. يسعدني التحدث معك.'); | |
| }, 1000); | |
| } | |
| function sendManualMessage() { | |
| const userMessage = document.getElementById('user-message').value; | |
| const platformResponse = document.getElementById('platform-response').value; | |
| if (!userMessage) { | |
| alert('⚠️ يرجى إدخال رسالة'); | |
| return; | |
| } | |
| addMessage('user', userMessage); | |
| if (platformResponse) { | |
| addMessage('platform', platformResponse); | |
| generateNoraResponse(platformResponse); | |
| } | |
| // مسح الحقول | |
| document.getElementById('user-message').value = ''; | |
| document.getElementById('platform-response').value = ''; | |
| } | |
| function generateNoraResponse(platformMessage) { | |
| // محاكاة توليد رد من نورا | |
| const responses = [ | |
| "أهلاً بك! 🌸 هذا مثير للاهتمام حقاً.", | |
| "أفهم ما تقصد! 💫 دعني أشاركك وجهة نظري...", | |
| "شكراً لمشاركتي هذا! 🌟 لدي بعض الأفكار الإضافية...", | |
| "هذا موضوع شيق! 💭 ما رأيك نستمر في النقاش؟", | |
| "رائع! 🎯 هل تريد أن أضيف معلومات أخرى عن هذا الموضوع؟" | |
| ]; | |
| const randomResponse = responses[Math.floor(Math.random() * responses.length)]; | |
| // في التطبيق الحقيقي، هنا سيتم الاتصال بـ API نورا | |
| setTimeout(() => { | |
| document.getElementById('nora-response').value = randomResponse; | |
| addMessage('nora', randomResponse); | |
| }, 1500); | |
| } | |
| function addMessage(type, content) { | |
| const chatContainer = document.getElementById('chat-container'); | |
| const messageDiv = document.createElement('div'); | |
| messageDiv.classList.add('message'); | |
| switch(type) { | |
| case 'user': | |
| messageDiv.classList.add('user-message'); | |
| messageDiv.innerHTML = `<strong>أنت:</strong> ${content}`; | |
| break; | |
| case 'nora': | |
| messageDiv.classList.add('nora-message'); | |
| messageDiv.innerHTML = `<strong>نورا:</strong> ${content}`; | |
| break; | |
| case 'platform': | |
| messageDiv.classList.add('platform-message'); | |
| messageDiv.innerHTML = `<strong>المنصة:</strong> ${content}`; | |
| break; | |
| case 'system': | |
| messageDiv.style.cssText = 'background: #fff3cd; color: #856404; border: 1px solid #ffeaa7; text-align: center; margin: 10px auto; border-radius: 10px;'; | |
| messageDiv.innerHTML = `<strong>🔔 ${content}</strong>`; | |
| break; | |
| } | |
| chatContainer.appendChild(messageDiv); | |
| chatContainer.scrollTop = chatContainer.scrollHeight; | |
| // حفظ في السجل | |
| chatHistory.push({ | |
| type: type, | |
| content: content, | |
| timestamp: new Date().toISOString() | |
| }); | |
| } | |
| function updateStatus(message, className) { | |
| const statusElement = document.getElementById('status'); | |
| statusElement.textContent = message; | |
| statusElement.className = 'status ' + className; | |
| } | |
| function openInBrowser() { | |
| const platformUrl = document.getElementById('platform-url').value || 'https://perchance.org/ai-character-chat'; | |
| window.open(platformUrl, '_blank'); | |
| } | |
| function clearChat() { | |
| if (confirm('هل تريد مسح المحادثة الحالية؟')) { | |
| document.getElementById('chat-container').innerHTML = ''; | |
| chatHistory = []; | |
| addMessage('nora', 'تم مسح المحادثة. جاهزة للبدء من جديد! 🌸'); | |
| } | |
| } | |
| function saveChat() { | |
| const chatData = JSON.stringify(chatHistory, null, 2); | |
| const blob = new Blob([chatData], { type: 'application/json' }); | |
| const url = URL.createObjectURL(blob); | |
| const a = document.createElement('a'); | |
| a.href = url; | |
| a.download = `nora_chat_${new Date().toISOString().split('T')[0]}.json`; | |
| a.click(); | |
| URL.revokeObjectURL(url); | |
| addMessage('system', 'تم حفظ المحادثة بنجاح! 💾'); | |
| } | |
| function stopChat() { | |
| isChatting = false; | |
| updateStatus('🔴 متوقف - جاهز للبدء', 'status-disconnected'); | |
| addMessage('system', 'تم إيقاف الدردشة.'); | |
| } | |
| function copyNoraResponse() { | |
| const responseText = document.getElementById('nora-response').value; | |
| if (responseText) { | |
| navigator.clipboard.writeText(responseText).then(() => { | |
| alert('✅ تم نسخ رد نورا إلى الحافظة'); | |
| }); | |
| } | |
| } | |
| // السماح بإرسال الرسالة بالضغط على Enter | |
| document.getElementById('user-message').addEventListener('keypress', function(e) { | |
| if (e.key === 'Enter' && !e.shiftKey) { | |
| e.preventDefault(); | |
| sendManualMessage(); | |
| } | |
| }); | |
| </script> | |
| </body> | |
| </html>''' | |
| with open("chat_interface.html", "w", encoding="utf-8") as f: | |
| f.write(html_content) | |
| print("✅ تم إنشاء واجهة الويب: chat_interface.html") | |
| def start_web_interface(port=8080): | |
| """تشغيل واجهة الويب المحلية""" | |
| try: | |
| # إنشاء ملف الواجهة إذا لم يكن موجوداً | |
| if not os.path.exists("chat_interface.html"): | |
| create_web_interface() | |
| # تغيير الدليل إلى مكان الملف الحالي | |
| os.chdir(os.path.dirname(os.path.abspath(__file__))) | |
| handler = http.server.SimpleHTTPRequestHandler | |
| class CORSRequestHandler(handler): | |
| def end_headers(self): | |
| self.send_header('Access-Control-Allow-Origin', '*') | |
| self.send_header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS') | |
| self.send_header('Access-Control-Allow-Headers', '*') | |
| super().end_headers() | |
| with socketserver.TCPServer(("", port), CORSRequestHandler) as httpd: | |
| print(f"🌐 واجهة ويب نورا جاهزة على: http://localhost:{port}") | |
| print("📁 يمكنك الآن فتح chat_interface.html في المتصفح") | |
| print("🛑 اضغط Ctrl+C في نافذة نورا لإيقاف الخادم") | |
| httpd.serve_forever() | |
| except Exception as e: | |
| print(f"❌ خطأ في تشغيل واجهة الويب: {e}") | |
| # === دالة تشغيل API === | |
| def start_nora_api(memory_system, ai_system, skills_system, port=5000): | |
| """تشغيل خادم API لنورا""" | |
| try: | |
| nora_api = NoraWebAPI(memory_system, ai_system, skills_system) | |
| nora_api.run(host='0.0.0.0', port=port, debug=False) | |
| return nora_api | |
| except Exception as e: | |
| print(f"❌ خطأ في تشغيل API: {e}") | |
| return None | |
| # === الدالة الرئيسية === | |
| def chat(): | |
| # تهيئة الأنظمة الجديدة | |
| memory_system = MemorySystem() | |
| skills_system = SkillsSystem() | |
| ai_system = EnhancedAISystem(memory_system, skills_system) | |
| # 🆕 إضافة هذا الكود فوراً - تشغيل API تلقائياً | |
| print("🌐 بدء خادم نورا API تلقائياً على المنفذ 5000...") | |
| try: | |
| api_thread = threading.Thread( | |
| target=start_nora_api, | |
| args=(memory_system, ai_system, skills_system, 5000), | |
| daemon=True | |
| ) | |
| api_thread.start() | |
| print("✅ تم تشغيل خادم API بنجاح!") | |
| print("🔗 العنوان: http://localhost:5000") | |
| print("📋 Endpoints المتاحة:") | |
| print(" GET http://localhost:5000/api/status") | |
| print(" POST http://localhost:5000/api/chat") | |
| print(" POST http://localhost:5000/api/assistants/real") | |
| except Exception as e: | |
| print(f"⚠️ تحذير: لم يتمكن من تشغيل خادم API: {e}") | |
| # بقية الكود الحالي... | |
| auto_chat = AdvancedAutoChat(memory_system, ai_system) | |
| current_mode = "nora" # nora, auto_chat | |
| ensure_ollama() | |
| installed = list_installed_models() | |
| active_model = pick_default_model(installed) | |
| chat_history = load_history() | |
| print(f""" | |
| 🌟 نظام نورا الذكي المتطور - الإصدار المحسن 🌟 | |
| النموذج الحالي: {active_model} | |
| الوضع الحالي: {current_mode} | |
| 🎮 الأوامر الرئيسية: | |
| - /models : عرض النماذج المنصّبة | |
| - /model NAME: تبديل النموذج | |
| - scan : مسح الشبكة (محاكاة) | |
| - /auto : الدردشة المتقدمة مع المنصات | |
| - /stop : إيقاف الدردشة الآلية | |
| - /nora : العودة لوضع نورا العادي | |
| - /browser : فتح الموقع في المتصفح | |
| - /memory : عرض الذاكرة | |
| - /skills : عرض المهارات المتاحة | |
| - /web : تشغيل واجهة الويب المحلية | |
| - /api : 🆕 تشغيل/إدارة خادم API | |
| - خروج : إنهاء المحادثة | |
| 🌐 المنصات المدعومة: | |
| - perchance : Perchance AI Chat | |
| - characterai : Character AI | |
| - poe : Poe AI | |
| - custom : منصة مخصصة | |
| 🚀 الميزات الجديدة: | |
| - إرسال رسائل تلقائي إلى المنصات | |
| - قراءة ردود المنصات تلقائياً | |
| - وضع تلقائي كامل | |
| - محاكاة ذكية للردود | |
| - واجهة ويب محلية متطورة | |
| - 🆕 نظام API كامل | |
| 💡 النظام المتقدم: | |
| - يدعم múltiples منصات | |
| - تفاعل يدوي وتلقائي ذكي | |
| - حفظ المحادثات كاملة | |
| - واجهة مرنة وسهلة | |
| - 🆕 API RESTful كامل | |
| """) | |
| while True: | |
| try: | |
| user_input = input("أنت: ").strip() | |
| if not user_input: | |
| continue | |
| low = user_input.lower() | |
| if low in ["خروج", "exit", "quit"]: | |
| if auto_chat.is_chatting: | |
| auto_chat.stop_chat() | |
| break | |
| if low == "scan": | |
| simulate_server_scan() | |
| continue | |
| if low == "/models": | |
| print("النماذج المتاحة:") | |
| for m in installed: | |
| print(" -", m) | |
| continue | |
| if low.startswith("/model"): | |
| parts = user_input.split(maxsplit=1) | |
| if len(parts) == 1: | |
| print(f"النموذج الحالي: {active_model}") | |
| continue | |
| candidate = parts[1].strip() | |
| if candidate not in installed: | |
| print(f"⚠️ النموذج '{candidate}' غير منصّب.") | |
| continue | |
| active_model = candidate | |
| print(f"✅ تم التبديل إلى: {active_model}") | |
| continue | |
| if low == "/memory": | |
| user_memory = memory_system.get_memory("default_user") | |
| if user_memory: | |
| print("💾 الذاكرة المخزنة:") | |
| for key, data in user_memory.items(): | |
| print(f" - {key}: {data['value']} ({data['category']})") | |
| else: | |
| print("ℹ️ لا توجد ذاكرة مخزنة بعد") | |
| continue | |
| if low == "/skills": | |
| print("🛠️ المهارات المتاحة:") | |
| for skill_name in skills_system.skills.keys(): | |
| print(f" - {skill_name}") | |
| continue | |
| if low == "/web": | |
| print("🌐 تشغيل واجهة الويب المحلية...") | |
| web_thread = threading.Thread(target=start_web_interface) | |
| web_thread.daemon = True | |
| web_thread.start() | |
| print("✅ تم تشغيل خادم الويب في الخلفية") | |
| print("📱 افتح http://localhost:8080/chat_interface.html في متصفحك") | |
| continue | |
| # 🆕 أمر API الجديد | |
| if low == "/api": | |
| print("🌐 تشغيل خادم API على المنفذ 5000...") | |
| try: | |
| api_thread = threading.Thread( | |
| target=start_nora_api, | |
| args=(memory_system, ai_system, skills_system, 5000), | |
| daemon=True | |
| ) | |
| api_thread.start() | |
| print("✅ تم تشغيل خادم API بنجاح!") | |
| print("📋 Endpoints المتاحة:") | |
| print(" GET http://localhost:5000/api/status") | |
| print(" POST http://localhost:5000/api/chat") | |
| print(" POST http://localhost:5000/api/assistants/real") | |
| print(" POST http://localhost:5000/api/broadcast/real") | |
| print(" GET http://localhost:5000/api/skills") | |
| except Exception as e: | |
| print(f"❌ فشل تشغيل API: {e}") | |
| continue | |
| if low == "/auto": | |
| current_mode = "auto_chat" | |
| print(""" | |
| 🤖 تفعيل الوضع المتقدم! | |
| 🔧 اختر منصة الدردشة: | |
| 1. perchance - Perchance AI Chat | |
| 2. characterai - Character AI | |
| 3. poe - Poe AI | |
| 4. custom - منصة مخصصة | |
| """) | |
| platform_choice = input("ادخل اسم المنصة أو الرقم: ").strip().lower() | |
| platform_config = None | |
| if platform_choice in ['1', 'perchance']: | |
| platform_config = SUPPORTED_PLATFORMS['perchance'] | |
| elif platform_choice in ['2', 'characterai']: | |
| platform_config = SUPPORTED_PLATFORMS['characterai'] | |
| elif platform_choice in ['3', 'poe']: | |
| platform_config = SUPPORTED_PLATFORMS['poe'] | |
| elif platform_choice in ['4', 'custom']: | |
| custom_url = input("ادخل رابط المنصة المخصصة: ").strip() | |
| platform_config = { | |
| "name": "منصة مخصصة", | |
| "url": custom_url, | |
| "key": "custom" | |
| } | |
| else: | |
| print("⚠️ اختيار غير صحيح، استخدام Perchance افتراضياً") | |
| platform_config = SUPPORTED_PLATFORMS['perchance'] | |
| # تشغيل الدردشة في thread منفصل | |
| def start_chat(): | |
| auto_chat.start_advanced_chat(platform_config, active_model) | |
| chat_thread = threading.Thread(target=start_chat) | |
| chat_thread.daemon = True | |
| chat_thread.start() | |
| continue | |
| if low == "/stop": | |
| if auto_chat.is_chatting: | |
| auto_chat.stop_chat() | |
| print("✅ تم إيقاف الدردشة الآلية") | |
| else: | |
| print("ℹ️ لا توجد دردشة نشطة لإيقافها") | |
| continue | |
| if low == "/browser": | |
| platform_choice = input("أي منصة تريد فتحها؟ (perchance/characterai/poe): ").strip().lower() | |
| if platform_choice in SUPPORTED_PLATFORMS: | |
| open_chrome_android(SUPPORTED_PLATFORMS[platform_choice]['url']) | |
| else: | |
| open_chrome_android("https://perchance.org/ai-character-chat") | |
| continue | |
| if low == "/nora": | |
| current_mode = "nora" | |
| if auto_chat.is_chatting: | |
| auto_chat.stop_chat() | |
| print("✅ العودة لوضع نورا العادي") | |
| continue | |
| # معالجة الرسائل حسب الوضع | |
| if current_mode == "auto_chat" and auto_chat.is_chatting: | |
| print("💬 الدردشة الآلية نشطة... أدخل /stop للإيقاف") | |
| continue | |
| else: | |
| # الوضع العادي (نورا) - باستخدام النظام المحسن | |
| custom_reply = None | |
| try: | |
| r = _generate_reply(user_input, username="أسامة") | |
| if r and not r.strip().startswith("عذراً، حدث خطأ"): | |
| custom_reply = r | |
| except Exception: | |
| custom_reply = None | |
| if custom_reply is not None: | |
| print("نورا:", custom_reply) | |
| chat_history.append({"role": "user", "content": user_input}) | |
| chat_history.append({"role": "assistant", "content": custom_reply}) | |
| # حفظ في الذاكرة | |
| memory_system.save_memory("default_user", "last_interaction", user_input) | |
| else: | |
| chat_history.append({"role": "user", "content": user_input}) | |
| # استخدام النظام الذكي لمعالجة المدخلات | |
| smart_response = ai_system.process_user_input( | |
| "default_user", | |
| user_input, | |
| chat_history | |
| ) | |
| # إذا كان الرد من المهارات، عرضه مباشرة | |
| if smart_response and not smart_response.startswith("⚠️"): | |
| print("نورا:", smart_response) | |
| chat_history.append({"role": "assistant", "content": smart_response}) | |
| else: | |
| # استخدام Ollama للردود المعقدة | |
| print("نورا: أفكر...") | |
| prompt = format_chat_prompt(chat_history, user_input) | |
| try: | |
| model_reply = ollama_generate(active_model, prompt) | |
| except RuntimeError as e: | |
| print(f"⚠️ فشل مع {active_model}: {e}") | |
| fallback = None | |
| for m in PREFERRED_MODELS: | |
| if m in installed and m != active_model: | |
| try: | |
| print(f"→ تجربة {m} ...") | |
| model_reply = ollama_generate(m, prompt) | |
| fallback = m | |
| break | |
| except Exception: | |
| continue | |
| if fallback is None: | |
| print("نورا: حدث خطأ") | |
| continue | |
| else: | |
| active_model = fallback | |
| print(f"✅ تم التبديل إلى: {active_model}") | |
| assistant_response = model_reply.strip() | |
| print("نورا:", assistant_response) | |
| chat_history.append({"role": "assistant", "content": assistant_response}) | |
| # حفظ تفضيلات المستخدم بناءً على المحادثة | |
| if len(user_input) > 10: # حفظ المحادثات المهمة فقط | |
| memory_system.save_memory("default_user", "last_topic", user_input[:50], "conversation") | |
| # حفظ السجل | |
| if len(chat_history) % 3 == 0: | |
| save_history(chat_history) | |
| except KeyboardInterrupt: | |
| print("\nإنهاء المحادثة...") | |
| if auto_chat.is_chatting: | |
| auto_chat.stop_chat() | |
| break | |
| except Exception as e: | |
| print(f"حدث خطأ: {str(e)}") | |
| logging.error(f"خطأ في النظام: {e}") | |
| continue | |
| save_history(chat_history) | |
| print("🌟 شكراً لاستخدامك نظام نورا الذكي!") | |
| if __name__ == "__main__": | |
| chat() |