| """ |
| ATOM Teams Integration Module |
| Integrates Microsoft Teams seamlessly into ATOM's Communication ecosystem |
| """ |
|
|
| import asyncio |
| from dataclasses import asdict, dataclass |
| from datetime import datetime, timedelta, timezone |
| from enum import Enum |
| import json |
| import logging |
| import os |
| from typing import Any, Dict, List, Optional, Union |
|
|
| |
| try: |
| from atom_ingestion_pipeline import AtomIngestionPipeline |
| from atom_memory_service import AtomMemoryService |
| from atom_search_service import AtomSearchService |
| from atom_workflow_service import AtomWorkflowService |
| from teams_analytics_engine import teams_analytics_engine |
| from teams_enhanced_service import ( |
| TeamsChannel, |
| TeamsFile, |
| TeamsMessage, |
| TeamsWorkspace, |
| teams_enhanced_service, |
| ) |
| except ImportError as e: |
| logging.warning(f"Teams integration services not available: {e}") |
| teams_enhanced_service = None |
| teams_analytics_engine = None |
| teams_workflow_engine = None |
|
|
| logger = logging.getLogger(__name__) |
|
|
| |
| class AtomTeamsIntegration: |
| """Main integration class for Microsoft Teams within ATOM ecosystem""" |
| |
| def __init__(self, config: Dict[str, Any]): |
| self.config = config |
| self.atom_memory = config.get('atom_memory_service') |
| self.atom_search = config.get('atom_search_service') |
| self.atom_workflow = config.get('atom_workflow_service') |
| self.atom_ingestion = config.get('atom_ingestion_pipeline') |
| |
| |
| self.teams_service = teams_enhanced_service |
| self.teams_analytics = teams_analytics_engine |
| |
| |
| self.is_initialized = False |
| self.active_workspaces: List[TeamsWorkspace] = [] |
| self.communication_channels: List[Dict[str, Any]] = [] |
| self.unified_messages: List[Dict[str, Any]] = [] |
| |
| logger.info("ATOM Teams Integration initialized") |
| |
| async def initialize(self) -> bool: |
| """Initialize Teams integration with ATOM services""" |
| try: |
| if not all([self.teams_service, self.atom_memory, self.atom_search]): |
| logger.error("Required services not available for Teams integration") |
| return False |
| |
| |
| await self._start_integration_workers() |
| |
| |
| await self._initialize_unified_data() |
| |
| |
| await self._setup_cross_platform_handlers() |
| |
| self.is_initialized = True |
| logger.info("Teams integration with ATOM ecosystem initialized successfully") |
| return True |
| |
| except Exception as e: |
| logger.error(f"Error initializing Teams integration: {e}") |
| return False |
| |
| async def get_unified_workspaces(self, user_id: str) -> List[Dict[str, Any]]: |
| """Get unified workspaces across all platforms including Teams""" |
| try: |
| |
| teams_workspaces = await self.teams_service.get_workspaces(user_id) |
| |
| |
| unified_workspaces = [] |
| |
| for workspace in teams_workspaces: |
| unified_workspace = { |
| 'id': f"teams_{workspace.team_id}", |
| 'name': workspace.display_name, |
| 'type': 'microsoft_teams', |
| 'platform': 'Microsoft Teams', |
| 'status': 'connected' if workspace.is_active else 'disconnected', |
| 'member_count': workspace.member_count, |
| 'channel_count': workspace.channel_count, |
| 'icon_url': 'https://static.squarespace.com/static/55f4f1e6e4b0c5255b878c8/t/5c96395219aefae371f52257/1552750239451/Teams_logo.png', |
| 'integration_data': { |
| 'team_id': workspace.team_id, |
| 'tenant_id': workspace.tenant_id, |
| 'visibility': workspace.visibility, |
| 'web_url': workspace.web_url, |
| 'last_sync': workspace.last_sync.isoformat() if workspace.last_sync else None |
| }, |
| 'capabilities': { |
| 'messaging': True, |
| 'voice_calls': True, |
| 'video_calls': True, |
| 'screen_sharing': True, |
| 'file_sharing': True, |
| 'meetings': True, |
| 'workflows': True, |
| 'analytics': True |
| } |
| } |
| unified_workspaces.append(unified_workspace) |
| |
| |
| self.active_workspaces = teams_workspaces |
| |
| return unified_workspaces |
| |
| except Exception as e: |
| logger.error(f"Error getting unified Teams workspaces: {e}") |
| return [] |
| |
| async def get_unified_channels(self, workspace_id: str, user_id: str = None) -> List[Dict[str, Any]]: |
| """Get unified channels across platforms for given workspace""" |
| try: |
| |
| if workspace_id.startswith('teams_'): |
| teams_workspace_id = workspace_id[6:] |
| else: |
| return [] |
| |
| |
| teams_channels = await self.teams_service.get_channels( |
| teams_workspace_id, |
| user_id, |
| include_private=True, |
| include_archived=False |
| ) |
| |
| |
| unified_channels = [] |
| |
| for channel in teams_channels: |
| unified_channel = { |
| 'id': f"teams_{channel.channel_id}", |
| 'name': channel.display_name, |
| 'display_name': channel.display_name, |
| 'description': channel.description, |
| 'type': channel.channel_type, |
| 'platform': 'Microsoft Teams', |
| 'workspace_id': workspace_id, |
| 'workspace_name': channel.workspaceName, |
| 'status': 'active' if not channel.is_archived else 'archived', |
| 'member_count': channel.member_count, |
| 'message_count': channel.message_count, |
| 'unread_count': channel.unreadCount or 0, |
| 'last_activity': channel.lastActivityAt.isoformat() if channel.lastActivityAt else None, |
| 'is_private': channel.channelType == 'private', |
| 'is_muted': channel.isMuted or False, |
| 'integration_data': { |
| 'channel_id': channel.channel_id, |
| 'membership_type': channel.membership_type, |
| 'email': channel.email, |
| 'web_url': channel.webUrl, |
| 'allow_cross_team_posts': channel.allowCrossTeamPosts |
| }, |
| 'capabilities': { |
| 'messaging': True, |
| 'file_sharing': True, |
| 'voice_calls': True, |
| 'video_calls': True, |
| 'meetings': True, |
| 'workflows': True |
| } |
| } |
| unified_channels.append(unified_channel) |
| |
| |
| self.communication_channels.extend(unified_channels) |
| |
| return unified_channels |
| |
| except Exception as e: |
| logger.error(f"Error getting unified Teams channels: {e}") |
| return [] |
| |
| async def send_unified_message(self, workspace_id: str, channel_id: str, |
| content: str, options: Dict[str, Any] = None) -> Dict[str, Any]: |
| """Send unified message across platforms including Teams""" |
| try: |
| options = options or {} |
| |
| |
| if channel_id.startswith('teams_'): |
| teams_channel_id = channel_id[6:] |
| teams_workspace_id = workspace_id[6:] if workspace_id.startswith('teams_') else None |
| |
| if not teams_workspace_id: |
| raise ValueError("Invalid workspace ID for Teams") |
| |
| |
| teams_result = await self.teams_service.send_message( |
| teams_workspace_id, |
| teams_channel_id, |
| content, |
| thread_id=options.get('thread_id'), |
| importance=options.get('importance', 'normal'), |
| subject=options.get('subject'), |
| attachments=options.get('attachments', []) |
| ) |
| |
| if teams_result.get('ok'): |
| |
| await self._store_message_in_memory(teams_result, 'teams', options) |
| |
| |
| await self._index_message_in_search(teams_result, 'teams', options) |
| |
| |
| await self._trigger_workflows(teams_result, 'teams_message_sent', options) |
| |
| return { |
| 'ok': True, |
| 'message_id': teams_result.get('message_id'), |
| 'platform': 'Microsoft Teams', |
| 'timestamp': datetime.utcnow().isoformat(), |
| 'channel_id': channel_id, |
| 'workspace_id': workspace_id |
| } |
| else: |
| return teams_result |
| |
| |
| else: |
| return {'ok': False, 'error': 'Unsupported platform'} |
| |
| except Exception as e: |
| logger.error(f"Error sending unified Teams message: {e}") |
| return {'ok': False, 'error': str(e)} |
| |
| async def get_unified_messages(self, workspace_id: str, channel_id: str, |
| limit: int = 100, options: Dict[str, Any] = None) -> List[Dict[str, Any]]: |
| """Get unified messages across platforms including Teams""" |
| try: |
| options = options or {} |
| unified_messages = [] |
| |
| |
| if channel_id.startswith('teams_'): |
| teams_channel_id = channel_id[6:] |
| teams_workspace_id = workspace_id[6:] if workspace_id.startswith('teams_') else None |
| |
| if not teams_workspace_id: |
| return [] |
| |
| |
| teams_messages = await self.teams_service.get_channel_messages( |
| teams_workspace_id, |
| teams_channel_id, |
| limit=limit, |
| latest=options.get('latest'), |
| oldest=options.get('oldest') |
| ) |
| |
| |
| for message in teams_messages: |
| unified_message = { |
| 'id': f"teams_{message.message_id}", |
| 'content': message.text, |
| 'html_content': message.html, |
| 'platform': 'Microsoft Teams', |
| 'workspace_id': workspace_id, |
| 'channel_id': channel_id, |
| 'user_id': f"teams_{message.userId}", |
| 'user_name': message.userName, |
| 'user_email': message.userEmail, |
| 'user_avatar': f"https://ui-avatars.com/api/?name={message.userName}&background=random", |
| 'timestamp': message.timestamp, |
| 'thread_id': f"teams_{message.threadId}" if message.threadId else None, |
| 'reply_to_id': f"teams_{message.replyToId}" if message.replyToId else None, |
| 'message_type': message.messageType, |
| 'importance': message.importance, |
| 'subject': message.subject, |
| 'is_edited': message.isEdited, |
| 'edit_timestamp': message.editTimestamp, |
| 'reactions': message.reactions, |
| 'attachments': message.attachments, |
| 'mentions': [ |
| { |
| 'id': mention.get('id'), |
| 'name': mention.get('displayName') or mention.get('userPrincipalName'), |
| 'type': 'user', |
| 'platform': 'Microsoft Teams' |
| } |
| for mention in message.mentions |
| ], |
| 'files': [ |
| { |
| 'id': file.get('id'), |
| 'name': file.get('name'), |
| 'type': 'teams_file', |
| 'platform': 'Microsoft Teams', |
| 'url': file.get('webUrl'), |
| 'size': file.get('size', 0) |
| } |
| for file in message.files |
| ], |
| 'integration_data': { |
| 'message_id': message.message_id, |
| 'user_id': message.userId, |
| 'tenant_id': message.tenantId, |
| 'etag': message.etag, |
| 'channel_identity': message.channelIdentity, |
| 'participant_count': message.participantCount |
| }, |
| 'metadata': { |
| 'has_thread': bool(message.threadId), |
| 'reply_count': len([msg for msg in teams_messages if msg.replyToId == message.message_id]), |
| 'has_attachments': bool(message.attachments), |
| 'has_mentions': bool(message.mentions), |
| 'importance_level': { |
| 'low': 1, |
| 'normal': 2, |
| 'high': 3, |
| 'urgent': 4 |
| }.get(message.importance, 2) |
| } |
| } |
| unified_messages.append(unified_message) |
| |
| |
| self.unified_messages.extend(unified_messages) |
| |
| |
| unified_messages.sort(key=lambda x: x['timestamp'], reverse=True) |
| |
| return unified_messages[:limit] |
| |
| except Exception as e: |
| logger.error(f"Error getting unified Teams messages: {e}") |
| return [] |
| |
| async def unified_search(self, query: str, workspace_id: str = None, |
| channel_id: str = None, options: Dict[str, Any] = None) -> List[Dict[str, Any]]: |
| """Perform unified search across platforms including Teams""" |
| try: |
| options = options or {} |
| unified_results = [] |
| |
| |
| if channel_id and channel_id.startswith('teams_'): |
| teams_channel_id = channel_id[6:] |
| teams_workspace_id = workspace_id[6:] if workspace_id and workspace_id.startswith('teams_') else None |
| |
| if teams_workspace_id: |
| teams_results = await self.teams_service.search_messages( |
| teams_workspace_id, |
| query, |
| channel_id=teams_channel_id, |
| user_id=options.get('user_id'), |
| limit=options.get('limit', 50) |
| ) |
| |
| if teams_results.get('ok'): |
| for message in teams_results.get('messages', []): |
| unified_result = { |
| 'id': f"teams_{message.message_id}", |
| 'title': message.subject or f"Message from {message.userName}", |
| 'content': message.text, |
| 'platform': 'Microsoft Teams', |
| 'workspace_id': workspace_id or f"teams_{message.tenantId}", |
| 'channel_id': channel_id, |
| 'user_id': f"teams_{message.userId}", |
| 'user_name': message.userName, |
| 'timestamp': message.timestamp, |
| 'type': 'message', |
| 'url': f"https://teams.microsoft.com/l/message/{message.message_id}/thread/{message.threadId}" if message.threadId else f"https://teams.microsoft.com/l/message/{message.message_id}", |
| 'relevance_score': message.metadata.get('search_score', 1.0) if hasattr(message, 'metadata') else 1.0, |
| 'highlights': self._generate_search_highlights(message.text, query), |
| 'integration_data': { |
| 'message_id': message.message_id, |
| 'channel_name': message.channelIdentity.get('displayName') if hasattr(message, 'channelIdentity') else None, |
| 'importance': message.importance |
| } |
| } |
| unified_results.append(unified_result) |
| |
| |
| |
| |
| unified_results.sort(key=lambda x: x['relevance_score'], reverse=True) |
| |
| return unified_results[:options.get('limit', 50)] |
| |
| except Exception as e: |
| logger.error(f"Error in unified Teams search: {e}") |
| return [] |
| |
| async def create_unified_workflow(self, workflow_data: Dict[str, Any]) -> Dict[str, Any]: |
| """Create unified workflow that can operate across platforms including Teams""" |
| try: |
| |
| teams_involved = False |
| for trigger in workflow_data.get('triggers', []): |
| if trigger.get('platform') == 'microsoft_teams' or 'teams' in trigger.get('event', '').lower(): |
| teams_involved = True |
| break |
| |
| for action in workflow_data.get('actions', []): |
| if action.get('platform') == 'microsoft_teams' or 'teams' in action.get('action', '').lower(): |
| teams_involved = True |
| break |
| |
| if not teams_involved: |
| |
| if self.atom_workflow: |
| return await self.atom_workflow.create_workflow(workflow_data) |
| else: |
| return {'ok': False, 'error': 'Workflow service not available'} |
| |
| |
| if teams_workflow_engine: |
| teams_workflow = TeamsWorkflow( |
| id=f"teams_workflow_{int(datetime.utcnow().timestamp())}", |
| name=workflow_data['name'], |
| description=workflow_data.get('description', ''), |
| triggers=[ |
| TeamsWorkflowTrigger(**trigger_data) |
| for trigger_data in workflow_data.get('triggers', []) |
| if trigger_data.get('platform') == 'microsoft_teams' |
| ], |
| actions=[ |
| TeamsWorkflowAction(**action_data) |
| for action_data in workflow_data.get('actions', []) |
| if action_data.get('platform') == 'microsoft_teams' |
| ], |
| created_by=workflow_data.get('created_by', 'system'), |
| created_at=datetime.utcnow(), |
| category=workflow_data.get('category', 'teams'), |
| tags=workflow_data.get('tags', []) |
| ) |
| |
| |
| success = teams_workflow_engine.register_workflow(teams_workflow) |
| |
| if success: |
| return { |
| 'ok': True, |
| 'workflow_id': teams_workflow.id, |
| 'platform': 'microsoft_teams', |
| 'message': 'Teams workflow created successfully' |
| } |
| else: |
| return {'ok': False, 'error': 'Failed to create Teams workflow'} |
| else: |
| return {'ok': False, 'error': 'Teams workflow engine not available'} |
| |
| except Exception as e: |
| logger.error(f"Error creating unified Teams workflow: {e}") |
| return {'ok': False, 'error': str(e)} |
| |
| async def get_unified_analytics(self, metric: str, time_range: str, |
| workspace_id: str = None, options: Dict[str, Any] = None) -> Dict[str, Any]: |
| """Get unified analytics across platforms including Teams""" |
| try: |
| options = options or {} |
| |
| |
| teams_analytics = await self.teams_analytics.get_analytics( |
| metric=metric, |
| time_range=time_range, |
| workspace_id=workspace_id[6:] if workspace_id and workspace_id.startswith('teams_') else None, |
| filters=options.get('filters', {}) |
| ) |
| |
| |
| unified_analytics = { |
| 'platform': 'Microsoft Teams', |
| 'metric': metric, |
| 'time_range': time_range, |
| 'workspace_id': workspace_id, |
| 'data_points': [ |
| { |
| 'timestamp': point.timestamp.isoformat(), |
| 'value': point.value, |
| 'dimensions': point.dimensions, |
| 'metadata': point.metadata |
| } |
| for point in teams_analytics |
| ], |
| 'total_points': len(teams_analytics) |
| } |
| |
| |
| |
| return unified_analytics |
| |
| except Exception as e: |
| logger.error(f"Error getting unified Teams analytics: {e}") |
| return {'ok': False, 'error': str(e)} |
| |
| |
| async def _start_integration_workers(self): |
| """Start background integration workers""" |
| |
| asyncio.create_task(self._teams_message_ingestion_worker()) |
| |
| |
| asyncio.create_task(self._teams_event_processing_worker()) |
| |
| |
| asyncio.create_task(self._unified_search_indexing_worker()) |
| |
| async def _initialize_unified_data(self): |
| """Initialize unified data structures""" |
| |
| if self.atom_memory: |
| try: |
| |
| workspaces_data = await self.atom_memory.query({ |
| 'type': 'unified_workspace', |
| 'platform': 'microsoft_teams' |
| }) |
| |
| |
| channels_data = await self.atom_memory.query({ |
| 'type': 'unified_channel', |
| 'platform': 'microsoft_teams' |
| }) |
| |
| |
| messages_data = await self.atom_memory.query({ |
| 'type': 'unified_message', |
| 'platform': 'microsoft_teams' |
| }) |
| |
| logger.info(f"Loaded unified Teams data: {len(workspaces_data)} workspaces, {len(channels_data)} channels, {len(messages_data)} messages") |
| |
| except Exception as e: |
| logger.error(f"Error loading unified Teams data: {e}") |
| |
| async def _setup_cross_platform_handlers(self): |
| """Setup cross-platform event handlers""" |
| |
| |
| |
| if self.teams_service: |
| self.teams_service.event_handlers[TeamsEventType.MESSAGE].append( |
| self._handle_teams_message_cross_platform |
| ) |
| |
| self.teams_service.event_handlers[TeamsEventType.FILE_UPLOAD].append( |
| self._handle_teams_file_cross_platform |
| ) |
| |
| self.teams_service.event_handlers[TeamsEventType.USER_JOIN].append( |
| self._handle_teams_user_event_cross_platform |
| ) |
| |
| async def _handle_teams_message_cross_platform(self, event_data: Dict[str, Any]): |
| """Handle Teams message cross-platform integration""" |
| try: |
| |
| await self._store_message_in_memory(event_data, 'teams') |
| |
| |
| await self._index_message_in_search(event_data, 'teams') |
| |
| |
| await self._trigger_workflows(event_data, 'teams_message_cross_platform') |
| |
| except Exception as e: |
| logger.error(f"Error handling Teams message cross-platform: {e}") |
| |
| async def _handle_teams_file_cross_platform(self, event_data: Dict[str, Any]): |
| """Handle Teams file cross-platform integration""" |
| try: |
| |
| await self._index_file_in_search(event_data, 'teams') |
| |
| |
| await self._store_file_in_memory(event_data, 'teams') |
| |
| |
| await self._trigger_workflows(event_data, 'teams_file_cross_platform') |
| |
| except Exception as e: |
| logger.error(f"Error handling Teams file cross-platform: {e}") |
| |
| async def _handle_teams_user_event_cross_platform(self, event_data: Dict[str, Any]): |
| """Handle Teams user event cross-platform integration""" |
| try: |
| |
| await self._update_user_profile_cross_platform(event_data, 'teams') |
| |
| |
| await self._trigger_workflows(event_data, 'teams_user_event_cross_platform') |
| |
| except Exception as e: |
| logger.error(f"Error handling Teams user event cross-platform: {e}") |
| |
| async def _store_message_in_memory(self, message_data: Dict[str, Any], platform: str, options: Dict[str, Any] = None): |
| """Store message in unified ATOM memory""" |
| try: |
| if not self.atom_memory: |
| return |
| |
| memory_data = { |
| 'type': 'unified_message', |
| 'platform': platform, |
| 'message_id': message_data.get('message_id'), |
| 'content': message_data.get('text') or message_data.get('content', ''), |
| 'html_content': message_data.get('html'), |
| 'user_id': message_data.get('user_id'), |
| 'user_name': message_data.get('user_name'), |
| 'user_email': message_data.get('user_email'), |
| 'channel_id': message_data.get('channel_id'), |
| 'workspace_id': message_data.get('workspace_id'), |
| 'timestamp': message_data.get('timestamp') or datetime.utcnow().isoformat(), |
| 'importance': message_data.get('importance', 'normal'), |
| 'subject': message_data.get('subject'), |
| 'thread_id': message_data.get('thread_id'), |
| 'reactions': message_data.get('reactions', []), |
| 'attachments': message_data.get('attachments', []), |
| 'mentions': message_data.get('mentions', []), |
| 'files': message_data.get('files', []), |
| 'integration_data': message_data, |
| 'options': options or {}, |
| 'indexed': False, |
| 'synced': True |
| } |
| |
| await self.atom_memory.store(memory_data) |
| |
| except Exception as e: |
| logger.error(f"Error storing Teams message in unified memory: {e}") |
| |
| async def _index_message_in_search(self, message_data: Dict[str, Any], platform: str, options: Dict[str, Any] = None): |
| """Index message in unified ATOM search""" |
| try: |
| if not self.atom_search: |
| return |
| |
| search_data = { |
| 'type': 'unified_message', |
| 'platform': platform, |
| 'id': f"{platform}_{message_data.get('message_id')}", |
| 'title': message_data.get('subject') or f"Message from {message_data.get('user_name', 'Unknown')}", |
| 'content': message_data.get('text') or message_data.get('content', ''), |
| 'metadata': { |
| 'user_id': message_data.get('user_id'), |
| 'user_name': message_data.get('user_name'), |
| 'user_email': message_data.get('user_email'), |
| 'channel_id': message_data.get('channel_id'), |
| 'workspace_id': message_data.get('workspace_id'), |
| 'timestamp': message_data.get('timestamp') or datetime.utcnow().isoformat(), |
| 'importance': message_data.get('importance', 'normal'), |
| 'platform': platform, |
| 'has_thread': bool(message_data.get('thread_id')), |
| 'has_attachments': bool(message_data.get('attachments')), |
| 'has_mentions': bool(message_data.get('mentions')), |
| 'integration_data': message_data |
| } |
| } |
| |
| await self.atom_search.index(search_data) |
| |
| except Exception as e: |
| logger.error(f"Error indexing Teams message in unified search: {e}") |
| |
| async def _trigger_workflows(self, event_data: Dict[str, Any], event_type: str, options: Dict[str, Any] = None): |
| """Trigger workflows for cross-platform events""" |
| try: |
| if not self.atom_workflow: |
| return |
| |
| workflow_trigger = { |
| 'event_type': event_type, |
| 'platform': 'microsoft_teams', |
| 'data': event_data, |
| 'timestamp': datetime.utcnow().isoformat(), |
| 'options': options or {} |
| } |
| |
| await self.atom_workflow.trigger_workflows(workflow_trigger) |
| |
| except Exception as e: |
| logger.error(f"Error triggering workflows for Teams event: {e}") |
| |
| def _generate_search_highlights(self, content: str, query: str) -> List[str]: |
| """Generate search highlights for Teams message content""" |
| try: |
| import re |
| highlights = [] |
| |
| |
| query_words = query.lower().split() |
| words = content.split() |
| |
| for i, word in enumerate(words): |
| if any(qword in word.lower() for qword in query_words): |
| |
| start = max(0, i - 3) |
| end = min(len(words), i + 4) |
| context = ' '.join(words[start:end]) |
| highlights.append(context) |
| |
| return list(set(highlights))[:3] |
| |
| except Exception: |
| return [] |
| |
| |
| async def _teams_message_ingestion_worker(self): |
| """Background worker for Teams message ingestion""" |
| while True: |
| try: |
| |
| |
| await asyncio.sleep(30) |
| |
| except Exception as e: |
| logger.error(f"Error in Teams message ingestion worker: {e}") |
| await asyncio.sleep(60) |
| |
| async def _teams_event_processing_worker(self): |
| """Background worker for Teams event processing""" |
| while True: |
| try: |
| |
| |
| await asyncio.sleep(10) |
| |
| except Exception as e: |
| logger.error(f"Error in Teams event processing worker: {e}") |
| await asyncio.sleep(30) |
| |
| async def _unified_search_indexing_worker(self): |
| """Background worker for unified search indexing""" |
| while True: |
| try: |
| |
| if self.atom_search and self.atom_memory: |
| unindexed_messages = await self.atom_memory.query({ |
| 'type': 'unified_message', |
| 'platform': 'microsoft_teams', |
| 'indexed': False |
| }) |
| |
| for message in unindexed_messages: |
| await self._index_message_in_search(message, 'teams') |
| await self.atom_memory.update(message['id'], {'indexed': True}) |
| |
| await asyncio.sleep(60) |
| |
| except Exception as e: |
| logger.error(f"Error in unified search indexing worker: {e}") |
| await asyncio.sleep(120) |
|
|
| |
| atom_teams_integration = AtomTeamsIntegration({ |
| 'atom_memory_service': None, |
| 'atom_search_service': None, |
| 'atom_workflow_service': None, |
| 'atom_ingestion_pipeline': None |
| }) |