feat: add wave 2 plugins and --cprofile CLI flag

Add 7 new pure-stdlib plugins: whois (raw TCP port 43), portcheck
(async TCP connect scan with internal-net guard), httpcheck (HTTP
status/redirects/timing), tlscheck (TLS version/cipher/cert inspect),
blacklist (parallel DNSBL check against 10 RBLs), rand (password/hex/
uuid/bytes/int/coin/dice), and timer (async countdown notifications).

Add --cprofile flag to CLI for profiling bot runtime. Update all docs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
user
2026-02-15 01:58:47 +01:00
parent c5b0430da8
commit 530f33be76
12 changed files with 960 additions and 12 deletions

View File

@@ -32,6 +32,13 @@ def build_parser() -> argparse.ArgumentParser:
action="store_true",
help="enable debug logging",
)
p.add_argument(
"--cprofile",
metavar="PATH",
nargs="?",
const="derp.prof",
help="enable cProfile; dump stats to PATH [derp.prof]",
)
p.add_argument(
"-V", "--version",
action="version",
@@ -40,6 +47,14 @@ def build_parser() -> argparse.ArgumentParser:
return p
def _run(bot: Bot) -> None:
"""Run the bot event loop."""
try:
asyncio.run(bot.start())
except KeyboardInterrupt:
logging.getLogger("derp").info("interrupted, shutting down")
def main(argv: list[str] | None = None) -> int:
"""Main entry point."""
parser = build_parser()
@@ -57,10 +72,14 @@ def main(argv: list[str] | None = None) -> int:
bot = Bot(config, registry)
bot.load_plugins()
try:
asyncio.run(bot.start())
except KeyboardInterrupt:
log.info("interrupted, shutting down")
if args.cprofile:
import cProfile
log.info("cProfile enabled, output: %s", args.cprofile)
cProfile.runctx("_run(bot)", globals(), {"bot": bot, "_run": _run}, args.cprofile)
log.info("profile saved to %s", args.cprofile)
else:
_run(bot)
return 0