| | from typing import Dict, List, Any, Optional, Union |
| | import pandas as pd |
| | import smtplib |
| | from email.mime.multipart import MIMEMultipart |
| | from email.mime.text import MIMEText |
| | from email.mime.image import MIMEImage |
| | import base64 |
| | import io |
| | from pathlib import Path |
| | import json |
| | import datetime |
| |
|
| | class ExportTools: |
| | """Tools for exporting data, generating reports, and sending emails.""" |
| | |
| | def __init__(self, output_directory: str = "./exports"): |
| | """Initialize with directory for saved exports.""" |
| | self.output_directory = Path(output_directory) |
| | self.output_directory.mkdir(exist_ok=True, parents=True) |
| | |
| | def get_tools(self) -> List[Dict[str, Any]]: |
| | """Get all available export tools.""" |
| | tools = [ |
| | { |
| | "name": "generate_report", |
| | "description": "Generate a report from conversation and results", |
| | "function": self.generate_report |
| | }, |
| | { |
| | "name": "save_results_to_csv", |
| | "description": "Save query results to a CSV file", |
| | "function": self.save_results_to_csv |
| | }, |
| | { |
| | "name": "send_email", |
| | "description": "Send results via email", |
| | "function": self.send_email |
| | } |
| | ] |
| | return tools |
| | |
| | def generate_report(self, title: str, content: str, |
| | images: List[str] = None) -> Dict[str, Any]: |
| | """Generate HTML report from content and images.""" |
| | timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S") |
| | filename = f"{title.replace(' ', '_')}_{timestamp}.html" |
| | file_path = self.output_directory / filename |
| | |
| | |
| | html = f""" |
| | <!DOCTYPE html> |
| | <html> |
| | <head> |
| | <title>{title}</title> |
| | <style> |
| | body {{ font-family: Arial, sans-serif; margin: 40px; line-height: 1.6; }} |
| | h1 {{ color: #333366; }} |
| | .report-container {{ max-width: 800px; margin: 0 auto; }} |
| | .timestamp {{ color: #666; font-size: 0.8em; }} |
| | img {{ max-width: 100%; height: auto; margin: 20px 0; }} |
| | </style> |
| | </head> |
| | <body> |
| | <div class="report-container"> |
| | <h1>{title}</h1> |
| | <div class="timestamp">Generated on: {datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")}</div> |
| | <div class="content"> |
| | {content.replace(chr(10), '<br>')} |
| | </div> |
| | """ |
| | |
| | |
| | if images and len(images) > 0: |
| | html += "<div class='images'>" |
| | for i, img_base64 in enumerate(images): |
| | html += f"<img src='data:image/png;base64,{img_base64}' alt='Figure {i+1}'>" |
| | html += "</div>" |
| | |
| | html += """ |
| | </div> |
| | </body> |
| | </html> |
| | """ |
| | |
| | |
| | with open(file_path, "w", encoding="utf-8") as f: |
| | f.write(html) |
| | |
| | return { |
| | "success": True, |
| | "report_path": str(file_path), |
| | "title": title, |
| | "timestamp": timestamp |
| | } |
| | |
| | def save_results_to_csv(self, data: List[Dict[str, Any]], |
| | filename: str = None) -> Dict[str, Any]: |
| | """Save query results to a CSV file.""" |
| | if not data or len(data) == 0: |
| | return {"success": False, "error": "No data provided"} |
| | |
| | |
| | df = pd.DataFrame(data) |
| | |
| | |
| | if not filename: |
| | timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S") |
| | filename = f"query_results_{timestamp}.csv" |
| | |
| | |
| | if not filename.lower().endswith('.csv'): |
| | filename += '.csv' |
| | |
| | file_path = self.output_directory / filename |
| | |
| | |
| | df.to_csv(file_path, index=False) |
| | |
| | return { |
| | "success": True, |
| | "file_path": str(file_path), |
| | "row_count": len(df), |
| | "column_count": len(df.columns) |
| | } |
| | |
| | def send_email(self, to_email: str, subject: str, body: str, |
| | from_email: str = None, smtp_server: str = None, |
| | smtp_port: int = 587, username: str = None, |
| | password: str = None, images: List[str] = None) -> Dict[str, Any]: |
| | """ |
| | Send email with results. |
| | Note: In production, credentials should be securely managed. |
| | For demo purposes, this will log the email content instead. |
| | """ |
| | |
| | |
| | |
| | email_content = { |
| | "to": to_email, |
| | "subject": subject, |
| | "body": body[:100] + "..." if len(body) > 100 else body, |
| | "images": f"{len(images) if images else 0} images would be attached", |
| | "note": "Email sending is simulated for demo purposes" |
| | } |
| | |
| | |
| | print(f"SIMULATED EMAIL: {json.dumps(email_content, indent=2)}") |
| | |
| | return { |
| | "success": True, |
| | "to": to_email, |
| | "subject": subject, |
| | "simulated": True, |
| | "timestamp": datetime.datetime.now().isoformat() |
| | } |
| |
|