various plugin refactors and fixes
This commit is contained in:
+63
-56
@@ -1,11 +1,13 @@
|
||||
"""
|
||||
This plugin provides DNSDumpster.com integration for domain reconnaissance and DNS mapping.
|
||||
DNSDumpster.com integration for domain reconnaissance and DNS mapping.
|
||||
Output uses shared code_block for aligned columns.
|
||||
"""
|
||||
|
||||
import logging
|
||||
import os
|
||||
import aiohttp
|
||||
import simplematrixbotlib as botlib
|
||||
from plugins.common import html_escape, collapsible_summary
|
||||
from plugins.common import html_escape, code_block, collapsible_summary
|
||||
|
||||
DNSDUMPSTER_API_KEY = os.getenv("DNSDUMPSTER_KEY", "")
|
||||
DNSDUMPSTER_API_BASE = "https://api.dnsdumpster.com"
|
||||
@@ -13,20 +15,13 @@ DNSDUMPSTER_API_BASE = "https://api.dnsdumpster.com"
|
||||
async def handle_command(room, message, bot, prefix, config):
|
||||
match = botlib.MessageMatch(room, message, bot, prefix)
|
||||
if match.is_not_from_this_bot() and match.prefix() and match.command("dnsdumpster"):
|
||||
logging.info("Received !dnsdumpster command")
|
||||
|
||||
if not DNSDUMPSTER_API_KEY:
|
||||
await bot.api.send_text_message(
|
||||
room.room_id,
|
||||
"DNSDumpster API key not configured. Set DNSDUMPSTER_KEY in .env."
|
||||
)
|
||||
await bot.api.send_text_message(room.room_id, "DNSDumpster API key not configured. Set DNSDUMPSTER_KEY in .env.")
|
||||
return
|
||||
|
||||
args = match.args()
|
||||
if len(args) < 1:
|
||||
await show_usage(room, bot)
|
||||
return
|
||||
|
||||
if args[0].lower() == "test":
|
||||
await test_dnsdumpster_connection(room, bot)
|
||||
else:
|
||||
@@ -37,9 +32,6 @@ async def show_usage(room, bot):
|
||||
usage = """<strong>🔍 DNSDumpster Commands:</strong>
|
||||
<strong>!dnsdumpster <domain_name></strong> - Get comprehensive DNS reconnaissance for a domain
|
||||
<strong>!dnsdumpster test</strong> - Test API connection
|
||||
<strong>Examples:</strong>
|
||||
• <code>!dnsdumpster google.com</code>
|
||||
• <code>!dnsdumpster github.com</code>
|
||||
"""
|
||||
await bot.api.send_markdown_message(room.room_id, usage)
|
||||
|
||||
@@ -51,8 +43,7 @@ async def test_dnsdumpster_connection(room, bot):
|
||||
async with aiohttp.ClientSession() as session:
|
||||
async with session.get(url, headers=headers, timeout=15) as response:
|
||||
status = response.status
|
||||
debug_info = f"<strong>🔧 DNSDumpster API Test</strong><br>Status Code: {status}<br>Test Domain: {test_domain}<br>"
|
||||
|
||||
debug_info = f"<strong>🔧 DNSDumpster API Test</strong><br>Status Code: {status}<br>"
|
||||
if status == 200:
|
||||
data = await response.json()
|
||||
debug_info += "<strong>✅ SUCCESS</strong><br>"
|
||||
@@ -81,50 +72,66 @@ async def dnsdumpster_domain_lookup(room, bot, domain):
|
||||
return
|
||||
data = await response.json()
|
||||
|
||||
output = await format_dnsdumpster_report(domain, data)
|
||||
sections = []
|
||||
|
||||
# A Records
|
||||
if data.get('a'):
|
||||
rows = []
|
||||
for rec in data['a']:
|
||||
host = rec.get('host', 'N/A')
|
||||
ips = ', '.join(ip.get('ip', '') for ip in rec.get('ips', []))
|
||||
rows.append(("📍", host, ips))
|
||||
sections.append({"title": "A Records (IPv4)", "rows": rows})
|
||||
|
||||
# NS Records
|
||||
if data.get('ns'):
|
||||
rows = []
|
||||
for rec in data['ns']:
|
||||
host = rec.get('host', 'N/A')
|
||||
ips = ', '.join(ip.get('ip', '') for ip in rec.get('ips', []))
|
||||
rows.append(("🖧", host, ips))
|
||||
sections.append({"title": "NS Records", "rows": rows})
|
||||
|
||||
# MX Records
|
||||
if data.get('mx'):
|
||||
rows = []
|
||||
for rec in data['mx']:
|
||||
host = rec.get('host', 'N/A')
|
||||
ips = ', '.join(ip.get('ip', '') for ip in rec.get('ips', []))
|
||||
rows.append(("📧", host, ips))
|
||||
sections.append({"title": "MX Records", "rows": rows})
|
||||
|
||||
# CNAME
|
||||
if data.get('cname'):
|
||||
rows = []
|
||||
for rec in data['cname']:
|
||||
host = rec.get('host', 'N/A')
|
||||
target = rec.get('target', 'N/A')
|
||||
rows.append(("🔀", host, target))
|
||||
sections.append({"title": "CNAME Records", "rows": rows})
|
||||
|
||||
# TXT
|
||||
if data.get('txt'):
|
||||
rows = []
|
||||
for txt in data['txt']:
|
||||
rows.append(("📄", "TXT", txt[:150] if len(txt) > 150 else txt))
|
||||
sections.append({"title": "TXT Records", "rows": rows})
|
||||
|
||||
if not sections:
|
||||
await bot.api.send_text_message(room.room_id, "No DNS records found.")
|
||||
return
|
||||
|
||||
block = code_block(f"🔍 DNSDumpster Report: {safe_domain}", sections)
|
||||
output = collapsible_summary(f"🔍 DNSDumpster Report: {safe_domain}", block)
|
||||
await bot.api.send_markdown_message(room.room_id, output)
|
||||
logging.info(f"Sent DNSDumpster data for {domain}")
|
||||
except asyncio.TimeoutError:
|
||||
await bot.api.send_text_message(room.room_id, "Request timed out.")
|
||||
except Exception as e:
|
||||
|
||||
except aiohttp.ClientError as e:
|
||||
await bot.api.send_text_message(room.room_id, f"Error: {e}")
|
||||
|
||||
async def format_dnsdumpster_report(domain, data):
|
||||
safe_domain = html_escape(domain)
|
||||
output = f"<strong>🔍 DNSDumpster Report: {safe_domain}</strong><br><br>"
|
||||
if data.get('total_a_recs'):
|
||||
output += f"<strong>📊 Summary</strong><br>Total A Records: {data['total_a_recs']}<br>"
|
||||
|
||||
for record_type, label in [('a','A Records'),('ns','NS Records'),('mx','MX Records'),('cname','CNAME'),('txt','TXT')]:
|
||||
if data.get(record_type) and data[record_type]:
|
||||
output += f"<br><strong>{label} ({len(data[record_type])} found)</strong><br>"
|
||||
for rec in data[record_type]:
|
||||
if record_type == 'txt':
|
||||
txt = html_escape(str(rec))
|
||||
if len(txt) > 200:
|
||||
txt = txt[:200] + "..."
|
||||
output += f" • {txt}<br>"
|
||||
elif record_type == 'a':
|
||||
host = html_escape(rec.get('host','N/A'))
|
||||
ips = rec.get('ips',[])
|
||||
output += f" • <strong>{host}</strong><br>"
|
||||
for ip_info in ips:
|
||||
ip = html_escape(ip_info.get('ip','N/A'))
|
||||
country = html_escape(ip_info.get('country','Unknown'))
|
||||
output += f" └─ {ip} ({country})<br>"
|
||||
else:
|
||||
host = html_escape(rec.get('host','N/A'))
|
||||
ips = rec.get('ips',[])
|
||||
output += f" • <strong>{host}</strong><br>"
|
||||
for ip_info in ips:
|
||||
ip = html_escape(ip_info.get('ip','N/A'))
|
||||
country = html_escape(ip_info.get('country','Unknown'))
|
||||
output += f" └─ {ip} ({country})<br>"
|
||||
|
||||
output += "<br><em>💡 Rate Limit: 1 request per 2 seconds</em>"
|
||||
return collapsible_summary(f"🔍 DNSDumpster Report: {safe_domain} (Click to expand)", output)
|
||||
|
||||
__version__ = "1.0.1"
|
||||
# ---------------------------------------------------------------------------
|
||||
# Plugin Metadata
|
||||
# ---------------------------------------------------------------------------
|
||||
__version__ = "1.0.2"
|
||||
__author__ = "Funguy Bot"
|
||||
__description__ = "DNSDumpster domain reconnaissance"
|
||||
__help__ = """
|
||||
|
||||
Reference in New Issue
Block a user