(interaction: discord.Interaction, result: dict, max_results: int = 10, display_mode: str = "full")
| 182 | logger.error(f"Failed to send followup: {followup_error}") |
| 183 | |
| 184 | async def process_shodan_results(interaction: discord.Interaction, result: dict, max_results: int = 10, display_mode: str = "full"): |
| 185 | user = interaction.user.name |
| 186 | guild_name = interaction.guild.name if interaction.guild else "Direct Message" |
| 187 | command_name = interaction.data.get("name", "unknown_command") |
| 188 | options = ", ".join([f"{option.get('name')}: {option.get('value')}" for option in interaction.data.get("options", [])]) |
| 189 | |
| 190 | logger.info(f"{user} executed /{command_name} from {guild_name}. Options used: {options}") |
| 191 | |
| 192 | print(f"{user} executed /{command_name} from {guild_name}. Options used: {options}") |
| 193 | |
| 194 | matches = result.get('matches', []) |
| 195 | if matches: |
| 196 | total = result.get('total', 0) |
| 197 | info = f"Found {total} results. Here are the top results:\n\n" |
| 198 | |
| 199 | # For list mode, send each IP link and screenshot immediately |
| 200 | if display_mode == "easy": |
| 201 | for match in matches[:max_results]: |
| 202 | ip = match.get('ip_str', 'No IP available.') |
| 203 | port = match.get('port', 'No port available.') |
| 204 | |
| 205 | # Format IP link |
| 206 | clickable_link = f"[{ip}:{port}](http://{ip}:{port})\n" |
| 207 | await interaction.followup.send(clickable_link, ephemeral=True) |
| 208 | |
| 209 | # Handle screenshot if available |
| 210 | screenshot_data = match.get('screenshot', {}).get('data') |
| 211 | if screenshot_data: |
| 212 | screenshot_bytes = base64.b64decode(screenshot_data) |
| 213 | screenshot_file = io.BytesIO(screenshot_bytes) |
| 214 | await interaction.followup.send(file=discord.File(screenshot_file, filename=f'screenshot_{ip}.jpg')) |
| 215 | return |
| 216 | |
| 217 | # If display mode is full |
| 218 | responses = [] # Initialize the responses list |
| 219 | for match in matches[:max_results]: |
| 220 | detailed_info = generate_detailed_info(match) |
| 221 | responses.append(detailed_info) |
| 222 | |
| 223 | message = info + "\n".join(responses) |
| 224 | await client.send_split_messages(interaction, message) |
| 225 | else: |
| 226 | # Extract the user's query from the interaction |
| 227 | query = "" |
| 228 | for option in interaction.data.get("options", []): |
| 229 | if option.get("name") == "query": |
| 230 | query = option.get("value", "") |
| 231 | break |
| 232 | |
| 233 | # If the query is not empty, include it in the response message |
| 234 | response_message = "No results found." |
| 235 | if query: |
| 236 | response_message = f"No results found for the query: `{query}`." |
| 237 | |
| 238 | await interaction.followup.send(response_message) |
| 239 | |
| 240 | def generate_detailed_info(match: dict) -> str: |
| 241 | ip = match.get('ip_str', 'No IP available.') |
no test coverage detected