Files
Bjorn/actions/presence_join.py
Fabien POLLY eb20b168a6 Add RLUtils class for managing RL/AI dashboard endpoints
- Implemented methods for fetching AI stats, training history, and recent experiences.
- Added functionality to set operation mode (MANUAL, AUTO, AI) with appropriate handling.
- Included helper methods for querying the database and sending JSON responses.
- Integrated model metadata extraction for visualization purposes.
2026-02-18 22:36:10 +01:00

85 lines
3.1 KiB
Python

# actions/presence_join.py
# -*- coding: utf-8 -*-
"""
PresenceJoin — Sends a Discord webhook when the targeted host JOINS the network.
- Triggered by the scheduler ONLY on transition OFF->ON (b_trigger="on_join").
- Targeting via b_requires (e.g. {"any":[{"mac_is":"AA:BB:..."}]}).
- The action does not query anything: it only notifies when called.
"""
import requests
from typing import Optional
import logging
import datetime
from logger import Logger
from shared import SharedData # only if executed directly for testing
logger = Logger(name="PresenceJoin", level=logging.DEBUG)
# --- Metadata (truth is in DB; here for reference/consistency) --------------
b_class = "PresenceJoin"
b_module = "presence_join"
b_status = "PresenceJoin"
b_port = None
b_service = None
b_parent = None
b_priority = 90
b_cooldown = 0 # not needed: on_join only fires on join transition
b_rate_limit = None
b_trigger = "on_join" # <-- Host JOINED the network (OFF -> ON since last scan)
b_requires = {"any":[{"mac_is":"60:57:c8:51:63:fb"}]} # adapt as needed
DISCORD_WEBHOOK_URL = "" # Configure via shared_data or DB
class PresenceJoin:
def __init__(self, shared_data):
self.shared_data = shared_data
def _send(self, text: str) -> None:
url = getattr(self.shared_data, 'discord_webhook_url', None) or DISCORD_WEBHOOK_URL
if not url or "webhooks/" not in url:
logger.error("PresenceJoin: DISCORD_WEBHOOK_URL missing/invalid.")
return
try:
r = requests.post(url, json={"content": text}, timeout=6)
if r.status_code < 300:
logger.info("PresenceJoin: webhook sent.")
else:
logger.error(f"PresenceJoin: HTTP {r.status_code}: {r.text}")
except Exception as e:
logger.error(f"PresenceJoin: webhook error: {e}")
def execute(self, ip: Optional[str], port: Optional[str], row: dict, status_key: str):
"""
Called by the orchestrator when the scheduler detected the join.
ip/port = host targets (if known), row = host info.
"""
try:
mac = row.get("MAC Address") or row.get("mac_address") or "MAC"
host = row.get("hostname") or (row.get("hostnames") or "").split(";")[0] if row.get("hostnames") else None
name = f"{host} ({mac})" if host else mac
ip_s = (ip or (row.get("IPs") or "").split(";")[0] or "").strip()
# Add timestamp in UTC
timestamp = datetime.datetime.now(datetime.timezone.utc).strftime("%Y-%m-%d %H:%M:%S UTC")
msg = f"✅ **Presence detected**\n"
msg += f"- Host: {host or 'unknown'}\n"
msg += f"- MAC: {mac}\n"
if ip_s:
msg += f"- IP: {ip_s}\n"
msg += f"- Time: {timestamp}"
self._send(msg)
return "success"
except Exception as e:
logger.error(f"PresenceJoin error: {e}")
return "failed"
if __name__ == "__main__":
sd = SharedData()
logger.info("PresenceJoin ready (direct mode).")