Spaces:
Sleeping
Sleeping
| """ | |
| GitHub Integration for Support Tickets | |
| """ | |
| import os | |
| import logging | |
| from typing import Dict, Any, Optional, List | |
| from github import Github, GithubException, Auth | |
| from config import GITHUB_TOKEN, GITHUB_REPO | |
| class GitHubSupport: | |
| """Handles GitHub issue creation for support tickets""" | |
| def __init__(self, token: Optional[str] = None, repo_name: Optional[str] = None, folder: Optional[str] = None): | |
| self.token = token or GITHUB_TOKEN | |
| self.repo_name = repo_name or GITHUB_REPO | |
| self.folder = folder or os.getenv("GITHUB_FOLDER", "") | |
| self.logger = logging.getLogger(__name__) | |
| self.github = None | |
| self.repo = None | |
| if self.token and self.repo_name: | |
| try: | |
| # Use Auth.Token for authentication | |
| auth = Auth.Token(self.token) | |
| self.github = Github(auth=auth) | |
| self.repo = self.github.get_repo(self.repo_name) | |
| self.logger.info(f"GitHub integration initialized for repo: {self.repo_name}") | |
| except Exception as e: | |
| self.logger.warning(f"GitHub initialization failed: {e}") | |
| def is_configured(self) -> bool: | |
| """Check if GitHub integration is properly configured""" | |
| return self.github is not None and self.repo is not None | |
| def _ensure_label_exists(self, label_name: str, color: str = "0075ca"): | |
| """Ensures a label exists in the repository, creates it if it doesn't""" | |
| if not self.repo: | |
| return | |
| try: | |
| self.repo.get_label(label_name) | |
| except GithubException: | |
| try: | |
| self.repo.create_label(name=label_name, color=color) | |
| self.logger.info(f"Created new label: {label_name}") | |
| except Exception as e: | |
| self.logger.warning(f"Could not create label {label_name}: {e}") | |
| def create_issue( | |
| self, | |
| title: str, | |
| body: str, | |
| labels: Optional[List[str]] = None | |
| ) -> Dict[str, Any]: | |
| """ | |
| Create a GitHub issue as a support ticket | |
| Args: | |
| title: Issue title | |
| body: Issue description | |
| labels: Optional list of labels to add | |
| Returns: | |
| Dictionary with success status and issue details | |
| """ | |
| if not self.is_configured(): | |
| self.logger.warning("GitHub not configured, using mock mode") | |
| return self._create_mock_ticket(title, body, labels) | |
| try: | |
| issue_labels = [] | |
| # 1. Handle folder label and title decoration | |
| if self.folder: | |
| folder_label = self.folder.lower().replace("/", "-").replace(" ", "-") | |
| self._ensure_label_exists(folder_label, "0075ca") # Blue | |
| issue_labels.append(folder_label) | |
| # Decorate title | |
| prefixed_title = f"[{self.folder}] {title}" | |
| # Add details to body | |
| full_body = f"**Project:** {self.folder}\n\n**Description:**\n{body}" | |
| else: | |
| prefixed_title = title | |
| full_body = body | |
| # 2. Add customer-support label (ensure it exists) | |
| self._ensure_label_exists("customer-support", "d73a4a") # Reddish | |
| issue_labels.append("customer-support") | |
| # 3. Add any additional labels provided | |
| if labels: | |
| for label in labels: | |
| if label not in issue_labels: | |
| # Ensure these labels exist too | |
| self._ensure_label_exists(label, "e6e6e6") # Light gray | |
| issue_labels.append(label) | |
| # Create the issue | |
| issue = self.repo.create_issue( | |
| title=prefixed_title, | |
| body=full_body, | |
| labels=issue_labels | |
| ) | |
| self.logger.info(f"Created GitHub issue #{issue.number}: {prefixed_title}") | |
| return { | |
| "success": True, | |
| "message": f"Ticket created successfully! Ticket ID: #{issue.number}", | |
| "issue_number": issue.number, | |
| "issue_url": issue.html_url, | |
| "title": prefixed_title | |
| } | |
| except GithubException as e: | |
| # Handle Validation Failed with more detail | |
| error_data = getattr(e, 'data', {}) | |
| error_msg = error_data.get('message', str(e)) | |
| errors = error_data.get('errors', []) | |
| full_error = f"GitHub API error: {error_msg}" | |
| if errors: | |
| full_error += f" - Details: {str(errors)}" | |
| self.logger.error(full_error) | |
| return { | |
| "success": False, | |
| "error": full_error | |
| } | |
| except Exception as e: | |
| error_msg = f"Error creating issue: {str(e)}" | |
| self.logger.error(error_msg) | |
| return { | |
| "success": False, | |
| "error": error_msg | |
| } | |
| except Exception as e: | |
| error_msg = f"Error creating issue: {str(e)}" | |
| self.logger.error(error_msg) | |
| return { | |
| "success": False, | |
| "error": error_msg | |
| } | |
| def _create_mock_ticket( | |
| self, | |
| title: str, | |
| body: str, | |
| labels: Optional[List[str]] = None | |
| ) -> Dict[str, Any]: | |
| """Create a mock support ticket when GitHub is not configured""" | |
| import random | |
| mock_id = f"MOCK-{random.randint(1000, 9999)}" | |
| self.logger.info(f"Created mock support ticket: {mock_id}") | |
| return { | |
| "success": True, | |
| "message": "Support ticket created (Mock Mode - GitHub not configured)", | |
| "ticket_id": mock_id, | |
| "title": title, | |
| "labels": labels or [], | |
| "note": "To enable real GitHub integration, set GITHUB_TOKEN and GITHUB_REPO in your .env file" | |
| } | |