| from typing import Dict |
| from services.ai_service import ai_service |
| from services.mcp_service import mcp_service |
| from utils.json_parser import JSONParser |
| from utils.error_handler import StandardAPIResponse, handle_service_error |
| from prompts.challenge_prompts import ChallengePrompts |
| from tools.email_tool import send_email |
| import logging |
|
|
| logger = logging.getLogger(__name__) |
|
|
| class ChallengeService: |
| """Centralized service for Topcoder challenge operations""" |
| |
| def __init__(self): |
| self.ai_service = ai_service |
| self.mcp_service = mcp_service |
| self.json_parser = JSONParser() |
| |
| def get_challenges_dry_run(self, preferences: str) -> Dict: |
| """ |
| Get challenges for dry run (immediate response without sending emails) |
| |
| Args: |
| preferences: User preferences for filtering challenges |
| |
| Returns: |
| Standardized response dictionary |
| """ |
| try: |
| logger.info(f"Getting challenges for dry run with preferences: {preferences}") |
| |
| |
| topcoder_client = self.mcp_service.create_topcoder_client() |
| |
| with topcoder_client: |
| |
| mcp_tools = self.mcp_service.get_topcoder_tools(topcoder_client) |
| |
| if not mcp_tools: |
| return StandardAPIResponse.error( |
| "No Topcoder MCP tools available", |
| status_code=503, |
| error_code="MCP_UNAVAILABLE" |
| ) |
| |
| |
| system_prompt = ChallengePrompts.get_dry_run_prompt(preferences) |
| agent = self.ai_service.create_agent(mcp_tools, system_prompt) |
| |
| |
| user_query = f""" |
| Please help me find Topcoder challenges that match my preferences: |
| |
| User Preferences: {preferences if preferences else "No specific preferences - show all relevant challenges"} |
| |
| Please: |
| 1. Query Topcoder challenges that are currently active |
| 2. Filter or prioritize challenges that match my preferences |
| 3. Return the results in the specified JSON format |
| """ |
| |
| |
| response = agent(user_query) |
| logger.info(f"Agent response: {response}") |
| |
| |
| parsed_data = self.json_parser.extract_json_from_response(str(response)) |
| |
| if parsed_data is None: |
| return StandardAPIResponse.error( |
| "Could not extract JSON from response", |
| status_code=500, |
| error_code="JSON_PARSE_ERROR" |
| ) |
| |
| |
| if "challenges" in parsed_data: |
| challenges = self.json_parser.normalize_challenges(parsed_data["challenges"]) |
| else: |
| challenges = self.json_parser.normalize_challenges(parsed_data) |
| |
| return StandardAPIResponse.success( |
| data={"challenges": challenges}, |
| message=f"Found {len(challenges)} challenge{'s' if len(challenges) != 1 else ''}", |
| metadata={"preferences": preferences} |
| ) |
| |
| except Exception as e: |
| return handle_service_error(e, "get challenges for dry run", preferences) |
| |
| def process_challenges_for_user(self, user_id: str, email: str, preferences: str) -> Dict: |
| """ |
| Process challenges for automated agent (email notifications) |
| |
| Args: |
| user_id: User ID from database |
| email: User email address |
| preferences: User preferences |
| |
| Returns: |
| Processing result dictionary |
| """ |
| result = { |
| "challenges_found": 0, |
| "notifications_sent": 0, |
| "status": "completed", |
| "error_message": None |
| } |
| |
| try: |
| logger.info(f"Processing challenges for user {email} with preferences: {preferences}") |
| |
| |
| topcoder_client = self.mcp_service.create_topcoder_client() |
| |
| with topcoder_client: |
| |
| mcp_tools = self.mcp_service.get_topcoder_tools(topcoder_client) |
| |
| if not mcp_tools: |
| result["status"] = "failed" |
| result["error_message"] = "No Topcoder MCP tools available" |
| return result |
| |
| |
| all_tools = [send_email] + mcp_tools |
| |
| |
| system_prompt = ChallengePrompts.get_agent_prompt(preferences, email) |
| agent = self.ai_service.create_agent(all_tools, system_prompt) |
| |
| |
| user_query = f""" |
| Please help me find and notify about relevant Topcoder challenges: |
| |
| User Email: {email} |
| User Preferences: {preferences if preferences else "No specific preferences - show high-value challenges"} |
| |
| Steps to follow: |
| 1. Query Topcoder for active challenges |
| 2. Filter challenges based on user preferences |
| 3. If relevant challenges found, send a professional email notification |
| 4. The email should include challenge details, prizes, and registration links |
| |
| IMPORTANT: Only send email if there are genuinely relevant challenges that match the user's preferences. |
| """ |
| |
| |
| response = agent(user_query) |
| logger.info(f"Agent response for {email}: {response}") |
| |
| |
| result["notifications_sent"] = 0 |
| |
| except Exception as e: |
| logger.error(f"Error processing challenges for {email}: {e}") |
| result["status"] = "failed" |
| result["error_message"] = str(e) |
| |
| return result |
| |
|
|
| |
| challenge_service = ChallengeService() |
|
|