Files
OnionClaw/ask.py
T

99 lines
3.6 KiB
Python
Executable File

#!/usr/bin/env python3
# SPDX-License-Identifier: Apache-2.0
# Copyright (c) 2026 JacobJandon — https://github.com/JacobJandon/OnionClaw
"""
OnionClaw — ask.py
Analyse dark web content with an LLM and get a structured OSINT report.
Usage:
python3 ask.py --query "QUERY" --mode MODE --content "RAW TEXT"
python3 ask.py --query "QUERY" --mode MODE --file /path/to/content.txt
echo "content" | python3 ask.py --query "QUERY" --mode MODE
Modes: threat_intel (default), ransomware, personal_identity, corporate
"""
import sys, os, argparse
# ── bootstrap ─────────────────────────────────────────────────────
_skill_dir = os.path.dirname(os.path.abspath(__file__))
sys.path.insert(0, _skill_dir)
_env = os.path.join(_skill_dir, ".env")
if os.path.exists(_env):
try:
from dotenv import load_dotenv
load_dotenv(_env, override=False)
except ImportError:
pass
# ──────────────────────────────────────────────────────────────────
try:
import sicry
except Exception as _e:
if "sicry" in str(_e).lower() or "No module named 'sicry'" in str(_e):
print("ERROR: sicry.py not found in", _skill_dir)
print(" Make sure sicry.py is in the OnionClaw folder.")
else:
print("ERROR: failed to import sicry:", _e)
print(" Run: pip install requests[socks] beautifulsoup4 python-dotenv stem")
sys.exit(1)
MODES = ["threat_intel", "ransomware", "personal_identity", "corporate"]
parser = argparse.ArgumentParser(description="OSINT analysis of dark web content")
parser.add_argument("--query", default="", help="Investigation query / topic")
parser.add_argument("--mode", default="threat_intel", choices=MODES,
help="Analysis mode (default: threat_intel)")
parser.add_argument("--content", default=None, help="Content to analyse (inline string)")
parser.add_argument("--file", default=None, help="File containing content to analyse")
parser.add_argument("--custom", default="", help="Custom instructions appended to the mode prompt")
args = parser.parse_args()
# ── Load content ──────────────────────────────────────────────────
if args.file:
try:
with open(args.file, "r", errors="replace") as f:
content = f.read()
print(f"Content: loaded from {args.file} ({len(content)} chars)")
except OSError as e:
print(f"ERROR: cannot read file: {e}")
sys.exit(1)
elif args.content:
content = args.content
print(f"Content: {len(content)} chars (inline)")
elif not sys.stdin.isatty():
content = sys.stdin.read()
print(f"Content: {len(content)} chars (stdin)")
else:
print("ERROR: provide content via --content, --file, or stdin")
parser.print_help()
sys.exit(1)
if not content.strip():
print("ERROR: content is empty")
sys.exit(1)
print(f"Query : {args.query or '(none)'}")
print(f"Mode : {args.mode}")
if args.custom:
print(f"Custom : {args.custom[:80]}")
print()
print("Analysing via LLM...")
print()
report = sicry.ask(
content,
query=args.query,
mode=args.mode,
custom_instructions=args.custom,
)
if report.startswith("[SICRY:"):
print("✗ LLM error:", report)
print()
print(" Set LLM_PROVIDER and API key in", os.path.join(_skill_dir, ".env"))
print(" Options: LLM_PROVIDER=openai|anthropic|gemini|ollama|llamacpp")
sys.exit(1)
print(report)