|
|
|
|
|
import requests |
|
import sys |
|
from typing import Dict, Any |
|
|
|
API_BASE = "http://127.0.0.1:8000/api/v1" |
|
|
|
class EmailQueryCLI: |
|
def __init__(self): |
|
self.session = requests.Session() |
|
|
|
def check_connection(self) -> bool: |
|
"""Check if API server is running""" |
|
try: |
|
response = self.session.get(f"{API_BASE}/health") |
|
response.raise_for_status() |
|
return True |
|
except: |
|
return False |
|
|
|
def pretty_print_email(self, email: Dict) -> str: |
|
"""Format email for display""" |
|
return f""" |
|
π§ {email['subject']} |
|
π
{email['date']} {email['time']} |
|
π¬ {email['content'][:200]}... |
|
π {email['message_id'][:20]}... |
|
{"β" * 60}""" |
|
|
|
def handle_query(self, query: str): |
|
"""Handle a natural language query""" |
|
print(f"\nπ Processing: '{query}'") |
|
|
|
try: |
|
|
|
response = self.session.post( |
|
f"{API_BASE}/get_emails", |
|
json={"query": query} |
|
) |
|
|
|
if response.status_code == 200: |
|
data = response.json() |
|
self.display_email_results(data) |
|
return True |
|
|
|
elif response.status_code == 400: |
|
error_detail = response.json()["detail"] |
|
|
|
|
|
if isinstance(error_detail, dict) and error_detail.get("type") == "need_email_input": |
|
mapping_success = self.handle_missing_mapping(error_detail) |
|
if mapping_success and hasattr(self, '_retry_query'): |
|
|
|
print(f"π Retrying query...") |
|
delattr(self, '_retry_query') |
|
return self.handle_query(query) |
|
return mapping_success |
|
else: |
|
print(f"β Error: {error_detail}") |
|
return False |
|
else: |
|
print(f"β API Error: {response.status_code}") |
|
return False |
|
|
|
except Exception as e: |
|
print(f"β Connection Error: {e}") |
|
return False |
|
|
|
def handle_missing_mapping(self, error_detail: Dict) -> bool: |
|
"""Handle case where email mapping is needed""" |
|
sender_intent = error_detail["sender_intent"] |
|
print(f"\nβ {error_detail['message']}") |
|
|
|
try: |
|
email = input(f"π§ Enter email for '{sender_intent}': ").strip() |
|
if not email or "@" not in email: |
|
print("β Invalid email address") |
|
return False |
|
|
|
|
|
mapping_response = self.session.post( |
|
f"{API_BASE}/add_email_mapping", |
|
json={"name": sender_intent, "email": email} |
|
) |
|
|
|
if mapping_response.status_code == 200: |
|
print(f"β
Mapping saved: '{sender_intent}' β '{email}'") |
|
self._retry_query = True |
|
return True |
|
else: |
|
print(f"β Failed to save mapping: {mapping_response.text}") |
|
return False |
|
|
|
except KeyboardInterrupt: |
|
print("\nβ Cancelled") |
|
return False |
|
|
|
def display_email_results(self, data: Dict): |
|
"""Display email search results""" |
|
print(f"\nβ
Found {data['total_emails']} emails") |
|
print(f"π€ From: {data['resolved_email']}") |
|
print(f"π
Period: {data['start_date']} to {data['end_date']}") |
|
|
|
if data['emails']: |
|
print(f"\nπ§ Emails:") |
|
for email in data['emails'][:10]: |
|
print(self.pretty_print_email(email)) |
|
|
|
if len(data['emails']) > 10: |
|
print(f"\n... and {len(data['emails']) - 10} more emails") |
|
else: |
|
print("\nπ No emails found in this date range") |
|
|
|
def show_mappings(self): |
|
"""Display all stored name-to-email mappings""" |
|
try: |
|
response = self.session.get(f"{API_BASE}/view_mappings") |
|
if response.status_code == 200: |
|
data = response.json() |
|
mappings = data["mappings"] |
|
|
|
print(f"\nπ Stored Mappings ({len(mappings)}):") |
|
if mappings: |
|
for name, email in mappings.items(): |
|
print(f" π€ {name} β π§ {email}") |
|
else: |
|
print(" (No mappings stored)") |
|
else: |
|
print(f"β Failed to load mappings: {response.text}") |
|
except Exception as e: |
|
print(f"β Error: {e}") |
|
|
|
def run(self): |
|
"""Main CLI loop""" |
|
if not self.check_connection(): |
|
print("β Cannot connect to API server at http://127.0.0.1:8000") |
|
print(" Make sure to run: uvicorn main:app --reload") |
|
sys.exit(1) |
|
|
|
print("β
Connected to Email Query System") |
|
print("π‘ Try queries like:") |
|
print(" β’ 'emails from john last week'") |
|
print(" β’ 'show amazon emails from last month'") |
|
print(" β’ 'get [email protected] emails yesterday'") |
|
print("\nπ Commands:") |
|
print(" β’ 'mappings' - View stored name-to-email mappings") |
|
print(" β’ 'quit' or Ctrl+C - Exit") |
|
print("=" * 60) |
|
|
|
while True: |
|
try: |
|
query = input("\nπ¨οΈ You: ").strip() |
|
|
|
if not query: |
|
continue |
|
|
|
if query.lower() in ['quit', 'exit', 'q']: |
|
break |
|
elif query.lower() in ['mappings', 'map', 'm']: |
|
self.show_mappings() |
|
elif query.lower() in ['help', 'h']: |
|
print("\nπ‘ Examples:") |
|
print(" β’ emails from amazon last 5 days") |
|
print(" β’ show john smith emails this week") |
|
print(" β’ get notifications from google yesterday") |
|
else: |
|
self.handle_query(query) |
|
|
|
except KeyboardInterrupt: |
|
break |
|
except Exception as e: |
|
print(f"β Unexpected error: {e}") |
|
|
|
print("\nπ Goodbye!") |
|
|
|
def main(): |
|
"""Entry point for CLI""" |
|
cli = EmailQueryCLI() |
|
cli.run() |
|
|
|
if __name__ == "__main__": |
|
main() |