Search GitHub for a username, email, or keyword. GITHUB_TOKEN increases rate limits.
(query: str, timeout_seconds: int = _DEFAULT_TIMEOUT)
| 126 | |
| 127 | |
| 128 | async def run_github_osint(query: str, timeout_seconds: int = _DEFAULT_TIMEOUT) -> str: |
| 129 | """Search GitHub for a username, email, or keyword. GITHUB_TOKEN increases rate limits.""" |
| 130 | query = query.strip() |
| 131 | if not query: |
| 132 | return "Error: query cannot be empty." |
| 133 | |
| 134 | token = os.environ.get("GITHUB_TOKEN") or None |
| 135 | timeout_cfg = aiohttp.ClientTimeout(total=timeout_seconds) |
| 136 | |
| 137 | try: |
| 138 | async with aiohttp.ClientSession( |
| 139 | headers=_build_headers(token), |
| 140 | timeout=timeout_cfg, |
| 141 | ) as session: |
| 142 | user = await _fetch_user(session, query) |
| 143 | if user: |
| 144 | repos = await _fetch_repos(session, query) |
| 145 | emails = await _discover_emails(session, query, repos) |
| 146 | return _format_profile(user, repos, emails) |
| 147 | |
| 148 | users = await _search_users(session, query) |
| 149 | if not users: |
| 150 | return f"[GitHub] No users found for query: '{query}'." |
| 151 | |
| 152 | lines = [f"[GitHub] Search results for '{query}' ({len(users)} match(es)):"] |
| 153 | for u in users: |
| 154 | lines.append( |
| 155 | f" • {u.get('login')} — {u.get('html_url')} (type: {u.get('type', '?')})" |
| 156 | ) |
| 157 | return "\n".join(lines) |
| 158 | |
| 159 | except asyncio.TimeoutError: |
| 160 | return f"Scan error: GitHub request timed out after {timeout_seconds}s." |
| 161 | except aiohttp.ClientResponseError as exc: |
| 162 | if exc.status == 403: |
| 163 | return "Scan error: GitHub rate limit exceeded. Set GITHUB_TOKEN for higher limits." |
| 164 | if exc.status == 401: |
| 165 | return "Scan error: Invalid GITHUB_TOKEN." |
| 166 | return f"Scan error: GitHub API error HTTP {exc.status}." |
| 167 | except aiohttp.ClientError as exc: |
| 168 | return f"Scan error: Network error querying GitHub: {exc}" |
| 169 | except Exception as exc: |
| 170 | logger.exception("Unexpected error during GitHub lookup.") |
| 171 | return f"Internal error: {exc}" |
no test coverage detected