import httpx import logging import random import hashlib from django.utils import timezone from django.utils.dateparse import parse_datetime from datetime import timedelta from .models import AIConfiguration, AIChatHistory, SyncHistoryLog from .utils import decrypt_value logger = logging.getLogger(__name__) def sync_all_configurations(): configs = AIConfiguration.objects.filter(is_active=True) for config in configs: sync_ai_history(config) def sync_ai_history(config: AIConfiguration): api_key = decrypt_value(config.api_key) provider = config.provider company = config.company log = SyncHistoryLog.objects.create( company=company, configuration=config, status='success', records_synced=0 ) try: if provider == 'openai': records = fetch_openai_history(api_key) elif provider == 'perplexity': records = fetch_perplexity_history(api_key) elif provider == 'merlin': records = fetch_merlin_history(api_key) elif provider == 'poe': records = fetch_poe_history(api_key) elif provider == 'openrouter': records = fetch_openrouter_history(api_key) else: records = [] synced_count = 0 for record in records: # Simple deduplication based on ai_chat_id and company obj, created = AIChatHistory.objects.update_or_create( company=company, ai_chat_id=record['id'], defaults={ 'ai_configuration': config, 'ai_chat_engine': provider.upper() if provider in ['poe', 'openrouter'] else provider.capitalize(), 'chat_title': record['title'], 'chat_content': record['content'], 'chat_last_date': record['last_date'], } ) if created: synced_count += 1 log.records_synced = synced_count log.save() config.last_sync = timezone.now() config.save() except Exception as e: logger.exception(f"Error syncing {provider} for {company.name}") log.status = 'error' log.error_message = str(e) log.save() def _generate_stable_id(title, provider): """Generates a stable ID based on the title and provider for mock data.""" hash_object = hashlib.md5(f"{provider}:{title}".encode()) return f"{provider[:2]}_{hash_object.hexdigest()[:8]}" def fetch_openai_history(api_key): if api_key == "ERROR_DECRYPTING": raise Exception("API Key decryption failed") data = [ { 'title': 'Optimizing Telecom Network Architecture', 'content': 'Discussion about 5G deployment and latency optimization in rural areas. Focus on edge computing and MIMO technologies.', 'last_date': timezone.now() - timedelta(hours=5) }, { 'title': 'Customer Churn Analysis Script', 'content': 'Python script using pandas to analyze monthly billing cycles and identify high-risk accounts based on data usage patterns.', 'last_date': timezone.now() - timedelta(days=2) }, { 'title': 'VoIP Quality Troubleshooting Guide', 'content': 'Steps to identify packet loss and jitter in enterprise VoIP setups. Recommended buffer settings and QoS tagging.', 'last_date': timezone.now() - timedelta(days=3) } ] for item in data: item['id'] = _generate_stable_id(item['title'], 'openai') return data def fetch_perplexity_history(api_key): data = [ { 'title': 'Latest Trends in Satellite Communication 2026', 'content': 'Summary of Starlink and Kuiper project progress as of February 2026. Includes regulatory changes in EMEA region.', 'last_date': timezone.now() - timedelta(minutes=15) }, { 'title': 'Regulatory Impact on 6G Spectrum', 'content': 'Analysis of FCC and ITU recent publications regarding terahertz frequency allocations for early 6G trials.', 'last_date': timezone.now() - timedelta(days=1) } ] for item in data: item['id'] = _generate_stable_id(item['title'], 'perplexity') return data def fetch_merlin_history(api_key): data = [ { 'title': 'Merlin AI - Project Planning SEO', 'content': 'SEO strategy for a new telecommunications landing page targeting enterprise clients. Keywords: SD-WAN, Managed Security.', 'last_date': timezone.now() - timedelta(hours=1) } ] for item in data: item['id'] = _generate_stable_id(item['title'], 'merlin') return data def fetch_poe_history(api_key): if api_key == "YOUR_MOCK_KEY_OR_EMPTY": # For now, it's returning mock data: data = [ { 'title': 'POE - Python Data Visualization', 'content': 'Generating heatmaps for network traffic distribution across various regional nodes using Seaborn and Matplotlib.', 'last_date': timezone.now() - timedelta(hours=2) }, { 'title': 'Automated Network Incident Response', 'content': 'Conceptual workflow for using LLMs to parse syslog errors and suggest immediate remediation steps for NOC engineers.', 'last_date': timezone.now() - timedelta(hours=8) } ] for item in data: item['id'] = _generate_stable_id(item['title'], 'poe') return data # Calling an API endpoint (Replace URL with the actual Poe API you use) response = httpx.get( "https://api.poe.com/v1", headers={"Authorization": f"Bearer {api_key}"} ) response.raise_for_status() data = response.json() # Transform the real API response to match our internal format: return [{ 'id': item['chatId'], 'title': item['title'], 'content': item['snippet'], 'last_date': parse_datetime(item['updatedAt']) or timezone.now() } for item in data['chats']] def fetch_openrouter_history(api_key): data = [ { 'title': 'OpenRouter - Llama 3 Research', 'content': 'Comparing performance of open-source models for automated customer support in Telecom. Benchmarks on response latency.', 'last_date': timezone.now() - timedelta(hours=3) } ] for item in data: item['id'] = _generate_stable_id(item['title'], 'openrouter') return data