mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-04-26 01:06:23 +02:00
254 lines
8.7 KiB
Python
254 lines
8.7 KiB
Python
"""
|
|
Microsoft Teams History Module
|
|
|
|
A module for retrieving conversation history from Microsoft Teams channels.
|
|
Allows fetching team lists, channel lists, and message history with date range filtering.
|
|
"""
|
|
|
|
import logging
|
|
from datetime import datetime
|
|
from typing import Any
|
|
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
|
|
from app.connectors.teams_connector import TeamsConnector
|
|
from app.schemas.teams_auth_credentials import TeamsAuthCredentialsBase
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
class TeamsHistory:
|
|
"""Class for retrieving conversation history from Microsoft Teams channels."""
|
|
|
|
def __init__(
|
|
self,
|
|
access_token: str | None = None,
|
|
session: AsyncSession | None = None,
|
|
connector_id: int | None = None,
|
|
credentials: TeamsAuthCredentialsBase | None = None,
|
|
):
|
|
"""
|
|
Initialize the TeamsHistory class.
|
|
|
|
Args:
|
|
access_token: Microsoft Graph API access token (optional, for backward compatibility)
|
|
session: Database session for token refresh (optional)
|
|
connector_id: Connector ID for token refresh (optional)
|
|
credentials: Teams OAuth credentials (optional, will be loaded from DB if not provided)
|
|
"""
|
|
self.connector = TeamsConnector(
|
|
access_token=access_token,
|
|
session=session,
|
|
connector_id=connector_id,
|
|
credentials=credentials,
|
|
)
|
|
|
|
async def get_all_teams(self) -> list[dict[str, Any]]:
|
|
"""
|
|
Get list of all teams the user has access to.
|
|
|
|
Returns:
|
|
List of team objects containing team metadata.
|
|
"""
|
|
try:
|
|
teams = await self.connector.get_joined_teams()
|
|
logger.info("Retrieved %s teams", len(teams))
|
|
return teams
|
|
except Exception as e:
|
|
logger.error("Error fetching teams: %s", str(e))
|
|
raise
|
|
|
|
async def get_channels_for_team(self, team_id: str) -> list[dict[str, Any]]:
|
|
"""
|
|
Get list of all channels in a specific team.
|
|
|
|
Args:
|
|
team_id: The ID of the team
|
|
|
|
Returns:
|
|
List of channel objects containing channel metadata.
|
|
"""
|
|
try:
|
|
channels = await self.connector.get_team_channels(team_id)
|
|
logger.info("Retrieved %s channels for team %s", len(channels), team_id)
|
|
return channels
|
|
except Exception as e:
|
|
logger.error("Error fetching channels for team %s: %s", team_id, str(e))
|
|
raise
|
|
|
|
async def get_messages_from_channel(
|
|
self,
|
|
team_id: str,
|
|
channel_id: str,
|
|
start_date: datetime | None = None,
|
|
end_date: datetime | None = None,
|
|
include_replies: bool = True,
|
|
) -> list[dict[str, Any]]:
|
|
"""
|
|
Get messages from a specific channel with optional date filtering.
|
|
|
|
Args:
|
|
team_id: The ID of the team
|
|
channel_id: The ID of the channel
|
|
start_date: Optional start date for filtering messages
|
|
end_date: Optional end date for filtering messages
|
|
include_replies: Whether to include reply messages (default: True)
|
|
|
|
Returns:
|
|
List of message objects with content and metadata.
|
|
"""
|
|
try:
|
|
messages = await self.connector.get_channel_messages(
|
|
team_id, channel_id, start_date, end_date
|
|
)
|
|
|
|
logger.info(
|
|
"Retrieved %s messages from channel %s in team %s",
|
|
len(messages),
|
|
channel_id,
|
|
team_id,
|
|
)
|
|
|
|
# Fetch replies if requested
|
|
if include_replies:
|
|
all_messages = []
|
|
for message in messages:
|
|
all_messages.append(message)
|
|
# Get replies for this message
|
|
try:
|
|
replies = await self.connector.get_message_replies(
|
|
team_id, channel_id, message.get("id")
|
|
)
|
|
all_messages.extend(replies)
|
|
except Exception:
|
|
logger.warning(
|
|
"Failed to get replies for message %s",
|
|
message.get("id"),
|
|
exc_info=True,
|
|
)
|
|
# Continue without replies for this message
|
|
|
|
logger.info(
|
|
"Total messages including replies: %s for channel %s",
|
|
len(all_messages),
|
|
channel_id,
|
|
)
|
|
return all_messages
|
|
|
|
return messages
|
|
|
|
except Exception as e:
|
|
logger.error(
|
|
"Error fetching messages from channel %s in team %s: %s",
|
|
channel_id,
|
|
team_id,
|
|
str(e),
|
|
)
|
|
raise
|
|
|
|
async def get_all_messages_from_team(
|
|
self,
|
|
team_id: str,
|
|
start_date: datetime | None = None,
|
|
end_date: datetime | None = None,
|
|
include_replies: bool = True,
|
|
) -> dict[str, list[dict[str, Any]]]:
|
|
"""
|
|
Get all messages from all channels in a team.
|
|
|
|
Args:
|
|
team_id: The ID of the team
|
|
start_date: Optional start date for filtering messages
|
|
end_date: Optional end date for filtering messages
|
|
include_replies: Whether to include reply messages (default: True)
|
|
|
|
Returns:
|
|
Dictionary mapping channel IDs to lists of messages.
|
|
"""
|
|
try:
|
|
channels = await self.get_channels_for_team(team_id)
|
|
all_channel_messages = {}
|
|
|
|
for channel in channels:
|
|
channel_id = channel.get("id")
|
|
channel_name = channel.get("displayName", "Unknown")
|
|
|
|
try:
|
|
messages = await self.get_messages_from_channel(
|
|
team_id, channel_id, start_date, end_date, include_replies
|
|
)
|
|
all_channel_messages[channel_id] = messages
|
|
logger.info(
|
|
"Fetched %s messages from channel '%s' (%s)",
|
|
len(messages),
|
|
channel_name,
|
|
channel_id,
|
|
)
|
|
except Exception:
|
|
logger.error(
|
|
"Failed to fetch messages from channel '%s' (%s)",
|
|
channel_name,
|
|
channel_id,
|
|
exc_info=True,
|
|
)
|
|
all_channel_messages[channel_id] = []
|
|
|
|
return all_channel_messages
|
|
|
|
except Exception as e:
|
|
logger.error("Error fetching messages from team %s: %s", team_id, str(e))
|
|
raise
|
|
|
|
async def get_all_messages(
|
|
self,
|
|
start_date: datetime | None = None,
|
|
end_date: datetime | None = None,
|
|
include_replies: bool = True,
|
|
) -> dict[str, dict[str, list[dict[str, Any]]]]:
|
|
"""
|
|
Get all messages from all teams and channels the user has access to.
|
|
|
|
Args:
|
|
start_date: Optional start date for filtering messages
|
|
end_date: Optional end date for filtering messages
|
|
include_replies: Whether to include reply messages (default: True)
|
|
|
|
Returns:
|
|
Nested dictionary: team_id -> channel_id -> list of messages.
|
|
"""
|
|
try:
|
|
teams = await self.get_all_teams()
|
|
all_messages = {}
|
|
|
|
for team in teams:
|
|
team_id = team.get("id")
|
|
team_name = team.get("displayName", "Unknown")
|
|
|
|
try:
|
|
team_messages = await self.get_all_messages_from_team(
|
|
team_id, start_date, end_date, include_replies
|
|
)
|
|
all_messages[team_id] = team_messages
|
|
total_messages = sum(
|
|
len(messages) for messages in team_messages.values()
|
|
)
|
|
logger.info(
|
|
"Fetched %s total messages from team '%s' (%s)",
|
|
total_messages,
|
|
team_name,
|
|
team_id,
|
|
)
|
|
except Exception:
|
|
logger.error(
|
|
"Failed to fetch messages from team '%s' (%s)",
|
|
team_name,
|
|
team_id,
|
|
exc_info=True,
|
|
)
|
|
all_messages[team_id] = {}
|
|
|
|
return all_messages
|
|
|
|
except Exception as e:
|
|
logger.error("Error fetching all messages: %s", str(e))
|
|
raise
|