various plugin refactors and fixes

This commit is contained in:
2026-05-09 04:51:50 -05:00
parent f822d6a450
commit 5c6234a317
25 changed files with 2044 additions and 3674 deletions
+63 -56
View File
@@ -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 &lt;domain_name&gt;</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__ = """